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 §ion); 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