From 03f740664bc8db8890359c9c5ad02df9db478bae Mon Sep 17 00:00:00 2001 From: Christian Menard Date: Thu, 9 Feb 2017 19:15:41 -0500 Subject: [PATCH] misc: Clean up and complete the gem5<->SystemC-TLM bridge [5/10] Changeset 11798:3a490c57058d --------------------------- misc: Clean up and complete the gem5<->SystemC-TLM bridge [5/10] The current TLM bridge only provides a Slave Port that allows the gem5 world to send request to the SystemC world. This patch series refractors and cleans up the existing code, and adds a Master Port that allows the SystemC world to send requests to the gem5 world. This patch: * Introduce transactor modules that represent the gem5 ports in the * SystemC world. * Update the SimControl module and let it keep track of the gem5 ports. Reviewed at http://reviews.gem5.org/r/3775/ Signed-off-by: Jason Lowe-Power --- util/tlm/examples/master_port/main.cc | 24 +++----- util/tlm/examples/master_port/tlm.py | 2 +- util/tlm/examples/slave_port/main.cc | 27 +++------ util/tlm/examples/slave_port/run_gem5.sh | 2 +- util/tlm/examples/slave_port/tlm.py | 2 +- util/tlm/master_transactor.cc | 62 +++++++++++++++++++++ util/tlm/master_transactor.hh | 70 ++++++++++++++++++++++++ util/tlm/sc_master_port.cc | 61 +++++++++++---------- util/tlm/sc_master_port.hh | 32 ++++++++--- util/tlm/sc_slave_port.cc | 55 ++++++++++--------- util/tlm/sc_slave_port.hh | 30 +++++++--- util/tlm/sim_control.cc | 53 +++++++++++++++++- util/tlm/sim_control.hh | 17 +++++- util/tlm/sim_control_if.hh | 56 +++++++++++++++++++ util/tlm/slave_transactor.cc | 62 +++++++++++++++++++++ util/tlm/slave_transactor.hh | 70 ++++++++++++++++++++++++ 16 files changed, 510 insertions(+), 115 deletions(-) create mode 100644 util/tlm/master_transactor.cc create mode 100644 util/tlm/master_transactor.hh create mode 100644 util/tlm/sim_control_if.hh create mode 100644 util/tlm/slave_transactor.cc create mode 100644 util/tlm/slave_transactor.hh diff --git a/util/tlm/examples/master_port/main.cc b/util/tlm/examples/master_port/main.cc index 588d81156..2fb1caeae 100644 --- a/util/tlm/examples/master_port/main.cc +++ b/util/tlm/examples/master_port/main.cc @@ -36,8 +36,8 @@ #include #include "cli_parser.hh" +#include "master_transactor.hh" #include "report_handler.hh" -#include "sc_master_port.hh" #include "sim_control.hh" #include "stats.hh" #include "traffic_generator.hh" @@ -50,24 +50,16 @@ sc_main(int argc, char** argv) sc_core::sc_report_handler::set_handler(reportHandler); - Gem5SystemC::Gem5SimControl simControl("gem5", - parser.getConfigFile(), - parser.getSimulationEnd(), - parser.getDebugFlags()); + Gem5SystemC::Gem5SimControl sim_control("gem5", + parser.getConfigFile(), + parser.getSimulationEnd(), + parser.getDebugFlags()); TrafficGenerator trafficGenerator("traffic_generator"); + Gem5SystemC::Gem5MasterTransactor transactor("transactor", "transactor"); - tlm::tlm_target_socket<>* mem_port = - dynamic_cast*>( - sc_core::sc_find_object("gem5.memory")); - - if (mem_port) { - SC_REPORT_INFO("sc_main", "Port Found"); - trafficGenerator.socket.bind(*mem_port); - } else { - SC_REPORT_FATAL("sc_main", "Port Not Found"); - std::exit(EXIT_FAILURE); - } + trafficGenerator.socket.bind(transactor.socket); + transactor.sim_control.bind(sim_control); SC_REPORT_INFO("sc_main", "Start of Simulation"); diff --git a/util/tlm/examples/master_port/tlm.py b/util/tlm/examples/master_port/tlm.py index 13c4388a9..0b017a6d1 100644 --- a/util/tlm/examples/master_port/tlm.py +++ b/util/tlm/examples/master_port/tlm.py @@ -61,7 +61,7 @@ system.clk_domain = SrcClockDomain(clock = '1.5GHz', # Create a external TLM port: system.tlm = ExternalMaster() system.tlm.port_type = "tlm_master" -system.tlm.port_data = "memory" +system.tlm.port_data = "transactor" # Route the connections: system.system_port = system.membus.slave diff --git a/util/tlm/examples/slave_port/main.cc b/util/tlm/examples/slave_port/main.cc index 9f1cadc8d..5f555aa32 100644 --- a/util/tlm/examples/slave_port/main.cc +++ b/util/tlm/examples/slave_port/main.cc @@ -50,6 +50,7 @@ #include "report_handler.hh" #include "sc_target.hh" #include "sim_control.hh" +#include "slave_transactor.hh" #include "stats.hh" int @@ -60,31 +61,21 @@ sc_main(int argc, char **argv) sc_core::sc_report_handler::set_handler(reportHandler); - Gem5SystemC::Gem5SimControl simControl("gem5", + Gem5SystemC::Gem5SimControl sim_control("gem5", parser.getConfigFile(), parser.getSimulationEnd(), parser.getDebugFlags()); - Target *memory; unsigned long long int memorySize = 512*1024*1024ULL; - tlm::tlm_initiator_socket <> *mem_port = - dynamic_cast *>( - sc_core::sc_find_object("gem5.memory") - ); + Gem5SystemC::Gem5SlaveTransactor transactor("transactor", "transactor"); + Target memory("memory", + parser.getVerboseFlag(), + memorySize, + parser.getMemoryOffset()); - if (mem_port) { - SC_REPORT_INFO("sc_main", "Port Found"); - memory = new Target("memory", - parser.getVerboseFlag(), - memorySize, - parser.getMemoryOffset()); - - memory->socket.bind(*mem_port); - } else { - SC_REPORT_FATAL("sc_main", "Port Not Found"); - std::exit(EXIT_FAILURE); - } + memory.socket.bind(transactor.socket); + transactor.sim_control.bind(sim_control); SC_REPORT_INFO("sc_main", "Start of Simulation"); diff --git a/util/tlm/examples/slave_port/run_gem5.sh b/util/tlm/examples/slave_port/run_gem5.sh index a4a0b8021..fd14689b9 100644 --- a/util/tlm/examples/slave_port/run_gem5.sh +++ b/util/tlm/examples/slave_port/run_gem5.sh @@ -37,7 +37,7 @@ BGre='\e[1;31m'; echo -e "\n${BGre}Create gem5 Configuration${RCol}\n" ../../../../build/ARM/gem5.opt ../../../../configs/example/fs.py \ ---tlm-memory=memory \ +--tlm-memory=transactor \ --cpu-type=timing \ --num-cpu=1 \ --mem-type=SimpleMemory \ diff --git a/util/tlm/examples/slave_port/tlm.py b/util/tlm/examples/slave_port/tlm.py index 9d6b26db1..ed4db4047 100644 --- a/util/tlm/examples/slave_port/tlm.py +++ b/util/tlm/examples/slave_port/tlm.py @@ -64,7 +64,7 @@ system.clk_domain = SrcClockDomain(clock = '1.5GHz', system.tlm = ExternalSlave() system.tlm.addr_ranges = [AddrRange('512MB')] system.tlm.port_type = "tlm_slave" -system.tlm.port_data = "memory" +system.tlm.port_data = "transactor" # Route the connections: system.cpu.port = system.membus.slave diff --git a/util/tlm/master_transactor.cc b/util/tlm/master_transactor.cc new file mode 100644 index 000000000..9e8c2ffec --- /dev/null +++ b/util/tlm/master_transactor.cc @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2016, Dresden University of Technology (TU Dresden) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Christian Menard + */ + +#include "master_transactor.hh" +#include "sc_master_port.hh" +#include "sim_control.hh" + +namespace Gem5SystemC +{ + +Gem5MasterTransactor::Gem5MasterTransactor(sc_core::sc_module_name name, + const std::string& portName) + : sc_core::sc_module(name), + socket(portName.c_str()), + sim_control("sim_control"), + portName(portName) +{ + if (portName.empty()) { + SC_REPORT_ERROR(name, "No port name specified!\n"); + } +} + +void +Gem5MasterTransactor::before_end_of_elaboration() +{ + auto* port = sim_control->getMasterPort(portName); + + port->bindToTransactor(this); +} + +} diff --git a/util/tlm/master_transactor.hh b/util/tlm/master_transactor.hh new file mode 100644 index 000000000..242c712e7 --- /dev/null +++ b/util/tlm/master_transactor.hh @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2016, Dresden University of Technology (TU Dresden) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Christian Menard + */ + +#ifndef __GEM5_MASTER_TRANSACTOR_HH__ +#define __GEM5_MASTER_TRANSACTOR_HH__ + +#include + +#include +#include + +#include "sc_master_port.hh" +#include "sim_control_if.hh" + +namespace Gem5SystemC +{ + +class Gem5MasterTransactor : public sc_core::sc_module +{ + public: + // module interface + tlm_utils::simple_target_socket socket; + sc_core::sc_port sim_control; + + private: + std::string portName; + + public: + SC_HAS_PROCESS(Gem5MasterTransactor); + + Gem5MasterTransactor(sc_core::sc_module_name name, + const std::string& portName); + + void before_end_of_elaboration(); +}; + +} + +#endif diff --git a/util/tlm/sc_master_port.cc b/util/tlm/sc_master_port.cc index 06fab51a2..4ab1f51c6 100644 --- a/util/tlm/sc_master_port.cc +++ b/util/tlm/sc_master_port.cc @@ -34,6 +34,7 @@ #include +#include "master_transactor.hh" #include "params/ExternalMaster.hh" #include "sc_master_port.hh" #include "sim/system.hh" @@ -81,18 +82,26 @@ SCMasterPort::destroyPacket(PacketPtr pkt) SCMasterPort::SCMasterPort(const std::string& name_, const std::string& systemc_name, ExternalMaster& owner_, - Module& module) + Gem5SimControl& simControl) : ExternalMaster::Port(name_, owner_), - tSocket(systemc_name.c_str()), peq(this, &SCMasterPort::peq_cb), waitForRetry(false), pendingRequest(nullptr), needToSendRetry(false), responseInProgress(false), - module(module) + transactor(nullptr), + simControl(simControl) { - auto system = + system = dynamic_cast(owner_.params())->system; +} + +void +SCMasterPort::bindToTransactor(Gem5MasterTransactor* transactor) +{ + sc_assert(this->transactor == nullptr); + + this->transactor = transactor; /* * Register the TLM non-blocking interface when using gem5 Timing mode and @@ -104,16 +113,18 @@ SCMasterPort::SCMasterPort(const std::string& name_, */ if (system->isTimingMode()) { SC_REPORT_INFO("SCMasterPort", "register non-blocking interface"); - tSocket.register_nb_transport_fw(this, - &SCMasterPort::nb_transport_fw); + transactor->socket.register_nb_transport_fw(this, + &SCMasterPort::nb_transport_fw); } else if (system->isAtomicMode()) { SC_REPORT_INFO("SCMasterPort", "register blocking interface"); - tSocket.register_b_transport(this, &SCMasterPort::b_transport); + transactor->socket.register_b_transport(this, + &SCMasterPort::b_transport); } else { panic("gem5 operates neither in Timing nor in Atomic mode"); } - tSocket.register_transport_dbg(this, &SCMasterPort::transport_dbg); + transactor->socket.register_transport_dbg(this, + &SCMasterPort::transport_dbg); } void @@ -156,7 +167,7 @@ SCMasterPort::peq_cb(tlm::tlm_generic_payload& trans, const tlm::tlm_phase& phase) { // catch up with SystemC time - module.catchup(); + simControl.catchup(); assert(curTick() == sc_core::sc_time_stamp().value()); switch (phase) { @@ -172,7 +183,7 @@ SCMasterPort::peq_cb(tlm::tlm_generic_payload& trans, // the functions called above may have scheduled gem5 events // -> notify the event loop handler - module.notify(); + simControl.notify(); } void @@ -216,7 +227,7 @@ SCMasterPort::sendEndReq(tlm::tlm_generic_payload& trans) tlm::tlm_phase phase = tlm::END_REQ; auto delay = sc_core::SC_ZERO_TIME; - auto status = tSocket->nb_transport_bw(trans, phase, delay); + auto status = transactor->socket->nb_transport_bw(trans, phase, delay); panic_if(status != tlm::TLM_ACCEPTED, "Unexpected status after sending END_REQ"); } @@ -300,7 +311,7 @@ SCMasterPort::sendBeginResp(tlm::tlm_generic_payload& trans, trans.set_response_status(tlm::TLM_OK_RESPONSE); - auto status = tSocket->nb_transport_bw(trans, phase, delay); + auto status = transactor->socket->nb_transport_bw(trans, phase, delay); if (status == tlm::TLM_COMPLETED || status == tlm::TLM_UPDATED && phase == tlm::END_RESP) { @@ -336,27 +347,17 @@ SCMasterPort::recvRangeChange() "received address range change but ignored it"); } -class SCMasterPortHandler : public ExternalMaster::Handler +ExternalMaster::Port* +SCMasterPortHandler::getExternalPort(const std::string &name, + ExternalMaster &owner, + const std::string &port_data) { - Module& module; + // Create and register a new SystemC master port + auto* port = new SCMasterPort(name, port_data, owner, control); - public: - SCMasterPortHandler(Module& module) : module(module) {} + control.registerMasterPort(port_data, port); - ExternalMaster::Port* getExternalPort(const std::string& name, - ExternalMaster& owner, - const std::string& port_data) - { - // This will make a new initiatiator port - return new SCMasterPort(name, port_data, owner, module); - } -}; - -void -SCMasterPort::registerPortHandler(Module& module) -{ - ExternalMaster::registerHandler("tlm_master", - new SCMasterPortHandler(module)); + return port; } } // namespace Gem5SystemC diff --git a/util/tlm/sc_master_port.hh b/util/tlm/sc_master_port.hh index f2ac1580e..5fae9b6b4 100644 --- a/util/tlm/sc_master_port.hh +++ b/util/tlm/sc_master_port.hh @@ -36,17 +36,20 @@ #define __SC_MASTER_PORT_HH__ #include -#include +#include #include #include -#include #include +#include namespace Gem5SystemC { +// forward declaration +class Gem5MasterTransactor; + /** * This is a gem5 master port that translates TLM transactions to gem5 packets. * @@ -84,11 +87,11 @@ class SCMasterPort : public ExternalMaster::Port bool responseInProgress; - // Keep a reference to the gem5 SystemC module - Module& module; + Gem5MasterTransactor* transactor; - public: - tlm_utils::simple_target_socket tSocket; + System* system; + + Gem5SimControl& simControl; protected: // payload event call back @@ -112,9 +115,9 @@ class SCMasterPort : public ExternalMaster::Port SCMasterPort(const std::string& name_, const std::string& systemc_name, ExternalMaster& owner_, - Module& module); + Gem5SimControl& simControl); - static void registerPortHandler(Module& module); + void bindToTransactor(Gem5MasterTransactor* transactor); friend PayloadEvent; @@ -132,6 +135,19 @@ class SCMasterPort : public ExternalMaster::Port void checkTransaction(tlm::tlm_generic_payload& trans); }; +class SCMasterPortHandler : public ExternalMaster::Handler +{ + private: + Gem5SimControl& control; + + public: + SCMasterPortHandler(Gem5SimControl& control) : control(control) {} + + ExternalMaster::Port *getExternalPort(const std::string &name, + ExternalMaster &owner, + const std::string &port_data); +}; + } #endif diff --git a/util/tlm/sc_slave_port.cc b/util/tlm/sc_slave_port.cc index 3176de928..cc4218fc0 100644 --- a/util/tlm/sc_slave_port.cc +++ b/util/tlm/sc_slave_port.cc @@ -35,14 +35,10 @@ * Christian Menard */ -#include -#include -#include - -#include "debug/ExternalPort.hh" #include "sc_ext.hh" #include "sc_mm.hh" #include "sc_slave_port.hh" +#include "slave_transactor.hh" namespace Gem5SystemC { @@ -116,11 +112,11 @@ SCSlavePort::recvAtomic(PacketPtr packet) if (packet->cmd == MemCmd::SwapReq) { SC_REPORT_FATAL("SCSlavePort", "SwapReq not supported"); } else if (packet->isRead()) { - iSocket->b_transport(*trans, delay); + transactor->socket->b_transport(*trans, delay); } else if (packet->isInvalidate()) { // do nothing } else if (packet->isWrite()) { - iSocket->b_transport(*trans, delay); + transactor->socket->b_transport(*trans, delay); } else { SC_REPORT_FATAL("SCSlavePort", "Typo of request not supported"); } @@ -150,7 +146,7 @@ SCSlavePort::recvFunctional(PacketPtr packet) trans->set_auto_extension(extension); /* Execute Debug Transport: */ - unsigned int bytes = iSocket->transport_dbg(*trans); + unsigned int bytes = transactor->socket->transport_dbg(*trans); if (bytes != trans->get_data_length()) { SC_REPORT_FATAL("SCSlavePort","debug transport was not completed"); } @@ -223,7 +219,7 @@ SCSlavePort::recvTimingReq(PacketPtr packet) sc_core::sc_time delay = sc_core::SC_ZERO_TIME; tlm::tlm_phase phase = tlm::BEGIN_REQ; tlm::tlm_sync_enum status; - status = iSocket->nb_transport_fw(*trans, phase, delay); + status = transactor->socket->nb_transport_fw(*trans, phase, delay); /* Check returned value: */ if (status == tlm::TLM_ACCEPTED) { sc_assert(phase == tlm::BEGIN_REQ); @@ -288,7 +284,7 @@ SCSlavePort::pec( /* Send END_RESP and we're finished: */ tlm::tlm_phase fw_phase = tlm::END_RESP; sc_time delay = SC_ZERO_TIME; - iSocket->nb_transport_fw(trans, fw_phase, delay); + transactor->socket->nb_transport_fw(trans, fw_phase, delay); /* Release the transaction with all the extensions */ trans.release(); } @@ -317,7 +313,7 @@ SCSlavePort::recvRespRetry() sc_core::sc_time delay = sc_core::SC_ZERO_TIME; tlm::tlm_phase phase = tlm::END_RESP; - iSocket->nb_transport_fw(*trans, phase, delay); + transactor->socket->nb_transport_fw(*trans, phase, delay); // Release transaction with all the extensions trans->release(); } @@ -337,30 +333,35 @@ SCSlavePort::SCSlavePort(const std::string &name_, const std::string &systemc_name, ExternalSlave &owner_) : ExternalSlave::Port(name_, owner_), - iSocket(systemc_name.c_str()), blockingRequest(NULL), needToSendRequestRetry(false), - blockingResponse(NULL) + blockingResponse(NULL), + transactor(nullptr) { - iSocket.register_nb_transport_bw(this, &SCSlavePort::nb_transport_bw); } -class SlavePortHandler : public ExternalSlave::Handler +void +SCSlavePort::bindToTransactor(Gem5SlaveTransactor* transactor) { - public: - ExternalSlave::Port *getExternalPort(const std::string &name, - ExternalSlave &owner, - const std::string &port_data) - { - // This will make a new initiatiator port - return new SCSlavePort(name, port_data, owner); - } -}; + sc_assert(this->transactor == nullptr); -void -SCSlavePort::registerPortHandler() + this->transactor = transactor; + + transactor->socket.register_nb_transport_bw(this, + &SCSlavePort::nb_transport_bw); +} + +ExternalSlave::Port* +SCSlavePortHandler::getExternalPort(const std::string &name, + ExternalSlave &owner, + const std::string &port_data) { - ExternalSlave::registerHandler("tlm_slave", new SlavePortHandler); + // Create and register a new SystemC slave port + auto* port = new SCSlavePort(name, port_data, owner); + + control.registerSlavePort(port_data, port); + + return port; } } diff --git a/util/tlm/sc_slave_port.hh b/util/tlm/sc_slave_port.hh index 9e37ff4bb..6f8f6a633 100644 --- a/util/tlm/sc_slave_port.hh +++ b/util/tlm/sc_slave_port.hh @@ -37,19 +37,20 @@ #ifndef __SC_SLAVE_PORT_HH__ #define __SC_SLAVE_PORT_HH__ -#include - -#include #include #include #include "mem/external_slave.hh" #include "sc_mm.hh" -#include "sc_module.hh" #include "sc_peq.hh" +#include "sim_control.hh" namespace Gem5SystemC { + +// forward declaration +class Gem5SlaveTransactor; + /** * Test that gem5 is at the same time as SystemC */ @@ -70,8 +71,6 @@ namespace Gem5SystemC class SCSlavePort : public ExternalSlave::Port { public: - tlm_utils::simple_initiator_socket iSocket; - /** One instance of pe and the related callback needed */ //payloadEvent pe; void pec(PayloadEvent * pe, @@ -104,21 +103,36 @@ class SCSlavePort : public ExternalSlave::Port void recvRespRetry(); void recvFunctionalSnoop(PacketPtr packet); + Gem5SlaveTransactor* transactor; + + public: /** The TLM initiator interface */ tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload& trans, tlm::tlm_phase& phase, sc_core::sc_time& t); - public: SCSlavePort(const std::string &name_, const std::string &systemc_name, ExternalSlave &owner_); - static void registerPortHandler(); + void bindToTransactor(Gem5SlaveTransactor* transactor); friend PayloadEvent; }; +class SCSlavePortHandler : public ExternalSlave::Handler +{ + private: + Gem5SimControl& control; + + public: + SCSlavePortHandler(Gem5SimControl& control) : control(control) {} + + ExternalSlave::Port *getExternalPort(const std::string &name, + ExternalSlave &owner, + const std::string &port_data); +}; + } #endif // __SC_SLAVE_PORT_H__ diff --git a/util/tlm/sim_control.cc b/util/tlm/sim_control.cc index d6bedc80b..f6a3e4ffe 100644 --- a/util/tlm/sim_control.cc +++ b/util/tlm/sim_control.cc @@ -77,8 +77,11 @@ Gem5SimControl::Gem5SimControl(sc_core::sc_module_name name, instance = this; cxxConfigInit(); - Gem5SystemC::SCSlavePort::registerPortHandler(); - Gem5SystemC::SCMasterPort::registerPortHandler(*this); + + // register the systemc slave and master port handler + ExternalSlave::registerHandler("tlm_slave", new SCSlavePortHandler(*this)); + ExternalMaster::registerHandler("tlm_master", + new SCMasterPortHandler(*this)); Trace::setDebugLogger(&logger); @@ -134,7 +137,7 @@ Gem5SimControl::Gem5SimControl(sc_core::sc_module_name name, } void -Gem5SimControl::before_end_of_elaboration() +Gem5SimControl::end_of_elaboration() { try { config_manager->initState(); @@ -167,4 +170,48 @@ Gem5SimControl::run() #endif } +void +Gem5SimControl::registerSlavePort(const std::string& name, SCSlavePort* port) +{ + if (slavePorts.find(name) == slavePorts.end()) { + slavePorts[name] = port; + } else { + std::cerr << "Slave Port " << name << " is already registered!\n"; + std::exit(EXIT_FAILURE); + } +} + +void +Gem5SimControl::registerMasterPort(const std::string& name, SCMasterPort* port) +{ + if (masterPorts.find(name) == masterPorts.end()) { + masterPorts[name] = port; + } else { + std::cerr << "Master Port " << name << " is already registered!\n"; + std::exit(EXIT_FAILURE); + } +} + +SCSlavePort* +Gem5SimControl::getSlavePort(const std::string& name) +{ + if (slavePorts.find(name) == slavePorts.end()) { + std::cerr << "Slave Port " << name << " was not found!\n"; + std::exit(EXIT_FAILURE); + } + + return slavePorts.at(name); +} + +SCMasterPort* +Gem5SimControl::getMasterPort(const std::string& name) +{ + if (masterPorts.find(name) == masterPorts.end()) { + std::cerr << "Master Port " << name << " was not found!\n"; + std::exit(EXIT_FAILURE); + } + + return masterPorts.at(name); +} + } diff --git a/util/tlm/sim_control.hh b/util/tlm/sim_control.hh index d210d76dd..b411022de 100644 --- a/util/tlm/sim_control.hh +++ b/util/tlm/sim_control.hh @@ -46,6 +46,7 @@ #include "sc_module.hh" #include "sim/cxx_manager.hh" #include "sim/system.hh" +#include "sim_control_if.hh" namespace Gem5SystemC { @@ -58,7 +59,7 @@ namespace Gem5SystemC * While it is mandatory to have one instance of this class for running a gem5 * simulation in SystemC, it is not allowed to have multiple instances! */ -class Gem5SimControl : public Gem5SystemC::Module +class Gem5SimControl : public Module, public Gem5SimControlInterface { protected: CxxConfigManager* config_manager; @@ -66,6 +67,13 @@ class Gem5SimControl : public Gem5SystemC::Module Tick simulationEnd; + /* + * Keep track of the slave and master ports that are created by gem5 + * according to the config file. + */ + std::map slavePorts; + std::map masterPorts; + /// Pointer to a previously created instance. static Gem5SimControl* instance; @@ -90,7 +98,12 @@ class Gem5SimControl : public Gem5SystemC::Module uint64_t simulationEnd, const std::string& gem5DebugFlags); - void before_end_of_elaboration(); + void registerSlavePort(const std::string& name, SCSlavePort* port); + void registerMasterPort(const std::string& name, SCMasterPort* port); + SCSlavePort* getSlavePort(const std::string& name) override; + SCMasterPort* getMasterPort(const std::string& name) override; + + void end_of_elaboration(); void run(); }; diff --git a/util/tlm/sim_control_if.hh b/util/tlm/sim_control_if.hh new file mode 100644 index 000000000..b65e919d2 --- /dev/null +++ b/util/tlm/sim_control_if.hh @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2017, Dresden University of Technology (TU Dresden) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Christian Menard + */ + +#ifndef __SC_SIM_CONTROL_IF_HH__ +#define __SC_SIM_CONTROL_IF_HH__ + +#include + +namespace Gem5SystemC +{ + +// forward declerations +class SCSlavePort; +class SCMasterPort; + +class Gem5SimControlInterface : public sc_core::sc_interface +{ + public: + virtual SCSlavePort* getSlavePort(const std::string& name) = 0; + virtual SCMasterPort* getMasterPort(const std::string& name) = 0; +}; + +} + +#endif diff --git a/util/tlm/slave_transactor.cc b/util/tlm/slave_transactor.cc new file mode 100644 index 000000000..d181156c6 --- /dev/null +++ b/util/tlm/slave_transactor.cc @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2016, Dresden University of Technology (TU Dresden) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Christian Menard + */ + +#include "sc_slave_port.hh" +#include "sim_control.hh" +#include "slave_transactor.hh" + +namespace Gem5SystemC +{ + +Gem5SlaveTransactor::Gem5SlaveTransactor(sc_core::sc_module_name name, + const std::string& portName) + : sc_core::sc_module(name), + socket(portName.c_str()), + sim_control("sim_control"), + portName(portName) +{ + if (portName.empty()) { + SC_REPORT_ERROR(name, "No port name specified!\n"); + } +} + +void +Gem5SlaveTransactor::before_end_of_elaboration() +{ + auto* port = sim_control->getSlavePort(portName); + + port->bindToTransactor(this); +} + +} diff --git a/util/tlm/slave_transactor.hh b/util/tlm/slave_transactor.hh new file mode 100644 index 000000000..6a9c5e836 --- /dev/null +++ b/util/tlm/slave_transactor.hh @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2016, Dresden University of Technology (TU Dresden) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Christian Menard + */ + +#ifndef __GEM5_SLAVE_TRANSACTOR_HH__ +#define __GEM5_SLAVE_TRANSACTOR_HH__ + +#include + +#include +#include + +#include "sc_slave_port.hh" +#include "sim_control_if.hh" + +namespace Gem5SystemC +{ + +class Gem5SlaveTransactor : public sc_core::sc_module +{ + public: + // module interface + tlm_utils::simple_initiator_socket socket; + sc_core::sc_port sim_control; + + private: + std::string portName; + + public: + SC_HAS_PROCESS(Gem5SlaveTransactor); + + Gem5SlaveTransactor(sc_core::sc_module_name name, + const std::string& portName); + + void before_end_of_elaboration(); +}; + +} + +#endif -- 2.30.2