atomic.cc (4998:51a0f9f59cc5) | atomic.cc (4999:b46ae02966d5) |
---|---|
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; --- 271 unchanged lines hidden (view full) --- 280 281 282template <class T> 283Fault 284AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags) 285{ 286 // use the CPU's statically allocated read request and packet objects 287 Request *req = &data_read_req; | 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; --- 271 unchanged lines hidden (view full) --- 280 281 282template <class T> 283Fault 284AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags) 285{ 286 // use the CPU's statically allocated read request and packet objects 287 Request *req = &data_read_req; |
288 req->setVirt(0, addr, sizeof(T), flags, thread->readPC()); | |
289 290 if (traceData) { 291 traceData->setAddr(addr); 292 } 293 | 288 289 if (traceData) { 290 traceData->setAddr(addr); 291 } 292 |
294 // translate to physical address 295 Fault fault = thread->translateDataReadReq(req); | 293 //The block size of our peer. 294 int blockSize = dcachePort.peerBlockSize(); 295 //The size of the data we're trying to read. 296 int dataSize = sizeof(T); |
296 | 297 |
297 // Now do the access. 298 if (fault == NoFault) { 299 Packet pkt = 300 Packet(req, 301 req->isLocked() ? MemCmd::LoadLockedReq : MemCmd::ReadReq, 302 Packet::Broadcast); 303 pkt.dataStatic(&data); | 298 uint8_t * dataPtr = (uint8_t *)&data; |
304 | 299 |
305 if (req->isMmapedIpr()) 306 dcache_latency = TheISA::handleIprRead(thread->getTC(), &pkt); 307 else { 308 if (hasPhysMemPort && pkt.getAddr() == physMemAddr) 309 dcache_latency = physmemPort.sendAtomic(&pkt); 310 else 311 dcache_latency = dcachePort.sendAtomic(&pkt); | 300 //The address of the second part of this access if it needs to be split 301 //across a cache line boundary. 302 Addr secondAddr = roundDown(addr + dataSize - 1, blockSize); 303 304 if(secondAddr > addr) 305 dataSize = secondAddr - addr; 306 307 dcache_latency = 0; 308 309 while(1) { 310 req->setVirt(0, addr, dataSize, flags, thread->readPC()); 311 312 // translate to physical address 313 Fault fault = thread->translateDataReadReq(req); 314 315 // Now do the access. 316 if (fault == NoFault) { 317 Packet pkt = Packet(req, 318 req->isLocked() ? MemCmd::LoadLockedReq : MemCmd::ReadReq, 319 Packet::Broadcast); 320 pkt.dataStatic(dataPtr); 321 322 if (req->isMmapedIpr()) 323 dcache_latency += TheISA::handleIprRead(thread->getTC(), &pkt); 324 else { 325 if (hasPhysMemPort && pkt.getAddr() == physMemAddr) 326 dcache_latency += physmemPort.sendAtomic(&pkt); 327 else 328 dcache_latency += dcachePort.sendAtomic(&pkt); 329 } 330 dcache_access = true; 331 assert(!pkt.isError()); 332 333 if (req->isLocked()) { 334 TheISA::handleLockedRead(thread, req); 335 } |
312 } | 336 } |
313 dcache_access = true; 314 assert(!pkt.isError()); | |
315 | 337 |
316 data = gtoh(data); | 338 // This will need a new way to tell if it has a dcache attached. 339 if (req->isUncacheable()) 340 recordEvent("Uncached Read"); |
317 | 341 |
318 if (req->isLocked()) { 319 TheISA::handleLockedRead(thread, req); | 342 //If there's a fault, return it 343 if (fault != NoFault) 344 return fault; 345 //If we don't need to access a second cache line, stop now. 346 if (secondAddr <= addr) 347 { 348 data = gtoh(data); 349 return fault; |
320 } | 350 } |
321 } | |
322 | 351 |
323 // This will need a new way to tell if it has a dcache attached. 324 if (req->isUncacheable()) 325 recordEvent("Uncached Read"); | 352 /* 353 * Set up for accessing the second cache line. 354 */ |
326 | 355 |
327 return fault; | 356 //Move the pointer we're reading into to the correct location. 357 dataPtr += dataSize; 358 //Adjust the size to get the remaining bytes. 359 dataSize = addr + sizeof(T) - secondAddr; 360 //And access the right address. 361 addr = secondAddr; 362 } |
328} 329 330#ifndef DOXYGEN_SHOULD_SKIP_THIS 331 332template 333Fault 334AtomicSimpleCPU::read(Addr addr, Twin32_t &data, unsigned flags); 335 --- 43 unchanged lines hidden (view full) --- 379 380 381template <class T> 382Fault 383AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) 384{ 385 // use the CPU's statically allocated write request and packet objects 386 Request *req = &data_write_req; | 363} 364 365#ifndef DOXYGEN_SHOULD_SKIP_THIS 366 367template 368Fault 369AtomicSimpleCPU::read(Addr addr, Twin32_t &data, unsigned flags); 370 --- 43 unchanged lines hidden (view full) --- 414 415 416template <class T> 417Fault 418AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) 419{ 420 // use the CPU's statically allocated write request and packet objects 421 Request *req = &data_write_req; |
387 req->setVirt(0, addr, sizeof(T), flags, thread->readPC()); | |
388 389 if (traceData) { 390 traceData->setAddr(addr); 391 } 392 | 422 423 if (traceData) { 424 traceData->setAddr(addr); 425 } 426 |
393 // translate to physical address 394 Fault fault = thread->translateDataWriteReq(req); | 427 //The block size of our peer. 428 int blockSize = dcachePort.peerBlockSize(); 429 //The size of the data we're trying to read. 430 int dataSize = sizeof(T); |
395 | 431 |
396 // Now do the access. 397 if (fault == NoFault) { 398 MemCmd cmd = MemCmd::WriteReq; // default 399 bool do_access = true; // flag to suppress cache access | 432 uint8_t * dataPtr = (uint8_t *)&data; |
400 | 433 |
401 if (req->isLocked()) { 402 cmd = MemCmd::StoreCondReq; 403 do_access = TheISA::handleLockedWrite(thread, req); 404 } else if (req->isSwap()) { 405 cmd = MemCmd::SwapReq; 406 if (req->isCondSwap()) { 407 assert(res); 408 req->setExtraData(*res); | 434 //The address of the second part of this access if it needs to be split 435 //across a cache line boundary. 436 Addr secondAddr = roundDown(addr + dataSize - 1, blockSize); 437 438 if(secondAddr > addr) 439 dataSize = secondAddr - addr; 440 441 dcache_latency = 0; 442 443 while(1) { 444 req->setVirt(0, addr, dataSize, flags, thread->readPC()); 445 446 // translate to physical address 447 Fault fault = thread->translateDataWriteReq(req); 448 449 // Now do the access. 450 if (fault == NoFault) { 451 MemCmd cmd = MemCmd::WriteReq; // default 452 bool do_access = true; // flag to suppress cache access 453 454 if (req->isLocked()) { 455 cmd = MemCmd::StoreCondReq; 456 do_access = TheISA::handleLockedWrite(thread, req); 457 } else if (req->isSwap()) { 458 cmd = MemCmd::SwapReq; 459 if (req->isCondSwap()) { 460 assert(res); 461 req->setExtraData(*res); 462 } |
409 } | 463 } |
410 } | |
411 | 464 |
412 if (do_access) { 413 Packet pkt = Packet(req, cmd, Packet::Broadcast); 414 pkt.dataStatic(&data); | 465 if (do_access) { 466 Packet pkt = Packet(req, cmd, Packet::Broadcast); 467 pkt.dataStatic(dataPtr); |
415 | 468 |
416 if (req->isMmapedIpr()) { 417 dcache_latency = TheISA::handleIprWrite(thread->getTC(), &pkt); 418 } else { 419 data = htog(data); 420 if (hasPhysMemPort && pkt.getAddr() == physMemAddr) 421 dcache_latency = physmemPort.sendAtomic(&pkt); 422 else 423 dcache_latency = dcachePort.sendAtomic(&pkt); | 469 if (req->isMmapedIpr()) { 470 dcache_latency += 471 TheISA::handleIprWrite(thread->getTC(), &pkt); 472 } else { 473 //XXX This needs to be outside of the loop in order to 474 //work properly for cache line boundary crossing 475 //accesses in transendian simulations. 476 data = htog(data); 477 if (hasPhysMemPort && pkt.getAddr() == physMemAddr) 478 dcache_latency += physmemPort.sendAtomic(&pkt); 479 else 480 dcache_latency += dcachePort.sendAtomic(&pkt); 481 } 482 dcache_access = true; 483 assert(!pkt.isError()); 484 485 if (req->isSwap()) { 486 assert(res); 487 *res = pkt.get<T>(); 488 } |
424 } | 489 } |
425 dcache_access = true; 426 assert(!pkt.isError()); | |
427 | 490 |
428 if (req->isSwap()) { 429 assert(res); 430 *res = pkt.get<T>(); | 491 if (res && !req->isSwap()) { 492 *res = req->getExtraData(); |
431 } 432 } 433 | 493 } 494 } 495 |
434 if (res && !req->isSwap()) { 435 *res = req->getExtraData(); | 496 // This will need a new way to tell if it's hooked up to a cache or not. 497 if (req->isUncacheable()) 498 recordEvent("Uncached Write"); 499 500 //If there's a fault or we don't need to access a second cache line, 501 //stop now. 502 if (fault != NoFault || secondAddr <= addr) 503 { 504 // If the write needs to have a fault on the access, consider 505 // calling changeStatus() and changing it to "bad addr write" 506 // or something. 507 return fault; |
436 } | 508 } |
437 } | |
438 | 509 |
439 // This will need a new way to tell if it's hooked up to a cache or not. 440 if (req->isUncacheable()) 441 recordEvent("Uncached Write"); | 510 /* 511 * Set up for accessing the second cache line. 512 */ |
442 | 513 |
443 // If the write needs to have a fault on the access, consider calling 444 // changeStatus() and changing it to "bad addr write" or something. 445 return fault; | 514 //Move the pointer we're reading into to the correct location. 515 dataPtr += dataSize; 516 //Adjust the size to get the remaining bytes. 517 dataSize = addr + sizeof(T) - secondAddr; 518 //And access the right address. 519 addr = secondAddr; 520 } |
446} 447 448 449#ifndef DOXYGEN_SHOULD_SKIP_THIS 450 451template 452Fault 453AtomicSimpleCPU::write(Twin32_t data, Addr addr, --- 172 unchanged lines hidden --- | 521} 522 523 524#ifndef DOXYGEN_SHOULD_SKIP_THIS 525 526template 527Fault 528AtomicSimpleCPU::write(Twin32_t data, Addr addr, --- 172 unchanged lines hidden --- |