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 ---