110779SCurtis.Dunham@arm.com// Copyright (c) 2015 ARM Limited
210779SCurtis.Dunham@arm.com// All rights reserved.
310779SCurtis.Dunham@arm.com//
410779SCurtis.Dunham@arm.com// The license below extends only to copyright in the software and shall
510779SCurtis.Dunham@arm.com// not be construed as granting a license to any other intellectual
610779SCurtis.Dunham@arm.com// property including but not limited to intellectual property relating
710779SCurtis.Dunham@arm.com// to a hardware implementation of the functionality of the software
810779SCurtis.Dunham@arm.com// licensed hereunder.  You may use the software subject to the license
910779SCurtis.Dunham@arm.com// terms below provided that you ensure that this notice is replicated
1010779SCurtis.Dunham@arm.com// unmodified and in its entirety in all distributions of the software,
1110779SCurtis.Dunham@arm.com// modified or unmodified, in source code or in binary form.
1210779SCurtis.Dunham@arm.com//
1310779SCurtis.Dunham@arm.com// Redistribution and use in source and binary forms, with or without
1410779SCurtis.Dunham@arm.com// modification, are permitted provided that the following conditions are
1510779SCurtis.Dunham@arm.com// met: redistributions of source code must retain the above copyright
1610779SCurtis.Dunham@arm.com// notice, this list of conditions and the following disclaimer;
1710779SCurtis.Dunham@arm.com// redistributions in binary form must reproduce the above copyright
1810779SCurtis.Dunham@arm.com// notice, this list of conditions and the following disclaimer in the
1910779SCurtis.Dunham@arm.com// documentation and/or other materials provided with the distribution;
2010779SCurtis.Dunham@arm.com// neither the name of the copyright holders nor the names of its
2110779SCurtis.Dunham@arm.com// contributors may be used to endorse or promote products derived from
2210779SCurtis.Dunham@arm.com// this software without specific prior written permission.
2310779SCurtis.Dunham@arm.com//
2410779SCurtis.Dunham@arm.com// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2510779SCurtis.Dunham@arm.com// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2610779SCurtis.Dunham@arm.com// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2710779SCurtis.Dunham@arm.com// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2810779SCurtis.Dunham@arm.com// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2910779SCurtis.Dunham@arm.com// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3010779SCurtis.Dunham@arm.com// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3110779SCurtis.Dunham@arm.com// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3210779SCurtis.Dunham@arm.com// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3310779SCurtis.Dunham@arm.com// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3410779SCurtis.Dunham@arm.com// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3510779SCurtis.Dunham@arm.com
3610779SCurtis.Dunham@arm.com// Copyright 2009-2014 Sandia Coporation.  Under the terms
3710779SCurtis.Dunham@arm.com// of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S.
3810779SCurtis.Dunham@arm.com// Government retains certain rights in this software.
3910779SCurtis.Dunham@arm.com//
4010779SCurtis.Dunham@arm.com// Copyright (c) 2009-2014, Sandia Corporation
4110779SCurtis.Dunham@arm.com// All rights reserved.
4210779SCurtis.Dunham@arm.com//
4310779SCurtis.Dunham@arm.com// For license information, see the LICENSE file in the current directory.
4410779SCurtis.Dunham@arm.com
4510779SCurtis.Dunham@arm.com#include "gem5.hh"
4610779SCurtis.Dunham@arm.com
4710779SCurtis.Dunham@arm.com#ifdef fatal  // gem5 sets this
4810779SCurtis.Dunham@arm.com#undef fatal
4910779SCurtis.Dunham@arm.com#endif
5010779SCurtis.Dunham@arm.com
5110779SCurtis.Dunham@arm.comusing namespace SST;
5210779SCurtis.Dunham@arm.comusing namespace SST::gem5;
5310779SCurtis.Dunham@arm.comusing namespace SST::MemHierarchy;
5410779SCurtis.Dunham@arm.com
5510779SCurtis.Dunham@arm.comExtSlave::ExtSlave(gem5Component *g5c, Output &out,
5610779SCurtis.Dunham@arm.com        ::ExternalSlave& port, std::string &name) :
5710779SCurtis.Dunham@arm.com    Port(name, port),
5810779SCurtis.Dunham@arm.com    comp(g5c), out(out), simPhase(CONSTRUCTION), initPackets(NULL),
5910779SCurtis.Dunham@arm.com    link(comp->configureLink(name, new Event::Handler<ExtSlave>(this,
6010779SCurtis.Dunham@arm.com                                              &ExtSlave::handleEvent)))
6110779SCurtis.Dunham@arm.com{
6210779SCurtis.Dunham@arm.com    if (!link) {
6310779SCurtis.Dunham@arm.com        out.fatal(CALL_INFO, 1, "Failed to configure link %s\n", name.c_str());
6410779SCurtis.Dunham@arm.com    }
6510779SCurtis.Dunham@arm.com}
6610779SCurtis.Dunham@arm.com
6710779SCurtis.Dunham@arm.comvoid ExtSlave::init(unsigned phase)
6810779SCurtis.Dunham@arm.com{
6910779SCurtis.Dunham@arm.com    simPhase = INIT;
7010779SCurtis.Dunham@arm.com    if (initPackets) {
7110779SCurtis.Dunham@arm.com        while (!initPackets->empty()) {
7210779SCurtis.Dunham@arm.com            link->sendInitData(initPackets->front());
7310779SCurtis.Dunham@arm.com            initPackets->pop_front();
7410779SCurtis.Dunham@arm.com        }
7510779SCurtis.Dunham@arm.com        delete initPackets;
7610779SCurtis.Dunham@arm.com        initPackets = NULL;
7710779SCurtis.Dunham@arm.com    }
7810779SCurtis.Dunham@arm.com}
7910779SCurtis.Dunham@arm.com
8010779SCurtis.Dunham@arm.comvoid
8110779SCurtis.Dunham@arm.comExtSlave::recvFunctional(PacketPtr pkt)
8210779SCurtis.Dunham@arm.com{
8310779SCurtis.Dunham@arm.com    if (simPhase == CONSTRUCTION) {
8410779SCurtis.Dunham@arm.com        if (initPackets == NULL) {
8510779SCurtis.Dunham@arm.com            initPackets = new std::list<MemEvent*>;
8610779SCurtis.Dunham@arm.com        }
8710779SCurtis.Dunham@arm.com        ::MemCmd::Command pktCmd = (::MemCmd::Command)pkt->cmd.toInt();
8811254SCurtis.Dunham@arm.com        assert(pktCmd == ::MemCmd::WriteReq);
8910779SCurtis.Dunham@arm.com        Addr a = pkt->getAddr();
9010779SCurtis.Dunham@arm.com        MemEvent* ev = new MemEvent(comp, a, a, GetX);
9110779SCurtis.Dunham@arm.com        ev->setPayload(pkt->getSize(), pkt->getPtr<uint8_t>());
9210779SCurtis.Dunham@arm.com        initPackets->push_back(ev);
9310779SCurtis.Dunham@arm.com    } else {
9410779SCurtis.Dunham@arm.com        panic("Functional accesses not allowed after construction phase");
9510779SCurtis.Dunham@arm.com    }
9610779SCurtis.Dunham@arm.com}
9710779SCurtis.Dunham@arm.com
9810779SCurtis.Dunham@arm.combool
9910779SCurtis.Dunham@arm.comExtSlave::recvTimingReq(PacketPtr pkt)
10010779SCurtis.Dunham@arm.com{
10110779SCurtis.Dunham@arm.com    Command cmd;
10210779SCurtis.Dunham@arm.com    switch ((::MemCmd::Command)pkt->cmd.toInt()) {
10310779SCurtis.Dunham@arm.com    case ::MemCmd::HardPFReq:
10410779SCurtis.Dunham@arm.com    case ::MemCmd::SoftPFReq:
10510779SCurtis.Dunham@arm.com    case ::MemCmd::LoadLockedReq:
10610779SCurtis.Dunham@arm.com    case ::MemCmd::ReadExReq:
10710779SCurtis.Dunham@arm.com    case ::MemCmd::ReadReq:       cmd = GetS;   break;
10810779SCurtis.Dunham@arm.com    case ::MemCmd::StoreCondReq:
10910779SCurtis.Dunham@arm.com    case ::MemCmd::WriteReq:      cmd = GetX;   break;
11010779SCurtis.Dunham@arm.com    default:
11110779SCurtis.Dunham@arm.com        out.fatal(CALL_INFO, 1, "Don't know how to convert gem5 packet "
11210779SCurtis.Dunham@arm.com                  "command %s to SST\n", pkt->cmd.toString().c_str());
11310779SCurtis.Dunham@arm.com    }
11410779SCurtis.Dunham@arm.com
11510779SCurtis.Dunham@arm.com    auto ev = new MemEvent(comp, pkt->getAddr(), pkt->getAddr(), cmd);
11610779SCurtis.Dunham@arm.com    ev->setPayload(pkt->getSize(), pkt->getPtr<uint8_t>());
11710779SCurtis.Dunham@arm.com    if ((::MemCmd::Command)pkt->cmd.toInt() == ::MemCmd::LoadLockedReq)
11810779SCurtis.Dunham@arm.com        ev->setLoadLink();
11910779SCurtis.Dunham@arm.com    else if ((::MemCmd::Command)pkt->cmd.toInt() == ::MemCmd::StoreCondReq)
12010779SCurtis.Dunham@arm.com        ev->setStoreConditional();
12110779SCurtis.Dunham@arm.com
12211254SCurtis.Dunham@arm.com    if (pkt->req->isLockedRMW())   ev->setFlag(MemEvent::F_LOCKED);
12310779SCurtis.Dunham@arm.com    if (pkt->req->isUncacheable()) ev->setFlag(MemEvent::F_NONCACHEABLE);
12410779SCurtis.Dunham@arm.com    if (pkt->req->hasContextId())  ev->setGroupId(pkt->req->contextId());
12510779SCurtis.Dunham@arm.com// Prefetches not working with SST; it maybe be dropping them, treating them
12610779SCurtis.Dunham@arm.com// as not deserving of responses, or something else -- not sure yet.
12710779SCurtis.Dunham@arm.com//  ev->setPrefetchFlag(pkt->req->isPrefetch());
12810779SCurtis.Dunham@arm.com
12910779SCurtis.Dunham@arm.com    if (simPhase == INIT) {
13010779SCurtis.Dunham@arm.com        link->sendInitData(ev);
13110779SCurtis.Dunham@arm.com        delete pkt;
13210779SCurtis.Dunham@arm.com    } else {
13310779SCurtis.Dunham@arm.com        if (pkt->needsResponse()) {
13410779SCurtis.Dunham@arm.com            PacketMap[ev->getID()] = pkt;
13510779SCurtis.Dunham@arm.com        }
13610779SCurtis.Dunham@arm.com        link->send(ev);
13710779SCurtis.Dunham@arm.com    }
13810779SCurtis.Dunham@arm.com    return true;
13910779SCurtis.Dunham@arm.com}
14010779SCurtis.Dunham@arm.com
14110779SCurtis.Dunham@arm.com
14210779SCurtis.Dunham@arm.comvoid
14310779SCurtis.Dunham@arm.comExtSlave::handleEvent(Event* ev)
14410779SCurtis.Dunham@arm.com{
14510779SCurtis.Dunham@arm.com    MemEvent* event = dynamic_cast<MemEvent*>(ev);
14610779SCurtis.Dunham@arm.com    if (!event) {
14710779SCurtis.Dunham@arm.com        out.fatal(CALL_INFO, 1, "ExtSlave handleEvent received non-MemEvent\n");
14810779SCurtis.Dunham@arm.com        delete ev;
14910779SCurtis.Dunham@arm.com        return;
15010779SCurtis.Dunham@arm.com    }
15110779SCurtis.Dunham@arm.com    Event::id_type id = event->getID();
15210779SCurtis.Dunham@arm.com
15310779SCurtis.Dunham@arm.com    PacketMap_t::iterator mi = PacketMap.find(id);
15410779SCurtis.Dunham@arm.com    if (mi != PacketMap.end()) { // replying to prior request
15510779SCurtis.Dunham@arm.com        PacketPtr pkt = mi->second;
15610779SCurtis.Dunham@arm.com        PacketMap.erase(mi);
15710779SCurtis.Dunham@arm.com
15810779SCurtis.Dunham@arm.com        pkt->makeResponse();  // Convert to a response packet
15910779SCurtis.Dunham@arm.com        pkt->setData(event->getPayload().data());
16010779SCurtis.Dunham@arm.com
16110779SCurtis.Dunham@arm.com        // Resolve the success of Store Conditionals
16210779SCurtis.Dunham@arm.com        if (pkt->isLLSC() && pkt->isWrite()) {
16310779SCurtis.Dunham@arm.com            pkt->req->setExtraData(event->isAtomic());
16410779SCurtis.Dunham@arm.com        }
16510779SCurtis.Dunham@arm.com
16610779SCurtis.Dunham@arm.com        // Clear out bus delay notifications
16710779SCurtis.Dunham@arm.com        pkt->headerDelay = pkt->payloadDelay = 0;
16810779SCurtis.Dunham@arm.com
16910779SCurtis.Dunham@arm.com        if (blocked() || !sendTimingResp(pkt)) {
17010779SCurtis.Dunham@arm.com            respQ.push_back(pkt);
17110779SCurtis.Dunham@arm.com        }
17210779SCurtis.Dunham@arm.com    } else { // we can handle unexpected invalidates, but nothing else.
17310779SCurtis.Dunham@arm.com        Command cmd = event->getCmd();
17410779SCurtis.Dunham@arm.com        assert(cmd == Inv);
17510779SCurtis.Dunham@arm.com
17610779SCurtis.Dunham@arm.com        // make Req/Pkt for Snoop/no response needed
17710779SCurtis.Dunham@arm.com        // presently no consideration for masterId, packet type, flags...
17812749Sgiacomo.travaglini@arm.com        RequestPtr req = std::make_shared<Request>(
17912749Sgiacomo.travaglini@arm.com            event->getAddr(), event->getSize(), 0, 0);
18012749Sgiacomo.travaglini@arm.com
18111158SCurtis.Dunham@arm.com        auto pkt = new Packet(req, ::MemCmd::InvalidateReq);
18210779SCurtis.Dunham@arm.com
18310779SCurtis.Dunham@arm.com        // Clear out bus delay notifications
18410779SCurtis.Dunham@arm.com        pkt->headerDelay = pkt->payloadDelay = 0;
18510779SCurtis.Dunham@arm.com
18610779SCurtis.Dunham@arm.com        sendTimingSnoopReq(pkt);
18710779SCurtis.Dunham@arm.com    }
18810779SCurtis.Dunham@arm.com    delete event;
18910779SCurtis.Dunham@arm.com}
19010779SCurtis.Dunham@arm.com
19110779SCurtis.Dunham@arm.comvoid
19210779SCurtis.Dunham@arm.comExtSlave::recvRespRetry()
19310779SCurtis.Dunham@arm.com{
19410779SCurtis.Dunham@arm.com    while (blocked() && sendTimingResp(respQ.front())) {
19510779SCurtis.Dunham@arm.com        respQ.pop_front();
19610779SCurtis.Dunham@arm.com    }
19710779SCurtis.Dunham@arm.com}
198