systemc: Simple TLM Example added
Change-Id: I2cb0c95773b8c6d15ffdffffaafbe3133a392a54
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/59549
Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
Maintainer: Jason Lowe-Power <power.jg@gmail.com>
diff --git a/util/systemc/systemc_within_gem5/README b/util/systemc/systemc_within_gem5/README
index 6c743b9..af10fc4 100644
--- a/util/systemc/systemc_within_gem5/README
+++ b/util/systemc/systemc_within_gem5/README
@@ -26,6 +26,7 @@
systemc_sc_main - Run code based on an sc_main function.
systemc_simple_object - Build systemc objects into a gem5 object hierarchy.
+systemc_tlm - Simple LT-Based TLM system
Note that these directories all have a systemc_ prefix so that when EXTRAS
diff --git a/util/systemc/systemc_within_gem5/systemc_tlm/SConscript b/util/systemc/systemc_within_gem5/systemc_tlm/SConscript
new file mode 100644
index 0000000..62b9b1d
--- /dev/null
+++ b/util/systemc/systemc_within_gem5/systemc_tlm/SConscript
@@ -0,0 +1,28 @@
+# Copyright 2018 Google, Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# 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;
+# neither the name of the copyright holders 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
+# OWNER 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.
+
+Import('*')
+
+Source('sc_tlm.cc')
diff --git a/util/systemc/systemc_within_gem5/systemc_tlm/config.py b/util/systemc/systemc_within_gem5/systemc_tlm/config.py
new file mode 100755
index 0000000..0d20e9e
--- /dev/null
+++ b/util/systemc/systemc_within_gem5/systemc_tlm/config.py
@@ -0,0 +1,67 @@
+# Copyright 2018 Google, Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# 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;
+# neither the name of the copyright holders 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
+# OWNER 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.
+
+import argparse
+import m5
+import sys
+
+from m5.objects import SystemC_Kernel, Root
+
+# pylint:disable=unused-variable
+
+# The python version of the systemc kernel acts as an interface to sc_main. The
+# c++ version of the kernel object has a lot of important jobs supporting
+# systemc objects and needs to exist in simulations using systemc.
+kernel = SystemC_Kernel()
+root = Root(full_system=True, systemc_kernel=kernel)
+
+parser = argparse.ArgumentParser()
+parser.add_argument('--word', action="append", default=[],
+ help='Add a word to the list of words to print. Can be repeated.')
+
+args = parser.parse_args()
+
+# Tell gem5 to run the c++ sc_main function. If one isn't defined, gem5 will
+# detect that and report an error. If gem5 isn't finding your sc_main, make
+# sure its signature matches exactly so your compiler doesn't think it's a
+# different function.
+#
+# The arguements passed to this function will be treated as the argv values
+# passed to the c++ sc_main, with the argc value set appropriately.
+m5.systemc.sc_main(*args.word);
+
+# Construct the SimObject hierarchy. Anything sc_main built has already been
+# constructed.
+m5.instantiate(None)
+
+# Run the simulation until something kicks us back to the config file. sc_main
+# will be at the point it first called sc_start and may keep executing as the
+# simulation runs, or it may be completed if it never called sc_start.
+cause = m5.simulate(m5.MaxTick).getCause()
+
+# If sc_main finished, extract what it returned and do something with it.
+result = m5.systemc.sc_main_result()
+if result.code != 0:
+ sys.exit(int(result.code))
diff --git a/util/systemc/systemc_within_gem5/systemc_tlm/sc_tlm.cc b/util/systemc/systemc_within_gem5/systemc_tlm/sc_tlm.cc
new file mode 100644
index 0000000..472e870
--- /dev/null
+++ b/util/systemc/systemc_within_gem5/systemc_tlm/sc_tlm.cc
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2022 Fraunhofer IESE
+ *
+ * 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.
+ *
+ */
+
+#include <tlm_utils/simple_initiator_socket.h>
+#include <tlm_utils/simple_target_socket.h>
+
+#include <iomanip>
+#include <iostream>
+#include <map>
+#include <queue>
+#include <vector>
+
+#include "base/trace.hh"
+
+#include "systemc/ext/systemc"
+#include "systemc/ext/tlm"
+#define N 1024
+
+using namespace std;
+using namespace sc_core;
+using namespace gem5;
+
+SC_MODULE(Initiator)
+{
+ public:
+ tlm_utils::simple_initiator_socket<Initiator> iSocket;
+
+ protected:
+ int data[16];
+
+ public:
+ SC_CTOR(Initiator): iSocket("iSocket")
+ {
+ SC_THREAD(process);
+
+ for (int i=0; i<16; i++) {
+ data[i] = 0;
+ }
+ }
+
+ protected:
+ void process()
+ {
+ sc_time delay;
+
+ for (int i = 0; i < N; i++)
+ {
+ tlm::tlm_generic_payload trans;
+ data[i % 16] = i;
+ trans.set_address(rand()%N);
+ trans.set_data_length(4);
+ trans.set_streaming_width(4);
+ trans.set_command(tlm::TLM_WRITE_COMMAND);
+ trans.set_data_ptr(reinterpret_cast<unsigned char*>(&data[i%16]));
+ trans.set_response_status( tlm::TLM_INCOMPLETE_RESPONSE );
+
+ sc_time delay = sc_time(10, SC_NS);
+
+ iSocket->b_transport(trans, delay);
+
+ if (trans.is_response_error())
+ {
+ SC_REPORT_FATAL(name(), "Response error");
+ }
+
+ wait(delay);
+
+ cout << "\033[1;31m("
+ << name()
+ << ")@" << setfill(' ') << setw(12) << sc_time_stamp()
+ << ": " << setw(12) << "Write to "
+ << "Addr = " << setfill('0') << setw(8)
+ << dec << trans.get_address()
+ << " Data = " << "0x" << setfill('0') << setw(8)
+ << hex << data[i%16] << "(b_transport) \033[0m" << endl;
+ }
+ }
+};
+
+SC_MODULE(Target)
+{
+ public:
+ tlm_utils::simple_target_socket<Target> tSocket;
+
+ private:
+ unsigned char mem[512];
+
+ public:
+ SC_HAS_PROCESS(Target);
+ Target(sc_module_name name, unsigned int bufferSize = 8) :
+ sc_module(name),
+ tSocket("tSocket")
+ {
+ tSocket.register_b_transport(this, &Target::b_transport);
+ }
+
+ virtual void b_transport(tlm::tlm_generic_payload& trans,
+ sc_time& delay)
+ {
+ executeTransaction(trans);
+ }
+
+
+ // Common to b_transport and nb_transport
+ void executeTransaction(tlm::tlm_generic_payload& trans)
+ {
+ tlm::tlm_command cmd = trans.get_command();
+ sc_dt::uint64 adr = trans.get_address();
+ 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 (trans.get_address() >= 512) {
+ trans.set_response_status( tlm::TLM_ADDRESS_ERROR_RESPONSE );
+ return;
+ }
+ if (byt != 0) {
+ trans.set_response_status( tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE );
+ return;
+ }
+ if (len > 4 || wid < len) {
+ trans.set_response_status( tlm::TLM_BURST_ERROR_RESPONSE );
+ return;
+ }
+
+ if (cmd == tlm::TLM_READ_COMMAND)
+ {
+ memcpy(&mem[trans.get_address()], // destination
+ trans.get_data_ptr(), // source
+ trans.get_data_length()); // size
+ }
+ else if (cmd == tlm::TLM_WRITE_COMMAND)
+ {
+ memcpy(trans.get_data_ptr(), // destination
+ &mem[trans.get_address()], // source
+ trans.get_data_length()); // size
+ }
+
+ cout << "\033[1;32m("
+ << name()
+ << ")@" << setfill(' ') << setw(12) << sc_time_stamp()
+ << ": " << setw(12) << (cmd ? "Exec. Write " : "Exec. Read ")
+ << "Addr = " << setfill('0') << setw(8) << dec << adr
+ << " Data = " << "0x" << setfill('0') << setw(8) << hex
+ << *reinterpret_cast<int*>(ptr)
+ << "\033[0m" << endl;
+
+ trans.set_response_status( tlm::TLM_OK_RESPONSE );
+ }
+
+};
+
+template<unsigned int I, unsigned int T>
+SC_MODULE(Interconnect)
+{
+ public:
+ tlm_utils::simple_target_socket_tagged<Interconnect> tSocket[T];
+ tlm_utils::simple_initiator_socket_tagged<Interconnect> iSocket[I];
+
+ SC_CTOR(Interconnect)
+ {
+ for (unsigned int i = 0; i < T; i++) {
+ tSocket[i].register_b_transport(this,
+ &Interconnect::b_transport,
+ i);
+ }
+ }
+
+ private:
+
+ int routeFW(int inPort, tlm::tlm_generic_payload &trans)
+ {
+ int outPort = 0;
+
+ // Memory map implementation:
+ if (trans.get_address() < 512) {
+ outPort = 0;
+ } else if (trans.get_address() >= 512 && trans.get_address() < 1024) {
+ // Correct Address:
+ trans.set_address(trans.get_address() - 512);
+ outPort = 1;
+ } else {
+ trans.set_response_status( tlm::TLM_ADDRESS_ERROR_RESPONSE );
+ }
+
+ return outPort;
+ }
+
+ virtual void b_transport( int id,
+ tlm::tlm_generic_payload& trans,
+ sc_time& delay )
+ {
+ sc_assert(id < T);
+ int outPort = routeFW(id, trans);
+ iSocket[outPort]->b_transport(trans, delay);
+ }
+
+};
+
+
+int
+sc_main (int __attribute__((unused)) sc_argc,
+ char __attribute__((unused)) *sc_argv[])
+{
+
+ Initiator * cpu1 = new Initiator("C1");
+ Initiator * cpu2 = new Initiator("C2");
+
+ Target * memory1 = new Target("M1");
+ Target * memory2 = new Target("M2");
+
+ Interconnect<2,2> * bus = new Interconnect<2,2>("B1");
+
+ cpu1->iSocket.bind(bus->tSocket[0]);
+ cpu2->iSocket.bind(bus->tSocket[1]);
+ bus->iSocket[0].bind(memory1->tSocket);
+ bus->iSocket[1].bind(memory2->tSocket);
+
+ sc_core::sc_start();
+
+ return 0;
+}