simple_memobj.cc revision 14252
112338Sjason@lowepower.com/* 212338Sjason@lowepower.com * Copyright (c) 2017 Jason Lowe-Power 312338Sjason@lowepower.com * All rights reserved. 412338Sjason@lowepower.com * 512338Sjason@lowepower.com * Redistribution and use in source and binary forms, with or without 612338Sjason@lowepower.com * modification, are permitted provided that the following conditions are 712338Sjason@lowepower.com * met: redistributions of source code must retain the above copyright 812338Sjason@lowepower.com * notice, this list of conditions and the following disclaimer; 912338Sjason@lowepower.com * redistributions in binary form must reproduce the above copyright 1012338Sjason@lowepower.com * notice, this list of conditions and the following disclaimer in the 1112338Sjason@lowepower.com * documentation and/or other materials provided with the distribution; 1212338Sjason@lowepower.com * neither the name of the copyright holders nor the names of its 1312338Sjason@lowepower.com * contributors may be used to endorse or promote products derived from 1412338Sjason@lowepower.com * this software without specific prior written permission. 1512338Sjason@lowepower.com * 1612338Sjason@lowepower.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1712338Sjason@lowepower.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1812338Sjason@lowepower.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1912338Sjason@lowepower.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2012338Sjason@lowepower.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2112338Sjason@lowepower.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2212338Sjason@lowepower.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2312338Sjason@lowepower.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2412338Sjason@lowepower.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2512338Sjason@lowepower.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2612338Sjason@lowepower.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2712338Sjason@lowepower.com * 2812338Sjason@lowepower.com * Authors: Jason Lowe-Power 2912338Sjason@lowepower.com */ 3012338Sjason@lowepower.com 3112338Sjason@lowepower.com#include "learning_gem5/part2/simple_memobj.hh" 3212338Sjason@lowepower.com 3312338Sjason@lowepower.com#include "debug/SimpleMemobj.hh" 3412338Sjason@lowepower.com 3512338Sjason@lowepower.comSimpleMemobj::SimpleMemobj(SimpleMemobjParams *params) : 3614252Sgabeblack@google.com SimObject(params), 3712338Sjason@lowepower.com instPort(params->name + ".inst_port", this), 3812338Sjason@lowepower.com dataPort(params->name + ".data_port", this), 3912338Sjason@lowepower.com memPort(params->name + ".mem_side", this), 4012338Sjason@lowepower.com blocked(false) 4112338Sjason@lowepower.com{ 4212338Sjason@lowepower.com} 4312338Sjason@lowepower.com 4413784Sgabeblack@google.comPort & 4513784Sgabeblack@google.comSimpleMemobj::getPort(const std::string &if_name, PortID idx) 4612338Sjason@lowepower.com{ 4712338Sjason@lowepower.com panic_if(idx != InvalidPortID, "This object doesn't support vector ports"); 4812338Sjason@lowepower.com 4912338Sjason@lowepower.com // This is the name from the Python SimObject declaration (SimpleMemobj.py) 5012338Sjason@lowepower.com if (if_name == "mem_side") { 5112338Sjason@lowepower.com return memPort; 5213784Sgabeblack@google.com } else if (if_name == "inst_port") { 5312338Sjason@lowepower.com return instPort; 5412338Sjason@lowepower.com } else if (if_name == "data_port") { 5512338Sjason@lowepower.com return dataPort; 5612338Sjason@lowepower.com } else { 5712338Sjason@lowepower.com // pass it along to our super class 5814252Sgabeblack@google.com return SimObject::getPort(if_name, idx); 5912338Sjason@lowepower.com } 6012338Sjason@lowepower.com} 6112338Sjason@lowepower.com 6212338Sjason@lowepower.comvoid 6312338Sjason@lowepower.comSimpleMemobj::CPUSidePort::sendPacket(PacketPtr pkt) 6412338Sjason@lowepower.com{ 6512338Sjason@lowepower.com // Note: This flow control is very simple since the memobj is blocking. 6612338Sjason@lowepower.com 6712338Sjason@lowepower.com panic_if(blockedPacket != nullptr, "Should never try to send if blocked!"); 6812338Sjason@lowepower.com 6912338Sjason@lowepower.com // If we can't send the packet across the port, store it for later. 7012338Sjason@lowepower.com if (!sendTimingResp(pkt)) { 7112338Sjason@lowepower.com blockedPacket = pkt; 7212338Sjason@lowepower.com } 7312338Sjason@lowepower.com} 7412338Sjason@lowepower.com 7512338Sjason@lowepower.comAddrRangeList 7612338Sjason@lowepower.comSimpleMemobj::CPUSidePort::getAddrRanges() const 7712338Sjason@lowepower.com{ 7812338Sjason@lowepower.com return owner->getAddrRanges(); 7912338Sjason@lowepower.com} 8012338Sjason@lowepower.com 8112338Sjason@lowepower.comvoid 8212338Sjason@lowepower.comSimpleMemobj::CPUSidePort::trySendRetry() 8312338Sjason@lowepower.com{ 8412338Sjason@lowepower.com if (needRetry && blockedPacket == nullptr) { 8512338Sjason@lowepower.com // Only send a retry if the port is now completely free 8612338Sjason@lowepower.com needRetry = false; 8712338Sjason@lowepower.com DPRINTF(SimpleMemobj, "Sending retry req for %d\n", id); 8812338Sjason@lowepower.com sendRetryReq(); 8912338Sjason@lowepower.com } 9012338Sjason@lowepower.com} 9112338Sjason@lowepower.com 9212338Sjason@lowepower.comvoid 9312338Sjason@lowepower.comSimpleMemobj::CPUSidePort::recvFunctional(PacketPtr pkt) 9412338Sjason@lowepower.com{ 9512338Sjason@lowepower.com // Just forward to the memobj. 9612338Sjason@lowepower.com return owner->handleFunctional(pkt); 9712338Sjason@lowepower.com} 9812338Sjason@lowepower.com 9912338Sjason@lowepower.combool 10012338Sjason@lowepower.comSimpleMemobj::CPUSidePort::recvTimingReq(PacketPtr pkt) 10112338Sjason@lowepower.com{ 10212338Sjason@lowepower.com // Just forward to the memobj. 10312338Sjason@lowepower.com if (!owner->handleRequest(pkt)) { 10412338Sjason@lowepower.com needRetry = true; 10512338Sjason@lowepower.com return false; 10612338Sjason@lowepower.com } else { 10712338Sjason@lowepower.com return true; 10812338Sjason@lowepower.com } 10912338Sjason@lowepower.com} 11012338Sjason@lowepower.com 11112338Sjason@lowepower.comvoid 11212338Sjason@lowepower.comSimpleMemobj::CPUSidePort::recvRespRetry() 11312338Sjason@lowepower.com{ 11412338Sjason@lowepower.com // We should have a blocked packet if this function is called. 11512338Sjason@lowepower.com assert(blockedPacket != nullptr); 11612338Sjason@lowepower.com 11712338Sjason@lowepower.com // Grab the blocked packet. 11812338Sjason@lowepower.com PacketPtr pkt = blockedPacket; 11912338Sjason@lowepower.com blockedPacket = nullptr; 12012338Sjason@lowepower.com 12112338Sjason@lowepower.com // Try to resend it. It's possible that it fails again. 12212338Sjason@lowepower.com sendPacket(pkt); 12312338Sjason@lowepower.com} 12412338Sjason@lowepower.com 12512338Sjason@lowepower.comvoid 12612338Sjason@lowepower.comSimpleMemobj::MemSidePort::sendPacket(PacketPtr pkt) 12712338Sjason@lowepower.com{ 12812338Sjason@lowepower.com // Note: This flow control is very simple since the memobj is blocking. 12912338Sjason@lowepower.com 13012338Sjason@lowepower.com panic_if(blockedPacket != nullptr, "Should never try to send if blocked!"); 13112338Sjason@lowepower.com 13212338Sjason@lowepower.com // If we can't send the packet across the port, store it for later. 13312338Sjason@lowepower.com if (!sendTimingReq(pkt)) { 13412338Sjason@lowepower.com blockedPacket = pkt; 13512338Sjason@lowepower.com } 13612338Sjason@lowepower.com} 13712338Sjason@lowepower.com 13812338Sjason@lowepower.combool 13912338Sjason@lowepower.comSimpleMemobj::MemSidePort::recvTimingResp(PacketPtr pkt) 14012338Sjason@lowepower.com{ 14112338Sjason@lowepower.com // Just forward to the memobj. 14212338Sjason@lowepower.com return owner->handleResponse(pkt); 14312338Sjason@lowepower.com} 14412338Sjason@lowepower.com 14512338Sjason@lowepower.comvoid 14612338Sjason@lowepower.comSimpleMemobj::MemSidePort::recvReqRetry() 14712338Sjason@lowepower.com{ 14812338Sjason@lowepower.com // We should have a blocked packet if this function is called. 14912338Sjason@lowepower.com assert(blockedPacket != nullptr); 15012338Sjason@lowepower.com 15112338Sjason@lowepower.com // Grab the blocked packet. 15212338Sjason@lowepower.com PacketPtr pkt = blockedPacket; 15312338Sjason@lowepower.com blockedPacket = nullptr; 15412338Sjason@lowepower.com 15512338Sjason@lowepower.com // Try to resend it. It's possible that it fails again. 15612338Sjason@lowepower.com sendPacket(pkt); 15712338Sjason@lowepower.com} 15812338Sjason@lowepower.com 15912338Sjason@lowepower.comvoid 16012338Sjason@lowepower.comSimpleMemobj::MemSidePort::recvRangeChange() 16112338Sjason@lowepower.com{ 16212338Sjason@lowepower.com owner->sendRangeChange(); 16312338Sjason@lowepower.com} 16412338Sjason@lowepower.com 16512338Sjason@lowepower.combool 16612338Sjason@lowepower.comSimpleMemobj::handleRequest(PacketPtr pkt) 16712338Sjason@lowepower.com{ 16812338Sjason@lowepower.com if (blocked) { 16912338Sjason@lowepower.com // There is currently an outstanding request. Stall. 17012338Sjason@lowepower.com return false; 17112338Sjason@lowepower.com } 17212338Sjason@lowepower.com 17312338Sjason@lowepower.com DPRINTF(SimpleMemobj, "Got request for addr %#x\n", pkt->getAddr()); 17412338Sjason@lowepower.com 17512338Sjason@lowepower.com // This memobj is now blocked waiting for the response to this packet. 17612338Sjason@lowepower.com blocked = true; 17712338Sjason@lowepower.com 17812338Sjason@lowepower.com // Simply forward to the memory port 17912338Sjason@lowepower.com memPort.sendPacket(pkt); 18012338Sjason@lowepower.com 18112338Sjason@lowepower.com return true; 18212338Sjason@lowepower.com} 18312338Sjason@lowepower.com 18412338Sjason@lowepower.combool 18512338Sjason@lowepower.comSimpleMemobj::handleResponse(PacketPtr pkt) 18612338Sjason@lowepower.com{ 18712338Sjason@lowepower.com assert(blocked); 18812338Sjason@lowepower.com DPRINTF(SimpleMemobj, "Got response for addr %#x\n", pkt->getAddr()); 18912338Sjason@lowepower.com 19012338Sjason@lowepower.com // The packet is now done. We're about to put it in the port, no need for 19112338Sjason@lowepower.com // this object to continue to stall. 19212338Sjason@lowepower.com // We need to free the resource before sending the packet in case the CPU 19312338Sjason@lowepower.com // tries to send another request immediately (e.g., in the same callchain). 19412338Sjason@lowepower.com blocked = false; 19512338Sjason@lowepower.com 19612338Sjason@lowepower.com // Simply forward to the memory port 19712338Sjason@lowepower.com if (pkt->req->isInstFetch()) { 19812338Sjason@lowepower.com instPort.sendPacket(pkt); 19912338Sjason@lowepower.com } else { 20012338Sjason@lowepower.com dataPort.sendPacket(pkt); 20112338Sjason@lowepower.com } 20212338Sjason@lowepower.com 20312338Sjason@lowepower.com // For each of the cpu ports, if it needs to send a retry, it should do it 20412338Sjason@lowepower.com // now since this memory object may be unblocked now. 20512338Sjason@lowepower.com instPort.trySendRetry(); 20612338Sjason@lowepower.com dataPort.trySendRetry(); 20712338Sjason@lowepower.com 20812338Sjason@lowepower.com return true; 20912338Sjason@lowepower.com} 21012338Sjason@lowepower.com 21112338Sjason@lowepower.comvoid 21212338Sjason@lowepower.comSimpleMemobj::handleFunctional(PacketPtr pkt) 21312338Sjason@lowepower.com{ 21412338Sjason@lowepower.com // Just pass this on to the memory side to handle for now. 21512338Sjason@lowepower.com memPort.sendFunctional(pkt); 21612338Sjason@lowepower.com} 21712338Sjason@lowepower.com 21812338Sjason@lowepower.comAddrRangeList 21912338Sjason@lowepower.comSimpleMemobj::getAddrRanges() const 22012338Sjason@lowepower.com{ 22112338Sjason@lowepower.com DPRINTF(SimpleMemobj, "Sending new ranges\n"); 22212338Sjason@lowepower.com // Just use the same ranges as whatever is on the memory side. 22312338Sjason@lowepower.com return memPort.getAddrRanges(); 22412338Sjason@lowepower.com} 22512338Sjason@lowepower.com 22612338Sjason@lowepower.comvoid 22712338Sjason@lowepower.comSimpleMemobj::sendRangeChange() 22812338Sjason@lowepower.com{ 22912338Sjason@lowepower.com instPort.sendRangeChange(); 23012338Sjason@lowepower.com dataPort.sendRangeChange(); 23112338Sjason@lowepower.com} 23212338Sjason@lowepower.com 23312338Sjason@lowepower.com 23412338Sjason@lowepower.com 23512338Sjason@lowepower.comSimpleMemobj* 23612338Sjason@lowepower.comSimpleMemobjParams::create() 23712338Sjason@lowepower.com{ 23812338Sjason@lowepower.com return new SimpleMemobj(this); 23912338Sjason@lowepower.com} 240