diff options
author | Kevin Lim <ktlim@umich.edu> | 2006-11-10 12:14:38 -0500 |
---|---|---|
committer | Kevin Lim <ktlim@umich.edu> | 2006-11-10 12:14:38 -0500 |
commit | 73581bf80186d71e4f59f1c69b103074a90554f9 (patch) | |
tree | 531bd4ebad377664abad2a1b3e4d6635a47c4920 /src/arch/sparc | |
parent | 6591ebb09839586b6849cd28b7c888a2757ba676 (diff) | |
parent | 9ef51f2dbaba88c10366d708f0ca872bb39064e4 (diff) | |
download | gem5-73581bf80186d71e4f59f1c69b103074a90554f9.tar.xz |
Merge ktlim@zizzer:/bk/newmem
into zamp.eecs.umich.edu:/z/ktlim2/clean/newmem-busfix
--HG--
extra : convert_revision : 56cb7fe3be5b63bd89b48ac6cb88b47d13b4c137
Diffstat (limited to 'src/arch/sparc')
-rw-r--r-- | src/arch/sparc/faults.cc | 15 | ||||
-rw-r--r-- | src/arch/sparc/isa/decoder.isa | 197 | ||||
-rw-r--r-- | src/arch/sparc/isa/formats/priv.isa | 24 | ||||
-rw-r--r-- | src/arch/sparc/isa/includes.isa | 1 | ||||
-rw-r--r-- | src/arch/sparc/isa/operands.isa | 50 | ||||
-rw-r--r-- | src/arch/sparc/miscregfile.cc | 75 | ||||
-rw-r--r-- | src/arch/sparc/miscregfile.hh | 301 | ||||
-rw-r--r-- | src/arch/sparc/process.cc | 3 | ||||
-rw-r--r-- | src/arch/sparc/system.cc | 42 | ||||
-rw-r--r-- | src/arch/sparc/system.hh | 9 |
10 files changed, 389 insertions, 328 deletions
diff --git a/src/arch/sparc/faults.cc b/src/arch/sparc/faults.cc index e895c02db..57ee040f1 100644 --- a/src/arch/sparc/faults.cc +++ b/src/arch/sparc/faults.cc @@ -493,21 +493,22 @@ void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv) void getREDVector(Addr & PC, Addr & NPC) { + //XXX The following constant might belong in a header file. const Addr RSTVAddr = 0xFFFFFFFFF0000000ULL; PC = RSTVAddr | 0xA0; NPC = PC + sizeof(MachInst); } -void getHyperVector(Addr & PC, Addr & NPC, MiscReg TT) +void getHyperVector(ThreadContext * tc, Addr & PC, Addr & NPC, MiscReg TT) { - Addr HTBA ; + Addr HTBA = tc->readMiscReg(MISCREG_HTBA); PC = (HTBA & ~mask(14)) | ((TT << 5) & mask(14)); NPC = PC + sizeof(MachInst); } -void getPrivVector(Addr & PC, Addr & NPC, MiscReg TT, MiscReg TL) +void getPrivVector(ThreadContext * tc, Addr & PC, Addr & NPC, MiscReg TT, MiscReg TL) { - Addr TBA ; + Addr TBA = tc->readMiscReg(MISCREG_TBA); PC = (TBA & ~mask(15)) | (TL > 1 ? (1 << 14) : 0) | ((TT << 5) & mask(14)); @@ -556,17 +557,17 @@ void SparcFaultBase::invoke(ThreadContext * tc) { //guest_watchdog fault doNormalFault(tc, trapType(), true); - getHyperVector(PC, NPC, 2); + getHyperVector(tc, PC, NPC, 2); } else if(level == Hyperprivileged) { doNormalFault(tc, trapType(), true); - getHyperVector(PC, NPC, trapType()); + getHyperVector(tc, PC, NPC, trapType()); } else { doNormalFault(tc, trapType(), false); - getPrivVector(PC, NPC, trapType(), TL+1); + getPrivVector(tc, PC, NPC, trapType(), TL+1); } tc->setPC(PC); diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa index a5f43367d..4f3ea7810 100644 --- a/src/arch/sparc/isa/decoder.isa +++ b/src/arch/sparc/isa/decoder.isa @@ -346,22 +346,93 @@ decode OP default Unknown::unknown() 0x0: sra({{Rd = Rs1.sw >> (I ? SHCNT32 : Rs2<4:0>);}}); 0x1: srax({{Rd = Rs1.sdw >> (I ? SHCNT64 : Rs2<5:0>);}}); } - // XXX might want a format rdipr thing here 0x28: decode RS1 { - 0xF: decode I { + 0x00: NoPriv::rdy({{Rd = Y;}}); + //1 should cause an illegal instruction exception + 0x02: NoPriv::rdccr({{Rd = Ccr;}}); + 0x03: NoPriv::rdasi({{Rd = Asi;}}); + 0x04: PrivCheck::rdtick({{Rd = Tick;}}, {{Tick<63:>}}); + 0x05: NoPriv::rdpc({{ + if(Pstate<3:>) + Rd = (xc->readPC())<31:0>; + else + Rd = xc->readPC();}}); + 0x06: NoPriv::rdfprs({{ + //Wait for all fpops to finish. + Rd = Fprs; + }}); + //7-14 should cause an illegal instruction exception + 0x0F: decode I { 0x0: Nop::stbar({{/*stuff*/}}); 0x1: Nop::membar({{/*stuff*/}}); } - default: rdasr({{ - Rd = xc->readMiscRegWithEffect(RS1 + AsrStart); + 0x10: Priv::rdpcr({{Rd = Pcr;}}); + 0x11: PrivCheck::rdpic({{Rd = Pic;}}, {{Pcr<0:>}}); + //0x12 should cause an illegal instruction exception + 0x13: NoPriv::rdgsr({{ + if(Fprs<2:> == 0 || Pstate<4:> == 0) + Rd = Gsr; + else + fault = new FpDisabled; }}); + //0x14-0x15 should cause an illegal instruction exception + 0x16: Priv::rdsoftint({{Rd = Softint;}}); + 0x17: Priv::rdtick_cmpr({{Rd = TickCmpr;}}); + 0x18: PrivCheck::rdstick({{Rd = Stick}}, {{Stick<63:>}}); + 0x19: Priv::rdstick_cmpr({{Rd = StickCmpr;}}); + //0x1A-0x1F should cause an illegal instruction exception + } + 0x29: decode RS1 { + 0x00: HPriv::rdhprhpstate({{Rd = Hpstate;}}); + 0x01: HPriv::rdhprhtstate({{ + if(Tl == 0) + return new IllegalInstruction; + Rd = Htstate; + }}); + //0x02 should cause an illegal instruction exception + 0x03: HPriv::rdhprhintp({{Rd = Hintp;}}); + //0x04 should cause an illegal instruction exception + 0x05: HPriv::rdhprhtba({{Rd = Htba;}}); + 0x06: HPriv::rdhprhver({{Rd = Hver;}}); + //0x07-0x1E should cause an illegal instruction exception + 0x1F: HPriv::rdhprhstick_cmpr({{Rd = HstickCmpr;}}); + } + 0x2A: decode RS1 { + 0x00: Priv::rdprtpc({{ + if(Tl == 0) + return new IllegalInstruction; + Rd = Tpc; + }}); + 0x01: Priv::rdprtnpc({{ + if(Tl == 0) + return new IllegalInstruction; + Rd = Tnpc; + }}); + 0x02: Priv::rdprtstate({{ + if(Tl == 0) + return new IllegalInstruction; + Rd = Tstate; + }}); + 0x03: Priv::rdprtt({{ + if(Tl == 0) + return new IllegalInstruction; + Rd = Tt; + }}); + 0x04: Priv::rdprtick({{Rd = Tick;}}); + 0x05: Priv::rdprtba({{Rd = Tba;}}); + 0x06: Priv::rdprpstate({{Rd = Pstate;}}); + 0x07: Priv::rdprtl({{Rd = Tl;}}); + 0x08: Priv::rdprpil({{Rd = Pil;}}); + 0x09: Priv::rdprcwp({{Rd = Cwp;}}); + 0x0A: Priv::rdprcansave({{Rd = Cansave;}}); + 0x0B: Priv::rdprcanrestore({{Rd = Canrestore;}}); + 0x0C: Priv::rdprcleanwin({{Rd = Cleanwin;}}); + 0x0D: Priv::rdprotherwin({{Rd = Otherwin;}}); + 0x0E: Priv::rdprwstate({{Rd = Wstate;}}); + //0x0F should cause an illegal instruction exception + 0x10: Priv::rdprgl({{Rd = Gl;}}); + //0x11-0x1F should cause an illegal instruction exception } - 0x29: HPriv::rdhpr({{ - Rd = xc->readMiscRegWithEffect(RS1 + HprStart); - }}); - 0x2A: Priv::rdpr({{ - Rd = xc->readMiscRegWithEffect(RS1 + PrStart); - }}); 0x2B: BasicOperate::flushw({{ if(NWindows - 2 - Cansave == 0) { @@ -417,9 +488,35 @@ decode OP default Unknown::unknown() 0x6: movrg({{Rd = (Rs1.sdw > 0) ? Rs2_or_imm10 : Rd;}}); 0x7: movrge({{Rd = (Rs1.sdw >= 0) ? Rs2_or_imm10 : Rd;}}); } - 0x30: wrasr({{ - xc->setMiscRegWithEffect(RD + AsrStart, Rs1 ^ Rs2_or_imm13); - }}); + 0x30: decode RD { + 0x00: NoPriv::wry({{Y = Rs1 ^ Rs2_or_imm13;}}); + //0x01 should cause an illegal instruction exception + 0x02: NoPriv::wrccr({{Ccr = Rs1 ^ Rs2_or_imm13;}}); + 0x03: NoPriv::wrasi({{Ccr = Rs1 ^ Rs2_or_imm13;}}); + //0x04-0x05 should cause an illegal instruction exception + 0x06: NoPriv::wrfprs({{Fprs = Rs1 ^ Rs2_or_imm13;}}); + //0x07-0x0E should cause an illegal instruction exception + 0x0F: Trap::softreset({{fault = new SoftwareInitiatedReset;}}); + 0x10: Priv::wrpcr({{Pcr = Rs1 ^ Rs2_or_imm13;}}); + 0x11: PrivCheck::wrpic({{Pic = Rs1 ^ Rs2_or_imm13;}}, {{Pcr<0:>}}); + //0x12 should cause an illegal instruction exception + 0x13: NoPriv::wrgsr({{ + if(Fprs<2:> == 0 || Pstate<4:> == 0) + return new FpDisabled; + Gsr = Rs1 ^ Rs2_or_imm13; + }}); + 0x14: Priv::wrsoftint_set({{SoftintSet = Rs1 ^ Rs2_or_imm13;}}); + 0x15: Priv::wrsoftint_clr({{SoftintClr = Rs1 ^ Rs2_or_imm13;}}); + 0x16: Priv::wrsoftint({{Softint = Rs1 ^ Rs2_or_imm13;}}); + 0x17: Priv::wrtick_cmpr({{TickCmpr = Rs1 ^ Rs2_or_imm13;}}); + 0x18: NoPriv::wrstick({{ + if(!Hpstate<2:>) + return new IllegalInstruction; + Stick = Rs1 ^ Rs2_or_imm13; + }}); + 0x19: Priv::wrstick_cmpr({{StickCmpr = Rs1 ^ Rs2_or_imm13;}}); + //0x1A-0x1F should cause an illegal instruction exception + } 0x31: decode FCN { 0x0: Priv::saved({{ assert(Cansave < NWindows - 2); @@ -440,16 +537,70 @@ decode OP default Unknown::unknown() Otherwin = Otherwin - 1; }}); } - 0x32: Priv::wrpr({{ - // XXX Need to protect with format that traps non-priv - // access - xc->setMiscRegWithEffect(RD + PrStart, Rs1 ^ Rs2_or_imm13); - }}); - 0x33: HPriv::wrhpr({{ - // XXX Need to protect with format that traps non-priv/priv - // access - xc->setMiscRegWithEffect(RD + HprStart, Rs1 ^ Rs2_or_imm13); - }}); + 0x32: decode RD { + 0x00: Priv::wrprtpc({{ + if(Tl == 0) + return new IllegalInstruction; + else + Tpc = Rs1 ^ Rs2_or_imm13; + }}); + 0x01: Priv::wrprtnpc({{ + if(Tl == 0) + return new IllegalInstruction; + else + Tnpc = Rs1 ^ Rs2_or_imm13; + }}); + 0x02: Priv::wrprtstate({{ + if(Tl == 0) + return new IllegalInstruction; + else + Tstate = Rs1 ^ Rs2_or_imm13; + }}); + 0x03: Priv::wrprtt({{ + if(Tl == 0) + return new IllegalInstruction; + else + Tt = Rs1 ^ Rs2_or_imm13; + }}); + 0x04: HPriv::wrprtick({{Tick = Rs1 ^ Rs2_or_imm13;}}); + 0x05: Priv::wrprtba({{Tba = Rs1 ^ Rs2_or_imm13;}}); + 0x06: Priv::wrprpstate({{Pstate = Rs1 ^ Rs2_or_imm13;}}); + 0x07: Priv::wrprtl({{ + if(Pstate<2:> && !Hpstate<2:>) + Tl = std::min<uint64_t>(Rs1 ^ Rs2_or_imm13, MaxPTL); + else + Tl = std::min<uint64_t>(Rs1 ^ Rs2_or_imm13, MaxTL); + }}); + 0x08: Priv::wrprpil({{Pil = Rs1 ^ Rs2_or_imm13;}}); + 0x09: Priv::wrprcwp({{Cwp = Rs1 ^ Rs2_or_imm13;}}); + 0x0A: Priv::wrprcansave({{Cansave = Rs1 ^ Rs2_or_imm13;}}); + 0x0B: Priv::wrprcanrestore({{Canrestore = Rs1 ^ Rs2_or_imm13;}}); + 0x0C: Priv::wrprcleanwin({{Cleanwin = Rs1 ^ Rs2_or_imm13;}}); + 0x0D: Priv::wrprotherwin({{Otherwin = Rs1 ^ Rs2_or_imm13;}}); + 0x0E: Priv::wrprwstate({{Wstate = Rs1 ^ Rs2_or_imm13;}}); + //0x0F should cause an illegal instruction exception + 0x10: Priv::wrprgl({{ + if(Pstate<2:> && !Hpstate<2:>) + Gl = std::min<uint64_t>(Rs1 ^ Rs2_or_imm13, MaxPGL); + else + Gl = std::min<uint64_t>(Rs1 ^ Rs2_or_imm13, MaxGL); + }}); + //0x11-0x1F should cause an illegal instruction exception + } + 0x33: decode RD { + 0x00: HPriv::wrhprhpstate({{Hpstate = Rs1 ^ Rs2_or_imm13;}}); + 0x01: HPriv::wrhprhtstate({{ + if(Tl == 0) + return new IllegalInstruction; + Htstate = Rs1 ^ Rs2_or_imm13; + }}); + //0x02 should cause an illegal instruction exception + 0x03: HPriv::wrhprhintp({{Hintp = Rs1 ^ Rs2_or_imm13;}}); + //0x04 should cause an illegal instruction exception + 0x05: HPriv::wrhprhtba({{Htba = Rs1 ^ Rs2_or_imm13;}}); + //0x06-0x01D should cause an illegal instruction exception + 0x1F: HPriv::wrhprhstick_cmpr({{HstickCmpr = Rs1 ^ Rs2_or_imm13;}}); + } 0x34: decode OPF{ format BasicOperate{ 0x01: fmovs({{ diff --git a/src/arch/sparc/isa/formats/priv.isa b/src/arch/sparc/isa/formats/priv.isa index 04c67d332..55bf968f4 100644 --- a/src/arch/sparc/isa/formats/priv.isa +++ b/src/arch/sparc/isa/formats/priv.isa @@ -119,18 +119,34 @@ let {{ return (header_output, decoder_output, exec_output, decode_block) }}; -// Primary format for integer operate instructions: def format Priv(code, *opt_flags) {{ - checkCode = "!(Pstate<2:2> || Hpstate<2:2>)" + checkCode = "!(Pstate<2:> || Hpstate<2:>)" (header_output, decoder_output, exec_output, decode_block) = doPrivFormat(code, - checkCode, name, Name, opt_flags + ('IprAccessOp',)) + checkCode, name, Name, opt_flags) +}}; + +def format NoPriv(code, *opt_flags) {{ + #Instructions which use this format don't really check for + #any particular mode, but the disassembly is performed + #using the control registers actual name + checkCode = "false" + (header_output, decoder_output, + exec_output, decode_block) = doPrivFormat(code, + checkCode, name, Name, opt_flags) +}}; + +def format PrivCheck(code, extraCheckCode, *opt_flags) {{ + checkCode = "(%s) && !(Pstate<2:> || Hpstate<2:>)" % extraCheckCode + (header_output, decoder_output, + exec_output, decode_block) = doPrivFormat(code, + checkCode, name, Name, opt_flags) }}; def format HPriv(code, *opt_flags) {{ checkCode = "!Hpstate<2:2>" (header_output, decoder_output, exec_output, decode_block) = doPrivFormat(code, - checkCode, name, Name, opt_flags + ('IprAccessOp',)) + checkCode, name, Name, opt_flags) }}; diff --git a/src/arch/sparc/isa/includes.isa b/src/arch/sparc/isa/includes.isa index a324756ec..624afb693 100644 --- a/src/arch/sparc/isa/includes.isa +++ b/src/arch/sparc/isa/includes.isa @@ -54,6 +54,7 @@ output decoder {{ #if defined(linux) #include <fenv.h> #endif +#include <algorithm> using namespace SparcISA; }}; diff --git a/src/arch/sparc/isa/operands.isa b/src/arch/sparc/isa/operands.isa index 80b499b91..caee20b0c 100644 --- a/src/arch/sparc/isa/operands.isa +++ b/src/arch/sparc/isa/operands.isa @@ -80,8 +80,6 @@ def operands {{ 'Frs2': ('FloatReg', 'df', 'dfpr(RS2)', 'IsFloating', 12), 'NPC': ('NPC', 'udw', None, ( None, None, 'IsControl' ), 31), 'NNPC': ('NNPC', 'udw', None, (None, None, 'IsControl' ), 32), - #'Runiq': ('ControlReg', 'uq', 'Uniq', None, 1), - #'FPCR': ('ControlReg', 'uq', 'Fpcr', None, 1), 'R0': ('IntReg', 'udw', '0', None, 6), 'R1': ('IntReg', 'udw', '1', None, 7), 'R15': ('IntReg', 'udw', '15', 'IsInteger', 8), @@ -91,24 +89,42 @@ def operands {{ 'Y': ('ControlReg', 'udw', 'MISCREG_Y', None, 40), 'Ccr': ('ControlReg', 'udw', 'MISCREG_CCR', None, 41), 'Asi': ('ControlReg', 'udw', 'MISCREG_ASI', None, 42), + 'Fprs': ('ControlReg', 'udw', 'MISCREG_FPRS', None, 43), + 'Pcr': ('ControlReg', 'udw', 'MISCREG_PCR', None, 44), + 'Pic': ('ControlReg', 'udw', 'MISCREG_PIC', None, 45), + 'Gsr': ('ControlReg', 'udw', 'MISCREG_GSR', None, 46), + 'Softint': ('ControlReg', 'udw', 'MISCREG_SOFTINT', None, 47), + 'SoftintSet': ('ControlReg', 'udw', 'MISCREG_SOFTINT_SET', None, 48), + 'SoftintClr': ('ControlReg', 'udw', 'MISCREG_SOFTINT_CLR', None, 49), + 'TickCmpr': ('ControlReg', 'udw', 'MISCREG_TICK_CMPR', None, 50), + 'Stick': ('ControlReg', 'udw', 'MISCREG_STICK', None, 51), + 'StickCmpr': ('ControlReg', 'udw', 'MISCREG_STICK_CMPR', None, 52), - 'Tpc': ('ControlReg', 'udw', 'MISCREG_TPC', None, 43), - 'Tnpc': ('ControlReg', 'udw', 'MISCREG_TNPC', None, 44), - 'Tstate': ('ControlReg', 'udw', 'MISCREG_TSTATE', None, 45), - 'Pstate': ('ControlReg', 'udw', 'MISCREG_PSTATE', None, 46), - 'Hpstate': ('ControlReg', 'udw', 'MISCREG_HPSTATE', None, 47), - 'Tl': ('ControlReg', 'udw', 'MISCREG_TL', None, 48), + 'Tpc': ('ControlReg', 'udw', 'MISCREG_TPC', None, 53), + 'Tnpc': ('ControlReg', 'udw', 'MISCREG_TNPC', None, 54), + 'Tstate': ('ControlReg', 'udw', 'MISCREG_TSTATE', None, 55), + 'Tt': ('ControlReg', 'udw', 'MISCREG_TT', None, 56), + 'Tick': ('ControlReg', 'udw', 'MISCREG_TICK', None, 57), + 'Tba': ('ControlReg', 'udw', 'MISCREG_TBA', None, 58), + 'Pstate': ('ControlReg', 'udw', 'MISCREG_PSTATE', None, 59), + 'Tl': ('ControlReg', 'udw', 'MISCREG_TL', None, 60), + 'Pil': ('ControlReg', 'udw', 'MISCREG_PIL', None, 61), + 'Cwp': ('ControlReg', 'udw', 'MISCREG_CWP', None, 62), + 'Cansave': ('ControlReg', 'udw', 'MISCREG_CANSAVE', None, 63), + 'Canrestore': ('ControlReg', 'udw', 'MISCREG_CANRESTORE', None, 64), + 'Cleanwin': ('ControlReg', 'udw', 'MISCREG_CLEANWIN', None, 65), + 'Otherwin': ('ControlReg', 'udw', 'MISCREG_OTHERWIN', None, 66), + 'Wstate': ('ControlReg', 'udw', 'MISCREG_WSTATE', None, 67), + 'Gl': ('ControlReg', 'udw', 'MISCREG_GL', None, 68), - 'Cwp': ('ControlReg', 'udw', 'MISCREG_CWP', None, 49), - 'Cansave': ('ControlReg', 'udw', 'MISCREG_CANSAVE', None, 50), - 'Canrestore': ('ControlReg', 'udw', 'MISCREG_CANRESTORE', None, 51), - 'Cleanwin': ('ControlReg', 'udw', 'MISCREG_CLEANWIN', None, 52), - 'Otherwin': ('ControlReg', 'udw', 'MISCREG_OTHERWIN', None, 53), - 'Wstate': ('ControlReg', 'udw', 'MISCREG_WSTATE', None, 54), - 'Gl': ('ControlReg', 'udw', 'MISCREG_GL', None, 55), + 'Hpstate': ('ControlReg', 'udw', 'MISCREG_HPSTATE', None, 69), + 'Htstate': ('ControlReg', 'udw', 'MISCREG_HTSTATE', None, 70), + 'Hintp': ('ControlReg', 'udw', 'MISCREG_HINTP', None, 71), + 'Htba': ('ControlReg', 'udw', 'MISCREG_HTBA', None, 72), + 'HstickCmpr': ('ControlReg', 'udw', 'MISCREG_HSTICK_CMPR', None, 73), + 'Hver': ('ControlReg', 'udw', 'MISCREG_HVER', None, 74), - 'Fsr': ('ControlReg', 'udw', 'MISCREG_FSR', None, 56), - 'Gsr': ('ControlReg', 'udw', 'MISCREG_GSR', None, 57), + 'Fsr': ('ControlReg', 'udw', 'MISCREG_FSR', None, 80), # Mem gets a large number so it's always last 'Mem': ('Mem', 'udw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 100) diff --git a/src/arch/sparc/miscregfile.cc b/src/arch/sparc/miscregfile.cc index 217fba0bd..d52e3983f 100644 --- a/src/arch/sparc/miscregfile.cc +++ b/src/arch/sparc/miscregfile.cc @@ -29,7 +29,9 @@ * Ali Saidi */ +#include "arch/sparc/asi.hh" #include "arch/sparc/miscregfile.hh" +#include "base/bitfield.hh" #include "base/trace.hh" #include "config/full_system.hh" #include "cpu/base.hh" @@ -62,6 +64,39 @@ string SparcISA::getMiscRegName(RegIndex index) void MiscRegFile::reset() { + y = 0; + ccr = 0; + asi = 0; + tick = 0; + fprs = 0; + gsr = 0; + softint = 0; + tick_cmpr = 0; + stick = 0; + stick_cmpr = 0; + memset(tpc, 0, sizeof(tpc)); + memset(tnpc, 0, sizeof(tnpc)); + memset(tstate, 0, sizeof(tstate)); + memset(tt, 0, sizeof(tt)); + pstate = 0; + tl = 0; + pil = 0; + cwp = 0; + cansave = 0; + canrestore = 0; + cleanwin = 0; + otherwin = 0; + wstate = 0; + gl = 0; + hpstate = 0; + memset(htstate, 0, sizeof(htstate)); + hintp = 0; + htba = 0; + hstick_cmpr = 0; + strandStatusReg = 0; + fsr = 0; + implicitInstAsi = ASI_PRIMARY; + implicitDataAsi = ASI_PRIMARY; } MiscReg MiscRegFile::readReg(int miscReg) @@ -78,8 +113,9 @@ MiscReg MiscRegFile::readReg(int miscReg) case MISCREG_TICK: return tick; case MISCREG_PCR: + panic("PCR not implemented\n"); case MISCREG_PIC: - panic("ASR number %d not implemented\n", miscReg - AsrStart); + panic("PIC not implemented\n"); case MISCREG_GSR: return gsr; case MISCREG_SOFTINT: @@ -154,8 +190,8 @@ MiscReg MiscRegFile::readRegWithEffect(int miscReg, ThreadContext * tc) switch (miscReg) { case MISCREG_TICK: case MISCREG_PRIVTICK: - return tc->getCpuPtr()->curCycle() - tickFields.counter | - tickFields.npt << 63; + return tc->getCpuPtr()->curCycle() - (tick & mask(63)) | + (tick & ~(mask(63))) << 63; case MISCREG_FPRS: panic("FPU not implemented\n"); case MISCREG_PCR: @@ -171,7 +207,7 @@ MiscReg MiscRegFile::readRegWithEffect(int miscReg, ThreadContext * tc) SparcSystem *sys; sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr()); assert(sys != NULL); - return curTick/Clock::Int::ns - sys->sysTick | stickFields.npt << 63; + return curTick/Clock::Int::ns - sys->sysTick | (stick & ~(mask(63))); #endif case MISCREG_HVER: return NWindows | MaxTL << 8 | MaxGL << 16; @@ -198,8 +234,9 @@ void MiscRegFile::setReg(int miscReg, const MiscReg &val) tick = val; break; case MISCREG_PCR: + panic("PCR not implemented\n"); case MISCREG_PIC: - panic("ASR number %d not implemented\n", miscReg - AsrStart); + panic("PIC not implemented\n"); case MISCREG_GSR: gsr = val; break; @@ -303,12 +340,12 @@ inline void MiscRegFile::setImplicitAsis() if(tl == 0) { implicitInstAsi = implicitDataAsi = - pstateFields.cle ? ASI_PRIMARY_LITTLE : ASI_PRIMARY; + (pstate & (1 << 9)) ? ASI_PRIMARY_LITTLE : ASI_PRIMARY; } else if(tl <= MaxPTL) { implicitInstAsi = ASI_NUCLEUS; - implicitDataAsi = pstateFields.cle ? ASI_NUCLEUS_LITTLE : ASI_NUCLEUS; + implicitDataAsi = (pstate & (1 << 9)) ? ASI_NUCLEUS_LITTLE : ASI_NUCLEUS; } else { @@ -328,8 +365,8 @@ void MiscRegFile::setRegWithEffect(int miscReg, #endif switch (miscReg) { case MISCREG_TICK: - tickFields.counter = tc->getCpuPtr()->curCycle() - val & ~Bit64; - tickFields.npt = val & Bit64 ? 1 : 0; + tick = tc->getCpuPtr()->curCycle() - val & ~Bit64; + tick |= val & Bit64; break; case MISCREG_FPRS: //Configure the fpu based on the fprs @@ -369,10 +406,10 @@ void MiscRegFile::setRegWithEffect(int miscReg, if (tickCompare == NULL) tickCompare = new TickCompareEvent(this, tc); setReg(miscReg, val); - if (tick_cmprFields.int_dis && tickCompare->scheduled()) + if ((tick_cmpr & mask(63)) && tickCompare->scheduled()) tickCompare->deschedule(); - time = tick_cmprFields.tick_cmpr - tickFields.counter; - if (!tick_cmprFields.int_dis && time > 0) + time = (tick_cmpr & mask(63)) - (tick & mask(63)); + if (!(tick_cmpr & ~mask(63)) && time > 0) tickCompare->schedule(time * tc->getCpuPtr()->cycles(1)); break; #endif @@ -390,17 +427,17 @@ void MiscRegFile::setRegWithEffect(int miscReg, sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr()); assert(sys != NULL); sys->sysTick = curTick/Clock::Int::ns - val & ~Bit64; - stickFields.npt = val & Bit64 ? 1 : 0; + stick |= val & Bit64; break; case MISCREG_STICK_CMPR: if (sTickCompare == NULL) sTickCompare = new STickCompareEvent(this, tc); sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr()); assert(sys != NULL); - if (stick_cmprFields.int_dis && sTickCompare->scheduled()) + if ((stick_cmpr & ~mask(63)) && sTickCompare->scheduled()) sTickCompare->deschedule(); - time = stick_cmprFields.tick_cmpr - sys->sysTick; - if (!stick_cmprFields.int_dis && time > 0) + time = (stick_cmpr & mask(63)) - sys->sysTick; + if (!(stick_cmpr & ~mask(63)) && time > 0) sTickCompare->schedule(time * Clock::Int::ns); break; case MISCREG_HSTICK_CMPR: @@ -408,10 +445,10 @@ void MiscRegFile::setRegWithEffect(int miscReg, hSTickCompare = new HSTickCompareEvent(this, tc); sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr()); assert(sys != NULL); - if (hstick_cmprFields.int_dis && hSTickCompare->scheduled()) + if ((hstick_cmpr & ~mask(63)) && hSTickCompare->scheduled()) hSTickCompare->deschedule(); - int64_t time = hstick_cmprFields.tick_cmpr - sys->sysTick; - if (!hstick_cmprFields.int_dis && time > 0) + int64_t time = (hstick_cmpr & mask(63)) - sys->sysTick; + if (!(hstick_cmpr & ~mask(63)) && time > 0) hSTickCompare->schedule(time * Clock::Int::ns); break; #endif diff --git a/src/arch/sparc/miscregfile.hh b/src/arch/sparc/miscregfile.hh index 0e424dbd2..f74943256 100644 --- a/src/arch/sparc/miscregfile.hh +++ b/src/arch/sparc/miscregfile.hh @@ -46,59 +46,53 @@ namespace SparcISA //These functions map register indices to names std::string getMiscRegName(RegIndex); - const int AsrStart = 0; - const int PrStart = 32; - const int HprStart = 64; - const int MiscStart = 96; - enum MiscRegIndex { /** Ancillary State Registers */ - MISCREG_Y = AsrStart + 0, - MISCREG_CCR = AsrStart + 2, - MISCREG_ASI = AsrStart + 3, - MISCREG_TICK = AsrStart + 4, - MISCREG_FPRS = AsrStart + 6, - MISCREG_PCR = AsrStart + 16, - MISCREG_PIC = AsrStart + 17, - MISCREG_GSR = AsrStart + 19, - MISCREG_SOFTINT_SET = AsrStart + 20, - MISCREG_SOFTINT_CLR = AsrStart + 21, - MISCREG_SOFTINT = AsrStart + 22, - MISCREG_TICK_CMPR = AsrStart + 23, - MISCREG_STICK = AsrStart + 24, - MISCREG_STICK_CMPR = AsrStart + 25, + MISCREG_Y, + MISCREG_CCR, + MISCREG_ASI, + MISCREG_TICK, + MISCREG_FPRS, + MISCREG_PCR, + MISCREG_PIC, + MISCREG_GSR, + MISCREG_SOFTINT_SET, + MISCREG_SOFTINT_CLR, + MISCREG_SOFTINT, + MISCREG_TICK_CMPR, + MISCREG_STICK, + MISCREG_STICK_CMPR, /** Privilged Registers */ - MISCREG_TPC = PrStart + 0, - MISCREG_TNPC = PrStart + 1, - MISCREG_TSTATE = PrStart + 2, - MISCREG_TT = PrStart + 3, - MISCREG_PRIVTICK = PrStart + 4, - MISCREG_TBA = PrStart + 5, - MISCREG_PSTATE = PrStart + 6, - MISCREG_TL = PrStart + 7, - MISCREG_PIL = PrStart + 8, - MISCREG_CWP = PrStart + 9, - MISCREG_CANSAVE = PrStart + 10, - MISCREG_CANRESTORE = PrStart + 11, - MISCREG_CLEANWIN = PrStart + 12, - MISCREG_OTHERWIN = PrStart + 13, - MISCREG_WSTATE = PrStart + 14, - MISCREG_GL = PrStart + 16, + MISCREG_TPC, + MISCREG_TNPC, + MISCREG_TSTATE, + MISCREG_TT, + MISCREG_PRIVTICK, + MISCREG_TBA, + MISCREG_PSTATE, + MISCREG_TL, + MISCREG_PIL, + MISCREG_CWP, + MISCREG_CANSAVE, + MISCREG_CANRESTORE, + MISCREG_CLEANWIN, + MISCREG_OTHERWIN, + MISCREG_WSTATE, + MISCREG_GL, /** Hyper privileged registers */ - MISCREG_HPSTATE = HprStart + 0, - MISCREG_HTSTATE = HprStart + 1, - MISCREG_HINTP = HprStart + 3, - MISCREG_HTBA = HprStart + 5, - MISCREG_HVER = HprStart + 6, - MISCREG_STRAND_STS_REG = HprStart + 16, - MISCREG_HSTICK_CMPR = HprStart + 31, + MISCREG_HPSTATE, + MISCREG_HTSTATE, + MISCREG_HINTP, + MISCREG_HTBA, + MISCREG_HVER, + MISCREG_STRAND_STS_REG, + MISCREG_HSTICK_CMPR, /** Floating Point Status Register */ - MISCREG_FSR = MiscStart + 0 - + MISCREG_FSR }; // The control registers, broken out into fields @@ -107,93 +101,16 @@ namespace SparcISA private: /* ASR Registers */ - union { - uint64_t y; // Y (used in obsolete multiplication) - struct { - uint64_t value:32; // The actual value stored in y - uint64_t :32; // reserved bits - } yFields; - }; - union { - uint8_t ccr; // Condition Code Register - struct { - union { - uint8_t icc:4; // 32-bit condition codes - struct { - uint8_t c:1; // Carry - uint8_t v:1; // Overflow - uint8_t z:1; // Zero - uint8_t n:1; // Negative - } iccFields; - }; - union { - uint8_t xcc:4; // 64-bit condition codes - struct { - uint8_t c:1; // Carry - uint8_t v:1; // Overflow - uint8_t z:1; // Zero - uint8_t n:1; // Negative - } xccFields; - }; - } ccrFields; - }; + uint64_t y; // Y (used in obsolete multiplication) + uint8_t ccr; // Condition Code Register uint8_t asi; // Address Space Identifier - union { - uint64_t tick; // Hardware clock-tick counter - struct { - int64_t counter:63; // Clock-tick count - uint64_t npt:1; // Non-priveleged trap - } tickFields; - }; - union { - uint8_t fprs; // Floating-Point Register State - struct { - uint8_t dl:1; // Dirty lower - uint8_t du:1; // Dirty upper - uint8_t fef:1; // FPRS enable floating-Point - } fprsFields; - }; - union { - uint64_t gsr; //General Status Register - struct { - uint64_t mask:32; - uint64_t :4; - uint64_t im:1; - uint64_t irnd:2; - uint64_t :17; - uint64_t scale:5; - uint64_t align:3; - } gsrFields; - }; - union { - uint64_t softint; - struct { - uint64_t tm:1; - uint64_t int_level:14; - uint64_t sm:1; - } softintFields; - }; - union { - uint64_t tick_cmpr; // Hardware tick compare registers - struct { - uint64_t tick_cmpr:63; // Clock-tick count - uint64_t int_dis:1; // Non-priveleged trap - } tick_cmprFields; - }; - union { - uint64_t stick; // Hardware clock-tick counter - struct { - int64_t :63; // Not used, storage in SparcSystem - uint64_t npt:1; // Non-priveleged trap - } stickFields; - }; - union { - uint64_t stick_cmpr; // Hardware tick compare registers - struct { - uint64_t tick_cmpr:63; // Clock-tick count - uint64_t int_dis:1; // Non-priveleged trap - } stick_cmprFields; - }; + uint64_t tick; // Hardware clock-tick counter + uint8_t fprs; // Floating-Point Register State + uint64_t gsr; // General Status Register + uint64_t softint; + uint64_t tick_cmpr; // Hardware tick compare registers + uint64_t stick; // Hardware clock-tick counter + uint64_t stick_cmpr; // Hardware tick compare registers /* Privileged Registers */ @@ -201,37 +118,12 @@ namespace SparcISA // previous trap level) uint64_t tnpc[MaxTL]; // Trap Next Program Counter (value from // previous trap level) - union { - uint64_t tstate[MaxTL]; // Trap State - struct { - //Values are from previous trap level - uint64_t cwp:5; // Current Window Pointer - uint64_t :3; // Reserved bits - uint64_t pstate:13; // Process State - uint64_t :3; // Reserved bits - uint64_t asi:8; // Address Space Identifier - uint64_t ccr:8; // Condition Code Register - uint64_t gl:8; // Global level - } tstateFields[MaxTL]; - }; + uint64_t tstate[MaxTL]; // Trap State uint16_t tt[MaxTL]; // Trap Type (Type of trap which occured // on the previous level) uint64_t tba; // Trap Base Address - union { - uint16_t pstate; // Process State Register - struct { - uint16_t :1; // reserved - uint16_t ie:1; // Interrupt enable - uint16_t priv:1; // Privelege mode - uint16_t am:1; // Address mask - uint16_t pef:1; // PSTATE enable floating-point - uint16_t :1; // reserved2 - uint16_t mm:2; // Memory Model - uint16_t tle:1; // Trap little-endian - uint16_t cle:1; // Current little-endian - } pstateFields; - }; + uint16_t pstate; // Process State Register uint8_t tl; // Trap Level uint8_t pil; // Process Interrupt Register uint8_t cwp; // Current Window Pointer @@ -239,97 +131,20 @@ namespace SparcISA uint8_t canrestore; // Restorable windows uint8_t cleanwin; // Clean windows uint8_t otherwin; // Other windows - union { - uint8_t wstate; // Window State - struct { - uint8_t normal:3; // Bits TT<4:2> are set to on a normal - // register window trap - uint8_t other:3; // Bits TT<4:2> are set to on an "otherwin" - // register window trap - } wstateFields; - }; + uint8_t wstate; // Window State uint8_t gl; // Global level register - /** Hyperprivileged Registers */ - union { - uint64_t hpstate; // Hyperprivileged State Register - struct { - uint8_t tlz: 1; - uint8_t :1; - uint8_t hpriv:1; - uint8_t :2; - uint8_t red:1; - uint8_t :4; - uint8_t ibe:1; - uint8_t id:1; - } hpstateFields; - }; - - uint64_t htstate[MaxTL]; // Hyperprivileged Trap State Register + uint64_t hpstate; // Hyperprivileged State Register + uint64_t htstate[MaxTL];// Hyperprivileged Trap State Register uint64_t hintp; - uint64_t htba; // Hyperprivileged Trap Base Address register - union { - uint64_t hstick_cmpr; // Hardware tick compare registers - struct { - uint64_t tick_cmpr:63; // Clock-tick count - uint64_t int_dis:1; // Non-priveleged trap - } hstick_cmprFields; - }; - - uint64_t strandStatusReg; // Per strand status register + uint64_t htba; // Hyperprivileged Trap Base Address register + uint64_t hstick_cmpr; // Hardware tick compare registers + uint64_t strandStatusReg;// Per strand status register /** Floating point misc registers. */ - union { - uint64_t fsr; // Floating-Point State Register - struct { - union { - uint64_t cexc:5; // Current excpetion - struct { - uint64_t nxc:1; // Inexact - uint64_t dzc:1; // Divide by zero - uint64_t ufc:1; // Underflow - uint64_t ofc:1; // Overflow - uint64_t nvc:1; // Invalid operand - } cexcFields; - }; - union { - uint64_t aexc:5; // Accrued exception - struct { - uint64_t nxc:1; // Inexact - uint64_t dzc:1; // Divide by zero - uint64_t ufc:1; // Underflow - uint64_t ofc:1; // Overflow - uint64_t nvc:1; // Invalid operand - } aexcFields; - }; - uint64_t fcc0:2; // Floating-Point condtion codes - uint64_t :1; // Reserved bits - uint64_t qne:1; // Deferred trap queue not empty - // with no queue, it should read 0 - uint64_t ftt:3; // Floating-Point trap type - uint64_t ver:3; // Version (of the FPU) - uint64_t :2; // Reserved bits - uint64_t ns:1; // Nonstandard floating point - union { - uint64_t tem:5; // Trap Enable Mask - struct { - uint64_t nxm:1; // Inexact - uint64_t dzm:1; // Divide by zero - uint64_t ufm:1; // Underflow - uint64_t ofm:1; // Overflow - uint64_t nvm:1; // Invalid operand - } temFields; - }; - uint64_t :2; // Reserved bits - uint64_t rd:2; // Rounding direction - uint64_t fcc1:2; // Floating-Point condition codes - uint64_t fcc2:2; // Floating-Point condition codes - uint64_t fcc3:2; // Floating-Point condition codes - uint64_t :26; // Reserved bits - } fsrFields; - }; + uint64_t fsr; // Floating-Point State Register ASI implicitInstAsi; ASI implicitDataAsi; @@ -391,8 +206,8 @@ namespace SparcISA protected: - bool isHyperPriv() { return hpstateFields.hpriv; } - bool isPriv() { return hpstateFields.hpriv || pstateFields.priv; } + bool isHyperPriv() { return (hpstate & (1 << 2)); } + bool isPriv() { return (hpstate & (1 << 2)) || (pstate & (1 << 2)); } bool isNonPriv() { return !isPriv(); } inline void setImplicitAsis(); }; diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc index a3b7dde7c..11a799ccb 100644 --- a/src/arch/sparc/process.cc +++ b/src/arch/sparc/process.cc @@ -29,6 +29,7 @@ * Ali Saidi */ +#include "arch/sparc/asi.hh" #include "arch/sparc/isa_traits.hh" #include "arch/sparc/process.hh" #include "base/loader/object_file.hh" @@ -105,6 +106,8 @@ SparcLiveProcess::startup() threadContexts[0]->setMiscReg(MISCREG_WSTATE, 0); //Set the trap level to 0 threadContexts[0]->setMiscReg(MISCREG_TL, 0); + //Set the ASI register to something fixed + threadContexts[0]->setMiscReg(MISCREG_ASI, ASI_PRIMARY); } m5_auxv_t buildAuxVect(int64_t type, int64_t val) diff --git a/src/arch/sparc/system.cc b/src/arch/sparc/system.cc index 952ac2deb..4e907f002 100644 --- a/src/arch/sparc/system.cc +++ b/src/arch/sparc/system.cc @@ -42,39 +42,46 @@ using namespace BigEndianGuest; SparcSystem::SparcSystem(Params *p) - : System(p), sysTick(0) + : System(p), sysTick(0),funcRomPort(p->name + "-fport") { resetSymtab = new SymbolTable; hypervisorSymtab = new SymbolTable; openbootSymtab = new SymbolTable; + Port *rom_port; + rom_port = params()->rom->getPort("functional"); + funcRomPort.setPeer(rom_port); + rom_port->setPeer(&funcRomPort); /** * Load the boot code, and hypervisor into memory. */ // Read the reset binary - reset = createObjectFile(params()->reset_bin); + reset = createObjectFile(params()->reset_bin, true); if (reset == NULL) fatal("Could not load reset binary %s", params()->reset_bin); // Read the openboot binary - openboot = createObjectFile(params()->openboot_bin); + openboot = createObjectFile(params()->openboot_bin, true); if (openboot == NULL) fatal("Could not load openboot bianry %s", params()->openboot_bin); // Read the hypervisor binary - hypervisor = createObjectFile(params()->hypervisor_bin); + hypervisor = createObjectFile(params()->hypervisor_bin, true); if (hypervisor == NULL) fatal("Could not load hypervisor binary %s", params()->hypervisor_bin); // Load reset binary into memory - reset->loadSections(&functionalPort, SparcISA::LoadAddrMask); + reset->setTextBase(params()->reset_addr); + reset->loadSections(&funcRomPort); // Load the openboot binary - openboot->loadSections(&functionalPort, SparcISA::LoadAddrMask); + openboot->setTextBase(params()->openboot_addr); + openboot->loadSections(&funcRomPort); // Load the hypervisor binary - hypervisor->loadSections(&functionalPort, SparcISA::LoadAddrMask); + hypervisor->setTextBase(params()->hypervisor_addr); + hypervisor->loadSections(&funcRomPort); // load symbols if (!reset->loadGlobalSymbols(resetSymtab)) @@ -141,8 +148,13 @@ SparcSystem::unserialize(Checkpoint *cp, const std::string §ion) BEGIN_DECLARE_SIM_OBJECT_PARAMS(SparcSystem) SimObjectParam<PhysicalMemory *> physmem; + SimObjectParam<PhysicalMemory *> rom; SimpleEnumParam<System::MemoryMode> mem_mode; + Param<Addr> reset_addr; + Param<Addr> hypervisor_addr; + Param<Addr> openboot_addr; + Param<std::string> kernel; Param<std::string> reset_bin; Param<std::string> hypervisor_bin; @@ -150,8 +162,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(SparcSystem) Param<Tick> boot_cpu_frequency; Param<std::string> boot_osflags; - Param<uint64_t> system_type; - Param<uint64_t> system_rev; Param<std::string> readfile; Param<unsigned int> init_param; @@ -160,8 +170,14 @@ END_DECLARE_SIM_OBJECT_PARAMS(SparcSystem) BEGIN_INIT_SIM_OBJECT_PARAMS(SparcSystem) INIT_PARAM(physmem, "phsyical memory"), + INIT_PARAM(rom, "ROM for boot code"), INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)", System::MemoryModeStrings), + + INIT_PARAM(reset_addr, "Address that reset should be loaded at"), + INIT_PARAM(hypervisor_addr, "Address that hypervisor should be loaded at"), + INIT_PARAM(openboot_addr, "Address that openboot should be loaded at"), + INIT_PARAM(kernel, "file that contains the kernel code"), INIT_PARAM(reset_bin, "file that contains the reset code"), INIT_PARAM(hypervisor_bin, "file that contains the hypervisor code"), @@ -169,8 +185,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(SparcSystem) INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"), INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot", "a"), - INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 34), - INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10), INIT_PARAM_DFLT(readfile, "file to read startup script from", ""), INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0) @@ -182,16 +196,18 @@ CREATE_SIM_OBJECT(SparcSystem) p->name = getInstanceName(); p->boot_cpu_frequency = boot_cpu_frequency; p->physmem = physmem; + p->rom = rom; p->mem_mode = mem_mode; p->kernel_path = kernel; + p->reset_addr = reset_addr; + p->hypervisor_addr = hypervisor_addr; + p->openboot_addr = openboot_addr; p->reset_bin = reset_bin; p->hypervisor_bin = hypervisor_bin; p->openboot_bin = openboot_bin; p->boot_osflags = boot_osflags; p->init_param = init_param; p->readfile = readfile; - p->system_type = system_type; - p->system_rev = system_rev; return new SparcSystem(p); } diff --git a/src/arch/sparc/system.hh b/src/arch/sparc/system.hh index 0b79eda38..9cf3bb568 100644 --- a/src/arch/sparc/system.hh +++ b/src/arch/sparc/system.hh @@ -45,12 +45,14 @@ class SparcSystem : public System public: struct Params : public System::Params { + PhysicalMemory *rom; + Addr reset_addr; + Addr hypervisor_addr; + Addr openboot_addr; std::string reset_bin; std::string hypervisor_bin; std::string openboot_bin; std::string boot_osflags; - uint64_t system_type; - uint64_t system_rev; }; SparcSystem(Params *p); @@ -87,6 +89,9 @@ class SparcSystem : public System /** System Tick for syncronized tick across all cpus. */ Tick sysTick; + /** functional port to ROM */ + FunctionalPort funcRomPort; + protected: const Params *params() const { return (const Params *)_params; } |