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