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