atomic.cc (7518:917208416d2a) atomic.cc (7520:67c670459d01)
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;

--- 280 unchanged lines hidden (view full) ---

289 if (tickEvent.scheduled())
290 deschedule(tickEvent);
291
292 notIdleFraction--;
293 _status = Idle;
294}
295
296
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;

--- 280 unchanged lines hidden (view full) ---

289 if (tickEvent.scheduled())
290 deschedule(tickEvent);
291
292 notIdleFraction--;
293 _status = Idle;
294}
295
296
297template <class T>
298Fault
297Fault
299AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags)
298AtomicSimpleCPU::readBytes(Addr addr, uint8_t * data,
299 unsigned size, unsigned flags)
300{
301 // use the CPU's statically allocated read request and packet objects
302 Request *req = &data_read_req;
303
304 if (traceData) {
305 traceData->setAddr(addr);
306 }
307
308 //The block size of our peer.
309 unsigned blockSize = dcachePort.peerBlockSize();
310 //The size of the data we're trying to read.
300{
301 // use the CPU's statically allocated read request and packet objects
302 Request *req = &data_read_req;
303
304 if (traceData) {
305 traceData->setAddr(addr);
306 }
307
308 //The block size of our peer.
309 unsigned blockSize = dcachePort.peerBlockSize();
310 //The size of the data we're trying to read.
311 int dataSize = sizeof(T);
311 int fullSize = size;
312
312
313 uint8_t * dataPtr = (uint8_t *)&data;
314
315 //The address of the second part of this access if it needs to be split
316 //across a cache line boundary.
313 //The address of the second part of this access if it needs to be split
314 //across a cache line boundary.
317 Addr secondAddr = roundDown(addr + dataSize - 1, blockSize);
315 Addr secondAddr = roundDown(addr + size - 1, blockSize);
318
316
319 if(secondAddr > addr)
320 dataSize = secondAddr - addr;
317 if (secondAddr > addr)
318 size = secondAddr - addr;
321
322 dcache_latency = 0;
323
319
320 dcache_latency = 0;
321
324 while(1) {
325 req->setVirt(0, addr, dataSize, flags, thread->readPC());
322 while (1) {
323 req->setVirt(0, addr, size, flags, thread->readPC());
326
327 // translate to physical address
328 Fault fault = thread->dtb->translateAtomic(req, tc, BaseTLB::Read);
329
330 // Now do the access.
331 if (fault == NoFault && !req->getFlags().isSet(Request::NO_ACCESS)) {
332 Packet pkt = Packet(req,
333 req->isLLSC() ? MemCmd::LoadLockedReq : MemCmd::ReadReq,
334 Packet::Broadcast);
324
325 // translate to physical address
326 Fault fault = thread->dtb->translateAtomic(req, tc, BaseTLB::Read);
327
328 // Now do the access.
329 if (fault == NoFault && !req->getFlags().isSet(Request::NO_ACCESS)) {
330 Packet pkt = Packet(req,
331 req->isLLSC() ? MemCmd::LoadLockedReq : MemCmd::ReadReq,
332 Packet::Broadcast);
335 pkt.dataStatic(dataPtr);
333 pkt.dataStatic(data);
336
337 if (req->isMmapedIpr())
338 dcache_latency += TheISA::handleIprRead(thread->getTC(), &pkt);
339 else {
340 if (hasPhysMemPort && pkt.getAddr() == physMemAddr)
341 dcache_latency += physmemPort.sendAtomic(&pkt);
342 else
343 dcache_latency += dcachePort.sendAtomic(&pkt);

--- 14 unchanged lines hidden (view full) ---

358 } else {
359 return fault;
360 }
361 }
362
363 //If we don't need to access a second cache line, stop now.
364 if (secondAddr <= addr)
365 {
334
335 if (req->isMmapedIpr())
336 dcache_latency += TheISA::handleIprRead(thread->getTC(), &pkt);
337 else {
338 if (hasPhysMemPort && pkt.getAddr() == physMemAddr)
339 dcache_latency += physmemPort.sendAtomic(&pkt);
340 else
341 dcache_latency += dcachePort.sendAtomic(&pkt);

--- 14 unchanged lines hidden (view full) ---

356 } else {
357 return fault;
358 }
359 }
360
361 //If we don't need to access a second cache line, stop now.
362 if (secondAddr <= addr)
363 {
366 data = gtoh(data);
367 if (traceData) {
368 traceData->setData(data);
369 }
370 if (req->isLocked() && fault == NoFault) {
371 assert(!locked);
372 locked = true;
373 }
374 return fault;
375 }
376
377 /*
378 * Set up for accessing the second cache line.
379 */
380
381 //Move the pointer we're reading into to the correct location.
364 if (req->isLocked() && fault == NoFault) {
365 assert(!locked);
366 locked = true;
367 }
368 return fault;
369 }
370
371 /*
372 * Set up for accessing the second cache line.
373 */
374
375 //Move the pointer we're reading into to the correct location.
382 dataPtr += dataSize;
376 data += size;
383 //Adjust the size to get the remaining bytes.
377 //Adjust the size to get the remaining bytes.
384 dataSize = addr + sizeof(T) - secondAddr;
378 size = addr + fullSize - secondAddr;
385 //And access the right address.
386 addr = secondAddr;
387 }
388}
389
379 //And access the right address.
380 addr = secondAddr;
381 }
382}
383
384
385template <class T>
386Fault
387AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags)
388{
389 uint8_t *dataPtr = (uint8_t *)&data;
390 memset(dataPtr, 0, sizeof(data));
391 Fault fault = readBytes(addr, dataPtr, sizeof(data), flags);
392 if (fault == NoFault) {
393 data = gtoh(data);
394 if (traceData)
395 traceData->setData(data);
396 }
397 return fault;
398}
399
390#ifndef DOXYGEN_SHOULD_SKIP_THIS
391
392template
393Fault
394AtomicSimpleCPU::read(Addr addr, Twin32_t &data, unsigned flags);
395
396template
397Fault

