packet.cc revision 11793
15245Sgblack@eecs.umich.edu/* 25245Sgblack@eecs.umich.edu * Copyright (c) 2011-2016 ARM Limited 35245Sgblack@eecs.umich.edu * All rights reserved 45245Sgblack@eecs.umich.edu * 57087Snate@binkert.org * The license below extends only to copyright in the software and shall 67087Snate@binkert.org * not be construed as granting a license to any other intellectual 77087Snate@binkert.org * property including but not limited to intellectual property relating 87087Snate@binkert.org * to a hardware implementation of the functionality of the software 97087Snate@binkert.org * licensed hereunder. You may use the software subject to the license 107087Snate@binkert.org * terms below provided that you ensure that this notice is replicated 117087Snate@binkert.org * unmodified and in its entirety in all distributions of the software, 127087Snate@binkert.org * modified or unmodified, in source code or in binary form. 135245Sgblack@eecs.umich.edu * 147087Snate@binkert.org * Copyright (c) 2006 The Regents of The University of Michigan 157087Snate@binkert.org * Copyright (c) 2010,2015 Advanced Micro Devices, Inc. 167087Snate@binkert.org * All rights reserved. 177087Snate@binkert.org * 187087Snate@binkert.org * Redistribution and use in source and binary forms, with or without 197087Snate@binkert.org * modification, are permitted provided that the following conditions are 207087Snate@binkert.org * met: redistributions of source code must retain the above copyright 217087Snate@binkert.org * notice, this list of conditions and the following disclaimer; 225245Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 237087Snate@binkert.org * notice, this list of conditions and the following disclaimer in the 245245Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 255245Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 265245Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 275245Sgblack@eecs.umich.edu * this software without specific prior written permission. 285245Sgblack@eecs.umich.edu * 295245Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 305245Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 315245Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 325245Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 335245Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 345245Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 355245Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 365245Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 375245Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 385245Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 395245Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 405245Sgblack@eecs.umich.edu * 415245Sgblack@eecs.umich.edu * Authors: Ali Saidi 425245Sgblack@eecs.umich.edu * Steve Reinhardt 435245Sgblack@eecs.umich.edu */ 445245Sgblack@eecs.umich.edu 455245Sgblack@eecs.umich.edu/** 465245Sgblack@eecs.umich.edu * @file 476216Snate@binkert.org * Definition of the Packet Class, a packet is a transaction occuring 485245Sgblack@eecs.umich.edu * between a single level of the memory heirarchy (ie L1->L2). 495245Sgblack@eecs.umich.edu */ 505245Sgblack@eecs.umich.edu 517901Shestness@cs.utexas.edu#include "mem/packet.hh" 528832SAli.Saidi@ARM.com 535245Sgblack@eecs.umich.edu#include <cstring> 545245Sgblack@eecs.umich.edu#include <iostream> 555245Sgblack@eecs.umich.edu 565245Sgblack@eecs.umich.edu#include "base/cprintf.hh" 575245Sgblack@eecs.umich.edu#include "base/misc.hh" 585245Sgblack@eecs.umich.edu#include "base/trace.hh" 595245Sgblack@eecs.umich.edu 605245Sgblack@eecs.umich.eduusing namespace std; 617912Shestness@cs.utexas.edu 628922Swilliam.wang@arm.com// The one downside to bitsets is that static initializers can get ugly. 635245Sgblack@eecs.umich.edu#define SET1(a1) (1 << (a1)) 645245Sgblack@eecs.umich.edu#define SET2(a1, a2) (SET1(a1) | SET1(a2)) 655245Sgblack@eecs.umich.edu#define SET3(a1, a2, a3) (SET2(a1, a2) | SET1(a3)) 668922Swilliam.wang@arm.com#define SET4(a1, a2, a3, a4) (SET3(a1, a2, a3) | SET1(a4)) 675245Sgblack@eecs.umich.edu#define SET5(a1, a2, a3, a4, a5) (SET4(a1, a2, a3, a4) | SET1(a5)) 685245Sgblack@eecs.umich.edu#define SET6(a1, a2, a3, a4, a5, a6) (SET5(a1, a2, a3, a4, a5) | SET1(a6)) 695245Sgblack@eecs.umich.edu#define SET7(a1, a2, a3, a4, a5, a6, a7) (SET6(a1, a2, a3, a4, a5, a6) | \ 708832SAli.Saidi@ARM.com SET1(a7)) 715245Sgblack@eecs.umich.edu 728975Sandreas.hansson@arm.comconst MemCmd::CommandInfo 7310713Sandreas.hansson@arm.comMemCmd::commandInfo[] = 745245Sgblack@eecs.umich.edu{ 755245Sgblack@eecs.umich.edu /* InvalidCmd */ 767912Shestness@cs.utexas.edu { 0, InvalidCmd, "InvalidCmd" }, 777912Shestness@cs.utexas.edu /* ReadReq - Read issued by a non-caching agent such as a CPU or 785245Sgblack@eecs.umich.edu * device, with no restrictions on alignment. */ 797912Shestness@cs.utexas.edu { SET3(IsRead, IsRequest, NeedsResponse), ReadResp, "ReadReq" }, 809044SAli.Saidi@ARM.com /* ReadResp */ 817912Shestness@cs.utexas.edu { SET3(IsRead, IsResponse, HasData), InvalidCmd, "ReadResp" }, 829701Sgedare@rtems.org /* ReadRespWithInvalidate */ 837912Shestness@cs.utexas.edu { SET4(IsRead, IsResponse, HasData, IsInvalidate), 847912Shestness@cs.utexas.edu InvalidCmd, "ReadRespWithInvalidate" }, 857912Shestness@cs.utexas.edu /* WriteReq */ 867912Shestness@cs.utexas.edu { SET5(IsWrite, NeedsWritable, IsRequest, NeedsResponse, HasData), 877912Shestness@cs.utexas.edu WriteResp, "WriteReq" }, 887912Shestness@cs.utexas.edu /* WriteResp */ 897912Shestness@cs.utexas.edu { SET2(IsWrite, IsResponse), InvalidCmd, "WriteResp" }, 907912Shestness@cs.utexas.edu /* WritebackDirty */ 917912Shestness@cs.utexas.edu { SET5(IsWrite, IsRequest, IsEviction, HasData, FromCache), 927912Shestness@cs.utexas.edu InvalidCmd, "WritebackDirty" }, 937912Shestness@cs.utexas.edu /* WritebackClean - This allows the upstream cache to writeback a 945245Sgblack@eecs.umich.edu * line to the downstream cache without it being considered 957912Shestness@cs.utexas.edu * dirty. */ 968832SAli.Saidi@ARM.com { SET5(IsWrite, IsRequest, IsEviction, HasData, FromCache), 977912Shestness@cs.utexas.edu InvalidCmd, "WritebackClean" }, 987912Shestness@cs.utexas.edu /* CleanEvict */ 997912Shestness@cs.utexas.edu { SET3(IsRequest, IsEviction, FromCache), InvalidCmd, "CleanEvict" }, 1007912Shestness@cs.utexas.edu /* SoftPFReq */ 1017912Shestness@cs.utexas.edu { SET4(IsRead, IsRequest, IsSWPrefetch, NeedsResponse), 1027912Shestness@cs.utexas.edu SoftPFResp, "SoftPFReq" }, 1037912Shestness@cs.utexas.edu /* HardPFReq */ 1047912Shestness@cs.utexas.edu { SET5(IsRead, IsRequest, IsHWPrefetch, NeedsResponse, FromCache), 1057912Shestness@cs.utexas.edu HardPFResp, "HardPFReq" }, 1067912Shestness@cs.utexas.edu /* SoftPFResp */ 1077912Shestness@cs.utexas.edu { SET4(IsRead, IsResponse, IsSWPrefetch, HasData), 1087912Shestness@cs.utexas.edu InvalidCmd, "SoftPFResp" }, 1097912Shestness@cs.utexas.edu /* HardPFResp */ 1107912Shestness@cs.utexas.edu { SET4(IsRead, IsResponse, IsHWPrefetch, HasData), 1117912Shestness@cs.utexas.edu InvalidCmd, "HardPFResp" }, 1127912Shestness@cs.utexas.edu /* WriteLineReq */ 1137912Shestness@cs.utexas.edu { SET5(IsWrite, NeedsWritable, IsRequest, NeedsResponse, HasData), 1147912Shestness@cs.utexas.edu WriteResp, "WriteLineReq" }, 1157912Shestness@cs.utexas.edu /* UpgradeReq */ 1167912Shestness@cs.utexas.edu { SET6(IsInvalidate, NeedsWritable, IsUpgrade, IsRequest, NeedsResponse, 1177912Shestness@cs.utexas.edu FromCache), 1187912Shestness@cs.utexas.edu UpgradeResp, "UpgradeReq" }, 1197912Shestness@cs.utexas.edu /* SCUpgradeReq: response could be UpgradeResp or UpgradeFailResp */ 1207912Shestness@cs.utexas.edu { SET7(IsInvalidate, NeedsWritable, IsUpgrade, IsLlsc, 1217912Shestness@cs.utexas.edu IsRequest, NeedsResponse, FromCache), 1227912Shestness@cs.utexas.edu UpgradeResp, "SCUpgradeReq" }, 1237912Shestness@cs.utexas.edu /* UpgradeResp */ 1247912Shestness@cs.utexas.edu { SET2(IsUpgrade, IsResponse), 1257912Shestness@cs.utexas.edu InvalidCmd, "UpgradeResp" }, 1267912Shestness@cs.utexas.edu /* SCUpgradeFailReq: generates UpgradeFailResp but still gets the data */ 1278953Sgblack@eecs.umich.edu { SET7(IsRead, NeedsWritable, IsInvalidate, 1287912Shestness@cs.utexas.edu IsLlsc, IsRequest, NeedsResponse, FromCache), 1297912Shestness@cs.utexas.edu UpgradeFailResp, "SCUpgradeFailReq" }, 1307912Shestness@cs.utexas.edu /* UpgradeFailResp - Behaves like a ReadExReq, but notifies an SC 1317912Shestness@cs.utexas.edu * that it has failed, acquires line as Dirty*/ 1327912Shestness@cs.utexas.edu { SET3(IsRead, IsResponse, HasData), 1337912Shestness@cs.utexas.edu InvalidCmd, "UpgradeFailResp" }, 1347912Shestness@cs.utexas.edu /* ReadExReq - Read issues by a cache, always cache-line aligned, 1357912Shestness@cs.utexas.edu * and the response is guaranteed to be writeable (exclusive or 1367912Shestness@cs.utexas.edu * even modified) */ 1377912Shestness@cs.utexas.edu { SET6(IsRead, NeedsWritable, IsInvalidate, IsRequest, NeedsResponse, 1387912Shestness@cs.utexas.edu FromCache), 1397912Shestness@cs.utexas.edu ReadExResp, "ReadExReq" }, 1407912Shestness@cs.utexas.edu /* ReadExResp - Response matching a read exclusive, as we check 1417912Shestness@cs.utexas.edu * the need for exclusive also on responses */ 1427912Shestness@cs.utexas.edu { SET3(IsRead, IsResponse, HasData), 1437912Shestness@cs.utexas.edu InvalidCmd, "ReadExResp" }, 1447912Shestness@cs.utexas.edu /* ReadCleanReq - Read issued by a cache, always cache-line 1457912Shestness@cs.utexas.edu * aligned, and the response is guaranteed to not contain dirty data 1467912Shestness@cs.utexas.edu * (exclusive or shared).*/ 1477912Shestness@cs.utexas.edu { SET4(IsRead, IsRequest, NeedsResponse, FromCache), 1487912Shestness@cs.utexas.edu ReadResp, "ReadCleanReq" }, 1497912Shestness@cs.utexas.edu /* ReadSharedReq - Read issued by a cache, always cache-line 1507912Shestness@cs.utexas.edu * aligned, response is shared, possibly exclusive, owned or even 1517912Shestness@cs.utexas.edu * modified. */ 1527912Shestness@cs.utexas.edu { SET4(IsRead, IsRequest, NeedsResponse, FromCache), 1539542Sandreas.hansson@arm.com ReadResp, "ReadSharedReq" }, 1549542Sandreas.hansson@arm.com /* LoadLockedReq: note that we use plain ReadResp as response, so that 1557912Shestness@cs.utexas.edu * we can also use ReadRespWithInvalidate when needed */ 1567912Shestness@cs.utexas.edu { SET4(IsRead, IsLlsc, IsRequest, NeedsResponse), 1577912Shestness@cs.utexas.edu ReadResp, "LoadLockedReq" }, 1587912Shestness@cs.utexas.edu /* StoreCondReq */ 1597912Shestness@cs.utexas.edu { SET6(IsWrite, NeedsWritable, IsLlsc, 1607912Shestness@cs.utexas.edu IsRequest, NeedsResponse, HasData), 1617912Shestness@cs.utexas.edu StoreCondResp, "StoreCondReq" }, 1628953Sgblack@eecs.umich.edu /* StoreCondFailReq: generates failing StoreCondResp */ 1639294Sandreas.hansson@arm.com { SET6(IsWrite, NeedsWritable, IsLlsc, 1649294Sandreas.hansson@arm.com IsRequest, NeedsResponse, HasData), 1657912Shestness@cs.utexas.edu StoreCondResp, "StoreCondFailReq" }, 1667912Shestness@cs.utexas.edu /* StoreCondResp */ 1675245Sgblack@eecs.umich.edu { SET3(IsWrite, IsLlsc, IsResponse), 1685245Sgblack@eecs.umich.edu InvalidCmd, "StoreCondResp" }, 1695245Sgblack@eecs.umich.edu /* SwapReq -- for Swap ldstub type operations */ 1708832SAli.Saidi@ARM.com { SET6(IsRead, IsWrite, NeedsWritable, IsRequest, HasData, NeedsResponse), 1715245Sgblack@eecs.umich.edu SwapResp, "SwapReq" }, 1729701Sgedare@rtems.org /* SwapResp -- for Swap ldstub type operations */ 1739701Sgedare@rtems.org { SET4(IsRead, IsWrite, IsResponse, HasData), 1749701Sgedare@rtems.org InvalidCmd, "SwapResp" }, 1759701Sgedare@rtems.org /* IntReq -- for interrupts */ 1769701Sgedare@rtems.org { SET4(IsWrite, IsRequest, NeedsResponse, HasData), 1779701Sgedare@rtems.org MessageResp, "MessageReq" }, 17810654Sandreas.hansson@arm.com /* IntResp -- for interrupts */ 17910654Sandreas.hansson@arm.com { SET2(IsWrite, IsResponse), InvalidCmd, "MessageResp" }, 18010654Sandreas.hansson@arm.com /* MemFenceReq -- for synchronization requests */ 18112088Sspwilson2@wisc.edu {SET2(IsRequest, NeedsResponse), MemFenceResp, "MemFenceReq"}, 18210654Sandreas.hansson@arm.com /* MemFenceResp -- for synchronization responses */ 1837912Shestness@cs.utexas.edu {SET1(IsResponse), InvalidCmd, "MemFenceResp"}, 1848975Sandreas.hansson@arm.com /* InvalidDestError -- packet dest field invalid */ 18510713Sandreas.hansson@arm.com { SET2(IsResponse, IsError), InvalidCmd, "InvalidDestError" }, 1867912Shestness@cs.utexas.edu /* BadAddressError -- memory address invalid */ 1875245Sgblack@eecs.umich.edu { SET2(IsResponse, IsError), InvalidCmd, "BadAddressError" }, 1885245Sgblack@eecs.umich.edu /* FunctionalReadError */ 1895245Sgblack@eecs.umich.edu { SET3(IsRead, IsResponse, IsError), InvalidCmd, "FunctionalReadError" }, 1905245Sgblack@eecs.umich.edu /* FunctionalWriteError */ 1915245Sgblack@eecs.umich.edu { SET3(IsWrite, IsResponse, IsError), InvalidCmd, "FunctionalWriteError" }, 1925245Sgblack@eecs.umich.edu /* PrintReq */ 1935245Sgblack@eecs.umich.edu { SET2(IsRequest, IsPrint), InvalidCmd, "PrintReq" }, 1945245Sgblack@eecs.umich.edu /* Flush Request */ 1955245Sgblack@eecs.umich.edu { SET3(IsRequest, IsFlush, NeedsWritable), InvalidCmd, "FlushReq" }, 1965245Sgblack@eecs.umich.edu /* Invalidation Request */ 1978832SAli.Saidi@ARM.com { SET5(IsInvalidate, IsRequest, NeedsWritable, NeedsResponse, FromCache), 1988832SAli.Saidi@ARM.com InvalidateResp, "InvalidateReq" }, 1998832SAli.Saidi@ARM.com /* Invalidation Response */ 2008832SAli.Saidi@ARM.com { SET2(IsInvalidate, IsResponse), 2018832SAli.Saidi@ARM.com InvalidCmd, "InvalidateResp" } 2028832SAli.Saidi@ARM.com}; 2035245Sgblack@eecs.umich.edu 2047912Shestness@cs.utexas.edubool 2058832SAli.Saidi@ARM.comPacket::checkFunctional(Printable *obj, Addr addr, bool is_secure, int size, 2069701Sgedare@rtems.org uint8_t *_data) 20710654Sandreas.hansson@arm.com{ 20812088Sspwilson2@wisc.edu Addr func_start = getAddr(); 2095245Sgblack@eecs.umich.edu Addr func_end = getAddr() + getSize() - 1; 2105245Sgblack@eecs.umich.edu Addr val_start = addr; 2115245Sgblack@eecs.umich.edu Addr val_end = val_start + size - 1; 2125245Sgblack@eecs.umich.edu 2135245Sgblack@eecs.umich.edu if (is_secure != _isSecure || func_start > val_end || 214 val_start > func_end) { 215 // no intersection 216 return false; 217 } 218 219 // check print first since it doesn't require data 220 if (isPrint()) { 221 assert(!_data); 222 safe_cast<PrintReqState*>(senderState)->printObj(obj); 223 return false; 224 } 225 226 // we allow the caller to pass NULL to signify the other packet 227 // has no data 228 if (!_data) { 229 return false; 230 } 231 232 // offset of functional request into supplied value (could be 233 // negative if partial overlap) 234 int offset = func_start - val_start; 235 236 if (isRead()) { 237 if (func_start >= val_start && func_end <= val_end) { 238 memcpy(getPtr<uint8_t>(), _data + offset, getSize()); 239 if (bytesValid.empty()) 240 bytesValid.resize(getSize(), true); 241 // complete overlap, and as the current packet is a read 242 // we are done 243 return true; 244 } else { 245 // Offsets and sizes to copy in case of partial overlap 246 int func_offset; 247 int val_offset; 248 int overlap_size; 249 250 // calculate offsets and copy sizes for the two byte arrays 251 if (val_start < func_start && val_end <= func_end) { 252 // the one we are checking against starts before and 253 // ends before or the same 254 val_offset = func_start - val_start; 255 func_offset = 0; 256 overlap_size = val_end - func_start; 257 } else if (val_start >= func_start && val_end > func_end) { 258 // the one we are checking against starts after or the 259 // same, and ends after 260 val_offset = 0; 261 func_offset = val_start - func_start; 262 overlap_size = func_end - val_start; 263 } else if (val_start >= func_start && val_end <= func_end) { 264 // the one we are checking against is completely 265 // subsumed in the current packet, possibly starting 266 // and ending at the same address 267 val_offset = 0; 268 func_offset = val_start - func_start; 269 overlap_size = size; 270 } else if (val_start < func_start && val_end > func_end) { 271 // the current packet is completely subsumed in the 272 // one we are checking against 273 val_offset = func_start - val_start; 274 func_offset = 0; 275 overlap_size = func_end - func_start; 276 } else { 277 panic("Missed a case for checkFunctional with " 278 " %s 0x%x size %d, against 0x%x size %d\n", 279 cmdString(), getAddr(), getSize(), addr, size); 280 } 281 282 // copy partial data into the packet's data array 283 uint8_t *dest = getPtr<uint8_t>() + func_offset; 284 uint8_t *src = _data + val_offset; 285 memcpy(dest, src, overlap_size); 286 287 // initialise the tracking of valid bytes if we have not 288 // used it already 289 if (bytesValid.empty()) 290 bytesValid.resize(getSize(), false); 291 292 // track if we are done filling the functional access 293 bool all_bytes_valid = true; 294 295 int i = 0; 296 297 // check up to func_offset 298 for (; all_bytes_valid && i < func_offset; ++i) 299 all_bytes_valid &= bytesValid[i]; 300 301 // update the valid bytes 302 for (i = func_offset; i < func_offset + overlap_size; ++i) 303 bytesValid[i] = true; 304 305 // check the bit after the update we just made 306 for (; all_bytes_valid && i < getSize(); ++i) 307 all_bytes_valid &= bytesValid[i]; 308 309 return all_bytes_valid; 310 } 311 } else if (isWrite()) { 312 if (offset >= 0) { 313 memcpy(_data + offset, getConstPtr<uint8_t>(), 314 (min(func_end, val_end) - func_start) + 1); 315 } else { 316 // val_start > func_start 317 memcpy(_data, getConstPtr<uint8_t>() - offset, 318 (min(func_end, val_end) - val_start) + 1); 319 } 320 } else { 321 panic("Don't know how to handle command %s\n", cmdString()); 322 } 323 324 // keep going with request by default 325 return false; 326} 327 328void 329Packet::pushSenderState(Packet::SenderState *sender_state) 330{ 331 assert(sender_state != NULL); 332 sender_state->predecessor = senderState; 333 senderState = sender_state; 334} 335 336Packet::SenderState * 337Packet::popSenderState() 338{ 339 assert(senderState != NULL); 340 SenderState *sender_state = senderState; 341 senderState = sender_state->predecessor; 342 sender_state->predecessor = NULL; 343 return sender_state; 344} 345 346void 347Packet::print(ostream &o, const int verbosity, const string &prefix) const 348{ 349 ccprintf(o, "%s%s [%x:%x]%s%s%s%s", prefix, cmdString(), 350 getAddr(), getAddr() + getSize() - 1, 351 req->isSecure() ? " (s)" : "", 352 req->isInstFetch() ? " IF" : "", 353 req->isUncacheable() ? " UC" : "", 354 isExpressSnoop() ? " ES" : ""); 355} 356 357std::string 358Packet::print() const { 359 ostringstream str; 360 print(str); 361 return str.str(); 362} 363 364Packet::PrintReqState::PrintReqState(ostream &_os, int _verbosity) 365 : curPrefixPtr(new string("")), os(_os), verbosity(_verbosity) 366{ 367 labelStack.push_back(LabelStackEntry("", curPrefixPtr)); 368} 369 370Packet::PrintReqState::~PrintReqState() 371{ 372 labelStack.pop_back(); 373 assert(labelStack.empty()); 374 delete curPrefixPtr; 375} 376 377Packet::PrintReqState:: 378LabelStackEntry::LabelStackEntry(const string &_label, string *_prefix) 379 : label(_label), prefix(_prefix), labelPrinted(false) 380{ 381} 382 383void 384Packet::PrintReqState::pushLabel(const string &lbl, const string &prefix) 385{ 386 labelStack.push_back(LabelStackEntry(lbl, curPrefixPtr)); 387 curPrefixPtr = new string(*curPrefixPtr); 388 *curPrefixPtr += prefix; 389} 390 391void 392Packet::PrintReqState::popLabel() 393{ 394 delete curPrefixPtr; 395 curPrefixPtr = labelStack.back().prefix; 396 labelStack.pop_back(); 397 assert(!labelStack.empty()); 398} 399 400void 401Packet::PrintReqState::printLabels() 402{ 403 if (!labelStack.back().labelPrinted) { 404 LabelStack::iterator i = labelStack.begin(); 405 LabelStack::iterator end = labelStack.end(); 406 while (i != end) { 407 if (!i->labelPrinted) { 408 ccprintf(os, "%s%s\n", *(i->prefix), i->label); 409 i->labelPrinted = true; 410 } 411 i++; 412 } 413 } 414} 415 416 417void 418Packet::PrintReqState::printObj(Printable *obj) 419{ 420 printLabels(); 421 obj->print(os, verbosity, curPrefix()); 422} 423