packet.cc revision 4040:eb894f3fc168
16313Sgblack@eecs.umich.edu/* 26313Sgblack@eecs.umich.edu * Copyright (c) 2006 The Regents of The University of Michigan 36313Sgblack@eecs.umich.edu * All rights reserved. 46313Sgblack@eecs.umich.edu * 56313Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 66313Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 76313Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 86313Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 96313Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 106313Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 116313Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 126313Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 136313Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 146313Sgblack@eecs.umich.edu * this software without specific prior written permission. 156313Sgblack@eecs.umich.edu * 166313Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176313Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186313Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196313Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206313Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216313Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226313Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236313Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246313Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256313Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266313Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276313Sgblack@eecs.umich.edu * 286313Sgblack@eecs.umich.edu * Authors: Ali Saidi 296313Sgblack@eecs.umich.edu * Steve Reinhardt 306313Sgblack@eecs.umich.edu */ 316313Sgblack@eecs.umich.edu 328229Snate@binkert.org/** 336334Sgblack@eecs.umich.edu * @file 346334Sgblack@eecs.umich.edu * Definition of the Packet Class, a packet is a transaction occuring 356334Sgblack@eecs.umich.edu * between a single level of the memory heirarchy (ie L1->L2). 366334Sgblack@eecs.umich.edu */ 376313Sgblack@eecs.umich.edu 388232Snate@binkert.org#include <iostream> 399384SAndreas.Sandberg@arm.com#include <cstring> 406313Sgblack@eecs.umich.edu#include "base/misc.hh" 416313Sgblack@eecs.umich.edu#include "base/trace.hh" 426313Sgblack@eecs.umich.edu#include "mem/packet.hh" 436313Sgblack@eecs.umich.edu 446334Sgblack@eecs.umich.edu// The one downside to bitsets is that static initializers can get ugly. 456334Sgblack@eecs.umich.edu#define SET1(a1) (1 << (a1)) 466334Sgblack@eecs.umich.edu#define SET2(a1, a2) (SET1(a1) | SET1(a2)) 476334Sgblack@eecs.umich.edu#define SET3(a1, a2, a3) (SET2(a1, a2) | SET1(a3)) 486334Sgblack@eecs.umich.edu#define SET4(a1, a2, a3, a4) (SET3(a1, a2, a3) | SET1(a4)) 496334Sgblack@eecs.umich.edu#define SET5(a1, a2, a3, a4, a5) (SET4(a1, a2, a3, a4) | SET1(a5)) 506334Sgblack@eecs.umich.edu#define SET6(a1, a2, a3, a4, a5, a6) (SET5(a1, a2, a3, a4, a5) | SET1(a6)) 516334Sgblack@eecs.umich.edu 526334Sgblack@eecs.umich.educonst MemCmd::CommandInfo 536334Sgblack@eecs.umich.eduMemCmd::commandInfo[] = 546334Sgblack@eecs.umich.edu{ 556334Sgblack@eecs.umich.edu /* InvalidCmd */ 566334Sgblack@eecs.umich.edu { 0, InvalidCmd, "InvalidCmd" }, 576334Sgblack@eecs.umich.edu /* ReadReq */ 586334Sgblack@eecs.umich.edu { SET3(IsRead, IsRequest, NeedsResponse), ReadResp, "ReadReq" }, 596334Sgblack@eecs.umich.edu /* WriteReq */ 606334Sgblack@eecs.umich.edu { SET4(IsWrite, IsRequest, NeedsResponse, HasData), 616334Sgblack@eecs.umich.edu WriteResp, "WriteReq" }, 626334Sgblack@eecs.umich.edu /* WriteReqNoAck */ 636334Sgblack@eecs.umich.edu { SET3(IsWrite, IsRequest, HasData), InvalidCmd, "WriteReqNoAck" }, 646334Sgblack@eecs.umich.edu /* ReadResp */ 656334Sgblack@eecs.umich.edu { SET3(IsRead, IsResponse, HasData), InvalidCmd, "ReadResp" }, 666334Sgblack@eecs.umich.edu /* WriteResp */ 676334Sgblack@eecs.umich.edu { SET2(IsWrite, IsResponse), InvalidCmd, "WriteResp" }, 686334Sgblack@eecs.umich.edu /* Writeback */ 696334Sgblack@eecs.umich.edu { SET3(IsWrite, IsRequest, HasData), InvalidCmd, "Writeback" }, 706334Sgblack@eecs.umich.edu /* SoftPFReq */ 716334Sgblack@eecs.umich.edu { SET4(IsRead, IsRequest, IsSWPrefetch, NeedsResponse), 726334Sgblack@eecs.umich.edu SoftPFResp, "SoftPFReq" }, 736334Sgblack@eecs.umich.edu /* HardPFReq */ 746334Sgblack@eecs.umich.edu { SET4(IsRead, IsRequest, IsHWPrefetch, NeedsResponse), 756334Sgblack@eecs.umich.edu HardPFResp, "HardPFReq" }, 766334Sgblack@eecs.umich.edu /* SoftPFResp */ 776334Sgblack@eecs.umich.edu { SET4(IsRead, IsResponse, IsSWPrefetch, HasData), 786334Sgblack@eecs.umich.edu InvalidCmd, "SoftPFResp" }, 796334Sgblack@eecs.umich.edu /* HardPFResp */ 806334Sgblack@eecs.umich.edu { SET4(IsRead, IsResponse, IsHWPrefetch, HasData), 816334Sgblack@eecs.umich.edu InvalidCmd, "HardPFResp" }, 826334Sgblack@eecs.umich.edu /* InvalidateReq */ 836334Sgblack@eecs.umich.edu { SET2(IsInvalidate, IsRequest), InvalidCmd, "InvalidateReq" }, 846334Sgblack@eecs.umich.edu /* WriteInvalidateReq */ 856334Sgblack@eecs.umich.edu { SET5(IsWrite, IsInvalidate, IsRequest, HasData, NeedsResponse), 866334Sgblack@eecs.umich.edu WriteInvalidateResp, "WriteInvalidateReq" }, 876334Sgblack@eecs.umich.edu /* WriteInvalidateResp */ 886334Sgblack@eecs.umich.edu { SET5(IsWrite, IsInvalidate, IsRequest, NeedsResponse, IsResponse), 896334Sgblack@eecs.umich.edu InvalidCmd, "WriteInvalidateResp" }, 906334Sgblack@eecs.umich.edu /* UpgradeReq */ 919384SAndreas.Sandberg@arm.com { SET3(IsInvalidate, IsRequest, IsUpgrade), InvalidCmd, "UpgradeReq" }, 9210033SAli.Saidi@ARM.com /* ReadExReq */ 936334Sgblack@eecs.umich.edu { SET4(IsRead, IsInvalidate, IsRequest, NeedsResponse), 946334Sgblack@eecs.umich.edu ReadExResp, "ReadExReq" }, 956334Sgblack@eecs.umich.edu /* ReadExResp */ 966334Sgblack@eecs.umich.edu { SET4(IsRead, IsInvalidate, IsResponse, HasData), 976334Sgblack@eecs.umich.edu InvalidCmd, "ReadExResp" }, 986334Sgblack@eecs.umich.edu /* SwapReq -- for Swap ldstub type operations */ 996334Sgblack@eecs.umich.edu { SET4(IsReadWrite, IsRequest, HasData, NeedsResponse), 1006334Sgblack@eecs.umich.edu SwapResp, "SwapReq" }, 1016334Sgblack@eecs.umich.edu /* SwapResp -- for Swap ldstub type operations */ 1026334Sgblack@eecs.umich.edu { SET3(IsReadWrite, IsResponse, HasData), 1036334Sgblack@eecs.umich.edu InvalidCmd, "SwapResp" } 1046376Sgblack@eecs.umich.edu}; 1056376Sgblack@eecs.umich.edu 1066334Sgblack@eecs.umich.edu 1076334Sgblack@eecs.umich.edu/** delete the data pointed to in the data pointer. Ok to call to matter how 1086334Sgblack@eecs.umich.edu * data was allocted. */ 1096383Sgblack@eecs.umich.eduvoid 1106383Sgblack@eecs.umich.eduPacket::deleteData() 1116383Sgblack@eecs.umich.edu{ 1126383Sgblack@eecs.umich.edu assert(staticData || dynamicData); 1136383Sgblack@eecs.umich.edu if (staticData) 1146383Sgblack@eecs.umich.edu return; 1156383Sgblack@eecs.umich.edu 1166383Sgblack@eecs.umich.edu if (arrayData) 1176334Sgblack@eecs.umich.edu delete [] data; 1186334Sgblack@eecs.umich.edu else 1196334Sgblack@eecs.umich.edu delete data; 1208181Sksewell@umich.edu} 1218181Sksewell@umich.edu 1226334Sgblack@eecs.umich.edu/** If there isn't data in the packet, allocate some. */ 1236334Sgblack@eecs.umich.eduvoid 1246334Sgblack@eecs.umich.eduPacket::allocate() 1256334Sgblack@eecs.umich.edu{ 1266334Sgblack@eecs.umich.edu if (data) 1276383Sgblack@eecs.umich.edu return; 1286383Sgblack@eecs.umich.edu assert(!staticData); 1296383Sgblack@eecs.umich.edu dynamicData = true; 1306383Sgblack@eecs.umich.edu arrayData = true; 1316383Sgblack@eecs.umich.edu data = new uint8_t[getSize()]; 1326383Sgblack@eecs.umich.edu} 1336334Sgblack@eecs.umich.edu 1346334Sgblack@eecs.umich.edu/** Do the packet modify the same addresses. */ 1356334Sgblack@eecs.umich.edubool 1366334Sgblack@eecs.umich.eduPacket::intersect(PacketPtr p) 1378181Sksewell@umich.edu{ 1386334Sgblack@eecs.umich.edu Addr s1 = getAddr(); 1396334Sgblack@eecs.umich.edu Addr e1 = getAddr() + getSize() - 1; 1406334Sgblack@eecs.umich.edu Addr s2 = p->getAddr(); 1418181Sksewell@umich.edu Addr e2 = p->getAddr() + p->getSize() - 1; 1426334Sgblack@eecs.umich.edu 1436334Sgblack@eecs.umich.edu return !(s1 > e2 || e1 < s2); 1449384SAndreas.Sandberg@arm.com} 1459384SAndreas.Sandberg@arm.com 1469384SAndreas.Sandberg@arm.combool 1479384SAndreas.Sandberg@arm.comfixDelayedResponsePacket(PacketPtr func, PacketPtr timing) 1489384SAndreas.Sandberg@arm.com{ 1499384SAndreas.Sandberg@arm.com bool result; 1506334Sgblack@eecs.umich.edu 1518181Sksewell@umich.edu if (timing->isRead() || timing->isWrite()) { 1528181Sksewell@umich.edu // Ugly hack to deal with the fact that we queue the requests 1538181Sksewell@umich.edu // and don't convert them to responses until we issue them on 1548181Sksewell@umich.edu // the bus. I tried to avoid this by converting packets to 1558181Sksewell@umich.edu // responses right away, but this breaks during snoops where a 1568181Sksewell@umich.edu // responder may do the conversion before other caches have 1578181Sksewell@umich.edu // done the snoop. Would work if we copied the packet instead 1588181Sksewell@umich.edu // of just hanging on to a pointer. 1598181Sksewell@umich.edu MemCmd oldCmd = timing->cmd; 1608181Sksewell@umich.edu timing->cmd = timing->cmd.responseCommand(); 1618181Sksewell@umich.edu result = fixPacket(func, timing); 1628181Sksewell@umich.edu timing->cmd = oldCmd; 1638181Sksewell@umich.edu } 1648181Sksewell@umich.edu else { 1656334Sgblack@eecs.umich.edu //Don't toggle if it isn't a read/write response 1666334Sgblack@eecs.umich.edu result = fixPacket(func, timing); 1678181Sksewell@umich.edu } 1686334Sgblack@eecs.umich.edu 1698181Sksewell@umich.edu return result; 1708181Sksewell@umich.edu} 1716334Sgblack@eecs.umich.edu 1726334Sgblack@eecs.umich.edubool 1736334Sgblack@eecs.umich.edufixPacket(PacketPtr func, PacketPtr timing) 1746334Sgblack@eecs.umich.edu{ 1756334Sgblack@eecs.umich.edu Addr funcStart = func->getAddr(); 1766334Sgblack@eecs.umich.edu Addr funcEnd = func->getAddr() + func->getSize() - 1; 1776334Sgblack@eecs.umich.edu Addr timingStart = timing->getAddr(); 1786334Sgblack@eecs.umich.edu Addr timingEnd = timing->getAddr() + timing->getSize() - 1; 1796383Sgblack@eecs.umich.edu 1806376Sgblack@eecs.umich.edu assert(!(funcStart > timingEnd || timingStart > funcEnd)); 1816376Sgblack@eecs.umich.edu 1826376Sgblack@eecs.umich.edu // this packet can't solve our problem, continue on 1836376Sgblack@eecs.umich.edu if (!timing->hasData()) 1846383Sgblack@eecs.umich.edu return true; 1856376Sgblack@eecs.umich.edu 1866334Sgblack@eecs.umich.edu if (func->isRead()) { 1876383Sgblack@eecs.umich.edu if (funcStart >= timingStart && funcEnd <= timingEnd) { 1886383Sgblack@eecs.umich.edu func->allocate(); 1896383Sgblack@eecs.umich.edu std::memcpy(func->getPtr<uint8_t>(), timing->getPtr<uint8_t>() + 1906334Sgblack@eecs.umich.edu funcStart - timingStart, func->getSize()); 1916334Sgblack@eecs.umich.edu func->result = Packet::Success; 1926383Sgblack@eecs.umich.edu func->flags |= SATISFIED; 1936376Sgblack@eecs.umich.edu return false; 1946376Sgblack@eecs.umich.edu } else { 1956376Sgblack@eecs.umich.edu // In this case the timing packet only partially satisfies the 1966376Sgblack@eecs.umich.edu // requset, so we would need more information to make this work. 1976376Sgblack@eecs.umich.edu // Like bytes valid in the packet or something, so the request could 1986376Sgblack@eecs.umich.edu // continue and get this bit of possibly newer data along with the 1996383Sgblack@eecs.umich.edu // older data not written to yet. 2006334Sgblack@eecs.umich.edu panic("Timing packet only partially satisfies the functional" 2016334Sgblack@eecs.umich.edu "request. Now what?"); 2026376Sgblack@eecs.umich.edu } 2036383Sgblack@eecs.umich.edu } else if (func->isWrite()) { 2046334Sgblack@eecs.umich.edu if (funcStart >= timingStart) { 2056334Sgblack@eecs.umich.edu std::memcpy(timing->getPtr<uint8_t>() + (funcStart - timingStart), 2066383Sgblack@eecs.umich.edu func->getPtr<uint8_t>(), 2076376Sgblack@eecs.umich.edu (std::min(funcEnd, timingEnd) - funcStart) + 1); 2086376Sgblack@eecs.umich.edu } else { // timingStart > funcStart 2096376Sgblack@eecs.umich.edu std::memcpy(timing->getPtr<uint8_t>(), 2106376Sgblack@eecs.umich.edu func->getPtr<uint8_t>() + (timingStart - funcStart), 2116376Sgblack@eecs.umich.edu (std::min(funcEnd, timingEnd) - timingStart) + 1); 2126376Sgblack@eecs.umich.edu } 2136376Sgblack@eecs.umich.edu // we always want to keep going with a write 2146376Sgblack@eecs.umich.edu return true; 2156376Sgblack@eecs.umich.edu } else 2166376Sgblack@eecs.umich.edu panic("Don't know how to handle command type %#x\n", 2176376Sgblack@eecs.umich.edu func->cmdToIndex()); 2186376Sgblack@eecs.umich.edu 2196376Sgblack@eecs.umich.edu} 2206376Sgblack@eecs.umich.edu 2216383Sgblack@eecs.umich.edu 2226334Sgblack@eecs.umich.edustd::ostream & 2236334Sgblack@eecs.umich.eduoperator<<(std::ostream &o, const Packet &p) 2246376Sgblack@eecs.umich.edu{ 2256383Sgblack@eecs.umich.edu 2266334Sgblack@eecs.umich.edu o << "[0x"; 2276334Sgblack@eecs.umich.edu o.setf(std::ios_base::hex, std::ios_base::showbase); 2286383Sgblack@eecs.umich.edu o << p.getAddr(); 2296376Sgblack@eecs.umich.edu o.unsetf(std::ios_base::hex| std::ios_base::showbase); 2306376Sgblack@eecs.umich.edu o << ":"; 2316376Sgblack@eecs.umich.edu o.setf(std::ios_base::hex, std::ios_base::showbase); 2326376Sgblack@eecs.umich.edu o << p.getAddr() + p.getSize() - 1 << "] "; 2336376Sgblack@eecs.umich.edu o.unsetf(std::ios_base::hex| std::ios_base::showbase); 2346376Sgblack@eecs.umich.edu 2356376Sgblack@eecs.umich.edu if (p.result == Packet::Success) 2366376Sgblack@eecs.umich.edu o << "Successful "; 2376376Sgblack@eecs.umich.edu if (p.result == Packet::BadAddress) 2386383Sgblack@eecs.umich.edu o << "BadAddress "; 2396334Sgblack@eecs.umich.edu if (p.result == Packet::Nacked) 2406334Sgblack@eecs.umich.edu o << "Nacked "; 2416376Sgblack@eecs.umich.edu if (p.result == Packet::Unknown) 2426383Sgblack@eecs.umich.edu o << "Inflight "; 2436334Sgblack@eecs.umich.edu 2446334Sgblack@eecs.umich.edu if (p.isRead()) 2456383Sgblack@eecs.umich.edu o << "Read "; 2466376Sgblack@eecs.umich.edu if (p.isWrite()) 2476376Sgblack@eecs.umich.edu o << "Write "; 2486376Sgblack@eecs.umich.edu if (p.isReadWrite()) 2496376Sgblack@eecs.umich.edu o << "Read/Write "; 2506376Sgblack@eecs.umich.edu if (p.isInvalidate()) 2516376Sgblack@eecs.umich.edu o << "Invalidate "; 2526376Sgblack@eecs.umich.edu if (p.isRequest()) 2536376Sgblack@eecs.umich.edu o << "Request "; 2546383Sgblack@eecs.umich.edu if (p.isResponse()) 2556334Sgblack@eecs.umich.edu o << "Response "; 2566334Sgblack@eecs.umich.edu if (p.hasData()) 2576376Sgblack@eecs.umich.edu o << "w/Data "; 2586383Sgblack@eecs.umich.edu 2596334Sgblack@eecs.umich.edu o << std::endl; 2606334Sgblack@eecs.umich.edu return o; 2616383Sgblack@eecs.umich.edu} 2626376Sgblack@eecs.umich.edu 2636376Sgblack@eecs.umich.edu