--- 35 unchanged lines hidden (view full) ---

433template<>
434Fault
435AtomicSimpleCPU::read(Addr addr, int32_t &data, unsigned flags)
436{
437 return read(addr, (uint32_t&)data, flags);
438}
439
440
400#ifndef DOXYGEN_SHOULD_SKIP_THIS
401
402template
403Fault
404AtomicSimpleCPU::read(Addr addr, Twin32_t &data, unsigned flags);
405
406template
407Fault

--- 35 unchanged lines hidden (view full) ---

443template<>
444Fault
445AtomicSimpleCPU::read(Addr addr, int32_t &data, unsigned flags)
446{
447 return read(addr, (uint32_t&)data, flags);
448}
449
450
441template <class T>
442Fault
451Fault
443AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
452AtomicSimpleCPU::writeBytes(uint8_t *data, unsigned size,
453 Addr addr, unsigned flags, uint64_t *res)
444{
445 // use the CPU's statically allocated write request and packet objects
446 Request *req = &data_write_req;
447
448 if (traceData) {
449 traceData->setAddr(addr);
454{
455 // use the CPU's statically allocated write request and packet objects
456 Request *req = &data_write_req;
457
458 if (traceData) {
459 traceData->setAddr(addr);
450 traceData->setData(data);
451 }
452
460 }
461
453 data = htog(data);
454
455 //The block size of our peer.
456 unsigned blockSize = dcachePort.peerBlockSize();
457 //The size of the data we're trying to read.
462 //The block size of our peer.
463 unsigned blockSize = dcachePort.peerBlockSize();
464 //The size of the data we're trying to read.
458 int dataSize = sizeof(T);
465 int fullSize = size;
459
466
460 uint8_t * dataPtr = (uint8_t *)&data;
461
462 //The address of the second part of this access if it needs to be split
463 //across a cache line boundary.
467 //The address of the second part of this access if it needs to be split
468 //across a cache line boundary.
464 Addr secondAddr = roundDown(addr + dataSize - 1, blockSize);
469 Addr secondAddr = roundDown(addr + size - 1, blockSize);
465
466 if(secondAddr > addr)
470
471 if(secondAddr > addr)
467 dataSize = secondAddr - addr;
472 size = secondAddr - addr;
468
469 dcache_latency = 0;
470
471 while(1) {
473
474 dcache_latency = 0;
475
476 while(1) {
472 req->setVirt(0, addr, dataSize, flags, thread->readPC());
477 req->setVirt(0, addr, size, flags, thread->readPC());
473
474 // translate to physical address
475 Fault fault = thread->dtb->translateAtomic(req, tc, BaseTLB::Write);
476
477 // Now do the access.
478 if (fault == NoFault) {
479 MemCmd cmd = MemCmd::WriteReq; // default
480 bool do_access = true; // flag to suppress cache access

--- 6 unchanged lines hidden (view full) ---

487 if (req->isCondSwap()) {
488 assert(res);
489 req->setExtraData(*res);
490 }
491 }
492
493 if (do_access && !req->getFlags().isSet(Request::NO_ACCESS)) {
494 Packet pkt = Packet(req, cmd, Packet::Broadcast);
478
479 // translate to physical address
480 Fault fault = thread->dtb->translateAtomic(req, tc, BaseTLB::Write);
481
482 // Now do the access.
483 if (fault == NoFault) {
484 MemCmd cmd = MemCmd::WriteReq; // default
485 bool do_access = true; // flag to suppress cache access

--- 6 unchanged lines hidden (view full) ---

492 if (req->isCondSwap()) {
493 assert(res);
494 req->setExtraData(*res);
495 }
496 }
497
498 if (do_access && !req->getFlags().isSet(Request::NO_ACCESS)) {
499 Packet pkt = Packet(req, cmd, Packet::Broadcast);
495 pkt.dataStatic(dataPtr);
500 pkt.dataStatic(data);
496
497 if (req->isMmapedIpr()) {
498 dcache_latency +=
499 TheISA::handleIprWrite(thread->getTC(), &pkt);
500 } else {
501 if (hasPhysMemPort && pkt.getAddr() == physMemAddr)
502 dcache_latency += physmemPort.sendAtomic(&pkt);
503 else
504 dcache_latency += dcachePort.sendAtomic(&pkt);
505 }
506 dcache_access = true;
507 assert(!pkt.isError());
508
509 if (req->isSwap()) {
510 assert(res);
501
502 if (req->isMmapedIpr()) {
503 dcache_latency +=
504 TheISA::handleIprWrite(thread->getTC(), &pkt);
505 } else {
506 if (hasPhysMemPort && pkt.getAddr() == physMemAddr)
507 dcache_latency += physmemPort.sendAtomic(&pkt);
508 else
509 dcache_latency += dcachePort.sendAtomic(&pkt);
510 }
511 dcache_access = true;
512 assert(!pkt.isError());
513
514 if (req->isSwap()) {
515 assert(res);
511 *res = pkt.get<T>();
516 memcpy(res, pkt.getPtr<uint8_t>(), fullSize);
512 }
513 }
514
515 if (res && !req->isSwap()) {
516 *res = req->getExtraData();
517 }
518 }
519

--- 12 unchanged lines hidden (view full) ---

532 }
533 }
534
535 /*
536 * Set up for accessing the second cache line.
537 */
538
539 //Move the pointer we're reading into to the correct location.
517 }
518 }
519
520 if (res && !req->isSwap()) {
521 *res = req->getExtraData();
522 }
523 }
524

