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