them.
"""
+ if options.tlm_memory:
+ system.external_memory = m5.objects.ExternalSlave(
+ port_type="tlm",
+ port_data=options.tlm_memory,
+ port=system.membus.master,
+ addr_ranges=system.mem_ranges)
+ system.kernel_addr_check = False
+ return
+
if options.external_memory_system:
system.external_memory = m5.objects.ExternalSlave(
port_type=options.external_memory_system,
# Cache Options
parser.add_option("--external-memory-system", type="string",
help="use external ports of this port_type for caches")
+ parser.add_option("--tlm-memory", type="string",
+ help="use external port for SystemC TLM cosimulation")
parser.add_option("--caches", action="store_true")
parser.add_option("--l2cache", action="store_true")
parser.add_option("--fastmem", action="store_true")
--- /dev/null
+# Copyright (c) 2015, University of Kaiserslautern
+# 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
+
+
+ARCH = ARM
+VARIANT = opt
+#VARIANT = debug
+
+SYSTEMC_INC = /opt/systemc/include
+SYSTEMC_LIB = /opt/systemc/lib-linux64
+
+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
+
+LIBS = -lgem5_$(VARIANT) -lsystemc
+
+ALL = gem5.$(VARIANT).sc
+
+all: $(ALL)
+
+.cc.o:
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
+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
+
+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)
+
+clean:
+ $(RM) $(ALL)
+ $(RM) *.o
+ $(RM) -r m5out
--- /dev/null
+This directory contains a demo of a coupling between gem5 and SystemC-TLM.
+It is based on the gem5-systemc implementation in utils/systemc.
+First a simple example with gem5's traffic generator is shown, later an full
+system example.
+
+Files:
+
+ main.cc -- demonstration top level
+ sc_port.{cc,hh} -- transactor that translates beween gem5 and tlm
+ sc_mm.{cc,hh} -- implementation of a tlm memory manager
+ sc_ext.{cc,hh} -- a TLM extension that carries the gem5 packet
+ sc_target.{cc,hh} -- an example TLM LT/AT memory module
+ tlm.py -- simple gem5 configuration
+ tgen.cfg -- configuration file for the traceplayer
+
+Other Files will be used from utils/systemc example:
+
+ sc_logger.{cc,hh},
+ sc_module.{cc,hh},
+ sc_gem5_control.{cc,hh},
+ stats.{cc,hh}
+
+
+I. Traffic Generator Setup
+==========================
+
+To build:
+
+First build a normal gem5 (cxx-config not needed, Python needed).
+Second build gem5 as a library with cxx-config support and (optionally)
+without python.
+
+> cd ../..
+> scons build/ARM/gem5.opt
+> scons --with-cxx-config --without-python build/ARM/libgem5_opt.so
+> cd util/systemc_tlm
+
+Set a proper LD_LIBRARY_PATH e.g. for bash:
+> export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/path/to/gem5/build/ARM/"
+
+Then edit the Makefile to set the paths for SystemC and run make
+
+> make
+
+Make a config file for the C++-configured gem5 using normal gem5
+
+> ../../build/ARM/gem5.opt ./tlm.py
+
+The message "fatal: Can't find port handler type 'tlm'" is okay.
+The configuration will be stored in the m5out/ directory
+
+The binary 'gem5.opt.sc', that has been created in the make step,
+can now be used to load in the generated config file from the previous
+normal gem5 run.
+
+Try:
+
+> ./gem5.opt.sc m5out/config.ini -e 1000000
+
+It should run a simulation for 1us.
+
+To see more information what happens inside the TLM module use the -D flag:
+
+> ./gem5.opt.sc m5out/config.ini -e 1000000 -D
+
+To see more information about the port coupling use:
+
+> ./gem5.opt.sc m5out/config.ini -e 1000000 -d ExternalPort
+
+II. Full System Setup
+=====================
+
+Build gem5 as discribed in Section I. Then, make a config file for the
+C++-configured gem5 using normal gem5
+
+> ../../build/ARM/gem5.opt ../../configs/example/fs.py --tlm-memory=memory \
+ --cpu-type=timing --num-cpu=1 --mem-type=SimpleMemory --mem-size=512MB \
+ --mem-channels=1 --caches --l2cache --machine-type=VExpress_EMM \
+ --dtb-filename=vexpress.aarch32.ll_20131205.0-gem5.1cpu.dtb \
+ --kernel=vmlinux.aarch32.ll_20131205.0-gem5 \
+ --disk-image=linux-aarch32-ael.img
+
+The message "fatal: Can't find port handler type 'tlm'" is okay.
+The configuration will be stored in the m5out/ directory
+
+The binary 'gem5.opt.sc' can now be used to load in the generated config
+file from the previous normal gem5 run.
+
+Try:
+
+> ./gem5.opt.sc m5out/config.ini -o 2147483648
+
+The parameter -o specifies the begining of the memory region (0x80000000).
+The system should boot now.
+
+For conveniance a run_gem5.sh file holds all those commands
--- /dev/null
+/*
+ * Copyright (c) 2015, University of Kaiserslautern
+ * 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
+ */
+
+/**
+ * @file
+ *
+ * Example top level file for SystemC-TLM integration with C++-only
+ * instantiation.
+ *
+ */
+
+#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 "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 "stats.hh"
+
+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::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_)
+{
+ SC_THREAD(run);
+
+ std::string prog_name(argv[0]);
+ unsigned int arg_ptr = 1;
+
+ if (argc == 1) {
+ usage(prog_name);
+ }
+
+ cxxConfigInit();
+ Gem5SystemC::registerSCPorts();
+
+ Trace::setDebugLogger(&logger);
+
+ Gem5SystemC::setTickFrequency();
+ sc_core::sc_set_time_resolution(1, sc_core::SC_PS);
+
+ Gem5SystemC::Module::setupEventQueues(*this);
+ initSignals();
+
+ Stats::initSimStats();
+ Stats::registerHandlers(CxxConfig::statsReset, CxxConfig::statsDump);
+
+ Trace::enabled = true;
+
+ sim_end = 0;
+ debug = false;
+ offset = 0;
+
+ const std::string config_file(argv[arg_ptr]);
+
+ CxxConfigFileBase *conf = new CxxIniFile();
+
+ if (!conf->load(config_file.c_str())) {
+ std::cerr << "Can't open config file: " << config_file << '\n';
+ std::exit(EXIT_FAILURE);
+ }
+ arg_ptr++;
+
+ config_manager = new CxxConfigManager(*conf);
+
+ try {
+ while (arg_ptr < argc) {
+ std::string option(argv[arg_ptr]);
+ arg_ptr++;
+ unsigned num_args = argc - arg_ptr;
+
+ if (option == "-p") {
+ if (num_args < 3) {
+ usage(prog_name);
+ }
+
+ config_manager->setParam(argv[arg_ptr], argv[arg_ptr + 1],
+ argv[arg_ptr + 2]);
+ arg_ptr += 3;
+ } else if (option == "-v") {
+ std::vector<std::string> values;
+
+ if (num_args < 3) {
+ usage(prog_name);
+ }
+ tokenize(values, argv[2], ',');
+ config_manager->setParamVector(argv[arg_ptr],
+ argv[arg_ptr],
+ values);
+ arg_ptr += 3;
+ } else if (option == "-d") {
+ if (num_args < 1) {
+ usage(prog_name);
+ }
+ if (argv[arg_ptr][0] == '-') {
+ clearDebugFlag(argv[arg_ptr] + 1);
+ } else {
+ setDebugFlag(argv[arg_ptr]);
+ }
+ arg_ptr++;
+ } else if (option == "-e") {
+ if (num_args < 1) {
+ usage(prog_name);
+ }
+ std::istringstream(argv[arg_ptr]) >> sim_end;
+ arg_ptr++;
+ } else if (option == "-D") {
+ debug = true;
+ } else if (option == "-o") {
+ if (num_args < 1) {
+ usage(prog_name);
+ }
+ std::istringstream(argv[arg_ptr]) >> offset;
+ arg_ptr++;
+ /* code */
+ } else {
+ usage(prog_name);
+ }
+ }
+ } catch (CxxConfigManager::Exception &e) {
+ std::cerr << e.name << ": " << e.message << "\n";
+ std::exit(EXIT_FAILURE);
+ }
+
+ CxxConfig::statsEnable();
+ getEventQueue(0)->dump();
+
+ try {
+ config_manager->instantiate();
+ } catch (CxxConfigManager::Exception &e) {
+ std::cerr << "Config problem in sim object "
+ << e.name << ": " << e.message << "\n";
+ std::exit(EXIT_FAILURE);
+ }
+}
+
+void
+SimControl::before_end_of_elaboration()
+{
+ try {
+ config_manager->initState();
+ config_manager->startup();
+ } catch (CxxConfigManager::Exception &e) {
+ std::cerr << "Config problem in sim object "
+ << e.name << ": " << e.message << "\n";
+ std::exit(EXIT_FAILURE);
+ }
+}
+
+void
+SimControl::run()
+{
+ GlobalSimLoopExitEvent *exit_event = NULL;
+
+ if(sim_end == 0) {
+ exit_event = simulate();
+ } else {
+ exit_event = simulate(sim_end);
+ }
+
+ std::cerr << "Exit at tick " << curTick()
+ << ", cause: " << exit_event->getCause() << '\n';
+
+ getEventQueue(0)->dump();
+
+#if TRY_CLEAN_DELETE
+ 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;
+
+ 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");
+
+ return EXIT_SUCCESS;
+}
--- /dev/null
+#!/bin/bash
+# Copyright (c) 2015, University of Kaiserslautern
+# 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
+
+# Color Definition:
+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 \
+--tlm-memory=memory \
+--cpu-type=timing \
+--num-cpu=1 \
+--mem-type=SimpleMemory \
+--mem-size=512MB \
+--mem-channels=1 \
+--caches --l2cache \
+--machine-type=VExpress_EMM \
+--dtb-filename=vexpress.aarch32.ll_20131205.0-gem5.1cpu.dtb \
+--kernel=vmlinux.aarch32.ll_20131205.0-gem5
+
+echo -e "\n${BGre}Run gem5 ${RCol}\n"
+
+time ./gem5.opt.sc m5out/config.ini -o 2147483648
--- /dev/null
+/*
+ * Copyright (c) 2015, University of Kaiserslautern
+ * 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
+ */
+
+#include "sc_ext.hh"
+
+using namespace tlm;
+
+gem5Extension::gem5Extension(PacketPtr packet)
+{
+ Packet = packet;
+}
+
+gem5Extension& gem5Extension::getExtension(const tlm_generic_payload *payload)
+{
+ gem5Extension *result = NULL;
+ payload->get_extension(result);
+ sc_assert(result!=NULL);
+ return *result;
+}
+
+gem5Extension& gem5Extension::getExtension(const tlm_generic_payload &payload)
+{
+ return gem5Extension::getExtension(&payload);
+}
+
+PacketPtr gem5Extension::getPacket()
+{
+ return Packet;
+}
+
+tlm_extension_base* gem5Extension::clone() const
+{
+ return new gem5Extension(Packet);
+}
+
+void gem5Extension::copy_from(const tlm_extension_base& ext)
+{
+ const gem5Extension& cpyFrom = static_cast<const gem5Extension&>(ext);
+ Packet = cpyFrom.Packet;
+}
--- /dev/null
+/*
+ * Copyright (c) 2015, University of Kaiserslautern
+ * 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
+ */
+
+#ifndef SC_EXT_H_
+#define SC_EXT_H_
+
+#include <systemc.h>
+#include <tlm.h>
+
+#include <iostream>
+
+#include "mem/packet.hh"
+
+class gem5Extension: public tlm::tlm_extension<gem5Extension>
+{
+ public:
+ 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);
+ PacketPtr getPacket();
+
+ private:
+ PacketPtr Packet;
+};
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2015, University of Kaiserslautern
+ * 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:
+ * Robert Gernhardt
+ * Matthias Jung
+ */
+
+#include <iostream>
+
+#include "sc_mm.hh"
+
+using namespace std;
+
+MemoryManager::MemoryManager(): numberOfAllocations(0), numberOfFrees(0)
+{
+
+}
+
+MemoryManager::~MemoryManager()
+{
+ for(gp* payload: freePayloads) {
+ delete payload;
+ numberOfFrees++;
+ }
+}
+
+gp*
+MemoryManager::allocate()
+{
+ if(freePayloads.empty()) {
+ numberOfAllocations++;
+ return new gp(this);
+ } else {
+ gp* result = freePayloads.back();
+ freePayloads.pop_back();
+ return result;
+ }
+}
+
+void
+MemoryManager::free(gp* payload)
+{
+ payload->reset(); //clears all extensions
+ freePayloads.push_back(payload);
+}
--- /dev/null
+/*
+ * Copyright (c) 2015, University of Kaiserslautern
+ * 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:
+ * Robert Gernhardt
+ * Matthias Jung
+ */
+
+#ifndef MEMORYMANAGER_H_
+#define MEMORYMANAGER_H_
+
+#include <tlm.h>
+
+#include <vector>
+
+typedef tlm::tlm_generic_payload gp;
+
+class MemoryManager : public tlm::tlm_mm_interface
+{
+ public:
+ MemoryManager();
+ virtual ~MemoryManager();
+ virtual gp* allocate();
+ virtual void free(gp* payload);
+
+ private:
+ unsigned int numberOfAllocations;
+ unsigned int numberOfFrees;
+ std::vector<gp*> freePayloads;
+};
+
+#endif /* MEMORYMANAGER_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2015, University of Kaiserslautern
+ * 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
+ */
+
+#include <cctype>
+#include <iomanip>
+#include <sstream>
+
+#include "debug/ExternalPort.hh"
+#include "sc_ext.hh"
+#include "sc_mm.hh"
+#include "sc_port.hh"
+
+namespace Gem5SystemC
+{
+
+/**
+ * Instantiate a tlm memory manager that takes care about all the
+ * tlm transactions in the system
+ */
+MemoryManager mm;
+
+/**
+ * Convert a gem5 packet to a TLM payload by copying all the relevant
+ * information to a previously allocated tlm payload
+ */
+void
+packet2payload(PacketPtr packet, tlm::tlm_generic_payload &trans)
+{
+ trans.set_address(packet->getAddr());
+
+ /* Check if this transaction was allocated by mm */
+ sc_assert(trans.has_mm());
+
+ unsigned int size = packet->getSize();
+ unsigned char *data = packet->getPtr<unsigned char>();
+
+ trans.set_data_length(size);
+ trans.set_streaming_width(size);
+ trans.set_data_ptr(data);
+
+ if (packet->isRead()) {
+ trans.set_command(tlm::TLM_READ_COMMAND);
+ }
+ else if (packet->isInvalidate()) {
+ /* Do nothing */
+ } else if (packet->isWrite()) {
+ trans.set_command(tlm::TLM_WRITE_COMMAND);
+ } else {
+ SC_REPORT_FATAL("transactor", "No R/W packet");
+ }
+}
+
+/**
+ * Similar to TLM's blocking transport (LT)
+ */
+Tick
+sc_transactor::recvAtomic(PacketPtr packet)
+{
+ CAUGHT_UP;
+ SC_REPORT_INFO("transactor", "recvAtomic hasn't been tested much");
+
+ sc_core::sc_time delay = sc_core::SC_ZERO_TIME;
+
+
+ /* Prepare the transaction */
+ tlm::tlm_generic_payload * trans = mm.allocate();
+ trans->acquire();
+ packet2payload(packet, *trans);
+
+ /* Attach the packet pointer to the TLM transaction to keep track */
+ 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");
+ } else if (packet->isRead()) {
+ iSocket->b_transport(*trans, delay);
+ } else if (packet->isInvalidate()) {
+ // do nothing
+ } else if (packet->isWrite()) {
+ iSocket->b_transport(*trans, delay);
+ } else {
+ SC_REPORT_FATAL("transactor", "Typo of request not supported");
+ }
+
+ if (packet->needsResponse()) {
+ packet->makeResponse();
+ }
+
+ trans->release();
+
+ return delay.value();
+}
+
+/**
+ * Similar to TLM's debug transport
+ */
+void
+sc_transactor::recvFunctional(PacketPtr packet)
+{
+ /* Prepare the transaction */
+ tlm::tlm_generic_payload * trans = mm.allocate();
+ trans->acquire();
+ packet2payload(packet, *trans);
+
+ /* Attach the packet pointer to the TLM transaction to keep track */
+ 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");
+ }
+
+ trans->release();
+}
+
+bool
+sc_transactor::recvTimingSnoopResp(PacketPtr packet)
+{
+ /* Snooping should be implemented with tlm_dbg_transport */
+ SC_REPORT_FATAL("transactor","unimplemented func.: recvTimingSnoopResp");
+ return false;
+}
+
+void
+sc_transactor::recvFunctionalSnoop(PacketPtr packet)
+{
+ /* Snooping should be implemented with tlm_dbg_transport */
+ SC_REPORT_FATAL("transactor","unimplemented func.: recvFunctionalSnoop");
+}
+
+/**
+ * Similar to TLM's non-blocking transport (AT)
+ */
+bool
+sc_transactor::recvTimingReq(PacketPtr packet)
+{
+ CAUGHT_UP;
+
+ /* We should never get a second request after noting that a retry is
+ * required */
+ sc_assert(!needToSendRequestRetry);
+
+ /* FIXME screw coherency traffic */
+ if (packet->memInhibitAsserted())
+ return true;
+
+ /* Remember if a request comes in while we're blocked so that a retry
+ * can be sent to gem5 */
+ if (blockingRequest) {
+ needToSendRequestRetry = true;
+ return false;
+ }
+
+ /* NOTE: normal tlm is blocking here. But in our case we return false
+ * and tell gem5 when a retry can be done. This is the main difference
+ * in the protocol:
+ * if(requestInProgress)
+ * {
+ * wait(endRequestEvent);
+ * }
+ * requestInProgress = trans;
+ */
+
+ /* Prepare the transaction */
+ tlm::tlm_generic_payload * trans = mm.allocate();
+ trans->acquire();
+ packet2payload(packet, *trans);
+
+ /* Attach the packet pointer to the TLM transaction to keep track */
+ gem5Extension* extension = new gem5Extension(packet);
+ trans->set_auto_extension(extension);
+
+ /* Starting TLM non-blocking sequence (AT) Refer to IEEE1666-2011 SystemC
+ * Standard Page 507 for a visualisation of the procedure */
+ 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);
+ /* Check returned value: */
+ if(status == tlm::TLM_ACCEPTED) {
+ sc_assert(phase == tlm::BEGIN_REQ);
+ /* Accepted but is now blocking until END_REQ (exclusion rule)*/
+ blockingRequest = trans;
+ } else if(status == tlm::TLM_UPDATED) {
+ /* 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");
+ pe->notify(*trans, phase, delay);
+ } else if(status == tlm::TLM_COMPLETED) {
+ /* Transaction is over nothing has do be done. */
+ sc_assert(phase == tlm::END_RESP);
+ trans->release();
+ }
+
+ return true;
+}
+
+void
+sc_transactor::pec(
+ sc_transactor::payloadEvent<sc_transactor> * pe,
+ tlm::tlm_generic_payload& trans,
+ const tlm::tlm_phase& phase)
+{
+ sc_time delay;
+
+ if(phase == tlm::END_REQ ||
+ &trans == blockingRequest && phase == tlm::BEGIN_RESP) {
+ sc_assert(&trans == blockingRequest);
+ blockingRequest = NULL;
+
+ /* Did another request arrive while blocked, schedule a retry */
+ if (needToSendRequestRetry) {
+ needToSendRequestRetry = false;
+ iSocket.sendRetryReq();
+ }
+ }
+ else if(phase == tlm::BEGIN_RESP)
+ {
+ CAUGHT_UP;
+
+ PacketPtr packet = gem5Extension::getExtension(trans).getPacket();
+
+ sc_assert(!blockingResponse);
+
+ bool need_retry;
+ if (packet->needsResponse()) {
+ packet->makeResponse();
+ need_retry = !iSocket.sendTimingResp(packet);
+ } else {
+ need_retry = false;
+ }
+
+ if (need_retry) {
+ blockingResponse = &trans;
+ } else {
+ if (phase == tlm::BEGIN_RESP) {
+ /* 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);
+ /* Release the transaction with all the extensions */
+ trans.release();
+ }
+ }
+ } else {
+ SC_REPORT_FATAL("transactor", "Invalid protocol phase in pec");
+ }
+ delete pe;
+}
+
+void
+sc_transactor::recvRespRetry()
+{
+ CAUGHT_UP;
+
+ /* Retry a response */
+ sc_assert(blockingResponse);
+
+ tlm::tlm_generic_payload *trans = blockingResponse;
+ blockingResponse = NULL;
+ PacketPtr packet = gem5Extension::getExtension(trans).getPacket();
+
+ bool need_retry = !iSocket.sendTimingResp(packet);
+
+ sc_assert(!need_retry);
+
+ sc_core::sc_time delay = sc_core::SC_ZERO_TIME;
+ tlm::tlm_phase phase = tlm::END_RESP;
+ iSocket->nb_transport_fw(*trans, phase, delay);
+ // Release transaction with all the extensions
+ trans->release();
+}
+
+tlm::tlm_sync_enum
+sc_transactor::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");
+ pe->notify(trans, phase, delay);
+ return tlm::TLM_ACCEPTED;
+}
+
+void
+sc_transactor::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_transactor::sc_transactor(const std::string &name_,
+ const std::string &systemc_name,
+ ExternalSlave &owner_) :
+ tlm::tlm_initiator_socket<>(systemc_name.c_str()),
+ ExternalSlave::Port(name_, owner_),
+ iSocket(*this),
+ blockingRequest(NULL),
+ needToSendRequestRetry(false),
+ blockingResponse(NULL)
+{
+ m_export.bind(*this);
+}
+
+class sc_transactorHandler : public ExternalSlave::Handler
+{
+ public:
+ ExternalSlave::Port *getExternalPort(const std::string &name,
+ ExternalSlave &owner,
+ const std::string &port_data)
+ {
+ // This will make a new initiatiator port
+ return new sc_transactor(name, port_data, owner);
+ }
+};
+
+void
+registerSCPorts()
+{
+ ExternalSlave::registerHandler("tlm", new sc_transactorHandler);
+}
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015, University of Kaiserslautern
+ * 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
+ */
+
+#ifndef __SIM_SC_TRANSACTOR_HH__
+#define __SIM_SC_TRANSACTOR_HH__
+
+#include <tlm_utils/simple_initiator_socket.h>
+
+#include <map>
+#include <systemc>
+#include <tlm>
+
+#include "mem/external_slave.hh"
+#include "sc_mm.hh"
+#include "sc_module.hh"
+
+namespace Gem5SystemC
+{
+/**
+ * Test that gem5 is at the same time as SystemC
+ */
+#define CAUGHT_UP do { \
+ assert(curTick() == sc_core::sc_time_stamp().value()); \
+} while (0)
+
+
+class sc_transactor : 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);
+ }
+ };
+
+ /** One instance of pe and the related callback needed */
+ //payloadEvent<sc_transactor> pe;
+ void pec(payloadEvent<sc_transactor> * pe,
+ tlm::tlm_generic_payload& trans, const tlm::tlm_phase& phase);
+
+ /**
+ * A transaction after BEGIN_REQ has been sent but before END_REQ, which
+ * is blocking the request channel (Exlusion Rule, see IEEE1666)
+ */
+ tlm::tlm_generic_payload *blockingRequest;
+
+ /**
+ * Did another gem5 request arrive while currently blocked?
+ * This variable is needed when a retry should happen
+ */
+ bool needToSendRequestRetry;
+
+ /**
+ * A response which has been asked to retry by gem5 and so is blocking
+ * the response channel
+ */
+ tlm::tlm_generic_payload *blockingResponse;
+
+ protected:
+ /** The gem5 Port slave interface */
+ Tick recvAtomic(PacketPtr packet);
+ void recvFunctional(PacketPtr packet);
+ bool recvTimingReq(PacketPtr packet);
+ bool recvTimingSnoopResp(PacketPtr packet);
+ void recvRespRetry();
+ void recvFunctionalSnoop(PacketPtr packet);
+
+ /** 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);
+
+ void invalidate_direct_mem_ptr(sc_dt::uint64 start_range,
+ sc_dt::uint64 end_range);
+
+ public:
+ sc_transactor(const std::string &name_,
+ const std::string &systemc_name,
+ ExternalSlave &owner_);
+};
+
+void registerPort(const std::string &name, Port &port);
+
+void registerSCPorts();
+
+}
+
+#endif // __SIM_SC_PORT_HH__
--- /dev/null
+/*
+ * Copyright (c) 2015, University of Kaiserslautern
+ * 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
+ */
+
+#include "sc_target.hh"
+
+using namespace sc_core;
+using namespace std;
+
+Target::Target(sc_core::sc_module_name name,
+ bool debug,
+ unsigned long long int size,
+ unsigned int offset) :
+ socket("socket"),
+ transaction_in_progress(0),
+ response_in_progress(false),
+ next_response_pending(0),
+ end_req_pending(0),
+ m_peq(this, &Target::peq_cb),
+ debug(debug),
+ size(size),
+ offset(offset)
+{
+ /* Register tlm transport functions */
+ socket.register_b_transport(this, &Target::b_transport);
+ socket.register_transport_dbg(this, &Target::transport_dbg);
+ socket.register_nb_transport_fw(this, &Target::nb_transport_fw);
+
+
+ /* allocate storage memory */
+ mem = new unsigned char[size];
+
+ SC_METHOD(execute_transaction_process);
+ sensitive << target_done_event;
+ dont_initialize();
+}
+
+void
+Target::b_transport(tlm::tlm_generic_payload& trans, sc_time& delay)
+{
+ /* Execute the read or write commands */
+ execute_transaction(trans);
+}
+
+unsigned int
+Target::transport_dbg(tlm::tlm_generic_payload& trans)
+{
+ tlm::tlm_command cmd = trans.get_command();
+ sc_dt::uint64 adr = trans.get_address() - offset;
+ unsigned char* ptr = trans.get_data_ptr();
+ unsigned int len = trans.get_data_length();
+
+ unsigned char *mem_array_ptr = mem + adr;
+
+ /* Load / Store the access: */
+ if ( cmd == tlm::TLM_READ_COMMAND ) {
+ if(debug) {
+ SC_REPORT_INFO("target", "tlm::TLM_READ_COMMAND");
+ }
+ std::memcpy(ptr, mem_array_ptr, len);
+ } else if ( cmd == tlm::TLM_WRITE_COMMAND ) {
+ if(debug) {
+ SC_REPORT_INFO("target", "tlm::TLM_WRITE_COMMAND");
+ }
+ std::memcpy(mem_array_ptr, ptr, len);
+ }
+
+ return len;
+}
+
+
+/* TLM-2 non-blocking transport method */
+tlm::tlm_sync_enum Target::nb_transport_fw(tlm::tlm_generic_payload& trans,
+ tlm::tlm_phase& phase,
+ sc_time& delay)
+{
+ /* Queue the transaction until the annotated time has elapsed */
+ m_peq.notify(trans, phase, delay);
+ return tlm::TLM_ACCEPTED;
+}
+
+void
+Target::peq_cb(tlm::tlm_generic_payload& trans,
+ const tlm::tlm_phase& phase)
+{
+ sc_time delay;
+
+ if(phase == tlm::BEGIN_REQ) {
+ if(debug) SC_REPORT_INFO("target", "tlm::BEGIN_REQ");
+
+ /* Increment the transaction reference count */
+ trans.acquire();
+
+ if ( !transaction_in_progress ) {
+ send_end_req(trans);
+ } else {
+ /* Put back-pressure on initiator by deferring END_REQ until
+ * pipeline is clear */
+ end_req_pending = &trans;
+ }
+ } else if (phase == tlm::END_RESP) {
+ /* On receiving END_RESP, the target can release the transaction and
+ * allow other pending transactions to proceed */
+ if (!response_in_progress) {
+ SC_REPORT_FATAL("TLM-2", "Illegal transaction phase END_RESP"
+ "received by target");
+ }
+
+ transaction_in_progress = 0;
+
+ /* Target itself is now clear to issue the next BEGIN_RESP */
+ response_in_progress = false;
+ if (next_response_pending) {
+ send_response( *next_response_pending );
+ next_response_pending = 0;
+ }
+
+ /* ... and to unblock the initiator by issuing END_REQ */
+ if (end_req_pending) {
+ send_end_req( *end_req_pending );
+ end_req_pending = 0;
+ }
+
+ } else /* tlm::END_REQ or tlm::BEGIN_RESP */ {
+ SC_REPORT_FATAL("TLM-2", "Illegal transaction phase received by"
+ "target");
+ }
+}
+
+void
+Target::send_end_req(tlm::tlm_generic_payload& trans)
+{
+ tlm::tlm_phase bw_phase;
+ sc_time delay;
+
+ /* Queue the acceptance and the response with the appropriate latency */
+ bw_phase = tlm::END_REQ;
+ delay = sc_time(10, SC_NS); // Accept delay
+
+ tlm::tlm_sync_enum status;
+ status = socket->nb_transport_bw(trans, bw_phase, delay);
+
+ /* 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
+ target_done_event.notify(delay);
+
+ assert(transaction_in_progress == 0);
+ transaction_in_progress = &trans;
+}
+
+void
+Target::execute_transaction_process()
+{
+ /* Execute the read or write commands */
+ execute_transaction( *transaction_in_progress );
+
+ /* Target must honor BEGIN_RESP/END_RESP exclusion rule; i.e. must not
+ * send BEGIN_RESP until receiving previous END_RESP or BEGIN_REQ */
+ if (response_in_progress) {
+ /* Target allows only two transactions in-flight */
+ if (next_response_pending) {
+ SC_REPORT_FATAL("TLM-2", "Attempt to have two pending responses"
+ "in target");
+ }
+ next_response_pending = transaction_in_progress;
+ } else {
+ send_response( *transaction_in_progress );
+ }
+}
+
+void
+Target::execute_transaction(tlm::tlm_generic_payload& trans)
+{
+ tlm::tlm_command cmd = trans.get_command();
+ sc_dt::uint64 adr = trans.get_address() - offset;
+ unsigned char* ptr = trans.get_data_ptr();
+ unsigned int len = trans.get_data_length();
+ unsigned char* byt = trans.get_byte_enable_ptr();
+ unsigned int wid = trans.get_streaming_width();
+
+ if ( byt != 0 ) {
+ cout << "Byte Error" << endl;
+ trans.set_response_status( tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE );
+ return;
+ }
+
+ //if ( len > 4 || wid < len ) {
+ // cout << "Burst Error len=" << len << " wid=" << wid << endl;
+ // trans.set_response_status( tlm::TLM_BURST_ERROR_RESPONSE );
+ // return;
+ //}
+
+ unsigned char *mem_array_ptr = mem + adr;
+
+ /* Load / Store the access: */
+ if ( cmd == tlm::TLM_READ_COMMAND ) {
+ if(debug) {
+ SC_REPORT_INFO("target", "tlm::TLM_READ_COMMAND");
+ }
+ std::memcpy(ptr, mem_array_ptr, len);
+ } else if ( cmd == tlm::TLM_WRITE_COMMAND ) {
+ if(debug) {
+ SC_REPORT_INFO("target", "tlm::TLM_WRITE_COMMAND");
+ }
+ std::memcpy(mem_array_ptr, ptr, len);
+ }
+
+ trans.set_response_status( tlm::TLM_OK_RESPONSE );
+}
+
+void
+Target::send_response(tlm::tlm_generic_payload& trans)
+{
+ tlm::tlm_sync_enum status;
+ tlm::tlm_phase bw_phase;
+ sc_time delay;
+
+ response_in_progress = true;
+ bw_phase = tlm::BEGIN_RESP;
+ delay = sc_time(10, SC_NS);
+ status = socket->nb_transport_bw( trans, bw_phase, delay );
+
+ if (status == tlm::TLM_UPDATED) {
+ /* The timing annotation must be honored */
+ m_peq.notify(trans, bw_phase, delay);
+ } else if (status == tlm::TLM_COMPLETED) {
+ /* The initiator has terminated the transaction */
+ transaction_in_progress = 0;
+ response_in_progress = false;
+ }
+ trans.release();
+}
--- /dev/null
+/*
+ * Copyright (c) 2015, University of Kaiserslautern
+ * 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
+ */
+
+#ifndef __SIM_SC_TARGET_HH__
+#define __SIM_SC_TARGET_HH__
+
+#include <tlm_utils/peq_with_cb_and_phase.h>
+#include <tlm_utils/simple_target_socket.h>
+
+#include <iostream>
+#include <systemc>
+#include <tlm>
+
+using namespace sc_core;
+using namespace std;
+
+struct Target: sc_module
+{
+ /** TLM interface socket: */
+ tlm_utils::simple_target_socket<Target> socket;
+
+ /** TLM related member variables: */
+ tlm::tlm_generic_payload* transaction_in_progress;
+ sc_event target_done_event;
+ bool response_in_progress;
+ bool debug;
+ tlm::tlm_generic_payload* next_response_pending;
+ tlm::tlm_generic_payload* end_req_pending;
+ tlm_utils::peq_with_cb_and_phase<Target> m_peq;
+
+ /** Storage, may be implemented with a map for large devices */
+ unsigned char *mem;
+
+ Target(sc_core::sc_module_name name,
+ bool debug,
+ unsigned long long int size,
+ unsigned int offset);
+ SC_HAS_PROCESS(Target);
+
+ /** TLM interface functions */
+ virtual void b_transport(tlm::tlm_generic_payload& trans,
+ sc_time& delay);
+ virtual unsigned int transport_dbg(tlm::tlm_generic_payload& trans);
+ virtual tlm::tlm_sync_enum nb_transport_fw(
+ tlm::tlm_generic_payload& trans,
+ tlm::tlm_phase& phase,
+ sc_time& delay);
+
+ /** Callback of Payload Event Queue: */
+ void peq_cb(tlm::tlm_generic_payload& trans,
+ const tlm::tlm_phase& phase);
+
+ /** Helping function common to b_transport and nb_transport */
+ void execute_transaction(tlm::tlm_generic_payload& trans);
+
+ /** Helping functions and processes: */
+ void send_end_req(tlm::tlm_generic_payload& trans);
+ void send_response(tlm::tlm_generic_payload& trans);
+
+ /** Method process that runs on target_done_event */
+ void execute_transaction_process();
+
+ /** Helping Variables **/
+ unsigned long long int size;
+ unsigned offset;
+};
+
+#endif //__SIM_SC_TARGET_HH__
+
--- /dev/null
+# Copyright (c) 2015, University of Kaiserslautern
+# 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
+
+
+# This format supports comments using the '#' symbol as the leading
+# character of the line
+#
+# The file format contains [STATE]+ [INIT] [TRANSITION]+ in any order,
+# where the states are the nodes in the graph, init describes what
+# state to start in, and transition describes the edges of the graph.
+#
+# STATE <id> <duration (ticks)> <type>
+#
+# State IDLE idles
+#
+# States LINEAR and RANDOM have additional <percent reads> <start addr>
+# <end addr> <access size (bytes)> <min period (ticks)> <max period (ticks)>
+# <data limit (bytes)>
+#
+# State TRACE plays back a pre-recorded trace once
+#
+# Addresses are expressed as decimal numbers. The period in the linear
+# and random state is from a uniform random distribution over the
+# interval. If a specific value is desired, then the min and max can
+# be set to the same value.
+STATE 0 1000000 LINEAR 50 0 256 4 5000 5000 64
+INIT 0
+TRANSITION 0 0 1
--- /dev/null
+# Copyright (c) 2015, University of Kaiserslautern
+# 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
+
+import m5
+from m5.objects import *
+
+# This configuration shows a simple setup of a TrafficGen (CPU) and an
+# external TLM port for SystemC co-simulation
+#
+# Base System Architecture:
+# +-------------+ +-----+ ^
+# | System Port | | CPU | |
+# +-------+-----+ +--+--+ |
+# | | | gem5 World
+# | +----+ | (see this file)
+# | | |
+# +-------v------v-------+ |
+# | Membus | v
+# +----------------+-----+ External Port (see sc_port.*)
+# | ^
+# +---v---+ | TLM World
+# | TLM | | (see sc_target.*)
+# +-------+ v
+#
+
+# Create a system with a Crossbar and a TrafficGenerator as CPU:
+system = System()
+system.membus = IOXBar(width = 16)
+system.physmem = SimpleMemory() # This must be instanciated, even if not needed
+system.cpu = TrafficGen(config_file = "tgen.cfg")
+system.clk_domain = SrcClockDomain(clock = '1.5GHz',
+ voltage_domain = VoltageDomain(voltage = '1V'))
+
+# Create a external TLM port:
+system.tlm = ExternalSlave()
+system.tlm.addr_ranges = [AddrRange('512MB')]
+system.tlm.port_type = "tlm"
+system.tlm.port_data = "memory"
+
+# Route the connections:
+system.cpu.port = system.membus.slave
+system.system_port = system.membus.slave
+system.membus.master = system.tlm.port
+
+# Start the simulation:
+root = Root(full_system = False, system = system)
+root.system.mem_mode = 'timing'
+m5.instantiate()
+m5.simulate() #Simulation time specified later on commandline