lsq_unit.hh revision 2329
17119SN/A/* 27119SN/A * Copyright (c) 2004-2006 The Regents of The University of Michigan 37119SN/A * All rights reserved. 47119SN/A * 57119SN/A * Redistribution and use in source and binary forms, with or without 67119SN/A * modification, are permitted provided that the following conditions are 77119SN/A * met: redistributions of source code must retain the above copyright 87119SN/A * notice, this list of conditions and the following disclaimer; 97119SN/A * redistributions in binary form must reproduce the above copyright 107119SN/A * notice, this list of conditions and the following disclaimer in the 117119SN/A * documentation and/or other materials provided with the distribution; 127119SN/A * neither the name of the copyright holders nor the names of its 137119SN/A * contributors may be used to endorse or promote products derived from 147119SN/A * this software without specific prior written permission. 157119SN/A * 167119SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 177119SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 187119SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 197119SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 207119SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 217119SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 227119SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 237119SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 247119SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 257119SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 267119SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 277119SN/A */ 287119SN/A 297119SN/A#ifndef __CPU_O3_LSQ_UNIT_HH__ 307119SN/A#define __CPU_O3_LSQ_UNIT_HH__ 317119SN/A 327119SN/A#include <algorithm> 337119SN/A#include <map> 347119SN/A#include <queue> 357119SN/A 367119SN/A#include "arch/faults.hh" 377119SN/A#include "config/full_system.hh" 387119SN/A#include "base/hashmap.hh" 397119SN/A#include "cpu/inst_seq.hh" 407119SN/A#include "mem/mem_interface.hh" 417119SN/A//#include "mem/page_table.hh" 427119SN/A//#include "sim/debug.hh" 437119SN/A//#include "sim/sim_object.hh" 447119SN/A 457119SN/A/** 467120Sgblack@eecs.umich.edu * Class that implements the actual LQ and SQ for each specific 477120Sgblack@eecs.umich.edu * thread. Both are circular queues; load entries are freed upon 487120Sgblack@eecs.umich.edu * committing, while store entries are freed once they writeback. The 497119SN/A * LSQUnit tracks if there are memory ordering violations, and also 507119SN/A * detects partial load to store forwarding cases (a store only has 517120Sgblack@eecs.umich.edu * part of a load's data) that requires the load to wait until the 527120Sgblack@eecs.umich.edu * store writes back. In the former case it holds onto the instruction 537120Sgblack@eecs.umich.edu * until the dependence unit looks at it, and in the latter it stalls 547119SN/A * the LSQ until the store writes back. At that point the load is 557119SN/A * replayed. 567128Sgblack@eecs.umich.edu */ 577128Sgblack@eecs.umich.edutemplate <class Impl> 587128Sgblack@eecs.umich.educlass LSQUnit { 597128Sgblack@eecs.umich.edu protected: 607128Sgblack@eecs.umich.edu typedef TheISA::IntReg IntReg; 617128Sgblack@eecs.umich.edu public: 627128Sgblack@eecs.umich.edu typedef typename Impl::Params Params; 637128Sgblack@eecs.umich.edu typedef typename Impl::FullCPU FullCPU; 647120Sgblack@eecs.umich.edu typedef typename Impl::DynInstPtr DynInstPtr; 657119SN/A typedef typename Impl::CPUPol::IEW IEW; 667119SN/A typedef typename Impl::CPUPol::IssueStruct IssueStruct; 677119SN/A 687119SN/A private: 697119SN/A class StoreCompletionEvent : public Event { 707119SN/A public: 717119SN/A /** Constructs a store completion event. */ 727120Sgblack@eecs.umich.edu StoreCompletionEvent(int store_idx, Event *wb_event, LSQUnit *lsq_ptr); 737119SN/A 747119SN/A /** Processes the store completion event. */ 757119SN/A void process(); 767119SN/A 777119SN/A /** Returns the description of this event. */ 787120Sgblack@eecs.umich.edu const char *description(); 797120Sgblack@eecs.umich.edu 807119SN/A /** The writeback event for the store. Needed for store 817120Sgblack@eecs.umich.edu * conditionals. 827120Sgblack@eecs.umich.edu */ 837119SN/A Event *wbEvent; 847119SN/A 857119SN/A private: 867119SN/A /** The store index of the store being written back. */ 877119SN/A int storeIdx; 887119SN/A private: 897119SN/A /** The pointer to the LSQ unit that issued the store. */ 907119SN/A LSQUnit<Impl> *lsqPtr; 917119SN/A }; 927119SN/A 937119SN/A public: 947119SN/A /** Constructs an LSQ unit. init() must be called prior to use. */ 957120Sgblack@eecs.umich.edu LSQUnit(); 967119SN/A 977119SN/A /** Initializes the LSQ unit with the specified number of entries. */ 987119SN/A void init(Params *params, unsigned maxLQEntries, 997119SN/A unsigned maxSQEntries, unsigned id); 1007120Sgblack@eecs.umich.edu 1017119SN/A /** Returns the name of the LSQ unit. */ 1027120Sgblack@eecs.umich.edu std::string name() const; 1037120Sgblack@eecs.umich.edu 1047119SN/A /** Sets the CPU pointer. */ 1057120Sgblack@eecs.umich.edu void setCPU(FullCPU *cpu_ptr) 1067120Sgblack@eecs.umich.edu { cpu = cpu_ptr; } 1077119SN/A 1087119SN/A /** Sets the IEW stage pointer. */ 1097119SN/A void setIEW(IEW *iew_ptr) 1107119SN/A { iewStage = iew_ptr; } 1117119SN/A 1127119SN/A /** Sets the page table pointer. */ 1137119SN/A// void setPageTable(PageTable *pt_ptr); 1147119SN/A 1157119SN/A void switchOut(); 1167119SN/A 1177119SN/A void takeOverFrom(); 1187119SN/A 1197119SN/A bool isSwitchedOut() { return switchedOut; } 1207120Sgblack@eecs.umich.edu 1217119SN/A /** Ticks the LSQ unit, which in this case only resets the number of 1227119SN/A * used cache ports. 1237119SN/A * @todo: Move the number of used ports up to the LSQ level so it can 1247119SN/A * be shared by all LSQ units. 1257120Sgblack@eecs.umich.edu */ 1267119SN/A void tick() { usedPorts = 0; } 1277128Sgblack@eecs.umich.edu 1287128Sgblack@eecs.umich.edu /** Inserts an instruction. */ 1297128Sgblack@eecs.umich.edu void insert(DynInstPtr &inst); 1307128Sgblack@eecs.umich.edu /** Inserts a load instruction. */ 1317128Sgblack@eecs.umich.edu void insertLoad(DynInstPtr &load_inst); 1327128Sgblack@eecs.umich.edu /** Inserts a store instruction. */ 1337128Sgblack@eecs.umich.edu void insertStore(DynInstPtr &store_inst); 1347128Sgblack@eecs.umich.edu 1357128Sgblack@eecs.umich.edu /** Executes a load instruction. */ 1367128Sgblack@eecs.umich.edu Fault executeLoad(DynInstPtr &inst); 1377128Sgblack@eecs.umich.edu 1387128Sgblack@eecs.umich.edu Fault executeLoad(int lq_idx) { panic("Not implemented"); return NoFault; } 1397128Sgblack@eecs.umich.edu /** Executes a store instruction. */ 1407128Sgblack@eecs.umich.edu Fault executeStore(DynInstPtr &inst); 1417128Sgblack@eecs.umich.edu 1427128Sgblack@eecs.umich.edu /** Commits the head load. */ 1437128Sgblack@eecs.umich.edu void commitLoad(); 1447128Sgblack@eecs.umich.edu /** Commits loads older than a specific sequence number. */ 1457128Sgblack@eecs.umich.edu void commitLoads(InstSeqNum &youngest_inst); 1467128Sgblack@eecs.umich.edu 1477128Sgblack@eecs.umich.edu /** Commits stores older than a specific sequence number. */ 1487128Sgblack@eecs.umich.edu void commitStores(InstSeqNum &youngest_inst); 1497128Sgblack@eecs.umich.edu 1507128Sgblack@eecs.umich.edu /** Writes back stores. */ 1517128Sgblack@eecs.umich.edu void writebackStores(); 1527128Sgblack@eecs.umich.edu 1537128Sgblack@eecs.umich.edu // @todo: Include stats in the LSQ unit. 1547128Sgblack@eecs.umich.edu //void regStats(); 1557128Sgblack@eecs.umich.edu 1567128Sgblack@eecs.umich.edu /** Clears all the entries in the LQ. */ 1577128Sgblack@eecs.umich.edu void clearLQ(); 1587128Sgblack@eecs.umich.edu 1597128Sgblack@eecs.umich.edu /** Clears all the entries in the SQ. */ 1607128Sgblack@eecs.umich.edu void clearSQ(); 1617128Sgblack@eecs.umich.edu 1627128Sgblack@eecs.umich.edu /** Resizes the LQ to a given size. */ 1637128Sgblack@eecs.umich.edu void resizeLQ(unsigned size); 1647128Sgblack@eecs.umich.edu 1657128Sgblack@eecs.umich.edu /** Resizes the SQ to a given size. */ 1667128Sgblack@eecs.umich.edu void resizeSQ(unsigned size); 1677128Sgblack@eecs.umich.edu 1687128Sgblack@eecs.umich.edu /** Squashes all instructions younger than a specific sequence number. */ 1697128Sgblack@eecs.umich.edu void squash(const InstSeqNum &squashed_num); 1707128Sgblack@eecs.umich.edu 1717128Sgblack@eecs.umich.edu /** Returns if there is a memory ordering violation. Value is reset upon 1727120Sgblack@eecs.umich.edu * call to getMemDepViolator(). 1737120Sgblack@eecs.umich.edu */ 1747120Sgblack@eecs.umich.edu bool violation() { return memDepViolator; } 1757120Sgblack@eecs.umich.edu 1767120Sgblack@eecs.umich.edu /** Returns the memory ordering violator. */ 1777120Sgblack@eecs.umich.edu DynInstPtr getMemDepViolator(); 1787120Sgblack@eecs.umich.edu 1797120Sgblack@eecs.umich.edu /** Returns if a load became blocked due to the memory system. */ 1807120Sgblack@eecs.umich.edu bool loadBlocked() 1817120Sgblack@eecs.umich.edu { return isLoadBlocked; } 1827120Sgblack@eecs.umich.edu 1837120Sgblack@eecs.umich.edu void clearLoadBlocked() 1847120Sgblack@eecs.umich.edu { isLoadBlocked = false; } 1857119SN/A 1867128Sgblack@eecs.umich.edu bool isLoadBlockedHandled() 1877128Sgblack@eecs.umich.edu { return loadBlockedHandled; } 1887128Sgblack@eecs.umich.edu 1897128Sgblack@eecs.umich.edu void setLoadBlockedHandled() 1907128Sgblack@eecs.umich.edu { loadBlockedHandled = true; } 1917128Sgblack@eecs.umich.edu 1927128Sgblack@eecs.umich.edu /** Returns the number of free entries (min of free LQ and SQ entries). */ 1937128Sgblack@eecs.umich.edu unsigned numFreeEntries(); 1947128Sgblack@eecs.umich.edu 1957128Sgblack@eecs.umich.edu /** Returns the number of loads ready to execute. */ 1967128Sgblack@eecs.umich.edu int numLoadsReady(); 1977128Sgblack@eecs.umich.edu 1987128Sgblack@eecs.umich.edu /** Returns the number of loads in the LQ. */ 1997128Sgblack@eecs.umich.edu int numLoads() { return loads; } 2007120Sgblack@eecs.umich.edu 2017120Sgblack@eecs.umich.edu /** Returns the number of stores in the SQ. */ 2027120Sgblack@eecs.umich.edu int numStores() { return stores; } 2037120Sgblack@eecs.umich.edu 2047120Sgblack@eecs.umich.edu /** Returns if either the LQ or SQ is full. */ 2057120Sgblack@eecs.umich.edu bool isFull() { return lqFull() || sqFull(); } 2067128Sgblack@eecs.umich.edu 2077128Sgblack@eecs.umich.edu /** Returns if the LQ is full. */ 2087119SN/A bool lqFull() { return loads >= (LQEntries - 1); } 209 210 /** Returns if the SQ is full. */ 211 bool sqFull() { return stores >= (SQEntries - 1); } 212 213 /** Returns the number of instructions in the LSQ. */ 214 unsigned getCount() { return loads + stores; } 215 216 /** Returns if there are any stores to writeback. */ 217 bool hasStoresToWB() { return storesToWB; } 218 219 /** Returns the number of stores to writeback. */ 220 int numStoresToWB() { return storesToWB; } 221 222 /** Returns if the LSQ unit will writeback on this cycle. */ 223 bool willWB() { return storeQueue[storeWBIdx].canWB && 224 !storeQueue[storeWBIdx].completed && 225 !dcacheInterface->isBlocked(); } 226 227 private: 228 /** Completes the store at the specified index. */ 229 void completeStore(int store_idx); 230 231 /** Increments the given store index (circular queue). */ 232 inline void incrStIdx(int &store_idx); 233 /** Decrements the given store index (circular queue). */ 234 inline void decrStIdx(int &store_idx); 235 /** Increments the given load index (circular queue). */ 236 inline void incrLdIdx(int &load_idx); 237 /** Decrements the given load index (circular queue). */ 238 inline void decrLdIdx(int &load_idx); 239 240 public: 241 /** Debugging function to dump instructions in the LSQ. */ 242 void dumpInsts(); 243 244 private: 245 /** Pointer to the CPU. */ 246 FullCPU *cpu; 247 248 /** Pointer to the IEW stage. */ 249 IEW *iewStage; 250 251 /** Pointer to the D-cache. */ 252 MemInterface *dcacheInterface; 253 254 /** Pointer to the page table. */ 255// PageTable *pTable; 256 257 public: 258 struct SQEntry { 259 /** Constructs an empty store queue entry. */ 260 SQEntry() 261 : inst(NULL), req(NULL), size(0), data(0), 262 canWB(0), committed(0), completed(0) 263 { } 264 265 /** Constructs a store queue entry for a given instruction. */ 266 SQEntry(DynInstPtr &_inst) 267 : inst(_inst), req(NULL), size(0), data(0), 268 canWB(0), committed(0), completed(0) 269 { } 270 271 /** The store instruction. */ 272 DynInstPtr inst; 273 /** The memory request for the store. */ 274 MemReqPtr req; 275 /** The size of the store. */ 276 int size; 277 /** The store data. */ 278 IntReg data; 279 /** Whether or not the store can writeback. */ 280 bool canWB; 281 /** Whether or not the store is committed. */ 282 bool committed; 283 /** Whether or not the store is completed. */ 284 bool completed; 285 }; 286 287 private: 288 /** The LSQUnit thread id. */ 289 unsigned lsqID; 290 291 /** The store queue. */ 292 std::vector<SQEntry> storeQueue; 293 294 /** The load queue. */ 295 std::vector<DynInstPtr> loadQueue; 296 297 /** The number of LQ entries, plus a sentinel entry (circular queue). 298 * @todo: Consider having var that records the true number of LQ entries. 299 */ 300 unsigned LQEntries; 301 /** The number of SQ entries, plus a sentinel entry (circular queue). 302 * @todo: Consider having var that records the true number of SQ entries. 303 */ 304 unsigned SQEntries; 305 306 /** The number of load instructions in the LQ. */ 307 int loads; 308 /** The number of store instructions in the SQ. */ 309 int stores; 310 /** The number of store instructions in the SQ waiting to writeback. */ 311 int storesToWB; 312 313 /** The index of the head instruction in the LQ. */ 314 int loadHead; 315 /** The index of the tail instruction in the LQ. */ 316 int loadTail; 317 318 /** The index of the head instruction in the SQ. */ 319 int storeHead; 320 /** The index of the first instruction that may be ready to be 321 * written back, and has not yet been written back. 322 */ 323 int storeWBIdx; 324 /** The index of the tail instruction in the SQ. */ 325 int storeTail; 326 327 /// @todo Consider moving to a more advanced model with write vs read ports 328 /** The number of cache ports available each cycle. */ 329 int cachePorts; 330 331 /** The number of used cache ports in this cycle. */ 332 int usedPorts; 333 334 bool switchedOut; 335 336 //list<InstSeqNum> mshrSeqNums; 337 338 /** Wire to read information from the issue stage time queue. */ 339 typename TimeBuffer<IssueStruct>::wire fromIssue; 340 341 /** Whether or not the LSQ is stalled. */ 342 bool stalled; 343 /** The store that causes the stall due to partial store to load 344 * forwarding. 345 */ 346 InstSeqNum stallingStoreIsn; 347 /** The index of the above store. */ 348 int stallingLoadIdx; 349 350 /** Whether or not a load is blocked due to the memory system. */ 351 bool isLoadBlocked; 352 353 bool loadBlockedHandled; 354 355 InstSeqNum blockedLoadSeqNum; 356 357 /** The oldest load that caused a memory ordering violation. */ 358 DynInstPtr memDepViolator; 359 360 // Will also need how many read/write ports the Dcache has. Or keep track 361 // of that in stage that is one level up, and only call executeLoad/Store 362 // the appropriate number of times. 363/* 364 // total number of loads forwaded from LSQ stores 365 Stats::Vector<> lsq_forw_loads; 366 367 // total number of loads ignored due to invalid addresses 368 Stats::Vector<> inv_addr_loads; 369 370 // total number of software prefetches ignored due to invalid addresses 371 Stats::Vector<> inv_addr_swpfs; 372 373 // total non-speculative bogus addresses seen (debug var) 374 Counter sim_invalid_addrs; 375 Stats::Vector<> fu_busy; //cumulative fu busy 376 377 // ready loads blocked due to memory disambiguation 378 Stats::Vector<> lsq_blocked_loads; 379 380 Stats::Scalar<> lsqInversion; 381*/ 382 public: 383 /** Executes the load at the given index. */ 384 template <class T> 385 Fault read(MemReqPtr &req, T &data, int load_idx); 386 387 /** Executes the store at the given index. */ 388 template <class T> 389 Fault write(MemReqPtr &req, T &data, int store_idx); 390 391 /** Returns the index of the head load instruction. */ 392 int getLoadHead() { return loadHead; } 393 /** Returns the sequence number of the head load instruction. */ 394 InstSeqNum getLoadHeadSeqNum() 395 { 396 if (loadQueue[loadHead]) { 397 return loadQueue[loadHead]->seqNum; 398 } else { 399 return 0; 400 } 401 402 } 403 404 /** Returns the index of the head store instruction. */ 405 int getStoreHead() { return storeHead; } 406 /** Returns the sequence number of the head store instruction. */ 407 InstSeqNum getStoreHeadSeqNum() 408 { 409 if (storeQueue[storeHead].inst) { 410 return storeQueue[storeHead].inst->seqNum; 411 } else { 412 return 0; 413 } 414 415 } 416 417 /** Returns whether or not the LSQ unit is stalled. */ 418 bool isStalled() { return stalled; } 419}; 420 421template <class Impl> 422template <class T> 423Fault 424LSQUnit<Impl>::read(MemReqPtr &req, T &data, int load_idx) 425{ 426 assert(loadQueue[load_idx]); 427 428 assert(!loadQueue[load_idx]->isExecuted()); 429 430 // Make sure this isn't an uncacheable access 431 // A bit of a hackish way to get uncached accesses to work only if they're 432 // at the head of the LSQ and are ready to commit (at the head of the ROB 433 // too). 434 if (req->flags & UNCACHEABLE && 435 (load_idx != loadHead || !loadQueue[load_idx]->reachedCommit)) { 436 iewStage->rescheduleMemInst(loadQueue[load_idx]); 437 return TheISA::genMachineCheckFault(); 438 } 439 440 // Check the SQ for any previous stores that might lead to forwarding 441 int store_idx = loadQueue[load_idx]->sqIdx; 442 443 int store_size = 0; 444 445 DPRINTF(LSQUnit, "Read called, load idx: %i, store idx: %i, " 446 "storeHead: %i addr: %#x\n", 447 load_idx, store_idx, storeHead, req->paddr); 448 449#if 0 450 if (req->flags & LOCKED) { 451 cpu->lockAddr = req->paddr; 452 cpu->lockFlag = true; 453 } 454#endif 455 req->cmd = Read; 456 assert(!req->completionEvent); 457 req->completionEvent = NULL; 458 req->time = curTick; 459 460 while (store_idx != -1) { 461 // End once we've reached the top of the LSQ 462 if (store_idx == storeWBIdx) { 463 break; 464 } 465 466 // Move the index to one younger 467 if (--store_idx < 0) 468 store_idx += SQEntries; 469 470 assert(storeQueue[store_idx].inst); 471 472 store_size = storeQueue[store_idx].size; 473 474 if (store_size == 0) 475 continue; 476 477 // Check if the store data is within the lower and upper bounds of 478 // addresses that the request needs. 479 bool store_has_lower_limit = 480 req->vaddr >= storeQueue[store_idx].inst->effAddr; 481 bool store_has_upper_limit = 482 (req->vaddr + req->size) <= (storeQueue[store_idx].inst->effAddr + 483 store_size); 484 bool lower_load_has_store_part = 485 req->vaddr < (storeQueue[store_idx].inst->effAddr + 486 store_size); 487 bool upper_load_has_store_part = 488 (req->vaddr + req->size) > storeQueue[store_idx].inst->effAddr; 489 490 // If the store's data has all of the data needed, we can forward. 491 if (store_has_lower_limit && store_has_upper_limit) { 492 // Get shift amount for offset into the store's data. 493 int shift_amt = req->vaddr & (store_size - 1); 494 // @todo: Magic number, assumes byte addressing 495 shift_amt = shift_amt << 3; 496 497 // Cast this to type T? 498 data = storeQueue[store_idx].data >> shift_amt; 499 500 assert(!req->data); 501 req->data = new uint8_t[64]; 502 503 memcpy(req->data, &data, req->size); 504 505 DPRINTF(LSQUnit, "Forwarding from store idx %i to load to " 506 "addr %#x, data %#x\n", 507 store_idx, req->vaddr, *(req->data)); 508 509 typename IEW::LdWritebackEvent *wb = 510 new typename IEW::LdWritebackEvent(loadQueue[load_idx], 511 iewStage); 512 513 // We'll say this has a 1 cycle load-store forwarding latency 514 // for now. 515 // @todo: Need to make this a parameter. 516 wb->schedule(curTick); 517 518 // Should keep track of stat for forwarded data 519 return NoFault; 520 } else if ((store_has_lower_limit && lower_load_has_store_part) || 521 (store_has_upper_limit && upper_load_has_store_part) || 522 (lower_load_has_store_part && upper_load_has_store_part)) { 523 // This is the partial store-load forwarding case where a store 524 // has only part of the load's data. 525 526 // If it's already been written back, then don't worry about 527 // stalling on it. 528 if (storeQueue[store_idx].completed) { 529 continue; 530 } 531 532 // Must stall load and force it to retry, so long as it's the oldest 533 // load that needs to do so. 534 if (!stalled || 535 (stalled && 536 loadQueue[load_idx]->seqNum < 537 loadQueue[stallingLoadIdx]->seqNum)) { 538 stalled = true; 539 stallingStoreIsn = storeQueue[store_idx].inst->seqNum; 540 stallingLoadIdx = load_idx; 541 } 542 543 // Tell IQ/mem dep unit that this instruction will need to be 544 // rescheduled eventually 545 iewStage->rescheduleMemInst(loadQueue[load_idx]); 546 547 // Do not generate a writeback event as this instruction is not 548 // complete. 549 DPRINTF(LSQUnit, "Load-store forwarding mis-match. " 550 "Store idx %i to load addr %#x\n", 551 store_idx, req->vaddr); 552 553 return NoFault; 554 } 555 } 556 557 // If there's no forwarding case, then go access memory 558 DynInstPtr inst = loadQueue[load_idx]; 559 560 DPRINTF(LSQUnit, "Doing functional access for inst [sn:%lli] PC %#x\n", 561 loadQueue[load_idx]->seqNum, loadQueue[load_idx]->readPC()); 562 563 assert(!req->data); 564 req->data = new uint8_t[64]; 565 Fault fault = cpu->read(req, data); 566 memcpy(req->data, &data, sizeof(T)); 567 568 ++usedPorts; 569 570 // if we have a cache, do cache access too 571 if (fault == NoFault && dcacheInterface) { 572 if (dcacheInterface->isBlocked()) { 573 // There's an older load that's already going to squash. 574 if (isLoadBlocked && blockedLoadSeqNum < inst->seqNum) 575 return NoFault; 576 577 // Record that the load was blocked due to memory. This 578 // load will squash all instructions after it, be 579 // refetched, and re-executed. 580 isLoadBlocked = true; 581 loadBlockedHandled = false; 582 blockedLoadSeqNum = inst->seqNum; 583 // No fault occurred, even though the interface is blocked. 584 return NoFault; 585 } 586 587 DPRINTF(LSQUnit, "Doing timing access for inst PC %#x\n", 588 loadQueue[load_idx]->readPC()); 589 590 assert(!req->completionEvent); 591 req->completionEvent = 592 new typename IEW::LdWritebackEvent(loadQueue[load_idx], iewStage); 593 MemAccessResult result = dcacheInterface->access(req); 594 595 assert(dcacheInterface->doEvents()); 596 597 if (result != MA_HIT) { 598 DPRINTF(LSQUnit, "LSQUnit: D-cache miss!\n"); 599 DPRINTF(Activity, "Activity: ld accessing mem miss [sn:%lli]\n", 600 inst->seqNum); 601 } else { 602 DPRINTF(LSQUnit, "LSQUnit: D-cache hit!\n"); 603 DPRINTF(Activity, "Activity: ld accessing mem hit [sn:%lli]\n", 604 inst->seqNum); 605 } 606 } 607 608 return fault; 609} 610 611template <class Impl> 612template <class T> 613Fault 614LSQUnit<Impl>::write(MemReqPtr &req, T &data, int store_idx) 615{ 616 assert(storeQueue[store_idx].inst); 617 618 DPRINTF(LSQUnit, "Doing write to store idx %i, addr %#x data %#x" 619 " | storeHead:%i [sn:%i]\n", 620 store_idx, req->paddr, data, storeHead, 621 storeQueue[store_idx].inst->seqNum); 622 623 storeQueue[store_idx].req = req; 624 storeQueue[store_idx].size = sizeof(T); 625 storeQueue[store_idx].data = data; 626 627 // This function only writes the data to the store queue, so no fault 628 // can happen here. 629 return NoFault; 630} 631 632#endif // __CPU_O3_LSQ_UNIT_HH__ 633