systemc: Add some common test include files.
These are "common" in the sense that they're not in a particular test directory, but I think they're only used by one test. Change-Id: I4ffd209d04ed0e5253085810913827b87412b302 Reviewed-on: https://gem5-review.googlesource.com/11272 Reviewed-by: Gabe Black <gabeblack@google.com> Maintainer: Gabe Black <gabeblack@google.com>
This commit is contained in:
@@ -62,6 +62,7 @@ if env['USE_SYSTEMC']:
|
||||
}
|
||||
|
||||
ext_dir = Dir('..').Dir('ext')
|
||||
test_dir = Dir('.')
|
||||
class SystemCTestBin(Executable):
|
||||
def __init__(self, test):
|
||||
super(SystemCTestBin, self).__init__(test.target, *test.sources)
|
||||
@@ -75,6 +76,7 @@ if env['USE_SYSTEMC']:
|
||||
env['CCFLAGS'] = \
|
||||
filter(lambda f: f not in to_remove, env['CCFLAGS'])
|
||||
|
||||
env.Append(CPPPATH=test_dir.Dir('include'))
|
||||
env.Append(CPPPATH=ext_dir)
|
||||
|
||||
super(SystemCTestBin, cls).declare_all(env)
|
||||
|
||||
166
src/systemc/tests/include/CoreDecouplingLTInitiator.h
Normal file
166
src/systemc/tests/include/CoreDecouplingLTInitiator.h
Normal file
@@ -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
|
||||
176
src/systemc/tests/include/ExplicitATTarget.h
Normal file
176
src/systemc/tests/include/ExplicitATTarget.h
Normal file
@@ -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
|
||||
124
src/systemc/tests/include/ExplicitLTTarget.h
Normal file
124
src/systemc/tests/include/ExplicitLTTarget.h
Normal file
@@ -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
|
||||
92
src/systemc/tests/include/README.txt
Normal file
92
src/systemc/tests/include/README.txt
Normal file
@@ -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)
|
||||
333
src/systemc/tests/include/SimpleATInitiator1.h
Normal file
333
src/systemc/tests/include/SimpleATInitiator1.h
Normal file
@@ -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
|
||||
306
src/systemc/tests/include/SimpleATInitiator2.h
Normal file
306
src/systemc/tests/include/SimpleATInitiator2.h
Normal file
@@ -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
|
||||
211
src/systemc/tests/include/SimpleATTarget1.h
Normal file
211
src/systemc/tests/include/SimpleATTarget1.h
Normal file
@@ -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
|
||||
178
src/systemc/tests/include/SimpleATTarget2.h
Normal file
178
src/systemc/tests/include/SimpleATTarget2.h
Normal file
@@ -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
|
||||
378
src/systemc/tests/include/SimpleBusAT.h
Normal file
378
src/systemc/tests/include/SimpleBusAT.h
Normal file
@@ -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
|
||||
193
src/systemc/tests/include/SimpleBusLT.h
Normal file
193
src/systemc/tests/include/SimpleBusLT.h
Normal file
@@ -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
|
||||
162
src/systemc/tests/include/SimpleLTInitiator1.h
Normal file
162
src/systemc/tests/include/SimpleLTInitiator1.h
Normal file
@@ -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
|
||||
305
src/systemc/tests/include/SimpleLTInitiator1_DMI.h
Normal file
305
src/systemc/tests/include/SimpleLTInitiator1_DMI.h
Normal file
@@ -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
|
||||
151
src/systemc/tests/include/SimpleLTInitiator2.h
Normal file
151
src/systemc/tests/include/SimpleLTInitiator2.h
Normal file
@@ -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
|
||||
299
src/systemc/tests/include/SimpleLTInitiator2_DMI.h
Normal file
299
src/systemc/tests/include/SimpleLTInitiator2_DMI.h
Normal file
@@ -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
|
||||
152
src/systemc/tests/include/SimpleLTInitiator3.h
Normal file
152
src/systemc/tests/include/SimpleLTInitiator3.h
Normal file
@@ -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
|
||||
244
src/systemc/tests/include/SimpleLTInitiator3_DMI.h
Normal file
244
src/systemc/tests/include/SimpleLTInitiator3_DMI.h
Normal file
@@ -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
|
||||
158
src/systemc/tests/include/SimpleLTTarget1.h
Normal file
158
src/systemc/tests/include/SimpleLTTarget1.h
Normal file
@@ -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
|
||||
149
src/systemc/tests/include/SimpleLTTarget2.h
Normal file
149
src/systemc/tests/include/SimpleLTTarget2.h
Normal file
@@ -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
|
||||
1629
src/systemc/tests/include/specialized_signals/scx_signal_int.h
Normal file
1629
src/systemc/tests/include/specialized_signals/scx_signal_int.h
Normal file
File diff suppressed because it is too large
Load Diff
1833
src/systemc/tests/include/specialized_signals/scx_signal_signed.h
Normal file
1833
src/systemc/tests/include/specialized_signals/scx_signal_signed.h
Normal file
File diff suppressed because it is too large
Load Diff
1676
src/systemc/tests/include/specialized_signals/scx_signal_uint.h
Normal file
1676
src/systemc/tests/include/specialized_signals/scx_signal_uint.h
Normal file
File diff suppressed because it is too large
Load Diff
1834
src/systemc/tests/include/specialized_signals/scx_signal_unsigned.h
Normal file
1834
src/systemc/tests/include/specialized_signals/scx_signal_unsigned.h
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user