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