X86: Add a .serializing directive that makes a macroop serializing.
[gem5.git] / src / cpu / ozone / cpu.hh
1 /*
2 * Copyright (c) 2006 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;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Kevin Lim
29 */
30
31 #ifndef __CPU_OZONE_CPU_HH__
32 #define __CPU_OZONE_CPU_HH__
33
34 #include <set>
35
36 #include "base/statistics.hh"
37 #include "base/timebuf.hh"
38 #include "config/full_system.hh"
39 #include "config/the_isa.hh"
40 #include "cpu/base.hh"
41 #include "cpu/thread_context.hh"
42 #include "cpu/inst_seq.hh"
43 #include "cpu/ozone/rename_table.hh"
44 #include "cpu/ozone/thread_state.hh"
45 #include "cpu/pc_event.hh"
46 #include "cpu/static_inst.hh"
47 #include "mem/page_table.hh"
48 #include "sim/eventq.hh"
49
50 // forward declarations
51 #if FULL_SYSTEM
52 #include "arch/alpha/tlb.hh"
53
54 namespace TheISA
55 {
56 class TLB;
57 }
58 class PhysicalMemory;
59 class MemoryController;
60
61 namespace TheISA {
62 namespace Kernel {
63 class Statistics;
64 };
65 };
66
67 #else
68
69 class Process;
70
71 #endif // FULL_SYSTEM
72
73 class Checkpoint;
74 class EndQuiesceEvent;
75 class MemObject;
76 class Request;
77
78 namespace Trace {
79 class InstRecord;
80 }
81
82 template <class>
83 class Checker;
84
85 /**
86 * Light weight out of order CPU model that approximates an out of
87 * order CPU. It is separated into a front end and a back end, with
88 * the template parameter Impl describing the classes used for each.
89 * The goal is to be able to specify through the Impl the class to use
90 * for the front end and back end, with different classes used to
91 * model different levels of detail.
92 */
93 template <class Impl>
94 class OzoneCPU : public BaseCPU
95 {
96 private:
97 typedef typename Impl::FrontEnd FrontEnd;
98 typedef typename Impl::BackEnd BackEnd;
99 typedef typename Impl::DynInst DynInst;
100 typedef typename Impl::DynInstPtr DynInstPtr;
101
102 typedef TheISA::FloatReg FloatReg;
103 typedef TheISA::FloatRegBits FloatRegBits;
104 typedef TheISA::MiscReg MiscReg;
105
106 public:
107 class OzoneTC : public ThreadContext {
108 public:
109 OzoneCPU<Impl> *cpu;
110
111 OzoneThreadState<Impl> *thread;
112
113 BaseCPU *getCpuPtr();
114
115 TheISA::TLB *getITBPtr() { return cpu->itb; }
116
117 TheISA::TLB * getDTBPtr() { return cpu->dtb; }
118
119 #if FULL_SYSTEM
120 System *getSystemPtr() { return cpu->system; }
121
122 PhysicalMemory *getPhysMemPtr() { return cpu->physmem; }
123
124 TheISA::Kernel::Statistics *getKernelStats()
125 { return thread->getKernelStats(); }
126
127 FunctionalPort *getPhysPort() { return thread->getPhysPort(); }
128
129 VirtualPort *getVirtPort()
130 { return thread->getVirtPort(); }
131 #else
132 TranslatingPort *getMemPort() { return thread->getMemPort(); }
133
134 Process *getProcessPtr() { return thread->getProcessPtr(); }
135 #endif
136
137 Status status() const { return thread->status(); }
138
139 void setStatus(Status new_status);
140
141 /// Set the status to Active. Optional delay indicates number of
142 /// cycles to wait before beginning execution.
143 void activate(int delay = 1);
144
145 /// Set the status to Suspended.
146 void suspend();
147
148 /// Set the status to Halted.
149 void halt();
150
151 #if FULL_SYSTEM
152 void dumpFuncProfile();
153 #endif
154
155 void takeOverFrom(ThreadContext *old_context);
156
157 void regStats(const std::string &name);
158
159 void serialize(std::ostream &os);
160 void unserialize(Checkpoint *cp, const std::string &section);
161
162 #if FULL_SYSTEM
163 EndQuiesceEvent *getQuiesceEvent();
164
165 Tick readLastActivate();
166 Tick readLastSuspend();
167
168 void profileClear();
169 void profileSample();
170 #endif
171
172 int threadId();
173
174 // Also somewhat obnoxious. Really only used for the TLB fault.
175 TheISA::MachInst getInst();
176
177 void copyArchRegs(ThreadContext *tc);
178
179 void clearArchRegs();
180
181 uint64_t readIntReg(int reg_idx);
182
183 FloatReg readFloatReg(int reg_idx);
184
185 FloatRegBits readFloatRegBits(int reg_idx);
186
187 void setIntReg(int reg_idx, uint64_t val);
188
189 void setFloatReg(int reg_idx, FloatReg val);
190
191 void setFloatRegBits(int reg_idx, FloatRegBits val);
192
193 uint64_t readPC() { return thread->PC; }
194 void setPC(Addr val);
195
196 uint64_t readNextPC() { return thread->nextPC; }
197 void setNextPC(Addr val);
198
199 uint64_t readNextNPC()
200 {
201 #if ISA_HAS_DELAY_SLOT
202 panic("Ozone needs to support nextNPC");
203 #else
204 return thread->nextPC + sizeof(TheISA::MachInst);
205 #endif
206 }
207
208 void setNextNPC(uint64_t val)
209 {
210 #if ISA_HAS_DELAY_SLOT
211 panic("Ozone needs to support nextNPC");
212 #endif
213 }
214
215 public:
216 // ISA stuff:
217 MiscReg readMiscRegNoEffect(int misc_reg);
218
219 MiscReg readMiscReg(int misc_reg);
220
221 void setMiscRegNoEffect(int misc_reg, const MiscReg &val);
222
223 void setMiscReg(int misc_reg, const MiscReg &val);
224
225 unsigned readStCondFailures()
226 { return thread->storeCondFailures; }
227
228 void setStCondFailures(unsigned sc_failures)
229 { thread->storeCondFailures = sc_failures; }
230
231 bool misspeculating() { return false; }
232
233 #if !FULL_SYSTEM
234 Counter readFuncExeInst() { return thread->funcExeInst; }
235
236 void setFuncExeInst(Counter new_val)
237 { thread->funcExeInst = new_val; }
238 #endif
239 };
240
241 // Ozone specific thread context
242 OzoneTC ozoneTC;
243 // Thread context to be used
244 ThreadContext *tc;
245 // Checker thread context; will wrap the OzoneTC if a checker is
246 // being used.
247 ThreadContext *checkerTC;
248
249 typedef OzoneThreadState<Impl> ImplState;
250
251 private:
252 // Committed thread state for the OzoneCPU.
253 OzoneThreadState<Impl> thread;
254
255 public:
256 // main simulation loop (one cycle)
257 void tick();
258
259 #ifndef NDEBUG
260 /** Count of total number of dynamic instructions in flight. */
261 int instcount;
262 #endif
263
264 std::set<InstSeqNum> snList;
265 std::set<Addr> lockAddrList;
266 private:
267 struct TickEvent : public Event
268 {
269 OzoneCPU *cpu;
270 int width;
271
272 TickEvent(OzoneCPU *c, int w);
273 void process();
274 const char *description() const;
275 };
276
277 TickEvent tickEvent;
278
279 /// Schedule tick event, regardless of its current state.
280 void scheduleTickEvent(int delay)
281 {
282 if (tickEvent.squashed())
283 tickEvent.reschedule(curTick + ticks(delay));
284 else if (!tickEvent.scheduled())
285 tickEvent.schedule(curTick + ticks(delay));
286 }
287
288 /// Unschedule tick event, regardless of its current state.
289 void unscheduleTickEvent()
290 {
291 if (tickEvent.scheduled())
292 tickEvent.squash();
293 }
294
295 public:
296 enum Status {
297 Running,
298 Idle,
299 SwitchedOut
300 };
301
302 Status _status;
303
304 public:
305 void wakeup();
306
307 void zero_fill_64(Addr addr) {
308 static int warned = 0;
309 if (!warned) {
310 warn ("WH64 is not implemented");
311 warned = 1;
312 }
313 };
314
315 typedef typename Impl::Params Params;
316
317 OzoneCPU(Params *params);
318
319 virtual ~OzoneCPU();
320
321 void init();
322
323 public:
324 BaseCPU *getCpuPtr() { return this; }
325
326 void switchOut();
327 void signalSwitched();
328 void takeOverFrom(BaseCPU *oldCPU);
329
330 int switchCount;
331
332 #if FULL_SYSTEM
333 Addr dbg_vtophys(Addr addr);
334
335 bool interval_stats;
336
337 TheISA::TLB *itb;
338 TheISA::TLB *dtb;
339 System *system;
340 PhysicalMemory *physmem;
341 #endif
342
343 virtual Port *getPort(const std::string &name, int idx);
344
345 FrontEnd *frontEnd;
346
347 BackEnd *backEnd;
348
349 private:
350 Status status() const { return _status; }
351 void setStatus(Status new_status) { _status = new_status; }
352
353 virtual void activateContext(int thread_num, int delay);
354 virtual void suspendContext(int thread_num);
355 virtual void deallocateContext(int thread_num, int delay);
356 virtual void haltContext(int thread_num);
357
358 // statistics
359 virtual void regStats();
360 virtual void resetStats();
361
362 // number of simulated instructions
363 public:
364 Counter numInst;
365 Counter startNumInst;
366
367 virtual Counter totalInstructions() const
368 {
369 return numInst - startNumInst;
370 }
371
372 private:
373 // number of simulated loads
374 Counter numLoad;
375 Counter startNumLoad;
376
377 // number of idle cycles
378 Stats::Average notIdleFraction;
379 Stats::Formula idleFraction;
380
381 public:
382 virtual void serialize(std::ostream &os);
383 virtual void unserialize(Checkpoint *cp, const std::string &section);
384
385 void demapPage(Addr vaddr, uint64_t asn)
386 {
387 cpu->itb->demap(vaddr, asn);
388 cpu->dtb->demap(vaddr, asn);
389 }
390
391 void demapInstPage(Addr vaddr, uint64_t asn)
392 {
393 cpu->itb->demap(vaddr, asn);
394 }
395
396 void demapDataPage(Addr vaddr, uint64_t asn)
397 {
398 cpu->dtb->demap(vaddr, asn);
399 }
400
401 /** CPU read function, forwards read to LSQ. */
402 template <class T>
403 Fault read(Request *req, T &data, int load_idx)
404 {
405 return backEnd->read(req, data, load_idx);
406 }
407
408 /** CPU write function, forwards write to LSQ. */
409 template <class T>
410 Fault write(Request *req, T &data, int store_idx)
411 {
412 return backEnd->write(req, data, store_idx);
413 }
414
415 void prefetch(Addr addr, unsigned flags)
416 {
417 // need to do this...
418 }
419
420 void writeHint(Addr addr, int size, unsigned flags)
421 {
422 // need to do this...
423 }
424
425 Fault copySrcTranslate(Addr src);
426
427 Fault copy(Addr dest);
428
429 public:
430 void squashFromTC();
431
432 void dumpInsts() { frontEnd->dumpInsts(); }
433
434 #if FULL_SYSTEM
435 Fault hwrei();
436 bool simPalCheck(int palFunc);
437 void processInterrupts();
438 #else
439 void syscall(uint64_t &callnum);
440 #endif
441
442 ThreadContext *tcBase() { return tc; }
443
444 struct CommStruct {
445 InstSeqNum doneSeqNum;
446 InstSeqNum nonSpecSeqNum;
447 bool uncached;
448 unsigned lqIdx;
449
450 bool stall;
451 };
452
453 InstSeqNum globalSeqNum;
454
455 TimeBuffer<CommStruct> comm;
456
457 bool decoupledFrontEnd;
458
459 bool lockFlag;
460
461 Stats::Scalar quiesceCycles;
462
463 Checker<DynInstPtr> *checker;
464 };
465
466 #endif // __CPU_OZONE_CPU_HH__