simple_memobj.cc revision 12338
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) : 3612338Sjason@lowepower.com MemObject(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 4412338Sjason@lowepower.comBaseMasterPort& 4512338Sjason@lowepower.comSimpleMemobj::getMasterPort(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; 5212338Sjason@lowepower.com } else { 5312338Sjason@lowepower.com // pass it along to our super class 5412338Sjason@lowepower.com return MemObject::getMasterPort(if_name, idx); 5512338Sjason@lowepower.com } 5612338Sjason@lowepower.com} 5712338Sjason@lowepower.com 5812338Sjason@lowepower.comBaseSlavePort& 5912338Sjason@lowepower.comSimpleMemobj::getSlavePort(const std::string& if_name, PortID idx) 6012338Sjason@lowepower.com{ 6112338Sjason@lowepower.com panic_if(idx != InvalidPortID, "This object doesn't support vector ports"); 6212338Sjason@lowepower.com 6312338Sjason@lowepower.com // This is the name from the Python SimObject declaration in SimpleCache.py 6412338Sjason@lowepower.com if (if_name == "inst_port") { 6512338Sjason@lowepower.com return instPort; 6612338Sjason@lowepower.com } else if (if_name == "data_port") { 6712338Sjason@lowepower.com return dataPort; 6812338Sjason@lowepower.com } else { 6912338Sjason@lowepower.com // pass it along to our super class 7012338Sjason@lowepower.com return MemObject::getSlavePort(if_name, idx); 7112338Sjason@lowepower.com } 7212338Sjason@lowepower.com} 7312338Sjason@lowepower.com 7412338Sjason@lowepower.comvoid 7512338Sjason@lowepower.comSimpleMemobj::CPUSidePort::sendPacket(PacketPtr pkt) 7612338Sjason@lowepower.com{ 7712338Sjason@lowepower.com // Note: This flow control is very simple since the memobj is blocking. 7812338Sjason@lowepower.com 7912338Sjason@lowepower.com panic_if(blockedPacket != nullptr, "Should never try to send if blocked!"); 8012338Sjason@lowepower.com 8112338Sjason@lowepower.com // If we can't send the packet across the port, store it for later. 8212338Sjason@lowepower.com if (!sendTimingResp(pkt)) { 8312338Sjason@lowepower.com blockedPacket = pkt; 8412338Sjason@lowepower.com } 8512338Sjason@lowepower.com} 8612338Sjason@lowepower.com 8712338Sjason@lowepower.comAddrRangeList 8812338Sjason@lowepower.comSimpleMemobj::CPUSidePort::getAddrRanges() const 8912338Sjason@lowepower.com{ 9012338Sjason@lowepower.com return owner->getAddrRanges(); 9112338Sjason@lowepower.com} 9212338Sjason@lowepower.com 9312338Sjason@lowepower.comvoid 9412338Sjason@lowepower.comSimpleMemobj::CPUSidePort::trySendRetry() 9512338Sjason@lowepower.com{ 9612338Sjason@lowepower.com if (needRetry && blockedPacket == nullptr) { 9712338Sjason@lowepower.com // Only send a retry if the port is now completely free 9812338Sjason@lowepower.com needRetry = false; 9912338Sjason@lowepower.com DPRINTF(SimpleMemobj, "Sending retry req for %d\n", id); 10012338Sjason@lowepower.com sendRetryReq(); 10112338Sjason@lowepower.com } 10212338Sjason@lowepower.com} 10312338Sjason@lowepower.com 10412338Sjason@lowepower.comvoid 10512338Sjason@lowepower.comSimpleMemobj::CPUSidePort::recvFunctional(PacketPtr pkt) 10612338Sjason@lowepower.com{ 10712338Sjason@lowepower.com // Just forward to the memobj. 10812338Sjason@lowepower.com return owner->handleFunctional(pkt); 10912338Sjason@lowepower.com} 11012338Sjason@lowepower.com 11112338Sjason@lowepower.combool 11212338Sjason@lowepower.comSimpleMemobj::CPUSidePort::recvTimingReq(PacketPtr pkt) 11312338Sjason@lowepower.com{ 11412338Sjason@lowepower.com // Just forward to the memobj. 11512338Sjason@lowepower.com if (!owner->handleRequest(pkt)) { 11612338Sjason@lowepower.com needRetry = true; 11712338Sjason@lowepower.com return false; 11812338Sjason@lowepower.com } else { 11912338Sjason@lowepower.com return true; 12012338Sjason@lowepower.com } 12112338Sjason@lowepower.com} 12212338Sjason@lowepower.com 12312338Sjason@lowepower.comvoid 12412338Sjason@lowepower.comSimpleMemobj::CPUSidePort::recvRespRetry() 12512338Sjason@lowepower.com{ 12612338Sjason@lowepower.com // We should have a blocked packet if this function is called. 12712338Sjason@lowepower.com assert(blockedPacket != nullptr); 12812338Sjason@lowepower.com 12912338Sjason@lowepower.com // Grab the blocked packet. 13012338Sjason@lowepower.com PacketPtr pkt = blockedPacket; 13112338Sjason@lowepower.com blockedPacket = nullptr; 13212338Sjason@lowepower.com 13312338Sjason@lowepower.com // Try to resend it. It's possible that it fails again. 13412338Sjason@lowepower.com sendPacket(pkt); 13512338Sjason@lowepower.com} 13612338Sjason@lowepower.com 13712338Sjason@lowepower.comvoid 13812338Sjason@lowepower.comSimpleMemobj::MemSidePort::sendPacket(PacketPtr pkt) 13912338Sjason@lowepower.com{ 14012338Sjason@lowepower.com // Note: This flow control is very simple since the memobj is blocking. 14112338Sjason@lowepower.com 14212338Sjason@lowepower.com panic_if(blockedPacket != nullptr, "Should never try to send if blocked!"); 14312338Sjason@lowepower.com 14412338Sjason@lowepower.com // If we can't send the packet across the port, store it for later. 14512338Sjason@lowepower.com if (!sendTimingReq(pkt)) { 14612338Sjason@lowepower.com blockedPacket = pkt; 14712338Sjason@lowepower.com } 14812338Sjason@lowepower.com} 14912338Sjason@lowepower.com 15012338Sjason@lowepower.combool 15112338Sjason@lowepower.comSimpleMemobj::MemSidePort::recvTimingResp(PacketPtr pkt) 15212338Sjason@lowepower.com{ 15312338Sjason@lowepower.com // Just forward to the memobj. 15412338Sjason@lowepower.com return owner->handleResponse(pkt); 15512338Sjason@lowepower.com} 15612338Sjason@lowepower.com 15712338Sjason@lowepower.comvoid 15812338Sjason@lowepower.comSimpleMemobj::MemSidePort::recvReqRetry() 15912338Sjason@lowepower.com{ 16012338Sjason@lowepower.com // We should have a blocked packet if this function is called. 16112338Sjason@lowepower.com assert(blockedPacket != nullptr); 16212338Sjason@lowepower.com 16312338Sjason@lowepower.com // Grab the blocked packet. 16412338Sjason@lowepower.com PacketPtr pkt = blockedPacket; 16512338Sjason@lowepower.com blockedPacket = nullptr; 16612338Sjason@lowepower.com 16712338Sjason@lowepower.com // Try to resend it. It's possible that it fails again. 16812338Sjason@lowepower.com sendPacket(pkt); 16912338Sjason@lowepower.com} 17012338Sjason@lowepower.com 17112338Sjason@lowepower.comvoid 17212338Sjason@lowepower.comSimpleMemobj::MemSidePort::recvRangeChange() 17312338Sjason@lowepower.com{ 17412338Sjason@lowepower.com owner->sendRangeChange(); 17512338Sjason@lowepower.com} 17612338Sjason@lowepower.com 17712338Sjason@lowepower.combool 17812338Sjason@lowepower.comSimpleMemobj::handleRequest(PacketPtr pkt) 17912338Sjason@lowepower.com{ 18012338Sjason@lowepower.com if (blocked) { 18112338Sjason@lowepower.com // There is currently an outstanding request. Stall. 18212338Sjason@lowepower.com return false; 18312338Sjason@lowepower.com } 18412338Sjason@lowepower.com 18512338Sjason@lowepower.com DPRINTF(SimpleMemobj, "Got request for addr %#x\n", pkt->getAddr()); 18612338Sjason@lowepower.com 18712338Sjason@lowepower.com // This memobj is now blocked waiting for the response to this packet. 18812338Sjason@lowepower.com blocked = true; 18912338Sjason@lowepower.com 19012338Sjason@lowepower.com // Simply forward to the memory port 19112338Sjason@lowepower.com memPort.sendPacket(pkt); 19212338Sjason@lowepower.com 19312338Sjason@lowepower.com return true; 19412338Sjason@lowepower.com} 19512338Sjason@lowepower.com 19612338Sjason@lowepower.combool 19712338Sjason@lowepower.comSimpleMemobj::handleResponse(PacketPtr pkt) 19812338Sjason@lowepower.com{ 19912338Sjason@lowepower.com assert(blocked); 20012338Sjason@lowepower.com DPRINTF(SimpleMemobj, "Got response for addr %#x\n", pkt->getAddr()); 20112338Sjason@lowepower.com 20212338Sjason@lowepower.com // The packet is now done. We're about to put it in the port, no need for 20312338Sjason@lowepower.com // this object to continue to stall. 20412338Sjason@lowepower.com // We need to free the resource before sending the packet in case the CPU 20512338Sjason@lowepower.com // tries to send another request immediately (e.g., in the same callchain). 20612338Sjason@lowepower.com blocked = false; 20712338Sjason@lowepower.com 20812338Sjason@lowepower.com // Simply forward to the memory port 20912338Sjason@lowepower.com if (pkt->req->isInstFetch()) { 21012338Sjason@lowepower.com instPort.sendPacket(pkt); 21112338Sjason@lowepower.com } else { 21212338Sjason@lowepower.com dataPort.sendPacket(pkt); 21312338Sjason@lowepower.com } 21412338Sjason@lowepower.com 21512338Sjason@lowepower.com // For each of the cpu ports, if it needs to send a retry, it should do it 21612338Sjason@lowepower.com // now since this memory object may be unblocked now. 21712338Sjason@lowepower.com instPort.trySendRetry(); 21812338Sjason@lowepower.com dataPort.trySendRetry(); 21912338Sjason@lowepower.com 22012338Sjason@lowepower.com return true; 22112338Sjason@lowepower.com} 22212338Sjason@lowepower.com 22312338Sjason@lowepower.comvoid 22412338Sjason@lowepower.comSimpleMemobj::handleFunctional(PacketPtr pkt) 22512338Sjason@lowepower.com{ 22612338Sjason@lowepower.com // Just pass this on to the memory side to handle for now. 22712338Sjason@lowepower.com memPort.sendFunctional(pkt); 22812338Sjason@lowepower.com} 22912338Sjason@lowepower.com 23012338Sjason@lowepower.comAddrRangeList 23112338Sjason@lowepower.comSimpleMemobj::getAddrRanges() const 23212338Sjason@lowepower.com{ 23312338Sjason@lowepower.com DPRINTF(SimpleMemobj, "Sending new ranges\n"); 23412338Sjason@lowepower.com // Just use the same ranges as whatever is on the memory side. 23512338Sjason@lowepower.com return memPort.getAddrRanges(); 23612338Sjason@lowepower.com} 23712338Sjason@lowepower.com 23812338Sjason@lowepower.comvoid 23912338Sjason@lowepower.comSimpleMemobj::sendRangeChange() 24012338Sjason@lowepower.com{ 24112338Sjason@lowepower.com instPort.sendRangeChange(); 24212338Sjason@lowepower.com dataPort.sendRangeChange(); 24312338Sjason@lowepower.com} 24412338Sjason@lowepower.com 24512338Sjason@lowepower.com 24612338Sjason@lowepower.com 24712338Sjason@lowepower.comSimpleMemobj* 24812338Sjason@lowepower.comSimpleMemobjParams::create() 24912338Sjason@lowepower.com{ 25012338Sjason@lowepower.com return new SimpleMemobj(this); 25112338Sjason@lowepower.com} 252