systemc: gem5 initiator TLM target example

This example shows how to connect a simple TLM target to a gem5 traffic
generator. It uses the systemc_within_gem5 feature.

Change-Id: I9755cc662c5c034cffe03d99dcbe6bed23176b16
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/60269
Maintainer: Jason Lowe-Power <power.jg@gmail.com>
Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
diff --git a/util/systemc/systemc_within_gem5/systemc_gem5_tlm/SConscript b/util/systemc/systemc_within_gem5/systemc_gem5_tlm/SConscript
new file mode 100644
index 0000000..8c7b257
--- /dev/null
+++ b/util/systemc/systemc_within_gem5/systemc_gem5_tlm/SConscript
@@ -0,0 +1,29 @@
+# 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('*')
+
+SimObject('SystemC_Example.py', sim_objects=["TLM_Target"])
+Source('sc_tlm_target.cc')
diff --git a/util/systemc/systemc_within_gem5/systemc_gem5_tlm/SystemC_Example.py b/util/systemc/systemc_within_gem5/systemc_gem5_tlm/SystemC_Example.py
new file mode 100644
index 0000000..0f1c9ed
--- /dev/null
+++ b/util/systemc/systemc_within_gem5/systemc_gem5_tlm/SystemC_Example.py
@@ -0,0 +1,41 @@
+# 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.
+
+from m5.params import *
+from m5.SimObject import SimObject
+from m5.params import *
+from m5.proxy import *
+
+from m5.objects.SystemC import SystemC_ScModule
+from m5.objects.Tlm import TlmTargetSocket
+
+# This class is a subclass of sc_module, and all the special magic which makes
+# that work is handled in the base classes.
+class TLM_Target(SystemC_ScModule):
+    type = 'TLM_Target'
+    cxx_class = 'Target'
+    cxx_header = 'systemc_gem5_tlm/sc_tlm_target.hh'
+    tlm = TlmTargetSocket(32, 'TLM target socket')
+    system = Param.System(Parent.any, "system")
diff --git a/util/systemc/systemc_within_gem5/systemc_gem5_tlm/config.py b/util/systemc/systemc_within_gem5/systemc_gem5_tlm/config.py
new file mode 100755
index 0000000..4d6e260
--- /dev/null
+++ b/util/systemc/systemc_within_gem5/systemc_gem5_tlm/config.py
@@ -0,0 +1,77 @@
+# Copyright (c) 2022, Fraunhofer IESE
+# 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.
+import os
+import m5
+
+from m5.objects import *
+
+# Create a config to be used by the traffic generator
+cfg_file_name = "memcheck.cfg"
+cfg_file_path = os.path.dirname(__file__) + "/" +cfg_file_name
+cfg_file = open(cfg_file_path, 'w')
+
+# Three states, with random, linear and idle behaviours. The random
+# and linear states access memory in the range [0 : 16 Mbyte] with 8
+# byte and 64 byte accesses respectively.
+cfg_file.write("STATE 0 10000000 RANDOM 65 0 16777216 8 50000 150000 0\n")
+cfg_file.write("STATE 1 10000000 LINEAR 65 0 16777216 64 50000 150000 0\n")
+cfg_file.write("STATE 2 10000000 IDLE\n")
+cfg_file.write("INIT 0\n")
+cfg_file.write("TRANSITION 0 1 0.5\n")
+cfg_file.write("TRANSITION 0 2 0.5\n")
+cfg_file.write("TRANSITION 1 0 0.5\n")
+cfg_file.write("TRANSITION 1 2 0.5\n")
+cfg_file.write("TRANSITION 2 0 0.5\n")
+cfg_file.write("TRANSITION 2 1 0.5\n")
+cfg_file.close()
+
+system = System()
+vd = VoltageDomain(voltage = '1V')
+
+system.mem_mode = 'timing'
+
+system.cpu = TrafficGen(config_file = cfg_file_path)
+system.target = TLM_Target()
+system.physmem = SimpleMemory() # This must be instanciated, even if not needed
+#system.mem.addr_ranges = [AddrRange('512MB')]
+system.transactor = Gem5ToTlmBridge32()
+system.clk_domain = SrcClockDomain(clock = '1.5GHz', voltage_domain = vd)
+
+# Connect everything:
+system.transactor.gem5 = system.cpu.port
+system.transactor.tlm = system.target.tlm
+
+kernel = SystemC_Kernel(system=system)
+root = Root(full_system=False, systemc_kernel=kernel)
+
+m5.instantiate(None)
+
+cause = m5.simulate(m5.MaxTick).getCause()
+print(cause)
diff --git a/util/systemc/systemc_within_gem5/systemc_gem5_tlm/sc_tlm_target.cc b/util/systemc/systemc_within_gem5/systemc_gem5_tlm/sc_tlm_target.cc
new file mode 100644
index 0000000..482eeb0
--- /dev/null
+++ b/util/systemc/systemc_within_gem5/systemc_gem5_tlm/sc_tlm_target.cc
@@ -0,0 +1,130 @@
+/*
+ * 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_target_socket.h>
+
+#include <iomanip>
+#include <iostream>
+#include <map>
+#include <queue>
+#include <vector>
+
+#include "base/trace.hh"
+#include "params/TLM_Target.hh"
+#include "sc_tlm_target.hh"
+
+#include "systemc/ext/systemc"
+#include "systemc/ext/tlm"
+
+using namespace std;
+using namespace sc_core;
+using namespace gem5;
+
+void Target::b_transport(tlm::tlm_generic_payload& trans,
+                            sc_time& delay)
+{
+    executeTransaction(trans);
+}
+
+void Target::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();
+
+    if (trans.get_address() >= 16*1024*1024) {
+        cout << "\033[1;31m("
+             << "Address Error"
+             << "\033[0m" << endl;
+        trans.set_response_status( tlm::TLM_ADDRESS_ERROR_RESPONSE );
+        return;
+    }
+    if (byt != 0) {
+        cout << "\033[1;31m("
+             << "Byte Enable Error"
+             << "\033[0m" << endl;
+        trans.set_response_status( tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE );
+        return;
+    }
+    if (len < 1 || len > 64) {
+        cout << "\033[1;31m("
+             << "Burst Error"
+             << "\033[0m" << endl;
+        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) << hex << adr
+            << " Data = " << "0x" << setfill('0') << setw(8) << hex
+            << *reinterpret_cast<int*>(ptr)
+            << "\033[0m" << endl;
+
+    trans.set_response_status( tlm::TLM_OK_RESPONSE );
+}
+
+// This "create" method bridges the python configuration and the systemc
+// objects. It instantiates the Printer object and sets it up using the
+// parameter values from the config, just like it would for a SimObject. The
+// systemc object could accept those parameters however it likes, for instance
+// through its constructor or by assigning them to a member variable.
+Target *
+gem5::TLM_TargetParams::create() const
+{
+    Target *target = new Target(name.c_str());
+    return target;
+}
+
+gem5::Port
+&Target::gem5_getPort(const std::string &if_name, int idx)
+{
+    return wrapper;
+}
diff --git a/util/systemc/systemc_within_gem5/systemc_gem5_tlm/sc_tlm_target.hh b/util/systemc/systemc_within_gem5/systemc_gem5_tlm/sc_tlm_target.hh
new file mode 100644
index 0000000..f9a5d28
--- /dev/null
+++ b/util/systemc/systemc_within_gem5/systemc_gem5_tlm/sc_tlm_target.hh
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef __SYSTEC_TLM_GEM5_EXAMPLE__
+#define __SYSTEC_TLM_GEM5_EXAMPLE__
+
+#include <tlm_utils/simple_target_socket.h>
+
+#include <iomanip>
+#include <iostream>
+#include <map>
+#include <queue>
+#include <vector>
+
+#include "base/trace.hh"
+#include "systemc/ext/core/sc_module_name.hh"
+#include "systemc/tlm_port_wrapper.hh"
+
+#include "systemc/ext/systemc"
+#include "systemc/ext/tlm"
+
+using namespace std;
+using namespace sc_core;
+using namespace gem5;
+
+SC_MODULE(Target)
+{
+  public:
+    tlm_utils::simple_target_socket<Target> tSocket;
+    sc_gem5::TlmTargetWrapper<32> wrapper;
+
+  private:
+    //unsigned char mem[512];
+    unsigned char *mem;
+
+  public:
+    SC_HAS_PROCESS(Target);
+    Target(sc_module_name name) :
+         sc_module(name),
+         tSocket("tSocket"),
+         wrapper(tSocket, std::string(name) + ".tlm", InvalidPortID)
+    {
+        tSocket.register_b_transport(this, &Target::b_transport);
+        mem = (unsigned char *)malloc(16*1024*1024);
+        std::cout << "TLM Target Online" << std::endl;
+    }
+
+    gem5::Port &gem5_getPort(const std::string &if_name, int idx=-1) override;
+
+    virtual void b_transport(tlm::tlm_generic_payload& trans,
+                             sc_time& delay);
+
+    void executeTransaction(tlm::tlm_generic_payload& trans);
+};
+
+#endif // __SYSTEC_TLM_GEM5_EXAMPLE__