timing.cc (5891:73084c6bb183) | timing.cc (5894:8091ac99341a) |
---|---|
1/* 2 * Copyright (c) 2002-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; --- 90 unchanged lines hidden (view full) --- 99void 100TimingSimpleCPU::CpuPort::TickEvent::schedule(PacketPtr _pkt, Tick t) 101{ 102 pkt = _pkt; 103 cpu->schedule(this, t); 104} 105 106TimingSimpleCPU::TimingSimpleCPU(TimingSimpleCPUParams *p) | 1/* 2 * Copyright (c) 2002-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; --- 90 unchanged lines hidden (view full) --- 99void 100TimingSimpleCPU::CpuPort::TickEvent::schedule(PacketPtr _pkt, Tick t) 101{ 102 pkt = _pkt; 103 cpu->schedule(this, t); 104} 105 106TimingSimpleCPU::TimingSimpleCPU(TimingSimpleCPUParams *p) |
107 : BaseSimpleCPU(p), icachePort(this, p->clock), dcachePort(this, p->clock), fetchEvent(this) | 107 : BaseSimpleCPU(p), fetchTranslation(this), icachePort(this, p->clock), 108 dcachePort(this, p->clock), fetchEvent(this) |
108{ 109 _status = Idle; 110 111 icachePort.snoopRangeSent = false; 112 dcachePort.snoopRangeSent = false; 113 114 ifetch_pkt = dcache_pkt = NULL; 115 drainEvent = NULL; --- 141 unchanged lines hidden (view full) --- 257 } else { 258 _status = DcacheWaitResponse; 259 // memory system takes ownership of packet 260 dcache_pkt = NULL; 261 } 262 return dcache_pkt == NULL; 263} 264 | 109{ 110 _status = Idle; 111 112 icachePort.snoopRangeSent = false; 113 dcachePort.snoopRangeSent = false; 114 115 ifetch_pkt = dcache_pkt = NULL; 116 drainEvent = NULL; --- 141 unchanged lines hidden (view full) --- 258 } else { 259 _status = DcacheWaitResponse; 260 // memory system takes ownership of packet 261 dcache_pkt = NULL; 262 } 263 return dcache_pkt == NULL; 264} 265 |
265Fault 266TimingSimpleCPU::buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2, 267 RequestPtr &req, Addr split_addr, uint8_t *data, bool read) | 266void 267TimingSimpleCPU::sendData(Fault fault, RequestPtr req, 268 uint8_t *data, uint64_t *res, bool read) |
268{ | 269{ |
269 Fault fault; 270 RequestPtr req1, req2; 271 assert(!req->isLocked() && !req->isSwap()); 272 req->splitOnVaddr(split_addr, req1, req2); 273 274 pkt1 = pkt2 = NULL; 275 if ((fault = buildPacket(pkt1, req1, read)) != NoFault || 276 (fault = buildPacket(pkt2, req2, read)) != NoFault) { | 270 _status = Running; 271 if (fault != NoFault) { 272 delete data; |
277 delete req; | 273 delete req; |
278 delete req1; 279 delete pkt1; 280 req = NULL; 281 pkt1 = NULL; 282 return fault; | 274 275 translationFault(fault); 276 return; |
283 } | 277 } |
278 PacketPtr pkt; 279 buildPacket(pkt, req, read); 280 pkt->dataDynamic<uint8_t>(data); 281 if (req->getFlags().isSet(Request::NO_ACCESS)) { 282 assert(!dcache_pkt); 283 pkt->makeResponse(); 284 completeDataAccess(pkt); 285 } else if (read) { 286 handleReadPacket(pkt); 287 } else { 288 bool do_access = true; // flag to suppress cache access |
|
284 | 289 |
285 assert(!req1->isMmapedIpr() && !req2->isMmapedIpr()); | 290 if (req->isLocked()) { 291 do_access = TheISA::handleLockedWrite(thread, req); 292 } else if (req->isCondSwap()) { 293 assert(res); 294 req->setExtraData(*res); 295 } |
286 | 296 |
287 req->setPhys(req1->getPaddr(), req->getSize(), req1->getFlags()); 288 PacketPtr pkt = new Packet(req, pkt1->cmd.responseCommand(), 289 Packet::Broadcast); 290 if (req->getFlags().isSet(Request::NO_ACCESS)) { | 297 if (do_access) { 298 dcache_pkt = pkt; 299 handleWritePacket(); 300 } else { 301 _status = DcacheWaitResponse; 302 completeDataAccess(pkt); 303 } 304 } 305} 306 307void 308TimingSimpleCPU::sendSplitData(Fault fault1, Fault fault2, 309 RequestPtr req1, RequestPtr req2, RequestPtr req, 310 uint8_t *data, bool read) 311{ 312 _status = Running; 313 if (fault1 != NoFault || fault2 != NoFault) { 314 delete data; |
291 delete req1; | 315 delete req1; |
292 delete pkt1; | |
293 delete req2; | 316 delete req2; |
294 delete pkt2; 295 pkt1 = pkt; 296 pkt2 = NULL; 297 return NoFault; | 317 if (fault1 != NoFault) 318 translationFault(fault1); 319 else if (fault2 != NoFault) 320 translationFault(fault2); 321 return; |
298 } | 322 } |
323 PacketPtr pkt1, pkt2; 324 buildSplitPacket(pkt1, pkt2, req1, req2, req, data, read); 325 if (req->getFlags().isSet(Request::NO_ACCESS)) { 326 assert(!dcache_pkt); 327 pkt1->makeResponse(); 328 completeDataAccess(pkt1); 329 } else if (read) { 330 if (handleReadPacket(pkt1)) { 331 SplitFragmentSenderState * send_state = 332 dynamic_cast<SplitFragmentSenderState *>(pkt1->senderState); 333 send_state->clearFromParent(); 334 if (handleReadPacket(pkt2)) { 335 send_state = dynamic_cast<SplitFragmentSenderState *>( 336 pkt1->senderState); 337 send_state->clearFromParent(); 338 } 339 } 340 } else { 341 dcache_pkt = pkt1; 342 if (handleWritePacket()) { 343 SplitFragmentSenderState * send_state = 344 dynamic_cast<SplitFragmentSenderState *>(pkt1->senderState); 345 send_state->clearFromParent(); 346 dcache_pkt = pkt2; 347 if (handleWritePacket()) { 348 send_state = dynamic_cast<SplitFragmentSenderState *>( 349 pkt1->senderState); 350 send_state->clearFromParent(); 351 } 352 } 353 } 354} |
|
299 | 355 |
300 pkt->dataDynamic<uint8_t>(data); 301 pkt1->dataStatic<uint8_t>(data); 302 pkt2->dataStatic<uint8_t>(data + req1->getSize()); | 356void 357TimingSimpleCPU::translationFault(Fault fault) 358{ 359 numCycles += tickToCycles(curTick - previousTick); 360 previousTick = curTick; |
303 | 361 |
304 SplitMainSenderState * main_send_state = new SplitMainSenderState; 305 pkt->senderState = main_send_state; 306 main_send_state->fragments[0] = pkt1; 307 main_send_state->fragments[1] = pkt2; 308 main_send_state->outstanding = 2; 309 pkt1->senderState = new SplitFragmentSenderState(pkt, 0); 310 pkt2->senderState = new SplitFragmentSenderState(pkt, 1); 311 return fault; | 362 if (traceData) { 363 // Since there was a fault, we shouldn't trace this instruction. 364 delete traceData; 365 traceData = NULL; 366 } 367 368 postExecute(); 369 370 if (getState() == SimObject::Draining) { 371 advancePC(fault); 372 completeDrain(); 373 } else { 374 advanceInst(fault); 375 } |
312} 313 | 376} 377 |
314Fault 315TimingSimpleCPU::buildPacket(PacketPtr &pkt, RequestPtr &req, bool read) | 378void 379TimingSimpleCPU::buildPacket(PacketPtr &pkt, RequestPtr req, bool read) |
316{ | 380{ |
317 Fault fault = thread->dtb->translateAtomic(req, tc, !read); | |
318 MemCmd cmd; | 381 MemCmd cmd; |
319 if (fault != NoFault) { 320 delete req; 321 req = NULL; 322 pkt = NULL; 323 return fault; 324 } else if (read) { | 382 if (read) { |
325 cmd = MemCmd::ReadReq; 326 if (req->isLocked()) 327 cmd = MemCmd::LoadLockedReq; 328 } else { 329 cmd = MemCmd::WriteReq; 330 if (req->isLocked()) { 331 cmd = MemCmd::StoreCondReq; 332 } else if (req->isSwap()) { 333 cmd = MemCmd::SwapReq; 334 } 335 } 336 pkt = new Packet(req, cmd, Packet::Broadcast); | 383 cmd = MemCmd::ReadReq; 384 if (req->isLocked()) 385 cmd = MemCmd::LoadLockedReq; 386 } else { 387 cmd = MemCmd::WriteReq; 388 if (req->isLocked()) { 389 cmd = MemCmd::StoreCondReq; 390 } else if (req->isSwap()) { 391 cmd = MemCmd::SwapReq; 392 } 393 } 394 pkt = new Packet(req, cmd, Packet::Broadcast); |
337 return NoFault; | |
338} 339 | 395} 396 |
397void 398TimingSimpleCPU::buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2, 399 RequestPtr req1, RequestPtr req2, RequestPtr req, 400 uint8_t *data, bool read) 401{ 402 pkt1 = pkt2 = NULL; 403 404 assert(!req1->isMmapedIpr() && !req2->isMmapedIpr()); 405 406 if (req->getFlags().isSet(Request::NO_ACCESS)) { 407 buildPacket(pkt1, req, read); 408 return; 409 } 410 411 buildPacket(pkt1, req1, read); 412 buildPacket(pkt2, req2, read); 413 414 req->setPhys(req1->getPaddr(), req->getSize(), req1->getFlags()); 415 PacketPtr pkt = new Packet(req, pkt1->cmd.responseCommand(), 416 Packet::Broadcast); 417 418 pkt->dataDynamic<uint8_t>(data); 419 pkt1->dataStatic<uint8_t>(data); 420 pkt2->dataStatic<uint8_t>(data + req1->getSize()); 421 422 SplitMainSenderState * main_send_state = new SplitMainSenderState; 423 pkt->senderState = main_send_state; 424 main_send_state->fragments[0] = pkt1; 425 main_send_state->fragments[1] = pkt2; 426 main_send_state->outstanding = 2; 427 pkt1->senderState = new SplitFragmentSenderState(pkt, 0); 428 pkt2->senderState = new SplitFragmentSenderState(pkt, 1); 429} 430 |
|
340template <class T> 341Fault 342TimingSimpleCPU::read(Addr addr, T &data, unsigned flags) 343{ 344 Fault fault; 345 const int asid = 0; 346 const int thread_id = 0; 347 const Addr pc = thread->readPC(); 348 int block_size = dcachePort.peerBlockSize(); 349 int data_size = sizeof(T); 350 | 431template <class T> 432Fault 433TimingSimpleCPU::read(Addr addr, T &data, unsigned flags) 434{ 435 Fault fault; 436 const int asid = 0; 437 const int thread_id = 0; 438 const Addr pc = thread->readPC(); 439 int block_size = dcachePort.peerBlockSize(); 440 int data_size = sizeof(T); 441 |
351 PacketPtr pkt; | |
352 RequestPtr req = new Request(asid, addr, data_size, 353 flags, pc, _cpuId, thread_id); 354 355 Addr split_addr = roundDown(addr + data_size - 1, block_size); 356 assert(split_addr <= addr || split_addr - addr < block_size); 357 | 442 RequestPtr req = new Request(asid, addr, data_size, 443 flags, pc, _cpuId, thread_id); 444 445 Addr split_addr = roundDown(addr + data_size - 1, block_size); 446 assert(split_addr <= addr || split_addr - addr < block_size); 447 |
448 449 _status = DTBWaitResponse; |
|
358 if (split_addr > addr) { | 450 if (split_addr > addr) { |
359 PacketPtr pkt1, pkt2; 360 Fault fault = this->buildSplitPacket(pkt1, pkt2, req, 361 split_addr, (uint8_t *)(new T), true); 362 if (fault != NoFault) 363 return fault; 364 if (req->getFlags().isSet(Request::NO_ACCESS)) { 365 dcache_pkt = pkt1; 366 } else if (handleReadPacket(pkt1)) { 367 SplitFragmentSenderState * send_state = 368 dynamic_cast<SplitFragmentSenderState *>(pkt1->senderState); 369 send_state->clearFromParent(); 370 if (handleReadPacket(pkt2)) { 371 send_state = 372 dynamic_cast<SplitFragmentSenderState *>(pkt1->senderState); 373 send_state->clearFromParent(); 374 } 375 } | 451 RequestPtr req1, req2; 452 assert(!req->isLocked() && !req->isSwap()); 453 req->splitOnVaddr(split_addr, req1, req2); 454 455 typedef SplitDataTranslation::WholeTranslationState WholeState; 456 WholeState *state = new WholeState(req1, req2, req, 457 (uint8_t *)(new T), true); 458 thread->dtb->translateTiming(req1, tc, 459 new SplitDataTranslation(this, 0, state), false); 460 thread->dtb->translateTiming(req2, tc, 461 new SplitDataTranslation(this, 1, state), false); |
376 } else { | 462 } else { |
377 Fault fault = buildPacket(pkt, req, true); 378 if (fault != NoFault) { 379 return fault; 380 } 381 if (req->getFlags().isSet(Request::NO_ACCESS)) { 382 dcache_pkt = pkt; 383 } else { 384 pkt->dataDynamic<T>(new T); 385 handleReadPacket(pkt); 386 } | 463 thread->dtb->translateTiming(req, tc, 464 new DataTranslation(this, (uint8_t *)(new T), NULL, true), 465 false); |
387 } 388 389 if (traceData) { 390 traceData->setData(data); 391 traceData->setAddr(addr); 392 } 393 394 // This will need a new way to tell if it has a dcache attached. --- 84 unchanged lines hidden (view full) --- 479 int data_size = sizeof(T); 480 481 RequestPtr req = new Request(asid, addr, data_size, 482 flags, pc, _cpuId, thread_id); 483 484 Addr split_addr = roundDown(addr + data_size - 1, block_size); 485 assert(split_addr <= addr || split_addr - addr < block_size); 486 | 466 } 467 468 if (traceData) { 469 traceData->setData(data); 470 traceData->setAddr(addr); 471 } 472 473 // This will need a new way to tell if it has a dcache attached. --- 84 unchanged lines hidden (view full) --- 558 int data_size = sizeof(T); 559 560 RequestPtr req = new Request(asid, addr, data_size, 561 flags, pc, _cpuId, thread_id); 562 563 Addr split_addr = roundDown(addr + data_size - 1, block_size); 564 assert(split_addr <= addr || split_addr - addr < block_size); 565 |
566 T *dataP = new T; 567 *dataP = TheISA::gtoh(data); 568 _status = DTBWaitResponse; |
|
487 if (split_addr > addr) { | 569 if (split_addr > addr) { |
488 PacketPtr pkt1, pkt2; 489 T *dataP = new T; 490 *dataP = data; 491 Fault fault = this->buildSplitPacket(pkt1, pkt2, req, split_addr, 492 (uint8_t *)dataP, false); 493 if (fault != NoFault) 494 return fault; 495 dcache_pkt = pkt1; 496 if (!req->getFlags().isSet(Request::NO_ACCESS)) { 497 if (handleWritePacket()) { 498 SplitFragmentSenderState * send_state = 499 dynamic_cast<SplitFragmentSenderState *>( 500 pkt1->senderState); 501 send_state->clearFromParent(); 502 dcache_pkt = pkt2; 503 if (handleReadPacket(pkt2)) { 504 send_state = 505 dynamic_cast<SplitFragmentSenderState *>( 506 pkt1->senderState); 507 send_state->clearFromParent(); 508 } 509 } 510 } 511 } else { 512 bool do_access = true; // flag to suppress cache access | 570 RequestPtr req1, req2; 571 assert(!req->isLocked() && !req->isSwap()); 572 req->splitOnVaddr(split_addr, req1, req2); |
513 | 573 |
514 Fault fault = buildPacket(dcache_pkt, req, false); 515 if (fault != NoFault) 516 return fault; 517 518 if (!req->getFlags().isSet(Request::NO_ACCESS)) { 519 if (req->isLocked()) { 520 do_access = TheISA::handleLockedWrite(thread, req); 521 } else if (req->isCondSwap()) { 522 assert(res); 523 req->setExtraData(*res); 524 } 525 526 dcache_pkt->allocate(); 527 if (req->isMmapedIpr()) 528 dcache_pkt->set(htog(data)); 529 else 530 dcache_pkt->set(data); 531 532 if (do_access) 533 handleWritePacket(); 534 } | 574 typedef SplitDataTranslation::WholeTranslationState WholeState; 575 WholeState *state = new WholeState(req1, req2, req, 576 (uint8_t *)dataP, false); 577 thread->dtb->translateTiming(req1, tc, 578 new SplitDataTranslation(this, 0, state), true); 579 thread->dtb->translateTiming(req2, tc, 580 new SplitDataTranslation(this, 1, state), true); 581 } else { 582 thread->dtb->translateTiming(req, tc, 583 new DataTranslation(this, (uint8_t *)dataP, res, false), 584 true); |
535 } 536 537 if (traceData) { 538 traceData->setAddr(req->getVaddr()); 539 traceData->setData(data); 540 } 541 542 // This will need a new way to tell if it's hooked up to a cache or not. --- 72 unchanged lines hidden (view full) --- 615 616 checkPcEventQueue(); 617 618 bool fromRom = isRomMicroPC(thread->readMicroPC()); 619 620 if (!fromRom) { 621 Request *ifetch_req = new Request(); 622 ifetch_req->setThreadContext(_cpuId, /* thread ID */ 0); | 585 } 586 587 if (traceData) { 588 traceData->setAddr(req->getVaddr()); 589 traceData->setData(data); 590 } 591 592 // This will need a new way to tell if it's hooked up to a cache or not. --- 72 unchanged lines hidden (view full) --- 665 666 checkPcEventQueue(); 667 668 bool fromRom = isRomMicroPC(thread->readMicroPC()); 669 670 if (!fromRom) { 671 Request *ifetch_req = new Request(); 672 ifetch_req->setThreadContext(_cpuId, /* thread ID */ 0); |
623 Fault fault = setupFetchRequest(ifetch_req); | 673 setupFetchRequest(ifetch_req); 674 thread->itb->translateTiming(ifetch_req, tc, 675 &fetchTranslation); 676 } else { 677 _status = IcacheWaitResponse; 678 completeIfetch(NULL); |
624 | 679 |
625 ifetch_pkt = new Packet(ifetch_req, MemCmd::ReadReq, Packet::Broadcast); | 680 numCycles += tickToCycles(curTick - previousTick); 681 previousTick = curTick; 682 } 683} 684 685 686void 687TimingSimpleCPU::sendFetch(Fault fault, RequestPtr req, ThreadContext *tc) 688{ 689 if (fault == NoFault) { 690 ifetch_pkt = new Packet(req, MemCmd::ReadReq, Packet::Broadcast); |
626 ifetch_pkt->dataStatic(&inst); 627 | 691 ifetch_pkt->dataStatic(&inst); 692 |
628 if (fault == NoFault) { 629 if (!icachePort.sendTiming(ifetch_pkt)) { 630 // Need to wait for retry 631 _status = IcacheRetry; 632 } else { 633 // Need to wait for cache to respond 634 _status = IcacheWaitResponse; 635 // ownership of packet transferred to memory system 636 ifetch_pkt = NULL; 637 } | 693 if (!icachePort.sendTiming(ifetch_pkt)) { 694 // Need to wait for retry 695 _status = IcacheRetry; |
638 } else { | 696 } else { |
639 delete ifetch_req; 640 delete ifetch_pkt; 641 // fetch fault: advance directly to next instruction (fault handler) 642 advanceInst(fault); | 697 // Need to wait for cache to respond 698 _status = IcacheWaitResponse; 699 // ownership of packet transferred to memory system 700 ifetch_pkt = NULL; |
643 } 644 } else { | 701 } 702 } else { |
645 _status = IcacheWaitResponse; 646 completeIfetch(NULL); | 703 delete req; 704 // fetch fault: advance directly to next instruction (fault handler) 705 advanceInst(fault); |
647 } 648 649 numCycles += tickToCycles(curTick - previousTick); 650 previousTick = curTick; 651} 652 653 654void --- 39 unchanged lines hidden (view full) --- 694 695 preExecute(); 696 if (curStaticInst && 697 curStaticInst->isMemRef() && !curStaticInst->isDataPrefetch()) { 698 // load or store: just send to dcache 699 Fault fault = curStaticInst->initiateAcc(this, traceData); 700 if (_status != Running) { 701 // instruction will complete in dcache response callback | 706 } 707 708 numCycles += tickToCycles(curTick - previousTick); 709 previousTick = curTick; 710} 711 712 713void --- 39 unchanged lines hidden (view full) --- 753 754 preExecute(); 755 if (curStaticInst && 756 curStaticInst->isMemRef() && !curStaticInst->isDataPrefetch()) { 757 // load or store: just send to dcache 758 Fault fault = curStaticInst->initiateAcc(this, traceData); 759 if (_status != Running) { 760 // instruction will complete in dcache response callback |
702 assert(_status == DcacheWaitResponse || _status == DcacheRetry); | 761 assert(_status == DcacheWaitResponse || 762 _status == DcacheRetry || DTBWaitResponse); |
703 assert(fault == NoFault); 704 } else { | 763 assert(fault == NoFault); 764 } else { |
705 if (fault == NoFault) { 706 // Note that ARM can have NULL packets if the instruction gets 707 // squashed due to predication 708 // early fail on store conditional: complete now 709 assert(dcache_pkt != NULL || THE_ISA == ARM_ISA); 710 711 fault = curStaticInst->completeAcc(dcache_pkt, this, 712 traceData); 713 if (dcache_pkt != NULL) 714 { 715 delete dcache_pkt->req; 716 delete dcache_pkt; 717 dcache_pkt = NULL; 718 } 719 720 // keep an instruction count 721 if (fault == NoFault) 722 countInst(); 723 } else if (traceData) { | 765 if (fault != NoFault && traceData) { |
724 // If there was a fault, we shouldn't trace this instruction. 725 delete traceData; 726 traceData = NULL; 727 } 728 729 postExecute(); 730 // @todo remove me after debugging with legion done 731 if (curStaticInst && (!curStaticInst->isMicroop() || --- 106 unchanged lines hidden (view full) --- 838 return; 839 } else { 840 delete main_send_state; 841 big_pkt->senderState = NULL; 842 pkt = big_pkt; 843 } 844 } 845 | 766 // If there was a fault, we shouldn't trace this instruction. 767 delete traceData; 768 traceData = NULL; 769 } 770 771 postExecute(); 772 // @todo remove me after debugging with legion done 773 if (curStaticInst && (!curStaticInst->isMicroop() || --- 106 unchanged lines hidden (view full) --- 880 return; 881 } else { 882 delete main_send_state; 883 big_pkt->senderState = NULL; 884 pkt = big_pkt; 885 } 886 } 887 |
846 assert(_status == DcacheWaitResponse); | 888 assert(_status == DcacheWaitResponse || _status == DTBWaitResponse); |
847 _status = Running; 848 849 Fault fault = curStaticInst->completeAcc(pkt, this, traceData); 850 851 // keep an instruction count 852 if (fault == NoFault) 853 countInst(); 854 else if (traceData) { --- 165 unchanged lines hidden --- | 889 _status = Running; 890 891 Fault fault = curStaticInst->completeAcc(pkt, this, traceData); 892 893 // keep an instruction count 894 if (fault == NoFault) 895 countInst(); 896 else if (traceData) { --- 165 unchanged lines hidden --- |