packet.cc
来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· CC 代码 · 共 296 行
CC
296 行
/* * Copyright (c) 2006 * The Regents of The University of Michigan * All Rights Reserved * * This code is part of the M5 simulator. * * Permission is granted to use, copy, create derivative works and * redistribute this software and such derivative works for any * purpose, so long as the copyright notice above, this grant of * permission, and the disclaimer below appear in all copies made; and * so long as the name of The University of Michigan is not used in * any advertising or publicity pertaining to the use or distribution * of this software without specific, written prior authorization. * * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT, * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH * DAMAGES. * * Authors: Ali G. Saidi * Steven K. Reinhardt *//** * @file * Definition of the Packet Class, a packet is a transaction occuring * between a single level of the memory heirarchy (ie L1->L2). */#include <iostream>#include <cstring>#include "base/cprintf.hh"#include "base/misc.hh"#include "base/trace.hh"#include "mem/packet.hh"// The one downside to bitsets is that static initializers can get ugly.#define SET1(a1) (1 << (a1))#define SET2(a1, a2) (SET1(a1) | SET1(a2))#define SET3(a1, a2, a3) (SET2(a1, a2) | SET1(a3))#define SET4(a1, a2, a3, a4) (SET3(a1, a2, a3) | SET1(a4))#define SET5(a1, a2, a3, a4, a5) (SET4(a1, a2, a3, a4) | SET1(a5))#define SET6(a1, a2, a3, a4, a5, a6) (SET5(a1, a2, a3, a4, a5) | SET1(a6))const MemCmd::CommandInfoMemCmd::commandInfo[] ={ /* InvalidCmd */ { 0, InvalidCmd, "InvalidCmd" }, /* ReadReq */ { SET3(IsRead, IsRequest, NeedsResponse), ReadResp, "ReadReq" }, /* ReadResp */ { SET3(IsRead, IsResponse, HasData), InvalidCmd, "ReadResp" }, /* ReadRespWithInvalidate */ { SET4(IsRead, IsResponse, HasData, IsInvalidate), InvalidCmd, "ReadRespWithInvalidate" }, /* WriteReq */ { SET5(IsWrite, NeedsExclusive, IsRequest, NeedsResponse, HasData), WriteResp, "WriteReq" }, /* WriteResp */ { SET3(IsWrite, NeedsExclusive, IsResponse), InvalidCmd, "WriteResp" }, /* Writeback */ { SET4(IsWrite, NeedsExclusive, IsRequest, HasData), InvalidCmd, "Writeback" }, /* SoftPFReq */ { SET4(IsRead, IsRequest, IsSWPrefetch, NeedsResponse), SoftPFResp, "SoftPFReq" }, /* HardPFReq */ { SET4(IsRead, IsRequest, IsHWPrefetch, NeedsResponse), HardPFResp, "HardPFReq" }, /* SoftPFResp */ { SET4(IsRead, IsResponse, IsSWPrefetch, HasData), InvalidCmd, "SoftPFResp" }, /* HardPFResp */ { SET4(IsRead, IsResponse, IsHWPrefetch, HasData), InvalidCmd, "HardPFResp" }, /* WriteInvalidateReq */ { SET6(IsWrite, NeedsExclusive, IsInvalidate, IsRequest, HasData, NeedsResponse), WriteInvalidateResp, "WriteInvalidateReq" }, /* WriteInvalidateResp */ { SET3(IsWrite, NeedsExclusive, IsResponse), InvalidCmd, "WriteInvalidateResp" }, /* UpgradeReq */ { SET4(IsInvalidate, NeedsExclusive, IsRequest, NeedsResponse), UpgradeResp, "UpgradeReq" }, /* UpgradeResp */ { SET2(NeedsExclusive, IsResponse), InvalidCmd, "UpgradeResp" }, /* ReadExReq */ { SET5(IsRead, NeedsExclusive, IsInvalidate, IsRequest, NeedsResponse), ReadExResp, "ReadExReq" }, /* ReadExResp */ { SET4(IsRead, NeedsExclusive, IsResponse, HasData), InvalidCmd, "ReadExResp" }, /* LoadLockedReq */ { SET4(IsRead, IsLocked, IsRequest, NeedsResponse), LoadLockedResp, "LoadLockedReq" }, /* LoadLockedResp */ { SET4(IsRead, IsLocked, IsResponse, HasData), InvalidCmd, "LoadLockedResp" }, /* StoreCondReq */ { SET6(IsWrite, NeedsExclusive, IsLocked, IsRequest, NeedsResponse, HasData), StoreCondResp, "StoreCondReq" }, /* StoreCondResp */ { SET4(IsWrite, NeedsExclusive, IsLocked, IsResponse), InvalidCmd, "StoreCondResp" }, /* SwapReq -- for Swap ldstub type operations */ { SET6(IsRead, IsWrite, NeedsExclusive, IsRequest, HasData, NeedsResponse), SwapResp, "SwapReq" }, /* SwapResp -- for Swap ldstub type operations */ { SET5(IsRead, IsWrite, NeedsExclusive, IsResponse, HasData), InvalidCmd, "SwapResp" }, /* NetworkNackError -- nacked at network layer (not by protocol) */ { SET2(IsResponse, IsError), InvalidCmd, "NetworkNackError" }, /* InvalidDestError -- packet dest field invalid */ { SET2(IsResponse, IsError), InvalidCmd, "InvalidDestError" }, /* BadAddressError -- memory address invalid */ { SET2(IsResponse, IsError), InvalidCmd, "BadAddressError" }, /* PrintReq */ { SET2(IsRequest, IsPrint), InvalidCmd, "PrintReq" }};/** delete the data pointed to in the data pointer. Ok to call to matter how * data was allocted. */voidPacket::deleteData(){ assert(staticData || dynamicData); if (staticData) return; if (arrayData) delete [] data; else delete data;}/** If there isn't data in the packet, allocate some. */voidPacket::allocate(){ if (data) return; assert(!staticData); dynamicData = true; arrayData = true; data = new uint8_t[getSize()];}boolPacket::checkFunctional(Printable *obj, Addr addr, int size, uint8_t *data){ Addr func_start = getAddr(); Addr func_end = getAddr() + getSize() - 1; Addr val_start = addr; Addr val_end = val_start + size - 1; if (func_start > val_end || val_start > func_end) { // no intersection return false; } // check print first since it doesn't require data if (isPrint()) { dynamic_cast<PrintReqState*>(senderState)->printObj(obj); return false; } // if there's no data, there's no need to look further if (!data) { return false; } // offset of functional request into supplied value (could be // negative if partial overlap) int offset = func_start - val_start; if (isRead()) { if (func_start >= val_start && func_end <= val_end) { allocate(); std::memcpy(getPtr<uint8_t>(), data + offset, getSize()); makeResponse(); return true; } else { // In this case the timing packet only partially satisfies // the request, so we would need more information to make // this work. Like bytes valid in the packet or // something, so the request could continue and get this // bit of possibly newer data along with the older data // not written to yet. panic("Memory value only partially satisfies the functional " "request. Now what?"); } } else if (isWrite()) { if (offset >= 0) { std::memcpy(data + offset, getPtr<uint8_t>(), (std::min(func_end, val_end) - func_start) + 1); } else { // val_start > func_start std::memcpy(data, getPtr<uint8_t>() - offset, (std::min(func_end, val_end) - val_start) + 1); } } else { panic("Don't know how to handle command %s\n", cmdString()); } // keep going with request by default return false;}voidPacket::print(std::ostream &o, const int verbosity, const std::string &prefix) const{ ccprintf(o, "%s[%x:%x] %s\n", prefix, getAddr(), getAddr() + getSize() - 1, cmdString());}Packet::PrintReqState::PrintReqState(std::ostream &_os, int _verbosity) : curPrefixPtr(new std::string("")), os(_os), verbosity(_verbosity){ labelStack.push_back(LabelStackEntry("", curPrefixPtr));}Packet::PrintReqState::~PrintReqState(){ labelStack.pop_back(); assert(labelStack.empty()); delete curPrefixPtr;}Packet::PrintReqState::LabelStackEntry::LabelStackEntry(const std::string &_label, std::string *_prefix) : label(_label), prefix(_prefix), labelPrinted(false){}voidPacket::PrintReqState::pushLabel(const std::string &lbl, const std::string &prefix){ labelStack.push_back(LabelStackEntry(lbl, curPrefixPtr)); curPrefixPtr = new std::string(*curPrefixPtr); *curPrefixPtr += prefix;}voidPacket::PrintReqState::popLabel(){ delete curPrefixPtr; curPrefixPtr = labelStack.back().prefix; labelStack.pop_back(); assert(!labelStack.empty());}voidPacket::PrintReqState::printLabels(){ if (!labelStack.back().labelPrinted) { LabelStack::iterator i = labelStack.begin(); LabelStack::iterator end = labelStack.end(); while (i != end) { if (!i->labelPrinted) { ccprintf(os, "%s%s\n", *(i->prefix), i->label); i->labelPrinted = true; } i++; } }}voidPacket::PrintReqState::printObj(Printable *obj){ printLabels(); obj->print(os, verbosity, curPrefix());}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?