From 16fa8d7cc8c92f5ab879e4cf9c6c0bbb3567860f Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 24 May 2018 01:37:55 -0700 Subject: systemc: Import tests from the Accellera systemc distribution. Change-Id: Iad76b398949a55d768a34d027a2d8e3739953da6 Reviewed-on: https://gem5-review.googlesource.com/10845 Reviewed-by: Giacomo Travaglini Maintainer: Gabe Black --- .../ext2gp/SimpleLTInitiator_ext.h | 343 +++++++++++++++++++++ .../tests/tlm/static_extensions/ext2gp/ext2gp.cpp | 40 +++ .../static_extensions/ext2gp/extension_adaptors.h | 212 +++++++++++++ .../tlm/static_extensions/ext2gp/golden/ext2gp.log | 65 ++++ .../tlm/static_extensions/ext2gp/my_extension.h | 56 ++++ .../ext2gp2ext/SimpleLTInitiator_ext.h | 343 +++++++++++++++++++++ .../ext2gp2ext/SimpleLTTarget_ext.h | 186 +++++++++++ .../static_extensions/ext2gp2ext/ext2gp2ext.cpp | 45 +++ .../ext2gp2ext/extension_adaptors.h | 212 +++++++++++++ .../ext2gp2ext/golden/ext2gp2ext.log | 81 +++++ .../static_extensions/ext2gp2ext/my_extension.h | 56 ++++ .../static_extensions/gp2ext/SimpleLTTarget_ext.h | 186 +++++++++++ .../static_extensions/gp2ext/extension_adaptors.h | 212 +++++++++++++ .../tlm/static_extensions/gp2ext/golden/gp2ext.log | 81 +++++ .../tests/tlm/static_extensions/gp2ext/gp2ext.cpp | 40 +++ .../tlm/static_extensions/gp2ext/my_extension.h | 56 ++++ 16 files changed, 2214 insertions(+) create mode 100644 src/systemc/tests/tlm/static_extensions/ext2gp/SimpleLTInitiator_ext.h create mode 100644 src/systemc/tests/tlm/static_extensions/ext2gp/ext2gp.cpp create mode 100644 src/systemc/tests/tlm/static_extensions/ext2gp/extension_adaptors.h create mode 100644 src/systemc/tests/tlm/static_extensions/ext2gp/golden/ext2gp.log create mode 100644 src/systemc/tests/tlm/static_extensions/ext2gp/my_extension.h create mode 100644 src/systemc/tests/tlm/static_extensions/ext2gp2ext/SimpleLTInitiator_ext.h create mode 100644 src/systemc/tests/tlm/static_extensions/ext2gp2ext/SimpleLTTarget_ext.h create mode 100644 src/systemc/tests/tlm/static_extensions/ext2gp2ext/ext2gp2ext.cpp create mode 100644 src/systemc/tests/tlm/static_extensions/ext2gp2ext/extension_adaptors.h create mode 100644 src/systemc/tests/tlm/static_extensions/ext2gp2ext/golden/ext2gp2ext.log create mode 100644 src/systemc/tests/tlm/static_extensions/ext2gp2ext/my_extension.h create mode 100644 src/systemc/tests/tlm/static_extensions/gp2ext/SimpleLTTarget_ext.h create mode 100644 src/systemc/tests/tlm/static_extensions/gp2ext/extension_adaptors.h create mode 100644 src/systemc/tests/tlm/static_extensions/gp2ext/golden/gp2ext.log create mode 100644 src/systemc/tests/tlm/static_extensions/gp2ext/gp2ext.cpp create mode 100644 src/systemc/tests/tlm/static_extensions/gp2ext/my_extension.h (limited to 'src/systemc/tests/tlm/static_extensions') diff --git a/src/systemc/tests/tlm/static_extensions/ext2gp/SimpleLTInitiator_ext.h b/src/systemc/tests/tlm/static_extensions/ext2gp/SimpleLTInitiator_ext.h new file mode 100644 index 000000000..1d10e0785 --- /dev/null +++ b/src/systemc/tests/tlm/static_extensions/ext2gp/SimpleLTInitiator_ext.h @@ -0,0 +1,343 @@ +/***************************************************************************** + + 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_INITIATOR_EXT_H__ +#define __SIMPLE_LT_INITIATOR_EXT_H__ + +#include "tlm.h" +#include "tlm_utils/simple_initiator_socket.h" +#include "my_extension.h" + +#include +#include +#include +#include +#include + +class SimpleLTInitiator_ext : 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 initiator_socket_type; + +public: + initiator_socket_type socket; + +public: + SC_HAS_PROCESS(SimpleLTInitiator_ext); + SimpleLTInitiator_ext(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); + + // register nb_transport method + socket.register_nb_transport_bw(this, &SimpleLTInitiator_ext::myNBTransport); + socket.register_invalidate_direct_mem_ptr(this, &SimpleLTInitiator_ext::invalidate_direct_mem_ptr); + + // 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_data_ptr(reinterpret_cast(&mData)); + trans.set_command(tlm::TLM_WRITE_COMMAND); + + } + else if (mTransactionCount < 2 * mNrOfTransactions) + { + trans.set_address(mBaseAddress + 4*(mTransactionCount-mNrOfTransactions)); + mData = 0; + trans.set_data_ptr(reinterpret_cast(&mData)); + trans.set_command(tlm::TLM_READ_COMMAND); + + } + else + { + return false; + } + + ++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; + // make sure that our transaction has the proper extension: + my_extension* tmp_ext = new my_extension(); + tmp_ext->m_data = 11; + + trans.set_extension(tmp_ext); + + 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 + switch (socket->nb_transport_fw(trans, phase, t)) { + case tlm::TLM_COMPLETED: + // Transaction Finished, wait for the returned delay + wait(t); + break; + + case tlm::TLM_ACCEPTED: + case tlm::TLM_UPDATED: + // Transaction not yet finished, wait for the end of it + wait(mEndEvent); + break; + + default: + sc_assert(0); exit(1); + }; + + logEndTransaction(trans); + + // Acquire DMI pointer if one is available: + if (trans.is_dmi_allowed()) + { + trans.set_write(); + dmi_type tmp; + if (socket->get_direct_mem_ptr(trans, + tmp)) + { + // FIXME: No support for separate read/write ranges + sc_assert(tmp.is_read_write_allowed()); + mDMIData = tmp; + } + } + } + } + delete tmp_ext; + wait(); + + } + + sync_enum_type myNBTransport(transaction_type& trans, + phase_type& phase, + sc_core::sc_time& t) + { + switch (phase) { + case tlm::END_REQ: + // Request phase ended + return tlm::TLM_ACCEPTED; + + case tlm::BEGIN_RESP: + sc_assert(t == sc_core::SC_ZERO_TIME); // FIXME: can t != 0? + mEndEvent.notify(t); + // Not needed to update the phase if true is returned + 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 + sc_assert(0); exit(1); +// return tlm::TLM_COMPLETED; //unreachable code + }; + } + + 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, 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() << ", <>:" << 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 bridge("bridge"); + SimpleLTTarget1 target("target", true); + + initiator.socket(bridge.target_socket); + bridge.initiator_socket(target.socket); + + sc_core::sc_start(); + sc_core::sc_stop(); + + return 0; +} diff --git a/src/systemc/tests/tlm/static_extensions/ext2gp/extension_adaptors.h b/src/systemc/tests/tlm/static_extensions/ext2gp/extension_adaptors.h new file mode 100644 index 000000000..a6b470e2a --- /dev/null +++ b/src/systemc/tests/tlm/static_extensions/ext2gp/extension_adaptors.h @@ -0,0 +1,212 @@ +/***************************************************************************** + + 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 __EXTENSIONS_ADAPTORS_H__ +#define __EXTENSIONS_ADAPTORS_H__ + +#include "tlm.h" +#include "my_extension.h" + +#include "tlm_utils/simple_initiator_socket.h" +#include "tlm_utils/simple_target_socket.h" + +template +class adapt_ext2gp : public sc_core::sc_module +{ + public: + typedef tlm::tlm_generic_payload initiator_payload_type; + typedef tlm::tlm_generic_payload target_payload_type; + typedef tlm_utils::simple_initiator_socket initiator_socket_type; + typedef tlm_utils::simple_target_socket target_socket_type; + + target_socket_type target_socket; + initiator_socket_type initiator_socket; + + SC_HAS_PROCESS(adapt_ext2gp); + adapt_ext2gp(sc_core::sc_module_name name_) + : sc_core::sc_module(name_) + { + target_socket.register_nb_transport_fw(this, &adapt_ext2gp::forward_nb_transport); + target_socket.register_transport_dbg(this, &adapt_ext2gp::transport_debug); + target_socket.register_get_direct_mem_ptr(this, &adapt_ext2gp::get_dmi_pointer); + + initiator_socket.register_nb_transport_bw(this, &adapt_ext2gp::backward_nb_transport); + initiator_socket.register_invalidate_direct_mem_ptr(this, &adapt_ext2gp::invalidate_dmi_pointers); + } + + /////////////// + // NB transport + /////////////// + + // Forward direction: The initiator calls this method with an extended + // payload. We leave the extension class in the vector, and it will be + // ignored by the GP target. + tlm::tlm_sync_enum forward_nb_transport(initiator_payload_type& trans, + tlm::tlm_phase& phase, + sc_core::sc_time& t) + { + return initiator_socket->nb_transport_fw(trans, phase, t); + } + // Backward direction: we can assume here that the payload we get + // as parameter is the same one that the initiator sent out. Thus, the + // extension vector is known to be present. + tlm::tlm_sync_enum backward_nb_transport(target_payload_type& trans, + tlm::tlm_phase& phase, + sc_core::sc_time& t) + { + return target_socket->nb_transport_bw(trans, phase, t); + } + + bool get_dmi_pointer(target_payload_type& trans, + tlm::tlm_dmi& dmi_data) + { + bool tmp_ret = initiator_socket->get_direct_mem_ptr(trans, + dmi_data); + return tmp_ret; + } + + ////////////////////////// + // simple call forwarders: + ////////////////////////// + unsigned int transport_debug(target_payload_type& trans) + { + return initiator_socket->transport_dbg(trans); + } + void invalidate_dmi_pointers(sc_dt::uint64 start_range, + sc_dt::uint64 end_range) + { + target_socket->invalidate_direct_mem_ptr(start_range, + end_range); + } +}; + +template +class adapt_gp2ext : public sc_core::sc_module +{ + public: + typedef tlm::tlm_generic_payload initiator_payload_type; + typedef tlm::tlm_generic_payload target_payload_type; + typedef tlm_utils::simple_initiator_socket initiator_socket_type; + typedef tlm_utils::simple_target_socket target_socket_type; + + target_socket_type target_socket; + initiator_socket_type initiator_socket; + + SC_HAS_PROCESS(adapt_gp2ext); + adapt_gp2ext(sc_core::sc_module_name name_) + : sc_core::sc_module(name_) + { + // Optionally, we can initialize our private extension class + // here, if required. + + target_socket.register_nb_transport_fw(this, &adapt_gp2ext::forward_nb_transport); + target_socket.register_transport_dbg(this, &adapt_gp2ext::transport_debug); + target_socket.register_get_direct_mem_ptr(this, &adapt_gp2ext::get_dmi_pointer); + + initiator_socket.register_nb_transport_bw(this, &adapt_gp2ext::backward_nb_transport); + initiator_socket.register_invalidate_direct_mem_ptr(this, &adapt_gp2ext::invalidate_dmi_pointers); + + m_ext.m_data = 13; + } + + /////////////// + // NB transport + /////////////// + + // Forward direction: We extend the payload on the fly (if needed). + tlm::tlm_sync_enum forward_nb_transport(initiator_payload_type& trans, + tlm::tlm_phase& phase, + sc_core::sc_time& t) + { + // If the mandatory extension is not there, we need to add it and + // store it so that we can re-construc the original state. + // Otherwise we don't touch the extension, so that we don't overwrite + // it in e.g. a nonGP->GP->nonGP (initiator->interconnect->target) + // setup. + // Note, however, that there might be situations where we might need to + // re-initialize the extension, e.g. for mutable data fields in + // different system setups. + trans.get_extension(m_initiator_ext); + if (!m_initiator_ext) + { + m_initiator_ext = trans.set_extension(&m_ext); + } + tlm::tlm_sync_enum tmp = + initiator_socket->nb_transport_fw(trans, phase, t); + if (tmp == tlm::TLM_COMPLETED) + { + m_initiator_ext = trans.set_extension(m_initiator_ext); + } + return tmp; + } + // Backward direction: only restore of original extension and static_cast. + tlm::tlm_sync_enum backward_nb_transport(target_payload_type& trans, + tlm::tlm_phase& phase, + sc_core::sc_time& t) + { + m_initiator_ext = trans.set_extension(m_initiator_ext); + return target_socket->nb_transport_bw(trans, phase, t); + } + + bool get_dmi_pointer(target_payload_type& trans, + tlm::tlm_dmi& dmi_data) + { + // If the mandatory extension is not there, we need to add it and + // store it so that we can re-construc the original state. + // Otherwise we don't touch the extension, so that we don't overwrite + // it in e.g. a nonGP->GP->nonGP (initiator->interconnect->target) + // setup. + my_extension* tmp_ext; + trans.get_extension(tmp_ext); + if (!tmp_ext) + { + trans.set_extension(&m_ext); + } + bool tmp_ret = initiator_socket->get_direct_mem_ptr(trans, + dmi_data); + if(!tmp_ext) + { + trans.clear_extension(tmp_ext); + } + return tmp_ret; + } + ////////////////////////// + // simple call forwarders: + ////////////////////////// + unsigned int transport_debug(target_payload_type& trans) + { + return initiator_socket->transport_dbg(trans); + } + void invalidate_dmi_pointers(sc_dt::uint64 start_range, + sc_dt::uint64 end_range) + { + target_socket->invalidate_direct_mem_ptr(start_range, + end_range); + } + +private: + my_extension m_ext; + my_extension* m_initiator_ext; +}; + +#endif diff --git a/src/systemc/tests/tlm/static_extensions/ext2gp/golden/ext2gp.log b/src/systemc/tests/tlm/static_extensions/ext2gp/golden/ext2gp.log new file mode 100644 index 000000000..bffb34320 --- /dev/null +++ b/src/systemc/tests/tlm/static_extensions/ext2gp/golden/ext2gp.log @@ -0,0 +1,65 @@ +SystemC Simulation +initiator: Send write request: A = 0x0, D = 0x0 @ 0 s +target: Received write request: A = 0x0, D = 0x0 @ 0 s +initiator: Received ok response @ 10 ns +initiator: Send write request: A = 0x4, D = 0x1 @ 10 ns +initiator: Received ok response @ 20 ns +initiator: Send write request: A = 0x8, D = 0x2 @ 20 ns +initiator: Received ok response @ 30 ns +initiator: Send write request: A = 0xc, D = 0x3 @ 30 ns +initiator: got DMI pointer invalidation @ 35 ns +initiator: Received ok response @ 40 ns +initiator: Send write request: A = 0x10, D = 0x4 @ 40 ns +target: Received write request: A = 0x10, D = 0x4 @ 40 ns +initiator: Received ok response @ 50 ns +initiator: Send write request: A = 0x14, D = 0x5 @ 50 ns +initiator: Received ok response @ 60 ns +initiator: Send write request: A = 0x18, D = 0x6 @ 60 ns +initiator: Received ok response @ 70 ns +initiator: Send write request: A = 0x1c, D = 0x7 @ 70 ns +initiator: got DMI pointer invalidation @ 75 ns +initiator: Received ok response @ 80 ns +initiator: Send write request: A = 0x20, D = 0x8 @ 80 ns +target: Received write request: A = 0x20, D = 0x8 @ 80 ns +initiator: Received ok response @ 90 ns +initiator: Send write request: A = 0x24, D = 0x9 @ 90 ns +initiator: Received ok response @ 100 ns +initiator: Send read request: A = 0x0 @ 100 ns +initiator: got DMI pointer invalidation @ 115 ns +initiator: Received ok response: D = 0x0 @ 200 ns +initiator: Send read request: A = 0x4 @ 200 ns +target: Received read request: A = 0x4 @ 200 ns +initiator: Received ok response: D = 0x1 @ 300 ns +initiator: Send read request: A = 0x8 @ 300 ns +initiator: got DMI pointer invalidation @ 325 ns +initiator: Received ok response: D = 0x2 @ 400 ns +initiator: Send read request: A = 0xc @ 400 ns +target: Received read request: A = 0xc @ 400 ns +initiator: Received ok response: D = 0x3 @ 500 ns +initiator: Send read request: A = 0x10 @ 500 ns +initiator: got DMI pointer invalidation @ 525 ns +initiator: Received ok response: D = 0x4 @ 600 ns +initiator: Send read request: A = 0x14 @ 600 ns +target: Received read request: A = 0x14 @ 600 ns +initiator: Received ok response: D = 0x5 @ 700 ns +initiator: Send read request: A = 0x18 @ 700 ns +initiator: got DMI pointer invalidation @ 725 ns +initiator: Received ok response: D = 0x6 @ 800 ns +initiator: Send read request: A = 0x1c @ 800 ns +target: Received read request: A = 0x1c @ 800 ns +initiator: Received ok response: D = 0x7 @ 900 ns +initiator: Send read request: A = 0x20 @ 900 ns +initiator: got DMI pointer invalidation @ 925 ns +initiator: Received ok response: D = 0x8 @ 1 us +initiator: Send read request: A = 0x24 @ 1 us +target: Received read request: A = 0x24 @ 1 us +initiator: Received ok response: D = 0x9 @ 1100 ns +initiator: got DMI pointer invalidation @ 1125 ns + +Info: /OSCI/SystemC: Simulation stopped by user. +initiator, <>: + +Mem @0 +00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 +04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00 + diff --git a/src/systemc/tests/tlm/static_extensions/ext2gp/my_extension.h b/src/systemc/tests/tlm/static_extensions/ext2gp/my_extension.h new file mode 100644 index 000000000..650931cd1 --- /dev/null +++ b/src/systemc/tests/tlm/static_extensions/ext2gp/my_extension.h @@ -0,0 +1,56 @@ +/***************************************************************************** + + 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 __MY_EXTENSION_H__ +#define __MY_EXTENSION_H__ + +#include "tlm.h" +#include + +class my_extension : + public tlm::tlm_extension +{ +public: + my_extension() + : m_data(0) + {} + tlm_extension_base* clone() const + { + return new my_extension(*this); + } + void free() + { + delete this; + } + void copy_from(tlm_extension_base const & e) + { + sc_assert(typeid(this) == typeid(e)); + m_data = static_cast(e).m_data; + } + + int m_data; +}; + +struct my_extended_payload_types +{ + typedef tlm::tlm_base_protocol_types::tlm_payload_type tlm_payload_type; + typedef tlm::tlm_base_protocol_types::tlm_phase_type tlm_phase_type; +}; + +#endif diff --git a/src/systemc/tests/tlm/static_extensions/ext2gp2ext/SimpleLTInitiator_ext.h b/src/systemc/tests/tlm/static_extensions/ext2gp2ext/SimpleLTInitiator_ext.h new file mode 100644 index 000000000..1d10e0785 --- /dev/null +++ b/src/systemc/tests/tlm/static_extensions/ext2gp2ext/SimpleLTInitiator_ext.h @@ -0,0 +1,343 @@ +/***************************************************************************** + + 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_INITIATOR_EXT_H__ +#define __SIMPLE_LT_INITIATOR_EXT_H__ + +#include "tlm.h" +#include "tlm_utils/simple_initiator_socket.h" +#include "my_extension.h" + +#include +#include +#include +#include +#include + +class SimpleLTInitiator_ext : 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 initiator_socket_type; + +public: + initiator_socket_type socket; + +public: + SC_HAS_PROCESS(SimpleLTInitiator_ext); + SimpleLTInitiator_ext(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); + + // register nb_transport method + socket.register_nb_transport_bw(this, &SimpleLTInitiator_ext::myNBTransport); + socket.register_invalidate_direct_mem_ptr(this, &SimpleLTInitiator_ext::invalidate_direct_mem_ptr); + + // 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_data_ptr(reinterpret_cast(&mData)); + trans.set_command(tlm::TLM_WRITE_COMMAND); + + } + else if (mTransactionCount < 2 * mNrOfTransactions) + { + trans.set_address(mBaseAddress + 4*(mTransactionCount-mNrOfTransactions)); + mData = 0; + trans.set_data_ptr(reinterpret_cast(&mData)); + trans.set_command(tlm::TLM_READ_COMMAND); + + } + else + { + return false; + } + + ++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; + // make sure that our transaction has the proper extension: + my_extension* tmp_ext = new my_extension(); + tmp_ext->m_data = 11; + + trans.set_extension(tmp_ext); + + 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 + switch (socket->nb_transport_fw(trans, phase, t)) { + case tlm::TLM_COMPLETED: + // Transaction Finished, wait for the returned delay + wait(t); + break; + + case tlm::TLM_ACCEPTED: + case tlm::TLM_UPDATED: + // Transaction not yet finished, wait for the end of it + wait(mEndEvent); + break; + + default: + sc_assert(0); exit(1); + }; + + logEndTransaction(trans); + + // Acquire DMI pointer if one is available: + if (trans.is_dmi_allowed()) + { + trans.set_write(); + dmi_type tmp; + if (socket->get_direct_mem_ptr(trans, + tmp)) + { + // FIXME: No support for separate read/write ranges + sc_assert(tmp.is_read_write_allowed()); + mDMIData = tmp; + } + } + } + } + delete tmp_ext; + wait(); + + } + + sync_enum_type myNBTransport(transaction_type& trans, + phase_type& phase, + sc_core::sc_time& t) + { + switch (phase) { + case tlm::END_REQ: + // Request phase ended + return tlm::TLM_ACCEPTED; + + case tlm::BEGIN_RESP: + sc_assert(t == sc_core::SC_ZERO_TIME); // FIXME: can t != 0? + mEndEvent.notify(t); + // Not needed to update the phase if true is returned + 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 + sc_assert(0); exit(1); +// return tlm::TLM_COMPLETED; //unreachable code + }; + } + + 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, 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() << ", <>:" << 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 +#include +#include +//#include + +class SimpleLTTarget_ext : 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 target_socket_type; + +public: + target_socket_type socket; + +public: + SC_HAS_PROCESS(SimpleLTTarget_ext); + SimpleLTTarget_ext(sc_core::sc_module_name name, + sc_core::sc_time invalidate_dmi_time = sc_core::sc_time(25, sc_core::SC_NS)) : + sc_core::sc_module(name), + socket("socket") + { + // register nb_transport method + socket.register_nb_transport_fw(this, &SimpleLTTarget_ext::myNBTransport); + socket.register_get_direct_mem_ptr(this, &SimpleLTTarget_ext::myGetDMIPtr); + + socket.register_transport_dbg(this, &SimpleLTTarget_ext::transport_dbg); + + SC_METHOD(invalidate_dmi_method); + sensitive << m_invalidate_dmi_event; + dont_initialize(); + m_invalidate_dmi_time = invalidate_dmi_time; + } + + sync_enum_type myNBTransport(transaction_type& trans, phase_type& phase, sc_core::sc_time& t) + { + sc_assert(phase == tlm::BEGIN_REQ); + + my_extension* tmp_ext; + trans.get_extension(tmp_ext); + if (!tmp_ext) + { + std::cout << name() << ": ERROR, extension not present" << std::endl; + } + else + { + std::cout << name() << ": OK, extension data = " + << tmp_ext->m_data << std::endl; + } + sc_dt::uint64 address = trans.get_address(); + sc_assert(address < 400); + + unsigned int& data = *reinterpret_cast(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(&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(&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); + + // LT target + // - always return true + // - not necessary to update phase (if true 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) + { + // notify DMI invalidation, just to check if this reaches the + // initiators properly + m_invalidate_dmi_event.notify(m_invalidate_dmi_time); + + // Check for DMI extension: + my_extension * tmp_ext; + trans.get_extension(tmp_ext); + if (tmp_ext) + { + std::cout << name() << ": get_direct_mem_ptr OK, extension data = " + <m_data << std::endl; + } + else + { + std::cout << name() << ", get_direct_mem_ptr ERROR: " + << "didn't get pointer to extension" + << std::endl; + } + if (trans.get_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]; + sc_core::sc_event m_invalidate_dmi_event; + sc_core::sc_time m_invalidate_dmi_time; +}; + +#endif diff --git a/src/systemc/tests/tlm/static_extensions/ext2gp2ext/ext2gp2ext.cpp b/src/systemc/tests/tlm/static_extensions/ext2gp2ext/ext2gp2ext.cpp new file mode 100644 index 000000000..13f66f094 --- /dev/null +++ b/src/systemc/tests/tlm/static_extensions/ext2gp2ext/ext2gp2ext.cpp @@ -0,0 +1,45 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ +#define SC_INCLUDE_DYNAMIC_PROCESSES +#include "tlm.h" + +#include "SimpleLTInitiator_ext.h" +#include "SimpleBusLT.h" +#include "SimpleLTTarget_ext.h" +#include "extension_adaptors.h" + + +int sc_main(int argc, char* argv[]) +{ + SimpleLTInitiator_ext initiator("initiator1", 10, 0x0); + adapt_ext2gp<32> bridge1("bridge1"); + SimpleBusLT<1,1> bus("bus"); + adapt_gp2ext<32> bridge2("bridge2"); + SimpleLTTarget_ext target("target1"); + + initiator.socket(bridge1.target_socket); + bridge1.initiator_socket(bus.target_socket[0]); + bus.initiator_socket[0](bridge2.target_socket); + bridge2.initiator_socket(target.socket); + + sc_core::sc_start(); + sc_core::sc_stop(); + + return 0; +} diff --git a/src/systemc/tests/tlm/static_extensions/ext2gp2ext/extension_adaptors.h b/src/systemc/tests/tlm/static_extensions/ext2gp2ext/extension_adaptors.h new file mode 100644 index 000000000..a6b470e2a --- /dev/null +++ b/src/systemc/tests/tlm/static_extensions/ext2gp2ext/extension_adaptors.h @@ -0,0 +1,212 @@ +/***************************************************************************** + + 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 __EXTENSIONS_ADAPTORS_H__ +#define __EXTENSIONS_ADAPTORS_H__ + +#include "tlm.h" +#include "my_extension.h" + +#include "tlm_utils/simple_initiator_socket.h" +#include "tlm_utils/simple_target_socket.h" + +template +class adapt_ext2gp : public sc_core::sc_module +{ + public: + typedef tlm::tlm_generic_payload initiator_payload_type; + typedef tlm::tlm_generic_payload target_payload_type; + typedef tlm_utils::simple_initiator_socket initiator_socket_type; + typedef tlm_utils::simple_target_socket target_socket_type; + + target_socket_type target_socket; + initiator_socket_type initiator_socket; + + SC_HAS_PROCESS(adapt_ext2gp); + adapt_ext2gp(sc_core::sc_module_name name_) + : sc_core::sc_module(name_) + { + target_socket.register_nb_transport_fw(this, &adapt_ext2gp::forward_nb_transport); + target_socket.register_transport_dbg(this, &adapt_ext2gp::transport_debug); + target_socket.register_get_direct_mem_ptr(this, &adapt_ext2gp::get_dmi_pointer); + + initiator_socket.register_nb_transport_bw(this, &adapt_ext2gp::backward_nb_transport); + initiator_socket.register_invalidate_direct_mem_ptr(this, &adapt_ext2gp::invalidate_dmi_pointers); + } + + /////////////// + // NB transport + /////////////// + + // Forward direction: The initiator calls this method with an extended + // payload. We leave the extension class in the vector, and it will be + // ignored by the GP target. + tlm::tlm_sync_enum forward_nb_transport(initiator_payload_type& trans, + tlm::tlm_phase& phase, + sc_core::sc_time& t) + { + return initiator_socket->nb_transport_fw(trans, phase, t); + } + // Backward direction: we can assume here that the payload we get + // as parameter is the same one that the initiator sent out. Thus, the + // extension vector is known to be present. + tlm::tlm_sync_enum backward_nb_transport(target_payload_type& trans, + tlm::tlm_phase& phase, + sc_core::sc_time& t) + { + return target_socket->nb_transport_bw(trans, phase, t); + } + + bool get_dmi_pointer(target_payload_type& trans, + tlm::tlm_dmi& dmi_data) + { + bool tmp_ret = initiator_socket->get_direct_mem_ptr(trans, + dmi_data); + return tmp_ret; + } + + ////////////////////////// + // simple call forwarders: + ////////////////////////// + unsigned int transport_debug(target_payload_type& trans) + { + return initiator_socket->transport_dbg(trans); + } + void invalidate_dmi_pointers(sc_dt::uint64 start_range, + sc_dt::uint64 end_range) + { + target_socket->invalidate_direct_mem_ptr(start_range, + end_range); + } +}; + +template +class adapt_gp2ext : public sc_core::sc_module +{ + public: + typedef tlm::tlm_generic_payload initiator_payload_type; + typedef tlm::tlm_generic_payload target_payload_type; + typedef tlm_utils::simple_initiator_socket initiator_socket_type; + typedef tlm_utils::simple_target_socket target_socket_type; + + target_socket_type target_socket; + initiator_socket_type initiator_socket; + + SC_HAS_PROCESS(adapt_gp2ext); + adapt_gp2ext(sc_core::sc_module_name name_) + : sc_core::sc_module(name_) + { + // Optionally, we can initialize our private extension class + // here, if required. + + target_socket.register_nb_transport_fw(this, &adapt_gp2ext::forward_nb_transport); + target_socket.register_transport_dbg(this, &adapt_gp2ext::transport_debug); + target_socket.register_get_direct_mem_ptr(this, &adapt_gp2ext::get_dmi_pointer); + + initiator_socket.register_nb_transport_bw(this, &adapt_gp2ext::backward_nb_transport); + initiator_socket.register_invalidate_direct_mem_ptr(this, &adapt_gp2ext::invalidate_dmi_pointers); + + m_ext.m_data = 13; + } + + /////////////// + // NB transport + /////////////// + + // Forward direction: We extend the payload on the fly (if needed). + tlm::tlm_sync_enum forward_nb_transport(initiator_payload_type& trans, + tlm::tlm_phase& phase, + sc_core::sc_time& t) + { + // If the mandatory extension is not there, we need to add it and + // store it so that we can re-construc the original state. + // Otherwise we don't touch the extension, so that we don't overwrite + // it in e.g. a nonGP->GP->nonGP (initiator->interconnect->target) + // setup. + // Note, however, that there might be situations where we might need to + // re-initialize the extension, e.g. for mutable data fields in + // different system setups. + trans.get_extension(m_initiator_ext); + if (!m_initiator_ext) + { + m_initiator_ext = trans.set_extension(&m_ext); + } + tlm::tlm_sync_enum tmp = + initiator_socket->nb_transport_fw(trans, phase, t); + if (tmp == tlm::TLM_COMPLETED) + { + m_initiator_ext = trans.set_extension(m_initiator_ext); + } + return tmp; + } + // Backward direction: only restore of original extension and static_cast. + tlm::tlm_sync_enum backward_nb_transport(target_payload_type& trans, + tlm::tlm_phase& phase, + sc_core::sc_time& t) + { + m_initiator_ext = trans.set_extension(m_initiator_ext); + return target_socket->nb_transport_bw(trans, phase, t); + } + + bool get_dmi_pointer(target_payload_type& trans, + tlm::tlm_dmi& dmi_data) + { + // If the mandatory extension is not there, we need to add it and + // store it so that we can re-construc the original state. + // Otherwise we don't touch the extension, so that we don't overwrite + // it in e.g. a nonGP->GP->nonGP (initiator->interconnect->target) + // setup. + my_extension* tmp_ext; + trans.get_extension(tmp_ext); + if (!tmp_ext) + { + trans.set_extension(&m_ext); + } + bool tmp_ret = initiator_socket->get_direct_mem_ptr(trans, + dmi_data); + if(!tmp_ext) + { + trans.clear_extension(tmp_ext); + } + return tmp_ret; + } + ////////////////////////// + // simple call forwarders: + ////////////////////////// + unsigned int transport_debug(target_payload_type& trans) + { + return initiator_socket->transport_dbg(trans); + } + void invalidate_dmi_pointers(sc_dt::uint64 start_range, + sc_dt::uint64 end_range) + { + target_socket->invalidate_direct_mem_ptr(start_range, + end_range); + } + +private: + my_extension m_ext; + my_extension* m_initiator_ext; +}; + +#endif diff --git a/src/systemc/tests/tlm/static_extensions/ext2gp2ext/golden/ext2gp2ext.log b/src/systemc/tests/tlm/static_extensions/ext2gp2ext/golden/ext2gp2ext.log new file mode 100644 index 000000000..4a27a6f7d --- /dev/null +++ b/src/systemc/tests/tlm/static_extensions/ext2gp2ext/golden/ext2gp2ext.log @@ -0,0 +1,81 @@ +SystemC Simulation +initiator1: Send write request: A = 0x0, D = 0x0 @ 0 s +target1: OK, extension data = 11 +target1: Received write request: A = 0x0, D = 0x0 @ 0 s +initiator1: Received ok response @ 10 ns +target1: get_direct_mem_ptr OK, extension data = 11 +initiator1: Send write request: A = 0x4, D = 0x1 @ 10 ns +initiator1: Received ok response @ 20 ns +initiator1: Send write request: A = 0x8, D = 0x2 @ 20 ns +initiator1: Received ok response @ 30 ns +initiator1: Send write request: A = 0xc, D = 0x3 @ 30 ns +initiator1: got DMI pointer invalidation @ 35 ns +initiator1: Received ok response @ 40 ns +initiator1: Send write request: A = 0x10, D = 0x4 @ 40 ns +target1: OK, extension data = 11 +target1: Received write request: A = 0x10, D = 0x4 @ 40 ns +initiator1: Received ok response @ 50 ns +target1: get_direct_mem_ptr OK, extension data = 11 +initiator1: Send write request: A = 0x14, D = 0x5 @ 50 ns +initiator1: Received ok response @ 60 ns +initiator1: Send write request: A = 0x18, D = 0x6 @ 60 ns +initiator1: Received ok response @ 70 ns +initiator1: Send write request: A = 0x1c, D = 0x7 @ 70 ns +initiator1: got DMI pointer invalidation @ 75 ns +initiator1: Received ok response @ 80 ns +initiator1: Send write request: A = 0x20, D = 0x8 @ 80 ns +target1: OK, extension data = 11 +target1: Received write request: A = 0x20, D = 0x8 @ 80 ns +initiator1: Received ok response @ 90 ns +target1: get_direct_mem_ptr OK, extension data = 11 +initiator1: Send write request: A = 0x24, D = 0x9 @ 90 ns +initiator1: Received ok response @ 100 ns +initiator1: Send read request: A = 0x0 @ 100 ns +initiator1: got DMI pointer invalidation @ 115 ns +initiator1: Received ok response: D = 0x0 @ 200 ns +initiator1: Send read request: A = 0x4 @ 200 ns +target1: OK, extension data = 11 +target1: Received read request: A = 0x4 @ 200 ns +initiator1: Received ok response: D = 0x1 @ 300 ns +target1: get_direct_mem_ptr OK, extension data = 11 +initiator1: Send read request: A = 0x8 @ 300 ns +initiator1: got DMI pointer invalidation @ 325 ns +initiator1: Received ok response: D = 0x2 @ 400 ns +initiator1: Send read request: A = 0xc @ 400 ns +target1: OK, extension data = 11 +target1: Received read request: A = 0xc @ 400 ns +initiator1: Received ok response: D = 0x3 @ 500 ns +target1: get_direct_mem_ptr OK, extension data = 11 +initiator1: Send read request: A = 0x10 @ 500 ns +initiator1: got DMI pointer invalidation @ 525 ns +initiator1: Received ok response: D = 0x4 @ 600 ns +initiator1: Send read request: A = 0x14 @ 600 ns +target1: OK, extension data = 11 +target1: Received read request: A = 0x14 @ 600 ns +initiator1: Received ok response: D = 0x5 @ 700 ns +target1: get_direct_mem_ptr OK, extension data = 11 +initiator1: Send read request: A = 0x18 @ 700 ns +initiator1: got DMI pointer invalidation @ 725 ns +initiator1: Received ok response: D = 0x6 @ 800 ns +initiator1: Send read request: A = 0x1c @ 800 ns +target1: OK, extension data = 11 +target1: Received read request: A = 0x1c @ 800 ns +initiator1: Received ok response: D = 0x7 @ 900 ns +target1: get_direct_mem_ptr OK, extension data = 11 +initiator1: Send read request: A = 0x20 @ 900 ns +initiator1: got DMI pointer invalidation @ 925 ns +initiator1: Received ok response: D = 0x8 @ 1 us +initiator1: Send read request: A = 0x24 @ 1 us +target1: OK, extension data = 11 +target1: Received read request: A = 0x24 @ 1 us +initiator1: Received ok response: D = 0x9 @ 1100 ns +target1: get_direct_mem_ptr OK, extension data = 11 +initiator1: got DMI pointer invalidation @ 1125 ns + +Info: /OSCI/SystemC: Simulation stopped by user. +initiator1, <>: + +Mem @0 +00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 +04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00 + diff --git a/src/systemc/tests/tlm/static_extensions/ext2gp2ext/my_extension.h b/src/systemc/tests/tlm/static_extensions/ext2gp2ext/my_extension.h new file mode 100644 index 000000000..650931cd1 --- /dev/null +++ b/src/systemc/tests/tlm/static_extensions/ext2gp2ext/my_extension.h @@ -0,0 +1,56 @@ +/***************************************************************************** + + 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 __MY_EXTENSION_H__ +#define __MY_EXTENSION_H__ + +#include "tlm.h" +#include + +class my_extension : + public tlm::tlm_extension +{ +public: + my_extension() + : m_data(0) + {} + tlm_extension_base* clone() const + { + return new my_extension(*this); + } + void free() + { + delete this; + } + void copy_from(tlm_extension_base const & e) + { + sc_assert(typeid(this) == typeid(e)); + m_data = static_cast(e).m_data; + } + + int m_data; +}; + +struct my_extended_payload_types +{ + typedef tlm::tlm_base_protocol_types::tlm_payload_type tlm_payload_type; + typedef tlm::tlm_base_protocol_types::tlm_phase_type tlm_phase_type; +}; + +#endif diff --git a/src/systemc/tests/tlm/static_extensions/gp2ext/SimpleLTTarget_ext.h b/src/systemc/tests/tlm/static_extensions/gp2ext/SimpleLTTarget_ext.h new file mode 100644 index 000000000..c542c196d --- /dev/null +++ b/src/systemc/tests/tlm/static_extensions/gp2ext/SimpleLTTarget_ext.h @@ -0,0 +1,186 @@ +/***************************************************************************** + + 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/simple_target_socket.h" +#include "my_extension.h" + +//#include +#include +#include +//#include + +class SimpleLTTarget_ext : 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 target_socket_type; + +public: + target_socket_type socket; + +public: + SC_HAS_PROCESS(SimpleLTTarget_ext); + SimpleLTTarget_ext(sc_core::sc_module_name name, + sc_core::sc_time invalidate_dmi_time = sc_core::sc_time(25, sc_core::SC_NS)) : + sc_core::sc_module(name), + socket("socket") + { + // register nb_transport method + socket.register_nb_transport_fw(this, &SimpleLTTarget_ext::myNBTransport); + socket.register_get_direct_mem_ptr(this, &SimpleLTTarget_ext::myGetDMIPtr); + + socket.register_transport_dbg(this, &SimpleLTTarget_ext::transport_dbg); + + SC_METHOD(invalidate_dmi_method); + sensitive << m_invalidate_dmi_event; + dont_initialize(); + m_invalidate_dmi_time = invalidate_dmi_time; + } + + sync_enum_type myNBTransport(transaction_type& trans, phase_type& phase, sc_core::sc_time& t) + { + sc_assert(phase == tlm::BEGIN_REQ); + + my_extension* tmp_ext; + trans.get_extension(tmp_ext); + if (!tmp_ext) + { + std::cout << name() << ": ERROR, extension not present" << std::endl; + } + else + { + std::cout << name() << ": OK, extension data = " + << tmp_ext->m_data << std::endl; + } + sc_dt::uint64 address = trans.get_address(); + sc_assert(address < 400); + + unsigned int& data = *reinterpret_cast(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(&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(&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); + + // LT target + // - always return true + // - not necessary to update phase (if true 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) + { + // notify DMI invalidation, just to check if this reaches the + // initiators properly + m_invalidate_dmi_event.notify(m_invalidate_dmi_time); + + // Check for DMI extension: + my_extension * tmp_ext; + trans.get_extension(tmp_ext); + if (tmp_ext) + { + std::cout << name() << ": get_direct_mem_ptr OK, extension data = " + <m_data << std::endl; + } + else + { + std::cout << name() << ", get_direct_mem_ptr ERROR: " + << "didn't get pointer to extension" + << std::endl; + } + if (trans.get_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]; + sc_core::sc_event m_invalidate_dmi_event; + sc_core::sc_time m_invalidate_dmi_time; +}; + +#endif diff --git a/src/systemc/tests/tlm/static_extensions/gp2ext/extension_adaptors.h b/src/systemc/tests/tlm/static_extensions/gp2ext/extension_adaptors.h new file mode 100644 index 000000000..a6b470e2a --- /dev/null +++ b/src/systemc/tests/tlm/static_extensions/gp2ext/extension_adaptors.h @@ -0,0 +1,212 @@ +/***************************************************************************** + + 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 __EXTENSIONS_ADAPTORS_H__ +#define __EXTENSIONS_ADAPTORS_H__ + +#include "tlm.h" +#include "my_extension.h" + +#include "tlm_utils/simple_initiator_socket.h" +#include "tlm_utils/simple_target_socket.h" + +template +class adapt_ext2gp : public sc_core::sc_module +{ + public: + typedef tlm::tlm_generic_payload initiator_payload_type; + typedef tlm::tlm_generic_payload target_payload_type; + typedef tlm_utils::simple_initiator_socket initiator_socket_type; + typedef tlm_utils::simple_target_socket target_socket_type; + + target_socket_type target_socket; + initiator_socket_type initiator_socket; + + SC_HAS_PROCESS(adapt_ext2gp); + adapt_ext2gp(sc_core::sc_module_name name_) + : sc_core::sc_module(name_) + { + target_socket.register_nb_transport_fw(this, &adapt_ext2gp::forward_nb_transport); + target_socket.register_transport_dbg(this, &adapt_ext2gp::transport_debug); + target_socket.register_get_direct_mem_ptr(this, &adapt_ext2gp::get_dmi_pointer); + + initiator_socket.register_nb_transport_bw(this, &adapt_ext2gp::backward_nb_transport); + initiator_socket.register_invalidate_direct_mem_ptr(this, &adapt_ext2gp::invalidate_dmi_pointers); + } + + /////////////// + // NB transport + /////////////// + + // Forward direction: The initiator calls this method with an extended + // payload. We leave the extension class in the vector, and it will be + // ignored by the GP target. + tlm::tlm_sync_enum forward_nb_transport(initiator_payload_type& trans, + tlm::tlm_phase& phase, + sc_core::sc_time& t) + { + return initiator_socket->nb_transport_fw(trans, phase, t); + } + // Backward direction: we can assume here that the payload we get + // as parameter is the same one that the initiator sent out. Thus, the + // extension vector is known to be present. + tlm::tlm_sync_enum backward_nb_transport(target_payload_type& trans, + tlm::tlm_phase& phase, + sc_core::sc_time& t) + { + return target_socket->nb_transport_bw(trans, phase, t); + } + + bool get_dmi_pointer(target_payload_type& trans, + tlm::tlm_dmi& dmi_data) + { + bool tmp_ret = initiator_socket->get_direct_mem_ptr(trans, + dmi_data); + return tmp_ret; + } + + ////////////////////////// + // simple call forwarders: + ////////////////////////// + unsigned int transport_debug(target_payload_type& trans) + { + return initiator_socket->transport_dbg(trans); + } + void invalidate_dmi_pointers(sc_dt::uint64 start_range, + sc_dt::uint64 end_range) + { + target_socket->invalidate_direct_mem_ptr(start_range, + end_range); + } +}; + +template +class adapt_gp2ext : public sc_core::sc_module +{ + public: + typedef tlm::tlm_generic_payload initiator_payload_type; + typedef tlm::tlm_generic_payload target_payload_type; + typedef tlm_utils::simple_initiator_socket initiator_socket_type; + typedef tlm_utils::simple_target_socket target_socket_type; + + target_socket_type target_socket; + initiator_socket_type initiator_socket; + + SC_HAS_PROCESS(adapt_gp2ext); + adapt_gp2ext(sc_core::sc_module_name name_) + : sc_core::sc_module(name_) + { + // Optionally, we can initialize our private extension class + // here, if required. + + target_socket.register_nb_transport_fw(this, &adapt_gp2ext::forward_nb_transport); + target_socket.register_transport_dbg(this, &adapt_gp2ext::transport_debug); + target_socket.register_get_direct_mem_ptr(this, &adapt_gp2ext::get_dmi_pointer); + + initiator_socket.register_nb_transport_bw(this, &adapt_gp2ext::backward_nb_transport); + initiator_socket.register_invalidate_direct_mem_ptr(this, &adapt_gp2ext::invalidate_dmi_pointers); + + m_ext.m_data = 13; + } + + /////////////// + // NB transport + /////////////// + + // Forward direction: We extend the payload on the fly (if needed). + tlm::tlm_sync_enum forward_nb_transport(initiator_payload_type& trans, + tlm::tlm_phase& phase, + sc_core::sc_time& t) + { + // If the mandatory extension is not there, we need to add it and + // store it so that we can re-construc the original state. + // Otherwise we don't touch the extension, so that we don't overwrite + // it in e.g. a nonGP->GP->nonGP (initiator->interconnect->target) + // setup. + // Note, however, that there might be situations where we might need to + // re-initialize the extension, e.g. for mutable data fields in + // different system setups. + trans.get_extension(m_initiator_ext); + if (!m_initiator_ext) + { + m_initiator_ext = trans.set_extension(&m_ext); + } + tlm::tlm_sync_enum tmp = + initiator_socket->nb_transport_fw(trans, phase, t); + if (tmp == tlm::TLM_COMPLETED) + { + m_initiator_ext = trans.set_extension(m_initiator_ext); + } + return tmp; + } + // Backward direction: only restore of original extension and static_cast. + tlm::tlm_sync_enum backward_nb_transport(target_payload_type& trans, + tlm::tlm_phase& phase, + sc_core::sc_time& t) + { + m_initiator_ext = trans.set_extension(m_initiator_ext); + return target_socket->nb_transport_bw(trans, phase, t); + } + + bool get_dmi_pointer(target_payload_type& trans, + tlm::tlm_dmi& dmi_data) + { + // If the mandatory extension is not there, we need to add it and + // store it so that we can re-construc the original state. + // Otherwise we don't touch the extension, so that we don't overwrite + // it in e.g. a nonGP->GP->nonGP (initiator->interconnect->target) + // setup. + my_extension* tmp_ext; + trans.get_extension(tmp_ext); + if (!tmp_ext) + { + trans.set_extension(&m_ext); + } + bool tmp_ret = initiator_socket->get_direct_mem_ptr(trans, + dmi_data); + if(!tmp_ext) + { + trans.clear_extension(tmp_ext); + } + return tmp_ret; + } + ////////////////////////// + // simple call forwarders: + ////////////////////////// + unsigned int transport_debug(target_payload_type& trans) + { + return initiator_socket->transport_dbg(trans); + } + void invalidate_dmi_pointers(sc_dt::uint64 start_range, + sc_dt::uint64 end_range) + { + target_socket->invalidate_direct_mem_ptr(start_range, + end_range); + } + +private: + my_extension m_ext; + my_extension* m_initiator_ext; +}; + +#endif diff --git a/src/systemc/tests/tlm/static_extensions/gp2ext/golden/gp2ext.log b/src/systemc/tests/tlm/static_extensions/gp2ext/golden/gp2ext.log new file mode 100644 index 000000000..d43825d43 --- /dev/null +++ b/src/systemc/tests/tlm/static_extensions/gp2ext/golden/gp2ext.log @@ -0,0 +1,81 @@ +SystemC Simulation +initiator1: Send write request: A = 0x0, D = 0x0 @ 0 s +target1: OK, extension data = 13 +target1: Received write request: A = 0x0, D = 0x0 @ 0 s +initiator1: Received ok response @ 10 ns +target1: get_direct_mem_ptr OK, extension data = 13 +initiator1: Send write request: A = 0x4, D = 0x1 @ 10 ns +initiator1: Received ok response @ 20 ns +initiator1: Send write request: A = 0x8, D = 0x2 @ 20 ns +initiator1: Received ok response @ 30 ns +initiator1: Send write request: A = 0xc, D = 0x3 @ 30 ns +initiator1: got DMI pointer invalidation @ 35 ns +initiator1: Received ok response @ 40 ns +initiator1: Send write request: A = 0x10, D = 0x4 @ 40 ns +target1: OK, extension data = 13 +target1: Received write request: A = 0x10, D = 0x4 @ 40 ns +initiator1: Received ok response @ 50 ns +target1: get_direct_mem_ptr OK, extension data = 13 +initiator1: Send write request: A = 0x14, D = 0x5 @ 50 ns +initiator1: Received ok response @ 60 ns +initiator1: Send write request: A = 0x18, D = 0x6 @ 60 ns +initiator1: Received ok response @ 70 ns +initiator1: Send write request: A = 0x1c, D = 0x7 @ 70 ns +initiator1: got DMI pointer invalidation @ 75 ns +initiator1: Received ok response @ 80 ns +initiator1: Send write request: A = 0x20, D = 0x8 @ 80 ns +target1: OK, extension data = 13 +target1: Received write request: A = 0x20, D = 0x8 @ 80 ns +initiator1: Received ok response @ 90 ns +target1: get_direct_mem_ptr OK, extension data = 13 +initiator1: Send write request: A = 0x24, D = 0x9 @ 90 ns +initiator1: Received ok response @ 100 ns +initiator1: Send read request: A = 0x0 @ 100 ns +initiator1: got DMI pointer invalidation @ 115 ns +initiator1: Received ok response: D = 0x0 @ 200 ns +initiator1: Send read request: A = 0x4 @ 200 ns +target1: OK, extension data = 13 +target1: Received read request: A = 0x4 @ 200 ns +initiator1: Received ok response: D = 0x1 @ 300 ns +target1: get_direct_mem_ptr OK, extension data = 13 +initiator1: Send read request: A = 0x8 @ 300 ns +initiator1: got DMI pointer invalidation @ 325 ns +initiator1: Received ok response: D = 0x2 @ 400 ns +initiator1: Send read request: A = 0xc @ 400 ns +target1: OK, extension data = 13 +target1: Received read request: A = 0xc @ 400 ns +initiator1: Received ok response: D = 0x3 @ 500 ns +target1: get_direct_mem_ptr OK, extension data = 13 +initiator1: Send read request: A = 0x10 @ 500 ns +initiator1: got DMI pointer invalidation @ 525 ns +initiator1: Received ok response: D = 0x4 @ 600 ns +initiator1: Send read request: A = 0x14 @ 600 ns +target1: OK, extension data = 13 +target1: Received read request: A = 0x14 @ 600 ns +initiator1: Received ok response: D = 0x5 @ 700 ns +target1: get_direct_mem_ptr OK, extension data = 13 +initiator1: Send read request: A = 0x18 @ 700 ns +initiator1: got DMI pointer invalidation @ 725 ns +initiator1: Received ok response: D = 0x6 @ 800 ns +initiator1: Send read request: A = 0x1c @ 800 ns +target1: OK, extension data = 13 +target1: Received read request: A = 0x1c @ 800 ns +initiator1: Received ok response: D = 0x7 @ 900 ns +target1: get_direct_mem_ptr OK, extension data = 13 +initiator1: Send read request: A = 0x20 @ 900 ns +initiator1: got DMI pointer invalidation @ 925 ns +initiator1: Received ok response: D = 0x8 @ 1 us +initiator1: Send read request: A = 0x24 @ 1 us +target1: OK, extension data = 13 +target1: Received read request: A = 0x24 @ 1 us +initiator1: Received ok response: D = 0x9 @ 1100 ns +target1: get_direct_mem_ptr OK, extension data = 13 +initiator1: got DMI pointer invalidation @ 1125 ns + +Info: /OSCI/SystemC: Simulation stopped by user. +initiator1, <>: + +Mem @0 +00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 +04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00 + diff --git a/src/systemc/tests/tlm/static_extensions/gp2ext/gp2ext.cpp b/src/systemc/tests/tlm/static_extensions/gp2ext/gp2ext.cpp new file mode 100644 index 000000000..0533e9d1b --- /dev/null +++ b/src/systemc/tests/tlm/static_extensions/gp2ext/gp2ext.cpp @@ -0,0 +1,40 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ +#define SC_INCLUDE_DYNAMIC_PROCESSES +#include "tlm.h" + +#include "SimpleLTInitiator1_DMI.h" +#include "SimpleLTTarget_ext.h" +#include "extension_adaptors.h" + + +int sc_main(int argc, char* argv[]) +{ + SimpleLTInitiator1_dmi initiator("initiator1", 10, 0x0); + adapt_gp2ext<32> bridge("bridge"); + SimpleLTTarget_ext target("target1"); + + initiator.socket(bridge.target_socket); + bridge.initiator_socket(target.socket); + + sc_core::sc_start(); + sc_core::sc_stop(); + + return 0; +} diff --git a/src/systemc/tests/tlm/static_extensions/gp2ext/my_extension.h b/src/systemc/tests/tlm/static_extensions/gp2ext/my_extension.h new file mode 100644 index 000000000..650931cd1 --- /dev/null +++ b/src/systemc/tests/tlm/static_extensions/gp2ext/my_extension.h @@ -0,0 +1,56 @@ +/***************************************************************************** + + 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 __MY_EXTENSION_H__ +#define __MY_EXTENSION_H__ + +#include "tlm.h" +#include + +class my_extension : + public tlm::tlm_extension +{ +public: + my_extension() + : m_data(0) + {} + tlm_extension_base* clone() const + { + return new my_extension(*this); + } + void free() + { + delete this; + } + void copy_from(tlm_extension_base const & e) + { + sc_assert(typeid(this) == typeid(e)); + m_data = static_cast(e).m_data; + } + + int m_data; +}; + +struct my_extended_payload_types +{ + typedef tlm::tlm_base_protocol_types::tlm_payload_type tlm_payload_type; + typedef tlm::tlm_base_protocol_types::tlm_phase_type tlm_phase_type; +}; + +#endif -- cgit v1.2.3