diff options
Diffstat (limited to 'src/systemc/tests/include')
22 files changed, 10749 insertions, 0 deletions
diff --git a/src/systemc/tests/include/CoreDecouplingLTInitiator.h b/src/systemc/tests/include/CoreDecouplingLTInitiator.h new file mode 100644 index 000000000..b3c0e43fc --- /dev/null +++ b/src/systemc/tests/include/CoreDecouplingLTInitiator.h @@ -0,0 +1,166 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +//==================================================================== +// Nov 06, 2008 +// +// Updated by: +// Xiaopeng Qiu, JEDA Technologies, Inc +// Email: qiuxp@jedatechnologies.net +// +// To fix violations of TLM2.0 rules, which are detected by JEDA +// TLM2.0 checker. +// +//==================================================================== + +#ifndef __CORE_DECOUPLING_LT_INITIATOR_H__ +#define __CORE_DECOUPLING_LT_INITIATOR_H__ + +#include "tlm.h" +#include "tlm_utils/simple_initiator_socket.h" +#include "tlm_utils/tlm_quantumkeeper.h" +//#include <systemc> +#include <cassert> +//#include <iostream> + +class CoreDecouplingLTInitiator : public sc_core::sc_module +{ +public: + typedef tlm::tlm_generic_payload transaction_type; + typedef tlm_utils::simple_initiator_socket<CoreDecouplingLTInitiator> initiator_socket_type; + +public: + initiator_socket_type socket; + +public: + SC_HAS_PROCESS(CoreDecouplingLTInitiator); + CoreDecouplingLTInitiator(sc_core::sc_module_name name, + unsigned int nrOfTransactions = 0x5, + unsigned int baseAddress = 0) : + sc_core::sc_module(name), + socket("socket"), + mNrOfTransactions(nrOfTransactions), + mBaseAddress(baseAddress), + mTransactionCount(0) + { + tlm_utils::tlm_quantumkeeper::set_global_quantum(sc_core::sc_time(500, sc_core::SC_NS)); + mQuantumKeeper.reset(); + + // Initiator thread + SC_THREAD(run); + } + + bool initTransaction(transaction_type& trans) + { + if (mTransactionCount < mNrOfTransactions) { + trans.set_address(mBaseAddress + 4*mTransactionCount); + mData = mTransactionCount; + trans.set_command(tlm::TLM_WRITE_COMMAND); + + } else if (mTransactionCount < 2 * mNrOfTransactions) { + trans.set_address(mBaseAddress + 4*(mTransactionCount - mNrOfTransactions)); + mData = 0; + trans.set_command(tlm::TLM_READ_COMMAND); + + } else { + return false; + } + + trans.set_data_ptr(reinterpret_cast<unsigned char*>(&mData)); + trans.set_data_length(4); + trans.set_streaming_width(4); + trans.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE); + + ++mTransactionCount; + return true; + } + + void logStartTransation(transaction_type& trans) + { + if (trans.get_command() == tlm::TLM_WRITE_COMMAND) { + std::cout << name() << ": Send write request: A = 0x" + << std::hex << (unsigned int)trans.get_address() + << ", D = 0x" << mData << std::dec + << " @ " << mQuantumKeeper.get_current_time() + << " (" << sc_core::sc_time_stamp() << " + " + << mQuantumKeeper.get_local_time() << ")" + << std::endl; + + } else { + std::cout << name() << ": Send read request: A = 0x" + << std::hex << (unsigned int)trans.get_address() + << " @ " << mQuantumKeeper.get_current_time() + << " (" << sc_core::sc_time_stamp() << " + " + << mQuantumKeeper.get_local_time() << ")" + << std::endl; + } + } + + void logEndTransaction(transaction_type& trans) + { + if (trans.get_response_status() != tlm::TLM_OK_RESPONSE) { + std::cout << name() << ": Received error response @ " + << mQuantumKeeper.get_current_time() + << " (" << sc_core::sc_time_stamp() << " + " + << mQuantumKeeper.get_local_time() << ")" + << std::endl; + + } else { + std::cout << name() << ": Received ok response"; + if (trans.get_command() == tlm::TLM_READ_COMMAND) { + std::cout << ": D = 0x" << std::hex << mData << std::dec; + } + std::cout << " @ " << mQuantumKeeper.get_current_time() + << " (" << sc_core::sc_time_stamp() << " + " + << mQuantumKeeper.get_local_time() << ")" + << std::endl; + } + } + + void run() + { + transaction_type trans; + + while (initTransaction(trans)) { + logStartTransation(trans); + + // exec instr + sc_core::sc_time t = mQuantumKeeper.get_local_time(); + socket->b_transport(trans, t); + mQuantumKeeper.set(t); + // Target may have added a delay to the quantum -> sync if needed + if (mQuantumKeeper.need_sync()) { + std::cout << "Sync'ing..." << std::endl; + mQuantumKeeper.sync(); + } + + logEndTransaction(trans); + } + wait(); + } + +private: + unsigned int mNrOfTransactions; + unsigned int mBaseAddress; + unsigned int mTransactionCount; + unsigned int mData; + tlm_utils::tlm_quantumkeeper mQuantumKeeper; +}; + +#endif diff --git a/src/systemc/tests/include/ExplicitATTarget.h b/src/systemc/tests/include/ExplicitATTarget.h new file mode 100644 index 000000000..ccde70a0e --- /dev/null +++ b/src/systemc/tests/include/ExplicitATTarget.h @@ -0,0 +1,176 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __EXPLICIT_AT_TARGET_H__ +#define __EXPLICIT_AT_TARGET_H__ + +#include "tlm.h" +#include "tlm_utils/simple_target_socket.h" +//#include <systemc> +#include <cassert> +#include <vector> +#include <queue> +//#include <iostream> + +class ExplicitATTarget : public sc_core::sc_module +{ +public: + typedef tlm::tlm_generic_payload transaction_type; + typedef tlm::tlm_phase phase_type; + typedef tlm::tlm_sync_enum sync_enum_type; + typedef tlm_utils::simple_target_socket<ExplicitATTarget> target_socket_type; + +public: + target_socket_type socket; + +public: + SC_HAS_PROCESS(ExplicitATTarget); + ExplicitATTarget(sc_core::sc_module_name name) : + sc_core::sc_module(name), + socket("socket"), + mCurrentTransaction(0) + { + // register nb_transport method + socket.register_nb_transport_fw(this, &ExplicitATTarget::myNBTransport); + socket.register_transport_dbg(this, &ExplicitATTarget::transport_dbg); + + SC_THREAD(beginResponse) + } + + sync_enum_type myNBTransport(transaction_type& trans, phase_type& phase, sc_core::sc_time& t) + { + if (phase == tlm::BEGIN_REQ) { + sc_dt::uint64 address = trans.get_address(); + assert(address < 400); + + // This target only supports one transaction at a time + // This will only work with LT initiators + assert(mCurrentTransaction == 0); + + unsigned int& data = *reinterpret_cast<unsigned int*>(trans.get_data_ptr()); + if (trans.get_command() == tlm::TLM_WRITE_COMMAND) { + std::cout << name() << ": Received write request: A = 0x" + << std::hex << (unsigned int)address << ", D = 0x" << data + << std::dec << " @ " << sc_core::sc_time_stamp() + << std::endl; + + *reinterpret_cast<unsigned int*>(&mMem[address]) = data; + + // Synchronization on demand (eg need to assert an interrupt) + mResponseEvent.notify(t); + mCurrentTransaction = &trans; + + // End request phase + phase = tlm::END_REQ; + return tlm::TLM_UPDATED; + + } else { + std::cout << name() << ": Received read request: A = 0x" + << std::hex << (unsigned int)address + << std::dec << " @ " << sc_core::sc_time_stamp() + << std::endl; + + data = *reinterpret_cast<unsigned int*>(&mMem[address]); + trans.set_response_status(tlm::TLM_OK_RESPONSE); + + // Finish transaction (use timing annotation) + t += sc_core::sc_time(100, sc_core::SC_NS); + return tlm::TLM_COMPLETED; + } + + } else if (phase == tlm::END_RESP) { + + // Transaction finished + mCurrentTransaction = 0; + return tlm::TLM_COMPLETED; + } + + // Not possible + assert(0); exit(1); +// return tlm::TLM_COMPLETED; //unreachable code + } + + void beginResponse() + { + while (true) { + // Wait for next synchronization request + wait(mResponseEvent); + + assert(mCurrentTransaction); + // start response phase + phase_type phase = tlm::BEGIN_RESP; + sc_core::sc_time t = sc_core::SC_ZERO_TIME; + + // Set response data + mCurrentTransaction->set_response_status(tlm::TLM_OK_RESPONSE); + assert(mCurrentTransaction->get_command() == tlm::TLM_WRITE_COMMAND); + + sc_dt::uint64 address = mCurrentTransaction->get_address(); + assert(address < 400); + *reinterpret_cast<unsigned int*>(mCurrentTransaction->get_data_ptr()) = + *reinterpret_cast<unsigned int*>(&mMem[address]); + + // We are synchronized, we can read/write sc_signals, wait,... + // Wait before sending the response + wait(50, sc_core::SC_NS); + + if (socket->nb_transport_bw(*mCurrentTransaction, phase, t) == tlm::TLM_COMPLETED) { + mCurrentTransaction = 0; + + } else { + // Initiator will call nb_transport(trans, END_RESP, t) + } + } + } + + unsigned int transport_dbg(transaction_type& r) + { + if (r.get_address() >= 400) return 0; + + unsigned int tmp = (int)r.get_address(); + unsigned int num_bytes; + if (tmp + r.get_data_length() >= 400) { + num_bytes = 400 - tmp; + + } else { + num_bytes = r.get_data_length(); + } + if (!r.is_read() && !r.is_write()) { + return 0; + } + if (r.is_read()) { + for (unsigned int i = 0; i < num_bytes; ++i) { + r.get_data_ptr()[i] = mMem[i + tmp]; + } + + } else { + for (unsigned int i = 0; i < num_bytes; ++i) { + mMem[i + tmp] = r.get_data_ptr()[i]; + } + } + return num_bytes; + } + +private: + unsigned char mMem[400]; + sc_core::sc_event mResponseEvent; + transaction_type* mCurrentTransaction; +}; + +#endif diff --git a/src/systemc/tests/include/ExplicitLTTarget.h b/src/systemc/tests/include/ExplicitLTTarget.h new file mode 100644 index 000000000..2c308d966 --- /dev/null +++ b/src/systemc/tests/include/ExplicitLTTarget.h @@ -0,0 +1,124 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __EXPLICIT_LT_TARGET_H__ +#define __EXPLICIT_LT_TARGET_H__ + +#include "tlm.h" +#include "tlm_utils/simple_target_socket.h" +//#include <systemc> +#include <cassert> +#include <vector> +#include <queue> +//#include <iostream> + +class ExplicitLTTarget : public sc_core::sc_module +{ +public: + typedef tlm::tlm_generic_payload transaction_type; + typedef tlm::tlm_phase phase_type; + typedef tlm::tlm_sync_enum sync_enum_type; + typedef tlm_utils::simple_target_socket<ExplicitLTTarget> target_socket_type; + +public: + target_socket_type socket; + +public: + SC_HAS_PROCESS(ExplicitLTTarget); + ExplicitLTTarget(sc_core::sc_module_name name) : + sc_core::sc_module(name), + socket("socket") + { + // register nb_transport method + socket.register_b_transport(this, &ExplicitLTTarget::myBTransport); + socket.register_transport_dbg(this, &ExplicitLTTarget::transport_dbg); + } + + void myBTransport(transaction_type& trans, sc_core::sc_time& t) + { + sc_dt::uint64 address = trans.get_address(); + assert(address < 400); + + unsigned int& data = *reinterpret_cast<unsigned int*>(trans.get_data_ptr()); + if (trans.get_command() == tlm::TLM_WRITE_COMMAND) { + std::cout << name() << ": Received write request: A = 0x" + << std::hex << (unsigned int)address << ", D = 0x" << data + << std::dec << " @ " << sc_core::sc_time_stamp() + << std::endl; + + *reinterpret_cast<unsigned int*>(&mMem[address]) = data; + + // Synchronization on demand (eg need to assert an interrupt) + // Wait for passed timing annotation + wait for an extra 50 ns + wait(t + sc_core::sc_time(50, sc_core::SC_NS)); + t = sc_core::SC_ZERO_TIME; + + // We are synchronized, we can read/write sc_signals, wait,... + + *reinterpret_cast<unsigned int*>(trans.get_data_ptr()) = + *reinterpret_cast<unsigned int*>(&mMem[address]); + + } else { + std::cout << name() << ": Received read request: A = 0x" + << std::hex << (unsigned int)address + << std::dec << " @ " << sc_core::sc_time_stamp() + << std::endl; + + data = *reinterpret_cast<unsigned int*>(&mMem[address]); + + // Finish transaction (use timing annotation) + t += sc_core::sc_time(100, sc_core::SC_NS); + } + + trans.set_response_status(tlm::TLM_OK_RESPONSE); + } + + unsigned int transport_dbg(transaction_type& r) + { + if (r.get_address() >= 400) return 0; + + unsigned int tmp = (int)r.get_address(); + unsigned int num_bytes; + if (tmp + r.get_data_length() >= 400) { + num_bytes = 400 - tmp; + + } else { + num_bytes = r.get_data_length(); + } + if (!r.is_read() && !r.is_write()) { + return 0; + } + if (r.is_read()) { + for (unsigned int i = 0; i < num_bytes; ++i) { + r.get_data_ptr()[i] = mMem[i + tmp]; + } + + } else { + for (unsigned int i = 0; i < num_bytes; ++i) { + mMem[i + tmp] = r.get_data_ptr()[i]; + } + } + return num_bytes; + } + +private: + unsigned char mMem[400]; +}; + +#endif diff --git a/src/systemc/tests/include/README.txt b/src/systemc/tests/include/README.txt new file mode 100644 index 000000000..2636918b5 --- /dev/null +++ b/src/systemc/tests/include/README.txt @@ -0,0 +1,92 @@ +SimpleLTInitiator1/SimpleLTTarget1 +---------------------------------- + +- LT Initiator/Target model using the base (standard) tlm socket +- Added support for DMI in SimpleLTTarget1 + +SimpleLTInitiator1_DMI +---------------------- + +- uses DMI transactions, the DMI structure is using the DMI-hint + to check if a DMI request would make sense. +- uses a single transport_dbg transaction at end_of_simulation() + +SimpleLTInitiator2/SimpleLTTarget2 +---------------------------------- + +- LT Initiator/Target model using the convenience tlm socket +- Target and Initiator model use the REGISTER_DEBUGTRANSPORT macro to register + a transport callback to the socket +- Added support for DMI handling, callback registration with + REGISTER_DMI +- SimpleLTTarget2 does not register the transport_dbg callback, so that + we are able to test this case in bus_dmi. + +SimpleLTInitiator2_DMI +---------------------- + +- uses DMI transactions, but ignoring the DMI hint +- uses a single transport_dbg transaction at end_of_simulation() + +SimpleLTInitiator3 +------------------ + +- LT Initiator model using the convenience tlm socket +- Initiator model uses the endEvent of the socket to wait until the + transaction is finished + +SimpleLTInitiator3_DMI +---------------------- + +- based on SimpleInitiator3, uses DMI (without DMI hint) + +SimpleATInitiator1/SimpleATTarget1 +---------------------------------- + +- AT Initiator/Target model implementing the AT protocol +- one call of nb_transport for each timing point in the protocol (BEGIN_REQ, + END_REQ, BEGIN_RESP and END_RESP) + +SimpleATInitiator2/SimpleATTarget2 +---------------------------------- + +- AT Initiator/Target model implementing the AT protocol with timing annotation +- only a call of nb_transport for the start of a phase (BEGIN_REQ and + BEGIN_RESP) +- end of a phase is notified via timing annotation (t argument) + +CoreDecouplingLTInitiator +------------------------- + +- LT Initiator using 'Core Decoupling' + +ExplicitLTTarget +---------------- + +- LT Target that uses explicit timing (calls wait) +- added support for debug transactions + +ExplicitLTTarget +---------------- + +- AT Target, only registers nb_transport + +SimpleBus +--------- + +- Simple bus model +- Runtime switcheable between LT and AT (can only switch if no transactions + are pending) +- No limitation on number of pending transactions (all targets that can return + false must support multiple transactions) +- added support for DMI and debug transactions +- LT mode: +-- Forward nb_transport calls to initiator/targets +-- Only one active request/response phase +- AT mode: +-- Incoming transactions are queued +-- AT protocol is executed from a different SC_THREAD +-- A target is notified immediately of the end of a transaction (using timing + annotation). This is needed because the initiator can re-use the + transaction (and the target may use the transaction pointer to identify the + transaction) diff --git a/src/systemc/tests/include/SimpleATInitiator1.h b/src/systemc/tests/include/SimpleATInitiator1.h new file mode 100644 index 000000000..8becbb9b6 --- /dev/null +++ b/src/systemc/tests/include/SimpleATInitiator1.h @@ -0,0 +1,333 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +//==================================================================== +// Nov 06, 2008 +// +// Updated by: +// Xiaopeng Qiu, JEDA Technologies, Inc +// Email: qiuxp@jedatechnologies.net +// +// To fix violations of TLM2.0 rules, which are detected by JEDA +// TLM2.0 checker. +// +//==================================================================== + +#ifndef __SIMPLE_AT_INITIATOR1_H__ +#define __SIMPLE_AT_INITIATOR1_H__ + +#include "tlm.h" +#include "tlm_utils/simple_initiator_socket.h" +//#include <systemc> +#include <cassert> +#include <queue> +//#include <iostream> + +class SimpleATInitiator1 : public sc_core::sc_module +{ +public: + typedef tlm::tlm_generic_payload transaction_type; + typedef tlm::tlm_phase phase_type; + typedef tlm::tlm_sync_enum sync_enum_type; + typedef tlm_utils::simple_initiator_socket<SimpleATInitiator1> initiator_socket_type; + +public: + // extended transaction, holds tlm_generic_payload + data storage + template <typename DT> + class MyTransaction : public transaction_type + { + public: + MyTransaction() + { + this->set_data_ptr(reinterpret_cast<unsigned char*>(&mData)); + } + MyTransaction(tlm::tlm_mm_interface* mm) : transaction_type(mm) + { + this->set_data_ptr(reinterpret_cast<unsigned char*>(&mData)); + } + + void setData(DT& data) { mData = data; } + DT getData() const { return mData; } + + private: + DT mData; + }; + typedef MyTransaction<unsigned int> mytransaction_type; + + // Dummy Transaction Pool + class SimplePool : public tlm::tlm_mm_interface + { + public: + SimplePool() {} + mytransaction_type* claim() + { + mytransaction_type* t = new mytransaction_type(this); + t->acquire(); + return t; + } + void release(mytransaction_type* t) + { + t->release(); + } + void free(tlm::tlm_generic_payload* t) + { + t->reset(); + delete t; + } + }; + +public: + initiator_socket_type socket; + +public: + SC_HAS_PROCESS(SimpleATInitiator1); + SimpleATInitiator1(sc_core::sc_module_name name, + unsigned int nrOfTransactions = 0x5, + unsigned int baseAddress = 0x0) : + sc_core::sc_module(name), + socket("socket"), + ACCEPT_DELAY(10, sc_core::SC_NS), + mNrOfTransactions(nrOfTransactions), + mBaseAddress(baseAddress), + mTransactionCount(0), + mCurrentTransaction(0) + { + // register nb_transport method + socket.register_nb_transport_bw(this, &SimpleATInitiator1::myNBTransport); + + // Initiator thread + SC_THREAD(run); + + SC_METHOD(endResponse) + sensitive << mEndResponseEvent; + dont_initialize(); + } + + bool initTransaction(mytransaction_type*& trans) + { + if (mTransactionCount < mNrOfTransactions) { + trans = transPool.claim(); + trans->set_address(mBaseAddress + 4*mTransactionCount); + trans->setData(mTransactionCount); + trans->set_command(tlm::TLM_WRITE_COMMAND); + + } else if (mTransactionCount < 2 * mNrOfTransactions) { + trans = transPool.claim(); + trans->set_address(mBaseAddress + 4*(mTransactionCount - mNrOfTransactions)); + trans->set_command(tlm::TLM_READ_COMMAND); + + } else { + return false; + } + + trans->set_data_length(4); + trans->set_streaming_width(4); + + ++mTransactionCount; + return true; + } + + void logStartTransation(mytransaction_type& trans) + { + if (trans.get_command() == tlm::TLM_WRITE_COMMAND) { + std::cout << name() << ": Send write request: A = 0x" + << std::hex << (unsigned int)trans.get_address() + << ", D = 0x" << trans.getData() << std::dec + << " @ " << sc_core::sc_time_stamp() << std::endl; + + } else { + std::cout << name() << ": Send read request: A = 0x" + << std::hex << (int)trans.get_address() << std::dec + << " @ " << sc_core::sc_time_stamp() << std::endl; + } + } + + void logEndTransaction(mytransaction_type& trans) + { + if (trans.get_response_status() != tlm::TLM_OK_RESPONSE) { + std::cout << name() << ": Received error response @ " + << sc_core::sc_time_stamp() << std::endl; + + } else { + std::cout << name() << ": Received ok response"; + if (trans.get_command() == tlm::TLM_READ_COMMAND) { + std::cout << ": D = 0x" << trans.getData() << std::dec; + } + std::cout << " @ " << sc_core::sc_time_stamp() << std::endl; + } + } + + // + // Simple AT Initiator + // - Request must be accepted by the target before the next request can be + // send + // - Responses can come out of order + // - Responses will be accepted after fixed delay + // + void run() + { + phase_type phase; + sc_core::sc_time t; + + mytransaction_type* ptrans; + while (initTransaction(ptrans)) { + // Create transaction and initialise phase and t + mytransaction_type& trans = *ptrans; + phase = tlm::BEGIN_REQ; + t = sc_core::SC_ZERO_TIME; + + logStartTransation(trans); + + switch (socket->nb_transport_fw(trans, phase, t)) { + case tlm::TLM_COMPLETED: + // Transaction Finished, wait for the returned delay + wait(t); + logEndTransaction(trans); + transPool.release(&trans); + break; + + case tlm::TLM_ACCEPTED: + case tlm::TLM_UPDATED: + switch (phase) { + case tlm::BEGIN_REQ: + // Request phase not yet finished + // Wait until end of request phase before sending new request + + // FIXME + mCurrentTransaction = &trans; + wait(mEndRequestPhase); + mCurrentTransaction = 0; + break; + + case tlm::END_REQ: + // Request phase ended + if (t != sc_core::SC_ZERO_TIME) { + // Wait until end of request time before sending new request + wait(t); + } + break; + + case tlm::BEGIN_RESP: + // Request phase ended and response phase already started + if (t != sc_core::SC_ZERO_TIME) { + // Wait until end of request time before sending new request + wait(t); + } + if (mEndResponseQueue.empty()) { + // Notify end of response phase after ACCEPT delay + mEndResponseEvent.notify(ACCEPT_DELAY); + } + mEndResponseQueue.push(&trans); + break; + + case tlm::END_RESP: // fall-through + default: + // A target should never return with these phases + // If phase == END_RESP, nb_transport should have returned true + assert(0); exit(1); + break; + } + break; + + default: + assert(0); exit(1); + }; + } + wait(); + } + + sync_enum_type myNBTransport(transaction_type& trans, phase_type& phase, sc_core::sc_time& t) + { + switch (phase) { + case tlm::END_REQ: + assert(t == sc_core::SC_ZERO_TIME); // FIXME: can t != 0? + // Request phase ended + mEndRequestPhase.notify(sc_core::SC_ZERO_TIME); + return tlm::TLM_ACCEPTED; + + case tlm::BEGIN_RESP: + { + assert(t == sc_core::SC_ZERO_TIME); // FIXME: can t != 0? + + // Notify end of request phase if run thread is waiting for it + // FIXME + if (&trans == mCurrentTransaction) { + mEndRequestPhase.notify(sc_core::SC_ZERO_TIME); + } + + assert(dynamic_cast<mytransaction_type*>(&trans)); + mytransaction_type* myTrans = static_cast<mytransaction_type*>(&trans); + assert(myTrans); + + if (mEndResponseQueue.empty()) { + // Notify end of response phase after ACCEPT delay + mEndResponseEvent.notify(ACCEPT_DELAY); + } + mEndResponseQueue.push(myTrans); + return tlm::TLM_ACCEPTED; + } + + case tlm::BEGIN_REQ: // fall-through + case tlm::END_RESP: // fall-through + default: + // A target should never call nb_transport with these phases + assert(0); exit(1); +// return tlm::TLM_COMPLETED; //unreachable code + }; + } + + void endResponse() + { + assert(!mEndResponseQueue.empty()); + // end response phase + phase_type phase = tlm::END_RESP; + sc_core::sc_time t = sc_core::SC_ZERO_TIME; + mytransaction_type* trans = mEndResponseQueue.front(); + assert(trans); + mEndResponseQueue.pop(); + #if ( ! NDEBUG ) + sync_enum_type r = socket->nb_transport_fw(*trans, phase, t); + #endif /* ! NDEBUG */ + assert(r == tlm::TLM_COMPLETED); // FIXME: target should return TLM_COMPLETED? + assert(t == sc_core::SC_ZERO_TIME); // t must be SC_ZERO_TIME + + logEndTransaction(*trans); + transPool.release(trans); + + if (!mEndResponseQueue.empty()) { + // Notify end of response phase after ACCEPT delay + mEndResponseEvent.notify(ACCEPT_DELAY); + } + } + +private: + const sc_core::sc_time ACCEPT_DELAY; + +private: + unsigned int mNrOfTransactions; + unsigned int mBaseAddress; + SimplePool transPool; + unsigned int mTransactionCount; + sc_core::sc_event mEndRequestPhase; + std::queue<mytransaction_type*> mEndResponseQueue; + sc_core::sc_event mEndResponseEvent; + transaction_type* mCurrentTransaction; +}; + +#endif diff --git a/src/systemc/tests/include/SimpleATInitiator2.h b/src/systemc/tests/include/SimpleATInitiator2.h new file mode 100644 index 000000000..6decf11fa --- /dev/null +++ b/src/systemc/tests/include/SimpleATInitiator2.h @@ -0,0 +1,306 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +//==================================================================== +// Nov 06, 2008 +// +// Updated by: +// Xiaopeng Qiu, JEDA Technologies, Inc +// Email: qiuxp@jedatechnologies.net +// +// To fix violations of TLM2.0 rules, which are detected by JEDA +// TLM2.0 checker. +// +//==================================================================== + +#ifndef __SIMPLE_AT_INITIATOR2_H__ +#define __SIMPLE_AT_INITIATOR2_H__ + +#include "tlm.h" +#include "tlm_utils/simple_initiator_socket.h" +//#include <systemc> +#include <cassert> +#include <queue> +//#include <iostream> + +class SimpleATInitiator2 : public sc_core::sc_module +{ +public: + typedef tlm::tlm_generic_payload transaction_type; + typedef tlm::tlm_phase phase_type; + typedef tlm::tlm_sync_enum sync_enum_type; + typedef tlm_utils::simple_initiator_socket<SimpleATInitiator2> initiator_socket_type; + +public: + // extended transaction, holds tlm_generic_payload + data storage + template <typename DT> + class MyTransaction : public transaction_type + { + public: + MyTransaction() + { + this->set_data_ptr(reinterpret_cast<unsigned char*>(&mData)); + } + MyTransaction(tlm::tlm_mm_interface* mm) : transaction_type(mm) + { + this->set_data_ptr(reinterpret_cast<unsigned char*>(&mData)); + } + + void setData(DT& data) { mData = data; } + DT getData() const { return mData; } + + private: + DT mData; + }; + typedef MyTransaction<unsigned int> mytransaction_type; + + // Dummy Transaction Pool + class SimplePool : public tlm::tlm_mm_interface + { + public: + SimplePool() {} + mytransaction_type* claim() + { + mytransaction_type* t = new mytransaction_type(this); + t->acquire(); + return t; + } + void release(mytransaction_type* t) + { + t->release(); + } + void free(tlm::tlm_generic_payload* t) + { + t->reset(); + delete t; + } + }; + +public: + initiator_socket_type socket; + +public: + SC_HAS_PROCESS(SimpleATInitiator2); + SimpleATInitiator2(sc_core::sc_module_name name, + unsigned int nrOfTransactions = 0x5, + unsigned int baseAddress = 0) : + sc_core::sc_module(name), + socket("socket"), + ACCEPT_DELAY(10, sc_core::SC_NS), + mNrOfTransactions(nrOfTransactions), + mBaseAddress(baseAddress), + mTransactionCount(0), + mCurrentTransaction(0) + { + // register nb_transport method + socket.register_nb_transport_bw(this, &SimpleATInitiator2::myNBTransport); + + // Initiator thread + SC_THREAD(run); + } + + bool initTransaction(mytransaction_type*& trans) + { + if (mTransactionCount < mNrOfTransactions) { + trans = transPool.claim(); + trans->set_address(mBaseAddress + 4*mTransactionCount); + trans->setData(mTransactionCount); + trans->set_command(tlm::TLM_WRITE_COMMAND); + + } else if (mTransactionCount < 2 * mNrOfTransactions) { + trans = transPool.claim(); + trans->set_address(mBaseAddress + 4*(mTransactionCount - mNrOfTransactions)); + trans->set_command(tlm::TLM_READ_COMMAND); + + } else { + return false; + } + + trans->set_data_length(4); + trans->set_streaming_width(4); + + ++mTransactionCount; + return true; + } + + void logStartTransation(mytransaction_type& trans) + { + if (trans.get_command() == tlm::TLM_WRITE_COMMAND) { + std::cout << name() << ": Send write request: A = 0x" + << std::hex << (unsigned int)trans.get_address() + << ", D = 0x" << trans.getData() << std::dec + << " @ " << sc_core::sc_time_stamp() << std::endl; + + } else { + std::cout << name() << ": Send read request: A = 0x" + << std::hex << (unsigned int)trans.get_address() << std::dec + << " @ " << sc_core::sc_time_stamp() << std::endl; + } + } + + void logEndTransaction(mytransaction_type& trans) + { + if (trans.get_response_status() != tlm::TLM_OK_RESPONSE) { + std::cout << name() << ": Received error response @ " + << sc_core::sc_time_stamp() << std::endl; + + } else { + std::cout << name() << ": Received ok response"; + if (trans.get_command() == tlm::TLM_READ_COMMAND) { + std::cout << ": D = 0x" << std::hex << trans.getData() << std::dec; + } + std::cout << " @ " << sc_core::sc_time_stamp() << std::endl; + } + } + + // + // Simple AT Initiator + // - Request must be accepted by the target before the next request can be + // send + // - Responses can come out of order + // - Responses will be accepted after fixed delay + // + void run() + { + phase_type phase; + sc_core::sc_time t; + + mytransaction_type* ptrans; + while (initTransaction(ptrans)) { + // Create transaction and initialise phase and t + mytransaction_type& trans = *ptrans; + phase = tlm::BEGIN_REQ; + t = sc_core::SC_ZERO_TIME; + + logStartTransation(trans); + + switch (socket->nb_transport_fw(trans, phase, t)) { + case tlm::TLM_COMPLETED: + // Transaction Finished, wait for the returned delay + wait(t); + logEndTransaction(trans); + transPool.release(&trans); + break; + + case tlm::TLM_ACCEPTED: + case tlm::TLM_UPDATED: + switch (phase) { + case tlm::BEGIN_REQ: + // Request phase not yet finished + // Wait until end of request phase before sending new request + + // FIXME + mCurrentTransaction = &trans; + wait(mEndRequestPhase); + mCurrentTransaction = 0; + break; + + case tlm::END_REQ: + // Request phase ended + if (t != sc_core::SC_ZERO_TIME) { + // Wait until end of request time before sending new request + wait(t); + } + break; + + case tlm::BEGIN_RESP: + // Request phase ended and response phase already started + if (t != sc_core::SC_ZERO_TIME) { + // Wait until end of request time before sending new request + wait(t); + } + // Notify end of response phase after ACCEPT delay + t += ACCEPT_DELAY; + phase = tlm::END_RESP; + socket->nb_transport_fw(trans, phase, t); + logEndTransaction(trans); + transPool.release(&trans); + break; + + case tlm::END_RESP: // fall-through + default: + // A target should never return with these phases + // If phase == END_RESP, nb_transport should have returned true + assert(0); exit(1); + break; + } + break; + + default: + assert(0); exit(1); + }; + } + wait(); + + } + + sync_enum_type myNBTransport(transaction_type& trans, phase_type& phase, sc_core::sc_time& t) + { + switch (phase) { + case tlm::END_REQ: + assert(t == sc_core::SC_ZERO_TIME); // FIXME: can t != 0? + // Request phase ended + mEndRequestPhase.notify(sc_core::SC_ZERO_TIME); + return tlm::TLM_ACCEPTED; + + case tlm::BEGIN_RESP: + { + assert(t == sc_core::SC_ZERO_TIME); // FIXME: can t != 0? + + // Notify end of request phase if run thread is waiting for it + // FIXME + if (&trans == mCurrentTransaction) { + mEndRequestPhase.notify(sc_core::SC_ZERO_TIME); + } + + assert(dynamic_cast<mytransaction_type*>(&trans)); + mytransaction_type* myTrans = static_cast<mytransaction_type*>(&trans); + assert(myTrans); + + // Notify end of response phase after ACCEPT delay + t += ACCEPT_DELAY; + phase = tlm::END_RESP; + logEndTransaction(*myTrans); + transPool.release(myTrans); + + return tlm::TLM_COMPLETED; + } + + case tlm::BEGIN_REQ: // fall-through + case tlm::END_RESP: // fall-through + default: + // A target should never call nb_transport with these phases + assert(0); exit(1); +// return tlm::TLM_COMPLETED; //unreachable code + }; + } + +private: + const sc_core::sc_time ACCEPT_DELAY; + +private: + unsigned int mNrOfTransactions; + unsigned int mBaseAddress; + SimplePool transPool; + unsigned int mTransactionCount; + sc_core::sc_event mEndRequestPhase; + transaction_type* mCurrentTransaction; +}; + +#endif diff --git a/src/systemc/tests/include/SimpleATTarget1.h b/src/systemc/tests/include/SimpleATTarget1.h new file mode 100644 index 000000000..d99ec3bdd --- /dev/null +++ b/src/systemc/tests/include/SimpleATTarget1.h @@ -0,0 +1,211 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __SIMPLE_AT_TARGET1_H__ +#define __SIMPLE_AT_TARGET1_H__ + +#include "tlm.h" +#include "tlm_utils/simple_target_socket.h" +//#include <systemc> +#include <cassert> +#include <vector> +#include <queue> +//#include <iostream> + +class SimpleATTarget1 : public sc_core::sc_module +{ +public: + typedef tlm::tlm_generic_payload transaction_type; + typedef tlm::tlm_phase phase_type; + typedef tlm::tlm_sync_enum sync_enum_type; + typedef tlm_utils::simple_target_socket<SimpleATTarget1> target_socket_type; + +public: + target_socket_type socket; + +public: + SC_HAS_PROCESS(SimpleATTarget1); + SimpleATTarget1(sc_core::sc_module_name name) : + sc_core::sc_module(name), + socket("socket"), + ACCEPT_DELAY(25, sc_core::SC_NS), + RESPONSE_DELAY(100, sc_core::SC_NS) + { + // register nb_transport method + socket.register_nb_transport_fw(this, &SimpleATTarget1::myNBTransport); + + SC_METHOD(endRequest) + sensitive << mEndRequestEvent; + dont_initialize(); + + SC_METHOD(beginResponse) + sensitive << mBeginResponseEvent; + dont_initialize(); + + SC_METHOD(endResponse) + sensitive << mEndResponseEvent; + dont_initialize(); + } + + // + // Simple AT target + // - Request is accepted after ACCEPT delay (relative to end of prev request + // phase) + // - Response is started after RESPONSE delay (relative to end of prev resp + // phase) + // + sync_enum_type myNBTransport(transaction_type& trans, phase_type& phase, sc_core::sc_time& t) + { + if (phase == tlm::BEGIN_REQ) { + // transactions may be kept in queue after the initiator has send END_REQ + trans.acquire(); + + sc_dt::uint64 address = trans.get_address(); + assert(address < 400); + + unsigned int& data = *reinterpret_cast<unsigned int*>(trans.get_data_ptr()); + if (trans.get_command() == tlm::TLM_WRITE_COMMAND) { + std::cout << name() << ": Received write request: A = 0x" + << std::hex << (unsigned int)address << ", D = 0x" + << data << std::dec + << " @ " << sc_core::sc_time_stamp() << std::endl; + + *reinterpret_cast<unsigned int*>(&mMem[address]) = data; + + } else { + std::cout << name() << ": Received read request: A = 0x" + << std::hex << (unsigned int)address << std::dec + << " @ " << sc_core::sc_time_stamp() << std::endl; + + data = *reinterpret_cast<unsigned int*>(&mMem[address]); + } + + // Notify end of request phase after ACCEPT delay + if (mEndRequestQueue.empty()) { + mEndRequestEvent.notify(t + ACCEPT_DELAY); + } + mEndRequestQueue.push(&trans); + + // AT-noTA target + // - always return false + // - seperate call to indicate end of phase (do not update phase or t) + return tlm::TLM_ACCEPTED; + + } else if (phase == tlm::END_RESP) { + + // response phase ends after t + mEndResponseEvent.notify(t); + + return tlm::TLM_COMPLETED; + } + + // Not possible + assert(0); exit(1); +// return tlm::TLM_COMPLETED; //unreachable code + } + + void endRequest() + { + assert(!mEndRequestQueue.empty()); + // end request phase of oldest transaction + phase_type phase = tlm::END_REQ; + sc_core::sc_time t = sc_core::SC_ZERO_TIME; + transaction_type* trans = mEndRequestQueue.front(); + assert(trans); + mEndRequestQueue.pop(); + #if ( ! NDEBUG ) + sync_enum_type r = socket->nb_transport_bw(*trans, phase, t); + #endif /* ! NDEBUG */ + assert(r == tlm::TLM_ACCEPTED); // FIXME: initiator should return TLM_ACCEPTED? + assert(t == sc_core::SC_ZERO_TIME); // t must be SC_ZERO_TIME + + // Notify end of request phase for next transaction after ACCEPT delay + if (!mEndRequestQueue.empty()) { + mEndRequestEvent.notify(ACCEPT_DELAY); + } + + if (mResponseQueue.empty()) { + // Start processing transaction + // Notify begin of response phase after RESPONSE delay + mBeginResponseEvent.notify(RESPONSE_DELAY); + } + mResponseQueue.push(trans); + } + + void beginResponse() + { + assert(!mResponseQueue.empty()); + // start response phase of oldest transaction + phase_type phase = tlm::BEGIN_RESP; + sc_core::sc_time t = sc_core::SC_ZERO_TIME; + transaction_type* trans = mResponseQueue.front(); + assert(trans); + + // Set response data + trans->set_response_status(tlm::TLM_OK_RESPONSE); + if (trans->get_command() == tlm::TLM_READ_COMMAND) { + sc_dt::uint64 address = trans->get_address(); + assert(address < 400); + *reinterpret_cast<unsigned int*>(trans->get_data_ptr()) = + *reinterpret_cast<unsigned int*>(&mMem[address]); + } + + switch (socket->nb_transport_bw(*trans, phase, t)) { + case tlm::TLM_COMPLETED: + // response phase ends after t + mEndResponseEvent.notify(t); + break; + + case tlm::TLM_ACCEPTED: + case tlm::TLM_UPDATED: + // initiator will call nb_transport to indicate end of response phase + break; + + default: + assert(0); exit(1); + }; + } + + void endResponse() + { + assert(!mResponseQueue.empty()); + mResponseQueue.front()->release(); + mResponseQueue.pop(); + + if (!mResponseQueue.empty()) { + // Start processing next transaction + // Notify begin of response phase after RESPONSE delay + mBeginResponseEvent.notify(RESPONSE_DELAY); + } + } + +private: + const sc_core::sc_time ACCEPT_DELAY; + const sc_core::sc_time RESPONSE_DELAY; + +private: + unsigned char mMem[400]; + std::queue<transaction_type*> mEndRequestQueue; + sc_core::sc_event mEndRequestEvent; + std::queue<transaction_type*> mResponseQueue; + sc_core::sc_event mBeginResponseEvent; + sc_core::sc_event mEndResponseEvent; +}; + +#endif diff --git a/src/systemc/tests/include/SimpleATTarget2.h b/src/systemc/tests/include/SimpleATTarget2.h new file mode 100644 index 000000000..d4f2ae7e2 --- /dev/null +++ b/src/systemc/tests/include/SimpleATTarget2.h @@ -0,0 +1,178 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __SIMPLE_AT_TARGET2_H__ +#define __SIMPLE_AT_TARGET2_H__ + +#include "tlm.h" +#include "tlm_utils/simple_target_socket.h" +//#include <systemc> +#include <cassert> +#include <vector> +#include <queue> +//#include <iostream> + +class SimpleATTarget2 : public sc_core::sc_module +{ +public: + typedef tlm::tlm_generic_payload transaction_type; + typedef tlm::tlm_phase phase_type; + typedef tlm::tlm_sync_enum sync_enum_type; + typedef tlm_utils::simple_target_socket<SimpleATTarget2> target_socket_type; + +public: + target_socket_type socket; + +public: + SC_HAS_PROCESS(SimpleATTarget2); + SimpleATTarget2(sc_core::sc_module_name name) : + sc_core::sc_module(name), + socket("socket"), + ACCEPT_DELAY(25, sc_core::SC_NS), + RESPONSE_DELAY(100, sc_core::SC_NS) + { + // register nb_transport method + socket.register_nb_transport_fw(this, &SimpleATTarget2::myNBTransport); + + SC_METHOD(beginResponse) + sensitive << mBeginResponseEvent; + dont_initialize(); + + SC_METHOD(endResponse) + sensitive << mEndResponseEvent; + dont_initialize(); + } + + // + // Simple AT-TA target + // - Request is accepted after fixed delay (relative to end of prev request + // phase) + // - Response is started after fixed delay (relative to end of prev resp + // phase) + // + sync_enum_type myNBTransport(transaction_type& trans, + phase_type& phase, + sc_core::sc_time& t) + { + if (phase == tlm::BEGIN_REQ) { + // transactions may be kept in queue after the initiator has send END_REQ + trans.acquire(); + + sc_dt::uint64 address = trans.get_address(); + assert(address < 400); + + unsigned int& data = *reinterpret_cast<unsigned int*>(trans.get_data_ptr()); + if (trans.get_command() == tlm::TLM_WRITE_COMMAND) { + std::cout << name() << ": Received write request: A = 0x" + << std::hex << (unsigned int)address << ", D = 0x" << data + << std::dec << " @ " << sc_core::sc_time_stamp() + << std::endl; + + *reinterpret_cast<unsigned int*>(&mMem[address]) = data; + + } else { + std::cout << name() << ": Received read request: A = 0x" + << std::hex << (unsigned int)address + << std::dec << " @ " << sc_core::sc_time_stamp() + << std::endl; + + data = *reinterpret_cast<unsigned int*>(&mMem[address]); + } + + // End request phase after accept delay + t += ACCEPT_DELAY; + phase = tlm::END_REQ; + + if (mResponseQueue.empty()) { + // Start processing transaction after accept delay + // Notify begin of response phase after accept delay + response delay + mBeginResponseEvent.notify(t + RESPONSE_DELAY); + } + mResponseQueue.push(&trans); + + // AT-noTA target + // - always return false + // - immediately return delay to indicate end of phase + return tlm::TLM_UPDATED; + + } else if (phase == tlm::END_RESP) { + + // response phase ends after t + mEndResponseEvent.notify(t); + + return tlm::TLM_COMPLETED; + } + + // Not possible + assert(0); exit(1); +// return tlm::TLM_COMPLETED; //unreachable code + } + + void beginResponse() + { + assert(!mResponseQueue.empty()); + // start response phase of oldest transaction + phase_type phase = tlm::BEGIN_RESP; + sc_core::sc_time t = sc_core::SC_ZERO_TIME; + transaction_type* trans = mResponseQueue.front(); + assert(trans); + + // Set response data + trans->set_response_status(tlm::TLM_OK_RESPONSE); + if (trans->get_command() == tlm::TLM_READ_COMMAND) { + sc_dt::uint64 address = trans->get_address(); + assert(address < 400); + *reinterpret_cast<unsigned int*>(trans->get_data_ptr()) = + *reinterpret_cast<unsigned int*>(&mMem[address]); + } + + if (socket->nb_transport_bw(*trans, phase, t) == tlm::TLM_COMPLETED) { + // response phase ends after t + mEndResponseEvent.notify(t); + + } else { + // initiator will call nb_transport to indicate end of response phase + } + } + + void endResponse() + { + assert(!mResponseQueue.empty()); + mResponseQueue.front()->release(); + mResponseQueue.pop(); + + // Start processing next transaction when previous response is accepted. + // Notify begin of response phase after RESPONSE delay + if (!mResponseQueue.empty()) { + mBeginResponseEvent.notify(RESPONSE_DELAY); + } + } + +private: + const sc_core::sc_time ACCEPT_DELAY; + const sc_core::sc_time RESPONSE_DELAY; + +private: + unsigned char mMem[400]; + std::queue<transaction_type*> mResponseQueue; + sc_core::sc_event mBeginResponseEvent; + sc_core::sc_event mEndResponseEvent; +}; + +#endif diff --git a/src/systemc/tests/include/SimpleBusAT.h b/src/systemc/tests/include/SimpleBusAT.h new file mode 100644 index 000000000..db680338c --- /dev/null +++ b/src/systemc/tests/include/SimpleBusAT.h @@ -0,0 +1,378 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __SIMPLEBUSAT_H__ +#define __SIMPLEBUSAT_H__ + +//#include <systemc> +#include "tlm.h" + +#include "tlm_utils/simple_target_socket.h" +#include "tlm_utils/simple_initiator_socket.h" + +#include "tlm_utils/peq_with_get.h" + +template <int NR_OF_INITIATORS, int NR_OF_TARGETS> +class SimpleBusAT : public sc_core::sc_module +{ +public: + typedef tlm::tlm_generic_payload transaction_type; + typedef tlm::tlm_phase phase_type; + typedef tlm::tlm_sync_enum sync_enum_type; + typedef tlm_utils::simple_target_socket_tagged<SimpleBusAT> target_socket_type; + typedef tlm_utils::simple_initiator_socket_tagged<SimpleBusAT> initiator_socket_type; + +public: + target_socket_type target_socket[NR_OF_INITIATORS]; + initiator_socket_type initiator_socket[NR_OF_TARGETS]; + +public: + SC_HAS_PROCESS(SimpleBusAT); + SimpleBusAT(sc_core::sc_module_name name) : + sc_core::sc_module(name), + mRequestPEQ("requestPEQ"), + mResponsePEQ("responsePEQ") + { + for (unsigned int i = 0; i < NR_OF_INITIATORS; ++i) { + target_socket[i].register_nb_transport_fw(this, &SimpleBusAT::initiatorNBTransport, i); + target_socket[i].register_transport_dbg(this, &SimpleBusAT::transportDebug, i); + target_socket[i].register_get_direct_mem_ptr(this, &SimpleBusAT::getDMIPointer, i); + } + for (unsigned int i = 0; i < NR_OF_TARGETS; ++i) { + initiator_socket[i].register_nb_transport_bw(this, &SimpleBusAT::targetNBTransport, i); + initiator_socket[i].register_invalidate_direct_mem_ptr(this, &SimpleBusAT::invalidateDMIPointers, i); + } + + SC_THREAD(RequestThread); + SC_THREAD(ResponseThread); + } + + // + // Dummy decoder: + // - address[31-28]: portId + // - address[27-0]: masked address + // + + unsigned int getPortId(const sc_dt::uint64& address) + { + return (unsigned int)address >> 28; + } + + sc_dt::uint64 getAddressOffset(unsigned int portId) + { + return portId << 28; + } + + sc_dt::uint64 getAddressMask(unsigned int portId) + { + return 0xfffffff; + } + + unsigned int decode(const sc_dt::uint64& address) + { + // decode address: + // - return initiator socket id + + return getPortId(address); + } + + // + // AT protocol + // + + void RequestThread() + { + while (true) { + wait(mRequestPEQ.get_event()); + + transaction_type* trans; + while ((trans = mRequestPEQ.get_next_transaction())!=0) { + unsigned int portId = decode(trans->get_address()); + assert(portId < NR_OF_TARGETS); + initiator_socket_type* decodeSocket = &initiator_socket[portId]; + trans->set_address(trans->get_address() & getAddressMask(portId)); + + // Fill in the destination port + PendingTransactionsIterator it = mPendingTransactions.find(trans); + assert(it != mPendingTransactions.end()); + it->second.to = decodeSocket; + + phase_type phase = tlm::BEGIN_REQ; + sc_core::sc_time t = sc_core::SC_ZERO_TIME; + + // FIXME: No limitation on number of pending transactions + // All targets (that return false) must support multiple transactions + switch ((*decodeSocket)->nb_transport_fw(*trans, phase, t)) { + case tlm::TLM_ACCEPTED: + case tlm::TLM_UPDATED: + // Transaction not yet finished + if (phase == tlm::BEGIN_REQ) { + // Request phase not yet finished + wait(mEndRequestEvent); + + } else if (phase == tlm::END_REQ) { + // Request phase finished, but response phase not yet started + wait(t); + + } else if (phase == tlm::BEGIN_RESP) { + mResponsePEQ.notify(*trans, t); + // Not needed to send END_REQ to initiator + continue; + + } else { // END_RESP + assert(0); exit(1); + } + + // only send END_REQ to initiator if BEGIN_RESP was not already send + if (it->second.from) { + phase = tlm::END_REQ; + t = sc_core::SC_ZERO_TIME; + (*it->second.from)->nb_transport_bw(*trans, phase, t); + } + + break; + + case tlm::TLM_COMPLETED: + // Transaction finished + mResponsePEQ.notify(*trans, t); + + // reset to destination port (we must not send END_RESP to target) + it->second.to = 0; + + wait(t); + break; + + default: + assert(0); exit(1); + }; + } + } + } + + void ResponseThread() + { + while (true) { + wait(mResponsePEQ.get_event()); + + transaction_type* trans; + while ((trans = mResponsePEQ.get_next_transaction())!=0) { + PendingTransactionsIterator it = mPendingTransactions.find(trans); + assert(it != mPendingTransactions.end()); + + phase_type phase = tlm::BEGIN_RESP; + sc_core::sc_time t = sc_core::SC_ZERO_TIME; + + target_socket_type* initiatorSocket = it->second.from; + // if BEGIN_RESP is send first we don't have to send END_REQ anymore + it->second.from = 0; + + switch ((*initiatorSocket)->nb_transport_bw(*trans, phase, t)) { + case tlm::TLM_COMPLETED: + // Transaction finished + wait(t); + break; + + case tlm::TLM_ACCEPTED: + case tlm::TLM_UPDATED: + // Transaction not yet finished + wait(mEndResponseEvent); + break; + + default: + assert(0); exit(1); + }; + + // forward END_RESP to target + if (it->second.to) { + phase = tlm::END_RESP; + t = sc_core::SC_ZERO_TIME; + #if ( ! NDEBUG ) + sync_enum_type r = (*it->second.to)->nb_transport_fw(*trans, phase, t); + #endif /* ! NDEBUG */ + assert(r == tlm::TLM_COMPLETED); + } + + mPendingTransactions.erase(it); + trans->release(); + } + } + } + + // + // interface methods + // + + sync_enum_type initiatorNBTransport(int initiator_id, + transaction_type& trans, + phase_type& phase, + sc_core::sc_time& t) + { + if (phase == tlm::BEGIN_REQ) { + trans.acquire(); + addPendingTransaction(trans, 0, initiator_id); + + mRequestPEQ.notify(trans, t); + + } else if (phase == tlm::END_RESP) { + mEndResponseEvent.notify(t); + return tlm::TLM_COMPLETED; + + } else { + std::cout << "ERROR: '" << name() + << "': Illegal phase received from initiator." << std::endl; + assert(false); exit(1); + } + + return tlm::TLM_ACCEPTED; + } + + sync_enum_type targetNBTransport(int portId, + transaction_type& trans, + phase_type& phase, + sc_core::sc_time& t) + { + if (phase != tlm::END_REQ && phase != tlm::BEGIN_RESP) { + std::cout << "ERROR: '" << name() + << "': Illegal phase received from target." << std::endl; + assert(false); exit(1); + } + + mEndRequestEvent.notify(t); + if (phase == tlm::BEGIN_RESP) { + mResponsePEQ.notify(trans, t); + } + + return tlm::TLM_ACCEPTED; + } + + unsigned int transportDebug(int initiator_id, transaction_type& trans) + { + unsigned int portId = decode(trans.get_address()); + assert(portId < NR_OF_TARGETS); + initiator_socket_type* decodeSocket = &initiator_socket[portId]; + trans.set_address( trans.get_address() & getAddressMask(portId) ); + + return (*decodeSocket)->transport_dbg(trans); + } + + bool limitRange(unsigned int portId, sc_dt::uint64& low, sc_dt::uint64& high) + { + sc_dt::uint64 addressOffset = getAddressOffset(portId); + sc_dt::uint64 addressMask = getAddressMask(portId); + + if (low > addressMask) { + // Range does not overlap with addressrange for this target + return false; + } + + low += addressOffset; + if (high > addressMask) { + high = addressOffset + addressMask; + + } else { + high += addressOffset; + } + return true; + } + + bool getDMIPointer(int initiator_id, + transaction_type& trans, + tlm::tlm_dmi& dmi_data) + { + // FIXME: DMI not supported for AT bus? + sc_dt::uint64 address = trans.get_address(); + + unsigned int portId = decode(address); + assert(portId < NR_OF_TARGETS); + initiator_socket_type* decodeSocket = &initiator_socket[portId]; + sc_dt::uint64 maskedAddress = address & getAddressMask(portId); + + trans.set_address(maskedAddress); + + bool result = + (*decodeSocket)->get_direct_mem_ptr(trans, dmi_data); + + if (result) + { + // Range must contain address + assert(dmi_data.get_start_address() <= maskedAddress); + assert(dmi_data.get_end_address() >= maskedAddress); + } + + // Should always succeed + sc_dt::uint64 start, end; + start = dmi_data.get_start_address(); + end = dmi_data.get_end_address(); + + limitRange(portId, start, end); + + dmi_data.set_start_address(start); + dmi_data.set_end_address(end); + + return result; + } + + void invalidateDMIPointers(int portId, + sc_dt::uint64 start_range, + sc_dt::uint64 end_range) + { + // FIXME: probably faster to always invalidate everything? + + if ((portId >= 0) && !limitRange(portId, start_range, end_range)) { + // Range does not fall into address range of target + return; + } + + for (unsigned int i = 0; i < NR_OF_INITIATORS; ++i) { + (target_socket[i])->invalidate_direct_mem_ptr(start_range, end_range); + } + } + +private: + void addPendingTransaction(transaction_type& trans, + initiator_socket_type* to, + int initiatorId) + { + const ConnectionInfo info = { &target_socket[initiatorId], to }; + assert(mPendingTransactions.find(&trans) == mPendingTransactions.end()); + mPendingTransactions[&trans] = info; + } + +private: + struct ConnectionInfo { + target_socket_type* from; + initiator_socket_type* to; + }; + typedef std::map<transaction_type*, ConnectionInfo> PendingTransactions; + typedef typename PendingTransactions::iterator PendingTransactionsIterator; + typedef typename PendingTransactions::const_iterator PendingTransactionsConstIterator; + +private: + PendingTransactions mPendingTransactions; + + tlm_utils::peq_with_get<transaction_type> mRequestPEQ; + sc_core::sc_event mBeginRequestEvent; + sc_core::sc_event mEndRequestEvent; + + tlm_utils::peq_with_get<transaction_type> mResponsePEQ; + sc_core::sc_event mBeginResponseEvent; + sc_core::sc_event mEndResponseEvent; +}; + +#endif diff --git a/src/systemc/tests/include/SimpleBusLT.h b/src/systemc/tests/include/SimpleBusLT.h new file mode 100644 index 000000000..a2e71d866 --- /dev/null +++ b/src/systemc/tests/include/SimpleBusLT.h @@ -0,0 +1,193 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __SIMPLEBUSLT_H__ +#define __SIMPLEBUSLT_H__ + +//#include <systemc> +#include "tlm.h" + +#include "tlm_utils/simple_target_socket.h" +#include "tlm_utils/simple_initiator_socket.h" + +template <int NR_OF_INITIATORS, int NR_OF_TARGETS> +class SimpleBusLT : public sc_core::sc_module +{ +public: + typedef tlm::tlm_generic_payload transaction_type; + typedef tlm::tlm_phase phase_type; + typedef tlm::tlm_sync_enum sync_enum_type; + typedef tlm_utils::simple_target_socket_tagged<SimpleBusLT> target_socket_type; + typedef tlm_utils::simple_initiator_socket_tagged<SimpleBusLT> initiator_socket_type; + +public: + target_socket_type target_socket[NR_OF_INITIATORS]; + initiator_socket_type initiator_socket[NR_OF_TARGETS]; + +public: + SC_HAS_PROCESS(SimpleBusLT); + SimpleBusLT(sc_core::sc_module_name name) : + sc_core::sc_module(name) + { + for (unsigned int i = 0; i < NR_OF_INITIATORS; ++i) { + target_socket[i].register_b_transport(this, &SimpleBusLT::initiatorBTransport, i); + target_socket[i].register_transport_dbg(this, &SimpleBusLT::transportDebug, i); + target_socket[i].register_get_direct_mem_ptr(this, &SimpleBusLT::getDMIPointer, i); + } + for (unsigned int i = 0; i < NR_OF_TARGETS; ++i) { + initiator_socket[i].register_invalidate_direct_mem_ptr(this, &SimpleBusLT::invalidateDMIPointers, i); + } + } + + // + // Dummy decoder: + // - address[31-28]: portId + // - address[27-0]: masked address + // + + unsigned int getPortId(const sc_dt::uint64& address) + { + return (unsigned int)address >> 28; + } + + sc_dt::uint64 getAddressOffset(unsigned int portId) + { + return portId << 28; + } + + sc_dt::uint64 getAddressMask(unsigned int portId) + { + return 0xfffffff; + } + + unsigned int decode(const sc_dt::uint64& address) + { + // decode address: + // - return initiator socket id + + return getPortId(address); + } + + // + // interface methods + // + + // + // LT protocol + // - forward each call to the target/initiator + // + void initiatorBTransport(int SocketId, + transaction_type& trans, + sc_core::sc_time& t) + { + initiator_socket_type* decodeSocket; + unsigned int portId = decode(trans.get_address()); + assert(portId < NR_OF_TARGETS); + decodeSocket = &initiator_socket[portId]; + trans.set_address(trans.get_address() & getAddressMask(portId)); + + (*decodeSocket)->b_transport(trans, t); + } + + unsigned int transportDebug(int SocketId, + transaction_type& trans) + { + unsigned int portId = decode(trans.get_address()); + assert(portId < NR_OF_TARGETS); + initiator_socket_type* decodeSocket = &initiator_socket[portId]; + trans.set_address( trans.get_address() & getAddressMask(portId) ); + + return (*decodeSocket)->transport_dbg(trans); + } + + bool limitRange(unsigned int portId, sc_dt::uint64& low, sc_dt::uint64& high) + { + sc_dt::uint64 addressOffset = getAddressOffset(portId); + sc_dt::uint64 addressMask = getAddressMask(portId); + + if (low > addressMask) { + // Range does not overlap with addressrange for this target + return false; + } + + low += addressOffset; + if (high > addressMask) { + high = addressOffset + addressMask; + + } else { + high += addressOffset; + } + return true; + } + + bool getDMIPointer(int SocketId, + transaction_type& trans, + tlm::tlm_dmi& dmi_data) + { + sc_dt::uint64 address = trans.get_address(); + + unsigned int portId = decode(address); + assert(portId < NR_OF_TARGETS); + initiator_socket_type* decodeSocket = &initiator_socket[portId]; + sc_dt::uint64 maskedAddress = address & getAddressMask(portId); + + trans.set_address(maskedAddress); + + bool result = + (*decodeSocket)->get_direct_mem_ptr(trans, dmi_data); + + if (result) + { + // Range must contain address + assert(dmi_data.get_start_address() <= maskedAddress); + assert(dmi_data.get_end_address() >= maskedAddress); + } + + // Should always succeed + sc_dt::uint64 start, end; + start = dmi_data.get_start_address(); + end = dmi_data.get_end_address(); + + limitRange(portId, start, end); + + dmi_data.set_start_address(start); + dmi_data.set_end_address(end); + + return result; + } + + void invalidateDMIPointers(int port_id, + sc_dt::uint64 start_range, + sc_dt::uint64 end_range) + { + // FIXME: probably faster to always invalidate everything? + + if (!limitRange(port_id, start_range, end_range)) { + // Range does not fall into address range of target + return; + } + + for (unsigned int i = 0; i < NR_OF_INITIATORS; ++i) { + (target_socket[i])->invalidate_direct_mem_ptr(start_range, end_range); + } + } + +}; + +#endif diff --git a/src/systemc/tests/include/SimpleLTInitiator1.h b/src/systemc/tests/include/SimpleLTInitiator1.h new file mode 100644 index 000000000..6f1271278 --- /dev/null +++ b/src/systemc/tests/include/SimpleLTInitiator1.h @@ -0,0 +1,162 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +//==================================================================== +// Nov 06, 2008 +// +// Updated by: +// Xiaopeng Qiu, JEDA Technologies, Inc +// Email: qiuxp@jedatechnologies.net +// +// To fix violations of TLM2.0 rules, which are detected by JEDA +// TLM2.0 checker. +// +//==================================================================== + +#ifndef __SIMPLE_LT_INITIATOR1_H__ +#define __SIMPLE_LT_INITIATOR1_H__ + +#include "tlm.h" /// TLM definitions +#include <cassert> /// STD assert () + +class SimpleLTInitiator1 : + public sc_core::sc_module, + public virtual tlm::tlm_bw_transport_if<> +{ +public: + typedef tlm::tlm_generic_payload transaction_type; + typedef tlm::tlm_phase phase_type; + typedef tlm::tlm_sync_enum sync_enum_type; + typedef tlm::tlm_fw_transport_if<> fw_interface_type; + typedef tlm::tlm_bw_transport_if<> bw_interface_type; + typedef tlm::tlm_initiator_socket<32> initiator_socket_type; + +public: + initiator_socket_type socket; + +public: + SC_HAS_PROCESS(SimpleLTInitiator1); + SimpleLTInitiator1(sc_core::sc_module_name name, + unsigned int nrOfTransactions = 0x5, + unsigned int baseAddress = 0x0) : + sc_core::sc_module(name), + socket("socket"), + mNrOfTransactions(nrOfTransactions), + mBaseAddress(baseAddress), + mTransactionCount(0) + { + // Bind this initiator's interface to the initiator socket + socket(*this); + + // Initiator thread + SC_THREAD(run); + } + + bool initTransaction(transaction_type& trans) + { + if (mTransactionCount < mNrOfTransactions) { + trans.set_address(mBaseAddress + 4*mTransactionCount); + mData = mTransactionCount; + trans.set_command(tlm::TLM_WRITE_COMMAND); + + } else if (mTransactionCount < 2 * mNrOfTransactions) { + trans.set_address(mBaseAddress + 4*(mTransactionCount - mNrOfTransactions)); + mData = 0; + trans.set_command(tlm::TLM_READ_COMMAND); + + } else { + return false; + } + + trans.set_data_ptr(reinterpret_cast<unsigned char*>(&mData)); + trans.set_data_length(4); + trans.set_streaming_width(4); + trans.set_dmi_allowed(false); + trans.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE); + + ++mTransactionCount; + return true; + } + + void logStartTransation(transaction_type& trans) + { + if (trans.get_command() == tlm::TLM_WRITE_COMMAND) { + std::cout << name() << ": Send write request: A = 0x" + << std::hex << (unsigned int)trans.get_address() + << ", D = 0x" << mData << std::dec + << " @ " << sc_core::sc_time_stamp() << std::endl; + + } else { + std::cout << name() << ": Send read request: A = 0x" + << std::hex << (unsigned int)trans.get_address() << std::dec + << " @ " << sc_core::sc_time_stamp() << std::endl; + } + } + + void logEndTransaction(transaction_type& trans) + { + if (trans.get_response_status() != tlm::TLM_OK_RESPONSE) { + std::cout << name() << ": Received error response @ " + << sc_core::sc_time_stamp() << std::endl; + + } else { + std::cout << name() << ": Received ok response"; + if (trans.get_command() == tlm::TLM_READ_COMMAND) { + std::cout << ": D = 0x" << std::hex << mData << std::dec; + } + std::cout << " @ " << sc_core::sc_time_stamp() << std::endl; + } + } + + void run() + { + transaction_type trans; + sc_core::sc_time t(sc_core::SC_ZERO_TIME); + while (initTransaction(trans)) { + logStartTransation(trans); + socket->b_transport(trans, t); + wait(t); + logEndTransaction(trans); + t = sc_core::SC_ZERO_TIME; + } + wait(); + + } + + tlm::tlm_sync_enum nb_transport_bw(transaction_type &,phase_type &,sc_core::sc_time & ) + { + assert(0); // should never happen + return tlm::TLM_COMPLETED; + } + + void invalidate_direct_mem_ptr(sc_dt::uint64 start_range, + sc_dt::uint64 end_range) + { + // No DMI support: ignore + } + +private: + sc_core::sc_event mEndEvent; + unsigned int mNrOfTransactions; + unsigned int mBaseAddress; + unsigned int mTransactionCount; + unsigned int mData; +}; + +#endif diff --git a/src/systemc/tests/include/SimpleLTInitiator1_DMI.h b/src/systemc/tests/include/SimpleLTInitiator1_DMI.h new file mode 100644 index 000000000..4d982261f --- /dev/null +++ b/src/systemc/tests/include/SimpleLTInitiator1_DMI.h @@ -0,0 +1,305 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +//==================================================================== +// Nov 06, 2008 +// +// Updated by: +// Xiaopeng Qiu, JEDA Technologies, Inc +// Email: qiuxp@jedatechnologies.net +// +// To fix violations of TLM2.0 rules, which are detected by JEDA +// TLM2.0 checker. +// +//==================================================================== + +#ifndef __SIMPLE_LT_INITIATOR1_DMI_H__ +#define __SIMPLE_LT_INITIATOR1_DMI_H__ + +#include "tlm.h" +#include <systemc> +#include <cassert> +#include <iostream> +#include <iomanip> + +class SimpleLTInitiator1_dmi : + public sc_core::sc_module, + public virtual tlm::tlm_bw_transport_if<> +{ +public: + typedef tlm::tlm_generic_payload transaction_type; + typedef tlm::tlm_dmi dmi_type; + typedef tlm::tlm_phase phase_type; + typedef tlm::tlm_sync_enum sync_enum_type; + typedef tlm::tlm_fw_transport_if<> fw_interface_type; + typedef tlm::tlm_bw_transport_if<> bw_interface_type; + typedef tlm::tlm_initiator_socket<> initiator_socket_type; + +public: + initiator_socket_type socket; + +public: + SC_HAS_PROCESS(SimpleLTInitiator1_dmi); + SimpleLTInitiator1_dmi(sc_core::sc_module_name name, + unsigned int nrOfTransactions = 0x5, + unsigned int baseAddress = 0x0) : + sc_core::sc_module(name), + socket("socket"), + mNrOfTransactions(nrOfTransactions), + mBaseAddress(baseAddress), + mTransactionCount(0) + { + invalidate(mDMIData); + + // Bind this initiator's interface to the initiator socket + socket(*this); + + // Initiator thread + SC_THREAD(run); + } + + bool initTransaction(transaction_type& trans) + { + // initialize DMI hint: + trans.set_dmi_allowed(false); + + if (mTransactionCount < mNrOfTransactions) { + trans.set_address(mBaseAddress + 4*mTransactionCount); + mData = mTransactionCount; + trans.set_command(tlm::TLM_WRITE_COMMAND); + + } else if (mTransactionCount < 2 * mNrOfTransactions) { + trans.set_address(mBaseAddress + 4*(mTransactionCount-mNrOfTransactions)); + mData = 0; + trans.set_command(tlm::TLM_READ_COMMAND); + + } else { + return false; + } + + trans.set_data_ptr(reinterpret_cast<unsigned char*>(&mData)); + trans.set_data_length(4); + trans.set_streaming_width(4); + + ++mTransactionCount; + return true; + } + + void logStartTransation(transaction_type& trans) + { + if (trans.get_command() == tlm::TLM_WRITE_COMMAND) { + std::cout << name() << ": Send write request: A = 0x" + << std::hex << (unsigned int)trans.get_address() + << ", D = 0x" << mData << std::dec + << " @ " << sc_core::sc_time_stamp() << std::endl; + + } else { + std::cout << name() << ": Send read request: A = 0x" + << std::hex << (unsigned int)trans.get_address() << std::dec + << " @ " << sc_core::sc_time_stamp() << std::endl; + } + } + + void logEndTransaction(transaction_type& trans) + { + if (trans.get_response_status() != tlm::TLM_OK_RESPONSE) { + std::cout << name() << ": Received error response @ " + << sc_core::sc_time_stamp() << std::endl; + + } else { + std::cout << name() << ": Received ok response"; + if (trans.get_command() == tlm::TLM_READ_COMMAND) { + std::cout << ": D = 0x" << std::hex << mData << std::dec; + } + std::cout << " @ " << sc_core::sc_time_stamp() << std::endl; + } + } + + void run() + { + transaction_type trans; + phase_type phase; + sc_core::sc_time t; + + while (initTransaction(trans)) { + // Create transaction and initialise phase and t + phase = tlm::BEGIN_REQ; + t = sc_core::SC_ZERO_TIME; + + logStartTransation(trans); + + /////////////////////////////////////////////////////////// + // DMI handling: + // We use the DMI hint to check if it makes sense to ask for + // DMI pointers. The pattern is: + // - if the address is covered by a DMI region do a DMI access + // - otherwise do a normal transaction + // -> check if we get a DMI hint and acquire the DMI pointers if it is + // set + /////////////////////////////////////////////////////////// + + // Check if the address is covered by our DMI region + if ( (trans.get_address() >= mDMIData.get_start_address()) && + (trans.get_address() <= mDMIData.get_end_address()) ) { + // We can handle the data here. As the logEndTransaction is assuming + // something to happen in the data structure, we really need to + // do this: + trans.set_response_status(tlm::TLM_OK_RESPONSE); + sc_dt::uint64 tmp = trans.get_address() - mDMIData.get_start_address(); + if (trans.get_command() == tlm::TLM_WRITE_COMMAND) { + *(unsigned int*)&mDMIData.get_dmi_ptr()[tmp] = mData; + + } else { + mData = *(unsigned int*)&mDMIData.get_dmi_ptr()[tmp]; + } + + // Do the wait immediately. Note that doing the wait here eats almost + // all the performance anyway, so we only gain something if we're + // using temporal decoupling. + if (trans.get_command() == tlm::TLM_WRITE_COMMAND) { + wait(mDMIData.get_write_latency()); + + } else { + wait(mDMIData.get_read_latency()); + } + + logEndTransaction(trans); + + } else { // we need a full transaction + sc_dt::uint64 addr = trans.get_address(); //Save address before it is mutated + socket->b_transport(trans, t); + wait(t); + logEndTransaction(trans); + + // Acquire DMI pointer on is available: + if (trans.is_dmi_allowed()) + { + dmi_type tmp; + tmp.init(); + trans.set_address(addr); //restore address, in case it was mutated. + trans.set_write(); + if ( socket->get_direct_mem_ptr(trans, tmp) + && tmp.is_write_allowed() ) + { + mDMIData = tmp; + } + } + } + } + wait(); + } + + sync_enum_type nb_transport_bw(transaction_type& trans, phase_type& phase, sc_core::sc_time& t) + { + // We should never be called + assert(0); + return tlm::TLM_COMPLETED; + } + + void invalidate(dmi_type& dmiData) + { + dmiData.set_start_address(1); + dmiData.set_end_address(0); + } + + // Invalidate DMI pointer(s) + void invalidate_direct_mem_ptr(sc_dt::uint64 start_range, + sc_dt::uint64 end_range) + { + // do the invalidation if there is an address range overlap + if (start_range <= mDMIData.get_end_address ()&& + end_range >= mDMIData.get_start_address()) { + std::cout << name() << ": got DMI pointer invalidation" + << " @ " << sc_core::sc_time_stamp() << std::endl; + + invalidate(mDMIData); + } else { + std::cout << name() << ": ignored DMI invalidation for addresses " + << std::hex << start_range << ", " + << end_range << std::dec + << " @ " << sc_core::sc_time_stamp() << std::endl; + } + } + + // Test for transport_dbg: + // FIXME: use a configurable address + void end_of_simulation() + { + std::cout << name() << ", <<SimpleLTInitiator1>>:" << std::endl + << std::endl; + unsigned char data[32]; + + transaction_type trans; + trans.set_address(mBaseAddress); + trans.set_data_length(32); + trans.set_data_ptr(data); + trans.set_read(); + + unsigned int n = socket->transport_dbg(trans); + + std::cout << "Mem @" << std::hex << mBaseAddress << std::endl; + unsigned int j = 0; + + if (n > 0) + { + // always align endianness, so that we don't get a diff when + // printing the raw data + int e_start = 0; + int e_end = 4; + int e_increment = 1; + if (!tlm::host_has_little_endianness()) + { + e_start = 3; + e_end = -1; + e_increment = -1; + } + + for (unsigned int i=0; i<n; i+=4) + { + for (int k=e_start; k!=e_end; k+=e_increment) + { + std::cout << std::setw(2) << std::setfill('0') + << (int)data[i+k]; + j++; + if (j==16) { + j=0; + std::cout << std::endl; + } else { + std::cout << " "; + } + } + } + } + else + { + std::cout << "ERROR: debug transaction didn't give data." << std::endl; + } + std::cout << std::dec << std::endl; + } +private: + dmi_type mDMIData; + + sc_core::sc_event mEndEvent; + unsigned int mNrOfTransactions; + unsigned int mBaseAddress; + unsigned int mTransactionCount; + unsigned int mData; +}; + +#endif diff --git a/src/systemc/tests/include/SimpleLTInitiator2.h b/src/systemc/tests/include/SimpleLTInitiator2.h new file mode 100644 index 000000000..ee0118a21 --- /dev/null +++ b/src/systemc/tests/include/SimpleLTInitiator2.h @@ -0,0 +1,151 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +//==================================================================== +// Nov 06, 2008 +// +// Updated by: +// Xiaopeng Qiu, JEDA Technologies, Inc +// Email: qiuxp@jedatechnologies.net +// +// To fix violations of TLM2.0 rules, which are detected by JEDA +// TLM2.0 checker. +// +//==================================================================== + +#ifndef __SIMPLE_LT_INITIATOR2_H__ +#define __SIMPLE_LT_INITIATOR2_H__ + +#include "tlm.h" +#include "tlm_utils/simple_initiator_socket.h" +//#include <systemc> +#include <cassert> +//#include <iostream> + +class SimpleLTInitiator2 : public sc_core::sc_module +{ +public: + typedef tlm::tlm_generic_payload transaction_type; + typedef tlm::tlm_phase phase_type; + typedef tlm::tlm_sync_enum sync_enum_type; + typedef tlm_utils::simple_initiator_socket<SimpleLTInitiator2> initiator_socket_type; + +public: + initiator_socket_type socket; + +public: + SC_HAS_PROCESS(SimpleLTInitiator2); + SimpleLTInitiator2(sc_core::sc_module_name name, + unsigned int nrOfTransactions = 0x5, + unsigned int baseAddress = 0x0) : + sc_core::sc_module(name), + socket("socket"), + mNrOfTransactions(nrOfTransactions), + mBaseAddress(baseAddress), + mTransactionCount(0) + { + // Initiator thread + SC_THREAD(run); + } + + bool initTransaction(transaction_type& trans) + { + if (mTransactionCount < mNrOfTransactions) { + trans.set_address(mBaseAddress + 4*mTransactionCount); + mData = mTransactionCount; + trans.set_command(tlm::TLM_WRITE_COMMAND); + + } else if (mTransactionCount < 2 * mNrOfTransactions) { + trans.set_address(mBaseAddress + 4*(mTransactionCount - mNrOfTransactions)); + mData = 0; + trans.set_command(tlm::TLM_READ_COMMAND); + + } else { + return false; + } + + trans.set_data_ptr(reinterpret_cast<unsigned char*>(&mData)); + trans.set_data_length(4); + trans.set_streaming_width(4); + trans.set_dmi_allowed(false); + trans.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE); + + ++mTransactionCount; + return true; + } + + void logStartTransation(transaction_type& trans) + { + if (trans.get_command() == tlm::TLM_WRITE_COMMAND) { + std::cout << name() << ": Send write request: A = 0x" + << std::hex << (unsigned int)trans.get_address() + << ", D = 0x" << mData << std::dec + << " @ " << sc_core::sc_time_stamp() << std::endl; + + } else { + std::cout << name() << ": Send read request: A = 0x" + << std::hex << (unsigned int)trans.get_address() << std::dec + << " @ " << sc_core::sc_time_stamp() << std::endl; + } + } + + void logEndTransaction(transaction_type& trans) + { + if (trans.get_response_status() != tlm::TLM_OK_RESPONSE) { + std::cout << name() << ": Received error response @ " + << sc_core::sc_time_stamp() << std::endl; + + } else { + std::cout << name() << ": Received ok response"; + if (trans.get_command() == tlm::TLM_READ_COMMAND) { + std::cout << ": D = 0x" << std::hex << mData << std::dec; + } + std::cout << " @ " << sc_core::sc_time_stamp() << std::endl; + } + } + + void run() + { + transaction_type trans; + sc_core::sc_time t; + + while (initTransaction(trans)) { + // Create transaction and initialise t + t = sc_core::SC_ZERO_TIME; + + logStartTransation(trans); + + socket->b_transport(trans, t); + wait(t); + + logEndTransaction(trans); + } + wait(); + + } + +private: + sc_core::sc_event mEndEvent; + unsigned int mNrOfTransactions; + unsigned int mBaseAddress; + unsigned int mTransactionCount; + unsigned int mData; +}; + +#endif diff --git a/src/systemc/tests/include/SimpleLTInitiator2_DMI.h b/src/systemc/tests/include/SimpleLTInitiator2_DMI.h new file mode 100644 index 000000000..39fb76b1e --- /dev/null +++ b/src/systemc/tests/include/SimpleLTInitiator2_DMI.h @@ -0,0 +1,299 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +//==================================================================== +// Nov 06, 2008 +// +// Updated by: +// Xiaopeng Qiu, JEDA Technologies, Inc +// Email: qiuxp@jedatechnologies.net +// +// To fix violations of TLM2.0 rules, which are detected by JEDA +// TLM2.0 checker. +// +//==================================================================== + +#ifndef __SIMPLE_LT_INITIATOR2_DMI_H__ +#define __SIMPLE_LT_INITIATOR2_DMI_H__ + +#include "tlm.h" +#include "tlm_utils/simple_initiator_socket.h" +#include <systemc> +#include <cassert> +#include <iostream> +#include <iomanip> +#include <map> + +class SimpleLTInitiator2_dmi : public sc_core::sc_module +{ +public: + typedef tlm::tlm_generic_payload transaction_type; + typedef tlm::tlm_dmi dmi_type; + typedef tlm::tlm_phase phase_type; + typedef tlm::tlm_sync_enum sync_enum_type; + typedef tlm_utils::simple_initiator_socket<SimpleLTInitiator2_dmi> initiator_socket_type; + +public: + initiator_socket_type socket; + +public: + SC_HAS_PROCESS(SimpleLTInitiator2_dmi); + SimpleLTInitiator2_dmi(sc_core::sc_module_name name, + unsigned int nrOfTransactions = 0x5, + unsigned int baseAddress = 0x0) : + sc_core::sc_module(name), + socket("socket"), + mNrOfTransactions(nrOfTransactions), + mBaseAddress(baseAddress), + mTransactionCount(0) + { + mDMIDataReads.first.set_start_address(1); + mDMIDataReads.first.set_end_address(0); + mDMIDataWrites.first.set_start_address(1); + mDMIDataWrites.first.set_end_address(0); + + // register invalidate method + socket.register_invalidate_direct_mem_ptr(this, &SimpleLTInitiator2_dmi::invalidate_direct_mem_ptr); + + // Initiator thread + SC_THREAD(run); + } + + bool initTransaction(transaction_type& trans) + { + if (mTransactionCount < mNrOfTransactions) { + trans.set_address(mBaseAddress + 4*mTransactionCount); + mData = mTransactionCount; + trans.set_command(tlm::TLM_WRITE_COMMAND); + + } else if (mTransactionCount < 2 * mNrOfTransactions) { + trans.set_address(mBaseAddress + 4*(mTransactionCount-mNrOfTransactions)); + mData = 0; + trans.set_command(tlm::TLM_READ_COMMAND); + + } else { + return false; + } + + trans.set_data_ptr(reinterpret_cast<unsigned char*>(&mData)); + trans.set_data_length(4); + trans.set_streaming_width(4); + trans.set_dmi_allowed(false); + trans.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE); + + ++mTransactionCount; + return true; + } + + void logStartTransation(transaction_type& trans) + { + if (trans.get_command() == tlm::TLM_WRITE_COMMAND) { + std::cout << name() << ": Send write request: A = 0x" + << std::hex << (unsigned int)trans.get_address() + << ", D = 0x" << mData << std::dec + << " @ " << sc_core::sc_time_stamp() << std::endl; + + } else { + std::cout << name() << ": Send read request: A = 0x" + << std::hex << (unsigned int)trans.get_address() << std::dec + << " @ " << sc_core::sc_time_stamp() << std::endl; + } + } + + void logEndTransaction(transaction_type& trans) + { + if (trans.get_response_status() != tlm::TLM_OK_RESPONSE) { + std::cout << name() << ": Received error response @ " + << sc_core::sc_time_stamp() << std::endl; + + } else { + std::cout << name() << ": Received ok response"; + if (trans.get_command() == tlm::TLM_READ_COMMAND) { + std::cout << ": D = 0x" << std::hex << mData << std::dec; + } + std::cout << " @ " << sc_core::sc_time_stamp() << std::endl; + } + } + + std::pair<dmi_type, bool>& getDMIData(const transaction_type& trans) + { + if (trans.get_command() == tlm::TLM_READ_COMMAND) { + return mDMIDataReads; + + } else { // WRITE + return mDMIDataWrites; + } + } + + void run() + { + transaction_type trans; + sc_core::sc_time t; + + while (initTransaction(trans)) { + // Create transaction and initialise t + t = sc_core::SC_ZERO_TIME; + + logStartTransation(trans); + + /////////////////////////////////////////////////////////// + // DMI handling: + // We do *not* use the DMI hint to check if it makes sense to ask for + // DMI pointers. So the pattern is: + // - if the address is not covered by a DMI region try to acquire DMI + // pointers + // - if we have a DMI pointer, do the DMI "transaction" + // - otherwise fall back to a normal transaction + /////////////////////////////////////////////////////////// + + std::pair<dmi_type, bool>& dmi_data = getDMIData(trans); + + // Check if we need to acquire a DMI pointer + if((trans.get_address() < dmi_data.first.get_start_address()) || + (trans.get_address() > dmi_data.first.get_end_address()) ) + { + sc_dt::uint64 address = trans.get_address(); //save original address + dmi_data.second = + socket->get_direct_mem_ptr(trans, + dmi_data.first); + trans.set_address(address); + } + // Do DMI "transaction" if we have a valid region + if (dmi_data.second && + (trans.get_address() >= dmi_data.first.get_start_address()) && + (trans.get_address() <= dmi_data.first.get_end_address()) ) + { + // We can handle the data here. As the logEndTransaction is assuming + // something to happen in the data structure, we really need to + // do this: + trans.set_response_status(tlm::TLM_OK_RESPONSE); + sc_dt::uint64 tmp = trans.get_address() - dmi_data.first.get_start_address(); + if (trans.get_command() == tlm::TLM_WRITE_COMMAND) + { + *(unsigned int*)&dmi_data.first.get_dmi_ptr()[tmp] = mData; + } + else + { + mData = *(unsigned int*)&dmi_data.first.get_dmi_ptr()[tmp]; + } + + // Do the wait immediately. Note that doing the wait here eats almost + // all the performance anyway, so we only gain something if we're + // using temporal decoupling. + if (trans.get_command() == tlm::TLM_WRITE_COMMAND) { + wait(dmi_data.first.get_write_latency()); + + } else { + wait(dmi_data.first.get_read_latency()); + } + } + else // we need a full transaction + { + socket->b_transport(trans, t); + wait(t); + } + logEndTransaction(trans); + } + wait(); + + } + + // Invalidate DMI pointer(s) + void invalidate_direct_mem_ptr(sc_dt::uint64 start_range, + sc_dt::uint64 end_range) + { + // FIXME: probably faster to always invalidate everything? + if (start_range <= mDMIDataReads.first.get_end_address ()&& + end_range >= mDMIDataReads.first.get_start_address()) { + mDMIDataReads.second = false; + } + if (start_range <= mDMIDataWrites.first.get_end_address ()&& + end_range >= mDMIDataWrites.first.get_start_address()) { + mDMIDataWrites.second = false; + } + } + + // Test for transport_dbg, this one should fail in bus_dmi as we address + // a target that doesn't support transport_dbg: + // FIXME: use a configurable address + void end_of_simulation() + { + std::cout << name() << ", <<SimpleLTInitiator1>>:" << std::endl + << std::endl; + unsigned char data[32]; + + transaction_type trans; + trans.set_address(mBaseAddress); + trans.set_data_length(32); + trans.set_data_ptr(data); + trans.set_read(); + + unsigned int n = socket->transport_dbg(trans); + + std::cout << "Mem @" << std::hex << mBaseAddress << std::endl; + unsigned int j = 0; + + if (n > 0) + { + // always align endianness, so that we don't get a diff when + // printing the raw data + int e_start = 0; + int e_end = 4; + int e_increment = 1; + if (!tlm::host_has_little_endianness()) + { + e_start = 3; + e_end = -1; + e_increment = -1; + } + + for (unsigned int i=0; i<n; i+=4) + { + for (int k=e_start; k!=e_end; k+=e_increment) + { + std::cout << std::setw(2) << std::setfill('0') + << (int)data[i+k]; + j++; + if (j==16) { + j=0; + std::cout << std::endl; + } else { + std::cout << " "; + } + } + } + } + else + { + std::cout << "OK: debug transaction didn't give data." << std::endl; + } + std::cout << std::dec << std::endl; + } +private: + std::pair<dmi_type, bool> mDMIDataReads; + std::pair<dmi_type, bool> mDMIDataWrites; + + sc_core::sc_event mEndEvent; + unsigned int mNrOfTransactions; + unsigned int mBaseAddress; + unsigned int mTransactionCount; + unsigned int mData; +}; + +#endif diff --git a/src/systemc/tests/include/SimpleLTInitiator3.h b/src/systemc/tests/include/SimpleLTInitiator3.h new file mode 100644 index 000000000..d4eb63338 --- /dev/null +++ b/src/systemc/tests/include/SimpleLTInitiator3.h @@ -0,0 +1,152 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +//==================================================================== +// Nov 06, 2008 +// +// Updated by: +// Xiaopeng Qiu, JEDA Technologies, Inc +// Email: qiuxp@jedatechnologies.net +// +// To fix violations of TLM2.0 rules, which are detected by JEDA +// TLM2.0 checker. +// +//==================================================================== + +#ifndef __SIMPLE_LT_INITIATOR3_H__ +#define __SIMPLE_LT_INITIATOR3_H__ + +#include "tlm.h" +#include "tlm_utils/simple_initiator_socket.h" +//#include <systemc> +#include <cassert> +//#include <iostream> + +class SimpleLTInitiator3 : public sc_core::sc_module +{ +public: + typedef tlm::tlm_generic_payload transaction_type; + typedef tlm::tlm_phase phase_type; + typedef tlm::tlm_sync_enum sync_enum_type; + typedef tlm_utils::simple_initiator_socket<SimpleLTInitiator3> initiator_socket_type; + +public: + initiator_socket_type socket; + +public: + SC_HAS_PROCESS(SimpleLTInitiator3); + SimpleLTInitiator3(sc_core::sc_module_name name, + unsigned int nrOfTransactions = 0x5, + unsigned int baseAddress = 0x0) : + sc_core::sc_module(name), + socket("socket"), + mNrOfTransactions(nrOfTransactions), + mBaseAddress(baseAddress), + mTransactionCount(0) + { + // Initiator thread + SC_THREAD(run); + } + + bool initTransaction(transaction_type& trans) + { + if (mTransactionCount < mNrOfTransactions) { + trans.set_address(mBaseAddress + 4*mTransactionCount); + mData = mTransactionCount; + trans.set_command(tlm::TLM_WRITE_COMMAND); + + } else if (mTransactionCount < 2 * mNrOfTransactions) { + trans.set_address(mBaseAddress + 4*(mTransactionCount-mNrOfTransactions)); + mData = 0; + trans.set_command(tlm::TLM_READ_COMMAND); + + } else { + return false; + } + + trans.set_data_ptr(reinterpret_cast<unsigned char*>(&mData)); + trans.set_data_length(4); + trans.set_streaming_width(4); + trans.set_dmi_allowed(false); + trans.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE); + + ++mTransactionCount; + return true; + } + + void logStartTransation(transaction_type& trans) + { + if (trans.get_command() == tlm::TLM_WRITE_COMMAND) { + std::cout << name() << ": Send write request: A = 0x" + << std::hex << (unsigned int)trans.get_address() + << ", D = 0x" << mData << std::dec + << " @ " << sc_core::sc_time_stamp() << std::endl; + + } else { + std::cout << name() << ": Send read request: A = 0x" + << std::hex << (unsigned int)trans.get_address() << std::dec + << " @ " << sc_core::sc_time_stamp() << std::endl; + } + } + + void logEndTransaction(transaction_type& trans) + { + if (trans.get_response_status() != tlm::TLM_OK_RESPONSE) { + std::cout << name() << ": Received error response @ " + << sc_core::sc_time_stamp() << std::endl; + + } else { + std::cout << name() << ": Received ok response"; + if (trans.get_command() == tlm::TLM_READ_COMMAND) { + std::cout << ": D = 0x" << std::hex << mData << std::dec; + } + std::cout << " @ " << sc_core::sc_time_stamp() << std::endl; + } + } + + void run() + { + transaction_type trans; + sc_core::sc_time t; + + while (initTransaction(trans)) { + // Create transaction and initialise t + t = sc_core::SC_ZERO_TIME; + + logStartTransation(trans); + + socket->b_transport(trans, t); + // Transaction Finished, wait for the returned delay + wait(t); + + logEndTransaction(trans); + } + wait(); + + } + +private: + sc_core::sc_event mEndEvent; + unsigned int mNrOfTransactions; + unsigned int mBaseAddress; + unsigned int mTransactionCount; + unsigned int mData; +}; + +#endif diff --git a/src/systemc/tests/include/SimpleLTInitiator3_DMI.h b/src/systemc/tests/include/SimpleLTInitiator3_DMI.h new file mode 100644 index 000000000..6453a16a9 --- /dev/null +++ b/src/systemc/tests/include/SimpleLTInitiator3_DMI.h @@ -0,0 +1,244 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +//==================================================================== +// Nov 06, 2008 +// +// Updated by: +// Xiaopeng Qiu, JEDA Technologies, Inc +// Email: qiuxp@jedatechnologies.net +// +// To fix violations of TLM2.0 rules, which are detected by JEDA +// TLM2.0 checker. +// +//==================================================================== + +#ifndef __SIMPLE_LT_INITIATOR3_DMI_H__ +#define __SIMPLE_LT_INITIATOR3_DMI_H__ + +#include "tlm.h" +#include "tlm_utils/simple_initiator_socket.h" +#include <systemc> +#include <cassert> +#include <iostream> +#include <map> + +class SimpleLTInitiator3_dmi : public sc_core::sc_module +{ +public: + typedef tlm::tlm_generic_payload transaction_type; + typedef tlm::tlm_dmi dmi_type; + typedef tlm::tlm_phase phase_type; + typedef tlm::tlm_sync_enum sync_enum_type; + typedef tlm_utils::simple_initiator_socket<SimpleLTInitiator3_dmi> initiator_socket_type; + +public: + initiator_socket_type socket; + +public: + SC_HAS_PROCESS(SimpleLTInitiator3_dmi); + SimpleLTInitiator3_dmi(sc_core::sc_module_name name, + unsigned int nrOfTransactions = 0x5, + unsigned int baseAddress = 0x0) : + sc_core::sc_module(name), + socket("socket"), + mNrOfTransactions(nrOfTransactions), + mBaseAddress(baseAddress), + mTransactionCount(0) + { + mDMIDataReads.first.set_start_address(1); + mDMIDataReads.first.set_end_address(0); + mDMIDataWrites.first.set_start_address(1); + mDMIDataWrites.first.set_end_address(0); + + socket.register_invalidate_direct_mem_ptr(this, &SimpleLTInitiator3_dmi::invalidate_direct_mem_ptr); + + // Initiator thread + SC_THREAD(run); + } + + bool initTransaction(transaction_type& trans) + { + if (mTransactionCount < mNrOfTransactions) { + trans.set_address(mBaseAddress + 4*mTransactionCount); + mData = mTransactionCount; + trans.set_command(tlm::TLM_WRITE_COMMAND); + + } else if (mTransactionCount < 2 * mNrOfTransactions) { + trans.set_address(mBaseAddress + 4*(mTransactionCount-mNrOfTransactions)); + mData = 0; + trans.set_command(tlm::TLM_READ_COMMAND); + + } else { + return false; + } + + trans.set_data_ptr(reinterpret_cast<unsigned char*>(&mData)); + trans.set_data_length(4); + trans.set_streaming_width(4); + trans.set_dmi_allowed(false); + trans.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE); + + ++mTransactionCount; + return true; + } + + void logStartTransation(transaction_type& trans) + { + if (trans.get_command() == tlm::TLM_WRITE_COMMAND) { + std::cout << name() << ": Send write request: A = 0x" + << std::hex << (unsigned int)trans.get_address() + << ", D = 0x" << mData << std::dec + << " @ " << sc_core::sc_time_stamp() << std::endl; + + } else { + std::cout << name() << ": Send read request: A = 0x" + << std::hex << (unsigned int)trans.get_address() << std::dec + << " @ " << sc_core::sc_time_stamp() << std::endl; + } + } + + void logEndTransaction(transaction_type& trans) + { + if (trans.get_response_status() != tlm::TLM_OK_RESPONSE) { + std::cout << name() << ": Received error response @ " + << sc_core::sc_time_stamp() << std::endl; + + } else { + std::cout << name() << ": Received ok response"; + if (trans.get_command() == tlm::TLM_READ_COMMAND) { + std::cout << ": D = 0x" << std::hex << mData << std::dec; + } + std::cout << " @ " << sc_core::sc_time_stamp() << std::endl; + } + } + + std::pair<dmi_type, bool>& getDMIData(const transaction_type& trans) + { + if (trans.get_command() == tlm::TLM_READ_COMMAND) { + return mDMIDataReads; + + } else { // WRITE + return mDMIDataWrites; + } + } + + void run() + { + transaction_type trans; + sc_core::sc_time t; + + while (initTransaction(trans)) { + // Create transaction and initialise t + t = sc_core::SC_ZERO_TIME; + + logStartTransation(trans); + + /////////////////////////////////////////////////////////// + // DMI handling: + // We do *not* use the DMI hint to check if it makes sense to ask for + // DMI pointers. So the pattern is: + // - if the address is not covered by a DMI region try to acquire DMI + // pointers + // - if we have a DMI pointer, do the DMI "transaction" + // - otherwise fall back to a normal transaction + /////////////////////////////////////////////////////////// + + std::pair<dmi_type, bool>& dmi_data = getDMIData(trans); + + // Check if we need to acquire a DMI pointer + if((trans.get_address() < dmi_data.first.get_start_address()) || + (trans.get_address() > dmi_data.first.get_end_address()) ) + { + sc_dt::uint64 address = trans.get_address(); //save original address + dmi_data.second = + socket->get_direct_mem_ptr(trans, + dmi_data.first); + trans.set_address(address); + } + // Do DMI "transaction" if we have a valid region + if (dmi_data.second && + (trans.get_address() >= dmi_data.first.get_start_address()) && + (trans.get_address() <= dmi_data.first.get_end_address()) ) + { + // We can handle the data here. As the logEndTransaction is assuming + // something to happen in the data structure, we really need to + // do this: + trans.set_response_status(tlm::TLM_OK_RESPONSE); + + sc_dt::uint64 tmp = trans.get_address() - dmi_data.first.get_start_address(); + if (trans.get_command() == tlm::TLM_WRITE_COMMAND) + { + *(unsigned int*)&dmi_data.first.get_dmi_ptr()[tmp] = mData; + } + else + { + mData = *(unsigned int*)&dmi_data.first.get_dmi_ptr()[tmp]; + } + + // Do the wait immediately. Note that doing the wait here eats almost + // all the performance anyway, so we only gain something if we're + // using temporal decoupling. + if (trans.get_command() == tlm::TLM_WRITE_COMMAND) { + wait(dmi_data.first.get_write_latency()); + + } else { + wait(dmi_data.first.get_read_latency()); + } + } + else // we need a full transaction + { + socket->b_transport(trans, t); + // wait for the returned delay + wait(t); + } + + logEndTransaction(trans); + } + wait(); + + } + + // Invalidate DMI pointer(s) + void invalidate_direct_mem_ptr(sc_dt::uint64 start_range, + sc_dt::uint64 end_range) + { + // FIXME: probably faster to always invalidate everything? + if (start_range <= mDMIDataReads.first.get_end_address ()&& + end_range >= mDMIDataReads.first.get_start_address()) { + mDMIDataReads.second = false; + } + if (start_range <= mDMIDataWrites.first.get_end_address ()&& + end_range >= mDMIDataWrites.first.get_start_address()) { + mDMIDataWrites.second = false; + } + } + +private: + std::pair<dmi_type, bool> mDMIDataReads; + std::pair<dmi_type, bool> mDMIDataWrites; + + sc_core::sc_event mEndEvent; + unsigned int mNrOfTransactions; + unsigned int mBaseAddress; + unsigned int mTransactionCount; + unsigned int mData; +}; + +#endif diff --git a/src/systemc/tests/include/SimpleLTTarget1.h b/src/systemc/tests/include/SimpleLTTarget1.h new file mode 100644 index 000000000..37ac19a21 --- /dev/null +++ b/src/systemc/tests/include/SimpleLTTarget1.h @@ -0,0 +1,158 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __SIMPLE_LT_TARGET1_H__ +#define __SIMPLE_LT_TARGET1_H__ + +#include "tlm.h" +#include <cassert> +#include <vector> + +class SimpleLTTarget1 : + public sc_core::sc_module, + public virtual tlm::tlm_fw_transport_if<> +{ +public: + typedef tlm::tlm_generic_payload transaction_type; + typedef tlm::tlm_phase phase_type; + typedef tlm::tlm_sync_enum sync_enum_type; + typedef tlm::tlm_fw_transport_if<> fw_interface_type; + typedef tlm::tlm_bw_transport_if<> bw_interface_type; + typedef tlm::tlm_target_socket<32> target_socket_type; + +public: + target_socket_type socket; + +public: + SC_HAS_PROCESS(SimpleLTTarget1); + SimpleLTTarget1(sc_core::sc_module_name name, bool invalidate = false) : + sc_core::sc_module(name), + socket("socket"), + m_invalidate(invalidate) + { + // Bind this target's interface to the target socket + socket(*this); + if (invalidate) + { + SC_METHOD(invalidate_dmi_method); + sensitive << m_invalidate_dmi_event; + dont_initialize(); + m_invalidate_dmi_time = sc_core::sc_time(25, sc_core::SC_NS); + } + } + + sync_enum_type nb_transport_fw(transaction_type& trans, phase_type& phase, sc_core::sc_time& t) + { + //Target never calls wait, so we can do this + b_transport(trans, t); + + return tlm::TLM_COMPLETED; + } + + void b_transport(transaction_type& trans, sc_core::sc_time &t) + { + sc_dt::uint64 address = trans.get_address(); + assert(address < 400); + + unsigned int& data = *reinterpret_cast<unsigned int*>(trans.get_data_ptr()); + if (trans.get_command() == tlm::TLM_WRITE_COMMAND) { + std::cout << name() << ": Received write request: A = 0x" + << std::hex << (unsigned int)address + << ", D = 0x" << data << std::dec + << " @ " << sc_core::sc_time_stamp() << std::endl; + + *reinterpret_cast<unsigned int*>(&mMem[address]) = data; + t+= sc_core::sc_time(10, sc_core::SC_NS); + + } else { + std::cout << name() << ": Received read request: A = 0x" + << std::hex << (unsigned int)address << std::dec + << " @ " << sc_core::sc_time_stamp() << std::endl; + + data = *reinterpret_cast<unsigned int*>(&mMem[address]); + t += sc_core::sc_time(100, sc_core::SC_NS); + } + + trans.set_response_status(tlm::TLM_OK_RESPONSE); + + trans.set_dmi_allowed(true); + } + + unsigned int transport_dbg(transaction_type& r) + { + if (r.get_address() >= 400) return 0; + + unsigned int tmp = (int)r.get_address(); + unsigned int num_bytes; + if (tmp + r.get_data_length() >= 400) { + num_bytes = 400 - tmp; + + } else { + num_bytes = r.get_data_length(); + } + if (r.is_read()) { + for (unsigned int i = 0; i < num_bytes; ++i) { + r.get_data_ptr()[i] = mMem[i + tmp]; + } + + } else { + for (unsigned int i = 0; i < num_bytes; ++i) { + mMem[i + tmp] = r.get_data_ptr()[i]; + } + } + return num_bytes; + } + + bool get_direct_mem_ptr(transaction_type& trans, + tlm::tlm_dmi& dmi_data) + { + sc_dt::uint64 address = trans.get_address(); + if (m_invalidate) m_invalidate_dmi_event.notify(m_invalidate_dmi_time); + if (address < 400) { + dmi_data.allow_read_write(); + dmi_data.set_start_address(0x0); + dmi_data.set_end_address(399); + dmi_data.set_dmi_ptr(mMem); + dmi_data.set_read_latency(sc_core::sc_time(100, sc_core::SC_NS)); + dmi_data.set_write_latency(sc_core::sc_time(10, sc_core::SC_NS)); + return true; + + } else { + // should not happen + dmi_data.set_start_address(trans.get_address()); + dmi_data.set_end_address(trans.get_address()); + return false; + + } + } + + void invalidate_dmi_method() + { + sc_dt::uint64 start_address = 0x0; + sc_dt::uint64 end_address = 399; + socket->invalidate_direct_mem_ptr(start_address, end_address); + } +private: + unsigned char mMem[400]; + bool m_invalidate; + sc_core::sc_event m_invalidate_dmi_event; + sc_core::sc_time m_invalidate_dmi_time; +}; + +#endif diff --git a/src/systemc/tests/include/SimpleLTTarget2.h b/src/systemc/tests/include/SimpleLTTarget2.h new file mode 100644 index 000000000..61558dc56 --- /dev/null +++ b/src/systemc/tests/include/SimpleLTTarget2.h @@ -0,0 +1,149 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __SIMPLE_LT_TARGET2_H__ +#define __SIMPLE_LT_TARGET2_H__ + +#include "tlm.h" +#include "tlm_utils/passthrough_target_socket.h" +#include <cassert> +#include <vector> + +class SimpleLTTarget2 : public sc_core::sc_module +{ +public: + typedef tlm::tlm_generic_payload transaction_type; + typedef tlm::tlm_phase phase_type; + typedef tlm::tlm_sync_enum sync_enum_type; + typedef tlm_utils::passthrough_target_socket<SimpleLTTarget2> target_socket_type; + + +public: + target_socket_type socket; + +public: + SimpleLTTarget2(sc_core::sc_module_name name) : + sc_core::sc_module(name), + socket("socket") + { + // register nb_transport method + socket.register_b_transport(this, &SimpleLTTarget2::myBTransport); + socket.register_nb_transport_fw(this, &SimpleLTTarget2::myNBTransport); + socket.register_get_direct_mem_ptr(this, &SimpleLTTarget2::myGetDMIPtr); + + // TODO: we don't register the transport_dbg callback here, so we + // can test if something bad happens + // REGISTER_DEBUGTRANSPORT(socket, transport_dbg, 0); + } + + void myBTransport(transaction_type& trans, + sc_core::sc_time& t) + { + sc_dt::uint64 address = trans.get_address(); + assert(address < 400); + + unsigned int& data = *reinterpret_cast<unsigned int*>(trans.get_data_ptr()); + if (trans.get_command() == tlm::TLM_WRITE_COMMAND) { + std::cout << name() << ": Received write request: A = 0x" + << std::hex << (unsigned int)address + << ", D = 0x" << data << std::dec + << " @ " << sc_core::sc_time_stamp() << std::endl; + + *reinterpret_cast<unsigned int*>(&mMem[address]) = data; + t += sc_core::sc_time(10, sc_core::SC_NS); + + } else { + std::cout << name() << ": Received read request: A = 0x" + << std::hex << (unsigned int)address << std::dec + << " @ " << sc_core::sc_time_stamp() << std::endl; + + data = *reinterpret_cast<unsigned int*>(&mMem[address]); + t += sc_core::sc_time(100, sc_core::SC_NS); + } + + trans.set_response_status(tlm::TLM_OK_RESPONSE); + + trans.set_dmi_allowed(true); + } + + sync_enum_type myNBTransport(transaction_type& trans, + phase_type& phase, + sc_core::sc_time& t) + { + assert(phase == tlm::BEGIN_REQ); + + // Never blocks, so call b_transport implementation + myBTransport(trans, t); + // LT target + // - always return TLM_COMPLETED + // - not necessary to update phase (if TLM_COMPLETED is returned) + return tlm::TLM_COMPLETED; + } + + unsigned int transport_dbg(transaction_type& r) + { + if (r.get_address() >= 400) return 0; + + unsigned int tmp = (int)r.get_address(); + unsigned int num_bytes; + if (tmp + r.get_data_length() >= 400) { + num_bytes = 400 - tmp; + + } else { + num_bytes = r.get_data_length(); + } + if (r.is_read()) { + for (unsigned int i = 0; i < num_bytes; ++i) { + r.get_data_ptr()[i] = mMem[i + tmp]; + } + + } else { + for (unsigned int i = 0; i < num_bytes; ++i) { + mMem[i + tmp] = r.get_data_ptr()[i]; + } + } + return num_bytes; + } + + bool myGetDMIPtr(transaction_type& trans, + tlm::tlm_dmi& dmi_data) + { + sc_dt::uint64 address = trans.get_address(); + if (address < 400) { + dmi_data.allow_read_write(); + dmi_data.set_start_address(0x0); + dmi_data.set_end_address(399); + dmi_data.set_dmi_ptr(mMem); + dmi_data.set_read_latency(sc_core::sc_time(100, sc_core::SC_NS)); + dmi_data.set_write_latency(sc_core::sc_time(10, sc_core::SC_NS)); + return true; + + } else { + // should not happen + dmi_data.set_start_address(address); + dmi_data.set_end_address(address); + return false; + + } + } +private: + unsigned char mMem[400]; +}; + +#endif diff --git a/src/systemc/tests/include/specialized_signals/scx_signal_int.h b/src/systemc/tests/include/specialized_signals/scx_signal_int.h new file mode 100644 index 000000000..050521de0 --- /dev/null +++ b/src/systemc/tests/include/specialized_signals/scx_signal_int.h @@ -0,0 +1,1629 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_signal_int.cpp -- The sc_signal<sc_dt::sc_int<W> > implementations. + + Original Author: Andy Goodrich, Forte Design Systems, 2002-10-22 + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +/* +$Log: scx_signal_int.h,v $ +Revision 1.1 2011/08/15 17:31:11 acg + Andy Goodrich: moved specialized signals from examples to this tree. + +Revision 1.2 2011/08/15 16:43:24 acg + Torsten Maehne: changes to remove unused argument warnings. + +Revision 1.1.1.1 2006/12/15 20:20:03 acg +SystemC 2.3 + +Revision 1.2 2005/12/26 20:11:14 acg +Fixed up copyright. + +Revision 1.1.1.1 2005/12/19 23:16:42 acg +First check in of SystemC 2.1 into its own archive. + +Revision 1.11 2005/04/11 19:05:36 acg +Change to sc_clock for Microsoft VCC 6.0. Changes for namespaces + +Revision 1.10 2005/04/03 22:52:51 acg +Namespace changes. + +Revision 1.9 2005/03/21 22:31:32 acg +Changes to sc_core namespace. + +Revision 1.8 2004/09/27 21:01:59 acg +Andy Goodrich - Forte Design Systems, Inc. + - This is specialized signal support that allows better use of signals + and ports whose target value is a SystemC native type. + +*/ + + + +#include <systemc> +#include <typeinfo> + +/***************************************************************************** + + sc_signal_uint.h -- The sc_signal<sc_dt::sc_int<W> > definitions. + + Original Author: Andy Goodrich, Forte Design Systems, 2002-10-22 + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +/* +$Log: scx_signal_int.h,v $ +Revision 1.1 2011/08/15 17:31:11 acg + Andy Goodrich: moved specialized signals from examples to this tree. + +Revision 1.3 2011/08/15 16:43:24 acg + Torsten Maehne: changes to remove unused argument warnings. + +Revision 1.2 2011/06/28 21:23:02 acg + Andy Goodrich: merging of SCV tree. + +Revision 1.1.1.1 2006/12/15 20:20:03 acg +SystemC 2.3 + +Revision 1.2 2005/12/26 20:11:14 acg +Fixed up copyright. + +Revision 1.1.1.1 2005/12/19 23:16:42 acg +First check in of SystemC 2.1 into its own archive. + +Revision 1.21 2005/03/21 22:31:32 acg +Changes to sc_core namespace. + +Revision 1.20 2005/01/10 17:51:58 acg +Improvements. + +Revision 1.19 2004/11/09 00:11:26 acg +Added support for sc_generic_base<T> in place of sc_concatref. sc_concatref +now is derived from sc_generic_base<sc_concatref>. + +Revision 1.18 2004/09/27 21:01:59 acg +Andy Goodrich - Forte Design Systems, Inc. + - This is specialized signal support that allows better use of signals + and ports whose target value is a SystemC native type. + +*/ + + +#if !defined(SC_SIGNAL_INT_H) +#define SC_SIGNAL_INT_H + +#if ( !defined(_MSC_VER) || _MSC_VER > 1200 ) +# define SC_TEMPLATE template<int W> +#else +# define SC_TEMPLATE template<> template<int W> +#endif + + +// FORWARD REFERENCES AND USINGS: + + +namespace sc_core { + +class sc_int_sigref; + +//============================================================================== +// CLASS sc_int_part_if +// +// This class provides generic access to part selections for signals whose +// data type is sc_dt::sc_int<W>. This class serves as the base class for the +// sc_dt::sc_int<W> specialization of the sc_signal_in_if<T> class. The methods +// in this class may be over-ridden individually, those that are not overridden +// will produce an error message when called. The methods are used by the +// sc_int_sigref class. +// +// Notes: +// (1) Descriptions of the methods and operators in this class appear with +// their implementations in sc_signal<sc_dt::sc_int<W> >. +//============================================================================== +class sc_int_part_if : virtual public sc_interface { + protected: + // constructor: + sc_int_part_if() {} + + public: + // perform a part read. + virtual sc_dt::sc_int_base* part_read_target(); + virtual sc_dt::uint64 read_part( int left, int right ) const; + + // perform a part write. + virtual sc_int_sigref& select_part( int left, int right ); + virtual void write_part( sc_dt::uint64 v, int left, int right ); + + private: + sc_int_part_if( const sc_int_part_if& ); + sc_int_part_if& operator = ( const sc_int_part_if& ); +}; + + +//============================================================================== +// CLASS sc_signal_in_if<sc_dt::sc_int<W> > +// +// This is the class specializations for the sc_signal_in_if<T> class to +// provide additional features for sc_signal instances whose template is +// sc_dt::sc_int<W>, including part access. +// +// Notes: +// (1) Descriptions of the methods and operators in this class appear with +// their implementations in sc_signal<sc_dt::sc_int<W> >. +//============================================================================== +template< int W > +class sc_signal_in_if<sc_dt::sc_int<W> > : public sc_int_part_if { + friend class sc_int_sigref; + public: + typedef sc_signal_in_if<sc_dt::sc_int<W> > this_type; + + // get the value changed event + virtual const sc_event& value_changed_event() const = 0; + + + // read the current value + virtual const sc_dt::sc_int<W>& read() const = 0; + + // get a reference to the current value (for tracing) + virtual const sc_dt::sc_int<W>& get_data_ref() const = 0; + + + // was there a value changed event? + virtual bool event() const = 0; + + protected: + // constructor + sc_signal_in_if() + {} + + private: // disabled + sc_signal_in_if( const this_type& ); + this_type& operator = ( const this_type& ); +}; + +//============================================================================= +// CLASS : sc_int_sigref +// +// Proxy class for sc_signal_int bit and part selection. +//============================================================================= +class sc_int_sigref : public sc_dt::sc_int_subref_r +{ + public: + sc_int_sigref() : sc_dt::sc_int_subref_r() {} + virtual ~sc_int_sigref() {} + virtual void concat_set(sc_dt::int64 src, int low_i); + virtual void concat_set(const sc_dt::sc_signed& src, int low_i); + virtual void concat_set(const sc_dt::sc_unsigned& src, int low_i); + virtual void concat_set(const sc_dt::sc_lv_base& src, int low_i); + virtual void concat_set(sc_dt::uint64 src, int low_i); + + public: + inline void initialize( sc_int_part_if* if_p, int left_, int right_ ); + + public: + inline void operator = ( sc_dt::uint64 v ); + inline void operator = ( const char* v ); + inline void operator = ( unsigned long v ); + inline void operator = ( long v ); + inline void operator = ( unsigned int v ); + inline void operator = ( int v ); + inline void operator = ( sc_dt::int64 v ); + inline void operator = ( double v ); + inline void operator = ( const sc_int_sigref& v ); + template<typename T> + inline void operator = ( const sc_dt::sc_generic_base<T>& v ); + inline void operator = ( const sc_dt::sc_signed& v ); + inline void operator = ( const sc_dt::sc_unsigned& v ); + inline void operator = ( const sc_dt::sc_bv_base& v ); + inline void operator = ( const sc_dt::sc_lv_base& v ); + + public: + static sc_vpool<sc_int_sigref> m_pool; // Pool of objects to use. + + protected: + sc_int_part_if* m_if_p; // Target for selection. + + private: + + // disabled + sc_int_sigref( const sc_int_sigref& a ); +}; + + +//============================================================================== +// CLASS sc_signal<sc_dt::sc_int<W> > +// +// This class implements a signal whose value acts like an sc_dt::sc_int<W> data +// value. This class is a specialization of the generic sc_signal class to +// implement tailored support for the sc_dt::sc_int<W> class. +// +// Notes: +// (1) Descriptions of the methods and operators in this class appear with +// their implementations. +//============================================================================== +SC_TEMPLATE +class sc_signal<sc_dt::sc_int<W> > : + public sc_signal_inout_if<sc_dt::sc_int<W> >, + public sc_prim_channel, + public sc_dt::sc_int<W> +{ + public: // typedefs + typedef sc_signal<sc_dt::sc_int<W> > this_type; + + public: // constructors and destructor: + inline sc_signal(); + explicit inline sc_signal(const char* name_); + virtual inline ~sc_signal(); + + public: // base methods: + inline bool base_event() const; + inline const sc_dt::sc_int<W>& base_read() const; + inline const sc_event& base_value_changed_event() const; + inline void base_write( sc_dt::int64 value ); + + public: // sc_prim_channel virtual methods: + virtual inline const char* kind() const; + virtual inline void update(); + + public: // sc_interface virtual methods: + virtual inline const sc_event& default_event() const; + virtual inline void register_port( + sc_port_base& port_, const char* if_typename_ ); + + public: // sc_int_part_if virtual methods: + virtual inline sc_dt::sc_int_base* part_read_target(); + virtual inline sc_dt::uint64 read_part(int left, int right) const; + virtual inline sc_int_sigref& select_part(int left, int right); + virtual inline void write_part(sc_dt::uint64 v, int left, int right); + + public: // interface virtual methods: + virtual inline bool event() const; + virtual inline const sc_dt::sc_int<W>& get_data_ref() const; + virtual inline sc_signal<sc_dt::sc_int<W> >& get_signal() ; + virtual inline const sc_dt::sc_int<W>& read() const; + virtual inline const sc_event& value_changed_event() const; + virtual inline void write( const sc_in<sc_dt::sc_int<W> >& value ); + virtual inline void write( const sc_inout<sc_dt::sc_int<W> >& value ); + virtual inline void write( const sc_dt::sc_int<W>& value ); + + public: // part selections: + inline sc_int_sigref& operator () ( int left, int right ); + inline sc_int_sigref& operator [] ( int bit ); + + public: // operators: + inline void operator = ( const this_type& new_val ); + inline void operator = ( const char* new_val ); + inline void operator = ( sc_dt::uint64 new_val ); + inline void operator = ( sc_dt::int64 new_val ); + inline void operator = ( int new_val ); + inline void operator = ( long new_val ) ; + inline void operator = ( short new_val ) ; + inline void operator = ( unsigned int new_val ) ; + inline void operator = ( unsigned long new_val ); + inline void operator = ( unsigned short new_val ); + template<typename T> + inline void operator = ( const sc_dt::sc_generic_base<T>& new_val ); + inline void operator = ( const sc_dt::sc_signed& new_val ); + inline void operator = ( const sc_dt::sc_unsigned& new_val ); + inline void operator = ( const sc_dt::sc_bv_base& new_val ); + inline void operator = ( const sc_dt::sc_lv_base& new_val ); + + // concatenation methods (we inherit length and gets from sc_dt::sc_int<W>): + + virtual inline void concat_set(sc_dt::int64 src, int low_i); + virtual inline void concat_set(const sc_dt::sc_lv_base& src, int low_i); + virtual inline void concat_set(const sc_dt::sc_signed& src, int low_i); + virtual inline void concat_set(const sc_dt::sc_unsigned& src, int low_i); + virtual inline void concat_set(sc_dt::uint64 src, int low_i); + + protected: // debugging methods: + // #### void check_port(); + void check_writer(); + + private: // Disabled operations that sc_dt::sc_int<W> supports: + sc_signal<sc_dt::sc_int<W> >& operator ++ (); // prefix + const sc_signal<sc_dt::sc_int<W> >& operator ++ (int); // postfix + sc_signal<sc_dt::sc_int<W> >& operator -- (); // prefix + const sc_signal<sc_dt::sc_int<W> >& operator -- (int); // postfix + sc_signal<sc_dt::sc_int<W> >& operator += (sc_dt::int_type); + sc_signal<sc_dt::sc_int<W> >& operator -= (sc_dt::int_type); + sc_signal<sc_dt::sc_int<W> >& operator *= (sc_dt::int_type); + sc_signal<sc_dt::sc_int<W> >& operator /= (sc_dt::int_type); + sc_signal<sc_dt::sc_int<W> >& operator %= (sc_dt::int_type); + sc_signal<sc_dt::sc_int<W> >& operator &= (sc_dt::int_type); + sc_signal<sc_dt::sc_int<W> >& operator |= (sc_dt::int_type); + sc_signal<sc_dt::sc_int<W> >& operator ^= (sc_dt::int_type); + + protected: + mutable sc_event* m_changed_event_p; // Value changed event this object. + sc_dt::uint64 m_event_delta; // Delta cycle of last event. + sc_dt::int64 m_new_val; // New value for this object instance. + sc_port_base* m_output_p; // Single write port verify field. + sc_process_b* m_writer_p; // Single writer verify field. +}; + + +SC_TEMPLATE // Return true if a changed event happened in the last delta cycle. +inline bool sc_signal<sc_dt::sc_int<W> >::base_event() const +{ + return simcontext()->delta_count() == m_event_delta + 1; +} + + +SC_TEMPLATE // Return this object's sc_dt::sc_int<W> object instance. +inline const sc_dt::sc_int<W>& sc_signal<sc_dt::sc_int<W> >::base_read() const +{ + return *this; +} + + +SC_TEMPLATE // Return the value changed event, allocating it if necessary. +inline const sc_event& sc_signal<sc_dt::sc_int<W> >::base_value_changed_event() const +{ + if ( !m_changed_event_p ) m_changed_event_p = new sc_event; + return *m_changed_event_p; +} + + +SC_TEMPLATE // Select a portion of a value. +inline sc_int_sigref& sc_signal<sc_dt::sc_int<W> >::select_part(int left, int right) +{ + sc_int_sigref* result_p = sc_int_sigref::m_pool.allocate(); + result_p->initialize(this, left, right); + return *result_p; +} + + +SC_TEMPLATE // Write an sc_dt::uint64 value to this object instance. +inline void sc_signal<sc_dt::sc_int<W> >::base_write( sc_dt::int64 value ) +{ +# if defined(DEBUG_SYSTEMC) + check_writer(); +# endif + m_new_val = value; + request_update(); +} + +//------------------------------------------------------------------------------ +//"sc_signal<sc_dt::sc_int<W> >::check_writer" +// +// This method checks to see if there is more than one writer for this +// object instance by keeping track of the process performing the write. +//------------------------------------------------------------------------------ +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_int<W> >::check_writer() +{ + sc_process_b* writer_p = sc_get_curr_process_handle(); + if( m_writer_p == 0 ) + { + m_writer_p = writer_p; + } + else if( m_writer_p != writer_p ) + { + sc_signal_invalid_writer( name(), kind(), + m_writer_p->name(), writer_p->name() ); + } +} + + +//------------------------------------------------------------------------------ +//"sc_signal<sc_dt::sc_int<W> >::concat_set" +// +// These virtual methods allow value assignments to this object instance +// from various sources. The position within the supplied source of the +// low order bit for this object instance's value is low_i. +// src = source value. +// low_i = bit within src to serve as low order bit of this object +// instance's value. +//------------------------------------------------------------------------------ +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_int<W> >::concat_set(sc_dt::int64 src, int low_i) +{ + if ( low_i < 64 ) + { + base_write(src >> low_i); + } + else + { + base_write( src >> 63 ); + } +} + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_int<W> >::concat_set(const sc_dt::sc_lv_base& src, int low_i) +{ + sc_dt::sc_unsigned tmp(src.length()); + tmp = src >> low_i; + base_write( tmp.to_int64() ); +} + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_int<W> >::concat_set(const sc_dt::sc_signed& src, int low_i) +{ + base_write( (src >> low_i).to_int64()); +} + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_int<W> >::concat_set(const sc_dt::sc_unsigned& src, int low_i) +{ + base_write( (src >> low_i).to_int64()); +} + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_int<W> >::concat_set(sc_dt::uint64 src, int low_i) +{ + base_write( ( low_i < 64 ) ? src >> low_i : 0 ); +} + + + +SC_TEMPLATE // Return the default event for this object instance. +inline const sc_event& sc_signal<sc_dt::sc_int<W> >::default_event() const + { return base_value_changed_event(); } + + +SC_TEMPLATE // Return true if a changed event happened in the last delta cycle. +inline bool sc_signal<sc_dt::sc_int<W> >::event() const + { return base_event(); } + + +SC_TEMPLATE // Return a reference to the value of this object instance. +inline const sc_dt::sc_int<W>& sc_signal<sc_dt::sc_int<W> >::get_data_ref() const + { return *this; } + + +SC_TEMPLATE // Return a pointer to this object instance. +inline sc_signal<sc_dt::sc_int<W> >& sc_signal<sc_dt::sc_int<W> >::get_signal() + { return *this; } + + +SC_TEMPLATE // Return a kind value of "sc_signal". +inline const char* sc_signal<sc_dt::sc_int<W> >::kind() const +{ + return "sc_signal"; +} + + +//------------------------------------------------------------------------------ +//"sc_signal_uint::operator () +// +// This operator returns a part selection of this object instance. +// left = left-hand bit of the selection. +// right = right-hand bit of the selection. +//------------------------------------------------------------------------------ +SC_TEMPLATE +inline sc_int_sigref& sc_signal<sc_dt::sc_int<W> >::operator () (int left, int right) +{ + sc_int_sigref* result_p; // Value to return. + + result_p = sc_int_sigref::m_pool.allocate(); + result_p->initialize(this, left, right); + return *result_p; +} + + +//------------------------------------------------------------------------------ +//"sc_signal_uint::operator []" +// +// This operator returns a bit selection of this object instance. +// i = bit to be selected. +//------------------------------------------------------------------------------ +SC_TEMPLATE +inline sc_int_sigref& sc_signal<sc_dt::sc_int<W> >::operator [] ( int bit ) +{ + return operator () (bit,bit); +} + + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_int<W> >::operator = ( const this_type& new_val ) + { base_write( (sc_dt::int64)new_val ); } + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_int<W> >::operator = ( const char* new_val ) + { m_new_val = sc_dt::sc_int<64>(new_val); request_update(); } + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_int<W> >::operator = ( sc_dt::uint64 new_val ) + { base_write((sc_dt::int64)new_val); } + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_int<W> >::operator = ( sc_dt::int64 new_val ) + { base_write(new_val); } + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_int<W> >::operator = ( int new_val ) + { base_write((sc_dt::int64)new_val); } + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_int<W> >::operator = ( long new_val ) + { base_write((sc_dt::int64)new_val); } + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_int<W> >::operator = ( short new_val ) + { base_write((sc_dt::int64)new_val); } + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_int<W> >::operator = ( unsigned int new_val ) + { base_write((sc_dt::int64)new_val); } + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_int<W> >::operator = ( unsigned long new_val ) + { base_write((sc_dt::int64)new_val); } + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_int<W> >::operator = ( unsigned short new_val ) + { base_write((sc_dt::int64)new_val); } + + +SC_TEMPLATE +template<typename T> +inline void sc_signal<sc_dt::sc_int<W> >::operator = ( + const sc_dt::sc_generic_base<T>& new_val ) + { base_write(new_val->to_int64()); } + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_int<W> >::operator = ( const sc_dt::sc_signed& new_val ) + { base_write(new_val.to_int64()); } + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_int<W> >::operator = ( const sc_dt::sc_unsigned& new_val ) + { base_write(new_val.to_int64()); } + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_int<W> >::operator = ( const sc_dt::sc_bv_base& new_val ) + { base_write( (sc_dt::sc_int<W>)new_val ); } + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_int<W> >::operator = ( const sc_dt::sc_lv_base& new_val ) + { base_write( (sc_dt::sc_int<W>)new_val ); } + + +SC_TEMPLATE +inline sc_dt::sc_int_base* sc_signal<sc_dt::sc_int<W> >::part_read_target() + { return this; } + + +SC_TEMPLATE +inline const sc_dt::sc_int<W>& sc_signal<sc_dt::sc_int<W> >::read() const + { return *this; } + + +SC_TEMPLATE // Read a portion of a value. +inline sc_dt::uint64 sc_signal<sc_dt::sc_int<W> >::read_part( int left, int right ) const +{ + // This pointer required for HP aCC. + return (this->m_val & ~sc_dt::mask_int[left][right]) >> right; +} + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_int<W> >::register_port( + sc_port_base& port_, const char* if_typename_ ) +{ +# ifdef DEBUG_SYSTEMC + std::string nm( if_typename_ ); + if( nm == typeid( sc_signal_inout_if<sc_dt::sc_int<W> > ).name() ) + { + if( m_output_p != 0 ) + { + sc_signal_invalid_writer( name(), kind(), + m_output_p->name(), port_.name() ); + } + m_output_p = &port_; + } +# else + if ( &port_ && if_typename_ ) {} // Silence unused args warning. +# endif +} + + +SC_TEMPLATE // Autogenerated name object instance constructor. +inline sc_signal<sc_dt::sc_int<W> >::sc_signal() : + sc_prim_channel(sc_gen_unique_name( "signal" )), + m_changed_event_p(0), + m_output_p(0), + m_writer_p(0) +{ } + + +SC_TEMPLATE // Explicitly named object instance constructor. +inline sc_signal<sc_dt::sc_int<W> >::sc_signal(const char* name_) : + sc_prim_channel(name_), + m_changed_event_p(0), + m_output_p(0), + m_writer_p(0) +{ } + + +SC_TEMPLATE // Object instance destructor. +inline sc_signal<sc_dt::sc_int<W> >::~sc_signal() +{ + if ( m_changed_event_p ) delete m_changed_event_p; +} + + +SC_TEMPLATE // Update the current value from new value. +inline void sc_signal<sc_dt::sc_int<W> >::update() +{ + if ( m_changed_event_p ) + { + // This pointer required for HP aCC. + sc_dt::int64 old_val = this->m_val; + sc_dt::sc_int_base::operator = (m_new_val); + if ( old_val != this->m_val ) + { + m_changed_event_p->notify_delayed(); + m_event_delta = simcontext()->delta_count(); + } + } + else + { + sc_dt::sc_int_base::operator = (m_new_val); + } +} + + +SC_TEMPLATE // Return the value changed event. +inline const sc_event& sc_signal<sc_dt::sc_int<W> >::value_changed_event() const + { return base_value_changed_event(); } + + +SC_TEMPLATE // Write a sc_in<sc_dt::sc_int<W> > value to this object instance. +inline void sc_signal<sc_dt::sc_int<W> >::write( const sc_in<sc_dt::sc_int<W> >& value ) + { base_write( value.operator sc_dt::int64 () ); } + + +SC_TEMPLATE // Write a sc_inout<sc_dt::sc_int<W> > value to this object instance. +inline void sc_signal<sc_dt::sc_int<W> >::write( const sc_inout<sc_dt::sc_int<W> >& value ) + { base_write( value.operator sc_dt::int64 () ); } + + +SC_TEMPLATE // Write a sc_dt::sc_int<W> value to this object instance. +inline void sc_signal<sc_dt::sc_int<W> >::write( const sc_dt::sc_int<W>& value ) + { base_write( value); } + + +SC_TEMPLATE // Write a portion of a value. If this is the first write in + // a delta cycle we copy the existing value before setting the bits. +inline void sc_signal<sc_dt::sc_int<W> >::write_part( sc_dt::uint64 v, int left, int right ) +{ + sc_dt::int64 new_v; // New value. + sc_dt::uint64 keep; // Keep mask value. + + keep = sc_dt::mask_int[left][right]; + new_v = (m_new_val & keep) | ((v << right) & ~keep); + if ( m_new_val != new_v ) request_update(); + m_new_val = new_v; +} + + +//============================================================================== +// CLASS sc_in<sc_dt::sc_int<W> > +// +// This class implements an input port whose target acts like an sc_dt::sc_int<W> data +// value. This class is a specialization of the generic sc_in class to +// implement tailored support for the sc_dt::sc_int<W> class. +//============================================================================== +SC_TEMPLATE +class sc_in<sc_dt::sc_int<W> > : + public sc_port<sc_signal_in_if<sc_dt::sc_int<W> >, 1>, + public sc_dt::sc_value_base +{ + public: + + // typedefs + + typedef sc_dt::sc_int<W> data_type; + typedef sc_signal_in_if<sc_dt::sc_int<W> > if_type; + typedef sc_port<if_type,1> base_type; + typedef sc_in<sc_dt::sc_int<W> > this_type; + + typedef if_type in_if_type; + typedef base_type in_port_type; + typedef sc_signal_inout_if<sc_dt::sc_int<W> > inout_if_type; + typedef sc_inout<sc_dt::sc_int<W> > inout_port_type; + + public: + + // bind methods and operators: + + void bind( const in_if_type& interface_ ) + { sc_port_base::bind( const_cast<in_if_type&>( interface_) );} + void operator () ( const in_if_type& interface_ ) + { sc_port_base::bind( const_cast<in_if_type&>( interface_) );} + void bind( in_port_type& parent_ ) + { sc_port_base::bind(parent_);} + void operator () ( in_port_type& parent_ ) + { sc_port_base::bind(parent_);} + void bind( inout_port_type& parent_ ) + { sc_port_base::bind(parent_);} + void operator () ( inout_port_type& parent_ ) + { sc_port_base::bind(parent_);} + + protected: + // called by pbind (for internal use only) + virtual inline int vbind( sc_interface& interface_ ) + { + return sc_port_b<if_type>::vbind( interface_ ); + } + virtual inline int vbind( sc_port_base& parent_ ) + { + in_port_type* in_parent = dynamic_cast<in_port_type*>( &parent_ ); + if( in_parent != 0 ) { + sc_port_base::bind( *in_parent ); + return 0; + } + inout_port_type* inout_parent = dynamic_cast<inout_port_type*>( &parent_ ); + if( inout_parent != 0 ) { + sc_port_base::bind( *inout_parent ); + return 0; + } + // type mismatch + return 2; + } + + + // constructors + + public: + sc_in() + : base_type(), m_traces( 0 ) + {} + + explicit sc_in( const char* name_ ) + : base_type( name_ ), m_traces( 0 ) + {} + + explicit sc_in( const in_if_type& interface_ ) + : base_type( const_cast<in_if_type&>( interface_ ) ), m_traces( 0 ) + {} + + sc_in( const char* name_, const in_if_type& interface_ ) + : base_type( name_, const_cast<in_if_type&>( interface_ ) ), m_traces( 0 ) + {} + + explicit sc_in( in_port_type& parent_ ) + : base_type( parent_ ), m_traces( 0 ) + {} + + sc_in( const char* name_, in_port_type& parent_ ) + : base_type( name_, parent_ ), m_traces( 0 ) + {} + + explicit sc_in( inout_port_type& parent_ ) + : base_type(), m_traces( 0 ) + { sc_port_base::bind( parent_ ); } + + sc_in( const char* name_, inout_port_type& parent_ ) + : base_type( name_ ), m_traces( 0 ) + { sc_port_base::bind( parent_ ); } + + sc_in( this_type& parent_ ) + : base_type( parent_ ), m_traces( 0 ) + {} + + sc_in( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ), m_traces( 0 ) + {} + + + // destructor + + virtual inline ~sc_in() + { + remove_traces(); + } + + // bit and part selection + + sc_dt::sc_int_bitref_r operator [] ( int i ) const + { return (*this)->read()[i]; } + sc_dt::sc_int_bitref_r bit( int i ) const + { return (*this)->read()[i]; } + sc_dt::sc_int_subref_r operator () ( int left, int right ) const + { return (*this)->read()(left,right); } + sc_dt::sc_int_subref_r range( int left, int right ) const + { return (*this)->read()(left,right); } + + + // interface access shortcut methods + + // get the default event + + const sc_event& default_event() const + { return (*this)->value_changed_event(); } + + + // get the value changed event + + const sc_event& value_changed_event() const + { return (*this)->value_changed_event(); } + + + // read the current value + + const sc_dt::sc_int<W>& read() const + { return (*this)->read(); } + + operator sc_dt::int64 () const + { return (sc_dt::int64)(*this)->read(); } + + // was there a value changed event? + + bool event() const + { return (*this)->event(); } + + + // (other) event finder method(s) + + sc_event_finder& value_changed() const + { + return *new sc_event_finder_t<in_if_type>( + *this, &in_if_type::value_changed_event ); + } + + + + // reduction methods: + + inline bool and_reduce() const + { return (*this)->read().and_reduce(); } + inline bool nand_reduce() const + { return (*this)->read().nand_reduce(); } + inline bool nor_reduce() const + { return (*this)->read().nor_reduce(); } + inline bool or_reduce() const + { return (*this)->read().or_reduce(); } + inline bool xnor_reduce() const + { return (*this)->read().xnor_reduce(); } + inline bool xor_reduce() const + { return (*this)->read().xor_reduce(); } + + + // called when elaboration is done + /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ + /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ + + virtual inline void end_of_elaboration() + { + if( m_traces != 0 ) { + for( unsigned int i = 0; i < m_traces->size(); ++ i ) { + sc_trace_params* p = (*m_traces)[i]; + sc_trace( p->tf, read(), p->name ); + } + remove_traces(); + } + } + + virtual inline const char* kind() const + { return "sc_in"; } + + + // called by sc_trace + void add_trace( sc_trace_file* tf_, const std::string& name_ ) const + { + if( tf_ != 0 ) { + if( m_traces == 0 ) { + m_traces = new sc_trace_params_vec; + } + m_traces->push_back( new sc_trace_params( tf_, name_ ) ); + } + } + + + // concatenation methods + + virtual inline int concat_length(bool* xz_present_p) const + { return (*this)->read().concat_length( xz_present_p ); } + virtual inline sc_dt::uint64 concat_get_uint64() const + { return (*this)->read().concat_get_uint64(); } + virtual + inline bool concat_get_ctrl( sc_dt::sc_digit* dst_p, int low_i ) const + { return (*this)->read().concat_get_ctrl(dst_p, low_i); } + virtual + inline bool concat_get_data( sc_dt::sc_digit* dst_p, int low_i ) const + { return (*this)->read().concat_get_data(dst_p, low_i); } + + protected: + void remove_traces() const + { + if( m_traces != 0 ) { + for( int i = m_traces->size() - 1; i >= 0; -- i ) { + delete (*m_traces)[i]; + } + delete m_traces; + m_traces = 0; + } + } + + mutable sc_trace_params_vec* m_traces; + + + private: + + // disabled + sc_in( const sc_in<sc_dt::sc_int<W> >& ); + sc_in<sc_dt::sc_int<W> >& operator = ( const sc_in<sc_dt::sc_int<W> >& ); + +#ifdef __GNUC__ + // Needed to circumvent a problem in the g++-2.95.2 compiler: + // This unused variable forces the compiler to instantiate + // an object of T template so an implicit conversion from + // read() to a C++ intrinsic data type will work. + static data_type dummy; +#endif + +}; + + + +SC_TEMPLATE +inline std::ostream& operator << (std::ostream& os, const sc_in<sc_dt::sc_int<W> >& a) +{ + a.read().print( os ); + return os; +} + + +//============================================================================== +// CLASS sc_inout<sc_dt::sc_int<W> > +// +// This class implements an input/output port whose target acts like an +// sc_dt::sc_int<W> data value. It is derived from the sc_int_in. This class is a +// specialization of the generic sc_inout class to implement tailored support +// for the sc_dt::sc_int<W> class. +//============================================================================== +SC_TEMPLATE +class sc_inout<sc_dt::sc_int<W> > : + public sc_port<sc_signal_inout_if<sc_dt::sc_int<W> >, 1>, + public sc_dt::sc_value_base +{ + public: + + // typedefs + + typedef sc_dt::sc_int<W> data_type; + typedef sc_signal_inout_if<sc_dt::sc_int<W> > if_type; + typedef sc_port<if_type,1> base_type; + typedef sc_inout<sc_dt::sc_int<W> > this_type; + + typedef if_type inout_if_type; + typedef base_type inout_port_type; + + public: + + // bind methods and operators: + + void bind( const inout_if_type& interface_ ) + { sc_port_base::bind( const_cast<inout_if_type&>( interface_) ); } + void operator () ( const inout_if_type& interface_ ) + { sc_port_base::bind( const_cast<inout_if_type&>( interface_) ); } + void bind( inout_port_type& parent_ ) + { sc_port_base::bind(parent_); } + void operator () ( inout_port_type& parent_ ) + { sc_port_base::bind(parent_); } + + protected: + // called by pbind (for internal use only) + virtual inline int vbind( sc_interface& interface_ ) + { + return sc_port_b<if_type>::vbind( interface_ ); + } + virtual inline int vbind( sc_port_base& parent_ ) + { + inout_port_type* inout_parent = dynamic_cast<inout_port_type*>( &parent_ ); + if( inout_parent != 0 ) { + sc_port_base::bind( *inout_parent ); + return 0; + } + // type mismatch + return 2; + } + + + // constructors + + public: + sc_inout() + : base_type(), m_init_val_p(0), m_traces( 0 ) + {} + + explicit sc_inout( const char* name_ ) + : base_type( name_ ), m_init_val_p(0), m_traces( 0 ) + {} + + explicit sc_inout( inout_if_type& interface_ ) + : base_type( interface_ ), m_init_val_p(0), m_traces( 0 ) + {} + + sc_inout( const char* name_, inout_if_type& interface_ ) + : base_type( name_, interface_ ), m_init_val_p(0), m_traces( 0 ) + {} + + explicit sc_inout( inout_port_type& parent_ ) + : base_type( parent_ ), m_init_val_p(0), m_traces( 0 ) + {} + + sc_inout( const char* name_, inout_port_type& parent_ ) + : base_type( name_, parent_ ), m_init_val_p(0), m_traces( 0 ) + {} + + sc_inout( this_type& parent_ ) + : base_type( parent_ ), m_init_val_p(0), m_traces( 0 ) + {} + + sc_inout( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ), m_init_val_p(0), m_traces( 0 ) + {} + + + // destructor + + virtual inline ~sc_inout() + { + remove_traces(); + } + + // bit and part selection + + sc_dt::sc_int_bitref_r operator [] ( int i ) const + { return (*this)->read()[i]; } + sc_dt::sc_int_bitref_r bit( int i ) const + { return (*this)->read()[i]; } + sc_int_sigref& operator [] ( int i ) + { return (*this)->select_part(i,i); } + sc_int_sigref& bit( int i ) + { return (*this)->select_part(i,i); } + sc_dt::sc_int_subref_r operator () ( int left, int right ) const + { return (*this)->read()(left,right); } + sc_dt::sc_int_subref_r range( int left, int right ) const + { return (*this)->read()(left,right); } + sc_int_sigref& operator () ( int left, int right ) + { return (*this)->select_part(left,right); } + sc_int_sigref& range( int left, int right ) + { return (*this)->select_part(left,right); } + + + // interface access shortcut methods + + // get the default event + + const sc_event& default_event() const + { return (*this)->value_changed_event(); } + + + // get the value changed event + + const sc_event& value_changed_event() const + { return (*this)->value_changed_event(); } + + + // read the current value + + const sc_dt::sc_int<W>& read() const + { return (*this)->read(); } + + operator sc_dt::int64 () const + { return (sc_dt::int64)(*this)->read(); } + + // was there a value changed event? + + bool event() const + { return (*this)->event(); } + + + // (other) event finder method(s) + + sc_event_finder& value_changed() const + { + return *new sc_event_finder_t<inout_if_type>( + *this, &inout_if_type::value_changed_event ); + } + + + + // reduction methods: + + inline bool and_reduce() const + { return (*this)->read().and_reduce(); } + inline bool nand_reduce() const + { return (*this)->read().nand_reduce(); } + inline bool nor_reduce() const + { return (*this)->read().nor_reduce(); } + inline bool or_reduce() const + { return (*this)->read().or_reduce(); } + inline bool xnor_reduce() const + { return (*this)->read().xnor_reduce(); } + inline bool xor_reduce() const + { return (*this)->read().xor_reduce(); } + + + // called when elaboration is done + /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ + /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ + + virtual inline void end_of_elaboration() + { + if( m_init_val_p != 0 ) { + (*this)->write( (sc_dt::int64) *m_init_val_p ); + delete m_init_val_p; + m_init_val_p = 0; + } + if( m_traces != 0 ) { + for( unsigned int i = 0; i < m_traces->size(); ++ i ) { + sc_trace_params* p = (*m_traces)[i]; + sc_trace( p->tf, read(), p->name ); + } + remove_traces(); + } + } + + virtual inline const char* kind() const + { return "sc_inout"; } + + // value initialization + + inline void initialize( const sc_dt::sc_int<W>& value_ ) + { + inout_if_type* iface = this->get_interface(0); + if( iface != 0 ) { + iface->write( value_ ); + } else { + if( m_init_val_p == 0 ) { + m_init_val_p = new sc_dt::int64; + } + *m_init_val_p = value_; + } + } + + + // called by sc_trace + void add_trace( sc_trace_file* tf_, const std::string& name_ ) const + { + if( tf_ != 0 ) { + if( m_traces == 0 ) { + m_traces = new sc_trace_params_vec; + } + m_traces->push_back( new sc_trace_params( tf_, name_ ) ); + } + } + + + // concatenation methods + + virtual inline int concat_length(bool* xz_present_p) const + { return (*this)->read().concat_length( xz_present_p ); } + virtual inline sc_dt::uint64 concat_get_uint64() const + { return (*this)->read().concat_get_uint64(); } + virtual + inline bool concat_get_ctrl( sc_dt::sc_digit* dst_p, int low_i ) const + { return (*this)->read().concat_get_ctrl(dst_p, low_i); } + virtual + inline bool concat_get_data( sc_dt::sc_digit* dst_p, int low_i ) const + { return (*this)->read().concat_get_data(dst_p, low_i); } + virtual inline void concat_set(sc_dt::int64 src, int low_i) + { *this = src >> (( low_i < 64 ) ? low_i : 63); } +#if 0 // #### + virtual inline void concat_set(const sc_dt::sc_lv_base& src, int low_i) + { *this = src >> low_i; } +#endif // 0 #### + virtual inline void concat_set(const sc_dt::sc_signed& src, int low_i) + { *this = src >> low_i; } + virtual inline void concat_set(const sc_dt::sc_unsigned& src, int low_i) + { *this = src >> low_i; } + virtual inline void concat_set(sc_dt::uint64 src, int low_i) + { *this = ( low_i < 64 ) ? src >> low_i : (sc_dt::uint64)0; } + + // assignment operators: + + public: + inline void operator = ( const this_type& new_val ) + { (*this)->write( (sc_dt::int64)new_val ); } + inline void operator = ( const char* new_val ) + { (*this)->write( this_type(new_val) ); } + inline void operator = ( sc_dt::uint64 new_val ) + { (*this)->write(new_val); } + inline void operator = ( sc_dt::int64 new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( int new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( long new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( short new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( unsigned int new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( unsigned long new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( unsigned short new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + template<typename T> + inline void operator = ( const sc_dt::sc_generic_base<T>& new_val ) + { (*this)->write(new_val->to_uint64()); } + inline void operator = ( const sc_dt::sc_signed& new_val ) + { (*this)->write(new_val.to_uint64()); } + inline void operator = ( const sc_dt::sc_unsigned& new_val ) + { (*this)->write(new_val.to_uint64()); } + inline void operator = ( const sc_dt::sc_bv_base& new_val ) + { (*this)->write((sc_dt::sc_int<W>)new_val); } + inline void operator = ( const sc_dt::sc_lv_base& new_val ) + { (*this)->write((sc_dt::sc_int<W>)new_val); } + + inline void write( const sc_in<sc_dt::sc_int<W> >& new_val ) + { (*this)->write( (sc_dt::int64)new_val ); } + + inline void write( const sc_inout<sc_dt::sc_int<W> >& new_val ) + { (*this)->write( (sc_dt::int64)new_val); } + + inline void write( const sc_dt::sc_int<W>& new_val ) + { (*this)->write( (sc_dt::int64)new_val); } + + protected: + void remove_traces() const + { + if( m_traces != 0 ) { + for( int i = m_traces->size() - 1; i >= 0; -- i ) { + delete (*m_traces)[i]; + } + delete m_traces; + m_traces = 0; + } + } + + sc_dt::int64* m_init_val_p; + mutable sc_trace_params_vec* m_traces; + + + private: + + // disabled + sc_inout( const sc_inout<sc_dt::sc_int<W> >& ); + +#ifdef __GNUC__ + // Needed to circumvent a problem in the g++-2.95.2 compiler: + // This unused variable forces the compiler to instantiate + // an object of T template so an implicit conversion from + // read() to a C++ intrinsic data type will work. + static data_type dummy; +#endif + +}; + + + +SC_TEMPLATE +inline std::ostream& operator << ( + std::ostream& os, const sc_inout<sc_dt::sc_int<W> >& a ) +{ + a.read().print( os ); + return os; +} + + +//============================================================================== +// CLASS sc_out<sc_dt::sc_int<W> > +// +// This class implements an output port whose target acts like an +// sc_dt::sc_int<W> data value. This class is a derivation of sc_inout, since +// output ports are really no different from input/output ports. +//============================================================================== +SC_TEMPLATE +class sc_out<sc_dt::sc_int<W> > : public sc_inout<sc_dt::sc_int<W> > +{ + public: + + // typedefs + + typedef sc_dt::sc_int<W> data_type; + + typedef sc_out<data_type> this_type; + typedef sc_inout<data_type> base_type; + + typedef typename base_type::inout_if_type inout_if_type; + typedef typename base_type::inout_port_type inout_port_type; + + // constructors + + sc_out() + : base_type() + {} + + explicit sc_out( const char* name_ ) + : base_type( name_ ) + {} + + explicit sc_out( inout_if_type& interface_ ) + : base_type( interface_ ) + {} + + sc_out( const char* name_, inout_if_type& interface_ ) + : base_type( name_, interface_ ) + {} + + explicit sc_out( inout_port_type& parent_ ) + : base_type( parent_ ) + {} + + sc_out( const char* name_, inout_port_type& parent_ ) + : base_type( name_, parent_ ) + {} + + sc_out( this_type& parent_ ) + : base_type( parent_ ) + {} + + sc_out( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ) + {} + + + // destructor (does nothing) + + virtual inline ~sc_out() + {} + + + // assignment operators: + + public: + inline void operator = ( const this_type& new_val ) + { (*this)->write( (sc_dt::int64)new_val ); } + inline void operator = ( const char* new_val ) + { (*this)->write( this_type(new_val) ); } + inline void operator = ( sc_dt::uint64 new_val ) + { (*this)->write(new_val); } + inline void operator = ( sc_dt::int64 new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( int new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( long new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( short new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( unsigned int new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( unsigned long new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( unsigned short new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + template<typename T> + inline void operator = ( const sc_dt::sc_generic_base<T>& new_val ) + { (*this)->write(new_val->to_uint64()); } + inline void operator = ( const sc_dt::sc_signed& new_val ) + { (*this)->write(new_val); } + inline void operator = ( const sc_dt::sc_unsigned& new_val ) + { (*this)->write(new_val); } + inline void operator = ( const sc_dt::sc_bv_base& new_val ) + { (*this)->write((sc_dt::sc_int<W>)new_val); } + inline void operator = ( const sc_dt::sc_lv_base& new_val ) + { (*this)->write((sc_dt::sc_int<W>)new_val); } + + private: + + // disabled + sc_out( const this_type& ); +}; + + + +//------------------------------------------------------------------------------ +//"sc_int_sigref::initialize" +// +// This method initializes an object instance from the supplied arguments. +// if_p -> access to target of this selection. +// left = left-most bit in selection. +// right = right-most bit in selection. +//------------------------------------------------------------------------------ +inline +void sc_int_sigref::initialize(sc_int_part_if* if_p, int left, int right) +{ + m_if_p = if_p; + m_left = left; + m_right = right; + m_obj_p = if_p->part_read_target(); +} + + +//------------------------------------------------------------------------------ +//"sc_int_sigref::operator =" +// +// These operators assign a value to the bits associated with this object +// instance within this object instance's target signal. +//------------------------------------------------------------------------------ +inline void sc_int_sigref::operator = ( sc_dt::uint64 v ) +{ + m_if_p->write_part( v, m_left, m_right ); +} + +inline void sc_int_sigref::operator = ( const char* /*v*/ ) +{ +} + +inline void sc_int_sigref:: operator = ( sc_dt::int64 v ) +{ + *this = (sc_dt::uint64)v; +} + +inline void sc_int_sigref:: operator = ( int v ) +{ + *this = (sc_dt::uint64)v; +} + +inline void sc_int_sigref:: operator = ( long v ) +{ + *this = (sc_dt::uint64)v; +} + +inline void sc_int_sigref:: operator = ( unsigned int v ) +{ + *this = (sc_dt::uint64)v; +} + +inline void sc_int_sigref:: operator = ( unsigned long v ) +{ + *this = (sc_dt::uint64)v; +} + +void sc_int_sigref::operator = ( const sc_int_sigref& v ) +{ + *this = (sc_dt::uint64)v; +} + +template<typename T> +inline void sc_int_sigref:: operator = ( const sc_dt::sc_generic_base<T>& v ) +{ + *this = v->to_uint64(); +} + +inline void sc_int_sigref:: operator = ( const sc_dt::sc_signed& v ) +{ + *this = v.to_uint64(); +} + +inline void sc_int_sigref:: operator = ( const sc_dt::sc_unsigned& v ) +{ + *this = v.to_uint64(); +} + +#undef SC_TEMPLATE +#undef TTEST +} // namespace sc_core +#endif // !defined(SC_SIGNAL_INT_H) + +namespace sc_core { + +extern +void +sc_signal_invalid_writer( const char* name, + const char* kind, + const char* first_writer, + const char* second_writer ); + +//------------------------------------------------------------------------------ +// POOL OF TEMPORARY INSTANCES OF sc_int_sigref +// +// This allows use to pass const references for part and bit selections +// on sc_signal_int object instances. +//------------------------------------------------------------------------------ +sc_vpool<sc_int_sigref> sc_int_sigref::m_pool(8); + + +//------------------------------------------------------------------------------ +//"sc_int_part_if::default methods" +// +// These versions just produce errors if they are not overloaded but used. +//------------------------------------------------------------------------------ + +sc_dt::sc_int_base* sc_int_part_if::part_read_target() +{ + SC_REPORT_ERROR( "attempted specalized signal operation on " + "non-specialized signal", "int" ); + return 0; +} +sc_dt::uint64 sc_int_part_if::read_part( int /*left*/, int /*right*/ ) const +{ + SC_REPORT_ERROR( "attempted specalized signal operation on " + "non-specialized signal", "int" ); + return 0; +} +sc_int_sigref& sc_int_part_if::select_part( int /*left*/, int /*right*/ ) +{ + SC_REPORT_ERROR( "attempted specalized signal operation on " + "non-specialized signal", "int" ); + return *(sc_int_sigref*)0; +} +void sc_int_part_if::write_part( sc_dt::uint64 v, int /*left*/, int /*right*/ ) +{ + SC_REPORT_ERROR( "attempted specalized signal operation on " + "non-specialized signal", "int" ); +} + + +//------------------------------------------------------------------------------ +//"sc_int_sigref::concate_set" +// +// These methods assign this object instance's value from the supplied +// value starting at the supplied bit within that value. +// src = value to use to set this object instance's value. +// low_i = bit in src that is to be the low order bit of the value to set. +// #### OPTIMIZE +//------------------------------------------------------------------------------ +void sc_int_sigref::concat_set(sc_dt::int64 src, int low_i) +{ + *this = (low_i < 64) ? src >> low_i : src >> 63; +} + + +void sc_int_sigref::concat_set(const sc_dt::sc_signed& src, int low_i) +{ + if ( low_i < src.length() ) + *this = src >> low_i; + else + *this = (src < 0) ? (sc_dt::uint64)-1 : 0; +} + + +void sc_int_sigref::concat_set(const sc_dt::sc_lv_base& src, int low_i) +{ + if ( low_i < src.length() ) + *this = (src >> low_i).to_uint64(); + else + *this = 0; +} + + +void sc_int_sigref::concat_set(const sc_dt::sc_unsigned& src, int low_i) +{ + if ( low_i < src.length() ) + *this = src >> low_i; + else + *this = 0; +} + + +void sc_int_sigref::concat_set(sc_dt::uint64 src, int low_i) +{ + *this = (low_i < 64) ? src >> low_i : 0; +} + +} // namespace sc_core diff --git a/src/systemc/tests/include/specialized_signals/scx_signal_signed.h b/src/systemc/tests/include/specialized_signals/scx_signal_signed.h new file mode 100644 index 000000000..bb48cecb3 --- /dev/null +++ b/src/systemc/tests/include/specialized_signals/scx_signal_signed.h @@ -0,0 +1,1833 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_signal_signed.cpp -- The sc_signal<sc_bigint<W> > implementations. + + Original Author: Andy Goodrich, Forte Design Systems, 2002-10-22 + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +/* +$Log: scx_signal_signed.h,v $ +Revision 1.1 2011/08/15 17:31:11 acg + Andy Goodrich: moved specialized signals from examples to this tree. + +Revision 1.2 2011/08/15 16:43:24 acg + Torsten Maehne: changes to remove unused argument warnings. + +Revision 1.1.1.1 2006/12/15 20:20:03 acg +SystemC 2.3 + +Revision 1.2 2005/12/26 20:11:14 acg +Fixed up copyright. + +Revision 1.1.1.1 2005/12/19 23:16:42 acg +First check in of SystemC 2.1 into its own archive. + +Revision 1.17 2005/09/15 23:01:52 acg +Added std:: prefix to appropriate methods and types to get around +issues with the Edison Front End. + +Revision 1.16 2005/05/03 19:52:26 acg +Get proper header locations on includes. + +Revision 1.15 2005/05/03 19:50:20 acg +Name space version. + +Revision 1.12 2005/04/11 19:05:36 acg +Change to sc_clock for Microsoft VCC 6.0. Changes for namespaces + +Revision 1.11 2005/04/03 22:52:52 acg +Namespace changes. + +Revision 1.10 2005/03/21 22:31:32 acg +Changes to sc_core namespace. + +Revision 1.9 2004/09/27 21:01:59 acg +Andy Goodrich - Forte Design Systems, Inc. + - This is specialized signal support that allows better use of signals + and ports whose target value is a SystemC native type. + +*/ + + + +#include <systemc> + +using sc_dt::sc_bigint; +using sc_dt::sc_bv_base; +using sc_dt::sc_lv_base; +using sc_dt::sc_concatref; +using sc_dt::sc_signed; +using sc_dt::sc_signed_subref_r; +using sc_dt::sc_unsigned; +using sc_dt::uint64; + +#include <typeinfo> + +/***************************************************************************** + + sc_signal_signed.h -- The sc_signal<sc_dt::sc_bigint<W> > definitions. + + Original Author: Andy Goodrich, Forte Design Systems, 2002-10-22 + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +/* +$Log: scx_signal_signed.h,v $ +Revision 1.1 2011/08/15 17:31:11 acg + Andy Goodrich: moved specialized signals from examples to this tree. + +Revision 1.3 2011/08/15 16:43:24 acg + Torsten Maehne: changes to remove unused argument warnings. + +Revision 1.2 2011/06/28 21:23:02 acg + Andy Goodrich: merging of SCV tree. + +Revision 1.1.1.1 2006/12/15 20:20:03 acg +SystemC 2.3 + +Revision 1.4 2006/10/23 19:40:35 acg + Andy Goodrich: added an explicit dynamic cast to keep gcc 4.x happy. + +Revision 1.3 2006/03/21 01:31:48 acg + Andy Goodrich: changed over to sc_get_current_process_b() from + sc_get_current_process_base() since the function's name changed. + +Revision 1.2 2005/12/26 20:11:14 acg +Fixed up copyright. + +Revision 1.1.1.1 2005/12/19 23:16:42 acg +First check in of SystemC 2.1 into its own archive. + +Revision 1.29 2005/09/15 23:01:52 acg +Added std:: prefix to appropriate methods and types to get around +issues with the Edison Front End. + +Revision 1.28 2005/07/30 03:44:11 acg +Changes from 2.1. + +Revision 1.27 2005/05/09 17:17:12 acg +Changes from 2.1. + +Revision 1.26 2005/05/08 19:04:06 acg +Fix bug in concat_set(int64,off). Other changes from 2.1 examples usage. + +Revision 1.25 2005/05/03 20:05:16 acg +Prefixed with sc_dt some sc_signed instances that were missed. + +Revision 1.24 2005/05/03 19:50:20 acg +Name space version. + +Revision 1.22 2005/03/21 22:31:32 acg +Changes to sc_core namespace. + +Revision 1.21 2005/01/10 17:51:58 acg +Improvements. + +Revision 1.20 2004/11/09 00:11:27 acg +Added support for sc_generic_base<T> in place of sc_concatref. sc_concatref +now is derived from sc_generic_base<sc_concatref>. + +Revision 1.19 2004/09/27 21:01:59 acg +Andy Goodrich - Forte Design Systems, Inc. + - This is specialized signal support that allows better use of signals + and ports whose target value is a SystemC native type. + +*/ + + +#if !defined(SC_SIGNAL_SIGNED_H) +#define SC_SIGNAL_SIGNED_H + +#if ( !defined(_MSC_VER) || _MSC_VER > 1200 ) +# define SC_TEMPLATE template<int W> +#else +# define SC_TEMPLATE template<> template<int W> +#endif + +// FORWARD REFERENCES AND USINGS: + +using sc_dt::int64; + +namespace sc_core { + +class sc_signed_sigref; + +//============================================================================== +// CLASS sc_signed_part_if +// +// This class provides generic access to part selections for signals whose +// data type is sc_dt::sc_bigint<W>. This class serves as the base class for the +// sc_dt::sc_bigint<W> specialization of the sc_signal_in_if<T> class. The methods +// in this class may be over-ridden individually, those that are not overridden +// will produce an error message when called. The methods are used by the +// sc_bigint_sigref class. +// +// Notes: +// (1) Descriptions of the methods and operators in this class appear with +// their implementations in sc_signal<sc_dt::sc_bigint<W> >. +//============================================================================== +class sc_signed_part_if : virtual public sc_interface { + protected: + // constructor: + sc_signed_part_if() {} + + public: + // perform a part read. + virtual sc_dt::sc_signed* part_read_target(); + virtual sc_dt::sc_signed read_part( int left, int right ) const; + + // perform a part write. + virtual sc_signed_sigref& select_part( int left, int right ); + virtual void write_part( sc_dt::int64 v, int left, int right ); + virtual void write_part( sc_dt::uint64 v, int left, int right ); + virtual void write_part( const sc_dt::sc_signed& v, int left, int right ); + virtual void write_part( const sc_dt::sc_unsigned& v, int left, int right ); + + + private: + sc_signed_part_if( const sc_signed_part_if& ); + sc_signed_part_if& operator = ( const sc_signed_part_if& ); +}; + + +//============================================================================== +// CLASS sc_signal_in_if<sc_dt::sc_bigint<W> > +// +// This is the class specializations for the sc_signal_in_if<T> class to +// provide additional features for sc_signal instances whose template is +// sc_dt::sc_bigint<W>, including part access. +// +// Notes: +// (1) Descriptions of the methods and operators in this class appear with +// their implementations in sc_signal<sc_dt::sc_bigint<W> >. +//============================================================================== +template< int W > +class sc_signal_in_if<sc_dt::sc_bigint<W> > : public sc_signed_part_if { + friend class sc_signed_sigref; + public: + typedef sc_signal_in_if<sc_dt::sc_bigint<W> > this_type; + + // get the value changed event + virtual const sc_event& value_changed_event() const = 0; + + + // read the current value + virtual const sc_dt::sc_bigint<W>& read() const = 0; + + // get a reference to the current value (for tracing) + virtual const sc_dt::sc_bigint<W>& get_data_ref() const = 0; + + + // was there a value changed event? + virtual bool event() const = 0; + + protected: + // constructor + sc_signal_in_if() + {} + + private: // disabled + sc_signal_in_if( const this_type& ); + this_type& operator = ( const this_type& ); +}; + +//============================================================================= +// CLASS : sc_signed_sigref +// +// Proxy class for sc_signal_uint bit and part selection. +//============================================================================= +class sc_signed_sigref : public sc_dt::sc_signed_subref_r +{ + public: + sc_signed_sigref() : sc_dt::sc_signed_subref_r() {} + virtual ~sc_signed_sigref() {} + virtual void concat_set(sc_dt::int64 src, int low_i); + virtual void concat_set(const sc_dt::sc_signed& src, int low_i); + virtual void concat_set(const sc_dt::sc_unsigned& src, int low_i); + virtual void concat_set(const sc_dt::sc_lv_base& src, int low_i); + virtual void concat_set(sc_dt::uint64 src, int low_i); + + public: + inline void initialize( sc_signed_part_if* if_p, int left_, int right_ ); + + public: + inline void operator = ( sc_dt::uint64 v ); + inline void operator = ( const char* v ); + inline void operator = ( unsigned long v ); + inline void operator = ( long v ); + inline void operator = ( unsigned int v ); + inline void operator = ( int v ); + inline void operator = ( sc_dt::int64 v ); + inline void operator = ( double v ); + inline void operator = ( const sc_signed_sigref& v ); + template<typename T> + inline void operator = ( const sc_dt::sc_generic_base<T>& v ); + inline void operator = ( const sc_dt::sc_signed& v ); + inline void operator = ( const sc_dt::sc_unsigned& v ); + inline void operator = ( const sc_dt::sc_bv_base& v ); + inline void operator = ( const sc_dt::sc_lv_base& v ); + + public: + static sc_vpool<sc_signed_sigref> m_pool; // Pool of objects to use. + + protected: + sc_signed_part_if* m_if_p; // Target for selection. + + private: + + // disabled + sc_signed_sigref( const sc_signed_sigref& a ); +}; + + +//============================================================================== +// CLASS sc_signal<sc_dt::sc_bigint<W> > +// +// This class implements a signal whose value acts like an sc_dt::sc_bigint<W> data +// value. This class is a specialization of the generic sc_signal class to +// implement tailored support for the sc_dt::sc_bigint<W> class. +// +// Notes: +// (1) Descriptions of the methods and operators in this class appear with +// their implementations. +//============================================================================== +SC_TEMPLATE +class sc_signal<sc_dt::sc_bigint<W> > : + public sc_dt::sc_bigint<W>, + public sc_prim_channel, + public sc_signal_inout_if<sc_dt::sc_bigint<W> > +{ + public: // typedefs + typedef sc_signal<sc_dt::sc_bigint<W> > this_type; + + public: // constructors and destructor: + inline sc_signal(); + explicit inline sc_signal(const char* name_); + virtual inline ~sc_signal(); + + public: // base methods: + inline bool base_event() const; + inline const sc_dt::sc_bigint<W>& base_read() const; + inline const sc_event& base_value_changed_event() const; + inline void base_write( sc_dt::int64 value ); + inline void base_write( sc_dt::uint64 value ); + inline void base_write( const sc_dt::sc_signed& value ); + inline void base_write( const sc_dt::sc_unsigned& value ); + + public: // sc_prim_channel virtual methods: + virtual inline const char* kind() const; + virtual inline void update(); + + public: // sc_interface virtual methods: + virtual inline const sc_event& default_event() const; + virtual inline void register_port( + sc_port_base& port_, const char* if_typename_ ); + + public: // sc_signed_part_if virtual methods: + virtual inline sc_dt::sc_signed* part_read_target(); + virtual inline sc_dt::sc_signed read_part(int left, int right) const; + virtual sc_signed_sigref& select_part( int left, int right ); + virtual inline void write_part( sc_dt::int64 v, int left, int right ); + virtual inline void write_part( sc_dt::uint64 v, int left, int right ); + virtual inline void write_part( const sc_dt::sc_signed& v, int left, int right ); + virtual inline void write_part(const sc_dt::sc_unsigned& v, int left, int right); + + public: // interface virtual methods: + virtual inline bool event() const; + virtual inline const sc_dt::sc_bigint<W>& get_data_ref() const; + virtual inline sc_signal<sc_dt::sc_bigint<W> >& get_signal(); + virtual inline const sc_dt::sc_bigint<W>& read() const; + virtual inline const sc_event& value_changed_event() const; + virtual inline void write( const sc_in<sc_dt::sc_bigint<W> >& value ); + virtual inline void write( const sc_inout<sc_dt::sc_bigint<W> >& value ); + virtual inline void write( const sc_dt::sc_bigint<W>& value ); + + public: // part selections: + inline sc_signed_sigref& operator () ( int left, int right ); + // #### Need to add bit() and range() + inline sc_signed_sigref& operator [] ( int bit ); + + public: // operators: + inline void operator = ( const this_type& new_val ); + inline void operator = ( const char* new_val ); + inline void operator = ( sc_dt::uint64 new_val ); + inline void operator = ( sc_dt::int64 new_val ); + inline void operator = ( int new_val ); + inline void operator = ( long new_val ); + inline void operator = ( short new_val ); + inline void operator = ( unsigned int new_val ); + inline void operator = ( unsigned long new_val ); + inline void operator = ( unsigned short new_val ); + template<typename T> + inline void operator = ( const sc_dt::sc_generic_base<T>& new_val ); + inline void operator = ( const sc_dt::sc_signed& new_val ); + inline void operator = ( const sc_dt::sc_unsigned& new_val ); + inline void operator = ( const sc_dt::sc_bv_base& new_val ); + inline void operator = ( const sc_dt::sc_lv_base& new_val ); + + // concatenation methods (we inherit length and gets from sc_dt::sc_bigint<W>): + + virtual inline void concat_set(sc_dt::int64 src, int low_i); + virtual inline void concat_set(const sc_dt::sc_lv_base& src, int low_i); + virtual inline void concat_set(const sc_dt::sc_signed& src, int low_i); + virtual inline void concat_set(const sc_dt::sc_unsigned& src, int low_i); + virtual inline void concat_set(sc_dt::uint64 src, int low_i); + + protected: // debugging methods: + // #### void check_port(); + void check_writer(); + + private: // Disabled operations that sc_dt::sc_bigint<W> supports: + sc_dt::sc_signed& operator ++ (); // prefix + const sc_dt::sc_signed& operator ++ (int); // postfix + sc_dt::sc_signed& operator -- (); // prefix + const sc_dt::sc_signed& operator -- (int); // postfix + sc_dt::sc_signed& operator += (const sc_dt::sc_signed& ); + sc_dt::sc_signed& operator += (const sc_dt::sc_unsigned& ); + sc_dt::sc_signed& operator += (sc_dt::int64 ); + sc_dt::sc_signed& operator += (sc_dt::uint64 ); + sc_dt::sc_signed& operator += (long ); + sc_dt::sc_signed& operator += (unsigned long ); + sc_dt::sc_signed& operator += (int ); + sc_dt::sc_signed& operator += (unsigned int ); + sc_dt::sc_signed& operator -= (const sc_dt::sc_signed& ); + sc_dt::sc_signed& operator -= (const sc_dt::sc_unsigned& ); + sc_dt::sc_signed& operator -= (sc_dt::int64 ); + sc_dt::sc_signed& operator -= (sc_dt::uint64 ); + sc_dt::sc_signed& operator -= (long ); + sc_dt::sc_signed& operator -= (unsigned long ); + sc_dt::sc_signed& operator -= (int ); + sc_dt::sc_signed& operator -= (unsigned int ); + sc_dt::sc_signed& operator *= (const sc_dt::sc_signed& ); + sc_dt::sc_signed& operator *= (const sc_dt::sc_unsigned& ); + sc_dt::sc_signed& operator *= (sc_dt::int64 ); + sc_dt::sc_signed& operator *= (sc_dt::uint64 ); + sc_dt::sc_signed& operator *= (long ); + sc_dt::sc_signed& operator *= (unsigned long ); + sc_dt::sc_signed& operator *= (int ); + sc_dt::sc_signed& operator *= (unsigned int ); + sc_dt::sc_signed& operator /= (const sc_dt::sc_signed& ); + sc_dt::sc_signed& operator /= (const sc_dt::sc_unsigned& ); + sc_dt::sc_signed& operator /= (sc_dt::int64 ); + sc_dt::sc_signed& operator /= (sc_dt::uint64 ); + sc_dt::sc_signed& operator /= (long ); + sc_dt::sc_signed& operator /= (unsigned long ); + sc_dt::sc_signed& operator /= (int ); + sc_dt::sc_signed& operator /= (unsigned int ); + sc_dt::sc_signed& operator %= (const sc_dt::sc_signed& ); + sc_dt::sc_signed& operator %= (const sc_dt::sc_unsigned& ); + sc_dt::sc_signed& operator %= (sc_dt::int64 ); + sc_dt::sc_signed& operator %= (sc_dt::uint64 ); + sc_dt::sc_signed& operator %= (long ); + sc_dt::sc_signed& operator %= (unsigned long ); + sc_dt::sc_signed& operator %= (int ); + sc_dt::sc_signed& operator %= (unsigned int ); + sc_dt::sc_signed& operator &= (const sc_dt::sc_signed& ); + sc_dt::sc_signed& operator &= (const sc_dt::sc_unsigned& ); + sc_dt::sc_signed& operator &= (sc_dt::int64 ); + sc_dt::sc_signed& operator &= (sc_dt::uint64 ); + sc_dt::sc_signed& operator &= (long ); + sc_dt::sc_signed& operator &= (unsigned long ); + sc_dt::sc_signed& operator &= (int ); + sc_dt::sc_signed& operator &= (unsigned int ); + sc_dt::sc_signed& operator |= (const sc_dt::sc_signed& ); + sc_dt::sc_signed& operator |= (const sc_dt::sc_unsigned& ); + sc_dt::sc_signed& operator |= (sc_dt::int64 ); + sc_dt::sc_signed& operator |= (sc_dt::uint64 ); + sc_dt::sc_signed& operator |= (long ); + sc_dt::sc_signed& operator |= (unsigned long ); + sc_dt::sc_signed& operator |= (int ); + sc_dt::sc_signed& operator |= (unsigned int ); + sc_dt::sc_signed& operator ^= (const sc_dt::sc_signed& ); + sc_dt::sc_signed& operator ^= (const sc_dt::sc_unsigned& ); + sc_dt::sc_signed& operator ^= (sc_dt::int64 ); + sc_dt::sc_signed& operator ^= (sc_dt::uint64 ); + sc_dt::sc_signed& operator ^= (long ); + sc_dt::sc_signed& operator ^= (unsigned long ); + sc_dt::sc_signed& operator ^= (int ); + sc_dt::sc_signed& operator ^= (unsigned int ); + + protected: + mutable sc_event* m_changed_event_p; // Value changed event this object. + sc_dt::uint64 m_event_delta; // Delta cycle of last event. + sc_dt::sc_signed m_new_val; // New value for this object instance. + sc_port_base* m_output_p; // Single write port verify field. + sc_process_b* m_writer_p; // Single writer verify field. +}; + + +SC_TEMPLATE // Return true if a changed event happened in the last delta cycle. +inline bool sc_signal<sc_dt::sc_bigint<W> >::base_event() const +{ + return simcontext()->delta_count() == m_event_delta + 1; +} + + +SC_TEMPLATE // Return this object's sc_dt::sc_bigint<W> object instance. +inline const sc_dt::sc_bigint<W>& sc_signal<sc_dt::sc_bigint<W> >::base_read() const +{ + return *this; +} + + +SC_TEMPLATE // Return the value changed event, allocating it if necessary. +inline const sc_event& sc_signal<sc_dt::sc_bigint<W> >::base_value_changed_event() const +{ + if ( !m_changed_event_p ) m_changed_event_p = new sc_event; + return *m_changed_event_p; +} + + +SC_TEMPLATE // Write a const sc_dt::sc_signed& value to this object instance. +inline void sc_signal<sc_dt::sc_bigint<W> >::base_write( const sc_dt::sc_signed& value ) +{ +# if defined(DEBUG_SYSTEMC) + check_writer(); +# endif + m_new_val = value; + request_update(); +} + +SC_TEMPLATE // Write a const sc_dt::sc_unsigned& value to this object instance. +inline void sc_signal<sc_dt::sc_bigint<W> >::base_write( const sc_dt::sc_unsigned& value ) +{ +# if defined(DEBUG_SYSTEMC) + check_writer(); +# endif + m_new_val = value; + request_update(); +} + +SC_TEMPLATE // Write a sc_dt::int64 value to this object instance. +inline void sc_signal<sc_dt::sc_bigint<W> >::base_write( sc_dt::int64 value ) +{ +# if defined(DEBUG_SYSTEMC) + check_writer(); +# endif + m_new_val = value; + request_update(); +} + + +SC_TEMPLATE // Write a sc_dt::uint64 value to this object instance. +inline void sc_signal<sc_dt::sc_bigint<W> >::base_write( sc_dt::uint64 value ) +{ +# if defined(DEBUG_SYSTEMC) + check_writer(); +# endif + m_new_val = value; + request_update(); +} + + +//------------------------------------------------------------------------------ +//"sc_signal<sc_dt::sc_bigint<W> >::check_writer" +// +// This method checks to see if there is more than one writer for this +// object instance by keeping track of the process performing the write. +//------------------------------------------------------------------------------ +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_bigint<W> >::check_writer() +{ + sc_process_b* writer_p = sc_get_current_process_b(); + if( m_writer_p == 0 ) + { + m_writer_p = writer_p; + } + else if( m_writer_p != writer_p ) + { + sc_signal_invalid_writer( name(), kind(), + m_writer_p->name(), writer_p->name() ); + } +} + + +//------------------------------------------------------------------------------ +//"sc_signal<sc_dt::sc_bigint<W> >::concat_set" +// +// These virtual methods allow value assignments to this object instance +// from various sources. The position within the supplied source of the +// low order bit for this object instance's value is low_i. +// src = source value. +// low_i = bit within src to serve as low order bit of this object +// instance's value. +//------------------------------------------------------------------------------ +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_bigint<W> >::concat_set(sc_dt::int64 src, int low_i) +{ + if ( low_i < 64 ) + { + base_write(src >> low_i); + } + else + { + base_write( (sc_dt::int64)((src < 0 ) ? -1 : 0 )); + } +} + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_bigint<W> >::concat_set( + const sc_dt::sc_lv_base& src, int low_i) +{ + sc_dt::sc_unsigned tmp(src.length()); + tmp = src >> low_i; + base_write( tmp ); +} + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_bigint<W> >::concat_set( + const sc_dt::sc_signed& src, int low_i) +{ + base_write( (src >> low_i) ); +} + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_bigint<W> >::concat_set( + const sc_dt::sc_unsigned& src, int low_i) +{ + base_write( (src >> low_i) ); +} + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_bigint<W> >::concat_set(sc_dt::uint64 src, int low_i) +{ + base_write( (sc_dt::uint64)(( low_i < 64 ) ? src >> low_i : 0)); +} + + + +SC_TEMPLATE // Return the default event for this object instance. +inline const sc_event& sc_signal<sc_dt::sc_bigint<W> >::default_event() const + { return base_value_changed_event(); } + + +SC_TEMPLATE // Return true if a changed event happened in the last delta cycle. +inline bool sc_signal<sc_dt::sc_bigint<W> >::event() const + { return base_event(); } + + +SC_TEMPLATE // Return a reference to the value of this object instance. +inline const sc_dt::sc_bigint<W>& sc_signal<sc_dt::sc_bigint<W> >::get_data_ref() const + { return *this; } + + +SC_TEMPLATE // Return a pointer to this object instance. +inline sc_signal<sc_dt::sc_bigint<W> >& sc_signal<sc_dt::sc_bigint<W> >::get_signal() + { return *this; } + + +SC_TEMPLATE // Return a kind value of "sc_signal". +inline const char* sc_signal<sc_dt::sc_bigint<W> >::kind() const +{ + return "sc_signal"; +} + + +//------------------------------------------------------------------------------ +//"sc_signal<sc_dt::sc_bigint<W> >::operator () +// +// This operator returns a part selection of this object instance. +// left = left-hand bit of the selection. +// right = right-hand bit of the selection. +//------------------------------------------------------------------------------ +SC_TEMPLATE +inline sc_signed_sigref& sc_signal<sc_dt::sc_bigint<W> >::operator () (int left, int right) +{ + sc_signed_sigref* result_p; // Value to return. + + result_p = sc_signed_sigref::m_pool.allocate(); + result_p->initialize(this, left, right); + return *result_p; +} + + +//------------------------------------------------------------------------------ +//"sc_signal<sc_dt::sc_bigint<W> >::operator []" +// +// This operator returns a bit selection of this object instance. +// i = bit to be selected. +//------------------------------------------------------------------------------ +SC_TEMPLATE +inline sc_signed_sigref& sc_signal<sc_dt::sc_bigint<W> >::operator [] ( int bit ) +{ + return operator () (bit,bit); +} + + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_bigint<W> >::operator = ( const this_type& new_val ) + { base_write( new_val ); } + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_bigint<W> >::operator = ( const char* new_val ) + { sc_dt::sc_bigint<W> tmp = new_val; m_new_val = tmp; request_update(); } + + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_bigint<W> >::operator = ( sc_dt::uint64 new_val ) + { base_write(new_val); } + + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_bigint<W> >::operator = ( sc_dt::int64 new_val ) + { base_write(new_val); } + + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_bigint<W> >::operator = ( int new_val ) + { base_write((sc_dt::int64)new_val); } + + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_bigint<W> >::operator = ( long new_val ) + { base_write((sc_dt::int64)new_val); } + + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_bigint<W> >::operator = ( short new_val ) + { base_write((sc_dt::int64)new_val); } + + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_bigint<W> >::operator = ( unsigned int new_val ) + { base_write((sc_dt::int64)new_val); } + + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_bigint<W> >::operator = ( unsigned long new_val ) + { base_write((sc_dt::int64)new_val); } + + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_bigint<W> >::operator = ( unsigned short new_val ) + { base_write((sc_dt::int64)new_val); } + +SC_TEMPLATE +template<typename T> +inline void sc_signal<sc_dt::sc_bigint<W> >::operator = ( + const sc_dt::sc_generic_base<T>& new_val ) +{ + sc_dt::sc_unsigned temp(W); + new_val->to_sc_unsigned(temp); + base_write(temp); +} + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_bigint<W> >::operator = ( const sc_dt::sc_unsigned& new_val ) + { base_write(new_val); } + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_bigint<W> >::operator = ( const sc_dt::sc_bv_base& new_val ) + { base_write( (sc_dt::sc_bigint<W>)new_val ); } + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_bigint<W> >::operator = ( const sc_dt::sc_lv_base& new_val ) + { base_write( (sc_dt::sc_bigint<W>)new_val ); } + + + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_bigint<W> >::operator = ( const sc_dt::sc_signed& new_val ) + { base_write(new_val); } + + +SC_TEMPLATE // Return a pointer to the read target for part selections. +inline sc_dt::sc_signed* sc_signal<sc_dt::sc_bigint<W> >::part_read_target() + { return this; } + +SC_TEMPLATE // Return this object's base value as a const reference. +inline const sc_dt::sc_bigint<W>& sc_signal<sc_dt::sc_bigint<W> >::read() const + { return *this; } + + +SC_TEMPLATE // Read a portion of a value. +inline sc_dt::sc_signed sc_signal<sc_dt::sc_bigint<W> >::read_part( + int left, int right ) const +{ + return (sc_dt::sc_signed)sc_dt::sc_signed::operator () (left, right); +} + +SC_TEMPLATE // Register a port for write checking. +inline void sc_signal<sc_dt::sc_bigint<W> >::register_port( + sc_port_base& port_, const char* if_typename_ ) +{ +# ifdef DEBUG_SYSTEMC + std::string nm( if_typename_ ); + if( nm == typeid( sc_signal_inout_if<sc_dt::sc_bigint<W> > ).name() ) + { + if( m_output_p != 0 ) + { + sc_signal_invalid_writer( name(), kind(), + m_output_p->name(), port_.name() ); + } + m_output_p = &port_; + } +# else + if ( &port_ && if_typename_ ) {} // Silence unused args warning. +# endif +} + + +SC_TEMPLATE // Autogenerated name object instance constructor. +inline sc_signal<sc_dt::sc_bigint<W> >::sc_signal() : + sc_prim_channel(sc_gen_unique_name( "signal" )), + m_changed_event_p(0), + m_new_val(W), + m_output_p(0), + m_writer_p(0) +{ } + + +SC_TEMPLATE // Explicitly named object instance constructor. +inline sc_signal<sc_dt::sc_bigint<W> >::sc_signal(const char* name_) : + sc_prim_channel(name_), + m_changed_event_p(0), + m_new_val(W), + m_output_p(0), + m_writer_p(0) +{ } + + +SC_TEMPLATE // Object instance destructor. +inline sc_signal<sc_dt::sc_bigint<W> >::~sc_signal() +{ + if ( m_changed_event_p ) delete m_changed_event_p; +} + + +SC_TEMPLATE // Update the current value from new value. +inline void sc_signal<sc_dt::sc_bigint<W> >::update() +{ + if ( m_changed_event_p ) + { + if ( m_new_val != *this ) + { + m_changed_event_p->notify_delayed(); + m_event_delta = simcontext()->delta_count(); + } + } + sc_dt::sc_signed::operator = (m_new_val); +} + + +SC_TEMPLATE // Return the value changed event. +inline const sc_event& sc_signal<sc_dt::sc_bigint<W> >::value_changed_event() const + { return base_value_changed_event(); } + + +SC_TEMPLATE // Write a sc_in<sc_dt::sc_bigint<W> > value to this object instance. +inline void sc_signal<sc_dt::sc_bigint<W> >::write( const sc_in<sc_dt::sc_bigint<W> >& value ) + { base_write( value ); } + + +SC_TEMPLATE // Write a sc_inout<sc_dt::sc_bigint<W> > value to this object instance. +inline void sc_signal<sc_dt::sc_bigint<W> >::write( const sc_inout<sc_dt::sc_bigint<W> >& value ) + { base_write( value ); } + + +SC_TEMPLATE // Write a sc_dt::sc_bigint<W> value to this object instance. +inline void sc_signal<sc_dt::sc_bigint<W> >::write( const sc_dt::sc_bigint<W>& value ) + { base_write( value); } + + +SC_TEMPLATE // Select a portion of a value. +inline sc_signed_sigref& sc_signal<sc_dt::sc_bigint<W> >::select_part( + int left, int right) +{ + sc_signed_sigref* result_p = sc_signed_sigref::m_pool.allocate(); + result_p->initialize(dynamic_cast<sc_signed_part_if*>(this), left, right); + return *result_p; +} + + +SC_TEMPLATE // Write a portion of a value. If this is the first write in + // a delta cycle we copy the existing value before setting the bits. +inline void sc_signal<sc_dt::sc_bigint<W> >::write_part(sc_dt::int64 v, int left, int right) +{ + m_new_val(left, right) = v; + request_update(); +} + + +SC_TEMPLATE // Write a portion of a value. If this is the first write in + // a delta cycle we copy the existing value before setting the bits. +inline void sc_signal<sc_dt::sc_bigint<W> >::write_part(sc_dt::uint64 v, int left, int right) +{ + m_new_val(left, right) = v; + request_update(); +} + + +SC_TEMPLATE // Write a portion of a value. If this is the first write in + // a delta cycle we copy the existing value before setting the bits. +inline void sc_signal<sc_dt::sc_bigint<W> >::write_part( + const sc_dt::sc_signed& v, int left, int right ) +{ + m_new_val(left, right) = v; + request_update(); +} + + +SC_TEMPLATE // Write a portion of a value. If this is the first write in + // a delta cycle we copy the existing value before setting the bits. +inline void sc_signal<sc_dt::sc_bigint<W> >::write_part( + const sc_dt::sc_unsigned& v, int left, int right ) +{ + m_new_val(left, right) = v; + request_update(); +} + + +//============================================================================== +// CLASS sc_in<sc_dt::sc_bigint<W> > +// +// This class implements an input port whose target acts like an sc_dt::sc_bigint<W> data +// value. This class is a specialization of the generic sc_in class to +// implement tailored support for the sc_dt::sc_bigint<W> class. +//============================================================================== +SC_TEMPLATE +class sc_in<sc_dt::sc_bigint<W> > : + public sc_port<sc_signal_in_if<sc_dt::sc_bigint<W> >, 1, + SC_ONE_OR_MORE_BOUND>, + public sc_dt::sc_value_base +{ + public: + + // typedefs + + typedef sc_dt::sc_bigint<W> data_type; + typedef sc_signal_in_if<sc_dt::sc_bigint<W> > if_type; + typedef sc_port<if_type,1,SC_ONE_OR_MORE_BOUND> base_type; + typedef sc_in<sc_dt::sc_bigint<W> > this_type; + + typedef if_type in_if_type; + typedef base_type in_port_type; + typedef sc_signal_inout_if<sc_dt::sc_bigint<W> > inout_if_type; + typedef sc_inout<sc_dt::sc_bigint<W> > inout_port_type; + + public: + + // bind methods and operators: + + void bind( const in_if_type& interface_ ) + { sc_port_base::bind( const_cast<in_if_type&>( interface_) );} + void operator () ( const in_if_type& interface_ ) + { sc_port_base::bind( const_cast<in_if_type&>( interface_) );} + void bind( in_port_type& parent_ ) + { sc_port_base::bind(parent_);} + void operator () ( in_port_type& parent_ ) + { sc_port_base::bind(parent_);} + void bind( inout_port_type& parent_ ) + { sc_port_base::bind(parent_);} + void operator () ( inout_port_type& parent_ ) + { sc_port_base::bind(parent_);} + + protected: + // called by pbind (for internal use only) + virtual inline int vbind( sc_interface& interface_ ) + { + return sc_port_b<if_type>::vbind( interface_ ); + } + virtual inline int vbind( sc_port_base& parent_ ) + { + in_port_type* in_parent = dynamic_cast<in_port_type*>( &parent_ ); + if( in_parent != 0 ) { + sc_port_base::bind( *in_parent ); + return 0; + } + inout_port_type* inout_parent = dynamic_cast<inout_port_type*>( &parent_ ); + if( inout_parent != 0 ) { + sc_port_base::bind( *inout_parent ); + return 0; + } + // type mismatch + return 2; + } + + + // constructors + + public: + sc_in() + : base_type(), m_traces( 0 ) + {} + + explicit sc_in( const char* name_ ) + : base_type( name_ ), m_traces( 0 ) + {} + + explicit sc_in( const in_if_type& interface_ ) + : base_type( const_cast<in_if_type&>( interface_ ) ), m_traces( 0 ) + {} + + sc_in( const char* name_, const in_if_type& interface_ ) + : base_type( name_, const_cast<in_if_type&>( interface_ ) ), m_traces( 0 ) + {} + + explicit sc_in( in_port_type& parent_ ) + : base_type( parent_ ), m_traces( 0 ) + {} + + sc_in( const char* name_, in_port_type& parent_ ) + : base_type( name_, parent_ ), m_traces( 0 ) + {} + + explicit sc_in( inout_port_type& parent_ ) + : base_type(), m_traces( 0 ) + { sc_port_base::bind( parent_ ); } + + sc_in( const char* name_, inout_port_type& parent_ ) + : base_type( name_ ), m_traces( 0 ) + { sc_port_base::bind( parent_ ); } + + sc_in( this_type& parent_ ) + : base_type( parent_ ), m_traces( 0 ) + {} + + sc_in( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ), m_traces( 0 ) + {} + + + // destructor + + virtual inline ~sc_in() + { + remove_traces(); + } + + // bit and part selection + + sc_dt::sc_signed_bitref_r operator [] ( int i ) const + { return (*this)->read()[i]; } + sc_dt::sc_signed_bitref_r bit( int i ) const + { return (*this)->read()[i]; } + sc_dt::sc_signed_subref_r operator () ( int left, int right ) const + { return (*this)->read()(left,right); } + sc_dt::sc_signed_subref_r range( int left, int right ) const + { return (*this)->read()(left,right); } + + + // interface access shortcut methods + + // get the default event + + const sc_event& default_event() const + { return (*this)->value_changed_event(); } + + + // get the value changed event + + const sc_event& value_changed_event() const + { return (*this)->value_changed_event(); } + + + // read the current value + + const sc_dt::sc_bigint<W>& read() const + { return (*this)->read(); } + + operator const sc_dt::sc_bigint<W>& () const + { return (*this)->read(); } + + // was there a value changed event? + + bool event() const + { return (*this)->event(); } + + + // (other) event finder method(s) + + sc_event_finder& value_changed() const + { + return *new sc_event_finder_t<in_if_type>( + *this, &in_if_type::value_changed_event ); + } + + + + // reduction methods: + + inline bool and_reduce() const + { return (*this)->read().and_reduce(); } + inline bool nand_reduce() const + { return (*this)->read().nand_reduce(); } + inline bool nor_reduce() const + { return (*this)->read().nor_reduce(); } + inline bool or_reduce() const + { return (*this)->read().or_reduce(); } + inline bool xnor_reduce() const + { return (*this)->read().xnor_reduce(); } + inline bool xor_reduce() const + { return (*this)->read().xor_reduce(); } + + + // called when elaboration is done + /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ + /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ + + virtual inline void end_of_elaboration() + { + if( m_traces != 0 ) { + for( unsigned int i = 0; i < m_traces->size(); ++ i ) { + sc_trace_params* p = (*m_traces)[i]; + sc_trace( p->tf, read(), p->name ); + } + remove_traces(); + } + } + + virtual inline const char* kind() const + { return "sc_in"; } + + + // called by sc_trace + void add_trace( sc_trace_file* tf_, const std::string& name_ ) const + { + if( tf_ != 0 ) { + if( m_traces == 0 ) { + m_traces = new sc_trace_params_vec; + } + m_traces->push_back( new sc_trace_params( tf_, name_ ) ); + } + } + + + // concatenation methods + + virtual inline int concat_length(bool* xz_present_p) const + { return (*this)->read().concat_length( xz_present_p ); } + virtual inline sc_dt::uint64 concat_get_uint64() const + { return (*this)->read().concat_get_uint64(); } + virtual inline bool concat_get_ctrl( sc_dt::sc_digit* dst_p, int low_i ) const + { return (*this)->read().concat_get_ctrl(dst_p, low_i); } + virtual inline bool concat_get_data( sc_dt::sc_digit* dst_p, int low_i ) const + { return (*this)->read().concat_get_data(dst_p, low_i); } + + protected: + void remove_traces() const + { + if( m_traces != 0 ) { + for( int i = m_traces->size() - 1; i >= 0; -- i ) { + delete (*m_traces)[i]; + } + delete m_traces; + m_traces = 0; + } + } + + mutable sc_trace_params_vec* m_traces; + + + private: + + // disabled + sc_in( const sc_in<sc_dt::sc_bigint<W> >& ); + sc_in<sc_dt::sc_bigint<W> >& operator = ( const sc_in<sc_dt::sc_bigint<W> >& ); + +#ifdef __GNUC__ + // Needed to circumvent a problem in the g++-2.95.2 compiler: + // This unused variable forces the compiler to instantiate + // an object of T template so an implicit conversion from + // read() to a C++ intrinsic data type will work. + static data_type dummy; +#endif + +}; + + + +SC_TEMPLATE +inline std::ostream& operator << ( + std::ostream& os, const sc_in<sc_dt::sc_bigint<W> >& a ) +{ + a.read().print( os ); + return os; +} + + +//============================================================================== +// CLASS sc_inout<sc_dt::sc_bigint<W> > +// +// This class implements an input/output port whose target acts like an +// sc_dt::sc_bigint<W> data value. It is derived from the sc_signed_in. This class is a +// specialization of the generic sc_inout class to implement tailored support +// for the sc_dt::sc_bigint<W> class. +//============================================================================== +SC_TEMPLATE +class sc_inout<sc_dt::sc_bigint<W> > : + public sc_port<sc_signal_inout_if<sc_dt::sc_bigint<W> >, 1, + SC_ONE_OR_MORE_BOUND>, + public sc_dt::sc_value_base +{ + public: + + // typedefs + + typedef sc_dt::sc_bigint<W> data_type; + typedef sc_signal_inout_if<sc_dt::sc_bigint<W> > if_type; + typedef sc_port<if_type,1,SC_ONE_OR_MORE_BOUND> base_type; + typedef sc_inout<sc_dt::sc_bigint<W> > this_type; + + typedef if_type inout_if_type; + typedef base_type inout_port_type; + + public: + + // bind methods and operators: + + void bind( const inout_if_type& interface_ ) + { sc_port_base::bind( const_cast<inout_if_type&>( interface_) ); } + void operator () ( const inout_if_type& interface_ ) + { sc_port_base::bind( const_cast<inout_if_type&>( interface_) ); } + void bind( inout_port_type& parent_ ) + { sc_port_base::bind(parent_); } + void operator () ( inout_port_type& parent_ ) + { sc_port_base::bind(parent_); } + + protected: + // called by pbind (for internal use only) + virtual inline int vbind( sc_interface& interface_ ) + { + return sc_port_b<if_type>::vbind( interface_ ); + } + virtual inline int vbind( sc_port_base& parent_ ) + { + inout_port_type* inout_parent = dynamic_cast<inout_port_type*>( &parent_ ); + if( inout_parent != 0 ) { + sc_port_base::bind( *inout_parent ); + return 0; + } + // type mismatch + return 2; + } + + + // constructors + + public: + sc_inout() + : base_type(), m_init_val_p(0), m_traces( 0 ) + {} + + explicit sc_inout( const char* name_ ) + : base_type( name_ ), m_init_val_p(0), m_traces( 0 ) + {} + + explicit sc_inout( inout_if_type& interface_ ) + : base_type( interface_ ), m_init_val_p(0), m_traces( 0 ) + {} + + sc_inout( const char* name_, inout_if_type& interface_ ) + : base_type( name_, interface_ ), m_init_val_p(0), m_traces( 0 ) + {} + + explicit sc_inout( inout_port_type& parent_ ) + : base_type( parent_ ), m_init_val_p(0), m_traces( 0 ) + {} + + sc_inout( const char* name_, inout_port_type& parent_ ) + : base_type( name_, parent_ ), m_init_val_p(0), m_traces( 0 ) + {} + + sc_inout( this_type& parent_ ) + : base_type( parent_ ), m_init_val_p(0), m_traces( 0 ) + {} + + sc_inout( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ), m_init_val_p(0), m_traces( 0 ) + {} + + + // destructor + + virtual inline ~sc_inout() + { + remove_traces(); + } + + // bit and part selection + + sc_dt::sc_signed_bitref_r operator [] ( int i ) const + { return (*this)->read()[i]; } + sc_dt::sc_signed_bitref_r bit( int i ) const + { return (*this)->read()[i]; } + sc_signed_sigref& operator [] ( int i ) + { return (*this)->select_part(i,i); } + sc_signed_sigref& bit( int i ) + { return (*this)->select_part(i,i); } + sc_dt::sc_signed_subref_r operator () ( int left, int right ) const + { return (*this)->read()(left,right); } + sc_dt::sc_signed_subref_r range( int left, int right ) const + { return (*this)->read()(left,right); } + sc_signed_sigref& operator () ( int left, int right ) + { return (*this)->select_part(left,right); } + sc_signed_sigref& range( int left, int right ) + { return (*this)->select_part(left,right); } + + + // interface access shortcut methods + + // get the default event + + const sc_event& default_event() const + { return (*this)->value_changed_event(); } + + + // get the value changed event + + const sc_event& value_changed_event() const + { return (*this)->value_changed_event(); } + + + // read the current value + + const sc_dt::sc_bigint<W>& read() const + { return (*this)->read(); } + + operator const sc_dt::sc_bigint<W>& () const + { return (*this)->read(); } + + // was there a value changed event? + + bool event() const + { return (*this)->event(); } + + + // (other) event finder method(s) + + sc_event_finder& value_changed() const + { + return *new sc_event_finder_t<inout_if_type>( + *this, &inout_if_type::value_changed_event ); + } + + + + // reduction methods: + + inline bool and_reduce() const + { return (*this)->read().and_reduce(); } + inline bool nand_reduce() const + { return (*this)->read().nand_reduce(); } + inline bool nor_reduce() const + { return (*this)->read().nor_reduce(); } + inline bool or_reduce() const + { return (*this)->read().or_reduce(); } + inline bool xnor_reduce() const + { return (*this)->read().xnor_reduce(); } + inline bool xor_reduce() const + { return (*this)->read().xor_reduce(); } + + + // called when elaboration is done + /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ + /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ + + virtual inline void end_of_elaboration() + { + if( m_init_val_p != 0 ) { + (*this)->write( *m_init_val_p ); + delete m_init_val_p; + m_init_val_p = 0; + } + if( m_traces != 0 ) { + for( unsigned int i = 0; i < m_traces->size(); ++ i ) { + sc_trace_params* p = (*m_traces)[i]; + sc_trace( p->tf, read(), p->name ); + } + remove_traces(); + } + } + + virtual inline const char* kind() const + { return "sc_inout"; } + + // value initialization + + inline void initialize( const sc_dt::sc_bigint<W>& value_ ) + { + inout_if_type* iface = dynamic_cast<inout_if_type*>( this->get_interface() ); + if( iface != 0 ) { + iface->write( value_ ); + } else { + if( m_init_val_p == 0 ) { + m_init_val_p = new sc_dt::sc_bigint<W>; + } + *m_init_val_p = value_; + } + } + + + // called by sc_trace + void add_trace( sc_trace_file* tf_, const std::string& name_ ) const + { + if( tf_ != 0 ) { + if( m_traces == 0 ) { + m_traces = new sc_trace_params_vec; + } + m_traces->push_back( new sc_trace_params( tf_, name_ ) ); + } + } + + + // concatenation methods + + virtual inline int concat_length(bool* xz_present_p) const + { return (*this)->read().concat_length( xz_present_p ); } + virtual inline sc_dt::uint64 concat_get_uint64() const + { return (*this)->read().concat_get_uint64(); } + virtual inline bool concat_get_ctrl( sc_dt::sc_digit* dst_p, int low_i ) const + { return (*this)->read().concat_get_ctrl(dst_p, low_i); } + virtual inline bool concat_get_data( sc_dt::sc_digit* dst_p, int low_i ) const + { return (*this)->read().concat_get_data(dst_p, low_i); } + virtual inline void concat_set(sc_dt::int64 src, int low_i) + { *this = (src >> ((low_i < 64) ? low_i : 63)); } +#if 0 // #### + virtual inline void concat_set(const sc_dt::sc_lv_base& src, int low_i) + { *this = src >> low_i; } +#endif // 0 #### + virtual inline void concat_set(const sc_dt::sc_signed& src, int low_i) + { *this = (src >> low_i); } + virtual inline void concat_set(const sc_dt::sc_unsigned& src, int low_i) + { *this = (src >> low_i); } + virtual inline void concat_set(sc_dt::uint64 src, int low_i) + { *this = ((low_i < 64) ? (src >> low_i) : (sc_dt::uint64)0); } + + + public: // assignment operators: + inline void operator = ( const this_type& new_val ) + { (*this)->write( new_val.read() ); } + inline void operator = ( const char* new_val ) + { sc_dt::sc_signed aa(W); aa = new_val; (*this)->write( aa ); } + inline void operator = ( sc_dt::uint64 new_val ) + { (*this)->write(new_val); } + inline void operator = ( sc_dt::int64 new_val ) + { (*this)->write(new_val); } + inline void operator = ( int new_val ) + { (*this)->write((sc_dt::int64)new_val); } + inline void operator = ( long new_val ) + { (*this)->write((sc_dt::int64)new_val); } + inline void operator = ( short new_val ) + { (*this)->write((sc_dt::int64)new_val); } + inline void operator = ( unsigned int new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( unsigned long new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( unsigned short new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + template<typename T> + inline void operator = ( const sc_dt::sc_generic_base<T>& new_val ) + { + sc_dt::sc_unsigned temp(W); + new_val->to_sc_unsigned(temp); + (*this)->write(temp); + } + inline void operator = ( const sc_dt::sc_signed& new_val ) + { (*this)->write(new_val); } + inline void operator = ( const sc_dt::sc_unsigned& new_val ) + { (*this)->write(new_val); } + inline void operator = ( const sc_dt::sc_bv_base& new_val ) + { (*this)->write((sc_dt::sc_bigint<W>)new_val); } + inline void operator = ( const sc_dt::sc_lv_base& new_val ) + { (*this)->write((sc_dt::sc_bigint<W>)new_val); } + + inline void write( const sc_in<sc_dt::sc_bigint<W> >& new_val ) + { (*this)->write( new_val.read() ); } + inline void write( const sc_inout<sc_dt::sc_bigint<W> >& new_val ) + { (*this)->write( new_val.read() ); } + inline void write( const sc_dt::sc_bigint<W>& new_val ) + { (*this)->write( new_val); } + + protected: + void remove_traces() const + { + if( m_traces != 0 ) { + for( int i = m_traces->size() - 1; i >= 0; -- i ) { + delete (*m_traces)[i]; + } + delete m_traces; + m_traces = 0; + } + } + + sc_dt::sc_bigint<W>* m_init_val_p; + mutable sc_trace_params_vec* m_traces; + + + private: + + // disabled + sc_inout( const sc_inout<sc_dt::sc_bigint<W> >& ); + +#ifdef __GNUC__ + // Needed to circumvent a problem in the g++-2.95.2 compiler: + // This unused variable forces the compiler to instantiate + // an object of T template so an implicit conversion from + // read() to a C++ intrinsic data type will work. + static data_type dummy; +#endif + +}; + + + +SC_TEMPLATE +inline std::ostream& operator << ( + std::ostream& os, const sc_inout<sc_dt::sc_bigint<W> >& a ) +{ + a.read().print( os ); + return os; +} + + +//============================================================================== +// CLASS sc_out<sc_dt::sc_bigint<W> > +// +// This class implements an output port whose target acts like an +// sc_dt::sc_bigint<W> data value. This class is a derivation of sc_inout, since +// output ports are really no different from input/output ports. +//============================================================================== +SC_TEMPLATE +class sc_out<sc_dt::sc_bigint<W> > : public sc_inout<sc_dt::sc_bigint<W> > +{ + public: + + // typedefs + + typedef sc_dt::sc_bigint<W> data_type; + + typedef sc_out<data_type> this_type; + typedef sc_inout<data_type> base_type; + + typedef typename base_type::inout_if_type inout_if_type; + typedef typename base_type::inout_port_type inout_port_type; + + // constructors + + sc_out() + : base_type() + {} + + explicit sc_out( const char* name_ ) + : base_type( name_ ) + {} + + explicit sc_out( inout_if_type& interface_ ) + : base_type( interface_ ) + {} + + sc_out( const char* name_, inout_if_type& interface_ ) + : base_type( name_, interface_ ) + {} + + explicit sc_out( inout_port_type& parent_ ) + : base_type( parent_ ) + {} + + sc_out( const char* name_, inout_port_type& parent_ ) + : base_type( name_, parent_ ) + {} + + sc_out( this_type& parent_ ) + : base_type( parent_ ) + {} + + sc_out( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ) + {} + + + // destructor (does nothing) + + virtual inline ~sc_out() + {} + + + // assignment operators: + + public: + inline void operator = ( const this_type& new_val ) + { (*this)->write( (const sc_dt::sc_signed&)new_val ); } + inline void operator = ( const char* new_val ) + { sc_dt::sc_signed aa(W); aa = new_val; (*this)->write( aa ); } + inline void operator = ( sc_dt::uint64 new_val ) + { (*this)->write(new_val); } + inline void operator = ( sc_dt::int64 new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( int new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( long new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( short new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( unsigned int new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( unsigned long new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( unsigned short new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + template<typename T> + inline void operator = ( const sc_dt::sc_generic_base<T>& new_val ) + { + sc_dt::sc_unsigned temp(W); + new_val->to_sc_unsigned(temp); + (*this)->write(temp); + } + inline void operator = ( const sc_dt::sc_signed& new_val ) + { (*this)->write(new_val); } + inline void operator = ( const sc_dt::sc_unsigned& new_val ) + { (*this)->write(new_val); } + inline void operator = ( const sc_dt::sc_bv_base& new_val ) + { (*this)->write((sc_dt::sc_bigint<W>)new_val); } + inline void operator = ( const sc_dt::sc_lv_base& new_val ) + { (*this)->write((sc_dt::sc_bigint<W>)new_val); } + + private: + + // disabled + sc_out( const this_type& ); +}; + + + +//------------------------------------------------------------------------------ +//"sc_signed_sigref::initialize" +// +// This method initializes an object instance from the supplied arguments. +// if_p -> target of this selection. +// left_ = left-most bit in selection. +// right_ = right-most bit in selection. +//------------------------------------------------------------------------------ +inline void sc_signed_sigref::initialize( + sc_signed_part_if* if_p, int left_, int right_ ) +{ + m_if_p = if_p; + m_left = left_; + m_right = right_; + m_obj_p = if_p->part_read_target(); +} + + +//------------------------------------------------------------------------------ +//"sc_signed_sigref::operator =" +// +// These operators assign a value to the bits associated with this object +// instance within this object instance's target signal. +//------------------------------------------------------------------------------ +inline void sc_signed_sigref::operator = ( sc_dt::uint64 v ) +{ + m_if_p->write_part( v, m_left, m_right ); +} + +inline void sc_signed_sigref::operator = ( const char* v ) +{ + sc_dt::sc_signed tmp(length()); tmp = v; *this = tmp; +} + +inline void sc_signed_sigref:: operator = ( sc_dt::int64 v ) +{ + *this = (sc_dt::uint64)v; +} + +inline void sc_signed_sigref:: operator = ( int v ) +{ + *this = (sc_dt::uint64)v; +} + +inline void sc_signed_sigref:: operator = ( long v ) +{ + *this = (sc_dt::uint64)v; +} + +inline void sc_signed_sigref:: operator = ( unsigned int v ) +{ + *this = (sc_dt::uint64)v; +} + +inline void sc_signed_sigref:: operator = ( unsigned long v ) +{ + *this = (sc_dt::uint64)v; +} + +template<typename T> +inline void sc_signed_sigref:: operator = ( const sc_dt::sc_generic_base<T>& v ) +{ + sc_dt::sc_unsigned temp(m_left-m_right+1); + v->to_sc_unsigned(temp); + m_if_p->write_part( temp, m_left, m_right ); +} + +inline void sc_signed_sigref:: operator = ( const sc_dt::sc_signed& v ) +{ + m_if_p->write_part( v, m_left, m_right ); +} + +inline void sc_signed_sigref:: operator = ( const sc_dt::sc_unsigned& v ) +{ + m_if_p->write_part( v, m_left, m_right ); +} + +void sc_signed_sigref::operator = ( const sc_signed_sigref& v ) +{ + *this = (sc_dt::sc_unsigned)v; +} + + +#undef SC_TEMPLATE +} // namespace sc_core +#endif // !defined(SC_SIGNAL_SIGNED_H) + +namespace sc_core { + +extern +void +sc_signal_invalid_writer( const char* name, + const char* kind, + const char* first_writer, + const char* second_writer ); + +//------------------------------------------------------------------------------ +// POOL OF TEMPORARY INSTANCES OF sc_signed_sigref +// +// This allows use to pass const references for part and bit selections +// on sc_signal_signed object instances. +//------------------------------------------------------------------------------ +sc_vpool<sc_signed_sigref> sc_signed_sigref::m_pool(8); + + +//------------------------------------------------------------------------------ +//"sc_signed_part_if::default methods" +// +// These versions just produce errors if they are not overloaded but used. +//------------------------------------------------------------------------------ + +sc_signed* sc_signed_part_if::part_read_target() +{ + SC_REPORT_ERROR( "attempted specalized signal operation on " + "non-specialized signal", "int" ); + return 0; +} +sc_signed sc_signed_part_if::read_part( int /*left*/, int /*right*/ ) const +{ + SC_REPORT_ERROR( "attempted specalized signal operation on " + "non-specialized signal", "int" ); + return sc_signed(1); +} +sc_signed_sigref& sc_signed_part_if::select_part( int /*left*/, int /*right*/ ) +{ + SC_REPORT_ERROR( "attempted specalized signal operation on " + "non-specialized signal", "int" ); + return *(sc_signed_sigref*)0; +} +void sc_signed_part_if::write_part( int64 v, int /*left*/, int /*right*/ ) +{ + SC_REPORT_ERROR( "attempted specalized signal operation on " + "non-specialized signal", "int" ); +} +void sc_signed_part_if::write_part( uint64 v, int /*left*/, int /*right*/ ) +{ + SC_REPORT_ERROR( "attempted specalized signal operation on " + "non-specialized signal", "int" ); +} +void sc_signed_part_if::write_part( + const sc_signed& v, int /*left*/, int /*right*/ ) +{ + SC_REPORT_ERROR( "attempted specalized signal operation on " + "non-specialized signal", "int" ); +} +void sc_signed_part_if::write_part( + const sc_unsigned& v, int /*left*/, int /*right*/ ) +{ + SC_REPORT_ERROR( "attempted specalized signal operation on " + "non-specialized signal", "int" ); +} + + +//------------------------------------------------------------------------------ +//"sc_signed_sigref::concate_set" +// +// These methods assign this object instance's value from the supplied +// value starting at the supplied bit within that value. +// src = value to use to set this object instance's value. +// low_i = bit in src that is to be the low order bit of the value to set. +// #### OPTIMIZE +//------------------------------------------------------------------------------ +void sc_signed_sigref::concat_set(sc_dt::int64 src, int low_i) +{ + int64 tmp; + if ( low_i < 63 ) + tmp = src >> low_i; + else + tmp = (src < 0) ? -1 : 0; + m_if_p->write_part( tmp, m_left, m_right ); +} + + +void sc_signed_sigref::concat_set(const sc_signed& src, int low_i) +{ + m_if_p->write_part( src >> low_i, m_left, m_right ); +} + + +void sc_signed_sigref::concat_set(const sc_lv_base& src, int low_i) +{ + sc_unsigned tmp(src.length()); + tmp = src; + m_if_p->write_part( tmp >> low_i, m_left, m_right ); +} + + +void sc_signed_sigref::concat_set(const sc_unsigned& src, int low_i) +{ + m_if_p->write_part( src >> low_i, m_left, m_right ); +} + + +void sc_signed_sigref::concat_set(sc_dt::uint64 src, int low_i) +{ + uint64 tmp = (low_i < 63) ? (src >> low_i) : 0; + m_if_p->write_part( tmp, m_left, m_right ); +} + +} // namespace sc_core diff --git a/src/systemc/tests/include/specialized_signals/scx_signal_uint.h b/src/systemc/tests/include/specialized_signals/scx_signal_uint.h new file mode 100644 index 000000000..acc4a4219 --- /dev/null +++ b/src/systemc/tests/include/specialized_signals/scx_signal_uint.h @@ -0,0 +1,1676 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_signal_uint.cpp -- The sc_signal<sc_dt::sc_uint<W> > implementations. + + Original Author: Andy Goodrich, Forte Design Systems, 2002-10-22 + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +/* +$Log: scx_signal_uint.h,v $ +Revision 1.1 2011/08/15 17:31:11 acg + Andy Goodrich: moved specialized signals from examples to this tree. + +Revision 1.2 2011/08/15 16:43:24 acg + Torsten Maehne: changes to remove unused argument warnings. + +Revision 1.1.1.1 2006/12/15 20:20:03 acg +SystemC 2.3 + +Revision 1.2 2005/12/26 20:11:14 acg +Fixed up copyright. + +Revision 1.1.1.1 2005/12/19 23:16:42 acg +First check in of SystemC 2.1 into its own archive. + +Revision 1.16 2005/09/15 23:01:52 acg +Added std:: prefix to appropriate methods and types to get around +issues with the Edison Front End. + +Revision 1.15 2005/05/03 19:52:26 acg +Get proper header locations on includes. + +Revision 1.14 2005/05/03 19:50:20 acg +Name space version. + +Revision 1.11 2005/04/11 19:05:36 acg +Change to sc_clock for Microsoft VCC 6.0. Changes for namespaces + +Revision 1.10 2005/04/03 22:52:52 acg +Namespace changes. + +Revision 1.9 2005/03/21 22:31:32 acg +Changes to sc_core namespace. + +Revision 1.8 2004/09/27 21:01:59 acg +Andy Goodrich - Forte Design Systems, Inc. + - This is specialized signal support that allows better use of signals + and ports whose target value is a SystemC native type. + +*/ + + + +#include <systemc> +#include <typeinfo> + +/***************************************************************************** + + sc_signal_uint.h -- The sc_signal<sc_uint<W> > definitions. + + Original Author: Andy Goodrich, Forte Design Systems, 2002-10-22 + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +/* +$Log: scx_signal_uint.h,v $ +Revision 1.1 2011/08/15 17:31:11 acg + Andy Goodrich: moved specialized signals from examples to this tree. + +Revision 1.3 2011/08/15 16:43:24 acg + Torsten Maehne: changes to remove unused argument warnings. + +Revision 1.2 2011/06/28 21:23:02 acg + Andy Goodrich: merging of SCV tree. + +Revision 1.1.1.1 2006/12/15 20:20:03 acg +SystemC 2.3 + +Revision 1.4 2006/04/05 23:47:02 acg + Andy Goodrich: changed sc_get_current_process_base calls into + sc_get_current_process_b calls. + +Revision 1.3 2006/03/21 01:31:48 acg + Andy Goodrich: changed over to sc_get_current_process_b() from + sc_get_current_process_base() since the function's name changed. + +Revision 1.2 2005/12/26 20:11:14 acg +Fixed up copyright. + +Revision 1.1.1.1 2005/12/19 23:16:42 acg +First check in of SystemC 2.1 into its own archive. + +Revision 1.27 2005/09/15 23:01:52 acg +Added std:: prefix to appropriate methods and types to get around +issues with the Edison Front End. + +Revision 1.26 2005/07/30 03:44:11 acg +Changes from 2.1. + +Revision 1.25 2005/06/10 22:40:55 acg +Changes from 2.1 for operator << and other iostream stuff. + +Revision 1.24 2005/05/09 17:17:12 acg +Changes from 2.1. + +Revision 1.23 2005/05/08 19:04:06 acg +Fix bug in concat_set(int64,off). Other changes from 2.1 examples usage. + +Revision 1.22 2005/05/03 19:50:20 acg +Name space version. + +Revision 1.20 2005/03/21 22:31:32 acg +Changes to sc_core namespace. + +Revision 1.18 2004/11/09 00:11:27 acg +Added support for sc_generic_base<T> in place of sc_concatref. sc_concatref +now is derived from sc_generic_base<sc_concatref>. + +Revision 1.17 2004/09/27 21:01:59 acg +Andy Goodrich - Forte Design Systems, Inc. + - This is specialized signal support that allows better use of signals + and ports whose target value is a SystemC native type. + +*/ + + +#if !defined(SC_SIGNAL_UINT_H) +#define SC_SIGNAL_UINT_H + +#if ( !defined(_MSC_VER) || _MSC_VER > 1200 ) +# define SC_TEMPLATE template<int W> +#else +# define SC_TEMPLATE template<> template<int W> +#endif + +// FORWARD REFERENCES AND USINGS: + +namespace sc_core { + +class sc_uint_sigref; + +//============================================================================== +// CLASS sc_uint_part_if +// +// This class provides generic access to part selections for signals whose +// data type is sc_dt::sc_uint<W>. This class serves as the base class for the +// sc_dt::sc_uint<W> specialization of the sc_signal_in_if<T> class. The methods +// in this class may be over-ridden individually, those that are not overridden +// will produce an error message when called. The methods are used by the +// sc_uint_sigref class. +// +// Notes: +// (1) Descriptions of the methods and operators in this class appear with +// their implementations in sc_signal<sc_dt::sc_uint<W> >. +//============================================================================== +class sc_uint_part_if : virtual public sc_interface { + protected: + // constructor: + sc_uint_part_if() {} + + public: + // perform a part read. + virtual sc_dt::sc_uint_base* part_read_target(); + virtual sc_dt::uint64 read_part( int left, int right ) const; + + // perform a part write. + virtual sc_uint_sigref& select_part( int left, int right ); + virtual void write_part( sc_dt::uint64 v, int left, int right ); + + private: + sc_uint_part_if( const sc_uint_part_if& ); + sc_uint_part_if& operator = ( const sc_uint_part_if& ); +}; + + +//============================================================================== +// CLASS sc_signal_in_if<sc_dt::sc_uint<W> > +// +// This is the class specializations for the sc_signal_in_if<T> class to +// provide additional features for sc_signal instances whose template is +// sc_dt::sc_uint<W>, including part access. +// +// Notes: +// (1) Descriptions of the methods and operators in this class appear with +// their implementations in sc_signal<sc_dt::sc_uint<W> >. +//============================================================================== +template< int W > +class sc_signal_in_if<sc_dt::sc_uint<W> > : public sc_uint_part_if { + friend class sc_uint_sigref; + public: + typedef sc_signal_in_if<sc_dt::sc_uint<W> > this_type; + + // get the value changed event + virtual const sc_event& value_changed_event() const = 0; + + + // read the current value + virtual const sc_dt::sc_uint<W>& read() const = 0; + + // get a reference to the current value (for tracing) + virtual const sc_dt::sc_uint<W>& get_data_ref() const = 0; + + + // was there a value changed event? + virtual bool event() const = 0; + + protected: + // constructor + sc_signal_in_if() + {} + + private: // disabled + sc_signal_in_if( const this_type& ); + this_type& operator = ( const this_type& ); +}; + +//============================================================================= +// CLASS : sc_uint_sigref +// +// Proxy class for sc_signal_uint bit and part selection. +//============================================================================= +class sc_uint_sigref : public sc_dt::sc_uint_subref_r +{ + public: + sc_uint_sigref() : sc_dt::sc_uint_subref_r() {} + virtual ~sc_uint_sigref() {} + virtual void concat_set(sc_dt::int64 src, int low_i); + virtual void concat_set(const sc_dt::sc_signed& src, int low_i); + virtual void concat_set(const sc_dt::sc_unsigned& src, int low_i); + virtual void concat_set(const sc_dt::sc_lv_base& src, int low_i); + virtual void concat_set(sc_dt::uint64 src, int low_i); + + public: + inline void initialize( sc_uint_part_if* if_p, int left_, int right_ ); + + public: + inline void operator = ( sc_dt::uint64 v ); + inline void operator = ( const char* v ); + inline void operator = ( unsigned long v ); + inline void operator = ( long v ); + inline void operator = ( unsigned int v ); + inline void operator = ( int v ); + inline void operator = ( sc_dt::int64 v ); + inline void operator = ( double v ); + inline void operator = ( const sc_uint_sigref& v ); + template<typename T> + inline void operator = ( const sc_dt::sc_generic_base<T>& v ); + inline void operator = ( const sc_dt::sc_signed& v ); + inline void operator = ( const sc_dt::sc_unsigned& v ); + inline void operator = ( const sc_dt::sc_bv_base& v ); + inline void operator = ( const sc_dt::sc_lv_base& v ); + + public: + static sc_vpool<sc_uint_sigref> m_pool; // Pool of objects to use. + + protected: + sc_uint_part_if* m_if_p; // Target for selection. + + private: + + // disabled + sc_uint_sigref( const sc_uint_sigref& a ); +}; + + +//============================================================================== +// CLASS sc_signal<sc_dt::sc_uint<W> > +// +// This class implements a signal whose value acts like an sc_dt::sc_uint<W> data +// value. This class is a specialization of the generic sc_signal class to +// implement tailored support for the sc_dt::sc_uint<W> class. +// +// Notes: +// (1) Descriptions of the methods and operators in this class appear with +// their implementations. +//============================================================================== +SC_TEMPLATE +class sc_signal<sc_dt::sc_uint<W> > : + public sc_signal_inout_if<sc_dt::sc_uint<W> >, + public sc_prim_channel, + public sc_dt::sc_uint<W> +{ + public: // typedefs + typedef sc_signal<sc_dt::sc_uint<W> > this_type; + + public: // constructors and destructor: + inline sc_signal(); + explicit inline sc_signal(const char* name_); + virtual inline ~sc_signal(); + + public: // base methods: + inline bool base_event() const; + inline const sc_dt::sc_uint<W>& base_read() const; + inline const sc_event& base_value_changed_event() const; + inline void base_write( sc_dt::uint64 value ); + + public: // sc_prim_channel virtual methods: + virtual inline const char* kind() const; + virtual inline void update(); + + public: // sc_interface virtual methods: + virtual inline const sc_event& default_event() const; + virtual inline void register_port( + sc_port_base& port_, const char* if_typename_ ); + + public: // sc_uint_channel virtual methods: + virtual sc_dt::sc_uint_base* part_read_target(); + virtual inline sc_dt::uint64 read_part(int left, int right) const; + virtual inline sc_uint_sigref& select_part(int left, int right); + virtual inline void write_part(sc_dt::uint64 v, int left, int right); + + public: // interface virtual methods: + virtual inline bool event() const; + virtual inline const sc_dt::sc_uint<W>& get_data_ref() const; + // virtual inline sc_signal<sc_dt::sc_uint<W> >& get_signal() ; + virtual inline const sc_dt::sc_uint<W>& read() const; + virtual inline const sc_event& value_changed_event() const; + virtual inline void write( const sc_in<sc_dt::sc_uint<W> >& value ); + virtual inline void write( const sc_inout<sc_dt::sc_uint<W> >& value ); + virtual inline void write( const sc_dt::sc_uint<W>& value ); + + public: // part selections: + inline sc_uint_sigref& operator () ( int left, int right ); + inline sc_uint_sigref& operator [] ( int bit ); + + public: // operators: + inline void operator = ( const this_type& new_val ); + inline void operator = ( const char* new_val ); + inline void operator = ( sc_dt::uint64 new_val ); + inline void operator = ( sc_dt::int64 new_val ); + inline void operator = ( int new_val ); + inline void operator = ( long new_val ) ; + inline void operator = ( short new_val ) ; + inline void operator = ( unsigned int new_val ) ; + inline void operator = ( unsigned long new_val ); + inline void operator = ( unsigned short new_val ); + template<typename T> + inline void operator = ( const sc_dt::sc_generic_base<T>& new_val ); + inline void operator = ( const sc_dt::sc_signed& new_val ); + inline void operator = ( const sc_dt::sc_unsigned& new_val ); + inline void operator = ( const sc_dt::sc_bv_base& new_val ); + inline void operator = ( const sc_dt::sc_lv_base& new_val ); + + public: // concatenation methods (we inherit length and gets from sc_dt::sc_uint<W>): + virtual inline void concat_set(sc_dt::int64 src, int low_i); + virtual inline void concat_set(const sc_dt::sc_lv_base& src, int low_i); + virtual inline void concat_set(const sc_dt::sc_signed& src, int low_i); + virtual inline void concat_set(const sc_dt::sc_unsigned& src, int low_i); + virtual inline void concat_set(sc_dt::uint64 src, int low_i); + + protected: // debugging methods: + // #### void check_port(); + void check_writer(); + + private: // Disabled operations that sc_dt::sc_uint<W> supports: + sc_signal<sc_dt::sc_uint<W> >& operator ++ (); // prefix + const sc_signal<sc_dt::sc_uint<W> >& operator ++ (int); // postfix + sc_signal<sc_dt::sc_uint<W> >& operator -- (); // prefix + const sc_signal<sc_dt::sc_uint<W> >& operator -- (int); // postfix + sc_signal<sc_dt::sc_uint<W> >& operator += (sc_dt::uint_type); + sc_signal<sc_dt::sc_uint<W> >& operator -= (sc_dt::uint_type); + sc_signal<sc_dt::sc_uint<W> >& operator *= (sc_dt::uint_type); + sc_signal<sc_dt::sc_uint<W> >& operator /= (sc_dt::uint_type); + sc_signal<sc_dt::sc_uint<W> >& operator %= (sc_dt::uint_type); + sc_signal<sc_dt::sc_uint<W> >& operator &= (sc_dt::uint_type); + sc_signal<sc_dt::sc_uint<W> >& operator |= (sc_dt::uint_type); + sc_signal<sc_dt::sc_uint<W> >& operator ^= (sc_dt::uint_type); + + protected: + mutable sc_event* m_changed_event_p; // Value changed event this object. + sc_dt::uint64 m_event_delta; // Delta cycle of last event. + sc_dt::uint64 m_new_val; // New value for this object instance. + sc_port_base* m_output_p; // Single write port verify field. + sc_process_b* m_writer_p; // Single writer verify field. +}; + + +SC_TEMPLATE // Return true if a changed event happened in the last delta cycle. +inline bool sc_signal<sc_dt::sc_uint<W> >::base_event() const +{ + return simcontext()->delta_count() == m_event_delta + 1; +} + + +SC_TEMPLATE // Return this object's sc_dt::sc_uint<W> object instance. +inline const sc_dt::sc_uint<W>& sc_signal<sc_dt::sc_uint<W> >::base_read() const +{ + return *this; +} + + +SC_TEMPLATE // Return the value changed event, allocating it if necessary. +inline const sc_event& sc_signal<sc_dt::sc_uint<W> >::base_value_changed_event() const +{ + if ( !m_changed_event_p ) m_changed_event_p = new sc_event; + return *m_changed_event_p; +} + + +SC_TEMPLATE // Write an sc_dt::uint64 value to this object instance. +inline void sc_signal<sc_dt::sc_uint<W> >::base_write( sc_dt::uint64 value ) +{ +# if defined(DEBUG_SYSTEMC) + check_writer(); +# endif + m_new_val = value; + request_update(); +} + +//------------------------------------------------------------------------------ +//"sc_signal<sc_dt::sc_uint<W> >::check_writer" +// +// This method checks to see if there is more than one writer for this +// object instance by keeping track of the process performing the write. +//------------------------------------------------------------------------------ +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_uint<W> >::check_writer() +{ + sc_process_b* writer_p = sc_get_current_process_b(); + if( m_writer_p == 0 ) + { + m_writer_p = writer_p; + } + else if( m_writer_p != writer_p ) + { + sc_signal_invalid_writer( name(), kind(), + m_writer_p->name(), writer_p->name() ); + } +} + + +//------------------------------------------------------------------------------ +//"sc_signal<sc_dt::sc_uint<W> >::concat_set" +// +// These virtual methods allow value assignments to this object instance +// from various sources. The position within the supplied source of the +// low order bit for this object instance's value is low_i. +// src = source value. +// low_i = bit within src to serve as low order bit of this object +// instance's value. +//------------------------------------------------------------------------------ +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_uint<W> >::concat_set( + sc_dt::int64 src, int low_i) +{ + if ( low_i < 64 ) + { + base_write(src >> low_i); + } + else + { + base_write( (src < 0 ) ? src >> 63 : 0 ); + } +} + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_uint<W> >::concat_set( + const sc_dt::sc_lv_base& src, int low_i) +{ + sc_dt::sc_unsigned tmp(src.length()); + tmp = src >> low_i; + base_write( tmp.to_uint64() ); +} + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_uint<W> >::concat_set( + const sc_dt::sc_signed& src, int low_i) +{ + base_write( (src >> low_i).to_uint64()); +} + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_uint<W> >::concat_set( + const sc_dt::sc_unsigned& src, int low_i) +{ + base_write( (src >> low_i).to_uint64()); +} + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_uint<W> >::concat_set( + sc_dt::uint64 src, int low_i) +{ + base_write( ( low_i < 64 ) ? src >> low_i : 0 ); +} + + + +SC_TEMPLATE // Return the default event for this object instance. +inline const sc_event& sc_signal<sc_dt::sc_uint<W> >::default_event() const + { return base_value_changed_event(); } + + +SC_TEMPLATE // Return true if a changed event happened in the last delta cycle. +inline bool sc_signal<sc_dt::sc_uint<W> >::event() const + { return base_event(); } + + +SC_TEMPLATE // Return a reference to the value of this object instance. +inline const sc_dt::sc_uint<W>& +sc_signal<sc_dt::sc_uint<W> >::get_data_ref() const + { return *this; } + + +#if 0 +SC_TEMPLATE // Return a pointer to this object instance. +inline sc_signal<sc_dt::sc_uint<W> >& sc_signal<sc_dt::sc_uint<W> >::get_signal() + { return *this; } +#endif // 0 + + +SC_TEMPLATE // Return a kind value of "sc_signal". +inline const char* sc_signal<sc_dt::sc_uint<W> >::kind() const +{ + return "sc_signal"; +} + + +//------------------------------------------------------------------------------ +//"sc_signal_uint::operator () +// +// This operator returns a part selection of this object instance. +// left = left-hand bit of the selection. +// right = right-hand bit of the selection. +//------------------------------------------------------------------------------ +SC_TEMPLATE +inline sc_uint_sigref& sc_signal<sc_dt::sc_uint<W> >::operator () + (int left, int right) +{ + sc_uint_sigref* result_p; // Value to return. + + result_p = sc_uint_sigref::m_pool.allocate(); + result_p->initialize(this, left, right); + return *result_p; +} + + +//------------------------------------------------------------------------------ +//"sc_signal_uint::operator []" +// +// This operator returns a bit selection of this object instance. +// i = bit to be selected. +//------------------------------------------------------------------------------ +SC_TEMPLATE +inline sc_uint_sigref& sc_signal<sc_dt::sc_uint<W> >::operator [] ( int bit ) +{ + return operator () (bit,bit); +} + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_uint<W> >::operator = ( + const this_type& new_val ) + { base_write( (sc_dt::uint64)new_val ); } + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_uint<W> >::operator = ( sc_dt::uint64 new_val ) + { base_write(new_val); } + + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_uint<W> >::operator = ( const char* new_val ) + { m_new_val = sc_dt::sc_uint<64>(new_val); request_update(); } + + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_uint<W> >::operator = ( sc_dt::int64 new_val ) + { base_write((sc_dt::uint64)new_val); } + + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_uint<W> >::operator = ( int new_val ) + { base_write((sc_dt::uint64)new_val); } + + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_uint<W> >::operator = ( long new_val ) + { base_write((sc_dt::uint64)new_val); } + + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_uint<W> >::operator = ( short new_val ) + { base_write((sc_dt::uint64)new_val); } + + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_uint<W> >::operator = ( unsigned int new_val ) + { base_write((sc_dt::uint64)new_val); } + + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_uint<W> >::operator = ( unsigned long new_val ) + { base_write((sc_dt::uint64)new_val); } + + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_uint<W> >::operator = ( unsigned short new_val ) + { base_write((sc_dt::uint64)new_val); } + + +SC_TEMPLATE +template<typename T> +inline void sc_signal<sc_dt::sc_uint<W> >::operator = ( + const sc_dt::sc_generic_base<T>& new_val ) + { base_write(new_val->to_uint64()); } + + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_uint<W> >::operator = ( + const sc_dt::sc_signed& new_val ) + { base_write(new_val.to_uint64()); } + + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_uint<W> >::operator = ( + const sc_dt::sc_unsigned& new_val ) + { base_write(new_val.to_uint64()); } + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_uint<W> >::operator = ( + const sc_dt::sc_bv_base& new_val ) + { base_write( (sc_dt::sc_uint<W>)new_val ); } + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_uint<W> >::operator = ( + const sc_dt::sc_lv_base& new_val ) + { base_write( (sc_dt::sc_uint<W>)new_val ); } + + +SC_TEMPLATE +inline sc_dt::sc_uint_base* sc_signal<sc_dt::sc_uint<W> >::part_read_target() + { return this; } + + +SC_TEMPLATE +inline const sc_dt::sc_uint<W>& sc_signal<sc_dt::sc_uint<W> >::read() const + { return *this; } + + +SC_TEMPLATE // Read a portion of a value. +inline sc_dt::uint64 sc_signal<sc_dt::sc_uint<W> >::read_part( int left, int right ) const +{ + // This pointer required for HP aCC. + return (this->m_val & ~sc_dt::mask_int[left][right]) >> right; +} + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_uint<W> >::register_port( + sc_port_base& port_, const char* if_typename_ ) +{ +# ifdef DEBUG_SYSTEMC + std::string nm( if_typename_ ); + if( nm == typeid( sc_signal_inout_if<sc_dt::sc_uint<W> > ).name() ) + { + if( m_output_p != 0 ) + { + sc_signal_invalid_writer( name(), kind(), + m_output_p->name(), port_.name() ); + } + m_output_p = &port_; + } +# else + if ( &port_ && if_typename_ ) {} // Silence unused args warning. +# endif +} + + +SC_TEMPLATE // Autogenerated name object instance constructor. +inline sc_signal<sc_dt::sc_uint<W> >::sc_signal() : + sc_prim_channel(sc_gen_unique_name( "signal" )), + m_changed_event_p(0), + m_output_p(0), + m_writer_p(0) +{ } + + +SC_TEMPLATE // Explicitly named object instance constructor. +inline sc_signal<sc_dt::sc_uint<W> >::sc_signal(const char* name_) : + sc_prim_channel(name_), + m_changed_event_p(0), + m_output_p(0), + m_writer_p(0) +{ } + + +SC_TEMPLATE // Object instance destructor. +inline sc_signal<sc_dt::sc_uint<W> >::~sc_signal() +{ + if ( m_changed_event_p ) delete m_changed_event_p; +} + + +SC_TEMPLATE // Update the current value from new value. +inline void sc_signal<sc_dt::sc_uint<W> >::update() +{ + if ( m_changed_event_p ) + { + // This pointer required for HP aCC. + sc_dt::uint64 old_val = this->m_val; + sc_dt::sc_uint_base::operator = (m_new_val); + if ( old_val != this->m_val ) + { + m_changed_event_p->notify_delayed(); + m_event_delta = simcontext()->delta_count(); + } + } + else + { + sc_dt::sc_uint_base::operator = (m_new_val); + } +} + + +SC_TEMPLATE // Return the value changed event. +inline const sc_event& sc_signal<sc_dt::sc_uint<W> >::value_changed_event() const + { return base_value_changed_event(); } + + +SC_TEMPLATE // Write a sc_in<sc_dt::sc_uint<W> > value to this object instance. +inline void sc_signal<sc_dt::sc_uint<W> >::write( const sc_in<sc_dt::sc_uint<W> >& value ) + { base_write( value.operator sc_dt::uint64 () ); } + + +SC_TEMPLATE // Write a sc_inout<sc_dt::sc_uint<W> > value to this object instance. +inline void sc_signal<sc_dt::sc_uint<W> >::write( const sc_inout<sc_dt::sc_uint<W> >& value ) + { base_write( value.operator sc_dt::uint64 () ); } + + +SC_TEMPLATE // Write a sc_dt::sc_uint<W> value to this object instance. +inline void sc_signal<sc_dt::sc_uint<W> >::write( + const sc_dt::sc_uint<W>& value ) + { base_write( value); } + + +SC_TEMPLATE // Select a portion of a value. +inline sc_uint_sigref& sc_signal<sc_dt::sc_uint<W> >::select_part(int left, int right) +{ + sc_uint_sigref* result_p = sc_uint_sigref::m_pool.allocate(); + result_p->initialize(this, left, right); + return *result_p; +} + + +SC_TEMPLATE // Write a portion of a value. If this is the first write in + // a delta cycle we copy the existing value before setting the bits. +inline void sc_signal<sc_dt::sc_uint<W> >::write_part( sc_dt::uint64 v, int left, int right ) +{ + sc_dt::uint64 new_v; // New value. + sc_dt::uint64 keep; // Keep mask value. + + keep = sc_dt::mask_int[left][right]; + new_v = (m_new_val & keep) | ((v << right) & ~keep); + m_new_val = new_v; + request_update(); +} + + +//============================================================================== +// CLASS sc_in<sc_dt::sc_uint<W> > +// +// This class implements an input port whose target acts like an sc_dt::sc_uint<W> data +// value. This class is a specialization of the generic sc_in class to +// implement tailored support for the sc_dt::sc_uint<W> class. +//============================================================================== +SC_TEMPLATE +class sc_in<sc_dt::sc_uint<W> > : + public sc_port<sc_signal_in_if<sc_dt::sc_uint<W> >, 1, + SC_ONE_OR_MORE_BOUND>, + public sc_dt::sc_value_base +{ + public: + + // typedefs + + typedef sc_dt::sc_uint<W> data_type; + typedef sc_signal_in_if<sc_dt::sc_uint<W> > if_type; + typedef sc_port<if_type,1,SC_ONE_OR_MORE_BOUND> base_type; + typedef sc_in<sc_dt::sc_uint<W> > this_type; + + typedef if_type in_if_type; + typedef base_type in_port_type; + typedef sc_signal_inout_if<sc_dt::sc_uint<W> > inout_if_type; + typedef sc_inout<sc_dt::sc_uint<W> > inout_port_type; + + public: + + // bind methods and operators: + + void bind( const in_if_type& interface_ ) + { sc_port_base::bind( const_cast<in_if_type&>( interface_) );} + void operator () ( const in_if_type& interface_ ) + { sc_port_base::bind( const_cast<in_if_type&>( interface_) );} + void bind( in_port_type& parent_ ) + { sc_port_base::bind(parent_);} + void operator () ( in_port_type& parent_ ) + { sc_port_base::bind(parent_);} + void bind( inout_port_type& parent_ ) + { sc_port_base::bind(parent_);} + void operator () ( inout_port_type& parent_ ) + { sc_port_base::bind(parent_);} + + protected: + // called by pbind (for internal use only) + virtual inline int vbind( sc_interface& interface_ ) + { + return sc_port_b<if_type>::vbind( interface_ ); + } + virtual inline int vbind( sc_port_base& parent_ ) + { + in_port_type* in_parent = dynamic_cast<in_port_type*>( &parent_ ); + if( in_parent != 0 ) { + sc_port_base::bind( *in_parent ); + return 0; + } + inout_port_type* inout_parent = dynamic_cast<inout_port_type*>( &parent_ ); + if( inout_parent != 0 ) { + sc_port_base::bind( *inout_parent ); + return 0; + } + // type mismatch + return 2; + } + + + // constructors + + public: + sc_in() + : base_type(), m_traces( 0 ) + {} + + explicit sc_in( const char* name_ ) + : base_type( name_ ), m_traces( 0 ) + {} + + explicit sc_in( const in_if_type& interface_ ) + : base_type( const_cast<in_if_type&>( interface_ ) ), m_traces( 0 ) + {} + + sc_in( const char* name_, const in_if_type& interface_ ) + : base_type( name_, const_cast<in_if_type&>( interface_ ) ), m_traces( 0 ) + {} + + explicit sc_in( in_port_type& parent_ ) + : base_type( parent_ ), m_traces( 0 ) + {} + + sc_in( const char* name_, in_port_type& parent_ ) + : base_type( name_, parent_ ), m_traces( 0 ) + {} + + explicit sc_in( inout_port_type& parent_ ) + : base_type(), m_traces( 0 ) + { sc_port_base::bind( parent_ ); } + + sc_in( const char* name_, inout_port_type& parent_ ) + : base_type( name_ ), m_traces( 0 ) + { sc_port_base::bind( parent_ ); } + + sc_in( this_type& parent_ ) + : base_type( parent_ ), m_traces( 0 ) + {} + + sc_in( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ), m_traces( 0 ) + {} + + + // destructor + + virtual inline ~sc_in() + { + remove_traces(); + } + + // bit and part selection + + sc_dt::sc_uint_bitref_r operator [] ( int i ) const + { return (*this)->read()[i]; } + sc_dt::sc_uint_bitref_r bit( int i ) const + { return (*this)->read()[i]; } + sc_dt::sc_uint_subref_r operator () ( int left, int right ) const + { return (*this)->read()(left,right); } + sc_dt::sc_uint_subref_r range( int left, int right ) const + { return (*this)->read()(left,right); } + + + // interface access shortcut methods + + // get the default event + + const sc_event& default_event() const + { return (*this)->value_changed_event(); } + + + // get the value changed event + + const sc_event& value_changed_event() const + { return (*this)->value_changed_event(); } + + + // read the current value + + const sc_dt::sc_uint<W>& read() const + { return (*this)->read(); } + + operator sc_dt::uint64 () const + { return (sc_dt::uint64)(*this)->read(); } + + // was there a value changed event? + + bool event() const + { return (*this)->event(); } + + + // (other) event finder method(s) + + sc_event_finder& value_changed() const + { + return *new sc_event_finder_t<in_if_type>( + *this, &in_if_type::value_changed_event ); + } + + + + // reduction methods: + + inline bool and_reduce() const + { return (*this)->read().and_reduce(); } + inline bool nand_reduce() const + { return (*this)->read().nand_reduce(); } + inline bool nor_reduce() const + { return (*this)->read().nor_reduce(); } + inline bool or_reduce() const + { return (*this)->read().or_reduce(); } + inline bool xnor_reduce() const + { return (*this)->read().xnor_reduce(); } + inline bool xor_reduce() const + { return (*this)->read().xor_reduce(); } + + + // called when elaboration is done + /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ + /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ + + virtual inline void end_of_elaboration() + { + if( m_traces != 0 ) { + for( unsigned int i = 0; i < m_traces->size(); ++ i ) { + sc_trace_params* p = (*m_traces)[i]; + sc_trace( p->tf, read(), p->name ); + } + remove_traces(); + } + } + + virtual inline const char* kind() const + { return "sc_in"; } + + + // called by sc_trace + void add_trace( sc_trace_file* tf_, const std::string& name_ ) const + { + if( tf_ != 0 ) { + if( m_traces == 0 ) { + m_traces = new sc_trace_params_vec; + } + m_traces->push_back( new sc_trace_params( tf_, name_ ) ); + } + } + + + // concatenation methods + + virtual inline int concat_length(bool* xz_present_p) const + { return (*this)->read().concat_length( xz_present_p ); } + virtual inline sc_dt::uint64 concat_get_uint64() const + { return (*this)->read().concat_get_uint64(); } + virtual inline bool concat_get_ctrl( + sc_dt::sc_digit* dst_p, int low_i ) const + { return (*this)->read().concat_get_ctrl(dst_p, low_i); } + virtual inline bool concat_get_data( + sc_dt::sc_digit* dst_p, int low_i ) const + { return (*this)->read().concat_get_data(dst_p, low_i); } + + protected: + void remove_traces() const + { + if( m_traces != 0 ) { + for( int i = m_traces->size() - 1; i >= 0; -- i ) { + delete (*m_traces)[i]; + } + delete m_traces; + m_traces = 0; + } + } + + mutable sc_trace_params_vec* m_traces; + + + private: + + // disabled + sc_in( const sc_in<sc_dt::sc_uint<W> >& ); + sc_in<sc_dt::sc_uint<W> >& operator = ( const sc_in<sc_dt::sc_uint<W> >& ); + +#ifdef __GNUC__ + // Needed to circumvent a problem in the g++-2.95.2 compiler: + // This unused variable forces the compiler to instantiate + // an object of T template so an implicit conversion from + // read() to a C++ intrinsic data type will work. + static data_type dummy; +#endif + +}; + + + +SC_TEMPLATE +inline std::ostream& operator << ( + std::ostream& os, const sc_in<sc_dt::sc_uint<W> >& a ) +{ + a.read().print( os ); + return os; +} + + +//============================================================================== +// CLASS sc_inout<sc_dt::sc_uint<W> > +// +// This class implements an input/output port whose target acts like an +// sc_dt::sc_uint<W> data value. It is derived from the sc_uint_in. This class is a +// specialization of the generic sc_inout class to implement tailored support +// for the sc_dt::sc_uint<W> class. +//============================================================================== +SC_TEMPLATE +class sc_inout<sc_dt::sc_uint<W> > : + public sc_port<sc_signal_inout_if<sc_dt::sc_uint<W> >, 1, + SC_ONE_OR_MORE_BOUND>, + public sc_dt::sc_value_base +{ + public: + + // typedefs + + typedef sc_dt::sc_uint<W> data_type; + typedef sc_signal_inout_if<sc_dt::sc_uint<W> > if_type; + typedef sc_port<if_type,1,SC_ONE_OR_MORE_BOUND> base_type; + typedef sc_inout<sc_dt::sc_uint<W> > this_type; + + typedef if_type inout_if_type; + typedef base_type inout_port_type; + + public: + + // bind methods and operators: + + void bind( const inout_if_type& interface_ ) + { sc_port_base::bind( const_cast<inout_if_type&>( interface_) ); } + void operator () ( const inout_if_type& interface_ ) + { sc_port_base::bind( const_cast<inout_if_type&>( interface_) ); } + void bind( inout_port_type& parent_ ) + { sc_port_base::bind(parent_); } + void operator () ( inout_port_type& parent_ ) + { sc_port_base::bind(parent_); } + + protected: + // called by pbind (for internal use only) + virtual inline int vbind( sc_interface& interface_ ) + { + return sc_port_b<if_type>::vbind( interface_ ); + } + virtual inline int vbind( sc_port_base& parent_ ) + { + inout_port_type* inout_parent = dynamic_cast<inout_port_type*>( &parent_ ); + if( inout_parent != 0 ) { + sc_port_base::bind( *inout_parent ); + return 0; + } + // type mismatch + return 2; + } + + + // constructors + + public: + sc_inout() + : base_type(), m_init_val_p(0), m_traces( 0 ) + {} + + explicit sc_inout( const char* name_ ) + : base_type( name_ ), m_init_val_p(0), m_traces( 0 ) + {} + + explicit sc_inout( inout_if_type& interface_ ) + : base_type( interface_ ), m_init_val_p(0), m_traces( 0 ) + {} + + sc_inout( const char* name_, inout_if_type& interface_ ) + : base_type( name_, interface_ ), m_init_val_p(0), m_traces( 0 ) + {} + + explicit sc_inout( inout_port_type& parent_ ) + : base_type( parent_ ), m_init_val_p(0), m_traces( 0 ) + {} + + sc_inout( const char* name_, inout_port_type& parent_ ) + : base_type( name_, parent_ ), m_init_val_p(0), m_traces( 0 ) + {} + + sc_inout( this_type& parent_ ) + : base_type( parent_ ), m_init_val_p(0), m_traces( 0 ) + {} + + sc_inout( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ), m_init_val_p(0), m_traces( 0 ) + {} + + + // destructor + + virtual inline ~sc_inout() + { + remove_traces(); + } + + // bit and part selection + + sc_dt::sc_uint_bitref_r operator [] ( int i ) const + { return (*this)->read()[i]; } + sc_dt::sc_uint_bitref_r bit( int i ) const + { return (*this)->read()[i]; } + sc_uint_sigref& operator [] ( int i ) + { return (*this)->select_part(i,i); } + sc_uint_sigref& bit( int i ) + { return (*this)->select_part(i,i); } + sc_dt::sc_uint_subref_r operator () ( int left, int right ) const + { return (*this)->read()(left,right); } + sc_dt::sc_uint_subref_r range( int left, int right ) const + { return (*this)->read()(left,right); } + sc_uint_sigref& operator () ( int left, int right ) + { return (*this)->select_part(left,right); } + sc_uint_sigref& range( int left, int right ) + { return (*this)->select_part(left,right); } + + + // interface access shortcut methods + + // get the default event + + const sc_event& default_event() const + { return (*this)->value_changed_event(); } + + + // get the value changed event + + const sc_event& value_changed_event() const + { return (*this)->value_changed_event(); } + + + // read the current value + + const sc_dt::sc_uint<W>& read() const + { return (*this)->read(); } + + operator sc_dt::uint64 () const + { return (sc_dt::uint64)(*this)->read(); } + + // was there a value changed event? + + bool event() const + { return (*this)->event(); } + + + // (other) event finder method(s) + + sc_event_finder& value_changed() const + { + return *new sc_event_finder_t<inout_if_type>( + *this, &inout_if_type::value_changed_event ); + } + + + + // reduction methods: + + inline bool and_reduce() const + { return (*this)->read().and_reduce(); } + inline bool nand_reduce() const + { return (*this)->read().nand_reduce(); } + inline bool nor_reduce() const + { return (*this)->read().nor_reduce(); } + inline bool or_reduce() const + { return (*this)->read().or_reduce(); } + inline bool xnor_reduce() const + { return (*this)->read().xnor_reduce(); } + inline bool xor_reduce() const + { return (*this)->read().xor_reduce(); } + + + // called when elaboration is done + /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ + /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ + + virtual inline void end_of_elaboration() + { + if( m_init_val_p != 0 ) { + (*this)->write( (sc_dt::uint64) *m_init_val_p ); + delete m_init_val_p; + m_init_val_p = 0; + } + if( m_traces != 0 ) { + for( unsigned int i = 0; i < m_traces->size(); ++ i ) { + sc_trace_params* p = (*m_traces)[i]; + sc_trace( p->tf, read(), p->name ); + } + remove_traces(); + } + } + + virtual inline const char* kind() const + { return "sc_inout"; } + + // value initialization + + inline void initialize( const sc_dt::sc_uint<W>& value_ ) + { + inout_if_type* iface = this->get_interface(0); + if( iface != 0 ) { + iface->write( value_ ); + } else { + if( m_init_val_p == 0 ) { + m_init_val_p = new sc_dt::uint64; + } + *m_init_val_p = value_; + } + } + + + // called by sc_trace + void add_trace( sc_trace_file* tf_, const std::string& name_ ) const + { + if( tf_ != 0 ) { + if( m_traces == 0 ) { + m_traces = new sc_trace_params_vec; + } + m_traces->push_back( new sc_trace_params( tf_, name_ ) ); + } + } + + + // concatenation methods + + virtual inline int concat_length(bool* xz_present_p) const + { return (*this)->read().concat_length( xz_present_p ); } + virtual inline sc_dt::uint64 concat_get_uint64() const + { return (*this)->read().concat_get_uint64(); } + virtual inline bool concat_get_ctrl( + sc_dt::sc_digit* dst_p, int low_i ) const + { return (*this)->read().concat_get_ctrl(dst_p, low_i); } + virtual inline bool concat_get_data( + sc_dt::sc_digit* dst_p, int low_i ) const + { return (*this)->read().concat_get_data(dst_p, low_i); } + virtual inline void concat_set(sc_dt::int64 src, int low_i) + { *this = (src >> ((low_i < 64) ? low_i : 63)); } +#if 0 + virtual inline void concat_set(const sc_dt::sc_lv_base& src, int low_i) + { if (low_i < 64) *this = src >> low_i; else *this = 0; } +#endif // 0 #### + virtual inline void concat_set(const sc_dt::sc_signed& src, int low_i) + { *this = (src >> low_i); } + virtual inline void concat_set(const sc_dt::sc_unsigned& src, int low_i) + { *this = (src >> low_i); } + virtual inline void concat_set(sc_dt::uint64 src, int low_i) + { *this = (low_i < 64) ? src >> low_i : (sc_dt::uint64)0; } + + // assignment operators: + + public: + inline void operator = ( const this_type& new_val ) + { (*this)->write( (sc_dt::uint64)new_val ); } + inline void operator = ( const char* new_val ) + { (*this)->write( this_type(new_val) ); } + inline void operator = ( sc_dt::uint64 new_val ) + { (*this)->write(new_val); } + inline void operator = ( sc_dt::int64 new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( int new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( long new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( short new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( unsigned int new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( unsigned long new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( unsigned short new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + template<typename T> + inline void operator = ( const sc_dt::sc_generic_base<T>& new_val ) + { (*this)->write(new_val->to_uint64()); } + inline void operator = ( const sc_dt::sc_signed& new_val ) + { (*this)->write(new_val.to_uint64()); } + inline void operator = ( const sc_dt::sc_unsigned& new_val ) + { (*this)->write(new_val.to_uint64()); } + inline void operator = ( const sc_dt::sc_bv_base& new_val ) + { (*this)->write((sc_dt::sc_uint<W>)new_val); } + inline void operator = ( const sc_dt::sc_lv_base& new_val ) + { (*this)->write((sc_dt::sc_uint<W>)new_val); } + + inline void write( const sc_in<sc_dt::sc_uint<W> >& new_val ) + { (*this)->write( (sc_dt::uint64)new_val ); } + inline void write( const sc_inout<sc_dt::sc_uint<W> >& new_val ) + { (*this)->write( (sc_dt::uint64)new_val); } + inline void write( const sc_dt::sc_uint<W>& new_val ) + { (*this)->write( (sc_dt::uint64)new_val); } + + protected: + void remove_traces() const + { + if( m_traces != 0 ) { + for( int i = m_traces->size() - 1; i >= 0; -- i ) { + delete (*m_traces)[i]; + } + delete m_traces; + m_traces = 0; + } + } + + sc_dt::uint64* m_init_val_p; + mutable sc_trace_params_vec* m_traces; + + + private: + + // disabled + sc_inout( const sc_inout<sc_dt::sc_uint<W> >& ); + +#ifdef __GNUC__ + // Needed to circumvent a problem in the g++-2.95.2 compiler: + // This unused variable forces the compiler to instantiate + // an object of T template so an implicit conversion from + // read() to a C++ intrinsic data type will work. + static data_type dummy; +#endif + +}; + + + +SC_TEMPLATE +inline std::ostream& operator << ( + std::ostream& os, const sc_inout<sc_dt::sc_uint<W> >& a ) +{ + a.read().print( os ); + return os; +} + + +//============================================================================== +// CLASS sc_out<sc_dt::sc_uint<W> > +// +// This class implements an output port whose target acts like an +// sc_dt::sc_uint<W> data value. This class is a derivation of sc_inout, since +// output ports are really no different from input/output ports. +//============================================================================== +SC_TEMPLATE +class sc_out<sc_dt::sc_uint<W> > : public sc_inout<sc_dt::sc_uint<W> > +{ + public: + + // typedefs + + typedef sc_dt::sc_uint<W> data_type; + + typedef sc_out<data_type> this_type; + typedef sc_inout<data_type> base_type; + + typedef typename base_type::inout_if_type inout_if_type; + typedef typename base_type::inout_port_type inout_port_type; + + // constructors + + sc_out() + : base_type() + {} + + explicit sc_out( const char* name_ ) + : base_type( name_ ) + {} + + explicit sc_out( inout_if_type& interface_ ) + : base_type( interface_ ) + {} + + sc_out( const char* name_, inout_if_type& interface_ ) + : base_type( name_, interface_ ) + {} + + explicit sc_out( inout_port_type& parent_ ) + : base_type( parent_ ) + {} + + sc_out( const char* name_, inout_port_type& parent_ ) + : base_type( name_, parent_ ) + {} + + sc_out( this_type& parent_ ) + : base_type( parent_ ) + {} + + sc_out( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ) + {} + + + // destructor (does nothing) + + virtual inline ~sc_out() + {} + + + // assignment operators: + + public: + inline void operator = ( const this_type& new_val ) + { (*this)->write( (sc_dt::uint64)new_val ); } + inline void operator = ( const char* new_val ) + { (*this)->write( this_type(new_val) ); } + inline void operator = ( sc_dt::uint64 new_val ) + { (*this)->write(new_val); } + inline void operator = ( sc_dt::int64 new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( int new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( long new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( short new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( unsigned int new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( unsigned long new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( unsigned short new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + template<typename T> + inline void operator = ( const sc_dt::sc_generic_base<T>& new_val ) + { (*this)->write(new_val->to_uint64()); } + inline void operator = ( const sc_dt::sc_signed& new_val ) + { (*this)->write(new_val); } + inline void operator = ( const sc_dt::sc_unsigned& new_val ) + { (*this)->write(new_val); } + inline void operator = ( const sc_dt::sc_bv_base& new_val ) + { (*this)->write((sc_dt::sc_uint<W>)new_val); } + inline void operator = ( const sc_dt::sc_lv_base& new_val ) + { (*this)->write((sc_dt::sc_uint<W>)new_val); } + + private: + + // disabled + sc_out( const this_type& ); +}; + + + +//------------------------------------------------------------------------------ +//"sc_uint_sigref::initialize" +// +// This method initializes an object instance from the supplied arguments. +// if_p -> interface for signal to perform writes for this object. +// left = left-most bit in selection. +// right = right-most bit in selection. +//------------------------------------------------------------------------------ +inline +void sc_uint_sigref::initialize(sc_uint_part_if* if_p, int left, int right) +{ + m_left = left; + m_right = right; + m_if_p = if_p; + m_obj_p = if_p->part_read_target(); +} + + +//------------------------------------------------------------------------------ +//"sc_uint_sigref::operator =" +// +// These operators assign a value to the bits associated with this object +// instance within this object instance's target signal. +//------------------------------------------------------------------------------ +inline void sc_uint_sigref::operator = ( sc_dt::uint64 v ) +{ + m_if_p->write_part( v, m_left, m_right ); +} + +inline void sc_uint_sigref::operator = ( const char* /*v*/ ) +{ +} + +inline void sc_uint_sigref:: operator = ( sc_dt::int64 v ) +{ + *this = (sc_dt::uint64)v; +} + +inline void sc_uint_sigref:: operator = ( int v ) +{ + *this = (sc_dt::uint64)v; +} + +inline void sc_uint_sigref:: operator = ( long v ) +{ + *this = (sc_dt::uint64)v; +} + +inline void sc_uint_sigref:: operator = ( unsigned int v ) +{ + *this = (sc_dt::uint64)v; +} + +inline void sc_uint_sigref:: operator = ( unsigned long v ) +{ + *this = (sc_dt::uint64)v; +} + +void sc_uint_sigref::operator = ( const sc_uint_sigref& v ) +{ + *this = (sc_dt::uint64)v; +} + +template<typename T> +inline void sc_uint_sigref:: operator = ( const sc_dt::sc_generic_base<T>& v ) +{ + *this = v->to_uint64(); +} + +inline void sc_uint_sigref:: operator = ( const sc_dt::sc_signed& v ) +{ + *this = v.to_uint64(); +} + +inline void sc_uint_sigref:: operator = ( const sc_dt::sc_unsigned& v ) +{ + *this = v.to_uint64(); +} + +#undef SC_TEMPLATE +} // namespace sc_core +#endif // !defined(SC_SIGNAL_UINT_H) + +namespace sc_core { + +//------------------------------------------------------------------------------ +// POOL OF TEMPORARY INSTANCES OF sc_uint_sigref +// +// This allows use to pass const references for part and bit selections +// on sc_signal<sc_dt::sc_uint<W> > object instances. +//------------------------------------------------------------------------------ +sc_vpool<sc_uint_sigref> sc_uint_sigref::m_pool(8); + + +//------------------------------------------------------------------------------ +//"sc_uint_part_if::default methods" +// +// These versions just produce errors if they are not overloaded but used. +//------------------------------------------------------------------------------ + +sc_dt::sc_uint_base* sc_uint_part_if::part_read_target() +{ + SC_REPORT_ERROR( "attempted specalized signal operation on " + "non-specialized signal", "int" ); + return 0; +} +sc_dt::uint64 sc_uint_part_if::read_part( int /*left*/, int /*right*/ ) const +{ + SC_REPORT_ERROR( "attempted specalized signal operation on " + "non-specialized signal", "int" ); + return 0; +} +sc_uint_sigref& sc_uint_part_if::select_part( int /*left*/, int /*right*/ ) +{ + SC_REPORT_ERROR( "attempted specalized signal operation on " + "non-specialized signal", "int" ); + return *(sc_uint_sigref*)0; +} +void sc_uint_part_if::write_part( sc_dt::uint64 v, int /*left*/, int /*right*/ ) +{ + SC_REPORT_ERROR( "attempted specalized signal operation on " + "non-specialized signal", "int" ); +} + +//------------------------------------------------------------------------------ +//"sc_uint_sigref::concate_set" +// +// These methods assign this object instance's value from the supplied +// value starting at the supplied bit within that value. +// src = value to use to set this object instance's value. +// low_i = bit in src that is to be the low order bit of the value to set. +// #### OPTIMIZE +//------------------------------------------------------------------------------ +void sc_uint_sigref::concat_set(sc_dt::int64 src, int low_i) +{ + *this = (low_i < 64) ? src >> low_i : src >> 63; +} + + +void sc_uint_sigref::concat_set(const sc_dt::sc_signed& src, int low_i) +{ + if ( low_i < src.length() ) + *this = src >> low_i; + else + *this = (src < 0) ? (sc_dt::uint64)-1 : 0; +} + + +void sc_uint_sigref::concat_set(const sc_dt::sc_lv_base& src, int low_i) +{ + if ( low_i < src.length() ) + *this = (src >> low_i).to_uint64(); + else + *this = 0; +} + + +void sc_uint_sigref::concat_set(const sc_dt::sc_unsigned& src, int low_i) +{ + if ( low_i < src.length() ) + *this = src >> low_i; + else + *this = 0; +} + + +void sc_uint_sigref::concat_set(sc_dt::uint64 src, int low_i) +{ + *this = (low_i < 64) ? src >> low_i : 0; +} + +} // namespace sc_core diff --git a/src/systemc/tests/include/specialized_signals/scx_signal_unsigned.h b/src/systemc/tests/include/specialized_signals/scx_signal_unsigned.h new file mode 100644 index 000000000..a356d44bd --- /dev/null +++ b/src/systemc/tests/include/specialized_signals/scx_signal_unsigned.h @@ -0,0 +1,1834 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_signal_unsigned.cpp -- The sc_signal<sc_unsigned<W> > implementations. + + Original Author: Andy Goodrich, Forte Design Systems, 2002-10-22 + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +/* +$Log: scx_signal_unsigned.h,v $ +Revision 1.1 2011/08/15 17:31:11 acg + Andy Goodrich: moved specialized signals from examples to this tree. + +Revision 1.2 2011/08/15 16:43:24 acg + Torsten Maehne: changes to remove unused argument warnings. + +Revision 1.1.1.1 2006/12/15 20:20:03 acg +SystemC 2.3 + +Revision 1.2 2005/12/26 20:11:14 acg +Fixed up copyright. + +Revision 1.1.1.1 2005/12/19 23:16:42 acg +First check in of SystemC 2.1 into its own archive. + +Revision 1.17 2005/09/15 23:01:52 acg +Added std:: prefix to appropriate methods and types to get around +issues with the Edison Front End. + +Revision 1.16 2005/05/03 19:52:26 acg +Get proper header locations on includes. + +Revision 1.15 2005/05/03 19:50:20 acg +Name space version. + +Revision 1.12 2005/04/11 19:05:36 acg +Change to sc_clock for Microsoft VCC 6.0. Changes for namespaces + +Revision 1.11 2005/04/03 22:52:52 acg +Namespace changes. + +Revision 1.10 2005/03/21 22:31:33 acg +Changes to sc_core namespace. + +Revision 1.9 2004/09/27 21:01:59 acg +Andy Goodrich - Forte Design Systems, Inc. + - This is specialized signal support that allows better use of signals + and ports whose target value is a SystemC native type. + +*/ + + + +#include <systemc> +#include <typeinfo> + +/***************************************************************************** + + sc_signal_unsigned.h -- The sc_signal<sc_dt::sc_biguint<W> > definitions. + + Original Author: Andy Goodrich, Forte Design Systems, 2002-10-22 + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +/* +$Log: scx_signal_unsigned.h,v $ +Revision 1.1 2011/08/15 17:31:11 acg + Andy Goodrich: moved specialized signals from examples to this tree. + +Revision 1.3 2011/08/15 16:43:24 acg + Torsten Maehne: changes to remove unused argument warnings. + +Revision 1.2 2011/06/28 21:23:02 acg + Andy Goodrich: merging of SCV tree. + +Revision 1.1.1.1 2006/12/15 20:20:03 acg +SystemC 2.3 + +Revision 1.4 2006/10/23 19:40:36 acg + Andy Goodrich: added an explicit dynamic cast to keep gcc 4.x happy. + +Revision 1.3 2006/03/21 01:31:49 acg + Andy Goodrich: changed over to sc_get_current_process_b() from + sc_get_current_process_base() since the function's name changed. + +Revision 1.2 2005/12/26 20:11:14 acg +Fixed up copyright. + +Revision 1.1.1.1 2005/12/19 23:16:42 acg +First check in of SystemC 2.1 into its own archive. + +Revision 1.28 2005/09/15 23:01:52 acg +Added std:: prefix to appropriate methods and types to get around +issues with the Edison Front End. + +Revision 1.27 2005/07/30 03:44:11 acg +Changes from 2.1. + +Revision 1.26 2005/05/09 17:17:12 acg +Changes from 2.1. + +Revision 1.25 2005/05/08 19:04:06 acg +Fix bug in concat_set(int64,off). Other changes from 2.1 examples usage. + +Revision 1.24 2005/05/03 19:50:20 acg +Name space version. + +Revision 1.22 2005/03/21 22:31:33 acg +Changes to sc_core namespace. + +Revision 1.21 2005/01/10 17:51:58 acg +Improvements. + +Revision 1.20 2004/11/09 00:11:27 acg +Added support for sc_generic_base<T> in place of sc_concatref. sc_concatref +now is derived from sc_generic_base<sc_concatref>. + +Revision 1.19 2004/09/27 21:01:59 acg +Andy Goodrich - Forte Design Systems, Inc. + - This is specialized signal support that allows better use of signals + and ports whose target value is a SystemC native type. + +*/ + + +#if !defined(SC_SIGNAL_UNSIGNED_H) +#define SC_SIGNAL_UNSIGNED_H + +#if ( !defined(_MSC_VER) || _MSC_VER > 1200 ) +# define SC_TEMPLATE template<int W> +#else +# define SC_TEMPLATE template<> template<int W> +#endif + + +// FORWARD REFERENCES AND USINGS: + +using sc_dt::sc_signed; +using sc_dt::int64; +using sc_dt::uint64; + +namespace sc_core { + +class sc_unsigned_sigref; + +//============================================================================== +// CLASS sc_unsigned_part_if +// +// This class provides generic access to part selections for signals whose +// data type is sc_dt::sc_biguint<W>. This class serves as the base class for the +// sc_dt::sc_biguint<W> specialization of the sc_signal_in_if<T> class. The methods +// in this class may be over-ridden individually, those that are not overridden +// will produce an error message when called. The methods are used by the +// sc_unsigned_sigref class. +// +// Notes: +// (1) Descriptions of the methods and operators in this class appear with +// their implementations in sc_signal<sc_dt::sc_biguint<W> >. +//============================================================================== +class sc_unsigned_part_if : virtual public sc_interface { + protected: + // constructor: + sc_unsigned_part_if() {} + + public: + // perform a part read. + virtual sc_dt::sc_unsigned* part_read_target(); + virtual sc_dt::sc_unsigned read_part( int left, int right ) const; + + // perform a part write. + virtual sc_unsigned_sigref& select_part( int left, int right ); + virtual void write_part( sc_dt::int64 v, int left, int right ); + virtual void write_part( sc_dt::uint64 v, int left, int right ); + virtual void write_part( const sc_dt::sc_signed& v, int left, int right ); + virtual void write_part( const sc_dt::sc_unsigned& v, int left, int right ); + + + private: + sc_unsigned_part_if( const sc_unsigned_part_if& ); + sc_unsigned_part_if& operator = ( const sc_unsigned_part_if& ); +}; + + +//============================================================================== +// CLASS sc_signal_in_if<sc_dt::sc_biguint<W> > +// +// This is the class specializations for the sc_signal_in_if<T> class to +// provide additional features for sc_signal instances whose template is +// sc_dt::sc_biguint<W>, including part access. +// +// Notes: +// (1) Descriptions of the methods and operators in this class appear with +// their implementations in sc_signal<sc_dt::sc_biguint<W> >. +//============================================================================== +template< int W > +class sc_signal_in_if<sc_dt::sc_biguint<W> > : public sc_unsigned_part_if { + friend class sc_unsigned_sigref; + public: + typedef sc_signal_in_if<sc_dt::sc_biguint<W> > this_type; + + // get the value changed event + virtual const sc_event& value_changed_event() const = 0; + + + // read the current value + virtual const sc_dt::sc_biguint<W>& read() const = 0; + + // get a reference to the current value (for tracing) + virtual const sc_dt::sc_biguint<W>& get_data_ref() const = 0; + + + // was there a value changed event? + virtual bool event() const = 0; + + protected: + // constructor + sc_signal_in_if() + {} + + private: // disabled + sc_signal_in_if( const this_type& ); + this_type& operator = ( const this_type& ); +}; + +//============================================================================= +// CLASS : sc_unsigned_sigref +// +// Proxy class for sc_signal_uint bit and part selection. +//============================================================================= +class sc_unsigned_sigref : public sc_dt::sc_unsigned_subref_r +{ + public: + sc_unsigned_sigref() : sc_dt::sc_unsigned_subref_r() {} + virtual ~sc_unsigned_sigref() {} + virtual void concat_set(sc_dt::int64 src, int low_i); + virtual void concat_set(const sc_dt::sc_signed& src, int low_i); + virtual void concat_set(const sc_dt::sc_unsigned& src, int low_i); + virtual void concat_set(const sc_dt::sc_lv_base& src, int low_i); + virtual void concat_set(sc_dt::uint64 src, int low_i); + + public: + inline void initialize( sc_unsigned_part_if* if_p, int left_, int right_ ); + + public: + inline void operator = ( sc_dt::uint64 v ); + inline void operator = ( const char* v ); + inline void operator = ( unsigned long v ); + inline void operator = ( long v ); + inline void operator = ( unsigned int v ); + inline void operator = ( int v ); + inline void operator = ( sc_dt::int64 v ); + inline void operator = ( double v ); + inline void operator = ( const sc_unsigned_sigref& v ); + template<typename T> + inline void operator = ( const sc_dt::sc_generic_base<T>& v ); + inline void operator = ( const sc_dt::sc_signed& v ); + inline void operator = ( const sc_dt::sc_unsigned& v ); + inline void operator = ( const sc_dt::sc_bv_base& v ); + inline void operator = ( const sc_dt::sc_lv_base& v ); + + public: + static sc_vpool<sc_unsigned_sigref> m_pool; // Pool of objects to use. + + protected: + sc_unsigned_part_if* m_if_p; // Target for selection. + + private: + + // disabled + sc_unsigned_sigref( const sc_unsigned_sigref& a ); +}; + + +//============================================================================== +// CLASS sc_signal<sc_dt::sc_biguint<W> > +// +// This class implements a signal whose value acts like an sc_dt::sc_biguint<W> data +// value. This class is a specialization of the generic sc_signal class to +// implement tailored support for the sc_dt::sc_biguint<W> class. +// +// Notes: +// (1) Descriptions of the methods and operators in this class appear with +// their implementations. +//============================================================================== +SC_TEMPLATE +class sc_signal<sc_dt::sc_biguint<W> > : + public sc_dt::sc_biguint<W>, + public sc_prim_channel, + public sc_signal_inout_if<sc_dt::sc_biguint<W> > +{ + public: // typedefs + typedef sc_signal<sc_dt::sc_biguint<W> > this_type; + + public: // constructors and destructor: + inline sc_signal(); + explicit inline sc_signal(const char* name_); + virtual inline ~sc_signal(); + + public: // base methods: + inline bool base_event() const; + inline const sc_dt::sc_biguint<W>& base_read() const; + inline const sc_event& base_value_changed_event() const; + inline void base_write( sc_dt::int64 value ); + inline void base_write( sc_dt::uint64 value ); + inline void base_write( const sc_dt::sc_signed& value ); + inline void base_write( const sc_dt::sc_unsigned& value ); + + public: // sc_prim_channel virtual methods: + virtual inline const char* kind() const; + virtual inline void update(); + + public: // sc_interface virtual methods: + virtual inline const sc_event& default_event() const; + virtual inline void register_port( + sc_port_base& port_, const char* if_typename_ ); + + public: // sc_unsigned_channel virtual methods: + virtual inline sc_dt::sc_unsigned* part_read_target(); + virtual inline sc_dt::sc_unsigned read_part(int left, int right) const; + virtual sc_unsigned_sigref& select_part( int left, int right ); + virtual inline void write_part( sc_dt::int64 v, int left, int right ); + virtual inline void write_part( sc_dt::uint64 v, int left, int right ); + virtual inline void write_part( const sc_dt::sc_signed& v, int left, int right ); + virtual inline void write_part(const sc_dt::sc_unsigned& v, int left, int right); + + public: // interface virtual methods: + virtual inline bool event() const; + virtual inline const sc_dt::sc_biguint<W>& get_data_ref() const; + virtual inline sc_signal<sc_dt::sc_biguint<W> >& get_signal(); + virtual inline const sc_dt::sc_biguint<W>& read() const; + virtual inline const sc_event& value_changed_event() const; + virtual inline void write( const sc_in<sc_dt::sc_biguint<W> >& value ); + virtual inline void write( const sc_inout<sc_dt::sc_biguint<W> >& value ); + virtual inline void write( const sc_dt::sc_biguint<W>& value ); + + public: // part selections: + inline sc_unsigned_sigref& operator () ( int left, int right ); + // #### Need to add range() and bit()! + inline sc_unsigned_sigref& operator [] ( int bit ); + + public: // operators: + inline void operator = ( const this_type& new_val ); + inline void operator = ( const char* new_val ); + inline void operator = ( sc_dt::uint64 new_val ); + inline void operator = ( sc_dt::int64 new_val ); + inline void operator = ( int new_val ); + inline void operator = ( long new_val ); + inline void operator = ( short new_val ); + inline void operator = ( unsigned int new_val ); + inline void operator = ( unsigned long new_val ); + inline void operator = ( unsigned short new_val ); + template<typename T> + inline void operator = ( const sc_dt::sc_generic_base<T>& new_val ); + inline void operator = ( const sc_dt::sc_signed& new_val ); + inline void operator = ( const sc_dt::sc_unsigned& new_val ); + inline void operator = ( const sc_dt::sc_bv_base& new_val ); + inline void operator = ( const sc_dt::sc_lv_base& new_val ); + + // concatenation methods (we inherit length and gets from sc_dt::sc_biguint<W>): + + virtual inline void concat_set(sc_dt::int64 src, int low_i); + virtual inline void concat_set(const sc_dt::sc_lv_base& src, int low_i); + virtual inline void concat_set(const sc_dt::sc_signed& src, int low_i); + virtual inline void concat_set(const sc_dt::sc_unsigned& src, int low_i); + virtual inline void concat_set(sc_dt::uint64 src, int low_i); + + protected: // debugging methods: + // #### void check_port(); + void check_writer(); + + private: // Disabled operations that sc_dt::sc_biguint<W> supports: + sc_dt::sc_unsigned& operator ++ (); // prefix + const sc_dt::sc_unsigned& operator ++ (int); // postfix + sc_dt::sc_unsigned& operator -- (); // prefix + const sc_dt::sc_unsigned& operator -- (int); // postfix + sc_dt::sc_unsigned& operator += (const sc_dt::sc_signed& ); + sc_dt::sc_unsigned& operator += (const sc_dt::sc_unsigned& ); + sc_dt::sc_unsigned& operator += (sc_dt::int64 ); + sc_dt::sc_unsigned& operator += (sc_dt::uint64 ); + sc_dt::sc_unsigned& operator += (long ); + sc_dt::sc_unsigned& operator += (unsigned long ); + sc_dt::sc_unsigned& operator += (int ); + sc_dt::sc_unsigned& operator += (unsigned int ); + sc_dt::sc_unsigned& operator -= (const sc_dt::sc_signed& ); + sc_dt::sc_unsigned& operator -= (const sc_dt::sc_unsigned& ); + sc_dt::sc_unsigned& operator -= (sc_dt::int64 ); + sc_dt::sc_unsigned& operator -= (sc_dt::uint64 ); + sc_dt::sc_unsigned& operator -= (long ); + sc_dt::sc_unsigned& operator -= (unsigned long ); + sc_dt::sc_unsigned& operator -= (int ); + sc_dt::sc_unsigned& operator -= (unsigned int ); + sc_dt::sc_unsigned& operator *= (const sc_dt::sc_signed& ); + sc_dt::sc_unsigned& operator *= (const sc_dt::sc_unsigned& ); + sc_dt::sc_unsigned& operator *= (sc_dt::int64 ); + sc_dt::sc_unsigned& operator *= (sc_dt::uint64 ); + sc_dt::sc_unsigned& operator *= (long ); + sc_dt::sc_unsigned& operator *= (unsigned long ); + sc_dt::sc_unsigned& operator *= (int ); + sc_dt::sc_unsigned& operator *= (unsigned int ); + sc_dt::sc_unsigned& operator /= (const sc_dt::sc_signed& ); + sc_dt::sc_unsigned& operator /= (const sc_dt::sc_unsigned& ); + sc_dt::sc_unsigned& operator /= (sc_dt::int64 ); + sc_dt::sc_unsigned& operator /= (sc_dt::uint64 ); + sc_dt::sc_unsigned& operator /= (long ); + sc_dt::sc_unsigned& operator /= (unsigned long ); + sc_dt::sc_unsigned& operator /= (int ); + sc_dt::sc_unsigned& operator /= (unsigned int ); + sc_dt::sc_unsigned& operator %= (const sc_dt::sc_signed& ); + sc_dt::sc_unsigned& operator %= (const sc_dt::sc_unsigned& ); + sc_dt::sc_unsigned& operator %= (sc_dt::int64 ); + sc_dt::sc_unsigned& operator %= (sc_dt::uint64 ); + sc_dt::sc_unsigned& operator %= (long ); + sc_dt::sc_unsigned& operator %= (unsigned long ); + sc_dt::sc_unsigned& operator %= (int ); + sc_dt::sc_unsigned& operator %= (unsigned int ); + sc_dt::sc_unsigned& operator &= (const sc_dt::sc_signed& ); + sc_dt::sc_unsigned& operator &= (const sc_dt::sc_unsigned& ); + sc_dt::sc_unsigned& operator &= (sc_dt::int64 ); + sc_dt::sc_unsigned& operator &= (sc_dt::uint64 ); + sc_dt::sc_unsigned& operator &= (long ); + sc_dt::sc_unsigned& operator &= (unsigned long ); + sc_dt::sc_unsigned& operator &= (int ); + sc_dt::sc_unsigned& operator &= (unsigned int ); + sc_dt::sc_unsigned& operator |= (const sc_dt::sc_signed& ); + sc_dt::sc_unsigned& operator |= (const sc_dt::sc_unsigned& ); + sc_dt::sc_unsigned& operator |= (sc_dt::int64 ); + sc_dt::sc_unsigned& operator |= (sc_dt::uint64 ); + sc_dt::sc_unsigned& operator |= (long ); + sc_dt::sc_unsigned& operator |= (unsigned long ); + sc_dt::sc_unsigned& operator |= (int ); + sc_dt::sc_unsigned& operator |= (unsigned int ); + sc_dt::sc_unsigned& operator ^= (const sc_dt::sc_signed& ); + sc_dt::sc_unsigned& operator ^= (const sc_dt::sc_unsigned& ); + sc_dt::sc_unsigned& operator ^= (sc_dt::int64 ); + sc_dt::sc_unsigned& operator ^= (sc_dt::uint64 ); + sc_dt::sc_unsigned& operator ^= (long ); + sc_dt::sc_unsigned& operator ^= (unsigned long ); + sc_dt::sc_unsigned& operator ^= (int ); + sc_dt::sc_unsigned& operator ^= (unsigned int ); + + protected: + mutable sc_event* m_changed_event_p; // Value changed event this object. + sc_dt::uint64 m_event_delta; // Delta cycle of last event. + sc_dt::sc_unsigned m_new_val; // New value for this object instance. + sc_port_base* m_output_p; // Single write port verify field. + sc_process_b* m_writer_p; // Single writer verify field. +}; + + +SC_TEMPLATE // Return true if a changed event happened in the last delta cycle. +inline bool sc_signal<sc_dt::sc_biguint<W> >::base_event() const +{ + return simcontext()->delta_count() == m_event_delta + 1; +} + + +SC_TEMPLATE // Return this object's sc_dt::sc_biguint<W> object instance. +inline const sc_dt::sc_biguint<W>& sc_signal<sc_dt::sc_biguint<W> >::base_read() const +{ + return *this; +} + + +SC_TEMPLATE // Return the value changed event, allocating it if necessary. +inline const sc_event& sc_signal<sc_dt::sc_biguint<W> >::base_value_changed_event() const +{ + if ( !m_changed_event_p ) m_changed_event_p = new sc_event; + return *m_changed_event_p; +} + + +SC_TEMPLATE // Write a const sc_dt::sc_signed& value to this object instance. +inline void sc_signal<sc_dt::sc_biguint<W> >::base_write( const sc_dt::sc_signed& value ) +{ +# if defined(DEBUG_SYSTEMC) + check_writer(); +# endif + m_new_val = value; + request_update(); +} + +SC_TEMPLATE // Write a const sc_dt::sc_unsigned& value to this object instance. +inline void sc_signal<sc_dt::sc_biguint<W> >::base_write( const sc_dt::sc_unsigned& value ) +{ +# if defined(DEBUG_SYSTEMC) + check_writer(); +# endif + m_new_val = value; + request_update(); +} + +SC_TEMPLATE // Write a sc_dt::int64 value to this object instance. +inline void sc_signal<sc_dt::sc_biguint<W> >::base_write( sc_dt::int64 value ) +{ +# if defined(DEBUG_SYSTEMC) + check_writer(); +# endif + m_new_val = value; + request_update(); +} + + +SC_TEMPLATE // Write a sc_dt::uint64 value to this object instance. +inline void sc_signal<sc_dt::sc_biguint<W> >::base_write( sc_dt::uint64 value ) +{ +# if defined(DEBUG_SYSTEMC) + check_writer(); +# endif + m_new_val = value; + request_update(); +} + + +//------------------------------------------------------------------------------ +//"sc_signal<sc_dt::sc_biguint<W> >::check_writer" +// +// This method checks to see if there is more than one writer for this +// object instance by keeping track of the process performing the write. +//------------------------------------------------------------------------------ +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_biguint<W> >::check_writer() +{ + sc_process_b* writer_p = sc_get_current_process_b(); + if( m_writer_p == 0 ) + { + m_writer_p = writer_p; + } + else if( m_writer_p != writer_p ) + { + sc_signal_invalid_writer( name(), kind(), + m_writer_p->name(), writer_p->name() ); + } +} + + +//------------------------------------------------------------------------------ +//"sc_signal<sc_dt::sc_biguint<W> >::concat_set" +// +// These virtual methods allow value assignments to this object instance +// from various sources. The position within the supplied source of the +// low order bit for this object instance's value is low_i. +// src = source value. +// low_i = bit within src to serve as low order bit of this object +// instance's value. +//------------------------------------------------------------------------------ +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_biguint<W> >::concat_set(sc_dt::int64 src, int low_i) +{ + if ( low_i < 64 ) + { + base_write(src >> low_i); + } + else + { + base_write( (sc_dt::int64)((src < 0 ) ? -1 : 0 )); + } +} + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_biguint<W> >::concat_set( + const sc_dt::sc_lv_base& src, int low_i) +{ + sc_dt::sc_unsigned tmp(src.length()); + tmp = src >> low_i; + base_write( tmp ); +} + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_biguint<W> >::concat_set( + const sc_dt::sc_signed& src, int low_i) +{ + base_write( (src >> low_i) ); +} + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_biguint<W> >::concat_set( + const sc_dt::sc_unsigned& src, int low_i) +{ + base_write( (src >> low_i) ); +} + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_biguint<W> >::concat_set(sc_dt::uint64 src, int low_i) +{ + base_write( (sc_dt::uint64)(( low_i < 64 ) ? src >> low_i : 0)); +} + + + +SC_TEMPLATE // Return the default event for this object instance. +inline const sc_event& sc_signal<sc_dt::sc_biguint<W> >::default_event() const + { return base_value_changed_event(); } + + +SC_TEMPLATE // Return true if a changed event happened in the last delta cycle. +inline bool sc_signal<sc_dt::sc_biguint<W> >::event() const + { return base_event(); } + + +SC_TEMPLATE // Return a reference to the value of this object instance. +inline const sc_dt::sc_biguint<W>& sc_signal<sc_dt::sc_biguint<W> >::get_data_ref() const + { return *this; } + + +SC_TEMPLATE // Return a pointer to this object instance. +inline sc_signal<sc_dt::sc_biguint<W> >& sc_signal<sc_dt::sc_biguint<W> >::get_signal() + { return *this; } + + +SC_TEMPLATE // Return a kind value of "sc_signal". +inline const char* sc_signal<sc_dt::sc_biguint<W> >::kind() const +{ + return "sc_signal"; +} + + +//------------------------------------------------------------------------------ +//"sc_signal_uint::operator () +// +// This operator returns a part selection of this object instance. +// left = left-hand bit of the selection. +// right = right-hand bit of the selection. +//------------------------------------------------------------------------------ +SC_TEMPLATE +inline sc_unsigned_sigref& sc_signal<sc_dt::sc_biguint<W> >::operator () (int left, int right) +{ + sc_unsigned_sigref* result_p; // Value to return. + + result_p = sc_unsigned_sigref::m_pool.allocate(); + result_p->initialize(this, left, right); + return *result_p; +} + + +//------------------------------------------------------------------------------ +//"sc_signal_uint::operator []" +// +// This operator returns a bit selection of this object instance. +// i = bit to be selected. +//------------------------------------------------------------------------------ +SC_TEMPLATE +inline sc_unsigned_sigref& sc_signal<sc_dt::sc_biguint<W> >::operator [] ( int bit ) +{ + return operator () (bit,bit); +} + + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_biguint<W> >::operator = ( const this_type& new_val ) + { base_write( new_val ); } + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_biguint<W> >::operator = ( const char* new_val ) + { sc_dt::sc_biguint<W> tmp = new_val; m_new_val = tmp; request_update(); } + + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_biguint<W> >::operator = ( const sc_dt::sc_unsigned& new_val ) + { base_write(new_val); } + + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_biguint<W> >::operator = ( sc_dt::uint64 new_val ) + { base_write(new_val); } + + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_biguint<W> >::operator = ( sc_dt::int64 new_val ) + { base_write(new_val); } + + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_biguint<W> >::operator = ( int new_val ) + { base_write((sc_dt::int64)new_val); } + + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_biguint<W> >::operator = ( long new_val ) + { base_write((sc_dt::int64)new_val); } + + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_biguint<W> >::operator = ( short new_val ) + { base_write((sc_dt::int64)new_val); } + + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_biguint<W> >::operator = ( unsigned int new_val ) + { base_write((sc_dt::int64)new_val); } + + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_biguint<W> >::operator = ( unsigned long new_val ) + { base_write((sc_dt::int64)new_val); } + + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_biguint<W> >::operator = ( unsigned short new_val ) + { base_write((sc_dt::int64)new_val); } + + +SC_TEMPLATE +template<typename T> +inline void sc_signal<sc_dt::sc_biguint<W> >::operator = ( + const sc_dt::sc_generic_base<T>& new_val ) +{ + sc_dt::sc_unsigned temp(W); + new_val->to_sc_unsigned(temp); + base_write(temp); +} + + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_biguint<W> >::operator = ( const sc_dt::sc_signed& new_val ) + { base_write(new_val); } + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_biguint<W> >::operator = ( const sc_dt::sc_bv_base& new_val ) + { base_write( (sc_dt::sc_biguint<W>)new_val ); } + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_biguint<W> >::operator = ( const sc_dt::sc_lv_base& new_val ) + { base_write( (sc_dt::sc_biguint<W>)new_val ); } + + +SC_TEMPLATE +inline sc_dt::sc_unsigned* sc_signal<sc_dt::sc_biguint<W> >::part_read_target() + { return this; } + + +SC_TEMPLATE +inline const sc_dt::sc_biguint<W>& sc_signal<sc_dt::sc_biguint<W> >::read() const + { return *this; } + + +SC_TEMPLATE // Read a portion of a value. +inline sc_dt::sc_unsigned sc_signal<sc_dt::sc_biguint<W> >::read_part( + int left, int right ) const +{ + sc_dt::sc_unsigned tmp(left-right+1); + tmp = (*(const sc_dt::sc_biguint<W>*)this)(left,right); + return tmp; +} + +SC_TEMPLATE +inline void sc_signal<sc_dt::sc_biguint<W> >::register_port( + sc_port_base& port_, const char* if_typename_ ) +{ +# ifdef DEBUG_SYSTEMC + std::string nm( if_typename_ ); + if( nm == typeid( sc_signal_inout_if<sc_dt::sc_biguint<W> > ).name() ) + { + if( m_output_p != 0 ) + { + sc_signal_invalid_writer( name(), kind(), + m_output_p->name(), port_.name() ); + } + m_output_p = &port_; + } +# else + if ( &port_ && if_typename_ ) {} // Silence unused args warning. +# endif +} + + +SC_TEMPLATE // Autogenerated name object instance constructor. +inline sc_signal<sc_dt::sc_biguint<W> >::sc_signal() : + sc_prim_channel(sc_gen_unique_name( "signal" )), + m_changed_event_p(0), + m_new_val(W), + m_output_p(0), + m_writer_p(0) +{ } + + +SC_TEMPLATE // Explicitly named object instance constructor. +inline sc_signal<sc_dt::sc_biguint<W> >::sc_signal(const char* name_) : + sc_prim_channel(name_), + m_changed_event_p(0), + m_new_val(W), + m_output_p(0), + m_writer_p(0) +{ } + + +SC_TEMPLATE // Object instance destructor. +inline sc_signal<sc_dt::sc_biguint<W> >::~sc_signal() +{ + if ( m_changed_event_p ) delete m_changed_event_p; +} + + +SC_TEMPLATE // Update the current value from new value. +inline void sc_signal<sc_dt::sc_biguint<W> >::update() +{ + if ( m_changed_event_p ) + { + if ( m_new_val != *this ) + { + m_changed_event_p->notify_delayed(); + m_event_delta = simcontext()->delta_count(); + } + } + sc_dt::sc_unsigned::operator = (m_new_val); +} + + +SC_TEMPLATE // Return the value changed event. +inline const sc_event& sc_signal<sc_dt::sc_biguint<W> >::value_changed_event() const + { return base_value_changed_event(); } + + +SC_TEMPLATE // Write a sc_in<sc_dt::sc_biguint<W> > value to this object instance. +inline void sc_signal<sc_dt::sc_biguint<W> >::write( + const sc_in<sc_dt::sc_biguint<W> >& value ) + { base_write( value ); } + + +SC_TEMPLATE // Write a sc_inout<sc_dt::sc_biguint<W> > value to this object instance. +inline void sc_signal<sc_dt::sc_biguint<W> >::write( + const sc_inout<sc_dt::sc_biguint<W> >& value ) +{ base_write( value ); } + + +SC_TEMPLATE // Write a sc_dt::sc_biguint<W> value to this object instance. +inline void sc_signal<sc_dt::sc_biguint<W> >::write( const sc_dt::sc_biguint<W>& value ) + { base_write( value); } + + +SC_TEMPLATE // Write a portion of a value. If this is the first write in + // a delta cycle we copy the existing value before setting the bits. +inline void sc_signal<sc_dt::sc_biguint<W> >::write_part(sc_dt::int64 v, int left, int right) +{ + m_new_val(left, right) = v; + request_update(); +} + + +SC_TEMPLATE // Select a portion of a value. +inline sc_unsigned_sigref& sc_signal<sc_dt::sc_biguint<W> >::select_part( + int left, int right) +{ + sc_unsigned_sigref* result_p = sc_unsigned_sigref::m_pool.allocate(); + result_p->initialize(dynamic_cast<sc_unsigned_part_if*>(this), left, right); + return *result_p; +} + + +SC_TEMPLATE // Write a portion of a value. If this is the first write in + // a delta cycle we copy the existing value before setting the bits. +inline void sc_signal<sc_dt::sc_biguint<W> >::write_part(sc_dt::uint64 v, int left, int right) +{ + m_new_val(left, right) = v; + request_update(); +} + + +SC_TEMPLATE // Write a portion of a value. If this is the first write in + // a delta cycle we copy the existing value before setting the bits. +inline void sc_signal<sc_dt::sc_biguint<W> >::write_part( + const sc_dt::sc_signed& v, int left, int right ) +{ + m_new_val(left, right) = v; + request_update(); +} + + +SC_TEMPLATE // Write a portion of a value. If this is the first write in + // a delta cycle we copy the existing value before setting the bits. +inline void sc_signal<sc_dt::sc_biguint<W> >::write_part( + const sc_dt::sc_unsigned& v, int left, int right ) +{ + m_new_val(left, right) = v; + request_update(); +} + + +//============================================================================== +// CLASS sc_in<sc_dt::sc_biguint<W> > +// +// This class implements an input port whose target acts like an sc_dt::sc_biguint<W> data +// value. This class is a specialization of the generic sc_in class to +// implement tailored support for the sc_dt::sc_biguint<W> class. +//============================================================================== +SC_TEMPLATE +class sc_in<sc_dt::sc_biguint<W> > : + public sc_port<sc_signal_in_if<sc_dt::sc_biguint<W> >, 1, + SC_ONE_OR_MORE_BOUND>, + public sc_dt::sc_value_base +{ + public: + + // typedefs + + typedef sc_dt::sc_biguint<W> data_type; + typedef sc_signal_in_if<sc_dt::sc_biguint<W> > if_type; + typedef sc_port<if_type,1,SC_ONE_OR_MORE_BOUND> base_type; + typedef sc_in<sc_dt::sc_biguint<W> > this_type; + + typedef if_type in_if_type; + typedef base_type in_port_type; + typedef sc_signal_inout_if<sc_dt::sc_biguint<W> > inout_if_type; + typedef sc_inout<sc_dt::sc_biguint<W> > inout_port_type; + + public: + + // bind methods and operators: + + void bind( const in_if_type& interface_ ) + { sc_port_base::bind( const_cast<in_if_type&>( interface_) );} + void operator () ( const in_if_type& interface_ ) + { sc_port_base::bind( const_cast<in_if_type&>( interface_) );} + void bind( in_port_type& parent_ ) + { sc_port_base::bind(parent_);} + void operator () ( in_port_type& parent_ ) + { sc_port_base::bind(parent_);} + void bind( inout_port_type& parent_ ) + { sc_port_base::bind(parent_);} + void operator () ( inout_port_type& parent_ ) + { sc_port_base::bind(parent_);} + + protected: + // called by pbind (for internal use only) + virtual inline int vbind( sc_interface& interface_ ) + { + return sc_port_b<if_type>::vbind( interface_ ); + } + virtual inline int vbind( sc_port_base& parent_ ) + { + in_port_type* in_parent = dynamic_cast<in_port_type*>( &parent_ ); + if( in_parent != 0 ) { + sc_port_base::bind( *in_parent ); + return 0; + } + inout_port_type* inout_parent = dynamic_cast<inout_port_type*>( &parent_ ); + if( inout_parent != 0 ) { + sc_port_base::bind( *inout_parent ); + return 0; + } + // type mismatch + return 2; + } + + + // constructors + + public: + sc_in() + : base_type(), m_traces( 0 ) + {} + + explicit sc_in( const char* name_ ) + : base_type( name_ ), m_traces( 0 ) + {} + + explicit sc_in( const in_if_type& interface_ ) + : base_type( const_cast<in_if_type&>( interface_ ) ), m_traces( 0 ) + {} + + sc_in( const char* name_, const in_if_type& interface_ ) + : base_type( name_, const_cast<in_if_type&>( interface_ ) ), m_traces( 0 ) + {} + + explicit sc_in( in_port_type& parent_ ) + : base_type( parent_ ), m_traces( 0 ) + {} + + sc_in( const char* name_, in_port_type& parent_ ) + : base_type( name_, parent_ ), m_traces( 0 ) + {} + + explicit sc_in( inout_port_type& parent_ ) + : base_type(), m_traces( 0 ) + { sc_port_base::bind( parent_ ); } + + sc_in( const char* name_, inout_port_type& parent_ ) + : base_type( name_ ), m_traces( 0 ) + { sc_port_base::bind( parent_ ); } + + sc_in( this_type& parent_ ) + : base_type( parent_ ), m_traces( 0 ) + {} + + sc_in( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ), m_traces( 0 ) + {} + + + // destructor + + virtual inline ~sc_in() + { + remove_traces(); + } + + // bit and part selection + + sc_dt::sc_unsigned_bitref_r operator [] ( int i ) const + { return (*this)->read()[i]; } + sc_dt::sc_unsigned_bitref_r bit( int i ) const + { return (*this)->read()[i]; } + sc_dt::sc_unsigned_subref_r operator () ( int left, int right ) const + { return (*this)->read()(left,right); } + sc_dt::sc_unsigned_subref_r range( int left, int right ) const + { return (*this)->read()(left,right); } + + + // interface access shortcut methods + + // get the default event + + const sc_event& default_event() const + { return (*this)->value_changed_event(); } + + + // get the value changed event + + const sc_event& value_changed_event() const + { return (*this)->value_changed_event(); } + + + // read the current value + + const sc_dt::sc_biguint<W>& read() const + { return (*this)->read(); } + + operator const sc_dt::sc_biguint<W>& () const + { return (*this)->read(); } + + // was there a value changed event? + + bool event() const + { return (*this)->event(); } + + + // (other) event finder method(s) + + sc_event_finder& value_changed() const + { + return *new sc_event_finder_t<in_if_type>( + *this, &in_if_type::value_changed_event ); + } + + + + // reduction methods: + + inline bool and_reduce() const + { return (*this)->read().and_reduce(); } + inline bool nand_reduce() const + { return (*this)->read().nand_reduce(); } + inline bool nor_reduce() const + { return (*this)->read().nor_reduce(); } + inline bool or_reduce() const + { return (*this)->read().or_reduce(); } + inline bool xnor_reduce() const + { return (*this)->read().xnor_reduce(); } + inline bool xor_reduce() const + { return (*this)->read().xor_reduce(); } + + + // called when elaboration is done + /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ + /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ + + virtual inline void end_of_elaboration() + { + if( m_traces != 0 ) { + for( unsigned int i = 0; i < m_traces->size(); ++ i ) { + sc_trace_params* p = (*m_traces)[i]; + sc_trace( p->tf, read(), p->name ); + } + remove_traces(); + } + } + + virtual inline const char* kind() const + { return "sc_in"; } + + + // called by sc_trace + void add_trace( sc_trace_file* tf_, const std::string& name_ ) const + { + if( tf_ != 0 ) { + if( m_traces == 0 ) { + m_traces = new sc_trace_params_vec; + } + m_traces->push_back( new sc_trace_params( tf_, name_ ) ); + } + } + + + // concatenation methods + + virtual inline int concat_length(bool* xz_present_p) const + { return (*this)->read().concat_length( xz_present_p ); } + virtual inline sc_dt::uint64 concat_get_uint64() const + { return (*this)->read().concat_get_uint64(); } + virtual inline bool concat_get_ctrl( sc_dt::sc_digit* dst_p, int low_i ) const + { return (*this)->read().concat_get_ctrl(dst_p, low_i); } + virtual inline bool concat_get_data( sc_dt::sc_digit* dst_p, int low_i ) const + { return (*this)->read().concat_get_data(dst_p, low_i); } + + protected: + void remove_traces() const + { + if( m_traces != 0 ) { + for( int i = m_traces->size() - 1; i >= 0; -- i ) { + delete (*m_traces)[i]; + } + delete m_traces; + m_traces = 0; + } + } + + mutable sc_trace_params_vec* m_traces; + + + private: + + // disabled + sc_in( const sc_in<sc_dt::sc_biguint<W> >& ); + sc_in<sc_dt::sc_biguint<W> >& operator = ( const sc_in<sc_dt::sc_biguint<W> >& ); + +#ifdef __GNUC__ + // Needed to circumvent a problem in the g++-2.95.2 compiler: + // This unused variable forces the compiler to instantiate + // an object of T template so an implicit conversion from + // read() to a C++ intrinsic data type will work. + static data_type dummy; +#endif + +}; + + + +SC_TEMPLATE +inline std::ostream& operator << ( + std::ostream& os, const sc_in<sc_dt::sc_biguint<W> >& a ) +{ + a.read().print( os ); + return os; +} + + +//============================================================================== +// CLASS sc_inout<sc_dt::sc_biguint<W> > +// +// This class implements an input/output port whose target acts like an +// sc_dt::sc_biguint<W> data value. It is derived from the sc_unsigned_in. This class is a +// specialization of the generic sc_inout class to implement tailored support +// for the sc_dt::sc_biguint<W> class. +//============================================================================== +SC_TEMPLATE +class sc_inout<sc_dt::sc_biguint<W> > : + public sc_port<sc_signal_inout_if<sc_dt::sc_biguint<W> >, 1, + SC_ONE_OR_MORE_BOUND>, + public sc_dt::sc_value_base +{ + public: + + // typedefs + + typedef sc_dt::sc_biguint<W> data_type; + typedef sc_signal_inout_if<sc_dt::sc_biguint<W> > if_type; + typedef sc_port<if_type,1,SC_ONE_OR_MORE_BOUND> base_type; + typedef sc_inout<sc_dt::sc_biguint<W> > this_type; + + typedef if_type inout_if_type; + typedef base_type inout_port_type; + + public: + + // bind methods and operators: + + void bind( const inout_if_type& interface_ ) + { sc_port_base::bind( const_cast<inout_if_type&>( interface_) ); } + void operator () ( const inout_if_type& interface_ ) + { sc_port_base::bind( const_cast<inout_if_type&>( interface_) ); } + void bind( inout_port_type& parent_ ) + { sc_port_base::bind(parent_); } + void operator () ( inout_port_type& parent_ ) + { sc_port_base::bind(parent_); } + + protected: + // called by pbind (for internal use only) + virtual inline int vbind( sc_interface& interface_ ) + { + return sc_port_b<if_type>::vbind( interface_ ); + } + virtual inline int vbind( sc_port_base& parent_ ) + { + inout_port_type* inout_parent = dynamic_cast<inout_port_type*>( &parent_ ); + if( inout_parent != 0 ) { + sc_port_base::bind( *inout_parent ); + return 0; + } + // type mismatch + return 2; + } + + + // constructors + + public: + sc_inout() + : base_type(), m_init_val_p(0), m_traces( 0 ) + {} + + explicit sc_inout( const char* name_ ) + : base_type( name_ ), m_init_val_p(0), m_traces( 0 ) + {} + + explicit sc_inout( inout_if_type& interface_ ) + : base_type( interface_ ), m_init_val_p(0), m_traces( 0 ) + {} + + sc_inout( const char* name_, inout_if_type& interface_ ) + : base_type( name_, interface_ ), m_init_val_p(0), m_traces( 0 ) + {} + + explicit sc_inout( inout_port_type& parent_ ) + : base_type( parent_ ), m_init_val_p(0), m_traces( 0 ) + {} + + sc_inout( const char* name_, inout_port_type& parent_ ) + : base_type( name_, parent_ ), m_init_val_p(0), m_traces( 0 ) + {} + + sc_inout( this_type& parent_ ) + : base_type( parent_ ), m_init_val_p(0), m_traces( 0 ) + {} + + sc_inout( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ), m_init_val_p(0), m_traces( 0 ) + {} + + + // destructor + + virtual inline ~sc_inout() + { + remove_traces(); + } + + // bit and part selection + + sc_dt::sc_unsigned_bitref_r operator [] ( int i ) const + { return (*this)->read()[i]; } + sc_dt::sc_unsigned_bitref_r bit( int i ) const + { return (*this)->read()[i]; } + sc_unsigned_sigref& operator [] ( int i ) + { return (*this)->select_part(i,i); } + sc_unsigned_sigref& bit( int i ) + { return (*this)->select_part(i,i); } + sc_dt::sc_unsigned_subref_r operator () ( int left, int right ) const + { return (*this)->read()(left,right); } + sc_dt::sc_unsigned_subref_r range( int left, int right ) const + { return (*this)->read()(left,right); } + sc_unsigned_sigref& operator () ( int left, int right ) + { return (*this)->select_part(left,right); } + sc_unsigned_sigref& range( int left, int right ) + { return (*this)->select_part(left,right); } + + + // interface access shortcut methods + + // get the default event + + const sc_event& default_event() const + { return (*this)->value_changed_event(); } + + + // get the value changed event + + const sc_event& value_changed_event() const + { return (*this)->value_changed_event(); } + + + // read the current value + + const sc_dt::sc_biguint<W>& read() const + { return (*this)->read(); } + + operator const sc_dt::sc_biguint<W>& () const + { return (*this)->read(); } + + // was there a value changed event? + + bool event() const + { return (*this)->event(); } + + + // (other) event finder method(s) + + sc_event_finder& value_changed() const + { + return *new sc_event_finder_t<inout_if_type>( + *this, &inout_if_type::value_changed_event ); + } + + + + // reduction methods: + + inline bool and_reduce() const + { return (*this)->read().and_reduce(); } + inline bool nand_reduce() const + { return (*this)->read().nand_reduce(); } + inline bool nor_reduce() const + { return (*this)->read().nor_reduce(); } + inline bool or_reduce() const + { return (*this)->read().or_reduce(); } + inline bool xnor_reduce() const + { return (*this)->read().xnor_reduce(); } + inline bool xor_reduce() const + { return (*this)->read().xor_reduce(); } + + + // called when elaboration is done + /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ + /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ + + virtual inline void end_of_elaboration() + { + if( m_init_val_p != 0 ) { + (*this)->write( *m_init_val_p ); + delete m_init_val_p; + m_init_val_p = 0; + } + if( m_traces != 0 ) { + for( unsigned int i = 0; i < m_traces->size(); ++ i ) { + sc_trace_params* p = (*m_traces)[i]; + sc_trace( p->tf, read(), p->name ); + } + remove_traces(); + } + } + + virtual inline const char* kind() const + { return "sc_inout"; } + + // value initialization + + inline void initialize( const sc_dt::sc_biguint<W>& value_ ) + { + inout_if_type* iface = dynamic_cast<inout_if_type*>( this->get_interface() ); + if( iface != 0 ) { + iface->write( value_ ); + } else { + if( m_init_val_p == 0 ) { + m_init_val_p = new sc_dt::sc_biguint<W>; + } + *m_init_val_p = value_; + } + } + + + // called by sc_trace + void add_trace( sc_trace_file* tf_, const std::string& name_ ) const + { + if( tf_ != 0 ) { + if( m_traces == 0 ) { + m_traces = new sc_trace_params_vec; + } + m_traces->push_back( new sc_trace_params( tf_, name_ ) ); + } + } + + + // concatenation methods + + virtual inline int concat_length(bool* xz_present_p) const + { return (*this)->read().concat_length( xz_present_p ); } + virtual inline sc_dt::uint64 concat_get_uint64() const + { return (*this)->read().concat_get_uint64(); } + virtual inline bool concat_get_ctrl( sc_dt::sc_digit* dst_p, int low_i ) const + { return (*this)->read().concat_get_ctrl(dst_p, low_i); } + virtual inline bool concat_get_data( sc_dt::sc_digit* dst_p, int low_i ) const + { return (*this)->read().concat_get_data(dst_p, low_i); } + virtual inline void concat_set(sc_dt::int64 src, int low_i) + { *this = (src >> ((low_i < 64) ? low_i : 63)); } +#if 0 // #### + virtual inline void concat_set(const sc_dt::sc_lv_base& src, int low_i) + { *this = src >> low_i; } +#endif // 0 #### + virtual inline void concat_set(const sc_dt::sc_signed& src, int low_i) + { *this = (src >> low_i); } + virtual inline void concat_set(const sc_dt::sc_unsigned& src, int low_i) + { *this = (src >> low_i); } + virtual inline void concat_set(sc_dt::uint64 src, int low_i) + { *this = (low_i < 64 ) ? src >> low_i : (sc_dt::uint64)0; } + + // assignment operators: + + public: + inline void operator = ( const this_type& new_val ) + { (*this)->write( (const sc_dt::sc_unsigned&)new_val ); } + inline void operator = ( const char* new_val ) + { sc_dt::sc_unsigned aa(W); aa = new_val; (*this)->write( aa ); } + inline void operator = ( sc_dt::uint64 new_val ) + { (*this)->write(new_val); } + inline void operator = ( sc_dt::int64 new_val ) + { (*this)->write((sc_dt::int64)new_val); } + inline void operator = ( int new_val ) + { (*this)->write((sc_dt::int64)new_val); } + inline void operator = ( long new_val ) + { (*this)->write((sc_dt::int64)new_val); } + inline void operator = ( short new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( unsigned int new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( unsigned long new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( unsigned short new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + template<typename T> + inline void operator = ( const sc_dt::sc_generic_base<T>& new_val ) + { + sc_dt::sc_unsigned temp(W); + new_val->to_sc_unsigned(temp); + (*this)->write(temp); + } + inline void operator = ( const sc_dt::sc_signed& new_val ) + { (*this)->write(new_val); } + inline void operator = ( const sc_dt::sc_unsigned& new_val ) + { (*this)->write(new_val); } + inline void operator = ( const sc_dt::sc_bv_base& new_val ) + { (*this)->write((sc_dt::sc_biguint<W>)new_val); } + inline void operator = ( const sc_dt::sc_lv_base& new_val ) + { (*this)->write((sc_dt::sc_biguint<W>)new_val); } + + inline void write( const sc_in<sc_dt::sc_biguint<W> >& new_val ) + { (*this)->write( new_val.read() ); } + inline void write( const sc_inout<sc_dt::sc_biguint<W> >& new_val ) + { (*this)->write( new_val.read() ); } + inline void write( const sc_dt::sc_biguint<W>& new_val ) + { (*this)->write( new_val ); } + + protected: + void remove_traces() const + { + if( m_traces != 0 ) { + for( int i = m_traces->size() - 1; i >= 0; -- i ) { + delete (*m_traces)[i]; + } + delete m_traces; + m_traces = 0; + } + } + + sc_dt::sc_biguint<W>* m_init_val_p; + mutable sc_trace_params_vec* m_traces; + + + private: + + // disabled + sc_inout( const sc_inout<sc_dt::sc_biguint<W> >& ); + +#ifdef __GNUC__ + // Needed to circumvent a problem in the g++-2.95.2 compiler: + // This unused variable forces the compiler to instantiate + // an object of T template so an implicit conversion from + // read() to a C++ intrinsic data type will work. + static data_type dummy; +#endif + +}; + + + +SC_TEMPLATE +inline std::ostream& operator << ( + std::ostream& os, const sc_inout<sc_dt::sc_biguint<W> >& a ) +{ + a.read().print( os ); + return os; +} + + +//============================================================================== +// CLASS sc_out<sc_dt::sc_biguint<W> > +// +// This class implements an output port whose target acts like an +// sc_dt::sc_biguint<W> data value. This class is a derivation of sc_inout, since +// output ports are really no different from input/output ports. +//============================================================================== +SC_TEMPLATE +class sc_out<sc_dt::sc_biguint<W> > : public sc_inout<sc_dt::sc_biguint<W> > +{ + public: + + // typedefs + + typedef sc_dt::sc_biguint<W> data_type; + + typedef sc_out<data_type> this_type; + typedef sc_inout<data_type> base_type; + + typedef typename base_type::inout_if_type inout_if_type; + typedef typename base_type::inout_port_type inout_port_type; + + // constructors + + sc_out() + : base_type() + {} + + explicit sc_out( const char* name_ ) + : base_type( name_ ) + {} + + explicit sc_out( inout_if_type& interface_ ) + : base_type( interface_ ) + {} + + sc_out( const char* name_, inout_if_type& interface_ ) + : base_type( name_, interface_ ) + {} + + explicit sc_out( inout_port_type& parent_ ) + : base_type( parent_ ) + {} + + sc_out( const char* name_, inout_port_type& parent_ ) + : base_type( name_, parent_ ) + {} + + sc_out( this_type& parent_ ) + : base_type( parent_ ) + {} + + sc_out( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ) + {} + + + // destructor (does nothing) + + virtual inline ~sc_out() + {} + + + // assignment operators: + + public: + inline void operator = ( const this_type& new_val ) + { (*this)->write( (const sc_dt::sc_unsigned&)new_val ); } + inline void operator = ( const char* new_val ) + { sc_dt::sc_unsigned aa(W); aa = new_val; (*this)->write( aa ); } + inline void operator = ( sc_dt::uint64 new_val ) + { (*this)->write(new_val); } + inline void operator = ( sc_dt::int64 new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( int new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( long new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( short new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( unsigned int new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( unsigned long new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + inline void operator = ( unsigned short new_val ) + { (*this)->write((sc_dt::uint64)new_val); } + template<typename T> + inline void operator = ( const sc_dt::sc_generic_base<T>& new_val ) + { + sc_dt::sc_unsigned temp(W); + new_val->to_sc_unsigned(temp); + (*this)->write(temp); + } + inline void operator = ( const sc_dt::sc_signed& new_val ) + { (*this)->write(new_val); } + inline void operator = ( const sc_dt::sc_unsigned& new_val ) + { (*this)->write(new_val); } + inline void operator = ( const sc_dt::sc_bv_base& new_val ) + { (*this)->write((sc_dt::sc_biguint<W>)new_val); } + inline void operator = ( const sc_dt::sc_lv_base& new_val ) + { (*this)->write((sc_dt::sc_biguint<W>)new_val); } + + private: + + // disabled + sc_out( const this_type& ); +}; + + + +//------------------------------------------------------------------------------ +//"sc_unsigned_sigref::initialize" +// +// This method initializes an object instance from the supplied arguments. +// if_p -> target of this selection. +// left_ = left-most bit in selection. +// right_ = right-most bit in selection. +//------------------------------------------------------------------------------ +inline void sc_unsigned_sigref::initialize( + sc_unsigned_part_if* if_p, int left_, int right_ ) +{ + m_if_p = if_p; + m_left = left_; + m_right = right_; + m_obj_p = if_p->part_read_target(); +} + + +//------------------------------------------------------------------------------ +//"sc_unsigned_sigref::operator =" +// +// These operators assign a value to the bits associated with this object +// instance within this object instance's target signal. +//------------------------------------------------------------------------------ +inline void sc_unsigned_sigref::operator = ( sc_dt::uint64 v ) +{ + m_if_p->write_part( v, m_left, m_right ); +} + +inline void sc_unsigned_sigref::operator = ( const char* v ) +{ + sc_dt::sc_unsigned tmp(length()); + tmp = v; + *this = tmp; +} + +inline void sc_unsigned_sigref:: operator = ( sc_dt::int64 v ) +{ + *this = (sc_dt::uint64)v; +} + +inline void sc_unsigned_sigref:: operator = ( int v ) +{ + *this = (sc_dt::uint64)v; +} + +inline void sc_unsigned_sigref:: operator = ( long v ) +{ + *this = (sc_dt::uint64)v; +} + +inline void sc_unsigned_sigref:: operator = ( unsigned int v ) +{ + *this = (sc_dt::uint64)v; +} + +inline void sc_unsigned_sigref:: operator = ( unsigned long v ) +{ + *this = (sc_dt::uint64)v; +} + +void sc_unsigned_sigref::operator = ( const sc_unsigned_sigref& v ) +{ + *this = (sc_dt::sc_unsigned)v; +} + + +inline void sc_unsigned_sigref:: operator = ( const sc_dt::sc_signed& v ) +{ + m_if_p->write_part( v, m_left, m_right ); +} + +inline void sc_unsigned_sigref:: operator = ( const sc_dt::sc_unsigned& v ) +{ + m_if_p->write_part( v, m_left, m_right ); +} + +template<typename T> +inline void sc_unsigned_sigref:: operator = ( + const sc_dt::sc_generic_base<T>& v ) +{ + sc_dt::sc_unsigned temp(m_left-m_right+1); + v->to_sc_unsigned(temp); + m_if_p->write_part( temp, m_left, m_right ); +} + +#undef SC_TEMPLATE +} // namespace sc_core +#endif // !defined(SC_SIGNAL_UNSIGNED_H) + +namespace sc_core { + +extern +void +sc_signal_invalid_writer( const char* name, + const char* kind, + const char* first_writer, + const char* second_writer ); + +//------------------------------------------------------------------------------ +// POOL OF TEMPORARY INSTANCES OF sc_unsigned_sigref +// +// This allows use to pass const references for part and bit selections +// on sc_signal_signed object instances. +//------------------------------------------------------------------------------ +sc_vpool<sc_unsigned_sigref> sc_unsigned_sigref::m_pool(8); + + +//------------------------------------------------------------------------------ +//"sc_unsigned_part_if::default methods" +// +// These versions just produce errors if they are not overloaded but used. +//------------------------------------------------------------------------------ +sc_dt::sc_unsigned* sc_unsigned_part_if::part_read_target() +{ + SC_REPORT_ERROR( "attempted specalized signal operation on " + "non-specialized signal", "int" ); + return 0; +} +sc_dt::sc_unsigned sc_unsigned_part_if::read_part( int /*left*/, int /*right*/ ) const +{ + SC_REPORT_ERROR( "attempted specalized signal operation on " + "non-specialized signal", "int" ); + return sc_dt::sc_unsigned(1); +} +sc_unsigned_sigref& sc_unsigned_part_if::select_part(int /*left*/, int /*right*/) +{ + SC_REPORT_ERROR( "attempted specalized signal operation on " + "non-specialized signal", "int" ); + return *(sc_unsigned_sigref*)0; +} +void sc_unsigned_part_if::write_part( sc_dt::int64 v, int /*left*/, int /*right*/ ) +{ + SC_REPORT_ERROR( "attempted specalized signal operation on " + "non-specialized signal", "int" ); +} +void sc_unsigned_part_if::write_part( sc_dt::uint64 v, int /*left*/, int /*right*/ ) +{ + SC_REPORT_ERROR( "attempted specalized signal operation on " + "non-specialized signal", "int" ); +} +void sc_unsigned_part_if::write_part( + const sc_dt::sc_signed& v, int /*left*/, int /*right*/ ) +{ + SC_REPORT_ERROR( "attempted specalized signal operation on " + "non-specialized signal", "int" ); +} +void sc_unsigned_part_if::write_part( + const sc_dt::sc_unsigned& v, int /*left*/, int /*right*/ ) +{ + SC_REPORT_ERROR( "attempted specalized signal operation on " + "non-specialized signal", "int" ); +} + + + +//------------------------------------------------------------------------------ +//"sc_unsigned_sigref::concate_set" +// +// These methods assign this object instance's value from the supplied +// value starting at the supplied bit within that value. +// src = value to use to set this object instance's value. +// low_i = bit in src that is to be the low order bit of the value to set. +// #### OPTIMIZE +//------------------------------------------------------------------------------ +void sc_unsigned_sigref::concat_set(sc_dt::int64 src, int low_i) +{ + sc_dt::int64 tmp; + if ( low_i < 63 ) + tmp = src >> low_i; + else + tmp = (src < 0) ? -1 : 0; + m_if_p->write_part( tmp, m_left, m_right ); +} + + +void sc_unsigned_sigref::concat_set(const sc_dt::sc_signed& src, int low_i) +{ + m_if_p->write_part( src >> low_i, m_left, m_right ); +} + + +void sc_unsigned_sigref::concat_set(const sc_dt::sc_lv_base& src, int low_i) +{ + sc_dt::sc_unsigned tmp(src.length()); + tmp = src; + m_if_p->write_part( tmp >> low_i, m_left, m_right ); +} + + +void sc_unsigned_sigref::concat_set(const sc_dt::sc_unsigned& src, int low_i) +{ + m_if_p->write_part( src >> low_i, m_left, m_right ); +} + + +void sc_unsigned_sigref::concat_set(sc_dt::uint64 src, int low_i) +{ + sc_dt::uint64 tmp = (low_i < 63) ? (src >> low_i) : 0; + m_if_p->write_part( tmp, m_left, m_right ); +} + + +} // namespace sc_core |