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; --- 14 unchanged lines hidden (view full) --- 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Steve Reinhardt 29 */ 30 |
31#include "arch/locked_mem.hh" |
32#include "arch/utility.hh" 33#include "cpu/exetrace.hh" 34#include "cpu/simple/timing.hh" 35#include "mem/packet_impl.hh" 36#include "sim/builder.hh" 37#include "sim/system.hh" 38 39using namespace std; --- 50 unchanged lines hidden (view full) --- 90void 91TimingSimpleCPU::CpuPort::TickEvent::schedule(Packet *_pkt, Tick t) 92{ 93 pkt = _pkt; 94 Event::schedule(t); 95} 96 97TimingSimpleCPU::TimingSimpleCPU(Params *p) |
98 : BaseSimpleCPU(p), icachePort(this, p->clock), dcachePort(this, p->clock), 99 cpu_id(p->cpu_id) |
100{ 101 _status = Idle; 102 ifetch_pkt = dcache_pkt = NULL; 103 drainEvent = NULL; 104 fetchEvent = NULL; 105 changeState(SimObject::Running); 106} 107 --- 118 unchanged lines hidden (view full) --- 226 227 228template <class T> 229Fault 230TimingSimpleCPU::read(Addr addr, T &data, unsigned flags) 231{ 232 Request *req = 233 new Request(/* asid */ 0, addr, sizeof(T), flags, thread->readPC(), |
234 cpu_id, /* thread ID */ 0); |
235 236 if (traceData) { 237 traceData->setAddr(req->getVaddr()); 238 } 239 240 // translate to physical address 241 Fault fault = thread->translateDataReadReq(req); 242 --- 64 unchanged lines hidden (view full) --- 307 308 309template <class T> 310Fault 311TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) 312{ 313 Request *req = 314 new Request(/* asid */ 0, addr, sizeof(T), flags, thread->readPC(), |
315 cpu_id, /* thread ID */ 0); |
316 317 // translate to physical address 318 Fault fault = thread->translateDataWriteReq(req); 319 320 // Now do the access. 321 if (fault == NoFault) { 322 assert(dcache_pkt == NULL); 323 dcache_pkt = new Packet(req, Packet::WriteReq, Packet::Broadcast); 324 dcache_pkt->allocate(); 325 dcache_pkt->set(data); 326 |
327 bool do_access = true; // flag to suppress cache access 328 329 if (req->isLocked()) { 330 do_access = TheISA::handleLockedWrite(thread, req); |
331 } |
332 333 if (do_access) { 334 if (!dcachePort.sendTiming(dcache_pkt)) { 335 _status = DcacheRetry; 336 } else { 337 _status = DcacheWaitResponse; 338 // memory system takes ownership of packet 339 dcache_pkt = NULL; 340 } 341 } |
342 } 343 344 // This will need a new way to tell if it's hooked up to a cache or not. 345 if (req->getFlags() & UNCACHEABLE) 346 recordEvent("Uncached Write"); 347 348 // If the write needs to have a fault on the access, consider calling 349 // changeStatus() and changing it to "bad addr write" or something. --- 47 unchanged lines hidden (view full) --- 397} 398 399 400void 401TimingSimpleCPU::fetch() 402{ 403 checkForInterrupts(); 404 |
405 Request *ifetch_req = new Request(); |
406 ifetch_req->setThreadContext(cpu_id, /* thread ID */ 0); |
407 Fault fault = setupFetchRequest(ifetch_req); 408 409 ifetch_pkt = new Packet(ifetch_req, Packet::ReadReq, Packet::Broadcast); 410 ifetch_pkt->dataStatic(&inst); 411 412 if (fault == NoFault) { 413 if (!icachePort.sendTiming(ifetch_pkt)) { 414 // Need to wait for retry --- 42 unchanged lines hidden (view full) --- 457 completeDrain(); 458 return; 459 } 460 461 preExecute(); 462 if (curStaticInst->isMemRef() && !curStaticInst->isDataPrefetch()) { 463 // load or store: just send to dcache 464 Fault fault = curStaticInst->initiateAcc(this, traceData); |
465 if (_status != Running) { 466 // instruction will complete in dcache response callback 467 assert(_status == DcacheWaitResponse || _status == DcacheRetry); 468 assert(fault == NoFault); |
469 } else { |
470 if (fault == NoFault) { 471 // early fail on store conditional: complete now 472 assert(dcache_pkt != NULL); 473 fault = curStaticInst->completeAcc(dcache_pkt, this, 474 traceData); 475 delete dcache_pkt->req; 476 delete dcache_pkt; 477 dcache_pkt = NULL; 478 } |
479 postExecute(); 480 advanceInst(fault); 481 } 482 } else { 483 // non-memory instruction: execute completely now 484 Fault fault = curStaticInst->execute(this, traceData); 485 postExecute(); 486 advanceInst(fault); --- 4 unchanged lines hidden (view full) --- 491TimingSimpleCPU::IcachePort::ITickEvent::process() 492{ 493 cpu->completeIfetch(pkt); 494} 495 496bool 497TimingSimpleCPU::IcachePort::recvTiming(Packet *pkt) 498{ |
499 // delay processing of returned data until next CPU clock edge |
500 Tick time = pkt->req->getTime(); 501 while (time < curTick) 502 time += lat; 503 504 if (time == curTick) 505 cpu->completeIfetch(pkt); 506 else 507 tickEvent.schedule(pkt, time); --- 30 unchanged lines hidden (view full) --- 538 delete pkt->req; 539 delete pkt; 540 541 return; 542 } 543 544 Fault fault = curStaticInst->completeAcc(pkt, this, traceData); 545 |
546 if (pkt->isRead() && pkt->req->isLocked()) { 547 TheISA::handleLockedRead(thread, pkt->req); 548 } 549 |
550 delete pkt->req; 551 delete pkt; 552 553 postExecute(); 554 advanceInst(fault); 555} 556 557 558void 559TimingSimpleCPU::completeDrain() 560{ 561 DPRINTF(Config, "Done draining\n"); 562 changeState(SimObject::Drained); 563 drainEvent->process(); 564} 565 566bool 567TimingSimpleCPU::DcachePort::recvTiming(Packet *pkt) 568{ |
569 // delay processing of returned data until next CPU clock edge |
570 Tick time = pkt->req->getTime(); 571 while (time < curTick) 572 time += lat; 573 574 if (time == curTick) 575 cpu->completeDataAccess(pkt); 576 else 577 tickEvent.schedule(pkt, time); --- 12 unchanged lines hidden (view full) --- 590{ 591 // we shouldn't get a retry unless we have a packet that we're 592 // waiting to transmit 593 assert(cpu->dcache_pkt != NULL); 594 assert(cpu->_status == DcacheRetry); 595 Packet *tmp = cpu->dcache_pkt; 596 if (sendTiming(tmp)) { 597 cpu->_status = DcacheWaitResponse; |
598 // memory system takes ownership of packet |
599 cpu->dcache_pkt = NULL; 600 } 601} 602 603 604//////////////////////////////////////////////////////////////////////// 605// 606// TimingSimpleCPU Simulation Object 607// 608BEGIN_DECLARE_SIM_OBJECT_PARAMS(TimingSimpleCPU) 609 610 Param<Counter> max_insts_any_thread; 611 Param<Counter> max_insts_all_threads; 612 Param<Counter> max_loads_any_thread; 613 Param<Counter> max_loads_all_threads; 614 Param<Tick> progress_interval; 615 SimObjectParam<MemObject *> mem; 616 SimObjectParam<System *> system; |
617 Param<int> cpu_id; |
618 619#if FULL_SYSTEM 620 SimObjectParam<AlphaITB *> itb; 621 SimObjectParam<AlphaDTB *> dtb; |
622 Param<Tick> profile; 623#else 624 SimObjectParam<Process *> workload; 625#endif // FULL_SYSTEM 626 627 Param<int> clock; 628 629 Param<bool> defer_registration; --- 12 unchanged lines hidden (view full) --- 642 "terminate when all threads have reached this inst count"), 643 INIT_PARAM(max_loads_any_thread, 644 "terminate when any thread reaches this load count"), 645 INIT_PARAM(max_loads_all_threads, 646 "terminate when all threads have reached this load count"), 647 INIT_PARAM(progress_interval, "Progress interval"), 648 INIT_PARAM(mem, "memory"), 649 INIT_PARAM(system, "system object"), |
650 INIT_PARAM(cpu_id, "processor ID"), |
651 652#if FULL_SYSTEM 653 INIT_PARAM(itb, "Instruction TLB"), 654 INIT_PARAM(dtb, "Data TLB"), |
655 INIT_PARAM(profile, ""), 656#else 657 INIT_PARAM(workload, "processes to run"), 658#endif // FULL_SYSTEM 659 660 INIT_PARAM(clock, "clock speed"), 661 INIT_PARAM(defer_registration, "defer system registration (for sampling)"), 662 INIT_PARAM(width, "cpu width"), --- 15 unchanged lines hidden (view full) --- 678 params->max_loads_all_threads = max_loads_all_threads; 679 params->progress_interval = progress_interval; 680 params->deferRegistration = defer_registration; 681 params->clock = clock; 682 params->functionTrace = function_trace; 683 params->functionTraceStart = function_trace_start; 684 params->mem = mem; 685 params->system = system; |
686 params->cpu_id = cpu_id; |
687 688#if FULL_SYSTEM 689 params->itb = itb; 690 params->dtb = dtb; |
691 params->profile = profile; 692#else 693 params->process = workload; 694#endif 695 696 TimingSimpleCPU *cpu = new TimingSimpleCPU(params); 697 return cpu; 698} 699 700REGISTER_SIM_OBJECT("TimingSimpleCPU", TimingSimpleCPU) 701 |