packet.cc revision 11793
11689SN/A/* 22329SN/A * Copyright (c) 2011-2016 ARM Limited 31689SN/A * All rights reserved 41689SN/A * 51689SN/A * The license below extends only to copyright in the software and shall 61689SN/A * not be construed as granting a license to any other intellectual 71689SN/A * property including but not limited to intellectual property relating 81689SN/A * to a hardware implementation of the functionality of the software 91689SN/A * licensed hereunder. You may use the software subject to the license 101689SN/A * terms below provided that you ensure that this notice is replicated 111689SN/A * unmodified and in its entirety in all distributions of the software, 121689SN/A * modified or unmodified, in source code or in binary form. 131689SN/A * 141689SN/A * Copyright (c) 2006 The Regents of The University of Michigan 151689SN/A * Copyright (c) 2010,2015 Advanced Micro Devices, Inc. 161689SN/A * All rights reserved. 171689SN/A * 181689SN/A * Redistribution and use in source and binary forms, with or without 191689SN/A * modification, are permitted provided that the following conditions are 201689SN/A * met: redistributions of source code must retain the above copyright 211689SN/A * notice, this list of conditions and the following disclaimer; 221689SN/A * redistributions in binary form must reproduce the above copyright 231689SN/A * notice, this list of conditions and the following disclaimer in the 241689SN/A * documentation and/or other materials provided with the distribution; 251689SN/A * neither the name of the copyright holders nor the names of its 261689SN/A * contributors may be used to endorse or promote products derived from 272665Ssaidi@eecs.umich.edu * this software without specific prior written permission. 282665Ssaidi@eecs.umich.edu * 291689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 301689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 311060SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 321060SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 331858SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 341717SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 351060SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 362292SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 372292SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 381061SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 392292SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 402292SN/A * 412292SN/A * Authors: Ali Saidi 422292SN/A * Steve Reinhardt 432292SN/A */ 442292SN/A 452292SN/A/** 461060SN/A * @file 472292SN/A * Definition of the Packet Class, a packet is a transaction occuring 482292SN/A * between a single level of the memory heirarchy (ie L1->L2). 492292SN/A */ 502292SN/A 512292SN/A#include "mem/packet.hh" 522292SN/A 532292SN/A#include <cstring> 542292SN/A#include <iostream> 552292SN/A 562292SN/A#include "base/cprintf.hh" 572292SN/A#include "base/misc.hh" 582301SN/A#include "base/trace.hh" 592292SN/A 602292SN/Ausing namespace std; 612292SN/A 622292SN/A// The one downside to bitsets is that static initializers can get ugly. 632292SN/A#define SET1(a1) (1 << (a1)) 642292SN/A#define SET2(a1, a2) (SET1(a1) | SET1(a2)) 652292SN/A#define SET3(a1, a2, a3) (SET2(a1, a2) | SET1(a3)) 662292SN/A#define SET4(a1, a2, a3, a4) (SET3(a1, a2, a3) | SET1(a4)) 672292SN/A#define SET5(a1, a2, a3, a4, a5) (SET4(a1, a2, a3, a4) | SET1(a5)) 682292SN/A#define SET6(a1, a2, a3, a4, a5, a6) (SET5(a1, a2, a3, a4, a5) | SET1(a6)) 692292SN/A#define SET7(a1, a2, a3, a4, a5, a6, a7) (SET6(a1, a2, a3, a4, a5, a6) | \ 702292SN/A SET1(a7)) 712292SN/A 722292SN/Aconst MemCmd::CommandInfo 732292SN/AMemCmd::commandInfo[] = 742292SN/A{ 752292SN/A /* InvalidCmd */ 761060SN/A { 0, InvalidCmd, "InvalidCmd" }, 771060SN/A /* ReadReq - Read issued by a non-caching agent such as a CPU or 781061SN/A * device, with no restrictions on alignment. */ 791060SN/A { SET3(IsRead, IsRequest, NeedsResponse), ReadResp, "ReadReq" }, 802292SN/A /* ReadResp */ 811062SN/A { SET3(IsRead, IsResponse, HasData), InvalidCmd, "ReadResp" }, 821062SN/A /* ReadRespWithInvalidate */ 832301SN/A { SET4(IsRead, IsResponse, HasData, IsInvalidate), 841062SN/A InvalidCmd, "ReadRespWithInvalidate" }, 851062SN/A /* WriteReq */ 861062SN/A { SET5(IsWrite, NeedsWritable, IsRequest, NeedsResponse, HasData), 872301SN/A WriteResp, "WriteReq" }, 881062SN/A /* WriteResp */ 891062SN/A { SET2(IsWrite, IsResponse), InvalidCmd, "WriteResp" }, 901062SN/A /* WritebackDirty */ 912301SN/A { SET5(IsWrite, IsRequest, IsEviction, HasData, FromCache), 921062SN/A InvalidCmd, "WritebackDirty" }, 931062SN/A /* WritebackClean - This allows the upstream cache to writeback a 942301SN/A * line to the downstream cache without it being considered 952301SN/A * dirty. */ 962301SN/A { SET5(IsWrite, IsRequest, IsEviction, HasData, FromCache), 972301SN/A InvalidCmd, "WritebackClean" }, 982292SN/A /* CleanEvict */ 992301SN/A { SET3(IsRequest, IsEviction, FromCache), InvalidCmd, "CleanEvict" }, 1002292SN/A /* SoftPFReq */ 1012292SN/A { SET4(IsRead, IsRequest, IsSWPrefetch, NeedsResponse), 1021062SN/A SoftPFResp, "SoftPFReq" }, 1032301SN/A /* HardPFReq */ 1041062SN/A { SET5(IsRead, IsRequest, IsHWPrefetch, NeedsResponse, FromCache), 1051062SN/A HardPFResp, "HardPFReq" }, 1061062SN/A /* SoftPFResp */ 1072301SN/A { SET4(IsRead, IsResponse, IsSWPrefetch, HasData), 1081062SN/A InvalidCmd, "SoftPFResp" }, 1091062SN/A /* HardPFResp */ 1101062SN/A { SET4(IsRead, IsResponse, IsHWPrefetch, HasData), 1112301SN/A InvalidCmd, "HardPFResp" }, 1121062SN/A /* WriteLineReq */ 1131062SN/A { SET5(IsWrite, NeedsWritable, IsRequest, NeedsResponse, HasData), 1141062SN/A WriteResp, "WriteLineReq" }, 1152301SN/A /* UpgradeReq */ 1162292SN/A { SET6(IsInvalidate, NeedsWritable, IsUpgrade, IsRequest, NeedsResponse, 1171062SN/A FromCache), 1181062SN/A UpgradeResp, "UpgradeReq" }, 1192301SN/A /* SCUpgradeReq: response could be UpgradeResp or UpgradeFailResp */ 1202292SN/A { SET7(IsInvalidate, NeedsWritable, IsUpgrade, IsLlsc, 1211062SN/A IsRequest, NeedsResponse, FromCache), 1222292SN/A UpgradeResp, "SCUpgradeReq" }, 1232301SN/A /* UpgradeResp */ 1242292SN/A { SET2(IsUpgrade, IsResponse), 1252292SN/A InvalidCmd, "UpgradeResp" }, 1261062SN/A /* SCUpgradeFailReq: generates UpgradeFailResp but still gets the data */ 1272301SN/A { SET7(IsRead, NeedsWritable, IsInvalidate, 1281062SN/A IsLlsc, IsRequest, NeedsResponse, FromCache), 1291062SN/A UpgradeFailResp, "SCUpgradeFailReq" }, 1301062SN/A /* UpgradeFailResp - Behaves like a ReadExReq, but notifies an SC 1312301SN/A * that it has failed, acquires line as Dirty*/ 1321062SN/A { SET3(IsRead, IsResponse, HasData), 1331062SN/A InvalidCmd, "UpgradeFailResp" }, 1341062SN/A /* ReadExReq - Read issues by a cache, always cache-line aligned, 1352301SN/A * and the response is guaranteed to be writeable (exclusive or 1361062SN/A * even modified) */ 1371062SN/A { SET6(IsRead, NeedsWritable, IsInvalidate, IsRequest, NeedsResponse, 1381062SN/A FromCache), 1392301SN/A ReadExResp, "ReadExReq" }, 1401062SN/A /* ReadExResp - Response matching a read exclusive, as we check 1411062SN/A * the need for exclusive also on responses */ 1421062SN/A { SET3(IsRead, IsResponse, HasData), 1432301SN/A InvalidCmd, "ReadExResp" }, 1441062SN/A /* ReadCleanReq - Read issued by a cache, always cache-line 1451062SN/A * aligned, and the response is guaranteed to not contain dirty data 1462301SN/A * (exclusive or shared).*/ 1472301SN/A { SET4(IsRead, IsRequest, NeedsResponse, FromCache), 1482301SN/A ReadResp, "ReadCleanReq" }, 1492301SN/A /* ReadSharedReq - Read issued by a cache, always cache-line 1502301SN/A * aligned, response is shared, possibly exclusive, owned or even 1512301SN/A * modified. */ 1522301SN/A { SET4(IsRead, IsRequest, NeedsResponse, FromCache), 1532301SN/A ReadResp, "ReadSharedReq" }, 1542301SN/A /* LoadLockedReq: note that we use plain ReadResp as response, so that 1552301SN/A * we can also use ReadRespWithInvalidate when needed */ 1562307SN/A { SET4(IsRead, IsLlsc, IsRequest, NeedsResponse), 1572307SN/A ReadResp, "LoadLockedReq" }, 1582307SN/A /* StoreCondReq */ 1592307SN/A { SET6(IsWrite, NeedsWritable, IsLlsc, 1602307SN/A IsRequest, NeedsResponse, HasData), 1611062SN/A StoreCondResp, "StoreCondReq" }, 1621062SN/A /* StoreCondFailReq: generates failing StoreCondResp */ 1631062SN/A { SET6(IsWrite, NeedsWritable, IsLlsc, 1641062SN/A IsRequest, NeedsResponse, HasData), 1652733Sktlim@umich.edu StoreCondResp, "StoreCondFailReq" }, 1661060SN/A /* StoreCondResp */ 1672292SN/A { SET3(IsWrite, IsLlsc, IsResponse), 1681060SN/A InvalidCmd, "StoreCondResp" }, 1691060SN/A /* SwapReq -- for Swap ldstub type operations */ 1701060SN/A { SET6(IsRead, IsWrite, NeedsWritable, IsRequest, HasData, NeedsResponse), 1711061SN/A SwapResp, "SwapReq" }, 1721060SN/A /* SwapResp -- for Swap ldstub type operations */ 1732292SN/A { SET4(IsRead, IsWrite, IsResponse, HasData), 1741060SN/A InvalidCmd, "SwapResp" }, 1752292SN/A /* IntReq -- for interrupts */ 1761060SN/A { SET4(IsWrite, IsRequest, NeedsResponse, HasData), 1771060SN/A MessageResp, "MessageReq" }, 1781060SN/A /* IntResp -- for interrupts */ 1791060SN/A { SET2(IsWrite, IsResponse), InvalidCmd, "MessageResp" }, 1801060SN/A /* MemFenceReq -- for synchronization requests */ 1811060SN/A {SET2(IsRequest, NeedsResponse), MemFenceResp, "MemFenceReq"}, 1821060SN/A /* MemFenceResp -- for synchronization responses */ 1831060SN/A {SET1(IsResponse), InvalidCmd, "MemFenceResp"}, 1841060SN/A /* InvalidDestError -- packet dest field invalid */ 1851060SN/A { SET2(IsResponse, IsError), InvalidCmd, "InvalidDestError" }, 1861060SN/A /* BadAddressError -- memory address invalid */ 1871060SN/A { SET2(IsResponse, IsError), InvalidCmd, "BadAddressError" }, 1881061SN/A /* FunctionalReadError */ 1891060SN/A { SET3(IsRead, IsResponse, IsError), InvalidCmd, "FunctionalReadError" }, 1902292SN/A /* FunctionalWriteError */ 1911060SN/A { SET3(IsWrite, IsResponse, IsError), InvalidCmd, "FunctionalWriteError" }, 1922292SN/A /* PrintReq */ 1931060SN/A { SET2(IsRequest, IsPrint), InvalidCmd, "PrintReq" }, 1941060SN/A /* Flush Request */ 1951060SN/A { SET3(IsRequest, IsFlush, NeedsWritable), InvalidCmd, "FlushReq" }, 1961060SN/A /* Invalidation Request */ 1971060SN/A { SET5(IsInvalidate, IsRequest, NeedsWritable, NeedsResponse, FromCache), 1981060SN/A InvalidateResp, "InvalidateReq" }, 1991061SN/A /* Invalidation Response */ 2001060SN/A { SET2(IsInvalidate, IsResponse), 2012292SN/A InvalidCmd, "InvalidateResp" } 2021060SN/A}; 2032292SN/A 2041060SN/Abool 2051060SN/APacket::checkFunctional(Printable *obj, Addr addr, bool is_secure, int size, 2061060SN/A uint8_t *_data) 2071060SN/A{ 2081060SN/A Addr func_start = getAddr(); 2091060SN/A Addr func_end = getAddr() + getSize() - 1; 2101061SN/A Addr val_start = addr; 2111060SN/A Addr val_end = val_start + size - 1; 2122292SN/A 2131060SN/A if (is_secure != _isSecure || func_start > val_end || 2142329SN/A val_start > func_end) { 2152292SN/A // no intersection 2162292SN/A return false; 2172292SN/A } 2182292SN/A 2192292SN/A // check print first since it doesn't require data 2202292SN/A if (isPrint()) { 2211060SN/A assert(!_data); 2221060SN/A safe_cast<PrintReqState*>(senderState)->printObj(obj); 2232292SN/A return false; 2242292SN/A } 2252292SN/A 2262292SN/A // we allow the caller to pass NULL to signify the other packet 2272292SN/A // has no data 2282292SN/A if (!_data) { 2292292SN/A return false; 2302292SN/A } 2312292SN/A 2321061SN/A // offset of functional request into supplied value (could be 2331060SN/A // negative if partial overlap) 2342292SN/A int offset = func_start - val_start; 2351060SN/A 2362292SN/A if (isRead()) { 2371060SN/A if (func_start >= val_start && func_end <= val_end) { 2382292SN/A memcpy(getPtr<uint8_t>(), _data + offset, getSize()); 2392292SN/A if (bytesValid.empty()) 2401060SN/A bytesValid.resize(getSize(), true); 2411060SN/A // complete overlap, and as the current packet is a read 2421060SN/A // we are done 2431061SN/A return true; 2441060SN/A } else { 2452292SN/A // Offsets and sizes to copy in case of partial overlap 2461060SN/A int func_offset; 2472292SN/A int val_offset; 2482292SN/A int overlap_size; 2492292SN/A 2501060SN/A // calculate offsets and copy sizes for the two byte arrays 2512292SN/A if (val_start < func_start && val_end <= func_end) { 2522292SN/A // the one we are checking against starts before and 2532292SN/A // ends before or the same 2542292SN/A val_offset = func_start - val_start; 2552292SN/A func_offset = 0; 2562292SN/A overlap_size = val_end - func_start; 2571060SN/A } else if (val_start >= func_start && val_end > func_end) { 2581060SN/A // the one we are checking against starts after or the 2591061SN/A // same, and ends after 2602863Sktlim@umich.edu val_offset = 0; 2612843Sktlim@umich.edu func_offset = val_start - func_start; 2621060SN/A overlap_size = func_end - val_start; 2632348SN/A } else if (val_start >= func_start && val_end <= func_end) { 2642843Sktlim@umich.edu // the one we are checking against is completely 2652863Sktlim@umich.edu // subsumed in the current packet, possibly starting 2662316SN/A // and ending at the same address 2671060SN/A val_offset = 0; 2682316SN/A func_offset = val_start - func_start; 2692316SN/A overlap_size = size; 2702843Sktlim@umich.edu } else if (val_start < func_start && val_end > func_end) { 2712316SN/A // the current packet is completely subsumed in the 2722348SN/A // one we are checking against 2732307SN/A val_offset = func_start - val_start; 2742307SN/A func_offset = 0; 2752307SN/A overlap_size = func_end - func_start; 2762307SN/A } else { 2772307SN/A panic("Missed a case for checkFunctional with " 2782307SN/A " %s 0x%x size %d, against 0x%x size %d\n", 2792307SN/A cmdString(), getAddr(), getSize(), addr, size); 2802307SN/A } 2812307SN/A 2822307SN/A // copy partial data into the packet's data array 2832307SN/A uint8_t *dest = getPtr<uint8_t>() + func_offset; 2842307SN/A uint8_t *src = _data + val_offset; 2852307SN/A memcpy(dest, src, overlap_size); 2862307SN/A 2872307SN/A // initialise the tracking of valid bytes if we have not 2882307SN/A // used it already 2892307SN/A if (bytesValid.empty()) 2902307SN/A bytesValid.resize(getSize(), false); 2912307SN/A 2922307SN/A // track if we are done filling the functional access 2931060SN/A bool all_bytes_valid = true; 2941060SN/A 2951060SN/A int i = 0; 2961061SN/A 2971060SN/A // check up to func_offset 2982307SN/A for (; all_bytes_valid && i < func_offset; ++i) 2991060SN/A all_bytes_valid &= bytesValid[i]; 3002307SN/A 3012307SN/A // update the valid bytes 3021060SN/A for (i = func_offset; i < func_offset + overlap_size; ++i) 3032329SN/A bytesValid[i] = true; 3042307SN/A 3052307SN/A // check the bit after the update we just made 3061060SN/A for (; all_bytes_valid && i < getSize(); ++i) 3072307SN/A all_bytes_valid &= bytesValid[i]; 3082307SN/A 3092307SN/A return all_bytes_valid; 3102307SN/A } 3112307SN/A } else if (isWrite()) { 3122307SN/A if (offset >= 0) { 3132307SN/A memcpy(_data + offset, getConstPtr<uint8_t>(), 3142307SN/A (min(func_end, val_end) - func_start) + 1); 3152307SN/A } else { 3162307SN/A // val_start > func_start 3172307SN/A memcpy(_data, getConstPtr<uint8_t>() - offset, 3182307SN/A (min(func_end, val_end) - val_start) + 1); 3192307SN/A } 3202307SN/A } else { 3212292SN/A panic("Don't know how to handle command %s\n", cmdString()); 3221858SN/A } 3232292SN/A 3241858SN/A // keep going with request by default 3252292SN/A return false; 3262292SN/A} 3272292SN/A 3282292SN/Avoid 3292292SN/APacket::pushSenderState(Packet::SenderState *sender_state) 3302301SN/A{ 3312698Sktlim@umich.edu assert(sender_state != NULL); 3322292SN/A sender_state->predecessor = senderState; 3332698Sktlim@umich.edu senderState = sender_state; 3342301SN/A} 3352292SN/A 3362292SN/APacket::SenderState * 3372292SN/APacket::popSenderState() 3382292SN/A{ 3392292SN/A assert(senderState != NULL); 3402329SN/A SenderState *sender_state = senderState; 3412292SN/A senderState = sender_state->predecessor; 3422292SN/A sender_state->predecessor = NULL; 3432292SN/A return sender_state; 3442292SN/A} 3452731Sktlim@umich.edu 3462292SN/Avoid 3472292SN/APacket::print(ostream &o, const int verbosity, const string &prefix) const 3482292SN/A{ 3492292SN/A ccprintf(o, "%s%s [%x:%x]%s%s%s%s", prefix, cmdString(), 3502292SN/A getAddr(), getAddr() + getSize() - 1, 3512292SN/A req->isSecure() ? " (s)" : "", 3522292SN/A req->isInstFetch() ? " IF" : "", 3532292SN/A req->isUncacheable() ? " UC" : "", 3542292SN/A isExpressSnoop() ? " ES" : ""); 3552292SN/A} 3562292SN/A 3572292SN/Astd::string 3582292SN/APacket::print() const { 3592292SN/A ostringstream str; 3602292SN/A print(str); 3612292SN/A return str.str(); 3622292SN/A} 3632292SN/A 3642292SN/APacket::PrintReqState::PrintReqState(ostream &_os, int _verbosity) 3652292SN/A : curPrefixPtr(new string("")), os(_os), verbosity(_verbosity) 3662292SN/A{ 3672292SN/A labelStack.push_back(LabelStackEntry("", curPrefixPtr)); 3682292SN/A} 3692292SN/A 3702292SN/APacket::PrintReqState::~PrintReqState() 3712292SN/A{ 3722292SN/A labelStack.pop_back(); 3732292SN/A assert(labelStack.empty()); 3742292SN/A delete curPrefixPtr; 3752292SN/A} 3762292SN/A 3772292SN/APacket::PrintReqState:: 3782292SN/ALabelStackEntry::LabelStackEntry(const string &_label, string *_prefix) 3792292SN/A : label(_label), prefix(_prefix), labelPrinted(false) 3802292SN/A{ 3812292SN/A} 3822292SN/A 3832292SN/Avoid 3842292SN/APacket::PrintReqState::pushLabel(const string &lbl, const string &prefix) 3852292SN/A{ 3862292SN/A labelStack.push_back(LabelStackEntry(lbl, curPrefixPtr)); 3872292SN/A curPrefixPtr = new string(*curPrefixPtr); 3882292SN/A *curPrefixPtr += prefix; 3892292SN/A} 3902292SN/A 3912292SN/Avoid 3922292SN/APacket::PrintReqState::popLabel() 3932292SN/A{ 3942292SN/A delete curPrefixPtr; 3952292SN/A curPrefixPtr = labelStack.back().prefix; 3962292SN/A labelStack.pop_back(); 3972292SN/A assert(!labelStack.empty()); 3982292SN/A} 3992292SN/A 4002292SN/Avoid 4012292SN/APacket::PrintReqState::printLabels() 4022292SN/A{ 4032292SN/A if (!labelStack.back().labelPrinted) { 4042292SN/A LabelStack::iterator i = labelStack.begin(); 4052292SN/A LabelStack::iterator end = labelStack.end(); 4062292SN/A while (i != end) { 4072292SN/A if (!i->labelPrinted) { 4082292SN/A ccprintf(os, "%s%s\n", *(i->prefix), i->label); 4092292SN/A i->labelPrinted = true; 4102292SN/A } 4112292SN/A i++; 4122292SN/A } 4132292SN/A } 4142292SN/A} 4152292SN/A 4162292SN/A 4172292SN/Avoid 4182292SN/APacket::PrintReqState::printObj(Printable *obj) 4192292SN/A{ 4202292SN/A printLabels(); 4212292SN/A obj->print(os, verbosity, curPrefix()); 4222292SN/A} 4232292SN/A