atomic.cc (9433:34971d2e0019) | atomic.cc (9443:0cb3209bc5c7) |
---|---|
1/* 2 * Copyright (c) 2012 ARM Limited 3 * All rights reserved. 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software --- 33 unchanged lines hidden (view full) --- 42 43#include "arch/locked_mem.hh" 44#include "arch/mmapped_ipr.hh" 45#include "arch/utility.hh" 46#include "base/bigint.hh" 47#include "config/the_isa.hh" 48#include "cpu/simple/atomic.hh" 49#include "cpu/exetrace.hh" | 1/* 2 * Copyright (c) 2012 ARM Limited 3 * All rights reserved. 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software --- 33 unchanged lines hidden (view full) --- 42 43#include "arch/locked_mem.hh" 44#include "arch/mmapped_ipr.hh" 45#include "arch/utility.hh" 46#include "base/bigint.hh" 47#include "config/the_isa.hh" 48#include "cpu/simple/atomic.hh" 49#include "cpu/exetrace.hh" |
50#include "debug/Drain.hh" |
|
50#include "debug/ExecFaulting.hh" 51#include "debug/SimpleCPU.hh" 52#include "mem/packet.hh" 53#include "mem/packet_access.hh" 54#include "mem/physical.hh" 55#include "params/AtomicSimpleCPU.hh" 56#include "sim/faults.hh" 57#include "sim/system.hh" --- 48 unchanged lines hidden (view full) --- 106 data_read_req.setThreadContext(_cpuId, 0); // Add thread ID here too 107 data_write_req.setThreadContext(_cpuId, 0); // Add thread ID here too 108} 109 110AtomicSimpleCPU::AtomicSimpleCPU(AtomicSimpleCPUParams *p) 111 : BaseSimpleCPU(p), tickEvent(this), width(p->width), locked(false), 112 simulate_data_stalls(p->simulate_data_stalls), 113 simulate_inst_stalls(p->simulate_inst_stalls), | 51#include "debug/ExecFaulting.hh" 52#include "debug/SimpleCPU.hh" 53#include "mem/packet.hh" 54#include "mem/packet_access.hh" 55#include "mem/physical.hh" 56#include "params/AtomicSimpleCPU.hh" 57#include "sim/faults.hh" 58#include "sim/system.hh" --- 48 unchanged lines hidden (view full) --- 107 data_read_req.setThreadContext(_cpuId, 0); // Add thread ID here too 108 data_write_req.setThreadContext(_cpuId, 0); // Add thread ID here too 109} 110 111AtomicSimpleCPU::AtomicSimpleCPU(AtomicSimpleCPUParams *p) 112 : BaseSimpleCPU(p), tickEvent(this), width(p->width), locked(false), 113 simulate_data_stalls(p->simulate_data_stalls), 114 simulate_inst_stalls(p->simulate_inst_stalls), |
115 drain_manager(NULL), |
|
114 icachePort(name() + ".icache_port", this), 115 dcachePort(name() + ".dcache_port", this), 116 fastmem(p->fastmem) 117{ 118 _status = Idle; 119} 120 121 122AtomicSimpleCPU::~AtomicSimpleCPU() 123{ 124 if (tickEvent.scheduled()) { 125 deschedule(tickEvent); 126 } 127} 128 | 116 icachePort(name() + ".icache_port", this), 117 dcachePort(name() + ".dcache_port", this), 118 fastmem(p->fastmem) 119{ 120 _status = Idle; 121} 122 123 124AtomicSimpleCPU::~AtomicSimpleCPU() 125{ 126 if (tickEvent.scheduled()) { 127 deschedule(tickEvent); 128 } 129} 130 |
129void 130AtomicSimpleCPU::serialize(ostream &os) | 131unsigned int 132AtomicSimpleCPU::drain(DrainManager *dm) |
131{ | 133{ |
132 Drainable::State so_state(getDrainState()); 133 SERIALIZE_ENUM(so_state); 134 SERIALIZE_SCALAR(locked); 135 BaseSimpleCPU::serialize(os); 136 nameOut(os, csprintf("%s.tickEvent", name())); 137 tickEvent.serialize(os); 138} | 134 assert(!drain_manager); 135 if (_status == SwitchedOut) 136 return 0; |
139 | 137 |
140void 141AtomicSimpleCPU::unserialize(Checkpoint *cp, const string §ion) 142{ 143 Drainable::State so_state; 144 UNSERIALIZE_ENUM(so_state); 145 UNSERIALIZE_SCALAR(locked); 146 BaseSimpleCPU::unserialize(cp, section); 147 tickEvent.unserialize(cp, csprintf("%s.tickEvent", section)); 148} | 138 if (!isDrained()) { 139 DPRINTF(Drain, "Requesting drain: %s\n", pcState()); 140 drain_manager = dm; 141 return 1; 142 } else { 143 if (tickEvent.scheduled()) 144 deschedule(tickEvent); |
149 | 145 |
150unsigned int 151AtomicSimpleCPU::drain(DrainManager *drain_manager) 152{ 153 setDrainState(Drainable::Drained); 154 return 0; | 146 DPRINTF(Drain, "Not executing microcode, no need to drain.\n"); 147 return 0; 148 } |
155} 156 157void 158AtomicSimpleCPU::drainResume() 159{ | 149} 150 151void 152AtomicSimpleCPU::drainResume() 153{ |
154 assert(!drain_manager); |
|
160 if (_status == Idle || _status == SwitchedOut) 161 return; 162 163 DPRINTF(SimpleCPU, "Resume\n"); 164 if (system->getMemoryMode() != Enums::atomic) { 165 fatal("The atomic CPU requires the memory system to be in " 166 "'atomic' mode.\n"); 167 } 168 | 155 if (_status == Idle || _status == SwitchedOut) 156 return; 157 158 DPRINTF(SimpleCPU, "Resume\n"); 159 if (system->getMemoryMode() != Enums::atomic) { 160 fatal("The atomic CPU requires the memory system to be in " 161 "'atomic' mode.\n"); 162 } 163 |
169 setDrainState(Drainable::Running); 170 if (thread->status() == ThreadContext::Active) { 171 if (!tickEvent.scheduled()) 172 schedule(tickEvent, nextCycle()); 173 } | 164 assert(!tickEvent.scheduled()); 165 if (thread->status() == ThreadContext::Active) 166 schedule(tickEvent, nextCycle()); 167 |
174 system->totalNumInsts = 0; 175} 176 | 168 system->totalNumInsts = 0; 169} 170 |
171bool 172AtomicSimpleCPU::tryCompleteDrain() 173{ 174 if (!drain_manager) 175 return false; 176 177 DPRINTF(Drain, "tryCompleteDrain: %s\n", pcState()); 178 if (!isDrained()) 179 return false; 180 181 DPRINTF(Drain, "CPU done draining, processing drain event\n"); 182 drain_manager->signalDrainDone(); 183 drain_manager = NULL; 184 185 return true; 186} 187 188 |
|
177void 178AtomicSimpleCPU::switchOut() 179{ 180 BaseSimpleCPU::switchOut(); 181 | 189void 190AtomicSimpleCPU::switchOut() 191{ 192 BaseSimpleCPU::switchOut(); 193 |
194 assert(!tickEvent.scheduled()); |
|
182 assert(_status == BaseSimpleCPU::Running || _status == Idle); | 195 assert(_status == BaseSimpleCPU::Running || _status == Idle); |
183 _status = SwitchedOut; | 196 assert(isDrained()); |
184 | 197 |
185 tickEvent.squash(); | 198 _status = SwitchedOut; |
186} 187 188 189void 190AtomicSimpleCPU::takeOverFrom(BaseCPU *oldCPU) 191{ 192 BaseSimpleCPU::takeOverFrom(oldCPU); 193 | 199} 200 201 202void 203AtomicSimpleCPU::takeOverFrom(BaseCPU *oldCPU) 204{ 205 BaseSimpleCPU::takeOverFrom(oldCPU); 206 |
207 // The tick event should have been descheduled by drain() |
|
194 assert(!tickEvent.scheduled()); 195 | 208 assert(!tickEvent.scheduled()); 209 |
196 // if any of this CPU's ThreadContexts are active, mark the CPU as 197 // running and schedule its tick event. 198 ThreadID size = threadContexts.size(); 199 for (ThreadID i = 0; i < size; ++i) { 200 ThreadContext *tc = threadContexts[i]; 201 if (tc->status() == ThreadContext::Active && 202 _status != BaseSimpleCPU::Running) { 203 _status = BaseSimpleCPU::Running; 204 schedule(tickEvent, nextCycle()); 205 break; 206 } 207 } 208 if (_status != BaseSimpleCPU::Running) { | 210 assert(!threadContexts.empty()); 211 if (threadContexts.size() > 1) 212 fatal("The atomic CPU only supports one thread.\n"); 213 214 // If the ThreadContext is active, mark the CPU as running. 215 if (thread->status() == ThreadContext::Active) 216 _status = BaseSimpleCPU::Running; 217 else |
209 _status = Idle; | 218 _status = Idle; |
210 } 211 assert(threadContexts.size() == 1); | 219 |
212 ifetch_req.setThreadContext(_cpuId, 0); // Add thread ID if we add MT 213 data_read_req.setThreadContext(_cpuId, 0); // Add thread ID here too 214 data_write_req.setThreadContext(_cpuId, 0); // Add thread ID here too 215} 216 217 218void 219AtomicSimpleCPU::activateContext(ThreadID thread_num, Cycles delay) --- 239 unchanged lines hidden (view full) --- 459 for (int i = 0; i < width || locked; ++i) { 460 numCycles++; 461 462 if (!curStaticInst || !curStaticInst->isDelayedCommit()) 463 checkForInterrupts(); 464 465 checkPcEventQueue(); 466 // We must have just got suspended by a PC event | 220 ifetch_req.setThreadContext(_cpuId, 0); // Add thread ID if we add MT 221 data_read_req.setThreadContext(_cpuId, 0); // Add thread ID here too 222 data_write_req.setThreadContext(_cpuId, 0); // Add thread ID here too 223} 224 225 226void 227AtomicSimpleCPU::activateContext(ThreadID thread_num, Cycles delay) --- 239 unchanged lines hidden (view full) --- 467 for (int i = 0; i < width || locked; ++i) { 468 numCycles++; 469 470 if (!curStaticInst || !curStaticInst->isDelayedCommit()) 471 checkForInterrupts(); 472 473 checkPcEventQueue(); 474 // We must have just got suspended by a PC event |
467 if (_status == Idle) | 475 if (_status == Idle) { 476 tryCompleteDrain(); |
468 return; | 477 return; |
478 } |
|
469 470 Fault fault = NoFault; 471 472 TheISA::PCState pcState = thread->pcState(); 473 474 bool needToFetch = !isRomMicroPC(pcState.microPC()) && 475 !curMacroStaticInst; 476 if (needToFetch) { --- 67 unchanged lines hidden (view full) --- 544 clockPeriod(); 545 } 546 547 } 548 if(fault != NoFault || !stayAtPC) 549 advancePC(fault); 550 } 551 | 479 480 Fault fault = NoFault; 481 482 TheISA::PCState pcState = thread->pcState(); 483 484 bool needToFetch = !isRomMicroPC(pcState.microPC()) && 485 !curMacroStaticInst; 486 if (needToFetch) { --- 67 unchanged lines hidden (view full) --- 554 clockPeriod(); 555 } 556 557 } 558 if(fault != NoFault || !stayAtPC) 559 advancePC(fault); 560 } 561 |
562 if (tryCompleteDrain()) 563 return; 564 |
|
552 // instruction takes at least one cycle 553 if (latency < clockPeriod()) 554 latency = clockPeriod(); 555 556 if (_status != Idle) 557 schedule(tickEvent, curTick() + latency); 558} 559 --- 20 unchanged lines hidden --- | 565 // instruction takes at least one cycle 566 if (latency < clockPeriod()) 567 latency = clockPeriod(); 568 569 if (_status != Idle) 570 schedule(tickEvent, curTick() + latency); 571} 572 --- 20 unchanged lines hidden --- |