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