From: Gabe Black Date: Tue, 26 Feb 2019 04:27:06 +0000 (-0800) Subject: tlm: Initial import of tlm/gem5 bridge code. X-Git-Tag: v19.0.0.0~999 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=9a042daa84630d2d0d286947005e96448fb5114a;p=gem5.git tlm: Initial import of tlm/gem5 bridge code. This is a slightly mangled version of the existing bridge code in util/tlm/src/. The changes fix some small style issues, change to gem5 specific include paths, and removes the Gem5SimControl code. That code coordinates gem5 with the external systemc kernel, and in this usage there's no external kernel. The code imported here compiles, but it isn't yet expected to work. Change-Id: I9c593a52e2554534720d21cd31a03e543ad897ad Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/17231 Reviewed-by: Gabe Black Maintainer: Gabe Black --- diff --git a/src/systemc/tlm_bridge/SConscript b/src/systemc/tlm_bridge/SConscript new file mode 100644 index 000000000..6d91436bb --- /dev/null +++ b/src/systemc/tlm_bridge/SConscript @@ -0,0 +1,38 @@ +# 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. +# +# Authors: Gabe Black + +Import('*') + +if not env['USE_SYSTEMC']: + Return() + +Source('master_transactor.cc') +Source('sc_ext.cc') +Source('sc_master_port.cc') +Source('sc_mm.cc') +Source('sc_slave_port.cc') +Source('slave_transactor.cc') diff --git a/src/systemc/tlm_bridge/master_transactor.cc b/src/systemc/tlm_bridge/master_transactor.cc new file mode 100644 index 000000000..58651b01f --- /dev/null +++ b/src/systemc/tlm_bridge/master_transactor.cc @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2016, Dresden University of Technology (TU Dresden) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Christian Menard + */ + +#include "systemc/tlm_bridge/master_transactor.hh" + +#include "systemc/ext/utils/sc_report_handler.hh" +#include "systemc/tlm_bridge/sc_master_port.hh" +#include "systemc/tlm_bridge/sim_control_if.hh" + +namespace Gem5SystemC +{ + +Gem5MasterTransactor::Gem5MasterTransactor(sc_core::sc_module_name name, + const std::string& portName) + : sc_core::sc_module(name), + socket(portName.c_str()), + sim_control("sim_control"), + portName(portName) +{ + if (portName.empty()) { + SC_REPORT_ERROR(name, "No port name specified!\n"); + } +} + +void +Gem5MasterTransactor::before_end_of_elaboration() +{ + auto *port = sim_control->getMasterPort(portName); + + port->bindToTransactor(this); +} + +} // namespace Gem5SystemC diff --git a/src/systemc/tlm_bridge/master_transactor.hh b/src/systemc/tlm_bridge/master_transactor.hh new file mode 100644 index 000000000..5033684de --- /dev/null +++ b/src/systemc/tlm_bridge/master_transactor.hh @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2016, Dresden University of Technology (TU Dresden) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Christian Menard + */ + +#ifndef __SYSTEMC_TLM_BRIDGE_MASTER_TRANSACTOR_HH__ +#define __SYSTEMC_TLM_BRIDGE_MASTER_TRANSACTOR_HH__ + +#include + +#include "systemc/ext/core/sc_module.hh" +#include "systemc/ext/core/sc_port.hh" +#include "systemc/ext/tlm_utils/simple_target_socket.h" +#include "systemc/tlm_bridge/sc_master_port.hh" +#include "systemc/tlm_bridge/sim_control_if.hh" + +namespace Gem5SystemC +{ + +class Gem5MasterTransactor : public sc_core::sc_module +{ + public: + // module interface + tlm_utils::simple_target_socket socket; + sc_core::sc_port sim_control; + + private: + std::string portName; + + public: + SC_HAS_PROCESS(Gem5MasterTransactor); + + Gem5MasterTransactor(sc_core::sc_module_name name, + const std::string& portName); + + void before_end_of_elaboration(); +}; + +} // namespace Gem5SystemC + +#endif // __SYSTEMC_TLM_BRIDGE_MASTER_TRANSACTOR_HH__ diff --git a/src/systemc/tlm_bridge/sc_ext.cc b/src/systemc/tlm_bridge/sc_ext.cc new file mode 100644 index 000000000..afad82182 --- /dev/null +++ b/src/systemc/tlm_bridge/sc_ext.cc @@ -0,0 +1,85 @@ +/* + * 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 + */ + +#include "systemc/tlm_bridge/sc_ext.hh" + +#include "systemc/ext/utils/sc_report_handler.hh" + +namespace Gem5SystemC +{ + +Gem5Extension::Gem5Extension(PacketPtr _packet) +{ + packet = _packet; + pipeThrough = false; +} + +Gem5Extension & +Gem5Extension::getExtension(const tlm::tlm_generic_payload *payload) +{ + Gem5Extension *result = NULL; + payload->get_extension(result); + sc_assert(result != NULL); + return *result; +} + +Gem5Extension & +Gem5Extension::getExtension(const tlm::tlm_generic_payload &payload) +{ + return Gem5Extension::getExtension(&payload); +} + +PacketPtr +Gem5Extension::getPacket() +{ + return packet; +} + +tlm::tlm_extension_base * +Gem5Extension::clone() const +{ + return new Gem5Extension(packet); +} + +void +Gem5Extension::copy_from(const tlm::tlm_extension_base &ext) +{ + const Gem5Extension &cpyFrom = static_cast(ext); + packet = cpyFrom.packet; +} + +} // namespace Gem5SystemC diff --git a/src/systemc/tlm_bridge/sc_ext.hh b/src/systemc/tlm_bridge/sc_ext.hh new file mode 100644 index 000000000..413c6106f --- /dev/null +++ b/src/systemc/tlm_bridge/sc_ext.hh @@ -0,0 +1,71 @@ +/* + * 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 __SYSTEMC_TLM_BRIDGE_SC_EXT_HH__ +#define __SYSTEMC_TLM_BRIDGE_SC_EXT_HH__ + +#include "mem/packet.hh" +#include "systemc/ext/tlm_core/2/generic_payload/gp.hh" + +namespace Gem5SystemC +{ + +class Gem5Extension: public tlm::tlm_extension +{ + 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(); + + bool isPipeThrough() const { return pipeThrough; } + void setPipeThrough() { pipeThrough = true; } + + private: + PacketPtr packet; + bool pipeThrough; +}; + +} // namespace Gem5SystemC + +#endif // __SYSTEMC_TLM_BRIDGE_SC_EXT_HH__ diff --git a/src/systemc/tlm_bridge/sc_master_port.cc b/src/systemc/tlm_bridge/sc_master_port.cc new file mode 100644 index 000000000..da5b94fbe --- /dev/null +++ b/src/systemc/tlm_bridge/sc_master_port.cc @@ -0,0 +1,428 @@ +/* + * Copyright (c) 2016, Dresden University of Technology (TU Dresden) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Christian Menard + */ + +#include "systemc/tlm_bridge/sc_master_port.hh" + +#include + +#include "params/ExternalMaster.hh" +#include "sim/system.hh" +#include "systemc/tlm_bridge/master_transactor.hh" +#include "systemc/tlm_bridge/sc_ext.hh" + +namespace Gem5SystemC +{ + +PacketPtr +SCMasterPort::generatePacket(tlm::tlm_generic_payload &trans) +{ + Request::Flags flags; + auto req = std::make_shared( + trans.get_address(), trans.get_data_length(), flags, + owner.masterId); + + MemCmd cmd; + + switch (trans.get_command()) { + case tlm::TLM_READ_COMMAND: + cmd = MemCmd::ReadReq; + break; + case tlm::TLM_WRITE_COMMAND: + cmd = MemCmd::WriteReq; + break; + default: + SC_REPORT_FATAL("SCMasterPort", + "received transaction with unsupported command"); + } + + /* + * Allocate a new Packet. The packet will be deleted when it returns from + * the gem5 world as a response. + */ + auto pkt = new Packet(req, cmd); + pkt->dataStatic(trans.get_data_ptr()); + + return pkt; +} + +void +SCMasterPort::destroyPacket(PacketPtr pkt) +{ + delete pkt; +} + +SCMasterPort::SCMasterPort(const std::string &name_, + const std::string &systemc_name, + ExternalMaster &owner_, + Gem5SimControl &simControl) + : ExternalMaster::Port(name_, owner_), + peq(this, &SCMasterPort::peq_cb), + waitForRetry(false), + pendingRequest(nullptr), + pendingPacket(nullptr), + needToSendRetry(false), + responseInProgress(false), + transactor(nullptr), + simControl(simControl) +{ + system = + dynamic_cast(owner_.params())->system; +} + +void +SCMasterPort::bindToTransactor(Gem5MasterTransactor *transactor) +{ + sc_assert(this->transactor == nullptr); + + this->transactor = transactor; + + /* + * Register the TLM non-blocking interface when using gem5 Timing mode and + * the TLM blocking interface when using the gem5 Atomic mode. + * Then the magic (TM) in simple_target_socket automatically transforms + * non-blocking in blocking transactions and vice versa. + * + * NOTE: The mode may change during execution. + */ + if (system->isTimingMode()) { + SC_REPORT_INFO("SCMasterPort", "register non-blocking interface"); + transactor->socket.register_nb_transport_fw(this, + &SCMasterPort::nb_transport_fw); + } else if (system->isAtomicMode()) { + SC_REPORT_INFO("SCMasterPort", "register blocking interface"); + transactor->socket.register_b_transport(this, + &SCMasterPort::b_transport); + } else { + panic("gem5 operates neither in Timing nor in Atomic mode"); + } + + transactor->socket.register_transport_dbg(this, + &SCMasterPort::transport_dbg); +} + +void +SCMasterPort::checkTransaction(tlm::tlm_generic_payload& trans) +{ + if (trans.is_response_error()) { + std::stringstream ss; + ss << "Transaction returned with error, response status = " + << trans.get_response_string(); + SC_REPORT_ERROR("TLM-2", ss.str().c_str()); + } +} + +tlm::tlm_sync_enum +SCMasterPort::nb_transport_fw(tlm::tlm_generic_payload &trans, + tlm::tlm_phase &phase, sc_core::sc_time &delay) +{ + unsigned len = trans.get_data_length(); + unsigned char *byteEnable = trans.get_byte_enable_ptr(); + unsigned width = trans.get_streaming_width(); + + // check the transaction attributes for unsupported features ... + if (byteEnable != 0) { + trans.set_response_status(tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE); + return tlm::TLM_COMPLETED; + } + if (width < len) { // is this a burst request? + trans.set_response_status(tlm::TLM_BURST_ERROR_RESPONSE); + return tlm::TLM_COMPLETED; + } + + // ... and queue the valid transaction + trans.acquire(); + peq.notify(trans, phase, delay); + return tlm::TLM_ACCEPTED; +} + +void +SCMasterPort::peq_cb(tlm::tlm_generic_payload &trans, + const tlm::tlm_phase &phase) +{ + // catch up with SystemC time + //simControl.catchup(); + assert(curTick() == sc_core::sc_time_stamp().value()); + + switch (phase) { + case tlm::BEGIN_REQ: + handleBeginReq(trans); + break; + case tlm::END_RESP: + handleEndResp(trans); + break; + default: + panic("unimplemented phase in callback"); + } + + // the functions called above may have scheduled gem5 events + // -> notify the event loop handler + //simControl.notify(); +} + +void +SCMasterPort::handleBeginReq(tlm::tlm_generic_payload &trans) +{ + sc_assert(!waitForRetry); + sc_assert(pendingRequest == nullptr); + sc_assert(pendingPacket == nullptr); + + trans.acquire(); + + PacketPtr pkt = nullptr; + + Gem5Extension *extension = nullptr; + trans.get_extension(extension); + + // If there is an extension, this transaction was initiated by the gem5 + // world and we can pipe through the original packet. Otherwise, we + // generate a new packet based on the transaction. + if (extension != nullptr) { + extension->setPipeThrough(); + pkt = extension->getPacket(); + } else { + pkt = generatePacket(trans); + } + + auto tlmSenderState = new TlmSenderState(trans); + pkt->pushSenderState(tlmSenderState); + + if (sendTimingReq(pkt)) { // port is free -> send END_REQ immediately + sendEndReq(trans); + trans.release(); + } else { // port is blocked -> wait for retry before sending END_REQ + waitForRetry = true; + pendingRequest = &trans; + pendingPacket = pkt; + } +} + +void +SCMasterPort::handleEndResp(tlm::tlm_generic_payload &trans) +{ + sc_assert(responseInProgress); + + responseInProgress = false; + + checkTransaction(trans); + + if (needToSendRetry) { + sendRetryResp(); + needToSendRetry = false; + } +} + +void +SCMasterPort::sendEndReq(tlm::tlm_generic_payload &trans) +{ + tlm::tlm_phase phase = tlm::END_REQ; + auto delay = sc_core::SC_ZERO_TIME; + + auto status = transactor->socket->nb_transport_bw(trans, phase, delay); + panic_if(status != tlm::TLM_ACCEPTED, + "Unexpected status after sending END_REQ"); +} + +void +SCMasterPort::b_transport(tlm::tlm_generic_payload &trans, + sc_core::sc_time &t) +{ + Gem5Extension *extension = nullptr; + trans.get_extension(extension); + + PacketPtr pkt = nullptr; + + // If there is an extension, this transaction was initiated by the gem5 + // world and we can pipe through the original packet. + if (extension != nullptr) { + extension->setPipeThrough(); + pkt = extension->getPacket(); + } else { + pkt = generatePacket(trans); + } + + Tick ticks = sendAtomic(pkt); + + // send an atomic request to gem5 + panic_if(pkt->needsResponse() && !pkt->isResponse(), + "Packet sending failed!\n"); + + // one tick is a pico second + auto delay = + sc_core::sc_time((double)(ticks / SimClock::Int::ps), sc_core::SC_PS); + + // update time + t += delay; + + if (extension == nullptr) + destroyPacket(pkt); + + trans.set_response_status(tlm::TLM_OK_RESPONSE); +} + +unsigned int +SCMasterPort::transport_dbg(tlm::tlm_generic_payload &trans) +{ + Gem5Extension *extension = nullptr; + trans.get_extension(extension); + + // If there is an extension, this transaction was initiated by the gem5 + // world and we can pipe through the original packet. + if (extension != nullptr) { + extension->setPipeThrough(); + sendFunctional(extension->getPacket()); + } else { + auto pkt = generatePacket(trans); + sendFunctional(pkt); + destroyPacket(pkt); + } + + return trans.get_data_length(); +} + +bool +SCMasterPort::get_direct_mem_ptr(tlm::tlm_generic_payload &trans, + tlm::tlm_dmi &dmi_data) +{ + return false; +} + +bool +SCMasterPort::recvTimingResp(PacketPtr pkt) +{ + // exclusion rule + // We need to Wait for END_RESP before sending next BEGIN_RESP + if (responseInProgress) { + sc_assert(!needToSendRetry); + needToSendRetry = true; + return false; + } + + sc_assert(pkt->isResponse()); + + /* + * Pay for annotated transport delays. + * + * See recvTimingReq in sc_slave_port.cc for a detailed description. + */ + auto delay = sc_core::sc_time::from_value(pkt->payloadDelay); + // reset the delays + pkt->payloadDelay = 0; + pkt->headerDelay = 0; + + auto tlmSenderState = dynamic_cast(pkt->popSenderState()); + sc_assert(tlmSenderState != nullptr); + + auto& trans = tlmSenderState->trans; + + Gem5Extension* extension = nullptr; + trans.get_extension(extension); + + // clean up + delete tlmSenderState; + + // If there is an extension the packet was piped through and we must not + // delete it. The packet travels back with the transaction. + if (extension == nullptr) + destroyPacket(pkt); + else + sc_assert(extension->isPipeThrough()); + + sendBeginResp(trans, delay); + trans.release(); + + return true; +} + +void +SCMasterPort::sendBeginResp(tlm::tlm_generic_payload &trans, + sc_core::sc_time &delay) +{ + tlm::tlm_phase phase = tlm::BEGIN_RESP; + + trans.set_response_status(tlm::TLM_OK_RESPONSE); + + auto status = transactor->socket->nb_transport_bw(trans, phase, delay); + + if (status == tlm::TLM_COMPLETED || + (status == tlm::TLM_UPDATED && phase == tlm::END_RESP)) { + // transaction completed -> no need to wait for tlm::END_RESP + responseInProgress = false; + } else if (status == tlm::TLM_ACCEPTED) { + // we need to wait for tlm::END_RESP + responseInProgress = true; + } else { + panic("Unexpected status after sending BEGIN_RESP"); + } +} + +void +SCMasterPort::recvReqRetry() +{ + sc_assert(waitForRetry); + sc_assert(pendingRequest != nullptr); + sc_assert(pendingPacket != nullptr); + + if (sendTimingReq(pendingPacket)) { + waitForRetry = false; + pendingPacket = nullptr; + + auto &trans = *pendingRequest; + sendEndReq(trans); + trans.release(); + + pendingRequest = nullptr; + } +} + +void +SCMasterPort::recvRangeChange() +{ + SC_REPORT_WARNING("SCMasterPort", + "received address range change but ignored it"); +} + +ExternalMaster::Port * +SCMasterPortHandler::getExternalPort(const std::string &name, + ExternalMaster &owner, + const std::string &port_data) +{ + // Create and register a new SystemC master port + auto *port = new SCMasterPort(name, port_data, owner, control); + + //control.registerMasterPort(port_data, port); + + return port; +} + +} // namespace Gem5SystemC diff --git a/src/systemc/tlm_bridge/sc_master_port.hh b/src/systemc/tlm_bridge/sc_master_port.hh new file mode 100644 index 000000000..a8f1c5b92 --- /dev/null +++ b/src/systemc/tlm_bridge/sc_master_port.hh @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2016, Dresden University of Technology (TU Dresden) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Christian Menard + */ + +#ifndef __SYSTEMC_TLM_BRIDGE_SC_MASTER_PORT_HH__ +#define __SYSTEMC_TLM_BRIDGE_SC_MASTER_PORT_HH__ + +#include "mem/external_master.hh" +#include "systemc/ext/tlm_core/2/generic_payload/gp.hh" +#include "systemc/ext/tlm_core/2/generic_payload/phase.hh" +#include "systemc/ext/tlm_utils/peq_with_cb_and_phase.h" +#include "systemc/tlm_bridge/sc_peq.hh" +#include "systemc/tlm_bridge/sim_control_if.hh" + +namespace Gem5SystemC +{ + +// forward declaration +class Gem5MasterTransactor; +class Gem5SimControl; + +/** + * This is a gem5 master port that translates TLM transactions to gem5 packets. + * + * Upon receiving a TLM transaction (b_transport, nb_transport_fw, + * dbg_transport) the port generates a gem5 packet and initializes the packet + * with information from the transaction payload. The original TLM payload is + * added as a sender state to the gem5 packet. This way the payload can be + * restored when the response packet arrives at the port. + * + * Special care is required, when the TLM transaction originates from a + * SCSlavePort (i.e. it is a gem5 packet that enters back into the gem5 world). + * This is a common scenario, when multiple gem5 CPUs communicate via a SystemC + * interconnect. In this case, the master port restores the original packet + * from the payload extension (added by the SCSlavePort) and forwards it to the + * gem5 world. Throughout the code, this mechanism is called 'pipe through'. + * + * If gem5 operates in atomic mode, the master port registers the TLM blocking + * interface and automatically translates non-blocking requests to blocking. + * If gem5 operates in timing mode, the transactor registers the non-blocking + * interface. Then, the transactor automatically translated blocking requests. + * It is assumed that the mode (atomic/timing) does not change during + * execution. + */ +class SCMasterPort : public ExternalMaster::Port +{ + private: + struct TlmSenderState : public Packet::SenderState + { + tlm::tlm_generic_payload &trans; + TlmSenderState(tlm::tlm_generic_payload &trans) : trans(trans) {} + }; + + tlm_utils::peq_with_cb_and_phase peq; + + bool waitForRetry; + tlm::tlm_generic_payload *pendingRequest; + PacketPtr pendingPacket; + + bool needToSendRetry; + + bool responseInProgress; + + Gem5MasterTransactor *transactor; + + System *system; + + Gem5SimControl &simControl; + + protected: + // payload event call back + void peq_cb(tlm::tlm_generic_payload &trans, const tlm::tlm_phase &phase); + + // The TLM target interface + tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload &trans, + tlm::tlm_phase &phase, + sc_core::sc_time &t); + void b_transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &t); + unsigned int transport_dbg(tlm::tlm_generic_payload &trans); + bool get_direct_mem_ptr(tlm::tlm_generic_payload &trans, + tlm::tlm_dmi &dmi_data); + + // Gem5 SCMasterPort interface + bool recvTimingResp(PacketPtr pkt); + void recvReqRetry(); + void recvRangeChange(); + + public: + SCMasterPort(const std::string &name_, + const std::string &systemc_name, + ExternalMaster &owner_, + Gem5SimControl &simControl); + + void bindToTransactor(Gem5MasterTransactor *transactor); + + friend PayloadEvent; + + private: + void sendEndReq(tlm::tlm_generic_payload &trans); + void sendBeginResp(tlm::tlm_generic_payload &trans, + sc_core::sc_time &delay); + + void handleBeginReq(tlm::tlm_generic_payload &trans); + void handleEndResp(tlm::tlm_generic_payload &trans); + + PacketPtr generatePacket(tlm::tlm_generic_payload &trans); + void destroyPacket(PacketPtr pkt); + + void checkTransaction(tlm::tlm_generic_payload &trans); +}; + +class SCMasterPortHandler : public ExternalMaster::Handler +{ + private: + Gem5SimControl &control; + + public: + SCMasterPortHandler(Gem5SimControl &control) : control(control) {} + + ExternalMaster::Port *getExternalPort(const std::string &name, + ExternalMaster &owner, + const std::string &port_data); +}; + +} // namespace Gem5SystemC + +#endif // __SYSTEMC_TLM_BRIDGE_SC_MASTER_PORT_HH__ diff --git a/src/systemc/tlm_bridge/sc_mm.cc b/src/systemc/tlm_bridge/sc_mm.cc new file mode 100644 index 000000000..e4cfa457b --- /dev/null +++ b/src/systemc/tlm_bridge/sc_mm.cc @@ -0,0 +1,72 @@ +/* + * 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 "systemc/tlm_bridge/sc_mm.hh" + +namespace Gem5SystemC +{ + +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); +} + +} // namespace Gem5SystemC diff --git a/src/systemc/tlm_bridge/sc_mm.hh b/src/systemc/tlm_bridge/sc_mm.hh new file mode 100644 index 000000000..818407665 --- /dev/null +++ b/src/systemc/tlm_bridge/sc_mm.hh @@ -0,0 +1,65 @@ +/* + * 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 __SYSTEMC_TLM_BRIDGE_SC_MM_HH__ +#define __SYSTEMC_TLM_BRIDGE_SC_MM_HH__ + +#include + +#include "systemc/ext/tlm_core/2/generic_payload/gp.hh" + +namespace Gem5SystemC +{ + +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 freePayloads; +}; + +} // namespace Gem5SystemC + +#endif // __SYSTEMC_TLM_BRIDGE_SC_MM_HH__ diff --git a/src/systemc/tlm_bridge/sc_peq.hh b/src/systemc/tlm_bridge/sc_peq.hh new file mode 100644 index 000000000..386142b72 --- /dev/null +++ b/src/systemc/tlm_bridge/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 + +// gem5 includes +#include + +namespace Gem5SystemC { +/** + * A 'Fake Payload Event Queue', similar to the TLM PEQs. This helps the + * transactors to schedule events in gem5. + */ +template +class PayloadEvent : public Event +{ + public: + OWNER& port; + const std::string eventName; + void (OWNER::*handler)(PayloadEvent* 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* 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/src/systemc/tlm_bridge/sc_slave_port.cc b/src/systemc/tlm_bridge/sc_slave_port.cc new file mode 100644 index 000000000..062cafb3f --- /dev/null +++ b/src/systemc/tlm_bridge/sc_slave_port.cc @@ -0,0 +1,400 @@ +/* + * 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 + * Abdul Mutaal Ahmad + * Christian Menard + */ + +#include "systemc/tlm_bridge/sc_slave_port.hh" + +#include "systemc/tlm_bridge/sc_ext.hh" +#include "systemc/tlm_bridge/sc_mm.hh" +#include "systemc/tlm_bridge/slave_transactor.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(); + + 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("SCSlavePort", "No R/W packet"); + } +} + +/** + * Similar to TLM's blocking transport (LT) + */ +Tick +SCSlavePort::recvAtomic(PacketPtr packet) +{ + CAUGHT_UP; + SC_REPORT_INFO("SCSlavePort", "recvAtomic hasn't been tested much"); + + panic_if(packet->cacheResponding(), "Should not see packets where cache " + "is responding"); + + panic_if(!(packet->isRead() || packet->isWrite()), + "Should only see read and writes at TLM memory\n"); + + + 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("SCSlavePort", "SwapReq not supported"); + } else if (packet->isRead()) { + transactor->socket->b_transport(*trans, delay); + } else if (packet->isInvalidate()) { + // do nothing + } else if (packet->isWrite()) { + transactor->socket->b_transport(*trans, delay); + } else { + SC_REPORT_FATAL("SCSlavePort", "Typo of request not supported"); + } + + if (packet->needsResponse()) { + packet->makeResponse(); + } + + trans->release(); + + return delay.value(); +} + +/** + * Similar to TLM's debug transport + */ +void +SCSlavePort::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 = transactor->socket->transport_dbg(*trans); + if (bytes != trans->get_data_length()) { + SC_REPORT_FATAL("SCSlavePort","debug transport was not completed"); + } + + trans->release(); +} + +bool +SCSlavePort::recvTimingSnoopResp(PacketPtr packet) +{ + /* Snooping should be implemented with tlm_dbg_transport */ + SC_REPORT_FATAL("SCSlavePort","unimplemented func.: recvTimingSnoopResp"); + return false; +} + +void +SCSlavePort::recvFunctionalSnoop(PacketPtr packet) +{ + /* Snooping should be implemented with tlm_dbg_transport */ + SC_REPORT_FATAL("SCSlavePort","unimplemented func.: recvFunctionalSnoop"); +} + +/** + * Similar to TLM's non-blocking transport (AT) + */ +bool +SCSlavePort::recvTimingReq(PacketPtr packet) +{ + CAUGHT_UP; + + panic_if(packet->cacheResponding(), "Should not see packets where cache " + "is responding"); + + panic_if(!(packet->isRead() || packet->isWrite()), + "Should only see read and writes at TLM memory\n"); + + + /* We should never get a second request after noting that a retry is + * required */ + sc_assert(!needToSendRequestRetry); + + /* 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); + + /* + * Pay for annotated transport delays. + * + * The header delay marks the point in time, when the packet first is seen + * by the transactor. This is the point int time, when the transactor needs + * to send the BEGIN_REQ to the SystemC world. + * + * NOTE: We drop the payload delay here. Normally, the receiver would be + * responsible for handling the payload delay. In this case, however, + * the receiver is a SystemC module and has no notion of the gem5 + * transport protocol and we cannot simply forward the + * payload delay to the receiving module. Instead, we expect the + * receiving SystemC module to model the payload delay by deferring + * the END_REQ. This could lead to incorrect delays, if the XBar + * payload delay is longer than the time the receiver needs to accept + * the request (time between BEGIN_REQ and END_REQ). + * + * TODO: We could detect the case described above by remembering the + * payload delay and comparing it to the time between BEGIN_REQ and + * END_REQ. Then, a warning should be printed. + */ + auto delay = sc_core::sc_time::from_value(packet->payloadDelay); + // reset the delays + packet->payloadDelay = 0; + packet->headerDelay = 0; + + /* Starting TLM non-blocking sequence (AT) Refer to IEEE1666-2011 SystemC + * Standard Page 507 for a visualisation of the procedure */ + tlm::tlm_phase phase = tlm::BEGIN_REQ; + tlm::tlm_sync_enum status; + status = transactor->socket->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 * pe; + pe = new PayloadEvent(*this, + &SCSlavePort::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 +SCSlavePort::pec( + PayloadEvent *pe, + tlm::tlm_generic_payload &trans, + const tlm::tlm_phase &phase) +{ + sc_core::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; + sendRetryReq(); + } + } + if (phase == tlm::BEGIN_RESP) { + CAUGHT_UP; + + auto& extension = Gem5Extension::getExtension(trans); + auto packet = extension.getPacket(); + + sc_assert(!blockingResponse); + + bool need_retry = false; + + /* + * If the packet was piped through and needs a response, we don't need + * to touch the packet and can forward it directly as a response. + * Otherwise, we need to make a response and send the transformed + * packet. + */ + if (extension.isPipeThrough()) { + if (packet->isResponse()) { + need_retry = !sendTimingResp(packet); + } + } else if (packet->needsResponse()) { + packet->makeResponse(); + need_retry = !sendTimingResp(packet); + } + + 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_core::sc_time delay = sc_core::SC_ZERO_TIME; + transactor->socket->nb_transport_fw(trans, fw_phase, delay); + /* Release the transaction with all the extensions */ + trans.release(); + } + } + } + delete pe; +} + +void +SCSlavePort::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 = !sendTimingResp(packet); + + sc_assert(!need_retry); + + sc_core::sc_time delay = sc_core::SC_ZERO_TIME; + tlm::tlm_phase phase = tlm::END_RESP; + transactor->socket->nb_transport_fw(*trans, phase, delay); + // Release transaction with all the extensions + trans->release(); +} + +tlm::tlm_sync_enum +SCSlavePort::nb_transport_bw(tlm::tlm_generic_payload &trans, + tlm::tlm_phase &phase, + sc_core::sc_time &delay) +{ + PayloadEvent *pe; + pe = new PayloadEvent(*this, &SCSlavePort::pec, "PE"); + pe->notify(trans, phase, delay); + return tlm::TLM_ACCEPTED; +} + +SCSlavePort::SCSlavePort(const std::string &name_, + const std::string &systemc_name, + ExternalSlave &owner_) : + ExternalSlave::Port(name_, owner_), + blockingRequest(NULL), + needToSendRequestRetry(false), + blockingResponse(NULL), + transactor(nullptr) +{ +} + +void +SCSlavePort::bindToTransactor(Gem5SlaveTransactor *transactor) +{ + sc_assert(this->transactor == nullptr); + + this->transactor = transactor; + + transactor->socket.register_nb_transport_bw(this, + &SCSlavePort::nb_transport_bw); +} + +ExternalSlave::Port * +SCSlavePortHandler::getExternalPort(const std::string &name, + ExternalSlave &owner, + const std::string &port_data) +{ + // Create and register a new SystemC slave port + auto *port = new SCSlavePort(name, port_data, owner); + + //control.registerSlavePort(port_data, port); + + return port; +} + +} // namespace Gem5SystemC diff --git a/src/systemc/tlm_bridge/sc_slave_port.hh b/src/systemc/tlm_bridge/sc_slave_port.hh new file mode 100644 index 000000000..218f11443 --- /dev/null +++ b/src/systemc/tlm_bridge/sc_slave_port.hh @@ -0,0 +1,138 @@ +/* + * 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 __SYSTEMC_TLM_BRIDGE_SC_SLAVE_PORT_HH__ +#define __SYSTEMC_TLM_BRIDGE_SC_SLAVE_PORT_HH__ + +#include + +#include "mem/external_slave.hh" +#include "systemc/ext/tlm_core/2/generic_payload/gp.hh" +#include "systemc/tlm_bridge/sc_mm.hh" +#include "systemc/tlm_bridge/sc_peq.hh" + +namespace Gem5SystemC +{ + +// forward declaration +class Gem5SimControl; +class Gem5SlaveTransactor; + +/** + * Test that gem5 is at the same time as SystemC + */ +#define CAUGHT_UP do { \ + assert(curTick() == sc_core::sc_time_stamp().value()); \ +} while (0) + +/** + * 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 ExternalSlave::Port +{ + public: + /** One instance of pe and the related callback needed */ + //payloadEvent pe; + void pec(PayloadEvent *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); + + Gem5SlaveTransactor *transactor; + + public: + /** The TLM initiator interface */ + tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload &trans, + tlm::tlm_phase &phase, + sc_core::sc_time &t); + + SCSlavePort(const std::string &name_, + const std::string &systemc_name, + ExternalSlave &owner_); + + void bindToTransactor(Gem5SlaveTransactor *transactor); + + friend PayloadEvent; +}; + +class SCSlavePortHandler : public ExternalSlave::Handler +{ + private: + Gem5SimControl &control; + + public: + SCSlavePortHandler(Gem5SimControl &control) : control(control) {} + + ExternalSlave::Port *getExternalPort(const std::string &name, + ExternalSlave &owner, + const std::string &port_data); +}; + +} // namespace Gem5SystemC + +#endif // __SYSTEMC_TLM_BRIDGE_SC_SLAVE_PORT_HH__ diff --git a/src/systemc/tlm_bridge/sim_control_if.hh b/src/systemc/tlm_bridge/sim_control_if.hh new file mode 100644 index 000000000..ae1d00c43 --- /dev/null +++ b/src/systemc/tlm_bridge/sim_control_if.hh @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2017, Dresden University of Technology (TU Dresden) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Christian Menard + */ + +#ifndef __SYSTEMC_TLM_BRIDGE_SC_SIM_CONTROL_IF_HH__ +#define __SYSTEMC_TLM_BRIDGE_SC_SIM_CONTROL_IF_HH__ + +#include "systemc/ext/core/sc_interface.hh" + +namespace Gem5SystemC +{ + +// forward declarations +class SCSlavePort; +class SCMasterPort; + +class Gem5SimControlInterface : public sc_core::sc_interface +{ + public: + virtual SCSlavePort *getSlavePort(const std::string &name) = 0; + virtual SCMasterPort *getMasterPort(const std::string &name) = 0; +}; + +} // namespace Gem5SystemC + +#endif // __SYSTEMC_TLM_BRIDGE_SC_SIM_CONTROL_IF_HH__ diff --git a/src/systemc/tlm_bridge/slave_transactor.cc b/src/systemc/tlm_bridge/slave_transactor.cc new file mode 100644 index 000000000..ac96e7ad0 --- /dev/null +++ b/src/systemc/tlm_bridge/slave_transactor.cc @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2016, Dresden University of Technology (TU Dresden) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Christian Menard + */ + +#include "systemc/tlm_bridge/slave_transactor.hh" + +#include "systemc/tlm_bridge/sc_slave_port.hh" + +namespace Gem5SystemC +{ + +Gem5SlaveTransactor::Gem5SlaveTransactor(sc_core::sc_module_name name, + const std::string &portName) + : sc_core::sc_module(name), + socket(portName.c_str()), + sim_control("sim_control"), + portName(portName) +{ + if (portName.empty()) { + SC_REPORT_ERROR(name, "No port name specified!\n"); + } +} + +void +Gem5SlaveTransactor::before_end_of_elaboration() +{ + // auto *port = sim_control->getSlavePort(portName); + + //port->bindToTransactor(this); +} + +} // namespace Gem5SystemC diff --git a/src/systemc/tlm_bridge/slave_transactor.hh b/src/systemc/tlm_bridge/slave_transactor.hh new file mode 100644 index 000000000..8530fb9d5 --- /dev/null +++ b/src/systemc/tlm_bridge/slave_transactor.hh @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2016, Dresden University of Technology (TU Dresden) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Christian Menard + */ + +#ifndef __SYSTEMC_TLM_BRIDGE_SLAVE_TRANSACTOR_HH__ +#define __SYSTEMC_TLM_BRIDGE_SLAVE_TRANSACTOR_HH__ + +#include + +#include "systemc/ext/core/sc_module.hh" +#include "systemc/ext/core/sc_port.hh" +#include "systemc/ext/tlm_utils/simple_initiator_socket.h" +#include "systemc/tlm_bridge/sc_slave_port.hh" +#include "systemc/tlm_bridge/sim_control_if.hh" + +namespace Gem5SystemC +{ + +class Gem5SlaveTransactor : public sc_core::sc_module +{ + public: + // module interface + tlm_utils::simple_initiator_socket socket; + sc_core::sc_port sim_control; + + private: + std::string portName; + + public: + SC_HAS_PROCESS(Gem5SlaveTransactor); + + Gem5SlaveTransactor(sc_core::sc_module_name name, + const std::string &portName); + + void before_end_of_elaboration(); +}; + +} // namespace Gem5SystemC + +#endif // __SYSTEMC_TLM_BRIDGE_SLAVE_TRANSACTOR_HH__