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