timing.cc (5728:9574f561dfa2) | timing.cc (5744:342cbc20a188) |
---|---|
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; --- 248 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 | 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; --- 248 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 |
265Fault 266TimingSimpleCPU::buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2, 267 RequestPtr &req, Addr split_addr, uint8_t *data, bool read) 268{ 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) { 277 delete req; 278 delete pkt1; 279 req = NULL; 280 pkt1 = NULL; 281 return fault; 282 } 283 284 assert(!req1->isMmapedIpr() && !req2->isMmapedIpr()); 285 286 req->setPhys(req1->getPaddr(), req->getSize(), req1->getFlags()); 287 PacketPtr pkt = new Packet(req, pkt1->cmd.responseCommand(), 288 Packet::Broadcast); 289 290 pkt->dataDynamic<uint8_t>(data); 291 pkt1->dataStatic<uint8_t>(data); 292 pkt2->dataStatic<uint8_t>(data + req1->getSize()); 293 294 SplitMainSenderState * main_send_state = new SplitMainSenderState; 295 pkt->senderState = main_send_state; 296 main_send_state->fragments[0] = pkt1; 297 main_send_state->fragments[1] = pkt2; 298 main_send_state->outstanding = 2; 299 pkt1->senderState = new SplitFragmentSenderState(pkt, 0); 300 pkt2->senderState = new SplitFragmentSenderState(pkt, 1); 301 return fault; 302} 303 304Fault 305TimingSimpleCPU::buildPacket(PacketPtr &pkt, RequestPtr &req, bool read) 306{ 307 Fault fault = read ? thread->translateDataReadReq(req) : 308 thread->translateDataWriteReq(req); 309 MemCmd cmd; 310 if (fault != NoFault) { 311 delete req; 312 req = NULL; 313 pkt = NULL; 314 return fault; 315 } else if (read) { 316 cmd = MemCmd::ReadReq; 317 if (req->isLocked()) 318 cmd = MemCmd::LoadLockedReq; 319 } else { 320 cmd = MemCmd::WriteReq; 321 if (req->isLocked()) { 322 cmd = MemCmd::StoreCondReq; 323 } else if (req->isSwap()) { 324 cmd = MemCmd::SwapReq; 325 } 326 } 327 pkt = new Packet(req, cmd, Packet::Broadcast); 328 return NoFault; 329} 330 |
|
265template <class T> 266Fault 267TimingSimpleCPU::read(Addr addr, T &data, unsigned flags) 268{ 269 Fault fault; 270 const int asid = 0; 271 const int thread_id = 0; 272 const Addr pc = thread->readPC(); | 331template <class T> 332Fault 333TimingSimpleCPU::read(Addr addr, T &data, unsigned flags) 334{ 335 Fault fault; 336 const int asid = 0; 337 const int thread_id = 0; 338 const Addr pc = thread->readPC(); |
273 274 PacketPtr pkt; 275 RequestPtr req; 276 | |
277 int block_size = dcachePort.peerBlockSize(); 278 int data_size = sizeof(T); 279 | 339 int block_size = dcachePort.peerBlockSize(); 340 int data_size = sizeof(T); 341 |
280 Addr second_addr = roundDown(addr + data_size - 1, block_size); | 342 PacketPtr pkt; 343 RequestPtr req = new Request(asid, addr, data_size, 344 flags, pc, _cpuId, thread_id); |
281 | 345 |
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); | 346 Addr split_addr = roundDown(addr + data_size - 1, block_size); 347 assert(split_addr <= addr || split_addr - addr < block_size); |
288 | 348 |
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; | 349 if (split_addr > addr) { 350 PacketPtr pkt1, pkt2; 351 this->buildSplitPacket(pkt1, pkt2, req, 352 split_addr, (uint8_t *)(new T), true); 353 if (handleReadPacket(pkt1)) { 354 SplitFragmentSenderState * send_state = 355 dynamic_cast<SplitFragmentSenderState *>(pkt1->senderState); 356 send_state->clearFromParent(); 357 if (handleReadPacket(pkt2)) { 358 send_state = 359 dynamic_cast<SplitFragmentSenderState *>(pkt1->senderState); 360 send_state->clearFromParent(); 361 } |
299 } | 362 } |
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 } 309 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 } | |
342 } else { | 363 } else { |
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 | 364 Fault fault = buildPacket(pkt, req, true); |
349 if (fault != NoFault) { | 365 if (fault != NoFault) { |
350 delete req; | |
351 return fault; 352 } | 366 return fault; 367 } |
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); 361 } 362 363 if (traceData) { 364 traceData->setData(data); 365 traceData->setAddr(addr); --- 97 unchanged lines hidden (view full) --- 463} 464 465template <class T> 466Fault 467TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) 468{ 469 const int asid = 0; 470 const int thread_id = 0; | 368 pkt->dataDynamic<T>(new T); 369 370 handleReadPacket(pkt); 371 } 372 373 if (traceData) { 374 traceData->setData(data); 375 traceData->setAddr(addr); --- 97 unchanged lines hidden (view full) --- 473} 474 475template <class T> 476Fault 477TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) 478{ 479 const int asid = 0; 480 const int thread_id = 0; |
471 bool do_access = true; // flag to suppress cache access | |
472 const Addr pc = thread->readPC(); | 481 const Addr pc = thread->readPC(); |
473 474 RequestPtr req; 475 | |
476 int block_size = dcachePort.peerBlockSize(); 477 int data_size = sizeof(T); 478 | 482 int block_size = dcachePort.peerBlockSize(); 483 int data_size = sizeof(T); 484 |
479 Addr second_addr = roundDown(addr + data_size - 1, block_size); | 485 RequestPtr req = new Request(asid, addr, data_size, 486 flags, pc, _cpuId, thread_id); |
480 | 487 |
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 Addr split_addr = roundDown(addr + data_size - 1, block_size); 489 assert(split_addr <= addr || split_addr - addr < block_size); |
488 | 490 |
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; | 491 if (split_addr > addr) { 492 PacketPtr pkt1, pkt2; 493 T *dataP = new T; 494 *dataP = data; 495 Fault fault = this->buildSplitPacket(pkt1, pkt2, req, split_addr, 496 (uint8_t *)dataP, false); 497 if (fault != NoFault) |
494 return fault; | 498 return fault; |
499 dcache_pkt = pkt1; 500 if (handleWritePacket()) { 501 SplitFragmentSenderState * send_state = 502 dynamic_cast<SplitFragmentSenderState *>(pkt1->senderState); 503 send_state->clearFromParent(); 504 dcache_pkt = pkt2; 505 if (handleReadPacket(pkt2)) { 506 send_state = 507 dynamic_cast<SplitFragmentSenderState *>(pkt1->senderState); 508 send_state->clearFromParent(); 509 } |
|
495 } | 510 } |
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 { | 511 } else { |
546 req = new Request(asid, addr, data_size, flags, pc, _cpuId, thread_id); | 512 bool do_access = true; // flag to suppress cache access |
547 | 513 |
548 // translate to physical address 549 Fault fault = thread->translateDataWriteReq(req); 550 if (fault != NoFault) { 551 delete req; | 514 Fault fault = buildPacket(dcache_pkt, req, false); 515 if (fault != NoFault) |
552 return fault; | 516 return fault; |
553 } | |
554 | 517 |
555 MemCmd cmd = MemCmd::WriteReq; // default 556 | |
557 if (req->isLocked()) { | 518 if (req->isLocked()) { |
558 cmd = MemCmd::StoreCondReq; | |
559 do_access = TheISA::handleLockedWrite(thread, req); | 519 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 } | 520 } else if (req->isCondSwap()) { 521 assert(res); 522 req->setExtraData(*res); |
566 } 567 | 523 } 524 |
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(); 573 if (req->isMmapedIpr()) 574 dcache_pkt->set(htog(data)); 575 else 576 dcache_pkt->set(data); 577 578 if (do_access) 579 handleWritePacket(); --- 505 unchanged lines hidden --- | 525 dcache_pkt->allocate(); 526 if (req->isMmapedIpr()) 527 dcache_pkt->set(htog(data)); 528 else 529 dcache_pkt->set(data); 530 531 if (do_access) 532 handleWritePacket(); --- 505 unchanged lines hidden --- |