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