1// Copyright (c) 2015 ARM Limited 2// All rights reserved. 3// 4// The license below extends only to copyright in the software and shall 5// not be construed as granting a license to any other intellectual 6// property including but not limited to intellectual property relating 7// to a hardware implementation of the functionality of the software 8// licensed hereunder. You may use the software subject to the license 9// terms below provided that you ensure that this notice is replicated 10// unmodified and in its entirety in all distributions of the software, 11// modified or unmodified, in source code or in binary form. 12// 13// Redistribution and use in source and binary forms, with or without 14// modification, are permitted provided that the following conditions are 15// met: redistributions of source code must retain the above copyright 16// notice, this list of conditions and the following disclaimer; 17// redistributions in binary form must reproduce the above copyright 18// notice, this list of conditions and the following disclaimer in the 19// documentation and/or other materials provided with the distribution; 20// neither the name of the copyright holders nor the names of its 21// contributors may be used to endorse or promote products derived from 22// this software without specific prior written permission. 23// 24// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 30// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 36// Copyright 2009-2014 Sandia Coporation. Under the terms 37// of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. 38// Government retains certain rights in this software. 39// 40// Copyright (c) 2009-2014, Sandia Corporation 41// All rights reserved. 42// 43// For license information, see the LICENSE file in the current directory. 44 45#include "gem5.hh" 46 47#ifdef fatal // gem5 sets this 48#undef fatal 49#endif 50 51#include <mem/packet.hh> 52 53#include <elements/memHierarchy/memNIC.h> 54 55using namespace SST; 56using namespace SST::gem5; 57using namespace SST::MemHierarchy; 58 59ExtMaster::ExtMaster(gem5Component *g, Output &o, ::ExternalMaster& p, 60 std::string &n) : 61 Port(n, p), out(o), port(p), simPhase(CONSTRUCTION), 62 gem5(g), name(n) 63{ 64 Params _p; // will be ignored 65 nic = dynamic_cast<MemNIC*>(gem5->loadModuleWithComponent("memHierarchy.memNIC", g, _p)); 66 67 MemNIC::ComponentInfo ci; 68 ci.num_vcs = 1; 69 ci.link_port = "network"; 70 ci.link_bandwidth = "16GB/s"; 71 ci.link_inbuf_size = "1KB"; 72 ci.link_outbuf_size = "1KB"; 73 ci.network_addr = 0; // hard coded at the moment 74 ci.type = MemNIC::TypeDirectoryCtrl; 75 nic->moduleInit(ci, new Event::Handler<ExtMaster> 76 (this, &ExtMaster::handleEvent)); 77} 78 79void 80ExtMaster::init(unsigned phase) 81{ 82 simPhase = INIT; 83 84 if (phase == 0) { 85 assert(nic); 86 for (auto range : getAddrRanges()) { 87 MemNIC::ComponentTypeInfo ti; 88 ti.rangeStart = range.start(); 89 ti.rangeEnd = range.end(); 90 ti.interleaveSize = 0; 91 ti.interleaveStep = 0; 92 nic->addTypeInfo(ti); 93 ranges.insert(range); 94 } 95 } 96 97 nic->init(phase); 98} 99 100void 101ExtMaster::setup(void) 102{ 103 nic->setup(); 104 105 simPhase = RUN; 106} 107 108void 109ExtMaster::finish(void) 110{ 111 nic->finish(); 112} 113 114void 115ExtMaster::clock(void) 116{ 117 nic->clock(); 118} 119 120void 121ExtMaster::handleEvent(SST::Event* event) 122{ 123 if (simPhase == CONSTRUCTION) { 124 out.fatal(CALL_INFO, 1, "received Event during Construction phase\n"); 125 } 126 127 MemEvent *ev = dynamic_cast<MemEvent*>(event); 128 if (!ev) { 129 out.fatal(CALL_INFO, 1, "Can't handle non-MemEvent Event's\n"); 130 } 131 132 Command cmdI = ev->getCmd(); // command in - SST 133 MemCmd::Command cmdO; // command out - gem5 134 bool data = false; 135 136 switch (cmdI) { 137 case GetS: cmdO = MemCmd::ReadReq; break; 138 case GetX: cmdO = MemCmd::WriteReq; data = true; break; 139 case GetSEx: 140 case PutS: 141 case PutM: 142 case PutE: 143 case PutX: 144 case PutXE: 145 case Inv: 146 case FetchInv: 147 case FetchInvX: 148 149 case NACK: 150 151 case NULLCMD: 152 case GetSResp: 153 case GetXResp: 154 case FetchResp: 155 case FetchXResp: 156 out.fatal(CALL_INFO, 1, "Don't know how to convert " 157 "SST command %s to gem5\n", 158 CommandString[cmdI]); 159 } 160 161 Request::FlagsType flags = 0; 162 if (ev->queryFlag(MemEvent::F_LOCKED)) 163 flags |= Request::LOCKED_RMW; 164 if (ev->queryFlag(MemEvent::F_NONCACHEABLE)) 165 flags |= Request::UNCACHEABLE; 166 if (ev->isLoadLink()) { 167 assert(cmdI == GetS); 168 cmdO = MemCmd::LoadLockedReq; 169 } else if (ev->isStoreConditional()) { 170 assert(cmdI == GetX); 171 cmdO = MemCmd::StoreCondReq; 172 } 173 174 auto req = std::make_shared<Request>(ev->getAddr(), ev->getSize(), flags, 0); 175 req->setContext(ev->getGroupId()); 176 177 auto pkt = new Packet(req, cmdO); 178 pkt->allocate(); 179 if (data) { 180 pkt->setData(ev->getPayload().data()); 181 } 182 pkt->pushSenderState(new SenderState(ev)); 183 184 if (blocked() || !sendTimingReq(pkt)) 185 sendQ.push_back(pkt); 186} 187 188bool 189ExtMaster::recvTimingResp(PacketPtr pkt) { 190 if (simPhase == INIT) { 191 out.fatal(CALL_INFO, 1, "not prepared to handle INIT-phase traffic\n"); 192 } 193 194 // get original SST packet from gem5 SenderState 195 auto senderState = dynamic_cast<SenderState*>(pkt->popSenderState()); 196 if (!senderState) 197 out.fatal(CALL_INFO, 1, "gem5 senderState corrupt\n"); 198 199 // make (new) response packet, discard (old) original request 200 MemEvent* ev = senderState->event; 201 delete senderState; 202 203 MemEvent* resp = ev->makeResponse(); 204 delete ev; 205 206 // copy the payload and then destroy gem5 packet 207 resp->setPayload(pkt->getSize(), pkt->getPtr<uint8_t>()); 208 delete pkt; 209 210 nic->send(resp); 211 return true; 212} 213 214void 215ExtMaster::recvReqRetry() { 216 while (blocked() && sendTimingReq(sendQ.front())) { 217 sendQ.pop_front(); 218 } 219} 220 221void 222ExtMaster::recvRangeChange() { 223 for (auto range : getAddrRanges()) { 224 if (ranges.find(range) == ranges.end()) { // i.e. if not found, 225 MemNIC::ComponentTypeInfo ti; // indicating a new range. 226 ti.rangeStart = range.start(); 227 ti.rangeEnd = range.end(); 228 ti.interleaveSize = 0; 229 ti.interleaveStep = 0; 230 nic->addTypeInfo(ti); 231 ranges.insert(range); 232 } 233 } 234} 235