packet.cc revision 7636
17934SN/A/* 27934SN/A * Copyright (c) 2006 The Regents of The University of Michigan 311960Sgabeblack@google.com * Copyright (c) 2010 Advanced Micro Devices, Inc. 411960Sgabeblack@google.com * All rights reserved. 511960Sgabeblack@google.com * 611960Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without 711960Sgabeblack@google.com * modification, are permitted provided that the following conditions are 811960Sgabeblack@google.com * met: redistributions of source code must retain the above copyright 911960Sgabeblack@google.com * notice, this list of conditions and the following disclaimer; 1011960Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright 1111960Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the 1211960Sgabeblack@google.com * documentation and/or other materials provided with the distribution; 1311960Sgabeblack@google.com * neither the name of the copyright holders nor the names of its 1411960Sgabeblack@google.com * contributors may be used to endorse or promote products derived from 1511960Sgabeblack@google.com * this software without specific prior written permission. 1611960Sgabeblack@google.com * 1711960Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1811960Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1911960Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2011960Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2111960Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2211960Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2311960Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2411960Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2511960Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2611960Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2711960Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2811960Sgabeblack@google.com * 2911960Sgabeblack@google.com * Authors: Ali Saidi 3011960Sgabeblack@google.com * Steve Reinhardt 3111960Sgabeblack@google.com */ 3211960Sgabeblack@google.com 3311960Sgabeblack@google.com/** 3411960Sgabeblack@google.com * @file 3511960Sgabeblack@google.com * Definition of the Packet Class, a packet is a transaction occuring 3611960Sgabeblack@google.com * between a single level of the memory heirarchy (ie L1->L2). 3711960Sgabeblack@google.com */ 3811960Sgabeblack@google.com 3911960Sgabeblack@google.com#include <iostream> 4011960Sgabeblack@google.com#include <cstring> 4111960Sgabeblack@google.com#include "base/cprintf.hh" 4211960Sgabeblack@google.com#include "base/misc.hh" 4311960Sgabeblack@google.com#include "base/trace.hh" 4411960Sgabeblack@google.com#include "mem/packet.hh" 4511960Sgabeblack@google.com 4611960Sgabeblack@google.comusing namespace std; 4711960Sgabeblack@google.com 4811960Sgabeblack@google.com// The one downside to bitsets is that static initializers can get ugly. 4911960Sgabeblack@google.com#define SET1(a1) (1 << (a1)) 5011960Sgabeblack@google.com#define SET2(a1, a2) (SET1(a1) | SET1(a2)) 5111960Sgabeblack@google.com#define SET3(a1, a2, a3) (SET2(a1, a2) | SET1(a3)) 5211960Sgabeblack@google.com#define SET4(a1, a2, a3, a4) (SET3(a1, a2, a3) | SET1(a4)) 5311960Sgabeblack@google.com#define SET5(a1, a2, a3, a4, a5) (SET4(a1, a2, a3, a4) | SET1(a5)) 5411960Sgabeblack@google.com#define SET6(a1, a2, a3, a4, a5, a6) (SET5(a1, a2, a3, a4, a5) | SET1(a6)) 5511960Sgabeblack@google.com 5611960Sgabeblack@google.comconst MemCmd::CommandInfo 5711960Sgabeblack@google.comMemCmd::commandInfo[] = 5811960Sgabeblack@google.com{ 5911960Sgabeblack@google.com /* InvalidCmd */ 6011960Sgabeblack@google.com { 0, InvalidCmd, "InvalidCmd" }, 6111960Sgabeblack@google.com /* ReadReq */ 6211960Sgabeblack@google.com { SET3(IsRead, IsRequest, NeedsResponse), ReadResp, "ReadReq" }, 6311960Sgabeblack@google.com /* ReadResp */ 6411960Sgabeblack@google.com { SET3(IsRead, IsResponse, HasData), InvalidCmd, "ReadResp" }, 6511960Sgabeblack@google.com /* ReadRespWithInvalidate */ 6611960Sgabeblack@google.com { SET4(IsRead, IsResponse, HasData, IsInvalidate), 6711960Sgabeblack@google.com InvalidCmd, "ReadRespWithInvalidate" }, 6811960Sgabeblack@google.com /* WriteReq */ 6911960Sgabeblack@google.com { SET5(IsWrite, NeedsExclusive, IsRequest, NeedsResponse, HasData), 7011960Sgabeblack@google.com WriteResp, "WriteReq" }, 7111960Sgabeblack@google.com /* WriteResp */ 7211960Sgabeblack@google.com { SET3(IsWrite, NeedsExclusive, IsResponse), InvalidCmd, "WriteResp" }, 7311960Sgabeblack@google.com /* Writeback */ 7411960Sgabeblack@google.com { SET4(IsWrite, NeedsExclusive, IsRequest, HasData), 7511960Sgabeblack@google.com InvalidCmd, "Writeback" }, 7611960Sgabeblack@google.com /* SoftPFReq */ 7711960Sgabeblack@google.com { SET4(IsRead, IsRequest, IsSWPrefetch, NeedsResponse), 7811960Sgabeblack@google.com SoftPFResp, "SoftPFReq" }, 7911960Sgabeblack@google.com /* HardPFReq */ 8011960Sgabeblack@google.com { SET4(IsRead, IsRequest, IsHWPrefetch, NeedsResponse), 8111960Sgabeblack@google.com HardPFResp, "HardPFReq" }, 8211960Sgabeblack@google.com /* SoftPFResp */ 8311960Sgabeblack@google.com { SET4(IsRead, IsResponse, IsSWPrefetch, HasData), 8411960Sgabeblack@google.com InvalidCmd, "SoftPFResp" }, 8511960Sgabeblack@google.com /* HardPFResp */ 8611960Sgabeblack@google.com { SET4(IsRead, IsResponse, IsHWPrefetch, HasData), 8711960Sgabeblack@google.com InvalidCmd, "HardPFResp" }, 8811960Sgabeblack@google.com /* WriteInvalidateReq */ 8911960Sgabeblack@google.com { SET6(IsWrite, NeedsExclusive, IsInvalidate, 9011960Sgabeblack@google.com IsRequest, HasData, NeedsResponse), 9111960Sgabeblack@google.com WriteInvalidateResp, "WriteInvalidateReq" }, 9211960Sgabeblack@google.com /* WriteInvalidateResp */ 9311960Sgabeblack@google.com { SET3(IsWrite, NeedsExclusive, IsResponse), 9411960Sgabeblack@google.com InvalidCmd, "WriteInvalidateResp" }, 9511960Sgabeblack@google.com /* UpgradeReq */ 9611960Sgabeblack@google.com { SET5(IsInvalidate, NeedsExclusive, IsUpgrade, IsRequest, NeedsResponse), 9711960Sgabeblack@google.com UpgradeResp, "UpgradeReq" }, 9811960Sgabeblack@google.com /* SCUpgradeReq: response could be UpgradeResp or UpgradeFailResp */ 9911960Sgabeblack@google.com { SET6(IsInvalidate, NeedsExclusive, IsUpgrade, IsLlsc, 10011960Sgabeblack@google.com IsRequest, NeedsResponse), 10111960Sgabeblack@google.com UpgradeResp, "SCUpgradeReq" }, 10211960Sgabeblack@google.com /* UpgradeResp */ 10311960Sgabeblack@google.com { SET3(NeedsExclusive, IsUpgrade, IsResponse), 10411960Sgabeblack@google.com InvalidCmd, "UpgradeResp" }, 10511960Sgabeblack@google.com /* SCUpgradeFailReq: generates UpgradeFailResp ASAP */ 10611960Sgabeblack@google.com { SET5(IsInvalidate, NeedsExclusive, IsLlsc, 10711960Sgabeblack@google.com IsRequest, NeedsResponse), 10811960Sgabeblack@google.com UpgradeFailResp, "SCUpgradeFailReq" }, 10911960Sgabeblack@google.com /* UpgradeFailResp */ 11011960Sgabeblack@google.com { SET2(NeedsExclusive, IsResponse), 11111960Sgabeblack@google.com InvalidCmd, "UpgradeFailResp" }, 11211960Sgabeblack@google.com /* ReadExReq */ 11311960Sgabeblack@google.com { SET5(IsRead, NeedsExclusive, IsInvalidate, IsRequest, NeedsResponse), 11411960Sgabeblack@google.com ReadExResp, "ReadExReq" }, 11511960Sgabeblack@google.com /* ReadExResp */ 11611960Sgabeblack@google.com { SET4(IsRead, NeedsExclusive, IsResponse, HasData), 11711960Sgabeblack@google.com InvalidCmd, "ReadExResp" }, 11811960Sgabeblack@google.com /* LoadLockedReq: note that we use plain ReadResp as response, so that 11911960Sgabeblack@google.com * we can also use ReadRespWithInvalidate when needed */ 12011960Sgabeblack@google.com { SET4(IsRead, IsLlsc, IsRequest, NeedsResponse), 12111960Sgabeblack@google.com ReadResp, "LoadLockedReq" }, 12211960Sgabeblack@google.com /* StoreCondReq */ 12311960Sgabeblack@google.com { SET6(IsWrite, NeedsExclusive, IsLlsc, 12411960Sgabeblack@google.com IsRequest, NeedsResponse, HasData), 12511960Sgabeblack@google.com StoreCondResp, "StoreCondReq" }, 12611960Sgabeblack@google.com /* StoreCondResp */ 12711960Sgabeblack@google.com { SET4(IsWrite, NeedsExclusive, IsLlsc, IsResponse), 12811960Sgabeblack@google.com InvalidCmd, "StoreCondResp" }, 12911960Sgabeblack@google.com /* SwapReq -- for Swap ldstub type operations */ 13011960Sgabeblack@google.com { SET6(IsRead, IsWrite, NeedsExclusive, IsRequest, HasData, NeedsResponse), 13111960Sgabeblack@google.com SwapResp, "SwapReq" }, 13211960Sgabeblack@google.com /* SwapResp -- for Swap ldstub type operations */ 13311960Sgabeblack@google.com { SET5(IsRead, IsWrite, NeedsExclusive, IsResponse, HasData), 13411960Sgabeblack@google.com InvalidCmd, "SwapResp" }, 13511960Sgabeblack@google.com /* IntReq -- for interrupts */ 13611960Sgabeblack@google.com { SET4(IsWrite, IsRequest, NeedsResponse, HasData), 13711960Sgabeblack@google.com MessageResp, "MessageReq" }, 13811960Sgabeblack@google.com /* IntResp -- for interrupts */ 13911960Sgabeblack@google.com { SET2(IsWrite, IsResponse), InvalidCmd, "MessageResp" }, 14011960Sgabeblack@google.com /* NetworkNackError -- nacked at network layer (not by protocol) */ 14111960Sgabeblack@google.com { SET2(IsResponse, IsError), InvalidCmd, "NetworkNackError" }, 14211960Sgabeblack@google.com /* InvalidDestError -- packet dest field invalid */ 14311960Sgabeblack@google.com { SET2(IsResponse, IsError), InvalidCmd, "InvalidDestError" }, 14411960Sgabeblack@google.com /* BadAddressError -- memory address invalid */ 14511960Sgabeblack@google.com { SET2(IsResponse, IsError), InvalidCmd, "BadAddressError" }, 14611960Sgabeblack@google.com /* PrintReq */ 14711960Sgabeblack@google.com { SET2(IsRequest, IsPrint), InvalidCmd, "PrintReq" } 14811960Sgabeblack@google.com}; 14911960Sgabeblack@google.com 15011960Sgabeblack@google.combool 15111960Sgabeblack@google.comPacket::checkFunctional(Printable *obj, Addr addr, int size, uint8_t *data) 15211960Sgabeblack@google.com{ 15311960Sgabeblack@google.com Addr func_start = getAddr(); 15411960Sgabeblack@google.com Addr func_end = getAddr() + getSize() - 1; 15511960Sgabeblack@google.com Addr val_start = addr; 15611960Sgabeblack@google.com Addr val_end = val_start + size - 1; 15711960Sgabeblack@google.com 15811960Sgabeblack@google.com if (func_start > val_end || val_start > func_end) { 15911960Sgabeblack@google.com // no intersection 16011960Sgabeblack@google.com return false; 16111960Sgabeblack@google.com } 16211960Sgabeblack@google.com 16311960Sgabeblack@google.com // check print first since it doesn't require data 16411960Sgabeblack@google.com if (isPrint()) { 16511960Sgabeblack@google.com dynamic_cast<PrintReqState*>(senderState)->printObj(obj); 16611960Sgabeblack@google.com return false; 16711960Sgabeblack@google.com } 16811960Sgabeblack@google.com 16911960Sgabeblack@google.com // if there's no data, there's no need to look further 17011960Sgabeblack@google.com if (!data) { 17111960Sgabeblack@google.com return false; 17211960Sgabeblack@google.com } 17311960Sgabeblack@google.com 17411960Sgabeblack@google.com // offset of functional request into supplied value (could be 17511960Sgabeblack@google.com // negative if partial overlap) 17611960Sgabeblack@google.com int offset = func_start - val_start; 17711960Sgabeblack@google.com 17811960Sgabeblack@google.com if (isRead()) { 17911960Sgabeblack@google.com if (func_start >= val_start && func_end <= val_end) { 18011960Sgabeblack@google.com allocate(); 18111960Sgabeblack@google.com memcpy(getPtr<uint8_t>(), data + offset, getSize()); 18211960Sgabeblack@google.com makeResponse(); 18311960Sgabeblack@google.com return true; 18411960Sgabeblack@google.com } else { 18511960Sgabeblack@google.com // In this case the timing packet only partially satisfies 18611960Sgabeblack@google.com // the request, so we would need more information to make 18711960Sgabeblack@google.com // this work. Like bytes valid in the packet or 18811960Sgabeblack@google.com // something, so the request could continue and get this 18911960Sgabeblack@google.com // bit of possibly newer data along with the older data 19011960Sgabeblack@google.com // not written to yet. 19111960Sgabeblack@google.com panic("Memory value only partially satisfies the functional " 19211960Sgabeblack@google.com "request. Now what?"); 19311960Sgabeblack@google.com } 19411960Sgabeblack@google.com } else if (isWrite()) { 19511960Sgabeblack@google.com if (offset >= 0) { 19611960Sgabeblack@google.com memcpy(data + offset, getPtr<uint8_t>(), 19711960Sgabeblack@google.com (min(func_end, val_end) - func_start) + 1); 19811960Sgabeblack@google.com } else { 19911960Sgabeblack@google.com // val_start > func_start 20011960Sgabeblack@google.com memcpy(data, getPtr<uint8_t>() - offset, 20111960Sgabeblack@google.com (min(func_end, val_end) - val_start) + 1); 20211960Sgabeblack@google.com } 20311960Sgabeblack@google.com } else { 20411960Sgabeblack@google.com panic("Don't know how to handle command %s\n", cmdString()); 20511960Sgabeblack@google.com } 20611960Sgabeblack@google.com 20711960Sgabeblack@google.com // keep going with request by default 20811960Sgabeblack@google.com return false; 20911960Sgabeblack@google.com} 21011960Sgabeblack@google.com 21111960Sgabeblack@google.comvoid 21211960Sgabeblack@google.comPacket::print(ostream &o, const int verbosity, const string &prefix) const 21311960Sgabeblack@google.com{ 21411960Sgabeblack@google.com ccprintf(o, "%s[%x:%x] %s\n", prefix, 21511960Sgabeblack@google.com getAddr(), getAddr() + getSize() - 1, cmdString()); 21611960Sgabeblack@google.com} 21711960Sgabeblack@google.com 21811960Sgabeblack@google.comPacket::PrintReqState::PrintReqState(ostream &_os, int _verbosity) 21911960Sgabeblack@google.com : curPrefixPtr(new string("")), os(_os), verbosity(_verbosity) 22011960Sgabeblack@google.com{ 22111960Sgabeblack@google.com labelStack.push_back(LabelStackEntry("", curPrefixPtr)); 22211960Sgabeblack@google.com} 22311960Sgabeblack@google.com 22411960Sgabeblack@google.comPacket::PrintReqState::~PrintReqState() 22511960Sgabeblack@google.com{ 22611960Sgabeblack@google.com labelStack.pop_back(); 22711960Sgabeblack@google.com assert(labelStack.empty()); 22811960Sgabeblack@google.com delete curPrefixPtr; 22911960Sgabeblack@google.com} 23011960Sgabeblack@google.com 23111960Sgabeblack@google.comPacket::PrintReqState:: 23211960Sgabeblack@google.comLabelStackEntry::LabelStackEntry(const string &_label, string *_prefix) 23311960Sgabeblack@google.com : label(_label), prefix(_prefix), labelPrinted(false) 23411960Sgabeblack@google.com{ 23511960Sgabeblack@google.com} 23611960Sgabeblack@google.com 23711960Sgabeblack@google.comvoid 23811960Sgabeblack@google.comPacket::PrintReqState::pushLabel(const string &lbl, const string &prefix) 23911960Sgabeblack@google.com{ 24011960Sgabeblack@google.com labelStack.push_back(LabelStackEntry(lbl, curPrefixPtr)); 24111960Sgabeblack@google.com curPrefixPtr = new string(*curPrefixPtr); 24211960Sgabeblack@google.com *curPrefixPtr += prefix; 24311960Sgabeblack@google.com} 24411960Sgabeblack@google.com 24511960Sgabeblack@google.comvoid 24611960Sgabeblack@google.comPacket::PrintReqState::popLabel() 24711960Sgabeblack@google.com{ 24811960Sgabeblack@google.com delete curPrefixPtr; 24911960Sgabeblack@google.com curPrefixPtr = labelStack.back().prefix; 25011960Sgabeblack@google.com labelStack.pop_back(); 25111960Sgabeblack@google.com assert(!labelStack.empty()); 25211960Sgabeblack@google.com} 25311960Sgabeblack@google.com 25411960Sgabeblack@google.comvoid 25511960Sgabeblack@google.comPacket::PrintReqState::printLabels() 25611960Sgabeblack@google.com{ 25711960Sgabeblack@google.com if (!labelStack.back().labelPrinted) { 25811960Sgabeblack@google.com LabelStack::iterator i = labelStack.begin(); 25911960Sgabeblack@google.com LabelStack::iterator end = labelStack.end(); 26011960Sgabeblack@google.com while (i != end) { 26111960Sgabeblack@google.com if (!i->labelPrinted) { 26211960Sgabeblack@google.com ccprintf(os, "%s%s\n", *(i->prefix), i->label); 26311960Sgabeblack@google.com i->labelPrinted = true; 26411960Sgabeblack@google.com } 26511960Sgabeblack@google.com i++; 26611960Sgabeblack@google.com } 26711960Sgabeblack@google.com } 26811960Sgabeblack@google.com} 26911960Sgabeblack@google.com 27011960Sgabeblack@google.com 27111960Sgabeblack@google.comvoid 27211960Sgabeblack@google.comPacket::PrintReqState::printObj(Printable *obj) 27311960Sgabeblack@google.com{ 27411960Sgabeblack@google.com printLabels(); 27511960Sgabeblack@google.com obj->print(os, verbosity, curPrefix()); 27611960Sgabeblack@google.com} 27711960Sgabeblack@google.com