2 * Copyright (c) 2003-2005 The Regents of The University of Michigan
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.
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.
32 #include "arch/sparc/asi.hh"
33 #include "arch/sparc/miscregfile.hh"
34 #include "base/bitfield.hh"
35 #include "base/trace.hh"
36 #include "config/full_system.hh"
37 #include "cpu/base.hh"
38 #include "cpu/thread_context.hh"
40 using namespace SparcISA
;
45 //These functions map register indices to names
46 string
SparcISA::getMiscRegName(RegIndex index
)
48 static::string miscRegName
[NumMiscRegs
] =
49 {/*"y", "ccr",*/ "asi", "tick", "fprs", "pcr", "pic",
50 "gsr", "softint_set", "softint_clr", "softint", "tick_cmpr",
51 "stick", "stick_cmpr",
52 "tpc", "tnpc", "tstate", "tt", "privtick", "tba", "pstate", "tl",
53 "pil", "cwp", /*"cansave", "canrestore", "cleanwin", "otherwin",
55 "hpstate", "htstate", "hintp", "htba", "hver", "strand_sts_reg",
57 "fsr", "prictx", "secctx", "partId", "lsuCtrlReg",
58 "scratch0", "scratch1", "scratch2", "scratch3", "scratch4",
59 "scratch5", "scratch6", "scratch7", "cpuMondoHead", "cpuMondoTail",
60 "devMondoHead", "devMondoTail", "resErrorHead", "resErrorTail",
61 "nresErrorHead", "nresErrorTail", "TlbData" };
63 return miscRegName
[index
];
68 PSTATE_MASK
= (((1 << 4) - 1) << 1) | (((1 << 4) - 1) << 6) | (1 << 12)
71 void MiscRegFile::clear()
83 memset(tpc
, 0, sizeof(tpc
));
84 memset(tnpc
, 0, sizeof(tnpc
));
85 memset(tstate
, 0, sizeof(tstate
));
86 memset(tt
, 0, sizeof(tt
));
97 //In a T1, bit 11 is apparently always 1
99 memset(htstate
, 0, sizeof(htstate
));
103 //This is set this way in Legion for some reason
104 strandStatusReg
= 0x50000;
112 memset(scratchPad
, 0, sizeof(scratchPad
));
116 hSTickCompare
= NULL
;
120 MiscReg
MiscRegFile::readRegNoEffect(int miscReg
)
123 // The three miscRegs are moved up from the switch statement
124 // due to more frequent calls.
126 if (miscReg
== MISCREG_GL
)
128 if (miscReg
== MISCREG_CWP
)
130 if (miscReg
== MISCREG_TLB_DATA
) {
131 /* Package up all the data for the tlb:
132 * 6666555555555544444444443333333333222222222211111111110000000000
133 * 3210987654321098765432109876543210987654321098765432109876543210
134 * secContext | priContext | |tl|partid| |||||^hpriv
141 return bits((uint64_t)hpstate
,2,2) |
142 bits((uint64_t)hpstate
,5,5) << 1 |
143 bits((uint64_t)pstate
,3,2) << 2 |
144 bits((uint64_t)lsuCtrlReg
,3,2) << 4 |
145 bits((uint64_t)partId
,7,0) << 8 |
146 bits((uint64_t)tl
,2,0) << 16 |
147 (uint64_t)priContext
<< 32 |
148 (uint64_t)secContext
<< 48;
152 //case MISCREG_TLB_DATA:
153 // [original contents see above]
165 panic("PCR not implemented\n");
167 panic("PIC not implemented\n");
170 case MISCREG_SOFTINT
:
172 case MISCREG_TICK_CMPR
:
176 case MISCREG_STICK_CMPR
:
179 /** Privilged Registers */
188 case MISCREG_PRIVTICK
:
189 panic("Priviliged access to tick registers not implemented\n");
201 //case MISCREG_CANSAVE:
203 //case MISCREG_CANRESTORE:
204 // return canrestore;
205 //case MISCREG_CLEANWIN:
207 //case MISCREG_OTHERWIN:
209 //case MISCREG_WSTATE:
214 /** Hyper privileged registers */
215 case MISCREG_HPSTATE
:
217 case MISCREG_HTSTATE
:
218 return htstate
[tl
-1];
223 case MISCREG_STRAND_STS_REG
:
224 return strandStatusReg
;
225 case MISCREG_HSTICK_CMPR
:
228 /** Floating Point Status Register */
230 DPRINTF(MiscRegs
, "FSR read as: %#x\n", fsr
);
233 case MISCREG_MMU_P_CONTEXT
:
235 case MISCREG_MMU_S_CONTEXT
:
237 case MISCREG_MMU_PART_ID
:
239 case MISCREG_MMU_LSU_CTRL
:
242 case MISCREG_SCRATCHPAD_R0
:
243 return scratchPad
[0];
244 case MISCREG_SCRATCHPAD_R1
:
245 return scratchPad
[1];
246 case MISCREG_SCRATCHPAD_R2
:
247 return scratchPad
[2];
248 case MISCREG_SCRATCHPAD_R3
:
249 return scratchPad
[3];
250 case MISCREG_SCRATCHPAD_R4
:
251 return scratchPad
[4];
252 case MISCREG_SCRATCHPAD_R5
:
253 return scratchPad
[5];
254 case MISCREG_SCRATCHPAD_R6
:
255 return scratchPad
[6];
256 case MISCREG_SCRATCHPAD_R7
:
257 return scratchPad
[7];
258 case MISCREG_QUEUE_CPU_MONDO_HEAD
:
259 return cpu_mondo_head
;
260 case MISCREG_QUEUE_CPU_MONDO_TAIL
:
261 return cpu_mondo_tail
;
262 case MISCREG_QUEUE_DEV_MONDO_HEAD
:
263 return dev_mondo_head
;
264 case MISCREG_QUEUE_DEV_MONDO_TAIL
:
265 return dev_mondo_tail
;
266 case MISCREG_QUEUE_RES_ERROR_HEAD
:
267 return res_error_head
;
268 case MISCREG_QUEUE_RES_ERROR_TAIL
:
269 return res_error_tail
;
270 case MISCREG_QUEUE_NRES_ERROR_HEAD
:
271 return nres_error_head
;
272 case MISCREG_QUEUE_NRES_ERROR_TAIL
:
273 return nres_error_tail
;
275 panic("Miscellaneous register %d not implemented\n", miscReg
);
279 MiscReg
MiscRegFile::readReg(int miscReg
, ThreadContext
* tc
)
282 // tick and stick are aliased to each other in niagra
283 // well store the tick data in stick and the interrupt bit in tick
286 case MISCREG_PRIVTICK
:
287 // I'm not sure why legion ignores the lowest two bits, but we'll go
289 // change from curCycle() to instCount() until we're done with legion
290 DPRINTF(Timer
, "Instruction Count when TICK read: %#X stick=%#X\n",
291 tc
->getCpuPtr()->instCount(), stick
);
292 return mbits(tc
->getCpuPtr()->instCount() + (int64_t)stick
,62,2) |
295 // in legion if fp is enabled du and dl are set
299 panic("Performance Instrumentation not impl\n");
300 case MISCREG_SOFTINT_CLR
:
301 case MISCREG_SOFTINT_SET
:
302 panic("Can read from softint clr/set\n");
303 case MISCREG_SOFTINT
:
304 case MISCREG_TICK_CMPR
:
305 case MISCREG_STICK_CMPR
:
307 case MISCREG_HTSTATE
:
310 case MISCREG_STRAND_STS_REG
:
311 case MISCREG_HSTICK_CMPR
:
312 case MISCREG_QUEUE_CPU_MONDO_HEAD
:
313 case MISCREG_QUEUE_CPU_MONDO_TAIL
:
314 case MISCREG_QUEUE_DEV_MONDO_HEAD
:
315 case MISCREG_QUEUE_DEV_MONDO_TAIL
:
316 case MISCREG_QUEUE_RES_ERROR_HEAD
:
317 case MISCREG_QUEUE_RES_ERROR_TAIL
:
318 case MISCREG_QUEUE_NRES_ERROR_HEAD
:
319 case MISCREG_QUEUE_NRES_ERROR_TAIL
:
321 case MISCREG_HPSTATE
:
322 return readFSReg(miscReg
, tc
);
324 case MISCREG_HPSTATE
:
325 //HPSTATE is special because because sometimes in privilege
326 //checks for instructions it will read HPSTATE to make sure
327 //the priv. level is ok So, we'll just have to tell it it
328 //isn't, instead of panicing.
331 panic("Accessing Fullsystem register %s in SE mode\n",
332 getMiscRegName(miscReg
));
336 return readRegNoEffect(miscReg
);
339 void MiscRegFile::setRegNoEffect(int miscReg
, const MiscReg
&val
)
358 panic("PCR not implemented\n");
360 panic("PIC not implemented\n");
364 case MISCREG_SOFTINT
:
367 case MISCREG_TICK_CMPR
:
373 case MISCREG_STICK_CMPR
:
377 /** Privilged Registers */
390 case MISCREG_PRIVTICK
:
391 panic("Priviliged access to tick regesiters not implemented\n");
393 // clear lower 7 bits on writes.
394 tba
= val
& ULL(~0x7FFF);
397 pstate
= (val
& PSTATE_MASK
);
408 // case MISCREG_CANSAVE:
411 // case MISCREG_CANRESTORE:
414 // case MISCREG_CLEANWIN:
417 // case MISCREG_OTHERWIN:
420 // case MISCREG_WSTATE:
427 /** Hyper privileged registers */
428 case MISCREG_HPSTATE
:
431 case MISCREG_HTSTATE
:
439 case MISCREG_STRAND_STS_REG
:
440 strandStatusReg
= val
;
442 case MISCREG_HSTICK_CMPR
:
446 /** Floating Point Status Register */
449 DPRINTF(MiscRegs
, "FSR written with: %#x\n", fsr
);
452 case MISCREG_MMU_P_CONTEXT
:
455 case MISCREG_MMU_S_CONTEXT
:
458 case MISCREG_MMU_PART_ID
:
461 case MISCREG_MMU_LSU_CTRL
:
465 case MISCREG_SCRATCHPAD_R0
:
468 case MISCREG_SCRATCHPAD_R1
:
471 case MISCREG_SCRATCHPAD_R2
:
474 case MISCREG_SCRATCHPAD_R3
:
477 case MISCREG_SCRATCHPAD_R4
:
480 case MISCREG_SCRATCHPAD_R5
:
483 case MISCREG_SCRATCHPAD_R6
:
486 case MISCREG_SCRATCHPAD_R7
:
489 case MISCREG_QUEUE_CPU_MONDO_HEAD
:
490 cpu_mondo_head
= val
;
492 case MISCREG_QUEUE_CPU_MONDO_TAIL
:
493 cpu_mondo_tail
= val
;
495 case MISCREG_QUEUE_DEV_MONDO_HEAD
:
496 dev_mondo_head
= val
;
498 case MISCREG_QUEUE_DEV_MONDO_TAIL
:
499 dev_mondo_tail
= val
;
501 case MISCREG_QUEUE_RES_ERROR_HEAD
:
502 res_error_head
= val
;
504 case MISCREG_QUEUE_RES_ERROR_TAIL
:
505 res_error_tail
= val
;
507 case MISCREG_QUEUE_NRES_ERROR_HEAD
:
508 nres_error_head
= val
;
510 case MISCREG_QUEUE_NRES_ERROR_TAIL
:
511 nres_error_tail
= val
;
514 panic("Miscellaneous register %d not implemented\n", miscReg
);
518 void MiscRegFile::setReg(int miscReg
,
519 const MiscReg
&val
, ThreadContext
* tc
)
521 MiscReg new_val
= val
;
526 // stick and tick are same thing on niagra
527 // use stick for offset and tick for holding intrrupt bit
528 stick
= mbits(val
,62,0) - tc
->getCpuPtr()->instCount();
529 tick
= mbits(val
,63,63);
530 DPRINTF(Timer
, "Writing TICK=%#X\n", val
);
533 //Configure the fpu based on the fprs
536 //Set up performance counting based on pcr value
539 pstate
= val
& PSTATE_MASK
;
544 if (hpstate
& HPSTATE::tlz
&& tl
== 0 && !(hpstate
& HPSTATE::hpriv
))
545 tc
->getCpuPtr()->postInterrupt(IT_TRAP_LEVEL_ZERO
, 0);
547 tc
->getCpuPtr()->clearInterrupt(IT_TRAP_LEVEL_ZERO
, 0);
551 new_val
= val
>= NWindows
? NWindows
- 1 : val
;
553 new_val
= NWindows
- 1;
558 case MISCREG_SOFTINT
:
559 case MISCREG_SOFTINT_SET
:
560 case MISCREG_SOFTINT_CLR
:
561 case MISCREG_TICK_CMPR
:
562 case MISCREG_STICK_CMPR
:
564 case MISCREG_HTSTATE
:
567 case MISCREG_STRAND_STS_REG
:
568 case MISCREG_HSTICK_CMPR
:
569 case MISCREG_QUEUE_CPU_MONDO_HEAD
:
570 case MISCREG_QUEUE_CPU_MONDO_TAIL
:
571 case MISCREG_QUEUE_DEV_MONDO_HEAD
:
572 case MISCREG_QUEUE_DEV_MONDO_TAIL
:
573 case MISCREG_QUEUE_RES_ERROR_HEAD
:
574 case MISCREG_QUEUE_RES_ERROR_TAIL
:
575 case MISCREG_QUEUE_NRES_ERROR_HEAD
:
576 case MISCREG_QUEUE_NRES_ERROR_TAIL
:
578 case MISCREG_HPSTATE
:
579 setFSReg(miscReg
, val
, tc
);
582 case MISCREG_HPSTATE
:
583 //HPSTATE is special because normal trap processing saves HPSTATE when
584 //it goes into a trap, and restores it when it returns.
586 panic("Accessing Fullsystem register %s to %#x in SE mode\n",
587 getMiscRegName(miscReg
), val
);
590 setRegNoEffect(miscReg
, new_val
);
594 MiscRegFile::serialize(EventManager
*em
, std::ostream
&os
)
596 SERIALIZE_SCALAR(asi
);
597 SERIALIZE_SCALAR(tick
);
598 SERIALIZE_SCALAR(fprs
);
599 SERIALIZE_SCALAR(gsr
);
600 SERIALIZE_SCALAR(softint
);
601 SERIALIZE_SCALAR(tick_cmpr
);
602 SERIALIZE_SCALAR(stick
);
603 SERIALIZE_SCALAR(stick_cmpr
);
604 SERIALIZE_ARRAY(tpc
,MaxTL
);
605 SERIALIZE_ARRAY(tnpc
,MaxTL
);
606 SERIALIZE_ARRAY(tstate
,MaxTL
);
607 SERIALIZE_ARRAY(tt
,MaxTL
);
608 SERIALIZE_SCALAR(tba
);
609 SERIALIZE_SCALAR(pstate
);
610 SERIALIZE_SCALAR(tl
);
611 SERIALIZE_SCALAR(pil
);
612 SERIALIZE_SCALAR(cwp
);
613 SERIALIZE_SCALAR(gl
);
614 SERIALIZE_SCALAR(hpstate
);
615 SERIALIZE_ARRAY(htstate
,MaxTL
);
616 SERIALIZE_SCALAR(hintp
);
617 SERIALIZE_SCALAR(htba
);
618 SERIALIZE_SCALAR(hstick_cmpr
);
619 SERIALIZE_SCALAR(strandStatusReg
);
620 SERIALIZE_SCALAR(fsr
);
621 SERIALIZE_SCALAR(priContext
);
622 SERIALIZE_SCALAR(secContext
);
623 SERIALIZE_SCALAR(partId
);
624 SERIALIZE_SCALAR(lsuCtrlReg
);
625 SERIALIZE_ARRAY(scratchPad
,8);
626 SERIALIZE_SCALAR(cpu_mondo_head
);
627 SERIALIZE_SCALAR(cpu_mondo_tail
);
628 SERIALIZE_SCALAR(dev_mondo_head
);
629 SERIALIZE_SCALAR(dev_mondo_tail
);
630 SERIALIZE_SCALAR(res_error_head
);
631 SERIALIZE_SCALAR(res_error_tail
);
632 SERIALIZE_SCALAR(nres_error_head
);
633 SERIALIZE_SCALAR(nres_error_tail
);
635 Tick tick_cmp
= 0, stick_cmp
= 0, hstick_cmp
= 0;
636 ThreadContext
*tc
= NULL
;
639 bool tick_intr_sched
= true;
642 tc
= tickCompare
->getTC();
643 else if (sTickCompare
)
644 tc
= sTickCompare
->getTC();
645 else if (hSTickCompare
)
646 tc
= hSTickCompare
->getTC();
648 tick_intr_sched
= false;
650 SERIALIZE_SCALAR(tick_intr_sched
);
653 cpu
= tc
->getCpuPtr();
654 tc_num
= cpu
->findContext(tc
);
655 if (tickCompare
&& tickCompare
->scheduled())
656 tick_cmp
= tickCompare
->when();
657 if (sTickCompare
&& sTickCompare
->scheduled())
658 stick_cmp
= sTickCompare
->when();
659 if (hSTickCompare
&& hSTickCompare
->scheduled())
660 hstick_cmp
= hSTickCompare
->when();
662 SERIALIZE_OBJPTR(cpu
);
663 SERIALIZE_SCALAR(tc_num
);
664 SERIALIZE_SCALAR(tick_cmp
);
665 SERIALIZE_SCALAR(stick_cmp
);
666 SERIALIZE_SCALAR(hstick_cmp
);
672 MiscRegFile::unserialize(EventManager
*em
, Checkpoint
*cp
,
673 const string
§ion
)
675 UNSERIALIZE_SCALAR(asi
);
676 UNSERIALIZE_SCALAR(tick
);
677 UNSERIALIZE_SCALAR(fprs
);
678 UNSERIALIZE_SCALAR(gsr
);
679 UNSERIALIZE_SCALAR(softint
);
680 UNSERIALIZE_SCALAR(tick_cmpr
);
681 UNSERIALIZE_SCALAR(stick
);
682 UNSERIALIZE_SCALAR(stick_cmpr
);
683 UNSERIALIZE_ARRAY(tpc
,MaxTL
);
684 UNSERIALIZE_ARRAY(tnpc
,MaxTL
);
685 UNSERIALIZE_ARRAY(tstate
,MaxTL
);
686 UNSERIALIZE_ARRAY(tt
,MaxTL
);
687 UNSERIALIZE_SCALAR(tba
);
688 UNSERIALIZE_SCALAR(pstate
);
689 UNSERIALIZE_SCALAR(tl
);
690 UNSERIALIZE_SCALAR(pil
);
691 UNSERIALIZE_SCALAR(cwp
);
692 UNSERIALIZE_SCALAR(gl
);
693 UNSERIALIZE_SCALAR(hpstate
);
694 UNSERIALIZE_ARRAY(htstate
,MaxTL
);
695 UNSERIALIZE_SCALAR(hintp
);
696 UNSERIALIZE_SCALAR(htba
);
697 UNSERIALIZE_SCALAR(hstick_cmpr
);
698 UNSERIALIZE_SCALAR(strandStatusReg
);
699 UNSERIALIZE_SCALAR(fsr
);
700 UNSERIALIZE_SCALAR(priContext
);
701 UNSERIALIZE_SCALAR(secContext
);
702 UNSERIALIZE_SCALAR(partId
);
703 UNSERIALIZE_SCALAR(lsuCtrlReg
);
704 UNSERIALIZE_ARRAY(scratchPad
,8);
705 UNSERIALIZE_SCALAR(cpu_mondo_head
);
706 UNSERIALIZE_SCALAR(cpu_mondo_tail
);
707 UNSERIALIZE_SCALAR(dev_mondo_head
);
708 UNSERIALIZE_SCALAR(dev_mondo_tail
);
709 UNSERIALIZE_SCALAR(res_error_head
);
710 UNSERIALIZE_SCALAR(res_error_tail
);
711 UNSERIALIZE_SCALAR(nres_error_head
);
712 UNSERIALIZE_SCALAR(nres_error_tail
);
715 Tick tick_cmp
= 0, stick_cmp
= 0, hstick_cmp
= 0;
716 ThreadContext
*tc
= NULL
;
719 bool tick_intr_sched
;
720 UNSERIALIZE_SCALAR(tick_intr_sched
);
721 if (tick_intr_sched
) {
722 UNSERIALIZE_OBJPTR(cpu
);
724 UNSERIALIZE_SCALAR(tc_num
);
725 UNSERIALIZE_SCALAR(tick_cmp
);
726 UNSERIALIZE_SCALAR(stick_cmp
);
727 UNSERIALIZE_SCALAR(hstick_cmp
);
728 tc
= cpu
->getContext(tc_num
);
731 tickCompare
= new TickCompareEvent(this, tc
);
732 em
->schedule(tickCompare
, tick_cmp
);
735 sTickCompare
= new STickCompareEvent(this, tc
);
736 em
->schedule(sTickCompare
, stick_cmp
);
739 hSTickCompare
= new HSTickCompareEvent(this, tc
);
740 em
->schedule(hSTickCompare
, hstick_cmp
);