cpu.cc revision 1060
1#ifndef __SIMPLE_FULL_CPU_CC__
2#define __SIMPLE_FULL_CPU_CC__
3
4#ifdef FULL_SYSTEM
5#include "sim/system.hh"
6#else
7#include "sim/process.hh"
8#endif
9#include "sim/universe.hh"
10
11#include "cpu/exec_context.hh"
12#include "cpu/beta_cpu/full_cpu.hh"
13#include "cpu/beta_cpu/alpha_impl.hh"
14#include "cpu/beta_cpu/alpha_dyn_inst.hh"
15
16using namespace std;
17
18#ifdef FULL_SYSTEM
19BaseFullCPU::BaseFullCPU(const std::string &_name,
20                         int number_of_threads,
21                         Counter max_insts_any_thread,
22                         Counter max_insts_all_threads,
23                         Counter max_loads_any_thread,
24                         Counter max_loads_all_threads,
25                         System *_system, Tick freq)
26    : BaseCPU(_name, number_of_threads,
27              max_insts_any_thread, max_insts_all_threads,
28              max_loads_any_thread, max_loads_all_threads,
29              _system, freq)
30{
31}
32#else
33BaseFullCPU::BaseFullCPU(const std::string &_name,
34                         int number_of_threads,
35                         Counter max_insts_any_thread,
36                         Counter max_insts_all_threads,
37                         Counter max_loads_any_thread,
38                         Counter max_loads_all_threads)
39    : BaseCPU(_name, number_of_threads,
40              max_insts_any_thread, max_insts_all_threads,
41              max_loads_any_thread, max_loads_all_threads)
42{
43}
44#endif // FULL_SYSTEM
45
46template <class Impl>
47FullBetaCPU<Impl>::TickEvent::TickEvent(FullBetaCPU<Impl> *c)
48    : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c)
49{
50}
51
52template <class Impl>
53void
54FullBetaCPU<Impl>::TickEvent::process()
55{
56    cpu->tick();
57}
58
59template <class Impl>
60const char *
61FullBetaCPU<Impl>::TickEvent::description()
62{
63    return "FullBetaCPU tick event";
64}
65
66//Call constructor to all the pipeline stages here
67template <class Impl>
68FullBetaCPU<Impl>::FullBetaCPU(Params &params)
69#ifdef FULL_SYSTEM
70    : BaseFullCPU(params.name, /* number_of_threads */ 1,
71                  params.maxInstsAnyThread, params.maxInstsAllThreads,
72                  params.maxLoadsAnyThread, params.maxLoadsAllThreads,
73                  params.system, params.freq),
74#else
75    : BaseFullCPU(params.name, /* number_of_threads */ 1,
76                  params.maxInstsAnyThread, params.maxInstsAllThreads,
77                  params.maxLoadsAnyThread, params.maxLoadsAllThreads),
78#endif // FULL_SYSTEM
79      tickEvent(this),
80      fetch(params),
81      decode(params),
82      rename(params),
83      iew(params),
84      commit(params),
85
86      regFile(params.numPhysIntRegs, params.numPhysFloatRegs),
87
88      freeList(Impl::ISA::NumIntRegs, params.numPhysIntRegs,
89               Impl::ISA::NumFloatRegs, params.numPhysFloatRegs),
90
91      renameMap(Impl::ISA::NumIntRegs, params.numPhysIntRegs,
92                Impl::ISA::NumFloatRegs, params.numPhysFloatRegs,
93                Impl::ISA::NumMiscRegs,
94                Impl::ISA::ZeroReg, Impl::ISA::ZeroReg),
95
96      rob(params.numROBEntries, params.squashWidth),
97
98      // What to pass to these time buffers?
99      // For now just have these time buffers be pretty big.
100      timeBuffer(20, 20),
101      fetchQueue(20, 20),
102      decodeQueue(20, 20),
103      renameQueue(20, 20),
104      iewQueue(20, 20),
105
106      xc(NULL),
107
108      globalSeqNum(1),
109
110#ifdef FULL_SYSTEM
111      system(params.system),
112      memCtrl(system->memCtrl),
113      physmem(system->physmem),
114      itb(params.itb),
115      dtb(params.dtb),
116      mem(params.mem),
117#else
118      process(params.process),
119      asid(params.asid),
120      mem(process->getMemory()),
121#endif // FULL_SYSTEM
122
123      icacheInterface(params.icacheInterface),
124      dcacheInterface(params.dcacheInterface),
125      deferRegistration(params.defReg),
126      numInsts(0),
127      funcExeInst(0)
128{
129    _status = Idle;
130#ifdef FULL_SYSTEM
131    xc = new ExecContext(this, 0, system, itb, dtb, mem);
132
133    // initialize CPU, including PC
134    TheISA::initCPU(&xc->regs);
135#else
136    xc = new ExecContext(this, /* thread_num */ 0, process, /* asid */ 0);
137    DPRINTF(FullCPU, "FullCPU: Process's starting PC is %#x, process is %#x",
138            process->prog_entry, process);
139
140    assert(process->getMemory() != NULL);
141    assert(mem != NULL);
142#endif // !FULL_SYSTEM
143    execContexts.push_back(xc);
144
145    // The stages also need their CPU pointer setup.  However this must be
146    // done at the upper level CPU because they have pointers to the upper
147    // level CPU, and not this FullBetaCPU.
148
149    // Give each of the stages the time buffer they will use.
150    fetch.setTimeBuffer(&timeBuffer);
151    decode.setTimeBuffer(&timeBuffer);
152    rename.setTimeBuffer(&timeBuffer);
153    iew.setTimeBuffer(&timeBuffer);
154    commit.setTimeBuffer(&timeBuffer);
155
156    // Also setup each of the stages' queues.
157    fetch.setFetchQueue(&fetchQueue);
158    decode.setFetchQueue(&fetchQueue);
159    decode.setDecodeQueue(&decodeQueue);
160    rename.setDecodeQueue(&decodeQueue);
161    rename.setRenameQueue(&renameQueue);
162    iew.setRenameQueue(&renameQueue);
163    iew.setIEWQueue(&iewQueue);
164    commit.setIEWQueue(&iewQueue);
165    commit.setRenameQueue(&renameQueue);
166
167    // Setup the rename map for whichever stages need it.
168    rename.setRenameMap(&renameMap);
169    iew.setRenameMap(&renameMap);
170
171    // Setup the free list for whichever stages need it.
172    rename.setFreeList(&freeList);
173    renameMap.setFreeList(&freeList);
174
175    // Setup the ROB for whichever stages need it.
176    commit.setROB(&rob);
177}
178
179template <class Impl>
180FullBetaCPU<Impl>::~FullBetaCPU()
181{
182}
183
184template <class Impl>
185void
186FullBetaCPU<Impl>::tick()
187{
188    DPRINTF(FullCPU, "\n\nFullCPU: Ticking main, FullBetaCPU.\n");
189
190    //Tick each of the stages if they're actually running.
191    //Will want to figure out a way to unschedule itself if they're all
192    //going to be idle for a long time.
193    fetch.tick();
194
195    decode.tick();
196
197    rename.tick();
198
199    iew.tick();
200
201    commit.tick();
202
203    // Now advance the time buffers, unless the stage is stalled.
204    timeBuffer.advance();
205
206    fetchQueue.advance();
207    decodeQueue.advance();
208    renameQueue.advance();
209    iewQueue.advance();
210
211    if (_status == Running && !tickEvent.scheduled())
212        tickEvent.schedule(curTick + 1);
213}
214
215template <class Impl>
216void
217FullBetaCPU<Impl>::init()
218{
219    if(!deferRegistration)
220    {
221        this->registerExecContexts();
222
223        // Need to do a copy of the xc->regs into the CPU's regfile so
224        // that it can start properly.
225
226        // First loop through the integer registers.
227        for (int i = 0; i < Impl::ISA::NumIntRegs; ++i)
228        {
229            regFile.intRegFile[i] = xc->regs.intRegFile[i];
230        }
231
232        // Then loop through the floating point registers.
233        for (int i = 0; i < Impl::ISA::NumFloatRegs; ++i)
234        {
235            regFile.floatRegFile[i].d = xc->regs.floatRegFile.d[i];
236            regFile.floatRegFile[i].q = xc->regs.floatRegFile.q[i];
237        }
238
239        // Then loop through the misc registers.
240        regFile.miscRegs.fpcr = xc->regs.miscRegs.fpcr;
241        regFile.miscRegs.uniq = xc->regs.miscRegs.uniq;
242        regFile.miscRegs.lock_flag = xc->regs.miscRegs.lock_flag;
243        regFile.miscRegs.lock_addr = xc->regs.miscRegs.lock_addr;
244
245        // Then finally set the PC and the next PC.
246        regFile.pc = xc->regs.pc;
247        regFile.npc = xc->regs.npc;
248    }
249}
250
251template <class Impl>
252void
253FullBetaCPU<Impl>::activateContext(int thread_num, int delay)
254{
255    // Needs to set each stage to running as well.
256
257    scheduleTickEvent(delay);
258
259    _status = Running;
260}
261
262template <class Impl>
263void
264FullBetaCPU<Impl>::suspendContext(int thread_num)
265{
266    panic("suspendContext unimplemented!");
267}
268
269template <class Impl>
270void
271FullBetaCPU<Impl>::deallocateContext(int thread_num)
272{
273    panic("deallocateContext unimplemented!");
274}
275
276template <class Impl>
277void
278FullBetaCPU<Impl>::haltContext(int thread_num)
279{
280    panic("haltContext unimplemented!");
281}
282
283template <class Impl>
284void
285FullBetaCPU<Impl>::switchOut()
286{
287    panic("FullBetaCPU does not have a switch out function.\n");
288}
289
290template <class Impl>
291void
292FullBetaCPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
293{
294    BaseCPU::takeOverFrom(oldCPU);
295
296    assert(!tickEvent.scheduled());
297
298    // Set all status's to active, schedule the
299    // CPU's tick event.
300    tickEvent.schedule(curTick);
301    for (int i = 0; i < execContexts.size(); ++i) {
302        execContexts[i]->activate();
303    }
304
305    // Switch out the other CPU.
306    oldCPU->switchOut();
307}
308
309template <class Impl>
310InstSeqNum
311FullBetaCPU<Impl>::getAndIncrementInstSeq()
312{
313    // Hopefully this works right.
314    return globalSeqNum++;
315}
316
317template <class Impl>
318uint64_t
319FullBetaCPU<Impl>::readIntReg(int reg_idx)
320{
321    return regFile.readIntReg(reg_idx);
322}
323
324template <class Impl>
325float
326FullBetaCPU<Impl>::readFloatRegSingle(int reg_idx)
327{
328    return regFile.readFloatRegSingle(reg_idx);
329}
330
331template <class Impl>
332double
333FullBetaCPU<Impl>::readFloatRegDouble(int reg_idx)
334{
335    return regFile.readFloatRegDouble(reg_idx);
336}
337
338template <class Impl>
339uint64_t
340FullBetaCPU<Impl>::readFloatRegInt(int reg_idx)
341{
342    return regFile.readFloatRegInt(reg_idx);
343}
344
345template <class Impl>
346void
347FullBetaCPU<Impl>::setIntReg(int reg_idx, uint64_t val)
348{
349    regFile.setIntReg(reg_idx, val);
350}
351
352template <class Impl>
353void
354FullBetaCPU<Impl>::setFloatRegSingle(int reg_idx, float val)
355{
356    regFile.setFloatRegSingle(reg_idx, val);
357}
358
359template <class Impl>
360void
361FullBetaCPU<Impl>::setFloatRegDouble(int reg_idx, double val)
362{
363    regFile.setFloatRegDouble(reg_idx, val);
364}
365
366template <class Impl>
367void
368FullBetaCPU<Impl>::setFloatRegInt(int reg_idx, uint64_t val)
369{
370    regFile.setFloatRegInt(reg_idx, val);
371}
372
373template <class Impl>
374uint64_t
375FullBetaCPU<Impl>::readPC()
376{
377    return regFile.readPC();
378}
379
380template <class Impl>
381void
382FullBetaCPU<Impl>::setNextPC(uint64_t val)
383{
384    regFile.setNextPC(val);
385}
386
387template <class Impl>
388void
389FullBetaCPU<Impl>::setPC(Addr new_PC)
390{
391    regFile.setPC(new_PC);
392}
393
394template <class Impl>
395void
396FullBetaCPU<Impl>::addInst(DynInst *inst)
397{
398    instList.push_back(inst);
399}
400
401template <class Impl>
402void
403FullBetaCPU<Impl>::instDone()
404{
405    // Keep an instruction count.
406    numInsts++;
407
408    // Check for instruction-count-based events.
409    comInstEventQueue[0]->serviceEvents(numInsts);
410}
411
412template <class Impl>
413void
414FullBetaCPU<Impl>::removeBackInst(DynInst *inst)
415{
416    DynInst *inst_to_delete;
417
418    // Walk through the instruction list, removing any instructions
419    // that were inserted after the given instruction, inst.
420    while (instList.back() != inst)
421    {
422        assert(!instList.empty());
423
424        // Obtain the pointer to the instruction.
425        inst_to_delete = instList.back();
426
427        DPRINTF(FullCPU, "FullCPU: Deleting instruction %#x, PC %#x\n",
428                inst_to_delete, inst_to_delete->readPC());
429
430        // Remove the instruction from the list.
431        instList.pop_back();
432
433        // Delete the instruction itself.
434        delete inst_to_delete;
435    }
436}
437
438template <class Impl>
439void
440FullBetaCPU<Impl>::removeFrontInst(DynInst *inst)
441{
442    DynInst *inst_to_delete;
443
444    // The front instruction should be the same one being asked to be deleted.
445    assert(instList.front() == inst);
446
447    // Remove the front instruction.
448    inst_to_delete = inst;
449    instList.pop_front();
450
451    DPRINTF(FullCPU, "FullCPU: Deleting committed instruction %#x, PC %#x\n",
452            inst_to_delete, inst_to_delete->readPC());
453
454    delete inst_to_delete;
455}
456
457template <class Impl>
458void
459FullBetaCPU<Impl>::removeInstsNotInROB()
460{
461    DPRINTF(FullCPU, "FullCPU: Deleting instructions from instruction "
462            "list.\n");
463
464    DynInst *rob_tail = rob.readTailInst();
465
466    removeBackInst(rob_tail);
467}
468
469template <class Impl>
470void
471FullBetaCPU<Impl>::removeAllInsts()
472{
473    instList.clear();
474}
475
476template <class Impl>
477void
478FullBetaCPU<Impl>::dumpInsts()
479{
480    int num = 0;
481    typename list<DynInst *>::iterator inst_list_it = instList.begin();
482
483    while (inst_list_it != instList.end())
484    {
485        cprintf("Instruction:%i\nInst:%#x\nPC:%#x\nSN:%lli\n\n",
486                num, (*inst_list_it), (*inst_list_it)->readPC(),
487                (*inst_list_it)->seqNum);
488        inst_list_it++;
489        ++num;
490    }
491}
492
493template <class Impl>
494void
495FullBetaCPU<Impl>::wakeDependents(DynInst *inst)
496{
497    iew.wakeDependents(inst);
498}
499
500// Forward declaration of FullBetaCPU.
501template FullBetaCPU<AlphaSimpleImpl>;
502
503#endif // __SIMPLE_FULL_CPU_HH__
504