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