packet.cc revision 11793
1/* 2 * Copyright (c) 2011-2016 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Copyright (c) 2006 The Regents of The University of Michigan 15 * Copyright (c) 2010,2015 Advanced Micro Devices, Inc. 16 * All rights reserved. 17 * 18 * Redistribution and use in source and binary forms, with or without 19 * modification, are permitted provided that the following conditions are 20 * met: redistributions of source code must retain the above copyright 21 * notice, this list of conditions and the following disclaimer; 22 * redistributions in binary form must reproduce the above copyright 23 * notice, this list of conditions and the following disclaimer in the 24 * documentation and/or other materials provided with the distribution; 25 * neither the name of the copyright holders nor the names of its 26 * contributors may be used to endorse or promote products derived from 27 * this software without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40 * 41 * Authors: Ali Saidi 42 * Steve Reinhardt 43 */ 44 45/** 46 * @file 47 * Definition of the Packet Class, a packet is a transaction occuring 48 * between a single level of the memory heirarchy (ie L1->L2). 49 */ 50 51#include "mem/packet.hh" 52 53#include <cstring> 54#include <iostream> 55 56#include "base/cprintf.hh" 57#include "base/misc.hh" 58#include "base/trace.hh" 59 60using namespace std; 61 62// The one downside to bitsets is that static initializers can get ugly. 63#define SET1(a1) (1 << (a1)) 64#define SET2(a1, a2) (SET1(a1) | SET1(a2)) 65#define SET3(a1, a2, a3) (SET2(a1, a2) | SET1(a3)) 66#define SET4(a1, a2, a3, a4) (SET3(a1, a2, a3) | SET1(a4)) 67#define SET5(a1, a2, a3, a4, a5) (SET4(a1, a2, a3, a4) | SET1(a5)) 68#define SET6(a1, a2, a3, a4, a5, a6) (SET5(a1, a2, a3, a4, a5) | SET1(a6)) 69#define SET7(a1, a2, a3, a4, a5, a6, a7) (SET6(a1, a2, a3, a4, a5, a6) | \ 70 SET1(a7)) 71 72const MemCmd::CommandInfo 73MemCmd::commandInfo[] = 74{ 75 /* InvalidCmd */ 76 { 0, InvalidCmd, "InvalidCmd" }, 77 /* ReadReq - Read issued by a non-caching agent such as a CPU or 78 * device, with no restrictions on alignment. */ 79 { SET3(IsRead, IsRequest, NeedsResponse), ReadResp, "ReadReq" }, 80 /* ReadResp */ 81 { SET3(IsRead, IsResponse, HasData), InvalidCmd, "ReadResp" }, 82 /* ReadRespWithInvalidate */ 83 { SET4(IsRead, IsResponse, HasData, IsInvalidate), 84 InvalidCmd, "ReadRespWithInvalidate" }, 85 /* WriteReq */ 86 { SET5(IsWrite, NeedsWritable, IsRequest, NeedsResponse, HasData), 87 WriteResp, "WriteReq" }, 88 /* WriteResp */ 89 { SET2(IsWrite, IsResponse), InvalidCmd, "WriteResp" }, 90 /* WritebackDirty */ 91 { SET5(IsWrite, IsRequest, IsEviction, HasData, FromCache), 92 InvalidCmd, "WritebackDirty" }, 93 /* WritebackClean - This allows the upstream cache to writeback a 94 * line to the downstream cache without it being considered 95 * dirty. */ 96 { SET5(IsWrite, IsRequest, IsEviction, HasData, FromCache), 97 InvalidCmd, "WritebackClean" }, 98 /* CleanEvict */ 99 { SET3(IsRequest, IsEviction, FromCache), InvalidCmd, "CleanEvict" }, 100 /* SoftPFReq */ 101 { SET4(IsRead, IsRequest, IsSWPrefetch, NeedsResponse), 102 SoftPFResp, "SoftPFReq" }, 103 /* HardPFReq */ 104 { SET5(IsRead, IsRequest, IsHWPrefetch, NeedsResponse, FromCache), 105 HardPFResp, "HardPFReq" }, 106 /* SoftPFResp */ 107 { SET4(IsRead, IsResponse, IsSWPrefetch, HasData), 108 InvalidCmd, "SoftPFResp" }, 109 /* HardPFResp */ 110 { SET4(IsRead, IsResponse, IsHWPrefetch, HasData), 111 InvalidCmd, "HardPFResp" }, 112 /* WriteLineReq */ 113 { SET5(IsWrite, NeedsWritable, IsRequest, NeedsResponse, HasData), 114 WriteResp, "WriteLineReq" }, 115 /* UpgradeReq */ 116 { SET6(IsInvalidate, NeedsWritable, IsUpgrade, IsRequest, NeedsResponse, 117 FromCache), 118 UpgradeResp, "UpgradeReq" }, 119 /* SCUpgradeReq: response could be UpgradeResp or UpgradeFailResp */ 120 { SET7(IsInvalidate, NeedsWritable, IsUpgrade, IsLlsc, 121 IsRequest, NeedsResponse, FromCache), 122 UpgradeResp, "SCUpgradeReq" }, 123 /* UpgradeResp */ 124 { SET2(IsUpgrade, IsResponse), 125 InvalidCmd, "UpgradeResp" }, 126 /* SCUpgradeFailReq: generates UpgradeFailResp but still gets the data */ 127 { SET7(IsRead, NeedsWritable, IsInvalidate, 128 IsLlsc, IsRequest, NeedsResponse, FromCache), 129 UpgradeFailResp, "SCUpgradeFailReq" }, 130 /* UpgradeFailResp - Behaves like a ReadExReq, but notifies an SC 131 * that it has failed, acquires line as Dirty*/ 132 { SET3(IsRead, IsResponse, HasData), 133 InvalidCmd, "UpgradeFailResp" }, 134 /* ReadExReq - Read issues by a cache, always cache-line aligned, 135 * and the response is guaranteed to be writeable (exclusive or 136 * even modified) */ 137 { SET6(IsRead, NeedsWritable, IsInvalidate, IsRequest, NeedsResponse, 138 FromCache), 139 ReadExResp, "ReadExReq" }, 140 /* ReadExResp - Response matching a read exclusive, as we check 141 * the need for exclusive also on responses */ 142 { SET3(IsRead, IsResponse, HasData), 143 InvalidCmd, "ReadExResp" }, 144 /* ReadCleanReq - Read issued by a cache, always cache-line 145 * aligned, and the response is guaranteed to not contain dirty data 146 * (exclusive or shared).*/ 147 { SET4(IsRead, IsRequest, NeedsResponse, FromCache), 148 ReadResp, "ReadCleanReq" }, 149 /* ReadSharedReq - Read issued by a cache, always cache-line 150 * aligned, response is shared, possibly exclusive, owned or even 151 * modified. */ 152 { SET4(IsRead, IsRequest, NeedsResponse, FromCache), 153 ReadResp, "ReadSharedReq" }, 154 /* LoadLockedReq: note that we use plain ReadResp as response, so that 155 * we can also use ReadRespWithInvalidate when needed */ 156 { SET4(IsRead, IsLlsc, IsRequest, NeedsResponse), 157 ReadResp, "LoadLockedReq" }, 158 /* StoreCondReq */ 159 { SET6(IsWrite, NeedsWritable, IsLlsc, 160 IsRequest, NeedsResponse, HasData), 161 StoreCondResp, "StoreCondReq" }, 162 /* StoreCondFailReq: generates failing StoreCondResp */ 163 { SET6(IsWrite, NeedsWritable, IsLlsc, 164 IsRequest, NeedsResponse, HasData), 165 StoreCondResp, "StoreCondFailReq" }, 166 /* StoreCondResp */ 167 { SET3(IsWrite, IsLlsc, IsResponse), 168 InvalidCmd, "StoreCondResp" }, 169 /* SwapReq -- for Swap ldstub type operations */ 170 { SET6(IsRead, IsWrite, NeedsWritable, IsRequest, HasData, NeedsResponse), 171 SwapResp, "SwapReq" }, 172 /* SwapResp -- for Swap ldstub type operations */ 173 { SET4(IsRead, IsWrite, IsResponse, HasData), 174 InvalidCmd, "SwapResp" }, 175 /* IntReq -- for interrupts */ 176 { SET4(IsWrite, IsRequest, NeedsResponse, HasData), 177 MessageResp, "MessageReq" }, 178 /* IntResp -- for interrupts */ 179 { SET2(IsWrite, IsResponse), InvalidCmd, "MessageResp" }, 180 /* MemFenceReq -- for synchronization requests */ 181 {SET2(IsRequest, NeedsResponse), MemFenceResp, "MemFenceReq"}, 182 /* MemFenceResp -- for synchronization responses */ 183 {SET1(IsResponse), InvalidCmd, "MemFenceResp"}, 184 /* InvalidDestError -- packet dest field invalid */ 185 { SET2(IsResponse, IsError), InvalidCmd, "InvalidDestError" }, 186 /* BadAddressError -- memory address invalid */ 187 { SET2(IsResponse, IsError), InvalidCmd, "BadAddressError" }, 188 /* FunctionalReadError */ 189 { SET3(IsRead, IsResponse, IsError), InvalidCmd, "FunctionalReadError" }, 190 /* FunctionalWriteError */ 191 { SET3(IsWrite, IsResponse, IsError), InvalidCmd, "FunctionalWriteError" }, 192 /* PrintReq */ 193 { SET2(IsRequest, IsPrint), InvalidCmd, "PrintReq" }, 194 /* Flush Request */ 195 { SET3(IsRequest, IsFlush, NeedsWritable), InvalidCmd, "FlushReq" }, 196 /* Invalidation Request */ 197 { SET5(IsInvalidate, IsRequest, NeedsWritable, NeedsResponse, FromCache), 198 InvalidateResp, "InvalidateReq" }, 199 /* Invalidation Response */ 200 { SET2(IsInvalidate, IsResponse), 201 InvalidCmd, "InvalidateResp" } 202}; 203 204bool 205Packet::checkFunctional(Printable *obj, Addr addr, bool is_secure, int size, 206 uint8_t *_data) 207{ 208 Addr func_start = getAddr(); 209 Addr func_end = getAddr() + getSize() - 1; 210 Addr val_start = addr; 211 Addr val_end = val_start + size - 1; 212 213 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