2 * Copyright (c) 2009 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.
31 #include "arch/sparc/asi.hh"
32 #include "arch/sparc/isa.hh"
33 #include "base/bitfield.hh"
34 #include "base/trace.hh"
35 #include "cpu/base.hh"
36 #include "cpu/thread_context.hh"
37 #include "debug/MiscRegs.hh"
38 #include "debug/Timer.hh"
58 static const PSTATE PstateMask
= buildPstateMask();
63 installGlobals(gl
, CurrentGlobalsOffset
);
64 installWindow(cwp
, CurrentWindowOffset
);
65 // Microcode registers.
66 for (int i
= 0; i
< NumMicroIntRegs
; i
++)
67 intRegMap
[MicroIntOffset
+ i
] = i
+ TotalGlobals
+ NWindows
* 16;
68 installGlobals(gl
, NextGlobalsOffset
);
69 installWindow(cwp
- 1, NextWindowOffset
);
70 installGlobals(gl
, PreviousGlobalsOffset
);
71 installWindow(cwp
+ 1, PreviousWindowOffset
);
75 ISA::installWindow(int cwp
, int offset
)
77 assert(offset
>= 0 && offset
+ NumWindowedRegs
<= NumIntRegs
);
78 RegIndex
*mapChunk
= intRegMap
+ offset
;
79 for (int i
= 0; i
< NumWindowedRegs
; i
++)
80 mapChunk
[i
] = TotalGlobals
+
81 ((i
- cwp
* RegsPerWindow
+ TotalWindowed
) % (TotalWindowed
));
85 ISA::installGlobals(int gl
, int offset
)
87 assert(offset
>= 0 && offset
+ NumGlobalRegs
<= NumIntRegs
);
88 RegIndex
*mapChunk
= intRegMap
+ offset
;
90 for (int i
= 1; i
< NumGlobalRegs
; i
++)
91 mapChunk
[i
] = i
+ gl
* NumGlobalRegs
;
111 memset(tpc
, 0, sizeof(tpc
));
112 memset(tnpc
, 0, sizeof(tnpc
));
113 memset(tstate
, 0, sizeof(tstate
));
114 memset(tt
, 0, sizeof(tt
));
124 // In a T1, bit 11 is apparently always 1
127 memset(htstate
, 0, sizeof(htstate
));
131 // This is set this way in Legion for some reason
132 strandStatusReg
= 0x50000;
140 memset(scratchPad
, 0, sizeof(scratchPad
));
151 // If one of these events is active, it's not obvious to me how to get
152 // rid of it cleanly. For now we'll just assert that they're not.
153 if (tickCompare
!= NULL
&& sTickCompare
!= NULL
&& hSTickCompare
!= NULL
)
154 panic("Tick comparison event active when clearing the ISA object.\n");
158 ISA::readMiscRegNoEffect(int miscReg
)
161 // The three miscRegs are moved up from the switch statement
162 // due to more frequent calls.
164 if (miscReg
== MISCREG_GL
)
166 if (miscReg
== MISCREG_CWP
)
168 if (miscReg
== MISCREG_TLB_DATA
) {
169 /* Package up all the data for the tlb:
170 * 6666555555555544444444443333333333222222222211111111110000000000
171 * 3210987654321098765432109876543210987654321098765432109876543210
172 * secContext | priContext | |tl|partid| |||||^hpriv
179 return (uint64_t)hpstate
.hpriv
|
180 (uint64_t)hpstate
.red
<< 1 |
181 (uint64_t)pstate
.priv
<< 2 |
182 (uint64_t)pstate
.am
<< 3 |
183 bits((uint64_t)lsuCtrlReg
,3,2) << 4 |
184 bits((uint64_t)partId
,7,0) << 8 |
185 bits((uint64_t)tl
,2,0) << 16 |
186 (uint64_t)priContext
<< 32 |
187 (uint64_t)secContext
<< 48;
191 // case MISCREG_TLB_DATA:
192 // [original contents see above]
204 panic("PCR not implemented\n");
206 panic("PIC not implemented\n");
209 case MISCREG_SOFTINT
:
211 case MISCREG_TICK_CMPR
:
215 case MISCREG_STICK_CMPR
:
218 /** Privilged Registers */
227 case MISCREG_PRIVTICK
:
228 panic("Priviliged access to tick registers not implemented\n");
232 return (MiscReg
)pstate
;
240 // case MISCREG_CANSAVE:
242 // case MISCREG_CANRESTORE:
243 // return canrestore;
244 // case MISCREG_CLEANWIN:
246 // case MISCREG_OTHERWIN:
248 // case MISCREG_WSTATE:
253 /** Hyper privileged registers */
254 case MISCREG_HPSTATE
:
255 return (MiscReg
)hpstate
;
256 case MISCREG_HTSTATE
:
257 return htstate
[tl
-1];
262 case MISCREG_STRAND_STS_REG
:
263 return strandStatusReg
;
264 case MISCREG_HSTICK_CMPR
:
267 /** Floating Point Status Register */
269 DPRINTF(MiscRegs
, "FSR read as: %#x\n", fsr
);
272 case MISCREG_MMU_P_CONTEXT
:
274 case MISCREG_MMU_S_CONTEXT
:
276 case MISCREG_MMU_PART_ID
:
278 case MISCREG_MMU_LSU_CTRL
:
281 case MISCREG_SCRATCHPAD_R0
:
282 return scratchPad
[0];
283 case MISCREG_SCRATCHPAD_R1
:
284 return scratchPad
[1];
285 case MISCREG_SCRATCHPAD_R2
:
286 return scratchPad
[2];
287 case MISCREG_SCRATCHPAD_R3
:
288 return scratchPad
[3];
289 case MISCREG_SCRATCHPAD_R4
:
290 return scratchPad
[4];
291 case MISCREG_SCRATCHPAD_R5
:
292 return scratchPad
[5];
293 case MISCREG_SCRATCHPAD_R6
:
294 return scratchPad
[6];
295 case MISCREG_SCRATCHPAD_R7
:
296 return scratchPad
[7];
297 case MISCREG_QUEUE_CPU_MONDO_HEAD
:
298 return cpu_mondo_head
;
299 case MISCREG_QUEUE_CPU_MONDO_TAIL
:
300 return cpu_mondo_tail
;
301 case MISCREG_QUEUE_DEV_MONDO_HEAD
:
302 return dev_mondo_head
;
303 case MISCREG_QUEUE_DEV_MONDO_TAIL
:
304 return dev_mondo_tail
;
305 case MISCREG_QUEUE_RES_ERROR_HEAD
:
306 return res_error_head
;
307 case MISCREG_QUEUE_RES_ERROR_TAIL
:
308 return res_error_tail
;
309 case MISCREG_QUEUE_NRES_ERROR_HEAD
:
310 return nres_error_head
;
311 case MISCREG_QUEUE_NRES_ERROR_TAIL
:
312 return nres_error_tail
;
314 panic("Miscellaneous register %d not implemented\n", miscReg
);
319 ISA::readMiscReg(int miscReg
, ThreadContext
* tc
)
322 // tick and stick are aliased to each other in niagra
323 // well store the tick data in stick and the interrupt bit in tick
326 case MISCREG_PRIVTICK
:
327 // I'm not sure why legion ignores the lowest two bits, but we'll go
329 // change from curCycle() to instCount() until we're done with legion
330 DPRINTF(Timer
, "Instruction Count when TICK read: %#X stick=%#X\n",
331 tc
->getCpuPtr()->instCount(), stick
);
332 return mbits(tc
->getCpuPtr()->instCount() + (int64_t)stick
,62,2) |
335 // in legion if fp is enabled du and dl are set
339 panic("Performance Instrumentation not impl\n");
340 case MISCREG_SOFTINT_CLR
:
341 case MISCREG_SOFTINT_SET
:
342 panic("Can read from softint clr/set\n");
343 case MISCREG_SOFTINT
:
344 case MISCREG_TICK_CMPR
:
345 case MISCREG_STICK_CMPR
:
347 case MISCREG_HTSTATE
:
350 case MISCREG_STRAND_STS_REG
:
351 case MISCREG_HSTICK_CMPR
:
352 case MISCREG_QUEUE_CPU_MONDO_HEAD
:
353 case MISCREG_QUEUE_CPU_MONDO_TAIL
:
354 case MISCREG_QUEUE_DEV_MONDO_HEAD
:
355 case MISCREG_QUEUE_DEV_MONDO_TAIL
:
356 case MISCREG_QUEUE_RES_ERROR_HEAD
:
357 case MISCREG_QUEUE_RES_ERROR_TAIL
:
358 case MISCREG_QUEUE_NRES_ERROR_HEAD
:
359 case MISCREG_QUEUE_NRES_ERROR_TAIL
:
360 case MISCREG_HPSTATE
:
361 return readFSReg(miscReg
, tc
);
363 return readMiscRegNoEffect(miscReg
);
367 ISA::setMiscRegNoEffect(int miscReg
, MiscReg val
)
386 panic("PCR not implemented\n");
388 panic("PIC not implemented\n");
392 case MISCREG_SOFTINT
:
395 case MISCREG_TICK_CMPR
:
401 case MISCREG_STICK_CMPR
:
405 /** Privilged Registers */
418 case MISCREG_PRIVTICK
:
419 panic("Priviliged access to tick regesiters not implemented\n");
421 // clear lower 7 bits on writes.
422 tba
= val
& ULL(~0x7FFF);
425 pstate
= (val
& PstateMask
);
436 // case MISCREG_CANSAVE:
439 // case MISCREG_CANRESTORE:
442 // case MISCREG_CLEANWIN:
445 // case MISCREG_OTHERWIN:
448 // case MISCREG_WSTATE:
455 /** Hyper privileged registers */
456 case MISCREG_HPSTATE
:
459 case MISCREG_HTSTATE
:
467 case MISCREG_STRAND_STS_REG
:
468 strandStatusReg
= val
;
470 case MISCREG_HSTICK_CMPR
:
474 /** Floating Point Status Register */
477 DPRINTF(MiscRegs
, "FSR written with: %#x\n", fsr
);
480 case MISCREG_MMU_P_CONTEXT
:
483 case MISCREG_MMU_S_CONTEXT
:
486 case MISCREG_MMU_PART_ID
:
489 case MISCREG_MMU_LSU_CTRL
:
493 case MISCREG_SCRATCHPAD_R0
:
496 case MISCREG_SCRATCHPAD_R1
:
499 case MISCREG_SCRATCHPAD_R2
:
502 case MISCREG_SCRATCHPAD_R3
:
505 case MISCREG_SCRATCHPAD_R4
:
508 case MISCREG_SCRATCHPAD_R5
:
511 case MISCREG_SCRATCHPAD_R6
:
514 case MISCREG_SCRATCHPAD_R7
:
517 case MISCREG_QUEUE_CPU_MONDO_HEAD
:
518 cpu_mondo_head
= val
;
520 case MISCREG_QUEUE_CPU_MONDO_TAIL
:
521 cpu_mondo_tail
= val
;
523 case MISCREG_QUEUE_DEV_MONDO_HEAD
:
524 dev_mondo_head
= val
;
526 case MISCREG_QUEUE_DEV_MONDO_TAIL
:
527 dev_mondo_tail
= val
;
529 case MISCREG_QUEUE_RES_ERROR_HEAD
:
530 res_error_head
= val
;
532 case MISCREG_QUEUE_RES_ERROR_TAIL
:
533 res_error_tail
= val
;
535 case MISCREG_QUEUE_NRES_ERROR_HEAD
:
536 nres_error_head
= val
;
538 case MISCREG_QUEUE_NRES_ERROR_TAIL
:
539 nres_error_tail
= val
;
542 panic("Miscellaneous register %d not implemented\n", miscReg
);
547 ISA::setMiscReg(int miscReg
, MiscReg val
, ThreadContext
* tc
)
549 MiscReg new_val
= val
;
554 // stick and tick are same thing on niagra
555 // use stick for offset and tick for holding intrrupt bit
556 stick
= mbits(val
,62,0) - tc
->getCpuPtr()->instCount();
557 tick
= mbits(val
,63,63);
558 DPRINTF(Timer
, "Writing TICK=%#X\n", val
);
561 // Configure the fpu based on the fprs
564 // Set up performance counting based on pcr value
567 pstate
= val
& PstateMask
;
572 if (hpstate
.tlz
&& tl
== 0 && !hpstate
.hpriv
)
573 tc
->getCpuPtr()->postInterrupt(IT_TRAP_LEVEL_ZERO
, 0);
575 tc
->getCpuPtr()->clearInterrupt(IT_TRAP_LEVEL_ZERO
, 0);
579 new_val
= val
>= NWindows
? NWindows
- 1 : val
;
581 new_val
= NWindows
- 1;
583 installWindow(new_val
, CurrentWindowOffset
);
584 installWindow(new_val
- 1, NextWindowOffset
);
585 installWindow(new_val
+ 1, PreviousWindowOffset
);
588 installGlobals(val
, CurrentGlobalsOffset
);
589 installGlobals(val
, NextGlobalsOffset
);
590 installGlobals(val
, PreviousGlobalsOffset
);
593 case MISCREG_SOFTINT
:
594 case MISCREG_SOFTINT_SET
:
595 case MISCREG_SOFTINT_CLR
:
596 case MISCREG_TICK_CMPR
:
597 case MISCREG_STICK_CMPR
:
599 case MISCREG_HTSTATE
:
602 case MISCREG_STRAND_STS_REG
:
603 case MISCREG_HSTICK_CMPR
:
604 case MISCREG_QUEUE_CPU_MONDO_HEAD
:
605 case MISCREG_QUEUE_CPU_MONDO_TAIL
:
606 case MISCREG_QUEUE_DEV_MONDO_HEAD
:
607 case MISCREG_QUEUE_DEV_MONDO_TAIL
:
608 case MISCREG_QUEUE_RES_ERROR_HEAD
:
609 case MISCREG_QUEUE_RES_ERROR_TAIL
:
610 case MISCREG_QUEUE_NRES_ERROR_HEAD
:
611 case MISCREG_QUEUE_NRES_ERROR_TAIL
:
612 case MISCREG_HPSTATE
:
613 setFSReg(miscReg
, val
, tc
);
616 setMiscRegNoEffect(miscReg
, new_val
);
620 ISA::serialize(EventManager
*em
, std::ostream
&os
)
622 SERIALIZE_SCALAR(asi
);
623 SERIALIZE_SCALAR(tick
);
624 SERIALIZE_SCALAR(fprs
);
625 SERIALIZE_SCALAR(gsr
);
626 SERIALIZE_SCALAR(softint
);
627 SERIALIZE_SCALAR(tick_cmpr
);
628 SERIALIZE_SCALAR(stick
);
629 SERIALIZE_SCALAR(stick_cmpr
);
630 SERIALIZE_ARRAY(tpc
,MaxTL
);
631 SERIALIZE_ARRAY(tnpc
,MaxTL
);
632 SERIALIZE_ARRAY(tstate
,MaxTL
);
633 SERIALIZE_ARRAY(tt
,MaxTL
);
634 SERIALIZE_SCALAR(tba
);
635 SERIALIZE_SCALAR((uint16_t)pstate
);
636 SERIALIZE_SCALAR(tl
);
637 SERIALIZE_SCALAR(pil
);
638 SERIALIZE_SCALAR(cwp
);
639 SERIALIZE_SCALAR(gl
);
640 SERIALIZE_SCALAR((uint64_t)hpstate
);
641 SERIALIZE_ARRAY(htstate
,MaxTL
);
642 SERIALIZE_SCALAR(hintp
);
643 SERIALIZE_SCALAR(htba
);
644 SERIALIZE_SCALAR(hstick_cmpr
);
645 SERIALIZE_SCALAR(strandStatusReg
);
646 SERIALIZE_SCALAR(fsr
);
647 SERIALIZE_SCALAR(priContext
);
648 SERIALIZE_SCALAR(secContext
);
649 SERIALIZE_SCALAR(partId
);
650 SERIALIZE_SCALAR(lsuCtrlReg
);
651 SERIALIZE_ARRAY(scratchPad
,8);
652 SERIALIZE_SCALAR(cpu_mondo_head
);
653 SERIALIZE_SCALAR(cpu_mondo_tail
);
654 SERIALIZE_SCALAR(dev_mondo_head
);
655 SERIALIZE_SCALAR(dev_mondo_tail
);
656 SERIALIZE_SCALAR(res_error_head
);
657 SERIALIZE_SCALAR(res_error_tail
);
658 SERIALIZE_SCALAR(nres_error_head
);
659 SERIALIZE_SCALAR(nres_error_tail
);
660 Tick tick_cmp
= 0, stick_cmp
= 0, hstick_cmp
= 0;
661 ThreadContext
*tc
= NULL
;
664 bool tick_intr_sched
= true;
667 tc
= tickCompare
->getTC();
668 else if (sTickCompare
)
669 tc
= sTickCompare
->getTC();
670 else if (hSTickCompare
)
671 tc
= hSTickCompare
->getTC();
673 tick_intr_sched
= false;
675 SERIALIZE_SCALAR(tick_intr_sched
);
678 cpu
= tc
->getCpuPtr();
679 tc_num
= cpu
->findContext(tc
);
680 if (tickCompare
&& tickCompare
->scheduled())
681 tick_cmp
= tickCompare
->when();
682 if (sTickCompare
&& sTickCompare
->scheduled())
683 stick_cmp
= sTickCompare
->when();
684 if (hSTickCompare
&& hSTickCompare
->scheduled())
685 hstick_cmp
= hSTickCompare
->when();
687 SERIALIZE_OBJPTR(cpu
);
688 SERIALIZE_SCALAR(tc_num
);
689 SERIALIZE_SCALAR(tick_cmp
);
690 SERIALIZE_SCALAR(stick_cmp
);
691 SERIALIZE_SCALAR(hstick_cmp
);
696 ISA::unserialize(EventManager
*em
, Checkpoint
*cp
, const std::string
§ion
)
698 UNSERIALIZE_SCALAR(asi
);
699 UNSERIALIZE_SCALAR(tick
);
700 UNSERIALIZE_SCALAR(fprs
);
701 UNSERIALIZE_SCALAR(gsr
);
702 UNSERIALIZE_SCALAR(softint
);
703 UNSERIALIZE_SCALAR(tick_cmpr
);
704 UNSERIALIZE_SCALAR(stick
);
705 UNSERIALIZE_SCALAR(stick_cmpr
);
706 UNSERIALIZE_ARRAY(tpc
,MaxTL
);
707 UNSERIALIZE_ARRAY(tnpc
,MaxTL
);
708 UNSERIALIZE_ARRAY(tstate
,MaxTL
);
709 UNSERIALIZE_ARRAY(tt
,MaxTL
);
710 UNSERIALIZE_SCALAR(tba
);
713 UNSERIALIZE_SCALAR(pstate
);
714 this->pstate
= pstate
;
716 UNSERIALIZE_SCALAR(tl
);
717 UNSERIALIZE_SCALAR(pil
);
718 UNSERIALIZE_SCALAR(cwp
);
719 UNSERIALIZE_SCALAR(gl
);
723 UNSERIALIZE_SCALAR(hpstate
);
724 this->hpstate
= hpstate
;
726 UNSERIALIZE_ARRAY(htstate
,MaxTL
);
727 UNSERIALIZE_SCALAR(hintp
);
728 UNSERIALIZE_SCALAR(htba
);
729 UNSERIALIZE_SCALAR(hstick_cmpr
);
730 UNSERIALIZE_SCALAR(strandStatusReg
);
731 UNSERIALIZE_SCALAR(fsr
);
732 UNSERIALIZE_SCALAR(priContext
);
733 UNSERIALIZE_SCALAR(secContext
);
734 UNSERIALIZE_SCALAR(partId
);
735 UNSERIALIZE_SCALAR(lsuCtrlReg
);
736 UNSERIALIZE_ARRAY(scratchPad
,8);
737 UNSERIALIZE_SCALAR(cpu_mondo_head
);
738 UNSERIALIZE_SCALAR(cpu_mondo_tail
);
739 UNSERIALIZE_SCALAR(dev_mondo_head
);
740 UNSERIALIZE_SCALAR(dev_mondo_tail
);
741 UNSERIALIZE_SCALAR(res_error_head
);
742 UNSERIALIZE_SCALAR(res_error_tail
);
743 UNSERIALIZE_SCALAR(nres_error_head
);
744 UNSERIALIZE_SCALAR(nres_error_tail
);
746 Tick tick_cmp
= 0, stick_cmp
= 0, hstick_cmp
= 0;
747 ThreadContext
*tc
= NULL
;
750 bool tick_intr_sched
;
751 UNSERIALIZE_SCALAR(tick_intr_sched
);
752 if (tick_intr_sched
) {
753 UNSERIALIZE_OBJPTR(cpu
);
755 UNSERIALIZE_SCALAR(tc_num
);
756 UNSERIALIZE_SCALAR(tick_cmp
);
757 UNSERIALIZE_SCALAR(stick_cmp
);
758 UNSERIALIZE_SCALAR(hstick_cmp
);
759 tc
= cpu
->getContext(tc_num
);
762 tickCompare
= new TickCompareEvent(this, tc
);
763 em
->schedule(tickCompare
, tick_cmp
);
766 sTickCompare
= new STickCompareEvent(this, tc
);
767 em
->schedule(sTickCompare
, stick_cmp
);
770 hSTickCompare
= new HSTickCompareEvent(this, tc
);
771 em
->schedule(hSTickCompare
, hstick_cmp
);