--- 12 unchanged lines hidden (view full) ---

537 }
538 }
539
540 /*
541 * Set up for accessing the second cache line.
542 */
543
544 //Move the pointer we're reading into to the correct location.
540 dataPtr += dataSize;
545 data += size;
541 //Adjust the size to get the remaining bytes.
546 //Adjust the size to get the remaining bytes.
542 dataSize = addr + sizeof(T) - secondAddr;
547 size = addr + fullSize - secondAddr;
543 //And access the right address.
544 addr = secondAddr;
545 }
546}
547
548
548 //And access the right address.
549 addr = secondAddr;
550 }
551}
552
553
554template <class T>
555Fault
556AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
557{
558 uint8_t *dataPtr = (uint8_t *)&data;
559 if (traceData)
560 traceData->setData(data);
561 data = htog(data);
562
563 Fault fault = writeBytes(dataPtr, sizeof(data), addr, flags, res);
564 if (fault == NoFault && data_write_req.isSwap()) {
565 *res = gtoh((T)*res);
566 }
567 return fault;
568}
569
570
549#ifndef DOXYGEN_SHOULD_SKIP_THIS
550
551template
552Fault
553AtomicSimpleCPU::write(Twin32_t data, Addr addr,
554 unsigned flags, uint64_t *res);
555
556template

--- 177 unchanged lines hidden ---
571#ifndef DOXYGEN_SHOULD_SKIP_THIS
572
573template
574Fault
575AtomicSimpleCPU::write(Twin32_t data, Addr addr,
576 unsigned flags, uint64_t *res);
577
578template

--- 177 unchanged lines hidden ---