diff options
author | Christian Menard <Christian.Menard@tu-dresden.de> | 2017-02-09 19:15:30 -0500 |
---|---|---|
committer | Christian Menard <Christian.Menard@tu-dresden.de> | 2017-02-09 19:15:30 -0500 |
commit | b25ea094d4350b8257d5f383a123ea620b614adf (patch) | |
tree | bf2be24b719fb45325012542bb77288f18ccb66e | |
parent | 41a61589545c284d109019c3cb528762b8345aa0 (diff) | |
download | gem5-b25ea094d4350b8257d5f383a123ea620b614adf.tar.xz |
misc: Clean up and complete the gem5<->SystemC-TLM bridge [1/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:
* Restructure the existing sources in preparation of the addition of the
* new
Master Port.
* Refractor names to allow for distinction of the slave and master port.
* Replace the Makefile by a SConstruct.
Testing Done: The examples provided in util/tlm (now
util/tlm/examples/slave_port) still compile and run error free.
Reviewed at http://reviews.gem5.org/r/3527/
Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
-rw-r--r-- | configs/common/MemConfig.py | 2 | ||||
-rw-r--r-- | util/tlm/examples/slave_port/SConstruct (renamed from util/tlm/Makefile) | 85 | ||||
-rw-r--r-- | util/tlm/examples/slave_port/main.cc | 115 | ||||
-rw-r--r-- | util/tlm/examples/slave_port/run_gem5.sh (renamed from util/tlm/run_gem5.sh) | 2 | ||||
-rw-r--r-- | util/tlm/examples/slave_port/sc_target.cc (renamed from util/tlm/sc_target.cc) | 6 | ||||
-rw-r--r-- | util/tlm/examples/slave_port/sc_target.hh (renamed from util/tlm/sc_target.hh) | 0 | ||||
-rw-r--r-- | util/tlm/examples/slave_port/tgen.cfg (renamed from util/tlm/tgen.cfg) | 0 | ||||
-rw-r--r-- | util/tlm/examples/slave_port/tlm.py (renamed from util/tlm/tlm.py) | 4 | ||||
-rw-r--r-- | util/tlm/examples/slave_port/tlm_elastic.py (renamed from util/tlm/tlm_elastic.py) | 0 | ||||
-rw-r--r-- | util/tlm/sc_ext.cc | 27 | ||||
-rw-r--r-- | util/tlm/sc_ext.hh | 21 | ||||
-rw-r--r-- | util/tlm/sc_mm.cc | 5 | ||||
-rw-r--r-- | util/tlm/sc_mm.hh | 11 | ||||
-rw-r--r-- | util/tlm/sc_peq.hh | 102 | ||||
-rw-r--r-- | util/tlm/sc_slave_port.cc (renamed from util/tlm/sc_port.cc) | 72 | ||||
-rw-r--r-- | util/tlm/sc_slave_port.hh (renamed from util/tlm/sc_port.hh) | 97 | ||||
-rw-r--r-- | util/tlm/sim_control.cc (renamed from util/tlm/main.cc) | 157 | ||||
-rw-r--r-- | util/tlm/sim_control.hh | 76 |
18 files changed, 477 insertions, 305 deletions
diff --git a/configs/common/MemConfig.py b/configs/common/MemConfig.py index 71e3bf460..2cfa25e58 100644 --- a/configs/common/MemConfig.py +++ b/configs/common/MemConfig.py @@ -163,7 +163,7 @@ def config_mem(options, system): if options.tlm_memory: system.external_memory = m5.objects.ExternalSlave( - port_type="tlm", + port_type="tlm_slave", port_data=options.tlm_memory, port=system.membus.master, addr_ranges=system.mem_ranges) diff --git a/util/tlm/Makefile b/util/tlm/examples/slave_port/SConstruct index 1fda3b113..8ca9959a0 100644 --- a/util/tlm/Makefile +++ b/util/tlm/examples/slave_port/SConstruct @@ -1,21 +1,23 @@ -# Copyright (c) 2015, University of Kaiserslautern +#!python + +# 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 @@ -27,50 +29,49 @@ # 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: Matthias Jung +# +# Authors: Christian Menard + +import os + +gem5_arch = 'ARM' +gem5_variant = 'opt' +#gem5_variant = 'debug' + +gem5_root = '#../../../..' +target = 'gem5.' + gem5_variant + '.sc' -ARCH = ARM -VARIANT = opt -#VARIANT = debug +env = Environment() -SYSTEMC_INC = /opt/systemc/include -SYSTEMC_LIB = /opt/systemc/lib-linux64 +# Import PKG_CONFIG_PATH from the external environment +if os.environ.has_key('PKG_CONFIG_PATH'): + env['ENV']['PKG_CONFIG_PATH'] = os.environ['PKG_CONFIG_PATH'] -CXXFLAGS = -I../../build/$(ARCH) -L../../build/$(ARCH) -CXXFLAGS += -I../systemc/ -CXXFLAGS += -I$(SYSTEMC_INC) -L$(SYSTEMC_LIB) -CXXFLAGS += -std=c++0x -CXXFLAGS += -g -CXXFLAGS += -DSC_INCLUDE_DYNAMIC_PROCESSES -DDEBUG -DTRACING_ON +# search for SystemC +env.ParseConfig('pkg-config --cflags --libs systemc') -LIBS = -lgem5_$(VARIANT) -lsystemc +# add include dirs +env.Append(CPPPATH=[gem5_root + '/build/' + gem5_arch, + gem5_root + '/util/systemc', + gem5_root + '/util/tlm']) -ALL = gem5.$(VARIANT).sc +env.Append(LIBS=['gem5_' + gem5_variant]) +env.Append(LIBPATH=[gem5_root + '/build/' + gem5_arch]) -all: $(ALL) +env.Append(CXXFLAGS=['-std=c++11', + '-DSC_INCLUDE_DYNAMIC_PROCESSES', + '-DTRACING_ON']) -.cc.o: - $(CXX) $(CXXFLAGS) -c -o $@ $< +if gem5_variant == 'debug': + env.Append(CXXFLAGS=['-g', '-DDEBUG']) -sc_gem5_control.o: ../systemc/sc_gem5_control.cc \ - ../systemc/sc_gem5_control.hh -sc_logger.o: ../systemc/sc_logger.cc ../systemc/sc_logger.hh -sc_module.o: ../systemc/sc_module.cc ../systemc/sc_module.hh -sc_mm.o: sc_mm.cc sc_mm.hh -sc_ext.o: sc_ext.cc sc_ext.hh -sc_port.o: sc_port.cc sc_port.hh -sc_target.o: sc_target.cc sc_target.hh -stats.o: ../systemc/stats.cc ../systemc/stats.hh -main.o: main.cc ../systemc/sc_logger.hh ../systemc/sc_module.hh \ - ../systemc/stats.hh +src_systemc = [gem5_root + '/util/systemc/sc_gem5_control.cc', + gem5_root + '/util/systemc/sc_logger.cc', + gem5_root + '/util/systemc/sc_module.cc', + gem5_root + '/util/systemc/stats.cc'] -gem5.$(VARIANT).sc: main.o ../systemc/stats.o ../systemc/sc_gem5_control.o \ - ../systemc/sc_logger.o ../systemc/sc_module.o sc_mm.o sc_ext.o sc_port.o sc_target.o - $(CXX) $(CXXFLAGS) -o $@ $^ $(LIBS) +src_tlm = Glob(gem5_root + '/util/tlm/*.cc') +src_main = Glob('*.cc') -clean: - $(RM) $(ALL) - $(RM) *.o - $(RM) -r m5out +main = env.Program(target, src_systemc + src_tlm + src_main) diff --git a/util/tlm/examples/slave_port/main.cc b/util/tlm/examples/slave_port/main.cc new file mode 100644 index 000000000..256a99d1b --- /dev/null +++ b/util/tlm/examples/slave_port/main.cc @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2015, University of Kaiserslautern + * 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: Matthias Jung + * Christian Menard + * Abdul Mutaal Ahmad + */ + +/** + * @file + * + * Example top level file for SystemC-TLM integration with C++-only + * instantiation. + * + */ + +#include <tlm_utils/simple_target_socket.h> + +#include <systemc> +#include <tlm> + +#include "sc_target.hh" +#include "sim_control.hh" +#include "stats.hh" + +// Defining global string variable decalred in stats.hh +std::string filename; + +void +reportHandler(const sc_core::sc_report &report, + const sc_core::sc_actions &actions) +{ + uint64_t systemc_time = report.get_time().value(); + uint64_t gem5_time = curTick(); + + std::cerr << report.get_time(); + + if (gem5_time < systemc_time) { + std::cerr << " (<) "; + } else if (gem5_time > systemc_time) { + std::cerr << " (!) "; + } else { + std::cerr << " (=) "; + } + + std::cerr << ": " << report.get_msg_type() + << ' ' << report.get_msg() << '\n'; +} + +int +sc_main(int argc, char **argv) +{ + sc_core::sc_report_handler::set_handler(reportHandler); + + SimControl sim_control("gem5", argc, argv); + Target *memory; + + filename = "m5out/stats-systemc.txt"; + + tlm::tlm_initiator_socket <> *mem_port = + dynamic_cast<tlm::tlm_initiator_socket<> *>( + sc_core::sc_find_object("gem5.memory") + ); + + if (mem_port) { + SC_REPORT_INFO("sc_main", "Port Found"); + unsigned long long int size = 512*1024*1024ULL; + memory = new Target("memory", + sim_control.getDebugFlag(), + size, + sim_control.getOffset()); + + memory->socket.bind(*mem_port); + } else { + SC_REPORT_FATAL("sc_main", "Port Not Found"); + std::exit(EXIT_FAILURE); + } + + sc_core::sc_start(); + + SC_REPORT_INFO("sc_main", "End of Simulation"); + + CxxConfig::statsDump(); + + return EXIT_SUCCESS; +} diff --git a/util/tlm/run_gem5.sh b/util/tlm/examples/slave_port/run_gem5.sh index c50391e69..a4a0b8021 100644 --- a/util/tlm/run_gem5.sh +++ b/util/tlm/examples/slave_port/run_gem5.sh @@ -36,7 +36,7 @@ RCol='\e[0m'; # Text Reset BGre='\e[1;31m'; echo -e "\n${BGre}Create gem5 Configuration${RCol}\n" -../../build/ARM/gem5.opt ../../configs/example/fs.py \ +../../../../build/ARM/gem5.opt ../../../../configs/example/fs.py \ --tlm-memory=memory \ --cpu-type=timing \ --num-cpu=1 \ diff --git a/util/tlm/sc_target.cc b/util/tlm/examples/slave_port/sc_target.cc index bae1de126..c44a27149 100644 --- a/util/tlm/sc_target.cc +++ b/util/tlm/examples/slave_port/sc_target.cc @@ -165,7 +165,7 @@ Target::send_end_req(tlm::tlm_generic_payload& trans) /* Queue the acceptance and the response with the appropriate latency */ bw_phase = tlm::END_REQ; - delay = sc_time(10, SC_NS); // Accept delay + delay = sc_time(10.0, SC_NS); // Accept delay tlm::tlm_sync_enum status; status = socket->nb_transport_bw(trans, bw_phase, delay); @@ -173,7 +173,7 @@ Target::send_end_req(tlm::tlm_generic_payload& trans) /* Ignore return value; * initiator cannot terminate transaction at this point * Queue internal event to mark beginning of response: */ - delay = delay + sc_time(40, SC_NS); // Latency + delay = delay + sc_time(40.0, SC_NS); // Latency target_done_event.notify(delay); assert(transaction_in_progress == 0); @@ -249,7 +249,7 @@ Target::send_response(tlm::tlm_generic_payload& trans) response_in_progress = true; bw_phase = tlm::BEGIN_RESP; - delay = sc_time(10, SC_NS); + delay = sc_time(10.0, SC_NS); status = socket->nb_transport_bw( trans, bw_phase, delay ); if (status == tlm::TLM_UPDATED) { diff --git a/util/tlm/sc_target.hh b/util/tlm/examples/slave_port/sc_target.hh index 7a2d075d9..7a2d075d9 100644 --- a/util/tlm/sc_target.hh +++ b/util/tlm/examples/slave_port/sc_target.hh diff --git a/util/tlm/tgen.cfg b/util/tlm/examples/slave_port/tgen.cfg index e341d8574..e341d8574 100644 --- a/util/tlm/tgen.cfg +++ b/util/tlm/examples/slave_port/tgen.cfg diff --git a/util/tlm/tlm.py b/util/tlm/examples/slave_port/tlm.py index e9025abab..9d6b26db1 100644 --- a/util/tlm/tlm.py +++ b/util/tlm/examples/slave_port/tlm.py @@ -45,7 +45,7 @@ from m5.objects import * # | | | # +-------v------v-------+ | # | Membus | v -# +----------------+-----+ External Port (see sc_port.*) +# +----------------+-----+ External Port (see sc_slave_port.*) # | ^ # +---v---+ | TLM World # | TLM | | (see sc_target.*) @@ -63,7 +63,7 @@ system.clk_domain = SrcClockDomain(clock = '1.5GHz', # Create a external TLM port: system.tlm = ExternalSlave() system.tlm.addr_ranges = [AddrRange('512MB')] -system.tlm.port_type = "tlm" +system.tlm.port_type = "tlm_slave" system.tlm.port_data = "memory" # Route the connections: diff --git a/util/tlm/tlm_elastic.py b/util/tlm/examples/slave_port/tlm_elastic.py index 3de0670c0..3de0670c0 100644 --- a/util/tlm/tlm_elastic.py +++ b/util/tlm/examples/slave_port/tlm_elastic.py diff --git a/util/tlm/sc_ext.cc b/util/tlm/sc_ext.cc index ce7417e49..db0c36f03 100644 --- a/util/tlm/sc_ext.cc +++ b/util/tlm/sc_ext.cc @@ -1,5 +1,6 @@ /* * Copyright (c) 2015, University of Kaiserslautern + * Copyright (c) 2016, Dresden University of Technology (TU Dresden) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,42 +32,48 @@ * * Authors: * Matthias Jung + * Christian Menard */ #include "sc_ext.hh" using namespace tlm; -gem5Extension::gem5Extension(PacketPtr packet) +namespace Gem5SystemC +{ + +Gem5Extension::Gem5Extension(PacketPtr packet) { Packet = packet; } -gem5Extension& gem5Extension::getExtension(const tlm_generic_payload *payload) +Gem5Extension& Gem5Extension::getExtension(const tlm_generic_payload *payload) { - gem5Extension *result = NULL; + Gem5Extension *result = NULL; payload->get_extension(result); sc_assert(result!=NULL); return *result; } -gem5Extension& gem5Extension::getExtension(const tlm_generic_payload &payload) +Gem5Extension& Gem5Extension::getExtension(const tlm_generic_payload &payload) { - return gem5Extension::getExtension(&payload); + return Gem5Extension::getExtension(&payload); } -PacketPtr gem5Extension::getPacket() +PacketPtr Gem5Extension::getPacket() { return Packet; } -tlm_extension_base* gem5Extension::clone() const +tlm_extension_base* Gem5Extension::clone() const { - return new gem5Extension(Packet); + return new Gem5Extension(Packet); } -void gem5Extension::copy_from(const tlm_extension_base& ext) +void Gem5Extension::copy_from(const tlm_extension_base& ext) { - const gem5Extension& cpyFrom = static_cast<const gem5Extension&>(ext); + const Gem5Extension& cpyFrom = static_cast<const Gem5Extension&>(ext); Packet = cpyFrom.Packet; } + +} diff --git a/util/tlm/sc_ext.hh b/util/tlm/sc_ext.hh index cb7411e44..79416f5ce 100644 --- a/util/tlm/sc_ext.hh +++ b/util/tlm/sc_ext.hh @@ -1,5 +1,6 @@ /* * Copyright (c) 2015, University of Kaiserslautern + * Copyright (c) 2016, Dresden University of Technology (TU Dresden) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,10 +32,11 @@ * * Authors: * Matthias Jung + * Christian Menard */ -#ifndef SC_EXT_H_ -#define SC_EXT_H_ +#ifndef __SC_EXT_HH__ +#define __SC_EXT_HH__ #include <systemc.h> #include <tlm.h> @@ -43,20 +45,27 @@ #include "mem/packet.hh" -class gem5Extension: public tlm::tlm_extension<gem5Extension> +namespace Gem5SystemC +{ + +class Gem5Extension: public tlm::tlm_extension<Gem5Extension> { public: - gem5Extension(PacketPtr packet); + Gem5Extension(PacketPtr packet); virtual tlm_extension_base* clone() const; virtual void copy_from(const tlm_extension_base& ext); - static gem5Extension& getExtension(const tlm::tlm_generic_payload *payload); - static gem5Extension& getExtension(const tlm::tlm_generic_payload &payload); + static Gem5Extension& + getExtension(const tlm::tlm_generic_payload *payload); + static Gem5Extension& + getExtension(const tlm::tlm_generic_payload &payload); PacketPtr getPacket(); private: PacketPtr Packet; }; +} + #endif diff --git a/util/tlm/sc_mm.cc b/util/tlm/sc_mm.cc index 2a169a37a..f5c07392c 100644 --- a/util/tlm/sc_mm.cc +++ b/util/tlm/sc_mm.cc @@ -40,6 +40,9 @@ using namespace std; +namespace Gem5SystemC +{ + MemoryManager::MemoryManager(): numberOfAllocations(0), numberOfFrees(0) { @@ -72,3 +75,5 @@ MemoryManager::free(gp* payload) payload->reset(); //clears all extensions freePayloads.push_back(payload); } + +} diff --git a/util/tlm/sc_mm.hh b/util/tlm/sc_mm.hh index 86d9ee11c..81316e7f6 100644 --- a/util/tlm/sc_mm.hh +++ b/util/tlm/sc_mm.hh @@ -34,13 +34,16 @@ * Matthias Jung */ -#ifndef MEMORYMANAGER_H_ -#define MEMORYMANAGER_H_ +#ifndef __SC_MM_HH__ +#define __SC_MM_HH__ #include <tlm.h> #include <vector> +namespace Gem5SystemC +{ + typedef tlm::tlm_generic_payload gp; class MemoryManager : public tlm::tlm_mm_interface @@ -57,4 +60,6 @@ class MemoryManager : public tlm::tlm_mm_interface std::vector<gp*> freePayloads; }; -#endif /* MEMORYMANAGER_H_ */ +} + +#endif /* __SC_MM_HH__ */ diff --git a/util/tlm/sc_peq.hh b/util/tlm/sc_peq.hh new file mode 100644 index 000000000..386142b72 --- /dev/null +++ b/util/tlm/sc_peq.hh @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2015, University of Kaiserslautern + * 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: Matthias Jung + * Christian Menard + */ + +#ifndef PAYLOAD_EVENT_H_ +#define PAYLOAD_EVENT_H_ + +// TLM includes +#include <tlm.h> + +// gem5 includes +#include <sim/eventq.hh> + +namespace Gem5SystemC { +/** + * A 'Fake Payload Event Queue', similar to the TLM PEQs. This helps the + * transactors to schedule events in gem5. + */ +template <typename OWNER> +class PayloadEvent : public Event +{ + public: + OWNER& port; + const std::string eventName; + void (OWNER::*handler)(PayloadEvent<OWNER>* pe, + tlm::tlm_generic_payload& trans, + const tlm::tlm_phase& phase); + + protected: + tlm::tlm_generic_payload* t; + tlm::tlm_phase p; + + void process() { (port.*handler)(this, *t, p); } + + public: + const std::string name() const { return eventName; } + + PayloadEvent(OWNER& port_, + void (OWNER::*handler_)(PayloadEvent<OWNER>* pe, + tlm::tlm_generic_payload& trans, + const tlm::tlm_phase& phase), + const std::string& event_name) + : port(port_) + , eventName(event_name) + , handler(handler_) + { + } + + /// Schedule an event into gem5 + void notify(tlm::tlm_generic_payload& trans, const tlm::tlm_phase& phase, + const sc_core::sc_time& delay) + { + assert(!scheduled()); + + t = &trans; + p = phase; + + /** + * Get time from SystemC as this will always be more up to date + * than gem5's + */ + Tick nextEventTick = sc_core::sc_time_stamp().value() + delay.value(); + + port.owner.wakeupEventQueue(nextEventTick); + port.owner.schedule(this, nextEventTick); + } +}; +} + +#endif diff --git a/util/tlm/sc_port.cc b/util/tlm/sc_slave_port.cc index ab94f73ca..cea0f6db6 100644 --- a/util/tlm/sc_port.cc +++ b/util/tlm/sc_slave_port.cc @@ -1,5 +1,6 @@ /* * Copyright (c) 2015, University of Kaiserslautern + * Copyright (c) 2016, Dresden University of Technology (TU Dresden) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,6 +32,7 @@ * * Authors: Matthias Jung * Abdul Mutaal Ahmad + * Christian Menard */ #include <cctype> @@ -40,7 +42,7 @@ #include "debug/ExternalPort.hh" #include "sc_ext.hh" #include "sc_mm.hh" -#include "sc_port.hh" +#include "sc_slave_port.hh" namespace Gem5SystemC { @@ -78,7 +80,7 @@ packet2payload(PacketPtr packet, tlm::tlm_generic_payload &trans) } else if (packet->isWrite()) { trans.set_command(tlm::TLM_WRITE_COMMAND); } else { - SC_REPORT_FATAL("transactor", "No R/W packet"); + SC_REPORT_FATAL("SCSlavePort", "No R/W packet"); } } @@ -86,10 +88,10 @@ packet2payload(PacketPtr packet, tlm::tlm_generic_payload &trans) * Similar to TLM's blocking transport (LT) */ Tick -sc_transactor::recvAtomic(PacketPtr packet) +SCSlavePort::recvAtomic(PacketPtr packet) { CAUGHT_UP; - SC_REPORT_INFO("transactor", "recvAtomic hasn't been tested much"); + SC_REPORT_INFO("SCSlavePort", "recvAtomic hasn't been tested much"); panic_if(packet->cacheResponding(), "Should not see packets where cache " "is responding"); @@ -107,12 +109,12 @@ sc_transactor::recvAtomic(PacketPtr packet) packet2payload(packet, *trans); /* Attach the packet pointer to the TLM transaction to keep track */ - gem5Extension* extension = new gem5Extension(packet); + Gem5Extension* extension = new Gem5Extension(packet); trans->set_auto_extension(extension); /* Execute b_transport: */ if (packet->cmd == MemCmd::SwapReq) { - SC_REPORT_FATAL("transactor", "SwapReq not supported"); + SC_REPORT_FATAL("SCSlavePort", "SwapReq not supported"); } else if (packet->isRead()) { iSocket->b_transport(*trans, delay); } else if (packet->isInvalidate()) { @@ -120,7 +122,7 @@ sc_transactor::recvAtomic(PacketPtr packet) } else if (packet->isWrite()) { iSocket->b_transport(*trans, delay); } else { - SC_REPORT_FATAL("transactor", "Typo of request not supported"); + SC_REPORT_FATAL("SCSlavePort", "Typo of request not supported"); } if (packet->needsResponse()) { @@ -136,7 +138,7 @@ sc_transactor::recvAtomic(PacketPtr packet) * Similar to TLM's debug transport */ void -sc_transactor::recvFunctional(PacketPtr packet) +SCSlavePort::recvFunctional(PacketPtr packet) { /* Prepare the transaction */ tlm::tlm_generic_payload * trans = mm.allocate(); @@ -144,38 +146,38 @@ sc_transactor::recvFunctional(PacketPtr packet) packet2payload(packet, *trans); /* Attach the packet pointer to the TLM transaction to keep track */ - gem5Extension* extension = new gem5Extension(packet); + Gem5Extension* extension = new Gem5Extension(packet); trans->set_auto_extension(extension); /* Execute Debug Transport: */ unsigned int bytes = iSocket->transport_dbg(*trans); if (bytes != trans->get_data_length()) { - SC_REPORT_FATAL("transactor","debug transport was not completed"); + SC_REPORT_FATAL("SCSlavePort","debug transport was not completed"); } trans->release(); } bool -sc_transactor::recvTimingSnoopResp(PacketPtr packet) +SCSlavePort::recvTimingSnoopResp(PacketPtr packet) { /* Snooping should be implemented with tlm_dbg_transport */ - SC_REPORT_FATAL("transactor","unimplemented func.: recvTimingSnoopResp"); + SC_REPORT_FATAL("SCSlavePort","unimplemented func.: recvTimingSnoopResp"); return false; } void -sc_transactor::recvFunctionalSnoop(PacketPtr packet) +SCSlavePort::recvFunctionalSnoop(PacketPtr packet) { /* Snooping should be implemented with tlm_dbg_transport */ - SC_REPORT_FATAL("transactor","unimplemented func.: recvFunctionalSnoop"); + SC_REPORT_FATAL("SCSlavePort","unimplemented func.: recvFunctionalSnoop"); } /** * Similar to TLM's non-blocking transport (AT) */ bool -sc_transactor::recvTimingReq(PacketPtr packet) +SCSlavePort::recvTimingReq(PacketPtr packet) { CAUGHT_UP; @@ -213,7 +215,7 @@ sc_transactor::recvTimingReq(PacketPtr packet) packet2payload(packet, *trans); /* Attach the packet pointer to the TLM transaction to keep track */ - gem5Extension* extension = new gem5Extension(packet); + Gem5Extension* extension = new Gem5Extension(packet); trans->set_auto_extension(extension); /* Starting TLM non-blocking sequence (AT) Refer to IEEE1666-2011 SystemC @@ -231,9 +233,9 @@ sc_transactor::recvTimingReq(PacketPtr packet) /* The Timing annotation must be honored: */ sc_assert(phase == tlm::END_REQ || phase == tlm::BEGIN_RESP); - payloadEvent<sc_transactor> * pe; - pe = new payloadEvent<sc_transactor>(*this, - &sc_transactor::pec, "PEQ"); + PayloadEvent<SCSlavePort> * pe; + pe = new PayloadEvent<SCSlavePort>(*this, + &SCSlavePort::pec, "PEQ"); pe->notify(*trans, phase, delay); } else if (status == tlm::TLM_COMPLETED) { /* Transaction is over nothing has do be done. */ @@ -245,8 +247,8 @@ sc_transactor::recvTimingReq(PacketPtr packet) } void -sc_transactor::pec( - sc_transactor::payloadEvent<sc_transactor> * pe, +SCSlavePort::pec( + PayloadEvent<SCSlavePort> * pe, tlm::tlm_generic_payload& trans, const tlm::tlm_phase& phase) { @@ -267,7 +269,7 @@ sc_transactor::pec( { CAUGHT_UP; - PacketPtr packet = gem5Extension::getExtension(trans).getPacket(); + PacketPtr packet = Gem5Extension::getExtension(trans).getPacket(); sc_assert(!blockingResponse); @@ -292,13 +294,13 @@ sc_transactor::pec( } } } else { - SC_REPORT_FATAL("transactor", "Invalid protocol phase in pec"); + SC_REPORT_FATAL("SCSlavePort", "Invalid protocol phase in pec"); } delete pe; } void -sc_transactor::recvRespRetry() +SCSlavePort::recvRespRetry() { CAUGHT_UP; @@ -307,7 +309,7 @@ sc_transactor::recvRespRetry() tlm::tlm_generic_payload *trans = blockingResponse; blockingResponse = NULL; - PacketPtr packet = gem5Extension::getExtension(trans).getPacket(); + PacketPtr packet = Gem5Extension::getExtension(trans).getPacket(); bool need_retry = !iSocket.sendTimingResp(packet); @@ -321,24 +323,24 @@ sc_transactor::recvRespRetry() } tlm::tlm_sync_enum -sc_transactor::nb_transport_bw(tlm::tlm_generic_payload& trans, +SCSlavePort::nb_transport_bw(tlm::tlm_generic_payload& trans, tlm::tlm_phase& phase, sc_core::sc_time& delay) { - payloadEvent<sc_transactor> * pe; - pe = new payloadEvent<sc_transactor>(*this, &sc_transactor::pec, "PE"); + PayloadEvent<SCSlavePort> * pe; + pe = new PayloadEvent<SCSlavePort>(*this, &SCSlavePort::pec, "PE"); pe->notify(trans, phase, delay); return tlm::TLM_ACCEPTED; } void -sc_transactor::invalidate_direct_mem_ptr(sc_dt::uint64 start_range, +SCSlavePort::invalidate_direct_mem_ptr(sc_dt::uint64 start_range, sc_dt::uint64 end_range) { - SC_REPORT_FATAL("transactor", "unimpl. func: invalidate_direct_mem_ptr"); + SC_REPORT_FATAL("SCSlavePort", "unimpl. func: invalidate_direct_mem_ptr"); } -sc_transactor::sc_transactor(const std::string &name_, +SCSlavePort::SCSlavePort(const std::string &name_, const std::string &systemc_name, ExternalSlave &owner_) : tlm::tlm_initiator_socket<>(systemc_name.c_str()), @@ -351,7 +353,7 @@ sc_transactor::sc_transactor(const std::string &name_, m_export.bind(*this); } -class sc_transactorHandler : public ExternalSlave::Handler +class SlavePortHandler : public ExternalSlave::Handler { public: ExternalSlave::Port *getExternalPort(const std::string &name, @@ -359,14 +361,14 @@ class sc_transactorHandler : public ExternalSlave::Handler const std::string &port_data) { // This will make a new initiatiator port - return new sc_transactor(name, port_data, owner); + return new SCSlavePort(name, port_data, owner); } }; void -registerSCPorts() +SCSlavePort::registerPortHandler() { - ExternalSlave::registerHandler("tlm", new sc_transactorHandler); + ExternalSlave::registerHandler("tlm_slave", new SlavePortHandler); } } diff --git a/util/tlm/sc_port.hh b/util/tlm/sc_slave_port.hh index 374a3cfc9..a42532cad 100644 --- a/util/tlm/sc_port.hh +++ b/util/tlm/sc_slave_port.hh @@ -1,5 +1,6 @@ /* * Copyright (c) 2015, University of Kaiserslautern + * Copyright (c) 2016, Dresden University of Technology (TU Dresden) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,10 +31,11 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Matthias Jung + * Christian Menard */ -#ifndef __SIM_SC_TRANSACTOR_HH__ -#define __SIM_SC_TRANSACTOR_HH__ +#ifndef __SC_SLAVE_PORT_HH__ +#define __SC_SLAVE_PORT_HH__ #include <tlm_utils/simple_initiator_socket.h> @@ -44,6 +46,7 @@ #include "mem/external_slave.hh" #include "sc_mm.hh" #include "sc_module.hh" +#include "sc_peq.hh" namespace Gem5SystemC { @@ -54,74 +57,26 @@ namespace Gem5SystemC assert(curTick() == sc_core::sc_time_stamp().value()); \ } while (0) - -class sc_transactor : public tlm::tlm_initiator_socket<>, +/** + * This is a gem5 slave port that translates gem5 packets to TLM transactions. + * + * Upon receiving a packet (recvAtomic, recvTiningReq, recvFunctional) the port + * creates a new TLM payload and initializes it with information from the gem5 + * packet. The original packet is added as an extension to the TLM payload. + * Then the port issues a TLM transaction in the SystemC world. By storing the + * original packet as a payload extension, the packet can be restored and send + * back to the gem5 world upon receiving a response from the SystemC world. + */ +class SCSlavePort : public tlm::tlm_initiator_socket<>, public tlm::tlm_bw_transport_if<>, public ExternalSlave::Port { public: - sc_transactor &iSocket; - - /** - * A 'Fake Payload Event Queue', similar to the TLM PEQs. This will help - * that gem5 behaves like a normal TLM Initiator - */ - template<typename OWNER> - class payloadEvent : public Event - { - public: - OWNER &port; - const std::string eventName; - void (OWNER::* handler)(payloadEvent<OWNER> * pe, - tlm::tlm_generic_payload& trans, - const tlm::tlm_phase &phase); - - protected: - tlm::tlm_generic_payload *t; - tlm::tlm_phase p; - - void process() { (port.*handler)(this,*t, p); } - - public: - const std::string name() const { return eventName; } - - payloadEvent( - OWNER &port_, - void (OWNER::* handler_)(payloadEvent<OWNER> * pe, - tlm::tlm_generic_payload& trans, - const tlm::tlm_phase &phase), - const std::string &event_name) : - port(port_), - eventName(event_name), - handler(handler_) - { } - - /// Schedule an event into gem5 - void - notify(tlm::tlm_generic_payload& trans, - const tlm::tlm_phase &phase, - const sc_core::sc_time& delay) - { - assert(!scheduled()); - - t = &trans; - p = phase; - - /** - * Get time from SystemC as this will alway be more up to date - * than gem5's - */ - Tick nextEventTick = sc_core::sc_time_stamp().value() - + delay.value(); - - port.owner.wakeupEventQueue(nextEventTick); - port.owner.schedule(this, nextEventTick); - } - }; + SCSlavePort &iSocket; /** One instance of pe and the related callback needed */ - //payloadEvent<sc_transactor> pe; - void pec(payloadEvent<sc_transactor> * pe, + //payloadEvent<SCSlavePort> pe; + void pec(PayloadEvent<SCSlavePort> * pe, tlm::tlm_generic_payload& trans, const tlm::tlm_phase& phase); /** @@ -160,15 +115,15 @@ class sc_transactor : public tlm::tlm_initiator_socket<>, sc_dt::uint64 end_range); public: - sc_transactor(const std::string &name_, - const std::string &systemc_name, - ExternalSlave &owner_); -}; + SCSlavePort(const std::string &name_, + const std::string &systemc_name, + ExternalSlave &owner_); -void registerPort(const std::string &name, Port &port); + static void registerPortHandler(); -void registerSCPorts(); + friend PayloadEvent<SCSlavePort>; +}; } -#endif // __SIM_SC_PORT_HH__ +#endif // __SC_SLAVE_PORT_H__ diff --git a/util/tlm/main.cc b/util/tlm/sim_control.cc index bf442e02b..ef04c6bbd 100644 --- a/util/tlm/main.cc +++ b/util/tlm/sim_control.cc @@ -1,5 +1,6 @@ /* * Copyright (c) 2015, University of Kaiserslautern + * Copyright (c) 2016, Dresden University of Technology (TU Dresden) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,6 +32,7 @@ * * Authors: Matthias Jung * Abdul Mutaal Ahmad + * Christian Menard */ /** @@ -41,87 +43,41 @@ * */ -#include <tlm_utils/simple_target_socket.h> - -#include <cstdlib> -#include <iomanip> -#include <iostream> -#include <sstream> #include <systemc> #include <tlm> -#include <typeinfo> -#include "base/statistics.hh" -#include "base/str.hh" -#include "base/trace.hh" -#include "cpu/base.hh" -#include "sc_logger.hh" -#include "sc_module.hh" -#include "sc_port.hh" -#include "sc_target.hh" +#include "sc_slave_port.hh" #include "sim/cxx_config_ini.hh" -#include "sim/cxx_manager.hh" #include "sim/init_signals.hh" -#include "sim/serialize.hh" -#include "sim/simulate.hh" #include "sim/stat_control.hh" -#include "sim/system.hh" +#include "sim_control.hh" #include "stats.hh" -// Defining global string variable decalred in stats.hh -std::string filename; - -void usage(const std::string &prog_name) +void +usage(const std::string& prog_name) { - std::cerr << "Usage: " << prog_name << ( - " <config_file.ini> [ <option> ]\n\n" - "OPTIONS:\n" - - " -o <offset> -- set memory offset\n" - " -p <object> <param> <value> -- set a parameter\n" - " -v <object> <param> <values> -- set a vector parameter from a\n" - " comma separated values string\n" - " -d <flag> -- set a debug flag\n" - " (-<flag> clear a flag)\n" - " -D -- debug on\n" - " -e <ticks> -- end of simulation after a \n" - " given number of ticks\n" - "\n" - ); + std::cerr + << "Usage: " << prog_name + << (" <config_file.ini> [ <option> ]\n\n" + "OPTIONS:\n" + + " -o <offset> -- set memory offset\n" + " -p <object> <param> <value> -- set a parameter\n" + " -v <object> <param> <values> -- set a vector parameter from a\n" + " comma separated values string\n" + " -d <flag> -- set a debug flag\n" + " (-<flag> clear a flag)\n" + " -D -- debug on\n" + " -e <ticks> -- end of simulation after a \n" + " given number of ticks\n" + "\n"); std::exit(EXIT_FAILURE); } -class SimControl : public Gem5SystemC::Module -{ - protected: - int argc; - char **argv; - CxxConfigManager *config_manager; - Gem5SystemC::Logger logger; - - Tick sim_end; - bool debug; - unsigned int offset; - - public: - SC_HAS_PROCESS(SimControl); - - SimControl(sc_core::sc_module_name name, int argc_, char **argv_); - - void before_end_of_elaboration(); - - bool getDebugFlag() { return debug; } - - unsigned int getOffset() { return offset; } - - void run(); -}; - -SimControl::SimControl(sc_core::sc_module_name name, - int argc_, - char **argv_) : Gem5SystemC::Module(name), - argc(argc_), - argv(argv_) +SimControl::SimControl(sc_core::sc_module_name name, int argc_, char** argv_) + : Gem5SystemC::Module(name), + argc(argc_), + argv(argv_) { SC_THREAD(run); @@ -133,7 +89,7 @@ SimControl::SimControl(sc_core::sc_module_name name, } cxxConfigInit(); - Gem5SystemC::registerSCPorts(); + Gem5SystemC::SCSlavePort::registerPortHandler(); Trace::setDebugLogger(&logger); @@ -268,64 +224,3 @@ SimControl::run() config_manager->deleteObjects(); #endif } - - -void -reportHandler(const sc_core::sc_report &report, - const sc_core::sc_actions &actions) -{ - uint64_t systemc_time = report.get_time().value(); - uint64_t gem5_time = curTick(); - - std::cerr << report.get_time(); - - if (gem5_time < systemc_time) { - std::cerr << " (<) "; - } else if (gem5_time > systemc_time) { - std::cerr << " (!) "; - } else { - std::cerr << " (=) "; - } - - std::cerr << ": " << report.get_msg_type() - << ' ' << report.get_msg() << '\n'; -} - - -int -sc_main(int argc, char **argv) -{ - sc_core::sc_report_handler::set_handler(reportHandler); - - SimControl sim_control("gem5", argc, argv); - Target *memory; - - filename = "m5out/stats-tlm.txt"; - - tlm::tlm_initiator_socket <> *mem_port = - dynamic_cast<tlm::tlm_initiator_socket<> *>( - sc_core::sc_find_object("gem5.memory") - ); - - if (mem_port) { - SC_REPORT_INFO("sc_main", "Port Found"); - unsigned long long int size = 512*1024*1024ULL; - memory = new Target("memory", - sim_control.getDebugFlag(), - size, - sim_control.getOffset()); - - memory->socket.bind(*mem_port); - } else { - SC_REPORT_FATAL("sc_main", "Port Not Found"); - std::exit(EXIT_FAILURE); - } - - sc_core::sc_start(); - - SC_REPORT_INFO("sc_main", "End of Simulation"); - - CxxConfig::statsDump(); - - return EXIT_SUCCESS; -} diff --git a/util/tlm/sim_control.hh b/util/tlm/sim_control.hh new file mode 100644 index 000000000..52bfa64d4 --- /dev/null +++ b/util/tlm/sim_control.hh @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2015, University of Kaiserslautern + * 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: Matthias Jung + * Christian Menard + */ + +#ifndef __SC_SIM_CONTROL_HH__ +#define __SC_SIM_CONTROL_HH__ + +#include <tlm_utils/simple_target_socket.h> + +#include <systemc> +#include <tlm> + +#include "sc_logger.hh" +#include "sc_module.hh" +#include "sim/cxx_manager.hh" +#include "sim/system.hh" + +class SimControl : public Gem5SystemC::Module +{ + protected: + int argc; + char** argv; + CxxConfigManager* config_manager; + Gem5SystemC::Logger logger; + + Tick sim_end; + bool debug; + unsigned int offset; + + public: + SC_HAS_PROCESS(SimControl); + + SimControl(sc_core::sc_module_name name, int argc_, char** argv_); + + void before_end_of_elaboration(); + + bool getDebugFlag() { return debug; } + + unsigned int getOffset() { return offset; } + + void run(); +}; + +#endif |