timing.cc (5726:17157c5f7e15) | timing.cc (5728:9574f561dfa2) |
---|---|
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; --- 227 unchanged lines hidden (view full) --- 236 237 // just change status to Idle... if status != Running, 238 // completeInst() will not initiate fetch of next instruction. 239 240 notIdleFraction--; 241 _status = Idle; 242} 243 | 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; --- 227 unchanged lines hidden (view full) --- 236 237 // just change status to Idle... if status != Running, 238 // completeInst() will not initiate fetch of next instruction. 239 240 notIdleFraction--; 241 _status = Idle; 242} 243 |
244bool 245TimingSimpleCPU::handleReadPacket(PacketPtr pkt) 246{ 247 RequestPtr req = pkt->req; 248 if (req->isMmapedIpr()) { 249 Tick delay; 250 delay = TheISA::handleIprRead(thread->getTC(), pkt); 251 new IprEvent(pkt, this, nextCycle(curTick + delay)); 252 _status = DcacheWaitResponse; 253 dcache_pkt = NULL; 254 } else if (!dcachePort.sendTiming(pkt)) { 255 _status = DcacheRetry; 256 dcache_pkt = pkt; 257 } else { 258 _status = DcacheWaitResponse; 259 // memory system takes ownership of packet 260 dcache_pkt = NULL; 261 } 262 return dcache_pkt == NULL; 263} |
|
244 245template <class T> 246Fault 247TimingSimpleCPU::read(Addr addr, T &data, unsigned flags) 248{ | 264 265template <class T> 266Fault 267TimingSimpleCPU::read(Addr addr, T &data, unsigned flags) 268{ |
249 Request *req = 250 new Request(/* asid */ 0, addr, sizeof(T), flags, thread->readPC(), 251 _cpuId, /* thread ID */ 0); | 269 Fault fault; 270 const int asid = 0; 271 const int thread_id = 0; 272 const Addr pc = thread->readPC(); |
252 | 273 |
253 if (traceData) { 254 traceData->setAddr(req->getVaddr()); 255 } | 274 PacketPtr pkt; 275 RequestPtr req; |
256 | 276 |
257 // translate to physical address 258 Fault fault = thread->translateDataReadReq(req); | 277 int block_size = dcachePort.peerBlockSize(); 278 int data_size = sizeof(T); |
259 | 279 |
260 // Now do the access. 261 if (fault == NoFault) { 262 PacketPtr pkt = 263 new Packet(req, 264 (req->isLocked() ? 265 MemCmd::LoadLockedReq : MemCmd::ReadReq), 266 Packet::Broadcast); 267 pkt->dataDynamic<T>(new T); | 280 Addr second_addr = roundDown(addr + data_size - 1, block_size); |
268 | 281 |
269 if (req->isMmapedIpr()) { 270 Tick delay; 271 delay = TheISA::handleIprRead(thread->getTC(), pkt); 272 new IprEvent(pkt, this, nextCycle(curTick + delay)); 273 _status = DcacheWaitResponse; 274 dcache_pkt = NULL; 275 } else if (!dcachePort.sendTiming(pkt)) { 276 _status = DcacheRetry; 277 dcache_pkt = pkt; 278 } else { 279 _status = DcacheWaitResponse; 280 // memory system takes ownership of packet 281 dcache_pkt = NULL; | 282 if (second_addr > addr) { 283 Addr first_size = second_addr - addr; 284 Addr second_size = data_size - first_size; 285 // Make sure we'll only need two accesses. 286 assert(roundDown(second_addr + second_size - 1, block_size) == 287 second_addr); 288 289 /* 290 * Do the translations. If something isn't going to work, find out 291 * before we waste time setting up anything else. 292 */ 293 req = new Request(asid, addr, first_size, 294 flags, pc, _cpuId, thread_id); 295 fault = thread->translateDataReadReq(req); 296 if (fault != NoFault) { 297 delete req; 298 return fault; |
282 } | 299 } |
300 Request *second_req = 301 new Request(asid, second_addr, second_size, 302 flags, pc, _cpuId, thread_id); 303 fault = thread->translateDataReadReq(second_req); 304 if (fault != NoFault) { 305 delete req; 306 delete second_req; 307 return fault; 308 } |
|
283 | 309 |
284 // This will need a new way to tell if it has a dcache attached. 285 if (req->isUncacheable()) 286 recordEvent("Uncached Read"); | 310 T * data_ptr = new T; 311 312 /* 313 * This is the big packet that will hold the data we've gotten so far, 314 * if any, and also act as the response we actually give to the 315 * instruction. 316 */ 317 Request *orig_req = 318 new Request(asid, addr, data_size, flags, pc, _cpuId, thread_id); 319 orig_req->setPhys(req->getPaddr(), data_size, flags); 320 PacketPtr big_pkt = 321 new Packet(orig_req, MemCmd::ReadResp, Packet::Broadcast); 322 big_pkt->dataDynamic<T>(data_ptr); 323 SplitMainSenderState * main_send_state = new SplitMainSenderState; 324 big_pkt->senderState = main_send_state; 325 main_send_state->outstanding = 2; 326 327 // This is the packet we'll process now. 328 pkt = new Packet(req, MemCmd::ReadReq, Packet::Broadcast); 329 pkt->dataStatic<uint8_t>((uint8_t *)data_ptr); 330 pkt->senderState = new SplitFragmentSenderState(big_pkt, 0); 331 332 // This is the second half of the access we'll deal with later. 333 PacketPtr second_pkt = 334 new Packet(second_req, MemCmd::ReadReq, Packet::Broadcast); 335 second_pkt->dataStatic<uint8_t>((uint8_t *)data_ptr + first_size); 336 second_pkt->senderState = new SplitFragmentSenderState(big_pkt, 1); 337 if (!handleReadPacket(pkt)) { 338 main_send_state->fragments[1] = second_pkt; 339 } else { 340 handleReadPacket(second_pkt); 341 } |
287 } else { | 342 } else { |
288 delete req; | 343 req = new Request(asid, addr, data_size, 344 flags, pc, _cpuId, thread_id); 345 346 // translate to physical address 347 Fault fault = thread->translateDataReadReq(req); 348 349 if (fault != NoFault) { 350 delete req; 351 return fault; 352 } 353 354 pkt = new Packet(req, 355 (req->isLocked() ? 356 MemCmd::LoadLockedReq : MemCmd::ReadReq), 357 Packet::Broadcast); 358 pkt->dataDynamic<T>(new T); 359 360 handleReadPacket(pkt); |
289 } 290 291 if (traceData) { 292 traceData->setData(data); | 361 } 362 363 if (traceData) { 364 traceData->setData(data); |
365 traceData->setAddr(addr); |
|
293 } | 366 } |
294 return fault; | 367 368 // This will need a new way to tell if it has a dcache attached. 369 if (req->isUncacheable()) 370 recordEvent("Uncached Read"); 371 372 return NoFault; |
295} 296 297Fault 298TimingSimpleCPU::translateDataReadAddr(Addr vaddr, Addr &paddr, 299 int size, unsigned flags) 300{ 301 Request *req = 302 new Request(0, vaddr, size, flags, thread->readPC(), _cpuId, 0); --- 56 unchanged lines hidden (view full) --- 359 360template<> 361Fault 362TimingSimpleCPU::read(Addr addr, int32_t &data, unsigned flags) 363{ 364 return read(addr, (uint32_t&)data, flags); 365} 366 | 373} 374 375Fault 376TimingSimpleCPU::translateDataReadAddr(Addr vaddr, Addr &paddr, 377 int size, unsigned flags) 378{ 379 Request *req = 380 new Request(0, vaddr, size, flags, thread->readPC(), _cpuId, 0); --- 56 unchanged lines hidden (view full) --- 437 438template<> 439Fault 440TimingSimpleCPU::read(Addr addr, int32_t &data, unsigned flags) 441{ 442 return read(addr, (uint32_t&)data, flags); 443} 444 |
445bool 446TimingSimpleCPU::handleWritePacket() 447{ 448 RequestPtr req = dcache_pkt->req; 449 if (req->isMmapedIpr()) { 450 Tick delay; 451 delay = TheISA::handleIprWrite(thread->getTC(), dcache_pkt); 452 new IprEvent(dcache_pkt, this, nextCycle(curTick + delay)); 453 _status = DcacheWaitResponse; 454 dcache_pkt = NULL; 455 } else if (!dcachePort.sendTiming(dcache_pkt)) { 456 _status = DcacheRetry; 457 } else { 458 _status = DcacheWaitResponse; 459 // memory system takes ownership of packet 460 dcache_pkt = NULL; 461 } 462 return dcache_pkt == NULL; 463} |
|
367 368template <class T> 369Fault 370TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) 371{ | 464 465template <class T> 466Fault 467TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) 468{ |
372 Request *req = 373 new Request(/* asid */ 0, addr, sizeof(T), flags, thread->readPC(), 374 _cpuId, /* thread ID */ 0); | 469 const int asid = 0; 470 const int thread_id = 0; 471 bool do_access = true; // flag to suppress cache access 472 const Addr pc = thread->readPC(); |
375 | 473 |
376 if (traceData) { 377 traceData->setAddr(req->getVaddr()); 378 } | 474 RequestPtr req; |
379 | 475 |
380 // translate to physical address 381 Fault fault = thread->translateDataWriteReq(req); | 476 int block_size = dcachePort.peerBlockSize(); 477 int data_size = sizeof(T); |
382 | 478 |
383 // Now do the access. 384 if (fault == NoFault) { | 479 Addr second_addr = roundDown(addr + data_size - 1, block_size); 480 481 if (second_addr > addr) { 482 Fault fault; 483 Addr first_size = second_addr - addr; 484 Addr second_size = data_size - first_size; 485 // Make sure we'll only need two accesses. 486 assert(roundDown(second_addr + second_size - 1, block_size) == 487 second_addr); 488 489 req = new Request(asid, addr, first_size, 490 flags, pc, _cpuId, thread_id); 491 fault = thread->translateDataWriteReq(req); 492 if (fault != NoFault) { 493 delete req; 494 return fault; 495 } 496 RequestPtr second_req = new Request(asid, second_addr, second_size, 497 flags, pc, _cpuId, thread_id); 498 fault = thread->translateDataWriteReq(second_req); 499 if (fault != NoFault) { 500 delete req; 501 delete second_req; 502 return fault; 503 } 504 505 if (req->isLocked() || req->isSwap() || 506 second_req->isLocked() || second_req->isSwap()) { 507 panic("LL/SCs and swaps can't be split."); 508 } 509 510 T * data_ptr = new T; 511 512 /* 513 * This is the big packet that will hold the data we've gotten so far, 514 * if any, and also act as the response we actually give to the 515 * instruction. 516 */ 517 RequestPtr orig_req = 518 new Request(asid, addr, data_size, flags, pc, _cpuId, thread_id); 519 orig_req->setPhys(req->getPaddr(), data_size, flags); 520 PacketPtr big_pkt = 521 new Packet(orig_req, MemCmd::WriteResp, Packet::Broadcast); 522 big_pkt->dataDynamic<T>(data_ptr); 523 big_pkt->set(data); 524 SplitMainSenderState * main_send_state = new SplitMainSenderState; 525 big_pkt->senderState = main_send_state; 526 main_send_state->outstanding = 2; 527 528 assert(dcache_pkt == NULL); 529 // This is the packet we'll process now. 530 dcache_pkt = new Packet(req, MemCmd::WriteReq, Packet::Broadcast); 531 dcache_pkt->dataStatic<uint8_t>((uint8_t *)data_ptr); 532 dcache_pkt->senderState = new SplitFragmentSenderState(big_pkt, 0); 533 534 // This is the second half of the access we'll deal with later. 535 PacketPtr second_pkt = 536 new Packet(second_req, MemCmd::WriteReq, Packet::Broadcast); 537 second_pkt->dataStatic<uint8_t>((uint8_t *)data_ptr + first_size); 538 second_pkt->senderState = new SplitFragmentSenderState(big_pkt, 1); 539 if (!handleWritePacket()) { 540 main_send_state->fragments[1] = second_pkt; 541 } else { 542 dcache_pkt = second_pkt; 543 handleWritePacket(); 544 } 545 } else { 546 req = new Request(asid, addr, data_size, flags, pc, _cpuId, thread_id); 547 548 // translate to physical address 549 Fault fault = thread->translateDataWriteReq(req); 550 if (fault != NoFault) { 551 delete req; 552 return fault; 553 } 554 |
385 MemCmd cmd = MemCmd::WriteReq; // default | 555 MemCmd cmd = MemCmd::WriteReq; // default |
386 bool do_access = true; // flag to suppress cache access | |
387 388 if (req->isLocked()) { 389 cmd = MemCmd::StoreCondReq; 390 do_access = TheISA::handleLockedWrite(thread, req); 391 } else if (req->isSwap()) { 392 cmd = MemCmd::SwapReq; 393 if (req->isCondSwap()) { 394 assert(res); 395 req->setExtraData(*res); 396 } 397 } 398 399 // Note: need to allocate dcache_pkt even if do_access is 400 // false, as it's used unconditionally to call completeAcc(). 401 assert(dcache_pkt == NULL); 402 dcache_pkt = new Packet(req, cmd, Packet::Broadcast); 403 dcache_pkt->allocate(); | 556 557 if (req->isLocked()) { 558 cmd = MemCmd::StoreCondReq; 559 do_access = TheISA::handleLockedWrite(thread, req); 560 } else if (req->isSwap()) { 561 cmd = MemCmd::SwapReq; 562 if (req->isCondSwap()) { 563 assert(res); 564 req->setExtraData(*res); 565 } 566 } 567 568 // Note: need to allocate dcache_pkt even if do_access is 569 // false, as it's used unconditionally to call completeAcc(). 570 assert(dcache_pkt == NULL); 571 dcache_pkt = new Packet(req, cmd, Packet::Broadcast); 572 dcache_pkt->allocate(); |
404 dcache_pkt->set(data); | 573 if (req->isMmapedIpr()) 574 dcache_pkt->set(htog(data)); 575 else 576 dcache_pkt->set(data); |
405 | 577 |
406 if (do_access) { 407 if (req->isMmapedIpr()) { 408 Tick delay; 409 dcache_pkt->set(htog(data)); 410 delay = TheISA::handleIprWrite(thread->getTC(), dcache_pkt); 411 new IprEvent(dcache_pkt, this, nextCycle(curTick + delay)); 412 _status = DcacheWaitResponse; 413 dcache_pkt = NULL; 414 } else if (!dcachePort.sendTiming(dcache_pkt)) { 415 _status = DcacheRetry; 416 } else { 417 _status = DcacheWaitResponse; 418 // memory system takes ownership of packet 419 dcache_pkt = NULL; 420 } 421 } 422 // This will need a new way to tell if it's hooked up to a cache or not. 423 if (req->isUncacheable()) 424 recordEvent("Uncached Write"); 425 } else { 426 delete req; | 578 if (do_access) 579 handleWritePacket(); |
427 } 428 429 if (traceData) { | 580 } 581 582 if (traceData) { |
583 traceData->setAddr(req->getVaddr()); |
|
430 traceData->setData(data); 431 } 432 | 584 traceData->setData(data); 585 } 586 |
587 // This will need a new way to tell if it's hooked up to a cache or not. 588 if (req->isUncacheable()) 589 recordEvent("Uncached Write"); 590 |
|
433 // If the write needs to have a fault on the access, consider calling 434 // changeStatus() and changing it to "bad addr write" or something. | 591 // If the write needs to have a fault on the access, consider calling 592 // changeStatus() and changing it to "bad addr write" or something. |
435 return fault; | 593 return NoFault; |
436} 437 438Fault 439TimingSimpleCPU::translateDataWriteAddr(Addr vaddr, Addr &paddr, 440 int size, unsigned flags) 441{ 442 Request *req = 443 new Request(0, vaddr, size, flags, thread->readPC(), _cpuId, 0); --- 272 unchanged lines hidden (view full) --- 716} 717 718void 719TimingSimpleCPU::completeDataAccess(PacketPtr pkt) 720{ 721 // received a response from the dcache: complete the load or store 722 // instruction 723 assert(!pkt->isError()); | 594} 595 596Fault 597TimingSimpleCPU::translateDataWriteAddr(Addr vaddr, Addr &paddr, 598 int size, unsigned flags) 599{ 600 Request *req = 601 new Request(0, vaddr, size, flags, thread->readPC(), _cpuId, 0); --- 272 unchanged lines hidden (view full) --- 874} 875 876void 877TimingSimpleCPU::completeDataAccess(PacketPtr pkt) 878{ 879 // received a response from the dcache: complete the load or store 880 // instruction 881 assert(!pkt->isError()); |
724 assert(_status == DcacheWaitResponse); 725 _status = Running; | |
726 727 numCycles += tickToCycles(curTick - previousTick); 728 previousTick = curTick; 729 | 882 883 numCycles += tickToCycles(curTick - previousTick); 884 previousTick = curTick; 885 |
886 if (pkt->senderState) { 887 SplitFragmentSenderState * send_state = 888 dynamic_cast<SplitFragmentSenderState *>(pkt->senderState); 889 assert(send_state); 890 delete pkt->req; 891 delete pkt; 892 PacketPtr big_pkt = send_state->bigPkt; 893 delete send_state; 894 895 SplitMainSenderState * main_send_state = 896 dynamic_cast<SplitMainSenderState *>(big_pkt->senderState); 897 assert(main_send_state); 898 // Record the fact that this packet is no longer outstanding. 899 assert(main_send_state->outstanding != 0); 900 main_send_state->outstanding--; 901 902 if (main_send_state->outstanding) { 903 return; 904 } else { 905 delete main_send_state; 906 big_pkt->senderState = NULL; 907 pkt = big_pkt; 908 } 909 } 910 911 assert(_status == DcacheWaitResponse); 912 _status = Running; 913 |
|
730 Fault fault = curStaticInst->completeAcc(pkt, this, traceData); 731 732 // keep an instruction count 733 if (fault == NoFault) 734 countInst(); 735 else if (traceData) { 736 // If there was a fault, we shouldn't trace this instruction. 737 delete traceData; --- 44 unchanged lines hidden (view full) --- 782 783bool 784TimingSimpleCPU::DcachePort::recvTiming(PacketPtr pkt) 785{ 786 if (pkt->isResponse() && !pkt->wasNacked()) { 787 // delay processing of returned data until next CPU clock edge 788 Tick next_tick = cpu->nextCycle(curTick); 789 | 914 Fault fault = curStaticInst->completeAcc(pkt, this, traceData); 915 916 // keep an instruction count 917 if (fault == NoFault) 918 countInst(); 919 else if (traceData) { 920 // If there was a fault, we shouldn't trace this instruction. 921 delete traceData; --- 44 unchanged lines hidden (view full) --- 966 967bool 968TimingSimpleCPU::DcachePort::recvTiming(PacketPtr pkt) 969{ 970 if (pkt->isResponse() && !pkt->wasNacked()) { 971 // delay processing of returned data until next CPU clock edge 972 Tick next_tick = cpu->nextCycle(curTick); 973 |
790 if (next_tick == curTick) | 974 if (next_tick == curTick) { |
791 cpu->completeDataAccess(pkt); | 975 cpu->completeDataAccess(pkt); |
792 else | 976 } else { |
793 tickEvent.schedule(pkt, next_tick); | 977 tickEvent.schedule(pkt, next_tick); |
978 } |
|
794 795 return true; 796 } 797 else if (pkt->wasNacked()) { 798 assert(cpu->_status == DcacheWaitResponse); 799 pkt->reinitNacked(); 800 if (!sendTiming(pkt)) { 801 cpu->_status = DcacheRetry; --- 13 unchanged lines hidden (view full) --- 815void 816TimingSimpleCPU::DcachePort::recvRetry() 817{ 818 // we shouldn't get a retry unless we have a packet that we're 819 // waiting to transmit 820 assert(cpu->dcache_pkt != NULL); 821 assert(cpu->_status == DcacheRetry); 822 PacketPtr tmp = cpu->dcache_pkt; | 979 980 return true; 981 } 982 else if (pkt->wasNacked()) { 983 assert(cpu->_status == DcacheWaitResponse); 984 pkt->reinitNacked(); 985 if (!sendTiming(pkt)) { 986 cpu->_status = DcacheRetry; --- 13 unchanged lines hidden (view full) --- 1000void 1001TimingSimpleCPU::DcachePort::recvRetry() 1002{ 1003 // we shouldn't get a retry unless we have a packet that we're 1004 // waiting to transmit 1005 assert(cpu->dcache_pkt != NULL); 1006 assert(cpu->_status == DcacheRetry); 1007 PacketPtr tmp = cpu->dcache_pkt; |
823 if (sendTiming(tmp)) { | 1008 if (tmp->senderState) { 1009 // This is a packet from a split access. 1010 SplitFragmentSenderState * send_state = 1011 dynamic_cast<SplitFragmentSenderState *>(tmp->senderState); 1012 assert(send_state); 1013 PacketPtr big_pkt = send_state->bigPkt; 1014 1015 SplitMainSenderState * main_send_state = 1016 dynamic_cast<SplitMainSenderState *>(big_pkt->senderState); 1017 assert(main_send_state); 1018 1019 if (sendTiming(tmp)) { 1020 // If we were able to send without retrying, record that fact 1021 // and try sending the other fragment. 1022 send_state->clearFromParent(); 1023 int other_index = main_send_state->getPendingFragment(); 1024 if (other_index > 0) { 1025 tmp = main_send_state->fragments[other_index]; 1026 cpu->dcache_pkt = tmp; 1027 if ((big_pkt->isRead() && cpu->handleReadPacket(tmp)) || 1028 (big_pkt->isWrite() && cpu->handleWritePacket())) { 1029 main_send_state->fragments[other_index] = NULL; 1030 } 1031 } else { 1032 cpu->_status = DcacheWaitResponse; 1033 // memory system takes ownership of packet 1034 cpu->dcache_pkt = NULL; 1035 } 1036 } 1037 } else if (sendTiming(tmp)) { |
824 cpu->_status = DcacheWaitResponse; 825 // memory system takes ownership of packet 826 cpu->dcache_pkt = NULL; 827 } 828} 829 830TimingSimpleCPU::IprEvent::IprEvent(Packet *_pkt, TimingSimpleCPU *_cpu, 831 Tick t) --- 39 unchanged lines hidden --- | 1038 cpu->_status = DcacheWaitResponse; 1039 // memory system takes ownership of packet 1040 cpu->dcache_pkt = NULL; 1041 } 1042} 1043 1044TimingSimpleCPU::IprEvent::IprEvent(Packet *_pkt, TimingSimpleCPU *_cpu, 1045 Tick t) --- 39 unchanged lines hidden --- |