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 &section)
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 ---