ext: Add SST connector
authorCurtis Dunham <Curtis.Dunham@arm.com>
Wed, 8 Apr 2015 20:56:06 +0000 (15:56 -0500)
committerCurtis Dunham <Curtis.Dunham@arm.com>
Wed, 8 Apr 2015 20:56:06 +0000 (15:56 -0500)
This patch adds a connector that allows gem5 to be used as a component
in SST (Structural Simulation Toolkit, sst-simulator.org). 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.

These connectors handle the administrative aspects of gem5
(initialization, simulation, shutdown) as well as translating SST's
MemEvents into gem5 Packets and vice-versa.

ext/sst/ExtMaster.cc [new file with mode: 0644]
ext/sst/ExtMaster.hh [new file with mode: 0644]
ext/sst/ExtSlave.cc [new file with mode: 0644]
ext/sst/ExtSlave.hh [new file with mode: 0644]
ext/sst/LICENSE [new file with mode: 0644]
ext/sst/Makefile [new file with mode: 0644]
ext/sst/README [new file with mode: 0644]
ext/sst/gem5.cc [new file with mode: 0644]
ext/sst/gem5.hh [new file with mode: 0644]
ext/sst/libgem5.cc [new file with mode: 0644]

diff --git a/ext/sst/ExtMaster.cc b/ext/sst/ExtMaster.cc
new file mode 100644 (file)
index 0000000..d8febbc
--- /dev/null
@@ -0,0 +1,240 @@
+// 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"
+
+#include <sst_config.h>
+
+#include <mem/packet.hh>
+
+#include <sst/core/component.h>
+#include <sst/core/params.h>
+#include <sst/core/link.h>
+#include <sst/elements/memHierarchy/memNIC.h>
+
+#ifdef fatal  // gem5 sets this
+#undef fatal
+#endif
+
+using namespace SST;
+using namespace SST::gem5;
+using namespace SST::MemHierarchy;
+
+ExtMaster::ExtMaster(gem5Component *g, Output &o, ::ExternalMaster& p,
+        std::string &n) :
+    Port(n, p), out(o), port(p), simPhase(CONSTRUCTION),
+    gem5(g), name(n)
+{
+    Params _p; // will be ignored
+    nic = dynamic_cast<MemNIC*>(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<ExtMaster>
+                                          (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<MemEvent*>(event);
+    if (!ev) {
+        out.fatal(CALL_INFO, 1, "Can't handle non-MemEvent Event's\n");
+    }
+
+    Command cmdI = ev->getCmd(); // command in - SST
+    MemCmd::Command cmdO;        // command out - gem5
+    bool data = false;
+
+    switch (cmdI) {
+        case GetS:      cmdO = MemCmd::ReadReq;                break;
+        case GetX:      cmdO = 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]);
+    }
+
+    Request::FlagsType flags = 0;
+    if (ev->queryFlag(MemEvent::F_LOCKED))
+        flags |= Request::LOCKED;
+    if (ev->queryFlag(MemEvent::F_NONCACHEABLE))
+        flags |= Request::UNCACHEABLE;
+    if (ev->isLoadLink()) {
+        assert(cmdI == GetS);
+        cmdO = MemCmd::LoadLockedReq;
+    } else if (ev->isStoreConditional()) {
+        assert(cmdI == GetX);
+        cmdO = MemCmd::StoreCondReq;
+    }
+
+    auto req = new Request(ev->getAddr(), ev->getSize(), flags, 0);
+    req->setThreadContext(ev->getGroupId(), 0);
+
+    auto pkt = new 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(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<SenderState*>(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<uint8_t>());
+    delete pkt->req;
+    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
new file mode 100644 (file)
index 0000000..2f68a40
--- /dev/null
@@ -0,0 +1,119 @@
+// 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 <list>
+#include <set>
+
+#include <sst/core/serialization.h>
+#include <sst/core/component.h>
+#include <sst/elements/memHierarchy/memEvent.h>
+
+#include <sim/sim_object.hh>
+#include <mem/packet.hh>
+#include <mem/request.hh>
+#include <mem/external_master.hh>
+
+namespace SST {
+
+using MemHierarchy::MemEvent;
+class Link;
+class Event;
+
+namespace MemHierarchy {
+class MemNIC;
+}
+
+namespace gem5 {
+
+class gem5Component;
+
+class ExtMaster : public ExternalMaster::Port {
+
+    enum Phase { CONSTRUCTION, INIT, RUN };
+
+    Output& out;
+    const ExternalMaster& port;
+    Phase simPhase;
+
+    gem5Component *const gem5;
+    const std::string name;
+    std::list<PacketPtr> sendQ;
+    bool blocked() { return !sendQ.empty(); }
+
+    MemHierarchy::MemNIC * nic;
+
+    struct SenderState : public Packet::SenderState
+    {
+        MemEvent *event;
+        SenderState(MemEvent* e) : event(e) {}
+    };
+
+    std::set<AddrRange> ranges;
+
+public:
+    bool recvTimingResp(PacketPtr);
+    void recvReqRetry();
+
+    ExtMaster(gem5Component*, Output&, 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
new file mode 100644 (file)
index 0000000..57df21d
--- /dev/null
@@ -0,0 +1,203 @@
+// 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"
+
+#include <sst_config.h>
+#include <sst/core/serialization.h>
+
+#include <sst/core/params.h>
+#include <sst/core/output.h>
+#include <sst/core/link.h>
+
+#ifdef fatal  // gem5 sets this
+#undef fatal
+#endif
+
+using namespace SST;
+using namespace SST::gem5;
+using namespace SST::MemHierarchy;
+
+ExtSlave::ExtSlave(gem5Component *g5c, Output &out,
+        ::ExternalSlave& port, std::string &name) :
+    Port(name, port),
+    comp(g5c), out(out), simPhase(CONSTRUCTION), initPackets(NULL),
+    link(comp->configureLink(name, new Event::Handler<ExtSlave>(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(PacketPtr pkt)
+{
+    if (simPhase == CONSTRUCTION) {
+        if (initPackets == NULL) {
+            initPackets = new std::list<MemEvent*>;
+        }
+        ::MemCmd::Command pktCmd = (::MemCmd::Command)pkt->cmd.toInt();
+        assert(pktCmd == ::MemCmd::WriteReq || pktCmd == ::MemCmd::Writeback);
+        Addr a = pkt->getAddr();
+        MemEvent* ev = new MemEvent(comp, a, a, GetX);
+        ev->setPayload(pkt->getSize(), pkt->getPtr<uint8_t>());
+        initPackets->push_back(ev);
+    } else {
+        panic("Functional accesses not allowed after construction phase");
+    }
+}
+
+bool
+ExtSlave::recvTimingReq(PacketPtr pkt)
+{
+    Command cmd;
+    switch ((::MemCmd::Command)pkt->cmd.toInt()) {
+    case ::MemCmd::HardPFReq:
+    case ::MemCmd::SoftPFReq:
+    case ::MemCmd::LoadLockedReq:
+    case ::MemCmd::ReadExReq:
+    case ::MemCmd::ReadReq:       cmd = GetS;   break;
+    case ::MemCmd::StoreCondReq:
+    case ::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<uint8_t>());
+    if ((::MemCmd::Command)pkt->cmd.toInt() == ::MemCmd::LoadLockedReq)
+        ev->setLoadLink();
+    else if ((::MemCmd::Command)pkt->cmd.toInt() == ::MemCmd::StoreCondReq)
+        ev->setStoreConditional();
+
+    if (pkt->req->isLocked())      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->req;
+        delete pkt;
+    } else {
+        if (pkt->needsResponse()) {
+            PacketMap[ev->getID()] = pkt;
+        }
+        link->send(ev);
+    }
+    return true;
+}
+
+
+void
+ExtSlave::handleEvent(Event* ev)
+{
+    MemEvent* event = dynamic_cast<MemEvent*>(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
+        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...
+        RequestPtr req = new Request(event->getAddr(), event->getSize(), 0, 0);
+        auto pkt = new Packet(req, ::MemCmd::InvalidationReq);
+
+        // 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
new file mode 100644 (file)
index 0000000..de91a6f
--- /dev/null
@@ -0,0 +1,119 @@
+// 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 <sst/core/serialization.h>
+#include <sst/core/component.h>
+#include <sst/core/output.h>
+#include <sst/core/interfaces/simpleMem.h>
+
+#include <sim/sim_object.hh>
+#include <mem/packet.hh>
+#include <mem/request.hh>
+#include <mem/external_slave.hh>
+
+namespace SST {
+class Link;
+class Event;
+class MemEvent;
+namespace gem5 {
+
+class gem5Component;
+
+class ExtSlave : public ExternalSlave::Port {
+  public:
+    const std::string name;
+
+    bool
+    recvTimingSnoopResp(PacketPtr packet)
+    {
+        fatal("recvTimingSnoopResp unimplemented");
+        return false;
+    }
+
+    bool recvTimingReq(PacketPtr packet);
+
+    void recvFunctional(PacketPtr packet);
+
+    void recvRespRetry();
+
+    Tick
+    recvAtomic(PacketPtr packet)
+    {
+        fatal("recvAtomic unimplemented");
+    }
+
+    enum Phase { CONSTRUCTION, INIT, RUN };
+
+    gem5Component *comp;
+    Output &out;
+    Phase simPhase;
+
+    std::list<MemEvent*>* initPackets;
+    Link* link;
+    std::list<PacketPtr> respQ;
+    bool blocked() { return !respQ.empty(); }
+
+    typedef std::map<Event::id_type, ::Packet*> PacketMap_t;
+    PacketMap_t PacketMap; // SST Event id -> gem5 Packet*
+
+public:
+    ExtSlave(gem5Component*, Output&, ExternalSlave&, std::string&);
+    void init(unsigned phase);
+
+    void
+    setup()
+    {
+        simPhase = RUN;
+    }
+
+    void handleEvent(Event*);
+};
+
+}
+}
+
+#endif
diff --git a/ext/sst/LICENSE b/ext/sst/LICENSE
new file mode 100644 (file)
index 0000000..787cadc
--- /dev/null
@@ -0,0 +1,72 @@
+** This license only applies to the source files in this directory.
+
+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 Corporation. 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.
+
+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 Sandia Corporation 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.
diff --git a/ext/sst/Makefile b/ext/sst/Makefile
new file mode 100644 (file)
index 0000000..3eb0a8e
--- /dev/null
@@ -0,0 +1,20 @@
+# These two variables are designed to be modifiable.
+SST_VERSION=SST-trunk
+GEM5_LIB=gem5_opt
+
+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
+CPPFLAGS+=-MMD -MP
+SRC=$(wildcard *.cc)
+
+.PHONY: clean all
+
+all: libgem5.so
+
+libgem5.so: $(SRC:%.cc=%.o)
+       ${CXX} ${CPPFLAGS} ${LDFLAGS} $? -o $@ -l${GEM5_LIB}
+
+-include $(SRC:%.cc=%.d)
+
+clean:
+       ${RM} *.[do] libgem5.so
diff --git a/ext/sst/README b/ext/sst/README
new file mode 100644 (file)
index 0000000..c9870ab
--- /dev/null
@@ -0,0 +1,65 @@
+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 <path to ./ext/sst> <config script, e.g. ext/sst/*.py>
+
+===========
+
+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/gem5.cc b/ext/sst/gem5.cc
new file mode 100644 (file)
index 0000000..29cea83
--- /dev/null
@@ -0,0 +1,272 @@
+// 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 <sst_config.h>
+#include <Python.h>  // Before serialization to prevent spurious warnings
+#include <sst/core/serialization.h>
+
+#include "gem5.hh"
+
+// System headers
+#include <boost/tokenizer.hpp>
+#include <string>
+
+// gem5 Headers
+#include <sim/core.hh>
+#include <sim/init.hh>
+#include <sim/init_signals.hh>
+#include <sim/system.hh>
+#include <sim/sim_object.hh>
+#include <base/misc.hh>
+#include <base/debug.hh>
+
+#ifdef fatal  // gem5 sets this
+#undef fatal
+#endif
+
+// More SST Headers
+#include <sst/core/params.h>
+#include <sst/core/link.h>
+#include <sst/core/timeConverter.h>
+#include <sst/core/debug.h>
+
+using namespace SST;
+using namespace SST::gem5;
+
+gem5Component::gem5Component(ComponentId_t id, Params &params) :
+    SST::Component(id)
+{
+    dbg.init("@t:gem5:@p():@l " + getName() + ": ", 0, 0,
+            (Output::output_location_t)params.find_integer("comp_debug", 0));
+    info.init("gem5:" + getName() + ": ", 0, 0, Output::STDOUT);
+
+    TimeConverter *clock = registerClock(
+            params.find_string("frequency", "1GHz"),
+            new Clock::Handler<gem5Component>(this, &gem5Component::clockTick));
+
+    // 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;
+
+    std::string cmd = params.find_string("cmd", "");
+    if (cmd.empty()) {
+        _abort(gem5Component, "Component %s must have a 'cmd' parameter.\n",
+               getName().c_str());
+    }
+
+    std::vector<char*> args;
+    args.push_back(const_cast<char*>("sst.x")); // TODO: Compute this somehow?
+    splitCommandArgs(cmd, args);
+    args.push_back(const_cast<char*>("--initialize-only"));
+    dbg.output(CALL_INFO, "Command string:  [sst.x %s --initialize-only]\n",
+               cmd.c_str());
+    for (size_t i = 0; i < args.size(); ++i) {
+        dbg.output(CALL_INFO, "  Arg [%02zu] = %s\n", i, args[i]);
+    }
+
+    std::vector<char*> flags;
+    std::string gem5DbgFlags = params.find_string("gem5DebugFlags", "");
+    splitCommandArgs(gem5DbgFlags, flags);
+    for (auto flag : flags) {
+        dbg.output(CALL_INFO, "  Setting Debug Flag [%s]\n", flag);
+        setDebugFlag(flag);
+    }
+
+    ExternalMaster::registerHandler("sst", this); // these are idempotent
+    ExternalSlave ::registerHandler("sst", this);
+
+    // Initialize m5 special signal handling.
+    initSignals();
+
+    initPython(args.size(), &args[0]);
+
+    // tell the simulator not to end without us
+    registerAsPrimaryComponent();
+    primaryComponentDoNotEndSim();
+
+    clocks_processed = 0;
+}
+
+gem5Component::~gem5Component(void)
+{
+    Py_Finalize();
+}
+
+void
+gem5Component::init(unsigned phase)
+{
+    for (auto m : masters) {
+        m->init(phase);
+    }
+    for (auto s : slaves) {
+        s->init(phase);
+    }
+}
+
+void
+gem5Component::setup(void)
+{
+    // Switch connectors from initData to regular Sends
+    for (auto m : masters) {
+        m->setup();
+    }
+    for (auto s : slaves) {
+        s->setup();
+    }
+}
+
+void
+gem5Component::finish(void)
+{
+    for (auto m : masters) {
+        m->finish();
+    }
+    info.output("Complete. Clocks Processed: %"PRIu64"\n", clocks_processed);
+}
+
+bool
+gem5Component::clockTick(Cycle_t cycle)
+{
+    dbg.output(CALL_INFO, "Cycle %lu\n", cycle);
+
+    for (auto m : masters) {
+        m->clock();
+    }
+
+    GlobalSimLoopExitEvent *event = simulate(sim_cycles);
+    ++clocks_processed;
+    if (event != simulate_limit_event) {
+        info.output("exiting: curTick()=%lu cause=`%s` code=%d\n",
+                curTick(), event->getCause().c_str(), event->getCode());
+        primaryComponentOKToEndSim();
+        return true;
+    }
+
+    return false;
+}
+
+
+void
+gem5Component::splitCommandArgs(std::string &cmd,
+                                std::vector<char *> &args)
+{
+    std::string sep1("\\");
+    std::string sep2(" ");
+    std::string sep3("\"\'");
+
+    boost::escaped_list_separator<char> els(sep1, sep2, sep3);
+    boost::tokenizer<boost::escaped_list_separator<char>> tok(cmd, els);
+
+    for (auto beg : tok) {
+        args.push_back(strdup(beg.c_str()));
+    }
+}
+
+
+void
+gem5Component::initPython(int argc, char *argv[])
+{
+    const char * m5MainCommands[] = {
+        "import m5",
+        "m5.main()",
+        0 // sentinel is required
+    };
+
+    PyObject *mainModule,*mainDict;
+
+    Py_SetProgramName(argv[0]); // optional but recommended
+
+    Py_Initialize();
+
+    int ret = initM5Python();
+    if (ret != 0) {
+        _abort(gem5Component, "Python failed to initialize. Code: %d\n", ret);
+    }
+
+    PySys_SetArgv(argc, argv);
+
+    mainModule = PyImport_AddModule("__main__");
+    assert(mainModule);
+
+    mainDict = PyModule_GetDict(mainModule);
+    assert(mainDict);
+
+    PyObject *result;
+    const char **command = m5MainCommands;
+
+    // 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);
+
+        command++;
+    }
+}
+
+ExternalMaster::Port*
+gem5Component::getExternalPort(const std::string &name,
+    ExternalMaster &owner, const std::string &port_data)
+{
+    std::string s(name); // bridges non-& result and &-arg
+    auto master = new ExtMaster(this, info, owner, s);
+    masters.push_back(master);
+    return master;
+}
+
+ExternalSlave::Port*
+gem5Component::getExternalPort(const std::string &name,
+    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;
+}
diff --git a/ext/sst/gem5.hh b/ext/sst/gem5.hh
new file mode 100644 (file)
index 0000000..6b2f1a1
--- /dev/null
@@ -0,0 +1,99 @@
+// 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_GEM5_HH
+#define EXT_SST_GEM5_HH
+
+#include <string>
+#include <vector>
+
+#include <sst/core/serialization.h>
+#include <sst/core/component.h>
+#include <sst/core/output.h>
+
+#include <sim/simulate.hh>
+
+#include "ExtMaster.hh"
+#include "ExtSlave.hh"
+
+namespace SST {
+namespace gem5 {
+
+class gem5Component : public SST::Component,
+                      public ExternalSlave::Handler,
+                      public ExternalMaster::Handler {
+private:
+
+    Output dbg;
+    Output info;
+    uint64_t sim_cycles;
+    uint64_t clocks_processed;
+
+    std::vector<ExtMaster*> masters;
+    std::vector<ExtSlave*> slaves;
+
+    void splitCommandArgs(std::string &cmd, std::vector<char*> &args);
+    void initPython(int argc, char *argv[]);
+
+public:
+    gem5Component(ComponentId_t id, Params &params);
+    ~gem5Component();
+    virtual void init(unsigned);
+    virtual void setup();
+    virtual void finish();
+    bool clockTick(Cycle_t);
+
+    virtual ExternalMaster::Port *getExternalPort(
+        const std::string &name, ExternalMaster &owner,
+        const std::string &port_data);
+
+    virtual ExternalSlave::Port *getExternalPort(
+        const std::string &name, ExternalSlave &owner,
+        const std::string &port_data);
+};
+
+}
+}
+
+#endif
diff --git a/ext/sst/libgem5.cc b/ext/sst/libgem5.cc
new file mode 100644 (file)
index 0000000..f490d6f
--- /dev/null
@@ -0,0 +1,84 @@
+// 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 <sst_config.h>
+
+#include <sst/core/serialization.h>
+#include <sst/core/element.h>
+#include <sst/core/component.h>
+
+#include "gem5.hh"
+
+static
+SST::Component* create_gem5(SST::ComponentId_t id, SST::Params &params)
+{
+    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,
+    };
+}