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