ExtSlave.cc revision 10779
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#include <sst_config.h>
4810779SCurtis.Dunham@arm.com#include <sst/core/serialization.h>
4910779SCurtis.Dunham@arm.com
5010779SCurtis.Dunham@arm.com#include <sst/core/params.h>
5110779SCurtis.Dunham@arm.com#include <sst/core/output.h>
5210779SCurtis.Dunham@arm.com#include <sst/core/link.h>
5310779SCurtis.Dunham@arm.com
5410779SCurtis.Dunham@arm.com#ifdef fatal  // gem5 sets this
5510779SCurtis.Dunham@arm.com#undef fatal
5610779SCurtis.Dunham@arm.com#endif
5710779SCurtis.Dunham@arm.com
5810779SCurtis.Dunham@arm.comusing namespace SST;
5910779SCurtis.Dunham@arm.comusing namespace SST::gem5;
6010779SCurtis.Dunham@arm.comusing namespace SST::MemHierarchy;
6110779SCurtis.Dunham@arm.com
6210779SCurtis.Dunham@arm.comExtSlave::ExtSlave(gem5Component *g5c, Output &out,
6310779SCurtis.Dunham@arm.com        ::ExternalSlave& port, std::string &name) :
6410779SCurtis.Dunham@arm.com    Port(name, port),
6510779SCurtis.Dunham@arm.com    comp(g5c), out(out), simPhase(CONSTRUCTION), initPackets(NULL),
6610779SCurtis.Dunham@arm.com    link(comp->configureLink(name, new Event::Handler<ExtSlave>(this,
6710779SCurtis.Dunham@arm.com                                              &ExtSlave::handleEvent)))
6810779SCurtis.Dunham@arm.com{
6910779SCurtis.Dunham@arm.com    if (!link) {
7010779SCurtis.Dunham@arm.com        out.fatal(CALL_INFO, 1, "Failed to configure link %s\n", name.c_str());
7110779SCurtis.Dunham@arm.com    }
7210779SCurtis.Dunham@arm.com}
7310779SCurtis.Dunham@arm.com
7410779SCurtis.Dunham@arm.comvoid ExtSlave::init(unsigned phase)
7510779SCurtis.Dunham@arm.com{
7610779SCurtis.Dunham@arm.com    simPhase = INIT;
7710779SCurtis.Dunham@arm.com    if (initPackets) {
7810779SCurtis.Dunham@arm.com        while (!initPackets->empty()) {
7910779SCurtis.Dunham@arm.com            link->sendInitData(initPackets->front());
8010779SCurtis.Dunham@arm.com            initPackets->pop_front();
8110779SCurtis.Dunham@arm.com        }
8210779SCurtis.Dunham@arm.com        delete initPackets;
8310779SCurtis.Dunham@arm.com        initPackets = NULL;
8410779SCurtis.Dunham@arm.com    }
8510779SCurtis.Dunham@arm.com}
8610779SCurtis.Dunham@arm.com
8710779SCurtis.Dunham@arm.comvoid
8810779SCurtis.Dunham@arm.comExtSlave::recvFunctional(PacketPtr pkt)
8910779SCurtis.Dunham@arm.com{
9010779SCurtis.Dunham@arm.com    if (simPhase == CONSTRUCTION) {
9110779SCurtis.Dunham@arm.com        if (initPackets == NULL) {
9210779SCurtis.Dunham@arm.com            initPackets = new std::list<MemEvent*>;
9310779SCurtis.Dunham@arm.com        }
9410779SCurtis.Dunham@arm.com        ::MemCmd::Command pktCmd = (::MemCmd::Command)pkt->cmd.toInt();
9510779SCurtis.Dunham@arm.com        assert(pktCmd == ::MemCmd::WriteReq || pktCmd == ::MemCmd::Writeback);
9610779SCurtis.Dunham@arm.com        Addr a = pkt->getAddr();
9710779SCurtis.Dunham@arm.com        MemEvent* ev = new MemEvent(comp, a, a, GetX);
9810779SCurtis.Dunham@arm.com        ev->setPayload(pkt->getSize(), pkt->getPtr<uint8_t>());
9910779SCurtis.Dunham@arm.com        initPackets->push_back(ev);
10010779SCurtis.Dunham@arm.com    } else {
10110779SCurtis.Dunham@arm.com        panic("Functional accesses not allowed after construction phase");
10210779SCurtis.Dunham@arm.com    }
10310779SCurtis.Dunham@arm.com}
10410779SCurtis.Dunham@arm.com
10510779SCurtis.Dunham@arm.combool
10610779SCurtis.Dunham@arm.comExtSlave::recvTimingReq(PacketPtr pkt)
10710779SCurtis.Dunham@arm.com{
10810779SCurtis.Dunham@arm.com    Command cmd;
10910779SCurtis.Dunham@arm.com    switch ((::MemCmd::Command)pkt->cmd.toInt()) {
11010779SCurtis.Dunham@arm.com    case ::MemCmd::HardPFReq:
11110779SCurtis.Dunham@arm.com    case ::MemCmd::SoftPFReq:
11210779SCurtis.Dunham@arm.com    case ::MemCmd::LoadLockedReq:
11310779SCurtis.Dunham@arm.com    case ::MemCmd::ReadExReq:
11410779SCurtis.Dunham@arm.com    case ::MemCmd::ReadReq:       cmd = GetS;   break;
11510779SCurtis.Dunham@arm.com    case ::MemCmd::StoreCondReq:
11610779SCurtis.Dunham@arm.com    case ::MemCmd::WriteReq:      cmd = GetX;   break;
11710779SCurtis.Dunham@arm.com    default:
11810779SCurtis.Dunham@arm.com        out.fatal(CALL_INFO, 1, "Don't know how to convert gem5 packet "
11910779SCurtis.Dunham@arm.com                  "command %s to SST\n", pkt->cmd.toString().c_str());
12010779SCurtis.Dunham@arm.com    }
12110779SCurtis.Dunham@arm.com
12210779SCurtis.Dunham@arm.com    auto ev = new MemEvent(comp, pkt->getAddr(), pkt->getAddr(), cmd);
12310779SCurtis.Dunham@arm.com    ev->setPayload(pkt->getSize(), pkt->getPtr<uint8_t>());
12410779SCurtis.Dunham@arm.com    if ((::MemCmd::Command)pkt->cmd.toInt() == ::MemCmd::LoadLockedReq)
12510779SCurtis.Dunham@arm.com        ev->setLoadLink();
12610779SCurtis.Dunham@arm.com    else if ((::MemCmd::Command)pkt->cmd.toInt() == ::MemCmd::StoreCondReq)
12710779SCurtis.Dunham@arm.com        ev->setStoreConditional();
12810779SCurtis.Dunham@arm.com
12910779SCurtis.Dunham@arm.com    if (pkt->req->isLocked())      ev->setFlag(MemEvent::F_LOCKED);
13010779SCurtis.Dunham@arm.com    if (pkt->req->isUncacheable()) ev->setFlag(MemEvent::F_NONCACHEABLE);
13110779SCurtis.Dunham@arm.com    if (pkt->req->hasContextId())  ev->setGroupId(pkt->req->contextId());
13210779SCurtis.Dunham@arm.com// Prefetches not working with SST; it maybe be dropping them, treating them
13310779SCurtis.Dunham@arm.com// as not deserving of responses, or something else -- not sure yet.
13410779SCurtis.Dunham@arm.com//  ev->setPrefetchFlag(pkt->req->isPrefetch());
13510779SCurtis.Dunham@arm.com
13610779SCurtis.Dunham@arm.com    if (simPhase == INIT) {
13710779SCurtis.Dunham@arm.com        link->sendInitData(ev);
13810779SCurtis.Dunham@arm.com        delete pkt->req;
13910779SCurtis.Dunham@arm.com        delete pkt;
14010779SCurtis.Dunham@arm.com    } else {
14110779SCurtis.Dunham@arm.com        if (pkt->needsResponse()) {
14210779SCurtis.Dunham@arm.com            PacketMap[ev->getID()] = pkt;
14310779SCurtis.Dunham@arm.com        }
14410779SCurtis.Dunham@arm.com        link->send(ev);
14510779SCurtis.Dunham@arm.com    }
14610779SCurtis.Dunham@arm.com    return true;
14710779SCurtis.Dunham@arm.com}
14810779SCurtis.Dunham@arm.com
14910779SCurtis.Dunham@arm.com
15010779SCurtis.Dunham@arm.comvoid
15110779SCurtis.Dunham@arm.comExtSlave::handleEvent(Event* ev)
15210779SCurtis.Dunham@arm.com{
15310779SCurtis.Dunham@arm.com    MemEvent* event = dynamic_cast<MemEvent*>(ev);
15410779SCurtis.Dunham@arm.com    if (!event) {
15510779SCurtis.Dunham@arm.com        out.fatal(CALL_INFO, 1, "ExtSlave handleEvent received non-MemEvent\n");
15610779SCurtis.Dunham@arm.com        delete ev;
15710779SCurtis.Dunham@arm.com        return;
15810779SCurtis.Dunham@arm.com    }
15910779SCurtis.Dunham@arm.com    Event::id_type id = event->getID();
16010779SCurtis.Dunham@arm.com
16110779SCurtis.Dunham@arm.com    PacketMap_t::iterator mi = PacketMap.find(id);
16210779SCurtis.Dunham@arm.com    if (mi != PacketMap.end()) { // replying to prior request
16310779SCurtis.Dunham@arm.com        PacketPtr pkt = mi->second;
16410779SCurtis.Dunham@arm.com        PacketMap.erase(mi);
16510779SCurtis.Dunham@arm.com
16610779SCurtis.Dunham@arm.com        pkt->makeResponse();  // Convert to a response packet
16710779SCurtis.Dunham@arm.com        pkt->setData(event->getPayload().data());
16810779SCurtis.Dunham@arm.com
16910779SCurtis.Dunham@arm.com        // Resolve the success of Store Conditionals
17010779SCurtis.Dunham@arm.com        if (pkt->isLLSC() && pkt->isWrite()) {
17110779SCurtis.Dunham@arm.com            pkt->req->setExtraData(event->isAtomic());
17210779SCurtis.Dunham@arm.com        }
17310779SCurtis.Dunham@arm.com
17410779SCurtis.Dunham@arm.com        // Clear out bus delay notifications
17510779SCurtis.Dunham@arm.com        pkt->headerDelay = pkt->payloadDelay = 0;
17610779SCurtis.Dunham@arm.com
17710779SCurtis.Dunham@arm.com        if (blocked() || !sendTimingResp(pkt)) {
17810779SCurtis.Dunham@arm.com            respQ.push_back(pkt);
17910779SCurtis.Dunham@arm.com        }
18010779SCurtis.Dunham@arm.com    } else { // we can handle unexpected invalidates, but nothing else.
18110779SCurtis.Dunham@arm.com        Command cmd = event->getCmd();
18210779SCurtis.Dunham@arm.com        assert(cmd == Inv);
18310779SCurtis.Dunham@arm.com
18410779SCurtis.Dunham@arm.com        // make Req/Pkt for Snoop/no response needed
18510779SCurtis.Dunham@arm.com        // presently no consideration for masterId, packet type, flags...
18610779SCurtis.Dunham@arm.com        RequestPtr req = new Request(event->getAddr(), event->getSize(), 0, 0);
18710779SCurtis.Dunham@arm.com        auto pkt = new Packet(req, ::MemCmd::InvalidationReq);
18810779SCurtis.Dunham@arm.com
18910779SCurtis.Dunham@arm.com        // Clear out bus delay notifications
19010779SCurtis.Dunham@arm.com        pkt->headerDelay = pkt->payloadDelay = 0;
19110779SCurtis.Dunham@arm.com
19210779SCurtis.Dunham@arm.com        sendTimingSnoopReq(pkt);
19310779SCurtis.Dunham@arm.com    }
19410779SCurtis.Dunham@arm.com    delete event;
19510779SCurtis.Dunham@arm.com}
19610779SCurtis.Dunham@arm.com
19710779SCurtis.Dunham@arm.comvoid
19810779SCurtis.Dunham@arm.comExtSlave::recvRespRetry()
19910779SCurtis.Dunham@arm.com{
20010779SCurtis.Dunham@arm.com    while (blocked() && sendTimingResp(respQ.front())) {
20110779SCurtis.Dunham@arm.com        respQ.pop_front();
20210779SCurtis.Dunham@arm.com    }
20310779SCurtis.Dunham@arm.com}
204