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