diff --git a/configs/example/sst/riscv_fs.py b/configs/example/sst/riscv_fs.py new file mode 100644 index 0000000000..bdbd061120 --- /dev/null +++ b/configs/example/sst/riscv_fs.py @@ -0,0 +1,163 @@ +# Copyright (c) 2021 The Regents of the University of California +# All rights reserved. +# +# 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 m5 +from m5.objects import * +from os import path + +# For downloading the disk image +from gem5.resources.resource import Resource + +import argparse + +def generateMemNode(state, mem_range): + node = FdtNode("memory@%x" % int(mem_range.start)) + node.append(FdtPropertyStrings("device_type", ["memory"])) + node.append(FdtPropertyWords("reg", + state.addrCells(mem_range.start) + + state.sizeCells(mem_range.size()) )) + return node + +def generateDtb(system): + """ + Autogenerate DTB. Arguments are the folder where the DTB + will be stored, and the name of the DTB file. + """ + state = FdtState(addr_cells=2, size_cells=2, cpu_cells=1) + root = FdtNode('/') + root.append(state.addrCellsProperty()) + root.append(state.sizeCellsProperty()) + root.appendCompatible(["riscv-virtio"]) + + for mem_range in system.mem_ranges: + root.append(generateMemNode(state, mem_range)) + + sections = [*system.cpu, system.platform] + + for section in sections: + for node in section.generateDeviceTree(state): + if node.get_name() == root.get_name(): + root.merge(node) + else: + root.append(node) + + fdt = Fdt() + fdt.add_rootnode(root) + fdt.writeDtsFile(path.join(m5.options.outdir, 'device.dts')) + fdt.writeDtbFile(path.join(m5.options.outdir, 'device.dtb')) + +def createHiFivePlatform(system): + # Since the latency from CPU to the bus was set in SST, additional latency + # is undesirable. + system.membus = NoncoherentXBar( + frontend_latency = 0, forward_latency = 0, response_latency = 0, + header_latency = 0, width = 64 + ) + system.membus.badaddr_responder = BadAddr() + system.membus.default = \ + system.membus.badaddr_responder.pio + + system.memory_outgoing_bridge = OutgoingRequestBridge() + system.memory_outgoing_bridge.port = system.membus.mem_side_ports + for cpu in system.cpu: + cpu.createThreads() + cpu.icache_port = system.membus.cpu_side_ports + cpu.dcache_port = system.membus.cpu_side_ports + + cpu.mmu.connectWalkerPorts( + system.membus.cpu_side_ports, system.membus.cpu_side_ports) + + + system.platform = HiFive() + + system.platform.rtc = RiscvRTC(frequency=Frequency("100MHz")) + system.platform.clint.int_pin = system.platform.rtc.int_pin + + system.pma_checker = PMAChecker( + uncacheable=[ + *system.platform._on_chip_ranges(), + *system.platform._off_chip_ranges(), + ] + ) + + system.iobus = IOXBar() + system.bridge = Bridge(delay='50ns') + system.bridge.mem_side_port = system.iobus.cpu_side_ports + system.bridge.cpu_side_port = system.membus.mem_side_ports + system.bridge.ranges = system.platform._off_chip_ranges() + + system.platform.setNumCores(1) + + system.platform.attachOnChipIO(system.membus) + system.platform.attachOffChipIO(system.iobus) + + system.platform.attachPlic() + +parser = argparse.ArgumentParser() +parser.add_argument('--cpu-clock-rate', type=str, + help='CPU clock rate, e.g. 3GHz') +parser.add_argument('--memory-size', type=str, help='Memory size, e.g. 4GiB') + +args = parser.parse_args() +cpu_clock_rate = args.cpu_clock_rate +memory_size = args.memory_size + +# Try downloading the Resource +bbl_resource = Resource("riscv-boot-exit-nodisk") +bbl_path = bbl_resource.get_local_path() + +system = System() + +system.clk_domain = SrcClockDomain( + clock=cpu_clock_rate, voltage_domain=VoltageDomain() +) + +system.mem_ranges = [AddrRange(start=0x80000000, size=memory_size)] + +system.cpu = [TimingSimpleCPU(cpu_id=i) for i in range(1)] +system.mem_mode = 'timing' + +createHiFivePlatform(system) + +system.system_outgoing_bridge = OutgoingRequestBridge() +system.system_port = system.system_outgoing_bridge.port +generateDtb(system) +system.workload = RiscvLinux() +system.workload.addr_check = False +system.workload.object_file = bbl_path +system.workload.dtb_filename = path.join(m5.options.outdir, 'device.dtb') +system.workload.dtb_addr = 0x87e00000 +kernel_cmd = [ + # specifying Linux kernel boot options + "console=ttyS0" +] +system.workload.command_line = " ".join(kernel_cmd) + +for cpu in system.cpu: + cpu.createInterruptController() + +root = Root(full_system = True, system = system) + diff --git a/ext/sst/ExtMaster.cc b/ext/sst/ExtMaster.cc deleted file mode 100644 index e727537431..0000000000 --- a/ext/sst/ExtMaster.cc +++ /dev/null @@ -1,235 +0,0 @@ -// Copyright (c) 2015 ARM Limited -// All rights reserved. -// -// The license below extends only to copyright in the software and shall -// not be construed as granting a license to any other intellectual -// property including but not limited to intellectual property relating -// to a hardware implementation of the functionality of the software -// licensed hereunder. You may use the software subject to the license -// terms below provided that you ensure that this notice is replicated -// unmodified and in its entirety in all distributions of the software, -// modified or unmodified, in source code or in binary form. -// -// 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. - -// Copyright 2009-2014 Sandia Coporation. Under the terms -// of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. -// Government retains certain rights in this software. -// -// Copyright (c) 2009-2014, Sandia Corporation -// All rights reserved. -// -// For license information, see the LICENSE file in the current directory. - -#include "gem5.hh" - -#ifdef fatal // gem5 sets this -#undef fatal -#endif - -#include - -#include - -using namespace SST; -using namespace SST::gem5; -using namespace SST::MemHierarchy; - -ExtMaster::ExtMaster(gem5Component *g, Output &o, ::gem5::ExternalMaster& p, - std::string &n) : - ::gem5::ExternalMaster::Port(n, p), out(o), port(p), - simPhase(CONSTRUCTION), gem5(g), name(n) -{ - Params _p; // will be ignored - nic = dynamic_cast(gem5->loadModuleWithComponent("memHierarchy.memNIC", g, _p)); - - MemNIC::ComponentInfo ci; - ci.num_vcs = 1; - ci.link_port = "network"; - ci.link_bandwidth = "16GB/s"; - ci.link_inbuf_size = "1KB"; - ci.link_outbuf_size = "1KB"; - ci.network_addr = 0; // hard coded at the moment - ci.type = MemNIC::TypeDirectoryCtrl; - nic->moduleInit(ci, new Event::Handler - (this, &ExtMaster::handleEvent)); -} - -void -ExtMaster::init(unsigned phase) -{ - simPhase = INIT; - - if (phase == 0) { - assert(nic); - for (auto range : getAddrRanges()) { - MemNIC::ComponentTypeInfo ti; - ti.rangeStart = range.start(); - ti.rangeEnd = range.end(); - ti.interleaveSize = 0; - ti.interleaveStep = 0; - nic->addTypeInfo(ti); - ranges.insert(range); - } - } - - nic->init(phase); -} - -void -ExtMaster::setup(void) -{ - nic->setup(); - - simPhase = RUN; -} - -void -ExtMaster::finish(void) -{ - nic->finish(); -} - -void -ExtMaster::clock(void) -{ - nic->clock(); -} - -void -ExtMaster::handleEvent(SST::Event* event) -{ - if (simPhase == CONSTRUCTION) { - out.fatal(CALL_INFO, 1, "received Event during Construction phase\n"); - } - - MemEvent *ev = dynamic_cast(event); - if (!ev) { - out.fatal(CALL_INFO, 1, "Can't handle non-MemEvent Event's\n"); - } - - Command cmdI = ev->getCmd(); // command in - SST - ::gem5::MemCmd::Command cmdO; // command out - gem5 - bool data = false; - - switch (cmdI) { - case GetS: cmdO = ::gem5::MemCmd::ReadReq; break; - case GetX: cmdO = ::gem5::MemCmd::WriteReq; data = true; break; - case GetSEx: - case PutS: - case PutM: - case PutE: - case PutX: - case PutXE: - case Inv: - case FetchInv: - case FetchInvX: - - case NACK: - - case NULLCMD: - case GetSResp: - case GetXResp: - case FetchResp: - case FetchXResp: - out.fatal(CALL_INFO, 1, "Don't know how to convert " - "SST command %s to gem5\n", - CommandString[cmdI]); - } - - ::gem5::Request::FlagsType flags = 0; - if (ev->queryFlag(MemEvent::F_LOCKED)) - flags |= ::gem5::Request::LOCKED_RMW; - if (ev->queryFlag(MemEvent::F_NONCACHEABLE)) - flags |= ::gem5::Request::UNCACHEABLE; - if (ev->isLoadLink()) { - assert(cmdI == GetS); - cmdO = ::gem5::MemCmd::LoadLockedReq; - } else if (ev->isStoreConditional()) { - assert(cmdI == GetX); - cmdO = ::gem5::MemCmd::StoreCondReq; - } - - auto req = std::make_shared<::gem5::Request>( - ev->getAddr(), ev->getSize(), flags, 0); - req->setContext(ev->getGroupId()); - - auto pkt = new ::gem5::Packet(req, cmdO); - pkt->allocate(); - if (data) { - pkt->setData(ev->getPayload().data()); - } - pkt->pushSenderState(new SenderState(ev)); - - if (blocked() || !sendTimingReq(pkt)) - sendQ.push_back(pkt); -} - -bool -ExtMaster::recvTimingResp(::gem5::PacketPtr pkt) { - if (simPhase == INIT) { - out.fatal(CALL_INFO, 1, "not prepared to handle INIT-phase traffic\n"); - } - - // get original SST packet from gem5 SenderState - auto senderState = dynamic_cast(pkt->popSenderState()); - if (!senderState) - out.fatal(CALL_INFO, 1, "gem5 senderState corrupt\n"); - - // make (new) response packet, discard (old) original request - MemEvent* ev = senderState->event; - delete senderState; - - MemEvent* resp = ev->makeResponse(); - delete ev; - - // copy the payload and then destroy gem5 packet - resp->setPayload(pkt->getSize(), pkt->getPtr()); - delete pkt; - - nic->send(resp); - return true; -} - -void -ExtMaster::recvReqRetry() { - while (blocked() && sendTimingReq(sendQ.front())) { - sendQ.pop_front(); - } -} - -void -ExtMaster::recvRangeChange() { - for (auto range : getAddrRanges()) { - if (ranges.find(range) == ranges.end()) { // i.e. if not found, - MemNIC::ComponentTypeInfo ti; // indicating a new range. - ti.rangeStart = range.start(); - ti.rangeEnd = range.end(); - ti.interleaveSize = 0; - ti.interleaveStep = 0; - nic->addTypeInfo(ti); - ranges.insert(range); - } - } -} diff --git a/ext/sst/ExtMaster.hh b/ext/sst/ExtMaster.hh deleted file mode 100644 index 8b4020bdd1..0000000000 --- a/ext/sst/ExtMaster.hh +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (c) 2015 ARM Limited -// All rights reserved. -// -// The license below extends only to copyright in the software and shall -// not be construed as granting a license to any other intellectual -// property including but not limited to intellectual property relating -// to a hardware implementation of the functionality of the software -// licensed hereunder. You may use the software subject to the license -// terms below provided that you ensure that this notice is replicated -// unmodified and in its entirety in all distributions of the software, -// modified or unmodified, in source code or in binary form. -// -// 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. - -// Copyright 2009-2014 Sandia Coporation. Under the terms -// of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. -// Government retains certain rights in this software. -// -// Copyright (c) 2009-2014, Sandia Corporation -// All rights reserved. -// -// For license information, see the LICENSE file in the current directory. - -#ifndef EXT_SST_EXTMASTER_HH -#define EXT_SST_EXTMASTER_HH - -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -namespace SST { - -using MemHierarchy::MemEvent; -class Link; -class Event; - -namespace MemHierarchy { -class MemNIC; -} - -namespace gem5 { - -class gem5Component; - -class ExtMaster : public ::gem5::ExternalMaster::Port -{ - - enum Phase { CONSTRUCTION, INIT, RUN }; - - Output& out; - const ::gem5::ExternalMaster& port; - Phase simPhase; - - gem5Component *const gem5; - const std::string name; - std::list<::gem5::PacketPtr> sendQ; - bool blocked() { return !sendQ.empty(); } - - MemHierarchy::MemNIC * nic; - - struct SenderState : public ::gem5::Packet::SenderState - { - MemEvent *event; - SenderState(MemEvent* e) : event(e) {} - }; - - std::set<::gem5::AddrRange> ranges; - -public: - bool recvTimingResp(::gem5::PacketPtr); - void recvReqRetry(); - - ExtMaster(gem5Component*, Output&, ::gem5::ExternalMaster&, std::string&); - void init(unsigned phase); - void setup(); - void finish(); - - void clock(); - - // receive Requests from SST bound for a gem5 slave; - // this module is "external" from gem5's perspective, thus ExternalMaster. - void handleEvent(SST::Event*); - -protected: - virtual void recvRangeChange(); -}; - -} // namespace gem5 -} // namespace SST - -#endif diff --git a/ext/sst/ExtSlave.cc b/ext/sst/ExtSlave.cc deleted file mode 100644 index b9a5e78c3f..0000000000 --- a/ext/sst/ExtSlave.cc +++ /dev/null @@ -1,204 +0,0 @@ -// Copyright (c) 2015 ARM Limited -// All rights reserved. -// -// The license below extends only to copyright in the software and shall -// not be construed as granting a license to any other intellectual -// property including but not limited to intellectual property relating -// to a hardware implementation of the functionality of the software -// licensed hereunder. You may use the software subject to the license -// terms below provided that you ensure that this notice is replicated -// unmodified and in its entirety in all distributions of the software, -// modified or unmodified, in source code or in binary form. -// -// 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. - -// Copyright 2009-2014 Sandia Coporation. Under the terms -// of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. -// Government retains certain rights in this software. -// -// Copyright (c) 2009-2014, Sandia Corporation -// All rights reserved. -// -// For license information, see the LICENSE file in the current directory. - -#include "gem5.hh" - -#ifdef fatal // gem5 sets this -#undef fatal -#endif - -#include - -using namespace SST; -using namespace SST::gem5; -using namespace SST::MemHierarchy; - -ExtSlave::ExtSlave(gem5Component *g5c, Output &out, - ::gem5::ExternalSlave& port, std::string &name) : - ::gem5::ExternalSlave::Port(name, port), - comp(g5c), out(out), simPhase(CONSTRUCTION), initPackets(NULL), - link(comp->configureLink(name, new Event::Handler(this, - &ExtSlave::handleEvent))) -{ - if (!link) { - out.fatal(CALL_INFO, 1, "Failed to configure link %s\n", name.c_str()); - } -} - -void -ExtSlave::init(unsigned phase) -{ - simPhase = INIT; - if (initPackets) { - while (!initPackets->empty()) { - link->sendInitData(initPackets->front()); - initPackets->pop_front(); - } - delete initPackets; - initPackets = NULL; - } -} - -void -ExtSlave::recvFunctional(::gem5::PacketPtr pkt) -{ - if (simPhase == CONSTRUCTION) { - if (initPackets == NULL) { - initPackets = new std::list; - } - ::gem5::MemCmd::Command pktCmd = - (::gem5::MemCmd::Command)pkt->cmd.toInt(); - assert(pktCmd == ::gem5::MemCmd::WriteReq); - ::gem5::Addr a = pkt->getAddr(); - MemEvent* ev = new MemEvent(comp, a, a, GetX); - ev->setPayload(pkt->getSize(), pkt->getPtr()); - initPackets->push_back(ev); - } else { - panic("Functional accesses not allowed after construction phase"); - } -} - -bool -ExtSlave::recvTimingReq(::gem5::PacketPtr pkt) -{ - Command cmd; - switch ((::gem5::MemCmd::Command)pkt->cmd.toInt()) { - case ::gem5::MemCmd::HardPFReq: - case ::gem5::MemCmd::SoftPFReq: - case ::gem5::MemCmd::LoadLockedReq: - case ::gem5::MemCmd::ReadExReq: - case ::gem5::MemCmd::ReadReq: cmd = GetS; break; - case ::gem5::MemCmd::StoreCondReq: - case ::gem5::MemCmd::WriteReq: cmd = GetX; break; - default: - out.fatal(CALL_INFO, 1, "Don't know how to convert gem5 packet " - "command %s to SST\n", pkt->cmd.toString().c_str()); - } - - auto ev = new MemEvent(comp, pkt->getAddr(), pkt->getAddr(), cmd); - ev->setPayload(pkt->getSize(), pkt->getPtr()); - if ((::gem5::MemCmd::Command)pkt->cmd.toInt() == - ::gem5::MemCmd::LoadLockedReq) { - ev->setLoadLink(); - } else if ((::gem5::MemCmd::Command)pkt->cmd.toInt() == - ::gem5::MemCmd::StoreCondReq) { - ev->setStoreConditional(); - } - - if (pkt->req->isLockedRMW()) ev->setFlag(MemEvent::F_LOCKED); - if (pkt->req->isUncacheable()) ev->setFlag(MemEvent::F_NONCACHEABLE); - if (pkt->req->hasContextId()) ev->setGroupId(pkt->req->contextId()); -// Prefetches not working with SST; it maybe be dropping them, treating them -// as not deserving of responses, or something else -- not sure yet. -// ev->setPrefetchFlag(pkt->req->isPrefetch()); - - if (simPhase == INIT) { - link->sendInitData(ev); - delete pkt; - } else { - if (pkt->needsResponse()) { - PacketMap[ev->getID()] = pkt; - } - link->send(ev); - } - return true; -} - - -void -ExtSlave::handleEvent(Event* ev) -{ - MemEvent* event = dynamic_cast(ev); - if (!event) { - out.fatal(CALL_INFO, 1, "ExtSlave handleEvent received non-MemEvent\n"); - delete ev; - return; - } - Event::id_type id = event->getID(); - - PacketMap_t::iterator mi = PacketMap.find(id); - if (mi != PacketMap.end()) { // replying to prior request - ::gem5::PacketPtr pkt = mi->second; - PacketMap.erase(mi); - - pkt->makeResponse(); // Convert to a response packet - pkt->setData(event->getPayload().data()); - - // Resolve the success of Store Conditionals - if (pkt->isLLSC() && pkt->isWrite()) { - pkt->req->setExtraData(event->isAtomic()); - } - - // Clear out bus delay notifications - pkt->headerDelay = pkt->payloadDelay = 0; - - if (blocked() || !sendTimingResp(pkt)) { - respQ.push_back(pkt); - } - } else { // we can handle unexpected invalidates, but nothing else. - Command cmd = event->getCmd(); - assert(cmd == Inv); - - // make Req/Pkt for Snoop/no response needed - // presently no consideration for masterId, packet type, flags... - ::gem5::RequestPtr req = std::make_shared<::gem5::Request>( - event->getAddr(), event->getSize(), 0, 0); - - auto pkt = new ::gem5::Packet(req, ::gem5::MemCmd::InvalidateReq); - - // Clear out bus delay notifications - pkt->headerDelay = pkt->payloadDelay = 0; - - sendTimingSnoopReq(pkt); - } - delete event; -} - -void -ExtSlave::recvRespRetry() -{ - while (blocked() && sendTimingResp(respQ.front())) { - respQ.pop_front(); - } -} diff --git a/ext/sst/ExtSlave.hh b/ext/sst/ExtSlave.hh deleted file mode 100644 index fa32655b07..0000000000 --- a/ext/sst/ExtSlave.hh +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) 2015 ARM Limited -// All rights reserved. -// -// The license below extends only to copyright in the software and shall -// not be construed as granting a license to any other intellectual -// property including but not limited to intellectual property relating -// to a hardware implementation of the functionality of the software -// licensed hereunder. You may use the software subject to the license -// terms below provided that you ensure that this notice is replicated -// unmodified and in its entirety in all distributions of the software, -// modified or unmodified, in source code or in binary form. -// -// 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. - -// Copyright 2009-2014 Sandia Coporation. Under the terms -// of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. -// Government retains certain rights in this software. -// -// Copyright (c) 2009-2014, Sandia Corporation -// All rights reserved. -// -// For license information, see the LICENSE file in the current directory. - -#ifndef EXT_SST_EXTSLAVE_HH -#define EXT_SST_EXTSLAVE_HH - -#include -#include - -#include - -#include -#include -#include -#include -#include - -namespace SST { -class Link; -class Event; -class MemEvent; -namespace gem5 { - -class gem5Component; - -class ExtSlave : public ::gem5::ExternalSlave::Port -{ - public: - const std::string name; - - bool - recvTimingSnoopResp(::gem5::PacketPtr packet) - { - fatal("recvTimingSnoopResp unimplemented"); - return false; - } - - bool recvTimingReq(::gem5::PacketPtr packet); - - void recvFunctional(::gem5::PacketPtr packet); - - void recvRespRetry(); - - ::gem5::Tick - recvAtomic(::gem5::PacketPtr packet) - { - fatal("recvAtomic unimplemented"); - } - - enum Phase { CONSTRUCTION, INIT, RUN }; - - gem5Component *comp; - Output &out; - Phase simPhase; - - std::list* initPackets; - Link* link; - std::list<::gem5::PacketPtr> respQ; - bool blocked() { return !respQ.empty(); } - - typedef std::map PacketMap_t; - PacketMap_t PacketMap; // SST Event id -> gem5 Packet* - -public: - ExtSlave(gem5Component*, Output&, ::gem5::ExternalSlave&, std::string&); - void init(unsigned phase); - - void - setup() - { - simPhase = RUN; - } - - void handleEvent(Event*); -}; - -} -} - -#endif diff --git a/ext/sst/INSTALL.md b/ext/sst/INSTALL.md new file mode 100644 index 0000000000..4268724f83 --- /dev/null +++ b/ext/sst/INSTALL.md @@ -0,0 +1,94 @@ +# Installing SST + +The links to download SST source code are available here +[http://sst-simulator.org/SSTPages/SSTMainDownloads/]. +This guide is using the most recent SST version (11.0.0) as of September 2021. +The following guide assumes `$SST_CORE_HOME` as the location where SST will be +installed. + +## SST-Core + +### Downloading the SST-Core Source Code + +```sh +wget https://github.com/sstsimulator/sst-core/releases/download/v11.0.0_Final/sstcore-11.0.0.tar.gz +tar xf sstcore-11.0.0.tar.gz +``` + +### Installing SST-Core + +```sh +cd sstcore-11.0.0 +./configure --prefix=$SST_CORE_HOME --with-python=/usr/bin/python3-config \ + --disable-mpi # optional, used when MPI is not available. +make all -j$(nproc) +make install +``` + +Update `PATH`, + +```sh +export PATH=$SST_CORE_HOME/bin:$PATH +``` + +## SST-Elements + +### Downloading the SST-Elements Source Code + +```sh +wget https://github.com/sstsimulator/sst-elements/releases/download/v11.0.0_Final/sstelements-11.0.0.tar.gz +tar xf sstelements-11.0.0.tar.gz +``` + +### Installing SST-Elements + +```shs +cd sst-elements-library-11.0.0 +./configure --prefix=$SST_CORE_HOME --with-python=/usr/bin/python3-config \ + --with-sst-core=$SST_CORE_HOME +make all -j$(nproc) +make install +``` + +Adding `PKG_CONFIG_PATH` to `.bashrc` (so pkg-config can find SST .pc file), + +```sh +echo "export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:$SST_CORE_HOME/lib/pkgconfig/" >> ~/.bashrc +``` + +### Building gem5 library + +At the root of gem5 folder, + +```sh +scons build/RISCV/libgem5_opt.so -j $(nproc) --without-tcmalloc +``` + +### Compiling the SST integration + +At the root of gem5 folder, + +```sh +cd ext/sst +make +``` + +### Running an example simulation + +Downloading the built bootloader containing a Linux Kernel and a workload, + +```sh +wget http://dist.gem5.org/dist/develop/misc/riscv/bbl-busybox-boot-exit +``` + +Running the simulation + +```sh +sst --add-lib-path=./ sst/example.py +``` + +`bbl-busybox-boot-exit` contains an m5 binary, and `m5 exit` will be called +upon the booting process reaching the early userspace. +More information about building a bootloader containing a Linux Kernel and a +customized workload is available at +[https://gem5.googlesource.com/public/gem5-resources/+/refs/heads/develop/src/riscv-boot-exit-nodisk/]. diff --git a/ext/sst/LICENSE b/ext/sst/LICENSE index 787cadce8b..0bd04e72e5 100644 --- a/ext/sst/LICENSE +++ b/ext/sst/LICENSE @@ -1,5 +1,31 @@ ** This license only applies to the source files in this directory. +Copyright (c) 2021 The Regents of the University of California +All rights reserved. + +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. + Copyright (c) 2015 ARM Limited All rights reserved. diff --git a/ext/sst/Makefile b/ext/sst/Makefile index 3eb0a8e6c8..682af3d9ff 100644 --- a/ext/sst/Makefile +++ b/ext/sst/Makefile @@ -1,9 +1,10 @@ -# These two variables are designed to be modifiable. -SST_VERSION=SST-trunk +SST_VERSION=SST-11.1.0 # Name of the .pc file in lib/pkgconfig where SST is installed GEM5_LIB=gem5_opt +ARCH=RISCV +OFLAG=3 -LDFLAGS=-shared -fno-common ${shell pkg-config ${SST_VERSION} --libs} -L../../build/ARM -CXXFLAGS=-std=c++0x -g -O2 -fPIC ${shell pkg-config ${SST_VERSION} --cflags} ${shell python-config --includes} -I../../build/ARM +LDFLAGS=-shared -fno-common ${shell pkg-config ${SST_VERSION} --libs} -L../../build/${ARCH}/ -Wl,-rpath ../../build/${ARCH} +CXXFLAGS=-std=c++17 -g -O${OFLAG} -fPIC ${shell pkg-config ${SST_VERSION} --cflags} ${shell python3-config --includes} -I../../build/${ARCH}/ -I../../ext/pybind11/include/ -I../../build/softfloat/ CPPFLAGS+=-MMD -MP SRC=$(wildcard *.cc) diff --git a/ext/sst/README b/ext/sst/README deleted file mode 100644 index c9870ab85e..0000000000 --- a/ext/sst/README +++ /dev/null @@ -1,65 +0,0 @@ -This directory contains a connector that allows gem5 to be used as a -component in SST (Structural Simulation Toolkit, sst-simulator.org). More -specifically, it creates a .so that wraps the libgem5_*.so library. At a -high level, this allows memory traffic to pass between the two simulators. -SST Links are roughly analogous to gem5 Ports, although Links do not have -a notion of master and slave. This distinction is important to gem5, so -when connecting a gem5 CPU to an SST cache, an ExternalSlave must be used, -and similarly when connecting the memory side of SST cache to a gem5 port -(for memory <-> I/O), an ExternalMaster must be used. - -The connector handles the administrative aspects of gem5 -(initialization, simulation, shutdown) as well as translating -SST's MemEvents into gem5 Packets and vice-versa. - -Step-by-step instructions: - -0. install SST and its dependencies - -Note: the Makefile assumes you installed from an SVN checkout, not a release. -If you install a release, modify SST_VERSION at the top of the Makefile. - -0b. set/append to the PKG_CONFIG_PATH variable the path where SST installed - its pkgconfig, if not in a system-wide location. - -Then from gem5 root: - -1. build gem5 library: -% scons build/ARM/libgem5_opt.so - -Note: if you would rather use a fast, debug, etc. variant instead, -modify GEM5_LIB at the top of the Makefile. - -2. build gem5 SST component: -% make -C ext/sst - -3. run SST like so: -% sst --add-lib-path - -=========== - -Note: if you want to use an arch other than ARM (not tested/supported), -tweak the Makefile to get includes from that build directory instead. - -=========== - -This directory provides: -1. an SST "Component" for gem5; -2. a class that implements gem5's "ExternalMaster" interface to connect with - SST "Link"s exchanging "memEvents" - (sst/elements/memHierarchy stuff - caches, memories, etc.) - This lets gem5 receive packets from SST, as in - an SST LL$ (a master external to gem5) <-> I/O devices. -3. a class that implements gem5's "ExternalSlave" interface to connect with - SST "Link"s exchanging "memEvents" once again with the packet flow reversed: - gem5 CPU <-> SST L1 cache (a slave external to gem5) -4. an example configuration that uses both as follows: - gem5 CPUs - ^ - | [ExternalSlave] - v - SST cache hierarchy <-> SST memory - ^ - | [ExternalMaster] - v - gem5 I/O devices (terminal, disk, etc.) diff --git a/ext/sst/README.md b/ext/sst/README.md new file mode 100644 index 0000000000..7a8f838f43 --- /dev/null +++ b/ext/sst/README.md @@ -0,0 +1,85 @@ +# Using gem5 in an SST simulation + +## Overview + +This directory contains the library needed to use gem5 TimingSimpleCPU model in +an SST-driven simulation. + +When compiled, the gem5 library for SST `libgem5.so` will be generated, +containing the `libgem5_*.so` as well as the gem5 Component and the +SST Responder SubComponent. + +```text + On/Off-chip devs TimingSimpleCPU + ^ ^ ^ + | | | + v v v + ==================================== [gem5::NonCoherentXBar] + ^ [OutgoingRequestBridge] + gem5_system_port | +[OutgoingRequestBridge] ^ | + | | + [SSTResponder] v v [SSTResponder] +gem5 Component {SSTResponderSubComponent, SSTResponderSubComponent} + ^ ^ + | | + v v + ================================== [SST Bus] + ^ + | + v + SST cache <----> SST memory +``` + +## Components and SubComponents + +- gem5 Component has the following responsibilities, + - initializing the gem5 Python environment + - instantiating/setting-up the gem5 SimObjects as specified by the gem5 +configuration + - connect every SSTResponderSubComponent to the corresponding +OutgoingRequestBridge + - handling a gem5 event queue (with all thread-synchronization barriers +removed) + - handling executions of gem5 events when it has clockTick yielded by SST +**Note:** there should only be one gem5 Component per process. + +- SSTResponderSubComponent has the responsibity of receiving requests from +gem5, translating requests to an SST Request and sending it to SSTResponder. +Upon receiving a response from the memory interface, SSTResponderSubComponent +will translate the response to a gem5 Packet and send it to the its +OutgoingRequestBridge. + +- SSTResponder is owned by SSTResponderSubComponent. The responder will receive +the request from the SubComponent and send it to the SST memory hierarchy. + +## Installation + +See `INSTALL.md`. + +## Running an example simulation + +Downloading the built bootloader containing a Linux Kernel and a workload, + +```sh +wget http://dist.gem5.org/dist/develop/misc/riscv/bbl-busybox-boot-exit +``` + +Running the simulation + +```sh +sst sst/example.py +``` + +`bbl-busybox-boot-exit` contains an m5 binary, and `m5 exit` will be called +upon the booting process reaching the early userspace. +More information about building a bootloader containing a Linux Kernel and a +customized workload is available at +[https://gem5.googlesource.com/public/gem5-resources/+/refs/heads/develop/src/riscv-boot-exit-nodisk/]. + +## Notes + +- SwapReq from gem5 requires reading from memory and writing to memory. +We handle the request in SST in a way that, when SST gets the response +from memory, SST will send that response to gem5, while SST will send +a write request with modified data to memory. diff --git a/ext/sst/gem5.cc b/ext/sst/gem5.cc index 304956760a..924ee49b39 100644 --- a/ext/sst/gem5.cc +++ b/ext/sst/gem5.cc @@ -1,15 +1,6 @@ -// Copyright (c) 2015-2016 ARM Limited +// Copyright (c) 2021 The Regents of the University of California // All rights reserved. -// -// The license below extends only to copyright in the software and shall -// not be construed as granting a license to any other intellectual -// property including but not limited to intellectual property relating -// to a hardware implementation of the functionality of the software -// licensed hereunder. You may use the software subject to the license -// terms below provided that you ensure that this notice is replicated -// unmodified and in its entirety in all distributions of the software, -// modified or unmodified, in source code or in binary form. -// +// // 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 @@ -20,7 +11,42 @@ // 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. + +// Copyright (c) 2015-2016 ARM Limited +// All rights reserved. +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// 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 @@ -42,24 +68,49 @@ // // For license information, see the LICENSE file in the current directory. -#include +#include +#include +#include +#include +#include +#include + #include // Before serialization to prevent spurious warnings #include "gem5.hh" +#include "util.hh" + // System headers -#include +#include +#include +#include +#include #include +#include // gem5 Headers -#include +#include #include #include +#include #include +#include #include #include #include +#include +#include +#include +#include +#include +#include + +#include + +#include + #ifdef fatal // gem5 sets this #undef fatal #endif @@ -67,205 +118,352 @@ // More SST Headers #include -using namespace SST; -using namespace SST::gem5; - -gem5Component::gem5Component(ComponentId_t id, Params ¶ms) : - SST::Component(id) +gem5Component::gem5Component(SST::ComponentId_t id, SST::Params& params): + SST::Component(id), threadInitialized(false) { - dbg.init("@t:gem5:@p():@l " + getName() + ": ", 0, 0, - (Output::output_location_t)params.find("comp_debug", 0)); - info.init("gem5:" + getName() + ": ", 0, 0, Output::STDOUT); + output.init("gem5Component-" + getName() + "->", 1, 0, + SST::Output::STDOUT); - TimeConverter *clock = registerClock( - params.find("frequency", "1GHz"), - new Clock::Handler(this, &gem5Component::clockTick)); + std::string cpu_frequency = params.find("frequency", ""); + if (cpu_frequency.empty()) { + output.fatal( + CALL_INFO, -1, "The frequency of the CPU must be specified.\n" + ); + } - // This sets how many gem5 cycles we'll need to simulate per clock tick - sim_cycles = clock->getFactor(); - - // Disable gem5's inform() messages. - want_info = false; + // Register a handler to be called on a set frequency. + timeConverter = registerClock( + cpu_frequency, + new SST::Clock::Handler(this, &gem5Component::clockTick) + ); + // "cmd" -> gem5's Python std::string cmd = params.find("cmd", ""); if (cmd.empty()) { - dbg.fatal(CALL_INFO, -1, "Component %s must have a 'cmd' parameter.\n", - getName().c_str()); + output.fatal( + CALL_INFO, -1, "Component %s must have a 'cmd' parameter.\n", + getName().c_str() + ); } - std::vector args; - args.push_back(const_cast("sst.x")); // TODO: Compute this somehow? + // Telling SST the command line call to gem5 + args.push_back(const_cast("sst.x")); splitCommandArgs(cmd, args); - args.push_back(const_cast("--initialize-only")); - dbg.output(CALL_INFO, "Command string: [sst.x %s --initialize-only]\n", - cmd.c_str()); + output.output(CALL_INFO, "Command string: [sst.x %s]\n", cmd.c_str()); for (size_t i = 0; i < args.size(); ++i) { - dbg.output(CALL_INFO, " Arg [%02zu] = %s\n", i, args[i]); + output.output(CALL_INFO, " Arg [%02zu] = %s\n", i, args[i]); } - std::vector flags; - std::string gem5DbgFlags = params.find("gem5DebugFlags", ""); - splitCommandArgs(gem5DbgFlags, flags); - for (auto flag : flags) { - dbg.output(CALL_INFO, " Setting Debug Flag [%s]\n", flag); - ::gem5::setDebugFlag(flag); + // Parsing and setting gem5 debug flags + std::string gem5_debug_flags = params.find("debug_flags", ""); + for (auto const debug_flag: tokenizeString(gem5_debug_flags, {' ', ','})) { + output.output(CALL_INFO, "Debug flag += %s\n", debug_flag.c_str()); + gem5::setDebugFlag(debug_flag.c_str()); } - // These are idempotent - ::gem5::ExternalMaster::registerHandler("sst", this); - ::gem5::ExternalSlave::registerHandler("sst", this); - - // Initialize gem5's special signal handling. - ::gem5::initSignals(); - - initPython(args.size(), &args[0]); - - // tell the simulator not to end without us registerAsPrimaryComponent(); primaryComponentDoNotEndSim(); - clocks_processed = 0; + systemPort = \ + loadUserSubComponent("system_port",0); + cachePort = \ + loadUserSubComponent("cache_port", 0); + + systemPort->setTimeConverter(timeConverter); + systemPort->setOutputStream(&(output)); + cachePort->setTimeConverter(timeConverter); + cachePort->setOutputStream(&(output)); + } -gem5Component::~gem5Component(void) +gem5Component::~gem5Component() { - Py_Finalize(); } void gem5Component::init(unsigned phase) { - for (auto m : masters) { - m->init(phase); - } - for (auto s : slaves) { - s->init(phase); + output.output(CALL_INFO," init phase: %u\n", phase); + + if (phase == 0) { + initPython(args.size(), &args[0]); + + const std::vector m5_instantiate_commands = { + "m5.instantiate()" + }; + execPythonCommands(m5_instantiate_commands); + + // calling SimObject.startup() + const std::vector simobject_setup_commands = { + "import atexit", + "import _m5", + "root = m5.objects.Root.getInstance()", + "for obj in root.descendants(): obj.startup()", + "atexit.register(m5.stats.dump)", + "atexit.register(_m5.core.doExitCleanup)", + "m5.stats.reset()" + }; + execPythonCommands(simobject_setup_commands); + + // find the corresponding SimObject for each SSTResponderSubComponent + gem5::Root* gem5_root = gem5::Root::root(); + systemPort->findCorrespondingSimObject(gem5_root); + cachePort->findCorrespondingSimObject(gem5_root); + + // initialize the gem5 event queue + if (!(threadInitialized)) { + threadInitialized = true; + gem5::simulate_limit_event = new gem5::GlobalSimLoopExitEvent( + gem5::mainEventQueue[0]->getCurTick(), + "simulate() limit reached", + 0 + ); + } + } + + systemPort->init(phase); + cachePort->init(phase); } void -gem5Component::setup(void) +gem5Component::setup() { - // Switch connectors from initData to regular Sends - for (auto m : masters) { - m->setup(); - } - for (auto s : slaves) { - s->setup(); - } + output.verbose(CALL_INFO, 1, 0, "Component is being setup.\n"); + systemPort->setup(); + cachePort->setup(); } void -gem5Component::finish(void) +gem5Component::finish() { - for (auto m : masters) { - m->finish(); - } - info.output("Complete. Clocks Processed: %" PRIu64"\n", clocks_processed); + output.verbose(CALL_INFO, 1, 0, "Component is being finished.\n"); } bool -gem5Component::clockTick(Cycle_t cycle) +gem5Component::clockTick(SST::Cycle_t currentCycle) { - dbg.output(CALL_INFO, "Cycle %lu\n", cycle); + // what to do in a SST's cycle + gem5::GlobalSimLoopExitEvent *event = simulateGem5(currentCycle); + clocksProcessed++; + // gem5 exits due to reasons other than reaching simulation limit + if (event != gem5::simulate_limit_event) { + output.output("exiting: curTick()=%lu cause=`%s` code=%d\n", + gem5::curTick(), event->getCause().c_str(), event->getCode() + ); + // output gem5 stats + const std::vector output_stats_commands = { + "m5.stats.dump()" + }; + execPythonCommands(output_stats_commands); - for (auto m : masters) { - m->clock(); - } - - ::gem5::GlobalSimLoopExitEvent *event = ::gem5::simulate(sim_cycles); - ++clocks_processed; - if (event != simulate_limit_event) { - info.output("exiting: curTick()=%lu cause=`%s` code=%d\n", - ::gem5::curTick(), event->getCause().c_str(), - event->getCode()); primaryComponentOKToEndSim(); return true; } + // returning False means the simulation should go on return false; + } +#define PyCC(x) (const_cast(x)) -void -gem5Component::splitCommandArgs(std::string &cmd, - std::vector &args) +gem5::GlobalSimLoopExitEvent* +gem5Component::simulateGem5(uint64_t current_cycle) { - std::string sep1("\\"); - std::string sep2(" "); - std::string sep3("\"\'"); + // This function should be similar to simulate() of src/sim/simulate.cc + // with synchronization barriers removed. - boost::escaped_list_separator els(sep1, sep2, sep3); - boost::tokenizer> tok(cmd, els); + inform_once("Entering event queue @ %d. Starting simulation...\n", + gem5::curTick()); - for (auto beg : tok) { - args.push_back(strdup(beg.c_str())); + // Tick conversion + // The main logic for synchronize SST Tick and gem5 Tick is here. + // next_end_tick = current_cycle * timeConverter->getFactor() + uint64_t next_end_tick = \ + timeConverter->convertToCoreTime(current_cycle); + + // Here, if the next event in gem5's queue is not executed within the next + // cycle, there's no need to enter the gem5's sim loop. + if (next_end_tick < gem5::mainEventQueue[0]->getHead()->when()) + return gem5::simulate_limit_event; + gem5::simulate_limit_event->reschedule(next_end_tick); + gem5::Event *local_event = doSimLoop(gem5::mainEventQueue[0]); + gem5::BaseGlobalEvent *global_event = local_event->globalEvent(); + gem5::GlobalSimLoopExitEvent *global_exit_event = + dynamic_cast(global_event); + return global_exit_event; +} + +gem5::Event* +gem5Component::doSimLoop(gem5::EventQueue* eventq) +{ + // This function should be similar to doSimLoop() in src/sim/simulate.cc + // with synchronization barriers removed. + gem5::curEventQueue(eventq); + eventq->handleAsyncInsertions(); + + while (true) + { + // there should always be at least one event (the SimLoopExitEvent + // we just scheduled) in the queue + + assert(!eventq->empty()); + assert(gem5::curTick() <= eventq->nextTick() && + "event scheduled in the past"); + + if (gem5::async_event) { + // Take the event queue lock in case any of the service + // routines want to schedule new events. + if (gem5::async_statdump || gem5::async_statreset) { + gem5::statistics::schedStatEvent(gem5::async_statdump, + gem5::async_statreset); + gem5::async_statdump = false; + gem5::async_statreset = false; + } + + if (gem5::async_io) { + gem5::async_io = false; + gem5::pollQueue.service(); + } + + if (gem5::async_exit) { + gem5::async_exit = false; + gem5::exitSimLoop("user interrupt received"); + } + + if (gem5::async_exception) { + gem5::async_exception = false; + return NULL; + } + } + + gem5::Event *exit_event = eventq->serviceOne(); + if (exit_event != NULL) { + return exit_event; + } } } - -void -gem5Component::initPython(int argc, char *argv[]) +int +gem5Component::execPythonCommands(const std::vector& commands) { - const char * m5MainCommands[] = { - "import m5", - "m5.main()", - 0 // sentinel is required - }; + PyObject *dict = PyModule_GetDict(pythonMain); - PyObject *mainModule,*mainDict; + PyObject *result; - Py_SetProgramName(argv[0]); // optional but recommended - - Py_Initialize(); - - int ret = initM5Python(); - if (ret != 0) { - dbg.fatal(CALL_INFO, -1, "Python failed to initialize. Code: %d\n", - ret); + for (auto const command: commands) { + result = PyRun_String(command.c_str(), Py_file_input, dict, dict); + if (!result) { + PyErr_Print(); + return 1; + } + Py_DECREF(result); } + return 0; +} + +int +gem5Component::startM5(int argc, char **_argv) +{ + // This function should be similar to m5Main() of src/sim/init.cc + +#if HAVE_PROTOBUF + // Verify that the version of the protobuf library that we linked + // against is compatible with the version of the headers we + // compiled against. + GOOGLE_PROTOBUF_VERIFY_VERSION; +#endif + + +#if PY_MAJOR_VERSION >= 3 + typedef std::unique_ptr WArgUPtr; + std::vector v_argv; + std::vector vp_argv; + v_argv.reserve(argc); + vp_argv.reserve(argc); + for (int i = 0; i < argc; i++) { + v_argv.emplace_back(Py_DecodeLocale(_argv[i], NULL), &PyMem_RawFree); + vp_argv.emplace_back(v_argv.back().get()); + } + + wchar_t **argv = vp_argv.data(); +#else + char **argv = _argv; +#endif PySys_SetArgv(argc, argv); - mainModule = PyImport_AddModule("__main__"); - assert(mainModule); + // We have to set things up in the special __main__ module + pythonMain = PyImport_AddModule(PyCC("__main__")); + if (pythonMain == NULL) + panic("Could not import __main__"); - mainDict = PyModule_GetDict(mainModule); - assert(mainDict); + const std::vector commands = { + "import m5", + "m5.main()" + }; + execPythonCommands(commands); - PyObject *result; - const char **command = m5MainCommands; +#if HAVE_PROTOBUF + google::protobuf::ShutdownProtobufLibrary(); +#endif - // evaluate each command in the m5MainCommands array (basically a - // bunch of python statements. - while (*command) { - result = PyRun_String(*command, Py_file_input, mainDict, mainDict); - if (!result) { - PyErr_Print(); - break; - } - Py_DECREF(result); + return 0; +} - command++; +void +gem5Component::initPython(int argc, char *_argv[]) +{ + // should be similar to main() in src/sim/main.cc + PyObject *mainModule, *mainDict; + + int ret; + + // Initialize m5 special signal handling. + gem5::initSignals(); + +#if PY_MAJOR_VERSION >= 3 + std::unique_ptr program( + Py_DecodeLocale(_argv[0], NULL), + &PyMem_RawFree); + Py_SetProgramName(program.get()); +#else + Py_SetProgramName(_argv[0]); +#endif + + // Register native modules with Python's init system before + // initializing the interpreter. + if (!Py_IsInitialized()) { + gem5::registerNativeModules(); + // initialize embedded Python interpreter + Py_Initialize(); + } else { + // https://stackoverflow.com/a/28349174 + PyImport_AddModule("_m5"); + PyObject* module = gem5::EmbeddedPyBind::initAll(); + PyObject* sys_modules = PyImport_GetModuleDict(); + PyDict_SetItemString(sys_modules, "_m5", module); + Py_DECREF(module); } + + + // Initialize the embedded m5 python library + ret = gem5::EmbeddedPython::initAll(); + + if (ret == 0) + startM5(argc, _argv); // start m5 + else + output.output(CALL_INFO, "Not calling m5Main due to ret=%d\n", ret); } -::gem5::ExternalMaster::Port* -gem5Component::getExternalPort(const std::string &name, - ::gem5::ExternalMaster &owner, const std::string &port_data) +void +gem5Component::splitCommandArgs(std::string &cmd, std::vector &args) { - std::string s(name); // bridges non-& result and &-arg - auto master = new ExtMaster(this, info, owner, s); - masters.push_back(master); - return master; -} + std::vector parsed_args = tokenizeString( + cmd, {'\\', ' ', '\'', '\"'} + ); -::gem5::ExternalSlave::Port* -gem5Component::getExternalPort(const std::string &name, - ::gem5::ExternalSlave &owner, const std::string &port_data) -{ - std::string s(name); // bridges non-& result and &-arg - auto slave = new ExtSlave(this, info, owner, s); - slaves.push_back(slave); - return slave; + for (auto part: parsed_args) + args.push_back(strdup(part.c_str())); } diff --git a/ext/sst/gem5.hh b/ext/sst/gem5.hh index 4dc0213cb1..34d8bd616c 100644 --- a/ext/sst/gem5.hh +++ b/ext/sst/gem5.hh @@ -1,15 +1,6 @@ -// Copyright (c) 2015 ARM Limited +// Copyright (c) 2021 The Regents of the University of California // All rights reserved. -// -// The license below extends only to copyright in the software and shall -// not be construed as granting a license to any other intellectual -// property including but not limited to intellectual property relating -// to a hardware implementation of the functionality of the software -// licensed hereunder. You may use the software subject to the license -// terms below provided that you ensure that this notice is replicated -// unmodified and in its entirety in all distributions of the software, -// modified or unmodified, in source code or in binary form. -// +// // 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 @@ -20,7 +11,42 @@ // 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. + +// Copyright (c) 2015 ARM Limited +// All rights reserved. +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// 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 @@ -42,61 +68,84 @@ // // For license information, see the LICENSE file in the current directory. -#ifndef EXT_SST_GEM5_HH -#define EXT_SST_GEM5_HH +#ifndef __GEM5_COMPONENT_H__ +#define __GEM5_COMPONENT_H__ + +#define TRACING_ON 0 -#include #include #include -#include -#include +#include +#include + +#include +#include +#include -#include -#include #include -#include "ExtMaster.hh" -#include "ExtSlave.hh" +#include +#include -namespace SST { -namespace gem5 { +#include "sst_responder_subcomponent.hh" -class gem5Component : public SST::Component, - public ::gem5::ExternalSlave::Handler, - public ::gem5::ExternalMaster::Handler +class gem5Component: public SST::Component { -private: - - Output dbg; - Output info; - uint64_t sim_cycles; - uint64_t clocks_processed; - - std::vector masters; - std::vector slaves; - - void splitCommandArgs(std::string &cmd, std::vector &args); - void initPython(int argc, char *argv[]); - -public: - gem5Component(ComponentId_t id, Params ¶ms); + public: + gem5Component(SST::ComponentId_t id, SST::Params& params); ~gem5Component(); - virtual void init(unsigned); - virtual void setup(); - virtual void finish(); - bool clockTick(Cycle_t); - virtual ::gem5::ExternalMaster::Port *getExternalPort( - const std::string &name, ::gem5::ExternalMaster &owner, - const std::string &port_data); + void init(unsigned phase); + void setup(); + void finish(); + bool clockTick(SST::Cycle_t current_cycle); + + int startM5(int argc, char **_argv); + + + // stuff needed for gem5 sim + public: + PyObject *pythonMain; + int execPythonCommands(const std::vector& commands); + + private: + SST::Output output; + SSTResponderSubComponent* systemPort; + SSTResponderSubComponent* cachePort; + uint64_t clocksProcessed; + SST::TimeConverter* timeConverter; + gem5::GlobalSimLoopExitEvent *simulateLimitEvent; + std::vector args; + + void initPython(int argc, char **argv); + void splitCommandArgs(std::string &cmd, std::vector &args); + + bool threadInitialized; + + gem5::GlobalSimLoopExitEvent* simulateGem5(gem5::Tick n_cycles); + + static gem5::Event* doSimLoop(gem5::EventQueue* eventq); + + public: // register the component to SST + SST_ELI_REGISTER_COMPONENT( + gem5Component, + "gem5", // SST will look for libgem5.so + "gem5Component", + SST_ELI_ELEMENT_VERSION(1, 0, 0), + "Initialize gem5 and link SST's ports to gem5's ports", + COMPONENT_CATEGORY_UNCATEGORIZED + ) + + SST_ELI_DOCUMENT_PARAMS( + {"cmd", "command to run gem5's config"} + ) + + SST_ELI_DOCUMENT_SUBCOMPONENT_SLOTS( + {"system_port", "Connection to gem5 system_port", "gem5.gem5Bridge"}, + {"cache_port", "Connection to gem5 CPU", "gem5.gem5Bridge"} + ) - virtual ::gem5::ExternalSlave::Port *getExternalPort( - const std::string &name, ::gem5::ExternalSlave &owner, - const std::string &port_data); }; -} -} - -#endif +#endif // __GEM5_COMPONENT_H__ diff --git a/ext/sst/libgem5.cc b/ext/sst/libgem5.cc deleted file mode 100644 index 93fa05b32a..0000000000 --- a/ext/sst/libgem5.cc +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) 2015 ARM Limited -// All rights reserved. -// -// The license below extends only to copyright in the software and shall -// not be construed as granting a license to any other intellectual -// property including but not limited to intellectual property relating -// to a hardware implementation of the functionality of the software -// licensed hereunder. You may use the software subject to the license -// terms below provided that you ensure that this notice is replicated -// unmodified and in its entirety in all distributions of the software, -// modified or unmodified, in source code or in binary form. -// -// 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. - -// Copyright 2009-2014 Sandia Coporation. Under the terms -// of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. -// Government retains certain rights in this software. -// -// Copyright (c) 2009-2014, Sandia Corporation -// All rights reserved. -// -// For license information, see the LICENSE file in the current directory. - -#include - -#include "gem5.hh" - -static -SST::Component* create_gem5(SST::ComponentId_t id, SST::Params ¶ms) -{ - return new SST::gem5::gem5Component(id, params); -} - - -static const SST::ElementInfoParam gem5_params[] = { - {"cmd", "gem5 command to execute."}, - {"comp_debug", "Debug information from the component: 0 (off), 1 (stdout)," - " 2 (stderr), 3(file)"}, - {"frequency", "Frequency with which to call into gem5"}, - {NULL, NULL} -}; - -static const SST::ElementInfoComponent components[] = { - { "gem5", - "gem5 simulation component", - NULL, - create_gem5, - gem5_params - }, - { NULL, NULL, NULL, NULL, NULL } -}; - -extern "C" { - SST::ElementLibraryInfo gem5_eli = { - "gem5", - "gem5 Simulation", - components, - }; -} diff --git a/ext/sst/sst/README.md b/ext/sst/sst/README.md new file mode 100644 index 0000000000..98f4b14a17 --- /dev/null +++ b/ext/sst/sst/README.md @@ -0,0 +1,3 @@ +# SST System Configurations + +This folder contains SST configurations used for SST/gem5 simulation. diff --git a/ext/sst/sst/example.py b/ext/sst/sst/example.py new file mode 100644 index 0000000000..76cf8ad24e --- /dev/null +++ b/ext/sst/sst/example.py @@ -0,0 +1,120 @@ +# Copyright (c) 2021 The Regents of the University of California +# All rights reserved. +# +# 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 sst +import sys +import os + +from sst import UnitAlgebra + +cache_link_latency = "1ps" + +bbl = "riscv-boot-exit-nodisk" +cpu_clock_rate = "3GHz" +# gem5 will send requests to physical addresses of range [0x80000000, inf) to memory +# currently, we do not subtract 0x80000000 from the request's address to get the "real" address +# so, the mem_size would always be 2GiB larger than the desired memory size +memory_size_gem5 = "4GiB" +memory_size_sst = "6GiB" +addr_range_end = UnitAlgebra(memory_size_sst).getRoundedValue() + +l1_params = { + "access_latency_cycles" : "1", + "cache_frequency" : cpu_clock_rate, + "replacement_policy" : "lru", + "coherence_protocol" : "MESI", + "associativity" : "4", + "cache_line_size" : "64", + "cache_size" : "4 KiB", + "L1" : "1", +} + +cpu_params = { + "frequency": cpu_clock_rate, + "cmd": " ../../configs/example/sst/riscv_fs.py --cpu-clock-rate {} --memory-size {}".format(cpu_clock_rate, memory_size_gem5), + "debug_flags": "" +} + +gem5_node = sst.Component("gem5_node", "gem5.gem5Component") +gem5_node.addParams(cpu_params) + +cache_bus = sst.Component("cache_bus", "memHierarchy.Bus") +cache_bus.addParams( { "bus_frequency" : cpu_clock_rate } ) + +system_port = gem5_node.setSubComponent("system_port", "gem5.gem5Bridge", 0) # for initialization +system_port.addParams({ "response_receiver_name": "system.system_outgoing_bridge"}) # tell the SubComponent the name of the corresponding SimObject + +cache_port = gem5_node.setSubComponent("cache_port", "gem5.gem5Bridge", 0) # SST -> gem5 +cache_port.addParams({ "response_receiver_name": "system.memory_outgoing_bridge"}) + +# L1 cache +l1_cache = sst.Component("l1_cache", "memHierarchy.Cache") +l1_cache.addParams(l1_params) + +# Memory +memctrl = sst.Component("memory", "memHierarchy.MemController") +memctrl.addParams({ + "debug" : "0", + "clock" : "1GHz", + "request_width" : "64", + "addr_range_end" : addr_range_end, # should be changed accordingly to memory_size_sst +}) +memory = memctrl.setSubComponent("backend", "memHierarchy.simpleMem") +memory.addParams({ + "access_time" : "30ns", + "mem_size" : memory_size_sst +}) + +# Connections +# cpu <-> L1 +cpu_cache_link = sst.Link("cpu_l1_cache_link") +cpu_cache_link.connect( + (cache_port, "port", cache_link_latency), + (cache_bus, "high_network_0", cache_link_latency) +) +system_cache_link = sst.Link("system_cache_link") +system_cache_link.connect( + (system_port, "port", cache_link_latency), + (cache_bus, "high_network_1", cache_link_latency) +) +cache_bus_cache_link = sst.Link("cache_bus_cache_link") +cache_bus_cache_link.connect( + (cache_bus, "low_network_0", cache_link_latency), + (l1_cache, "high_network_0", cache_link_latency) +) +# L1 <-> mem +cache_mem_link = sst.Link("l1_cache_mem_link") +cache_mem_link.connect( + (l1_cache, "low_network_0", cache_link_latency), + (memctrl, "direct_link", cache_link_latency) +) + +# enable Statistics +stat_params = { "rate" : "0ns" } +sst.setStatisticLoadLevel(5) +sst.setStatisticOutput("sst.statOutputTXT", {"filepath" : "./sst-stats.txt"}) +sst.enableAllStatisticsForComponentName("l1_cache", stat_params) +sst.enableAllStatisticsForComponentName("memory", stat_params) diff --git a/ext/sst/sst_responder.cc b/ext/sst/sst_responder.cc new file mode 100644 index 0000000000..14c64abb52 --- /dev/null +++ b/ext/sst/sst_responder.cc @@ -0,0 +1,68 @@ +// Copyright (c) 2021 The Regents of the University of California +// All rights reserved. +// +// 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. + +#include "sst_responder.hh" + +#include + +#include "translator.hh" + +SSTResponder::SSTResponder(SSTResponderSubComponent* owner_) + : gem5::SSTResponderInterface() +{ + owner = owner_; +} + +SSTResponder::~SSTResponder() +{ +} + +void +SSTResponder::setOutputStream(SST::Output* output_) +{ + output = output_; +} + +bool +SSTResponder::handleRecvTimingReq(gem5::PacketPtr pkt) +{ + auto request = Translator::gem5RequestToSSTRequest( + pkt, owner->sstRequestIdToPacketMap + ); + return owner->handleTimingReq(request); +} + +void +SSTResponder::handleRecvRespRetry() +{ + owner->handleRecvRespRetry(); +} + +void +SSTResponder::handleRecvFunctional(gem5::PacketPtr pkt) +{ + owner->handleRecvFunctional(pkt); +} diff --git a/ext/sst/sst_responder.hh b/ext/sst/sst_responder.hh new file mode 100644 index 0000000000..a89d311064 --- /dev/null +++ b/ext/sst/sst_responder.hh @@ -0,0 +1,74 @@ +// Copyright (c) 2021 The Regents of the University of California +// All rights reserved. +// +// 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. + +#ifndef __SST_RESPONDER_HH__ +#define __SST_RESPONDER_HH__ + +#define TRACING_ON 0 + +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include + +// from gem5 +#include +#include +#include + +#include "sst_responder_subcomponent.hh" + +class SSTResponderSubComponent; + +class SSTResponder: public gem5::SSTResponderInterface +{ + private: + SSTResponderSubComponent* owner; + SST::Output* output; + public: + SSTResponder(SSTResponderSubComponent* owner_); + ~SSTResponder() override; + + void setOutputStream(SST::Output* output_); + + bool handleRecvTimingReq(gem5::PacketPtr pkt) override; + void handleRecvRespRetry() override; + void handleRecvFunctional(gem5::PacketPtr pkt) override; +}; + +#endif // __SST_RESPONDER_HH__ diff --git a/ext/sst/sst_responder_subcomponent.cc b/ext/sst/sst_responder_subcomponent.cc new file mode 100644 index 0000000000..4c895acdb6 --- /dev/null +++ b/ext/sst/sst_responder_subcomponent.cc @@ -0,0 +1,238 @@ +// Copyright (c) 2021 The Regents of the University of California +// All rights reserved. +// +// 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. + +#include "sst_responder_subcomponent.hh" + +#include +#include +#include + +#ifdef fatal // gem5 sets this +#undef fatal +#endif + +SSTResponderSubComponent::SSTResponderSubComponent(SST::ComponentId_t id, + SST::Params& params) + : SubComponent(id) +{ + sstResponder = new SSTResponder(this); + gem5SimObjectName = params.find("response_receiver_name", ""); + if (gem5SimObjectName == "") + assert(false && "The response_receiver_name must be specified"); +} + +SSTResponderSubComponent::~SSTResponderSubComponent() +{ + delete sstResponder; +} + +void +SSTResponderSubComponent::setTimeConverter(SST::TimeConverter* tc) +{ + timeConverter = tc; + + // Get the memory interface + SST::Params interface_params; + // This is how you tell the interface the name of the port it should use + interface_params.insert("port", "port"); + interface_params.insert("mem_size", "8GiB"); + // Loads a “memHierarchy.memInterface” into index 0 of the “memory” slot + // SHARE_PORTS means the interface can use our port as if it were its own + // INSERT_STATS means the interface will inherit our statistic + // configuration (e.g., if ours are enabled, the interface’s will be too) + memoryInterface = \ + loadAnonymousSubComponent( + "memHierarchy.memInterface", "memory", 0, + SST::ComponentInfo::SHARE_PORTS | SST::ComponentInfo::INSERT_STATS, + interface_params, timeConverter, + new SST::Interfaces::SimpleMem::Handler( + this, &SSTResponderSubComponent::portEventHandler) + ); + assert(memoryInterface != NULL); +} + +void +SSTResponderSubComponent::setOutputStream(SST::Output* output_) +{ + output = output_; +} + +void +SSTResponderSubComponent::setResponseReceiver( + gem5::OutgoingRequestBridge* gem5_bridge) +{ + responseReceiver = gem5_bridge; + responseReceiver->setResponder(sstResponder); +} + +bool +SSTResponderSubComponent::handleTimingReq( + SST::Interfaces::SimpleMem::Request* request) +{ + memoryInterface->sendRequest(request); + return true; +} + +void +SSTResponderSubComponent::init(unsigned phase) +{ + if (phase == 1) { + for (auto p: responseReceiver->getInitData()) { + gem5::Addr addr = p.first; + std::vector data = p.second; + SST::Interfaces::SimpleMem::Request* request = \ + new SST::Interfaces::SimpleMem::Request( + SST::Interfaces::SimpleMem::Request::Command::Write, addr, + data.size(), data + ); + memoryInterface->sendInitData(request); + } + } + memoryInterface->init(phase); +} + +void +SSTResponderSubComponent::setup() +{ +} + +bool +SSTResponderSubComponent::findCorrespondingSimObject(gem5::Root* gem5_root) +{ + gem5::OutgoingRequestBridge* receiver = \ + dynamic_cast( + gem5_root->find(gem5SimObjectName.c_str())); + setResponseReceiver(receiver); + return receiver != NULL; +} + +void +SSTResponderSubComponent::handleSwapReqResponse( + SST::Interfaces::SimpleMem::Request* request) +{ + // get the data, then, + // 1. send a response to gem5 with the original data + // 2. send a write to memory with atomic op applied + + SST::Interfaces::SimpleMem::Request::id_t request_id = request->id; + TPacketMap::iterator it = sstRequestIdToPacketMap.find(request_id); + assert(it != sstRequestIdToPacketMap.end()); + std::vector data = request->data; + + // step 1 + gem5::PacketPtr pkt = it->second; + pkt->setData(request->data.data()); + pkt->makeAtomicResponse(); + pkt->headerDelay = pkt->payloadDelay = 0; + if (blocked() || !responseReceiver->sendTimingResp(pkt)) + responseQueue.push(pkt); + + // step 2 + (*(pkt->getAtomicOp()))(data.data()); // apply the atomic op + SST::Interfaces::SimpleMem::Request::Command cmd = \ + SST::Interfaces::SimpleMem::Request::Command::Write; + SST::Interfaces::SimpleMem::Addr addr = request->addr; + auto data_size = data.size(); + SST::Interfaces::SimpleMem::Request* write_request = \ + new SST::Interfaces::SimpleMem::Request( + cmd, addr, data_size, data + ); + write_request->setMemFlags( + SST::Interfaces::SimpleMem::Request::Flags::F_LOCKED); + memoryInterface->sendRequest(write_request); + + delete request; +} + +void +SSTResponderSubComponent::portEventHandler( + SST::Interfaces::SimpleMem::Request* request) +{ + // Expect to handle an SST response + SST::Interfaces::SimpleMem::Request::id_t request_id = request->id; + + TPacketMap::iterator it = sstRequestIdToPacketMap.find(request_id); + + // replying to a prior request + if (it != sstRequestIdToPacketMap.end()) { + gem5::PacketPtr pkt = it->second; // the packet that needs response + + // Responding to a SwapReq requires a special handler + // 1. send a response to gem5 with the original data + // 2. send a write to memory with atomic op applied + if ((gem5::MemCmd::Command)pkt->cmd.toInt() == gem5::MemCmd::SwapReq) { + handleSwapReqResponse(request); + return; + } + + sstRequestIdToPacketMap.erase(it); + + Translator::inplaceSSTRequestToGem5PacketPtr(pkt, request); + + if (blocked() || !(responseReceiver->sendTimingResp(pkt))) + responseQueue.push(pkt); + } else { // we can handle unexpected invalidates, but nothing else. + SST::Interfaces::SimpleMem::Request::Command cmd = request->cmd; + if (cmd == SST::Interfaces::SimpleMem::Request::Command::WriteResp) + return; + assert(cmd == SST::Interfaces::SimpleMem::Request::Command::Inv); + + // make Req/Pkt for Snoop/no response needed + // presently no consideration for masterId, packet type, flags... + gem5::RequestPtr req = std::make_shared( + request->addr, request->size, 0, 0 + ); + + gem5::PacketPtr pkt = new gem5::Packet( + req, gem5::MemCmd::InvalidateReq); + + // Clear out bus delay notifications + pkt->headerDelay = pkt->payloadDelay = 0; + + responseReceiver->sendTimingSnoopReq(pkt); + } + + delete request; +} + +void +SSTResponderSubComponent::handleRecvRespRetry() +{ + while (blocked() && + responseReceiver->sendTimingResp(responseQueue.front())) + responseQueue.pop(); +} + +void +SSTResponderSubComponent::handleRecvFunctional(gem5::PacketPtr pkt) +{ +} + +bool +SSTResponderSubComponent::blocked() +{ + return !(responseQueue.empty()); +} diff --git a/ext/sst/sst_responder_subcomponent.hh b/ext/sst/sst_responder_subcomponent.hh new file mode 100644 index 0000000000..a897deb367 --- /dev/null +++ b/ext/sst/sst_responder_subcomponent.hh @@ -0,0 +1,122 @@ +// Copyright (c) 2021 The Regents of the University of California +// All rights reserved. +// +// 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. + +#ifndef __SST_RESPONDER_SUBCOMPONENT_HH__ +#define __SST_RESPONDER_SUBCOMPONENT_HH__ + +#define TRACING_ON 0 + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include + +// from gem5 +#include +#include +#include +#include + +#include "translator.hh" +#include "sst_responder.hh" + +class SSTResponderSubComponent: public SST::SubComponent +{ + private: + gem5::OutgoingRequestBridge* responseReceiver; + gem5::SSTResponderInterface* sstResponder; + + SST::Interfaces::SimpleMem* memoryInterface; + SST::TimeConverter* timeConverter; + SST::Output* output; + std::queue responseQueue; + + std::vector initRequests; + + std::string gem5SimObjectName; + + public: + SSTResponderSubComponent(SST::ComponentId_t id, SST::Params& params); + ~SSTResponderSubComponent(); + + void init(unsigned phase); + void setTimeConverter(SST::TimeConverter* tc); + void setOutputStream(SST::Output* output_); + + void setResponseReceiver(gem5::OutgoingRequestBridge* gem5_bridge); + void portEventHandler(SST::Interfaces::SimpleMem::Request* request); + + bool blocked(); + void setup(); + + // return true if the SimObject could be found + bool findCorrespondingSimObject(gem5::Root* gem5_root); + + bool handleTimingReq(SST::Interfaces::SimpleMem::Request* request); + void handleRecvRespRetry(); + void handleRecvFunctional(gem5::PacketPtr pkt); + void handleSwapReqResponse(SST::Interfaces::SimpleMem::Request* request); + + TPacketMap sstRequestIdToPacketMap; + + public: // register the component to SST + SST_ELI_REGISTER_SUBCOMPONENT_API(SSTResponderSubComponent); + SST_ELI_REGISTER_SUBCOMPONENT_DERIVED( + SSTResponderSubComponent, + "gem5", // SST will look for libgem5.so + "gem5Bridge", + SST_ELI_ELEMENT_VERSION(1, 0, 0), + "Initialize gem5 and link SST's ports to gem5's ports", + SSTResponderSubComponent + ) + + SST_ELI_DOCUMENT_SUBCOMPONENT_SLOTS( + {"memory", "Interface to the memory subsystem", \ + "SST::Interfaces::SimpleMem"} + ) + + SST_ELI_DOCUMENT_PORTS( + {"port", "Handling mem events", {"memHierarchy.MemEvent", ""}} + ) + + SST_ELI_DOCUMENT_PARAMS( + {"response_receiver_name", \ + "Name of the SimObject receiving the responses"} + ) + +}; + +#endif // __SST_RESPONDER_SUBCOMPONENT_HH__ diff --git a/ext/sst/tests/test6_arm_4c.py b/ext/sst/tests/test6_arm_4c.py deleted file mode 100644 index f3bb43600b..0000000000 --- a/ext/sst/tests/test6_arm_4c.py +++ /dev/null @@ -1,204 +0,0 @@ -# Copyright (c) 2015-2016 ARM Limited -# All rights reserved. -# -# The license below extends only to copyright in the software and shall -# not be construed as granting a license to any other intellectual -# property including but not limited to intellectual property relating -# to a hardware implementation of the functionality of the software -# licensed hereunder. You may use the software subject to the license -# terms below provided that you ensure that this notice is replicated -# unmodified and in its entirety in all distributions of the software, -# modified or unmodified, in source code or in binary form. -# -# 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: Curtis Dunham - -import sst -import sys -import os - -lat="1 ns" -buslat="2 ns" -clockRate = "1GHz" - - -def getenv(name): - res = "" - try: - res = os.environ[name] - except KeyError: - pass - return res - -def debug(d): - try: - r = int(getenv(d)) - except ValueError: - return 0 - return r - -baseCacheParams = ({ - "debug" :debug("DEBUG"), - "debug_level" : 6, - "coherence_protocol" : "MSI", - "replacement_policy" : "LRU", - "cache_line_size" : 64, - "cache_frequency" : clockRate - }) - -l1CacheParams = ({ - "debug" : debug("DEBUG"), - "debug_level" : 6, - "L1" : 1, - "cache_size" : "64 KB", - "associativity" : 4, - "access_latency_cycles" : 2, - "low_network_links" : 1 - }) - -l2CacheParams = ({ - "debug" : debug("DEBUG"), - "debug_level" : 6, - "L1" : 0, - "cache_size" : "256 KB", - "associativity" : 8, - "access_latency_cycles" : 8, - "high_network_links" : 1, - "mshr_num_entries" : 4096, - "low_network_links" : 1 - }) - - -GEM5 = sst.Component("system", "gem5.gem5") -GEM5.addParams({ - "comp_debug" : debug("GEM5_DEBUG"), - "gem5DebugFlags" : debug("M5_DEBUG"), - "frequency" : clockRate, - "cmd" : "configs/example/fs.py --num-cpus 4 --disk-image=vexpress64-openembedded_minimal-armv8_20130623-376.img --root-device=/dev/sda2 --kernel=vmlinux.aarch64.20140821 --dtb-filename=vexpress.aarch64.20140821.dtb --mem-size=256MB --machine-type=VExpress_EMM64 --cpu-type=timing --external-memory-system=sst" - }) - -bus = sst.Component("membus", "memHierarchy.Bus") -bus.addParams({ - "bus_frequency": "2GHz", - "debug" : debug("DEBUG"), - "debug_level" : 8 - }) - -def buildL1(name, m5, connector): - cache = sst.Component(name, "memHierarchy.Cache") - cache.addParams(baseCacheParams) - cache.addParams(l1CacheParams) - link = sst.Link("cpu_%s_link"%name) - link.connect((m5, connector, lat), (cache, "high_network_0", lat)) - return cache - -SysBusConn = buildL1("gem5SystemBus", GEM5, "system.external_memory.port") -bus_port = 0 -link = sst.Link("sysbus_bus_link") -link.connect((SysBusConn, "low_network_0", buslat), (bus, "high_network_%u" % bus_port, buslat)) - -bus_port = bus_port + 1 -ioCache = buildL1("ioCache", GEM5, "system.iocache.port") -ioCache.addParams({ - "debug" : 0, - "debug_level" : 6, - "cache_size" : "16 KB", - "associativity" : 4 - }) -link = sst.Link("ioCache_bus_link") -link.connect((ioCache, "low_network_0", buslat), (bus, "high_network_%u" % bus_port, buslat)) - -def buildCPU(m5, num): - l1iCache = buildL1("cpu%u.l1iCache" % num, m5, "system.cpu%u.icache.port" % num) - l1dCache = buildL1("cpu%u.l1dCache" % num, m5, "system.cpu%u.dcache.port" % num) - itlbCache = buildL1("cpu%u.itlbCache" % num, m5, "system.cpu%u.itb_walker_cache.port" % num) - dtlbCache = buildL1("cpu%u.dtlbCache" % num, m5, "system.cpu%u.dtb_walker_cache.port" % num) - l1dCache.addParams({ - "debug" : 0, - "debug_level" : 10, - "snoop_l1_invalidations" : 1 - }) - - global bus_port - link = sst.Link("cpu%u.l1iCache_bus_link" % num) ; bus_port = bus_port + 1 - link.connect((l1iCache, "low_network_0", buslat), (bus, "high_network_%u" % bus_port, buslat)) - link = sst.Link("cpu%u.l1dCache_bus_link" % num) ; bus_port = bus_port + 1 - link.connect((l1dCache, "low_network_0", buslat), (bus, "high_network_%u" % bus_port, buslat)) - link = sst.Link("cpu%u.itlbCache_bus_link" % num) ; bus_port = bus_port + 1 - link.connect((itlbCache, "low_network_0", buslat), (bus, "high_network_%u" % bus_port, buslat)) - link = sst.Link("cpu%u.dtlbCache_bus_link" % num) ; bus_port = bus_port + 1 - link.connect((dtlbCache, "low_network_0", buslat), (bus, "high_network_%u" % bus_port, buslat)) - -buildCPU(GEM5, 0) -buildCPU(GEM5, 1) -buildCPU(GEM5, 2) -buildCPU(GEM5, 3) - -l2cache = sst.Component("l2cache", "memHierarchy.Cache") -l2cache.addParams(baseCacheParams) -l2cache.addParams(l2CacheParams) -l2cache.addParams({ - "network_address" : "2" -}) - -link = sst.Link("l2cache_bus_link") -link.connect((l2cache, "high_network_0", buslat), (bus, "low_network_0", buslat)) - -memory = sst.Component("memory", "memHierarchy.MemController") -memory.addParams({ - "request_width" : 64, - "coherence_protocol" : "MSI", - "access_time" : "25 ns", - "backend.mem_size" : "256MiB", - "clock" : "2GHz", - "debug" : debug("DEBUG"), - "range_start" : 0, # 2 * (1024 ** 3), # it's behind a directory controller. - }) - -comp_chiprtr = sst.Component("chiprtr", "merlin.hr_router") -comp_chiprtr.addParams({ - "xbar_bw" : "16GB/s", - "link_bw" : "16GB/s", - "input_buf_size" : "1KB", - "num_ports" : "3", - "flit_size" : "72B", - "output_buf_size" : "1KB", - "id" : "0", - "topology" : "merlin.singlerouter" -}) -comp_dirctrl = sst.Component("dirctrl", "memHierarchy.DirectoryController") -comp_dirctrl.addParams({ - "coherence_protocol" : "MSI", - "network_address" : "1", - "entry_cache_size" : "16384", - "network_bw" : "1GB/s", - "addr_range_start" : 2 * (1024 ** 3), - "addr_range_end" : 2 * (1024 ** 3) + 256 * (1024 ** 2) -}) - -sst.Link("link_cache_net_0").connect((l2cache, "directory", "10ns"), (comp_chiprtr, "port2", "2ns")) -sst.Link("link_dir_net_0").connect((comp_chiprtr, "port1", "2ns"), (comp_dirctrl, "network", "2ns")) -sst.Link("l2cache_io_link").connect((comp_chiprtr, "port0", "2ns"), (GEM5, "network", buslat)) -sst.Link("link_dir_mem_link").connect((comp_dirctrl, "memory", "10ns"), (memory, "direct_link", "10ns")) diff --git a/ext/sst/translator.hh b/ext/sst/translator.hh new file mode 100644 index 0000000000..a2faebb4fe --- /dev/null +++ b/ext/sst/translator.hh @@ -0,0 +1,121 @@ +// Copyright (c) 2021 The Regents of the University of California +// All rights reserved. +// +// 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. + +#ifndef __TRANSLATOR_H__ +#define __TRANSLATOR_H__ + +#include +#include +#include +#include +#include +#include + +typedef std::unordered_map TPacketMap; + +namespace Translator +{ + +inline SST::Interfaces::SimpleMem::Request* +gem5RequestToSSTRequest(gem5::PacketPtr pkt, + TPacketMap& sst_request_id_to_packet_map) +{ + SST::Interfaces::SimpleMem::Request::Command cmd; + switch ((gem5::MemCmd::Command)pkt->cmd.toInt()) { + case gem5::MemCmd::HardPFReq: + case gem5::MemCmd::SoftPFReq: + case gem5::MemCmd::LoadLockedReq: + case gem5::MemCmd::ReadExReq: + case gem5::MemCmd::ReadReq: + case gem5::MemCmd::SwapReq: + cmd = SST::Interfaces::SimpleMem::Request::Command::Read; + break; + case gem5::MemCmd::StoreCondReq: + case gem5::MemCmd::WriteReq: + cmd = SST::Interfaces::SimpleMem::Request::Command::Write; + break; + default: + assert(false && "Unable to convert gem5 packet"); + } + + SST::Interfaces::SimpleMem::Addr addr = pkt->getAddr(); + + uint8_t* data_ptr = pkt->getPtr(); + auto data_size = pkt->getSize(); + std::vector data = std::vector( + data_ptr, data_ptr + data_size + ); + + SST::Interfaces::SimpleMem::Request* request = \ + new SST::Interfaces::SimpleMem::Request( + cmd, addr, data_size, data + ); + + if ((gem5::MemCmd::Command)pkt->cmd.toInt() == gem5::MemCmd::LoadLockedReq + || (gem5::MemCmd::Command)pkt->cmd.toInt() == gem5::MemCmd::SwapReq + || pkt->req->isLockedRMW()) { + request->setMemFlags( + SST::Interfaces::SimpleMem::Request::Flags::F_LOCKED); + } else if ((gem5::MemCmd::Command)pkt->cmd.toInt() == \ + gem5::MemCmd::StoreCondReq) { + request->setMemFlags( + SST::Interfaces::SimpleMem::Request::Flags::F_LLSC); + } + + if (pkt->req->isUncacheable()) { + request->setFlags( + SST::Interfaces::SimpleMem::Request::Flags::F_NONCACHEABLE); + } + + if (pkt->needsResponse()) + sst_request_id_to_packet_map[request->id] = pkt; + + return request; +} + +inline void +inplaceSSTRequestToGem5PacketPtr(gem5::PacketPtr pkt, + SST::Interfaces::SimpleMem::Request* request) +{ + pkt->makeResponse(); + + // Resolve the success of Store Conditionals + if (pkt->isLLSC() && pkt->isWrite()) { + // SC interprets ExtraData == 1 as the store was successful + pkt->req->setExtraData(1); + } + + pkt->setData(request->data.data()); + + // Clear out bus delay notifications + pkt->headerDelay = pkt->payloadDelay = 0; + +} + +}; // namespace Translator + +#endif // __TRANSLATOR_H__ diff --git a/ext/sst/util.hh b/ext/sst/util.hh new file mode 100644 index 0000000000..f5b2c5a8fe --- /dev/null +++ b/ext/sst/util.hh @@ -0,0 +1,57 @@ +// Copyright (c) 2021 The Regents of the University of California +// All rights reserved. +// +// 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. + +#include +#include +#include + +std::vector +tokenizeString(std::string s_, const std::vector& delimiters) +{ + std::vector tokens; + + if (delimiters.size() < 1) { + tokens.push_back(s_); + return tokens; + } + + std::string s = s_ + delimiters[0]; + + uint64_t pos = -1ULL; // the current position of the delimiter + uint64_t n = s.size(); // the length of the string s + + while (pos != n - 1) { + uint64_t prev_pos = pos; + do { + pos++; + } while (std::find(delimiters.begin(), delimiters.end(), s[pos]) == \ + delimiters.end()); + if (pos > prev_pos + 1) + tokens.push_back(s.substr(prev_pos+1, pos - prev_pos - 1)); + } + + return tokens; +} diff --git a/src/sst/OutgoingRequestBridge.py b/src/sst/OutgoingRequestBridge.py new file mode 100644 index 0000000000..e688d5e074 --- /dev/null +++ b/src/sst/OutgoingRequestBridge.py @@ -0,0 +1,39 @@ +# Copyright (c) 2021 The Regents of the University of California +# All rights reserved. +# +# 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 + +class OutgoingRequestBridge(SimObject): + type = 'OutgoingRequestBridge' + cxx_header = "sst/outgoing_request_bridge.hh" + cxx_class = 'gem5::OutgoingRequestBridge' + + port = ResponsePort("Response Port") + physical_address_ranges = VectorParam.AddrRange( + [AddrRange(0x80000000, MaxAddr)], + "Physical address ranges." + ) diff --git a/src/sst/SConscript b/src/sst/SConscript new file mode 100644 index 0000000000..a6dec52f8b --- /dev/null +++ b/src/sst/SConscript @@ -0,0 +1,32 @@ +# Copyright (c) 2021 The Regents of the University of California +# All rights reserved. +# +# 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('OutgoingRequestBridge.py') + +Source('outgoing_request_bridge.cc') +Source('sst_responder_interface.cc') \ No newline at end of file diff --git a/src/sst/outgoing_request_bridge.cc b/src/sst/outgoing_request_bridge.cc new file mode 100644 index 0000000000..5f342665fe --- /dev/null +++ b/src/sst/outgoing_request_bridge.cc @@ -0,0 +1,154 @@ +// Copyright (c) 2021 The Regents of the University of California +// All rights reserved. +// +// 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. + +#include "sst/outgoing_request_bridge.hh" + +#include +#include +#include + +#include "base/trace.hh" + +namespace gem5 +{ + +OutgoingRequestBridge::OutgoingRequestBridge( + const OutgoingRequestBridgeParams ¶ms) : + SimObject(params), + outgoingPort(std::string(name()), this), + sstResponder(nullptr), + physicalAddressRanges(params.physical_address_ranges.begin(), + params.physical_address_ranges.end()) +{ +} + +OutgoingRequestBridge::~OutgoingRequestBridge() +{ +} + +OutgoingRequestBridge:: +OutgoingRequestPort::OutgoingRequestPort(const std::string &name_, + OutgoingRequestBridge* owner_) : + ResponsePort(name_, owner_) +{ + owner = owner_; +} + +OutgoingRequestBridge:: +OutgoingRequestPort::~OutgoingRequestPort() +{ +} + +void +OutgoingRequestBridge::init() +{ + if (outgoingPort.isConnected()) + outgoingPort.sendRangeChange(); +} + +Port & +OutgoingRequestBridge::getPort(const std::string &if_name, PortID idx) +{ + return outgoingPort; +} + +AddrRangeList +OutgoingRequestBridge::getAddrRanges() const +{ + return outgoingPort.getAddrRanges(); +} + +std::vector>> +OutgoingRequestBridge::getInitData() const +{ + return initData; +} + +void +OutgoingRequestBridge::setResponder(SSTResponderInterface* responder) +{ + sstResponder = responder; +} + +bool +OutgoingRequestBridge::sendTimingResp(gem5::PacketPtr pkt) +{ + return outgoingPort.sendTimingResp(pkt); +} + +void +OutgoingRequestBridge::sendTimingSnoopReq(gem5::PacketPtr pkt) +{ + outgoingPort.sendTimingSnoopReq(pkt); +} + +void +OutgoingRequestBridge::handleRecvFunctional(PacketPtr pkt) +{ + uint8_t* ptr = pkt->getPtr(); + uint64_t size = pkt->getSize(); + std::vector data(ptr, ptr+size); + initData.push_back(std::make_pair(pkt->getAddr(), data)); +} + +Tick +OutgoingRequestBridge:: +OutgoingRequestPort::recvAtomic(PacketPtr pkt) +{ + assert(false && "OutgoingRequestPort::recvAtomic not implemented"); + return Tick(); +} + +void +OutgoingRequestBridge:: +OutgoingRequestPort::recvFunctional(PacketPtr pkt) +{ + owner->handleRecvFunctional(pkt); +} + +bool +OutgoingRequestBridge:: +OutgoingRequestPort::recvTimingReq(PacketPtr pkt) +{ + owner->sstResponder->handleRecvTimingReq(pkt); + return true; +} + +void +OutgoingRequestBridge:: +OutgoingRequestPort::recvRespRetry() +{ + owner->sstResponder->handleRecvRespRetry(); +} + +AddrRangeList +OutgoingRequestBridge:: +OutgoingRequestPort::getAddrRanges() const +{ + return owner->physicalAddressRanges; +} + +}; // namespace gem5 diff --git a/src/sst/outgoing_request_bridge.hh b/src/sst/outgoing_request_bridge.hh new file mode 100644 index 0000000000..af049af45a --- /dev/null +++ b/src/sst/outgoing_request_bridge.hh @@ -0,0 +1,122 @@ +// Copyright (c) 2021 The Regents of the University of California +// All rights reserved. +// +// 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. + +#ifndef __SST_OUTGOING_REQUEST_BRIDGE_HH__ +#define __SST_OUTGOING_REQUEST_BRIDGE_HH__ + +#include +#include + +#include "mem/port.hh" +#include "params/OutgoingRequestBridge.hh" +#include "sim/sim_object.hh" +#include "sst/sst_responder_interface.hh" + +/** + * - OutgoingRequestBridge acts as a SimObject owning pointers to both a gem5 + * OutgoingRequestPort and an SST port (via SSTResponderInterface). This bridge + * will forward gem5 packets from the gem5 port to the SST interface. Responses + * from SST will be handle by OutgoingRequestPort itself. Note: the bridge + * should be decoupled from the SST libraries so that it'll be + * SST-version-independent. Thus, there's no translation between a gem5 packet + * and SST Response here. + * + * - OutgoingRequestPort is a specialized ResponsePort working with + * OutgoingRequestBridge. + */ + +namespace gem5 +{ + +class OutgoingRequestBridge: public SimObject +{ + public: + class OutgoingRequestPort: public ResponsePort + { + private: + OutgoingRequestBridge* owner; + public: + OutgoingRequestPort(const std::string &name_, + OutgoingRequestBridge* owner_); + ~OutgoingRequestPort(); + Tick recvAtomic(PacketPtr pkt); + void recvFunctional(PacketPtr pkt); + bool recvTimingReq(PacketPtr pkt); + void recvRespRetry(); + AddrRangeList getAddrRanges() const; + }; + + public: + // a gem5 ResponsePort + OutgoingRequestPort outgoingPort; + // pointer to the corresponding SST responder + SSTResponderInterface* sstResponder; + // this vector holds the initialization data sent by gem5 + std::vector>> initData; + + AddrRangeList physicalAddressRanges; + + public: + OutgoingRequestBridge(const OutgoingRequestBridgeParams ¶ms); + ~OutgoingRequestBridge(); + + // Required to let the OutgoingRequestPort to send range change request. + void init(); + + // Returns the range of addresses that the ports will handle. + // Currently, it will return the range of [0x80000000, inf), which is + // specific to RISCV (SiFive's HiFive boards). + AddrRangeList getAddrRanges() const; + + // Required to return a port during gem5 instantiate phase. + Port & getPort(const std::string &if_name, PortID idx); + + // Returns the buffered data for initialization. This is necessary as + // when gem5 sends functional requests to memory for initialization, + // the connection in SST Memory Hierarchy has not been constructed yet. + std::vector>> getInitData() const; + + // gem5 Component (from SST) will call this function to let set the + // bridge's corresponding SSTResponderSubComponent (which implemented + // SSTResponderInterface). I.e., this will connect this bridge to the + // corresponding port in SST. + void setResponder(SSTResponderInterface* responder); + + // This function is called when SST wants to sent a timing response to gem5 + bool sendTimingResp(PacketPtr pkt); + + // This function is called when SST sends response having an invalidate . + void sendTimingSnoopReq(PacketPtr pkt); + + // This function is called when gem5 wants to send a non-timing request + // to SST. Should only be called during the SST construction phase, i.e. + // not at the simulation time. + void handleRecvFunctional(PacketPtr pkt); +}; + +}; // namespace gem5 + +#endif //__SST_OUTGOING_REQUEST_BRIDGE_HH__ diff --git a/src/sst/sst_responder_interface.cc b/src/sst/sst_responder_interface.cc new file mode 100644 index 0000000000..faee1082bf --- /dev/null +++ b/src/sst/sst_responder_interface.cc @@ -0,0 +1,36 @@ +// Copyright (c) 2021 The Regents of the University of California +// All rights reserved. +// +// 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. + +#include "sst/sst_responder_interface.hh" + +namespace gem5 +{ + +SSTResponderInterface::SSTResponderInterface() +{ +} + +}; // namespace gem5 \ No newline at end of file diff --git a/src/sst/sst_responder_interface.hh b/src/sst/sst_responder_interface.hh new file mode 100644 index 0000000000..9010907b84 --- /dev/null +++ b/src/sst/sst_responder_interface.hh @@ -0,0 +1,69 @@ +// Copyright (c) 2021 The Regents of the University of California +// All rights reserved. +// +// 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. + + +#ifndef __SST_RESPONDER_INTERFACE_HH__ +#define __SST_RESPONDER_INTERFACE_HH__ + +#include + +#include "mem/port.hh" + +/** + * SSTResponderInterface provides an interface specified gem5's expectations + * on the functionality of an SST Responder. This interfaces expects + * SST Responder to be able to handle gem5 packet on recvTimingReq(), + * recvRespRetry(), and recvFunctional(). + */ + +namespace gem5 +{ + +class SSTResponderInterface +{ + public: + + SSTResponderInterface(); + virtual ~SSTResponderInterface() {}; + + // This function is called when OutgoingRequestBridge wants to forward + // a gem5 request to SST, i.e. when OutgoingRequestPort::recvTimingReq() + // is called. + virtual bool handleRecvTimingReq(PacketPtr pkt) = 0; + + // This function is called when OutogingRequestPort::recvRespRetry() is + // called. + virtual void handleRecvRespRetry() = 0; + + // This function is called when OutgoingRequestBridge wants to send a + // non-timing request. This function should only be called during the + // SST construction phrase, i.e. not at simulation time. + virtual void handleRecvFunctional(PacketPtr pkt) = 0; +}; + +} // namespace gem5 + +#endif // __SST_RESPONDER_INTERFACE_HH__ \ No newline at end of file