regfile.hh revision 1060
1#ifndef __REGFILE_HH__
2#define __REGFILE_HH__
3
4// @todo: Destructor
5
6using namespace std;
7
8#include "arch/alpha/isa_traits.hh"
9#include "cpu/beta_cpu/comm.hh"
10
11// This really only depends on the ISA, and not the Impl.  It might be nicer
12// to see if I can make it depend on nothing...
13// Things that are in the ifdef FULL_SYSTEM are pretty dependent on the ISA,
14// and should go in the AlphaFullCPU.
15
16template<class Impl>
17class PhysRegFile
18{
19    //Note that most of the definitions of the IntReg, FloatReg, etc. exist
20    //within the Impl class and not within this PhysRegFile class.
21
22    //Will need some way to allow stuff like swap_palshadow to access the
23    //correct registers.  Might require code changes to swap_palshadow and
24    //other execution contexts.
25
26    //Will make these registers public for now, but they probably should
27    //be private eventually with some accessor functions.
28  public:
29    typedef typename Impl::ISA ISA;
30
31    PhysRegFile(unsigned _numPhysicalIntRegs,
32                unsigned _numPhysicalFloatRegs);
33
34    //Everything below should be pretty well identical to the normal
35    //register file that exists within AlphaISA class.
36    //The duplication is unfortunate but it's better than having
37    //different ways to access certain registers.
38
39    //Add these in later when everything else is in place
40//    void serialize(std::ostream &os);
41//    void unserialize(Checkpoint *cp, const std::string &section);
42
43    uint64_t readIntReg(PhysRegIndex reg_idx)
44    {
45        DPRINTF(IEW, "RegFile: Access to int register %i, has data "
46                "%i\n", int(reg_idx), intRegFile[reg_idx]);
47        return intRegFile[reg_idx];
48    }
49
50    float readFloatRegSingle(PhysRegIndex reg_idx)
51    {
52        // Remove the base Float reg dependency.
53        reg_idx = reg_idx - numPhysicalIntRegs;
54
55        DPRINTF(IEW, "RegFile: Access to float register %i, has data "
56                "%f\n", int(reg_idx), (float)floatRegFile[reg_idx].d);
57
58        return (float)floatRegFile[reg_idx].d;
59    }
60
61    double readFloatRegDouble(PhysRegIndex reg_idx)
62    {
63        // Remove the base Float reg dependency.
64        reg_idx = reg_idx - numPhysicalIntRegs;
65
66        DPRINTF(IEW, "RegFile: Access to float register %i, has data "
67                "%f\n", int(reg_idx), floatRegFile[reg_idx].d);
68
69        return floatRegFile[reg_idx].d;
70    }
71
72    uint64_t readFloatRegInt(PhysRegIndex reg_idx)
73    {
74        // Remove the base Float reg dependency.
75        reg_idx = reg_idx - numPhysicalIntRegs;
76
77        DPRINTF(IEW, "RegFile: Access to float register %i, has data "
78                "%f\n", int(reg_idx), floatRegFile[reg_idx].q);
79
80        return floatRegFile[reg_idx].q;
81    }
82
83    void setIntReg(PhysRegIndex reg_idx, uint64_t val)
84    {
85        DPRINTF(IEW, "RegFile: Setting int register %i to %lli\n",
86                int(reg_idx), val);
87
88        intRegFile[reg_idx] = val;
89    }
90
91    void setFloatRegSingle(PhysRegIndex reg_idx, float val)
92    {
93        // Remove the base Float reg dependency.
94        reg_idx = reg_idx - numPhysicalIntRegs;
95
96        DPRINTF(IEW, "RegFile: Setting float register %i to %f\n",
97                int(reg_idx), val);
98
99        floatRegFile[reg_idx].d = (double)val;
100    }
101
102    void setFloatRegDouble(PhysRegIndex reg_idx, double val)
103    {
104        // Remove the base Float reg dependency.
105        reg_idx = reg_idx - numPhysicalIntRegs;
106
107        DPRINTF(IEW, "RegFile: Setting float register %i to %f\n",
108                int(reg_idx), val);
109
110        floatRegFile[reg_idx].d = val;
111    }
112
113    void setFloatRegInt(PhysRegIndex reg_idx, uint64_t val)
114    {
115        // Remove the base Float reg dependency.
116        reg_idx = reg_idx - numPhysicalIntRegs;
117
118        DPRINTF(IEW, "RegFile: Setting float register %i to %lli\n",
119                int(reg_idx), val);
120
121        floatRegFile[reg_idx].q = val;
122    }
123
124    uint64_t readPC()
125    {
126        return pc;
127    }
128
129    void setPC(uint64_t val)
130    {
131        pc = val;
132    }
133
134    void setNextPC(uint64_t val)
135    {
136        npc = val;
137    }
138
139    //Consider leaving this stuff and below in some implementation specific
140    //file as opposed to the general register file.  Or have a derived class.
141    uint64_t readUniq()
142    {
143        return miscRegs.uniq;
144    }
145
146    void setUniq(uint64_t val)
147    {
148        miscRegs.uniq = val;
149    }
150
151    uint64_t readFpcr()
152    {
153        return miscRegs.fpcr;
154    }
155
156    void setFpcr(uint64_t val)
157    {
158        miscRegs.fpcr = val;
159    }
160
161#ifdef FULL_SYSTEM
162    uint64_t readIpr(int idx, Fault &fault);
163    Fault setIpr(int idx, uint64_t val);
164    int readIntrFlag() { return intrflag; }
165    void setIntrFlag(int val) { intrflag = val; }
166#endif
167
168    // These should be private eventually, but will be public for now
169    // so that I can hack around the initregs issue.
170  public:
171    /** (signed) integer register file. */
172    IntReg *intRegFile;
173
174    /** Floating point register file. */
175    FloatReg *floatRegFile;
176
177    /** Miscellaneous register file. */
178    MiscRegFile miscRegs;
179
180    Addr pc;            // program counter
181    Addr npc;            // next-cycle program counter
182
183  private:
184    unsigned numPhysicalIntRegs;
185    unsigned numPhysicalFloatRegs;
186};
187
188template<class Impl>
189PhysRegFile<Impl>::PhysRegFile(unsigned _numPhysicalIntRegs,
190                               unsigned _numPhysicalFloatRegs)
191    : numPhysicalIntRegs(_numPhysicalIntRegs),
192      numPhysicalFloatRegs(_numPhysicalFloatRegs)
193{
194    intRegFile = new IntReg[numPhysicalIntRegs];
195    floatRegFile = new FloatReg[numPhysicalFloatRegs];
196
197    memset(intRegFile, 0, sizeof(*intRegFile));
198    memset(floatRegFile, 0, sizeof(*floatRegFile));
199}
200
201#ifdef FULL_SYSTEM
202
203//Problem:  This code doesn't make sense at the RegFile level because it
204//needs things such as the itb and dtb.  Either put it at the CPU level or
205//the DynInst level.
206template<class Impl>
207uint64_t
208PhysRegFile<Impl>::readIpr(int idx, Fault &fault)
209{
210    uint64_t retval = 0;    // return value, default 0
211
212    switch (idx) {
213      case ISA::IPR_PALtemp0:
214      case ISA::IPR_PALtemp1:
215      case ISA::IPR_PALtemp2:
216      case ISA::IPR_PALtemp3:
217      case ISA::IPR_PALtemp4:
218      case ISA::IPR_PALtemp5:
219      case ISA::IPR_PALtemp6:
220      case ISA::IPR_PALtemp7:
221      case ISA::IPR_PALtemp8:
222      case ISA::IPR_PALtemp9:
223      case ISA::IPR_PALtemp10:
224      case ISA::IPR_PALtemp11:
225      case ISA::IPR_PALtemp12:
226      case ISA::IPR_PALtemp13:
227      case ISA::IPR_PALtemp14:
228      case ISA::IPR_PALtemp15:
229      case ISA::IPR_PALtemp16:
230      case ISA::IPR_PALtemp17:
231      case ISA::IPR_PALtemp18:
232      case ISA::IPR_PALtemp19:
233      case ISA::IPR_PALtemp20:
234      case ISA::IPR_PALtemp21:
235      case ISA::IPR_PALtemp22:
236      case ISA::IPR_PALtemp23:
237      case ISA::IPR_PAL_BASE:
238
239      case ISA::IPR_IVPTBR:
240      case ISA::IPR_DC_MODE:
241      case ISA::IPR_MAF_MODE:
242      case ISA::IPR_ISR:
243      case ISA::IPR_EXC_ADDR:
244      case ISA::IPR_IC_PERR_STAT:
245      case ISA::IPR_DC_PERR_STAT:
246      case ISA::IPR_MCSR:
247      case ISA::IPR_ASTRR:
248      case ISA::IPR_ASTER:
249      case ISA::IPR_SIRR:
250      case ISA::IPR_ICSR:
251      case ISA::IPR_ICM:
252      case ISA::IPR_DTB_CM:
253      case ISA::IPR_IPLR:
254      case ISA::IPR_INTID:
255      case ISA::IPR_PMCTR:
256    // no side-effect
257    retval = ipr[idx];
258    break;
259
260      case ISA::IPR_CC:
261    retval |= ipr[idx] & ULL(0xffffffff00000000);
262    retval |= curTick  & ULL(0x00000000ffffffff);
263    break;
264
265      case ISA::IPR_VA:
266    // SFX: unlocks interrupt status registers
267    retval = ipr[idx];
268
269        if (!misspeculating())
270            regs.intrlock = false;
271    break;
272
273      case ISA::IPR_VA_FORM:
274      case ISA::IPR_MM_STAT:
275      case ISA::IPR_IFAULT_VA_FORM:
276      case ISA::IPR_EXC_MASK:
277      case ISA::IPR_EXC_SUM:
278    retval = ipr[idx];
279    break;
280
281      case ISA::IPR_DTB_PTE:
282    {
283        ISA::PTE &pte = dtb->index(!misspeculating());
284
285        retval |= ((u_int64_t)pte.ppn & ULL(0x7ffffff)) << 32;
286        retval |= ((u_int64_t)pte.xre & ULL(0xf)) << 8;
287        retval |= ((u_int64_t)pte.xwe & ULL(0xf)) << 12;
288        retval |= ((u_int64_t)pte.fonr & ULL(0x1)) << 1;
289        retval |= ((u_int64_t)pte.fonw & ULL(0x1))<< 2;
290        retval |= ((u_int64_t)pte.asma & ULL(0x1)) << 4;
291        retval |= ((u_int64_t)pte.asn & ULL(0x7f)) << 57;
292    }
293    break;
294
295    // write only registers
296      case ISA::IPR_HWINT_CLR:
297      case ISA::IPR_SL_XMIT:
298      case ISA::IPR_DC_FLUSH:
299      case ISA::IPR_IC_FLUSH:
300      case ISA::IPR_ALT_MODE:
301      case ISA::IPR_DTB_IA:
302      case ISA::IPR_DTB_IAP:
303      case ISA::IPR_ITB_IA:
304      case ISA::IPR_ITB_IAP:
305    fault = Unimplemented_Opcode_Fault;
306    break;
307
308      default:
309    // invalid IPR
310    fault = Unimplemented_Opcode_Fault;
311    break;
312    }
313
314    return retval;
315}
316
317#ifdef DEBUG
318// Cause the simulator to break when changing to the following IPL
319int break_ipl = -1;
320#endif
321
322template<class Impl>
323Fault
324PhysRegFile<Impl>::setIpr(int idx, uint64_t val)
325{
326    uint64_t old;
327
328    if (misspeculating())
329    return No_Fault;
330
331    switch (idx) {
332      case ISA::IPR_PALtemp0:
333      case ISA::IPR_PALtemp1:
334      case ISA::IPR_PALtemp2:
335      case ISA::IPR_PALtemp3:
336      case ISA::IPR_PALtemp4:
337      case ISA::IPR_PALtemp5:
338      case ISA::IPR_PALtemp6:
339      case ISA::IPR_PALtemp7:
340      case ISA::IPR_PALtemp8:
341      case ISA::IPR_PALtemp9:
342      case ISA::IPR_PALtemp10:
343      case ISA::IPR_PALtemp11:
344      case ISA::IPR_PALtemp12:
345      case ISA::IPR_PALtemp13:
346      case ISA::IPR_PALtemp14:
347      case ISA::IPR_PALtemp15:
348      case ISA::IPR_PALtemp16:
349      case ISA::IPR_PALtemp17:
350      case ISA::IPR_PALtemp18:
351      case ISA::IPR_PALtemp19:
352      case ISA::IPR_PALtemp20:
353      case ISA::IPR_PALtemp21:
354      case ISA::IPR_PALtemp22:
355      case ISA::IPR_PAL_BASE:
356      case ISA::IPR_IC_PERR_STAT:
357      case ISA::IPR_DC_PERR_STAT:
358      case ISA::IPR_PMCTR:
359    // write entire quad w/ no side-effect
360    ipr[idx] = val;
361    break;
362
363      case ISA::IPR_CC_CTL:
364    // This IPR resets the cycle counter.  We assume this only
365    // happens once... let's verify that.
366    assert(ipr[idx] == 0);
367    ipr[idx] = 1;
368    break;
369
370      case ISA::IPR_CC:
371    // This IPR only writes the upper 64 bits.  It's ok to write
372    // all 64 here since we mask out the lower 32 in rpcc (see
373    // isa_desc).
374    ipr[idx] = val;
375    break;
376
377      case ISA::IPR_PALtemp23:
378    // write entire quad w/ no side-effect
379    old = ipr[idx];
380    ipr[idx] = val;
381    kernelStats.context(old, val);
382    break;
383
384      case ISA::IPR_DTB_PTE:
385    // write entire quad w/ no side-effect, tag is forthcoming
386    ipr[idx] = val;
387    break;
388
389      case ISA::IPR_EXC_ADDR:
390    // second least significant bit in PC is always zero
391    ipr[idx] = val & ~2;
392    break;
393
394      case ISA::IPR_ASTRR:
395      case ISA::IPR_ASTER:
396    // only write least significant four bits - privilege mask
397    ipr[idx] = val & 0xf;
398    break;
399
400      case ISA::IPR_IPLR:
401#ifdef DEBUG
402    if (break_ipl != -1 && break_ipl == (val & 0x1f))
403        debug_break();
404#endif
405
406    // only write least significant five bits - interrupt level
407    ipr[idx] = val & 0x1f;
408    kernelStats.swpipl(ipr[idx]);
409    break;
410
411      case ISA::IPR_DTB_CM:
412    kernelStats.mode((val & 0x18) != 0);
413
414      case ISA::IPR_ICM:
415    // only write two mode bits - processor mode
416    ipr[idx] = val & 0x18;
417    break;
418
419      case ISA::IPR_ALT_MODE:
420    // only write two mode bits - processor mode
421    ipr[idx] = val & 0x18;
422    break;
423
424      case ISA::IPR_MCSR:
425    // more here after optimization...
426    ipr[idx] = val;
427    break;
428
429      case ISA::IPR_SIRR:
430    // only write software interrupt mask
431    ipr[idx] = val & 0x7fff0;
432    break;
433
434      case ISA::IPR_ICSR:
435    ipr[idx] = val & ULL(0xffffff0300);
436    break;
437
438      case ISA::IPR_IVPTBR:
439      case ISA::IPR_MVPTBR:
440    ipr[idx] = val & ULL(0xffffffffc0000000);
441    break;
442
443      case ISA::IPR_DC_TEST_CTL:
444    ipr[idx] = val & 0x1ffb;
445    break;
446
447      case ISA::IPR_DC_MODE:
448      case ISA::IPR_MAF_MODE:
449    ipr[idx] = val & 0x3f;
450    break;
451
452      case ISA::IPR_ITB_ASN:
453    ipr[idx] = val & 0x7f0;
454    break;
455
456      case ISA::IPR_DTB_ASN:
457    ipr[idx] = val & ULL(0xfe00000000000000);
458    break;
459
460      case ISA::IPR_EXC_SUM:
461      case ISA::IPR_EXC_MASK:
462    // any write to this register clears it
463    ipr[idx] = 0;
464    break;
465
466      case ISA::IPR_INTID:
467      case ISA::IPR_SL_RCV:
468      case ISA::IPR_MM_STAT:
469      case ISA::IPR_ITB_PTE_TEMP:
470      case ISA::IPR_DTB_PTE_TEMP:
471    // read-only registers
472    return Unimplemented_Opcode_Fault;
473
474      case ISA::IPR_HWINT_CLR:
475      case ISA::IPR_SL_XMIT:
476      case ISA::IPR_DC_FLUSH:
477      case ISA::IPR_IC_FLUSH:
478    // the following are write only
479    ipr[idx] = val;
480    break;
481
482      case ISA::IPR_DTB_IA:
483    // really a control write
484    ipr[idx] = 0;
485
486    dtb->flushAll();
487    break;
488
489      case ISA::IPR_DTB_IAP:
490    // really a control write
491    ipr[idx] = 0;
492
493    dtb->flushProcesses();
494    break;
495
496      case ISA::IPR_DTB_IS:
497    // really a control write
498    ipr[idx] = val;
499
500    dtb->flushAddr(val, DTB_ASN_ASN(ipr[ISA::IPR_DTB_ASN]));
501    break;
502
503      case ISA::IPR_DTB_TAG: {
504      struct ISA::PTE pte;
505
506      // FIXME: granularity hints NYI...
507      if (DTB_PTE_GH(ipr[ISA::IPR_DTB_PTE]) != 0)
508          panic("PTE GH field != 0");
509
510      // write entire quad
511      ipr[idx] = val;
512
513      // construct PTE for new entry
514      pte.ppn = DTB_PTE_PPN(ipr[ISA::IPR_DTB_PTE]);
515      pte.xre = DTB_PTE_XRE(ipr[ISA::IPR_DTB_PTE]);
516      pte.xwe = DTB_PTE_XWE(ipr[ISA::IPR_DTB_PTE]);
517      pte.fonr = DTB_PTE_FONR(ipr[ISA::IPR_DTB_PTE]);
518      pte.fonw = DTB_PTE_FONW(ipr[ISA::IPR_DTB_PTE]);
519      pte.asma = DTB_PTE_ASMA(ipr[ISA::IPR_DTB_PTE]);
520      pte.asn = DTB_ASN_ASN(ipr[ISA::IPR_DTB_ASN]);
521
522      // insert new TAG/PTE value into data TLB
523      dtb->insert(val, pte);
524      }
525    break;
526
527      case ISA::IPR_ITB_PTE: {
528      struct ISA::PTE pte;
529
530      // FIXME: granularity hints NYI...
531      if (ITB_PTE_GH(val) != 0)
532          panic("PTE GH field != 0");
533
534      // write entire quad
535      ipr[idx] = val;
536
537      // construct PTE for new entry
538      pte.ppn = ITB_PTE_PPN(val);
539      pte.xre = ITB_PTE_XRE(val);
540      pte.xwe = 0;
541      pte.fonr = ITB_PTE_FONR(val);
542      pte.fonw = ITB_PTE_FONW(val);
543      pte.asma = ITB_PTE_ASMA(val);
544      pte.asn = ITB_ASN_ASN(ipr[ISA::IPR_ITB_ASN]);
545
546      // insert new TAG/PTE value into data TLB
547      itb->insert(ipr[ISA::IPR_ITB_TAG], pte);
548      }
549    break;
550
551      case ISA::IPR_ITB_IA:
552    // really a control write
553    ipr[idx] = 0;
554
555    itb->flushAll();
556    break;
557
558      case ISA::IPR_ITB_IAP:
559    // really a control write
560    ipr[idx] = 0;
561
562    itb->flushProcesses();
563    break;
564
565      case ISA::IPR_ITB_IS:
566    // really a control write
567    ipr[idx] = val;
568
569    itb->flushAddr(val, ITB_ASN_ASN(ipr[ISA::IPR_ITB_ASN]));
570    break;
571
572      default:
573    // invalid IPR
574    return Unimplemented_Opcode_Fault;
575    }
576
577    // no error...
578    return No_Fault;
579}
580
581#endif // #ifdef FULL_SYSTEM
582
583#endif // __REGFILE_HH__
584