diff options
36 files changed, 1340 insertions, 598 deletions
diff --git a/SConscript b/SConscript index d49bee5e4..a2d5de279 100644 --- a/SConscript +++ b/SConscript @@ -62,6 +62,7 @@ base_sources = Split(''' base/range.cc base/random.cc base/sat_counter.cc + base/serializer.cc base/socket.cc base/statistics.cc base/str.cc diff --git a/arch/alpha/faults.cc b/arch/alpha/faults.cc index c8cb9124e..0083aa9f3 100644 --- a/arch/alpha/faults.cc +++ b/arch/alpha/faults.cc @@ -105,10 +105,6 @@ FaultName IntegerOverflowFault::_name = "intover"; FaultVect IntegerOverflowFault::_vect = 0x0501; FaultStat IntegerOverflowFault::_count; -FaultName UnimpFault::_name = "Unimplemented Simulator feature"; -FaultVect UnimpFault::_vect = 0x0001; -FaultStat UnimpFault::_count; - #if FULL_SYSTEM void AlphaFault::invoke(ExecContext * xc) @@ -174,12 +170,6 @@ void ItbFault::invoke(ExecContext * xc) AlphaFault::invoke(xc); } -void UnimpFault::invoke(ExecContext * xc) -{ - FaultBase::invoke(xc); - panic("Unimpfault: %s\n", panicStr.c_str()); -} - #endif } // namespace AlphaISA diff --git a/arch/alpha/faults.hh b/arch/alpha/faults.hh index 5024c124b..e8ccc6b79 100644 --- a/arch/alpha/faults.hh +++ b/arch/alpha/faults.hh @@ -347,26 +347,6 @@ class IntegerOverflowFault : public AlphaFault FaultStat & countStat() {return _count;} }; -class UnimpFault : public AlphaFault -{ - private: - std::string panicStr; - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - UnimpFault(std::string _str) - : panicStr(_str) - { } - - FaultName name() {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} -#if FULL_SYSTEM - void invoke(ExecContext * xc); -#endif -}; - } // AlphaISA namespace #endif // __FAULTS_HH__ diff --git a/arch/alpha/isa/decoder.isa b/arch/alpha/isa/decoder.isa index 3d38e91f9..1adcfb948 100644 --- a/arch/alpha/isa/decoder.isa +++ b/arch/alpha/isa/decoder.isa @@ -810,7 +810,7 @@ decode OPCODE default Unknown::unknown() { AlphaPseudo::addsymbol(xc->xcBase(), R16, R17); }}, IsNonSpeculative); 0x54: m5panic({{ - panic("M5 panic instruction called."); + panic("M5 panic instruction called at pc=%#x.", xc->readPC()); }}, IsNonSpeculative); } diff --git a/arch/mips/faults.cc b/arch/mips/faults.cc index a31856f07..1b31dfa69 100644 --- a/arch/mips/faults.cc +++ b/arch/mips/faults.cc @@ -98,10 +98,6 @@ FaultName IntegerOverflowFault::_name = "intover"; FaultVect IntegerOverflowFault::_vect = 0x0501; FaultStat IntegerOverflowFault::_count; -FaultName UnimpFault::_name = "Unimplemented Simulator feature"; -FaultVect UnimpFault::_vect = 0x0001; -FaultStat UnimpFault::_count; - #if FULL_SYSTEM void MipsFault::invoke(ExecContext * xc) @@ -129,12 +125,6 @@ void ArithmeticFault::invoke(ExecContext * xc) panic("Arithmetic traps are unimplemented!"); } -void UnimpFault::invoke(ExecContext * xc) -{ - FaultBase::invoke(xc); - panic("Unimpfault: %s\n", panicStr.c_str()); -} - #endif } // namespace MipsISA diff --git a/arch/mips/faults.hh b/arch/mips/faults.hh index b0d228090..0bdabe29e 100644 --- a/arch/mips/faults.hh +++ b/arch/mips/faults.hh @@ -264,26 +264,6 @@ class IntegerOverflowFault : public MipsFault FaultStat & countStat() {return _count;} }; -class UnimpFault : public MipsFault -{ - private: - std::string panicStr; - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - UnimpFault(std::string _str) - : panicStr(_str) - { } - - FaultName name() {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} -#if FULL_SYSTEM - void invoke(ExecContext * xc); -#endif -}; - } // MipsISA namespace #endif // __FAULTS_HH__ diff --git a/arch/mips/isa/base.isa b/arch/mips/isa/base.isa index 9ed9651d2..b2a31c018 100644 --- a/arch/mips/isa/base.isa +++ b/arch/mips/isa/base.isa @@ -8,8 +8,6 @@ //Outputs to decoder.hh output header {{ -#define R31 31 - using namespace MipsISA; diff --git a/arch/mips/isa/bitfields.isa b/arch/mips/isa/bitfields.isa index eb917595c..e1124a591 100644 --- a/arch/mips/isa/bitfields.isa +++ b/arch/mips/isa/bitfields.isa @@ -39,7 +39,6 @@ def bitfield FT <20:16>; def bitfield FS <15:11>; def bitfield FD <10:6>; -def bitfield CC <20:18>; def bitfield ND <17:17>; def bitfield TF <16:16>; def bitfield MOVCI <16:16>; @@ -48,6 +47,10 @@ def bitfield SRL <21:21>; def bitfield SRLV < 6: 6>; def bitfield SA <10: 6>; +// Floating Point Condition Codes +def bitfield CC <10:8>; +def bitfield BRANCH_CC <20:18>; + // CP0 Register Select def bitfield SEL < 2: 0>; diff --git a/arch/mips/isa/decoder.isa b/arch/mips/isa/decoder.isa index 53bbb94a4..1454aba39 100644 --- a/arch/mips/isa/decoder.isa +++ b/arch/mips/isa/decoder.isa @@ -1,4 +1,4 @@ -// -*- mode:c++ -*- + // -*- mode:c++ -*- //////////////////////////////////////////////////////////////////// // @@ -20,8 +20,8 @@ decode OPCODE_HI default Unknown::unknown() { 0x0: decode FUNCTION_LO { 0x1: decode MOVCI { format BasicOp { - 0: movf({{ if (xc->readMiscReg(FPCR) != CC) Rd = Rs}}); - 1: movt({{ if (xc->readMiscReg(FPCR) == CC) Rd = Rs}}); + 0: movf({{ if (getFPConditionCode(FCSR, CC) == 0) Rd = Rs}}); + 1: movt({{ if (getFPConditionCode(FCSR, CC) == 1) Rd = Rs}}); } } @@ -127,10 +127,10 @@ decode OPCODE_HI default Unknown::unknown() { 0x2: decode FUNCTION_LO { format BasicOp { - 0x0: mfhi({{ Rd = xc->readMiscReg(Hi); }}); - 0x1: mthi({{ xc->setMiscReg(Hi,Rs); }}); - 0x2: mflo({{ Rd = xc->readMiscReg(Lo); }}); - 0x3: mtlo({{ xc->setMiscReg(Lo,Rs); }}); + 0x0: mfhi({{ Rd = HI; }}); + 0x1: mthi({{ HI = Rs; }}); + 0x2: mflo({{ Rd = LO; }}); + 0x3: mtlo({{ LO = Rs; }}); } } @@ -138,24 +138,24 @@ decode OPCODE_HI default Unknown::unknown() { format IntOp { 0x0: mult({{ int64_t temp1 = Rs.sd * Rt.sd; - xc->setMiscReg(Hi,temp1<63:32>); - xc->setMiscReg(Lo,temp1<31:0>); + HI = temp1<63:32>; + LO = temp1<31:0>; }}); 0x1: multu({{ uint64_t temp1 = Rs.ud * Rt.ud; - xc->setMiscReg(Hi,temp1<63:32>); - xc->setMiscReg(Lo,temp1<31:0>); + HI = temp1<63:32>; + LO = temp1<31:0>; }}); 0x2: div({{ - xc->setMiscReg(Hi,Rs.sd % Rt.sd); - xc->setMiscReg(Lo,Rs.sd / Rt.sd); + HI = Rs.sd % Rt.sd; + LO = Rs.sd / Rt.sd; }}); 0x3: divu({{ - xc->setMiscReg(Hi,Rs.ud % Rt.ud); - xc->setMiscReg(Lo,Rs.ud / Rt.ud); + HI = Rs.ud % Rt.ud; + LO = Rs.ud / Rt.ud; }}); } } @@ -163,9 +163,9 @@ decode OPCODE_HI default Unknown::unknown() { 0x4: decode HINT { 0x0: decode FUNCTION_LO { format IntOp { - 0x0: add({{ Rd.sw = Rs.sw + Rt.sw;/*Trap on Overflow*/}}); + 0x0: add({{ Rd.sw = Rs.sw + Rt.sw; /*Trap on Overflow*/}}); 0x1: addu({{ Rd.sw = Rs.sw + Rt.sw;}}); - 0x2: sub({{ Rd.sw = Rs.sw - Rt.sw; /*Trap on Overflow*/}}); + 0x2: sub({{ Rd.sw = Rs.sw - Rt.sw; /*Trap on Overflow*/}}); 0x3: subu({{ Rd.sw = Rs.sw - Rt.sw;}}); 0x4: and({{ Rd = Rs & Rt;}}); 0x5: or({{ Rd = Rs | Rt;}}); @@ -204,7 +204,6 @@ decode OPCODE_HI default Unknown::unknown() { } format BranchLikely { - //MIPS obsolete instructions 0x2: bltzl({{ cond = (Rs.sw < 0); }}); 0x3: bgezl({{ cond = (Rs.sw >= 0); }}); } @@ -228,7 +227,6 @@ decode OPCODE_HI default Unknown::unknown() { } format BranchLikely { - //Will be removed in future MIPS releases 0x2: bltzall({{ cond = (Rs.sw < 0); }}, IsCall, IsReturn); 0x3: bgezall({{ cond = (Rs.sw >= 0); }}, IsCall, IsReturn); } @@ -301,6 +299,7 @@ decode OPCODE_HI default Unknown::unknown() { //sel field. In those instances, the sel field must be zero. //MT Code Needed Here + }}); 0xC: mttr({{ @@ -399,78 +398,71 @@ decode OPCODE_HI default Unknown::unknown() { 0x3: mfhc1({{ Rt.uw = Fs.ud<63:32>;}}); 0x4: mtc1 ({{ Fs.uw = Rt.uw; }}); 0x7: mthc1({{ - uint64_t fs_hi = Rt.ud << 32; + uint64_t fs_hi = Rt.uw; uint64_t fs_lo = Fs.ud & 0x0000FFFF; - Fs.ud = fs_hi & fs_lo; + Fs.ud = fs_hi << 32 | fs_lo; }}); } format System { 0x2: cfc1({{ - uint32_t fcsr_reg = xc->readMiscReg(FCSR); - switch (FS) { case 0: - Rt = xc->readMiscReg(FIR); + Rt = FIR; break; case 25: - Rt = 0 | (fcsr_reg & 0xFE000000) >> 24 | (fcsr_reg & 0x00800000) >> 23; + Rt = 0 | (FCSR & 0xFE000000) >> 24 | (FCSR & 0x00800000) >> 23; break; case 26: - Rt = 0 | (fcsr_reg & 0x0003F07C); + Rt = 0 | (FCSR & 0x0003F07C); break; case 28: - Rt = 0 | (fcsr_reg); + Rt = 0 | (FCSR & 0x00000F80) | (FCSR & 0x01000000) >> 21 | (FCSR & 0x00000003); break; case 31: - Rt = fcsr_reg; + Rt = FCSR; break; default: panic("FP Control Value (%d) Not Available. Ignoring Access to" - "Floating Control Status Register",fcsr_reg); + "Floating Control Status Register",FS); } }}); 0x6: ctc1({{ - uint32_t fcsr_reg = xc->readMiscReg(FCSR); - uint32_t temp; - switch (FS) { case 25: - temp = 0 | (Rt.uw<7:1> << 25) // move 31...25 - | (fcsr_reg & 0x01000000) // bit 24 - | (fcsr_reg & 0x004FFFFF);// bit 22...0 + FCSR = 0 | (Rt.uw<7:1> << 25) // move 31...25 + | (FCSR & 0x01000000) // bit 24 + | (FCSR & 0x004FFFFF);// bit 22...0 break; case 26: - temp = 0 | (fcsr_reg & 0xFFFC0000) // move 31...18 + FCSR = 0 | (FCSR & 0xFFFC0000) // move 31...18 | Rt.uw<17:12> << 12 // bit 17...12 - | (fcsr_reg & 0x00000F80) << 7// bit 11...7 + | (FCSR & 0x00000F80) << 7// bit 11...7 | Rt.uw<6:2> << 2 // bit 6...2 - | (fcsr_reg & 0x00000002); // bit 1...0 + | (FCSR & 0x00000002); // bit 1...0 break; case 28: - temp = 0 | (fcsr_reg & 0xFE000000) // move 31...25 + FCSR = 0 | (FCSR & 0xFE000000) // move 31...25 | Rt.uw<2:2> << 24 // bit 24 - | (fcsr_reg & 0x00FFF000) << 23// bit 23...12 + | (FCSR & 0x00FFF000) << 23// bit 23...12 | Rt.uw<11:7> << 7 // bit 24 - | (fcsr_reg & 0x000007E) + | (FCSR & 0x000007E) | Rt.uw<1:0>;// bit 22...0 break; case 31: - temp = Rt.uw; + FCSR = Rt.uw; break; default: panic("FP Control Value (%d) Not Available. Ignoring Access to" - "Floating Control Status Register",fcsr_reg); + "Floating Control Status Register", FS); } - - xc->setMiscReg(FCSR,temp); }}); } } @@ -478,15 +470,15 @@ decode OPCODE_HI default Unknown::unknown() { 0x1: decode ND { 0x0: decode TF { format Branch { - 0x0: bc1f({{ cond = (xc->readMiscReg(FPCR) == 0); }}); - 0x1: bc1t({{ cond = (xc->readMiscReg(FPCR) == 1); }}); + 0x0: bc1f({{ cond = (getFPConditionCode(FCSR,CC) == 0); }}); + 0x1: bc1t({{ cond = (getFPConditionCode(FCSR,CC) == 1); }}); } } 0x1: decode TF { format BranchLikely { - 0x0: bc1fl({{ cond = (xc->readMiscReg(FPCR) == 0); }}); - 0x1: bc1tl({{ cond = (xc->readMiscReg(FPCR) == 1); }}); + 0x0: bc1fl({{ cond = (getFPConditionCode(FCSR,CC) == 0); }}); + 0x1: bc1tl({{ cond = (getFPConditionCode(FCSR,CC) == 1); }}); } } } @@ -500,51 +492,51 @@ decode OPCODE_HI default Unknown::unknown() { 0x0: decode FUNCTION_HI { 0x0: decode FUNCTION_LO { format FloatOp { - 0x0: adds({{ Fd.sf = Fs.sf + Ft.sf;}}); - 0x1: subs({{ Fd.sf = Fs.sf - Ft.sf;}}); - 0x2: muls({{ Fd.sf = Fs.sf * Ft.sf;}}); - 0x3: divs({{ Fd.sf = Fs.sf / Ft.sf;}}); - 0x4: sqrts({{ Fd.sf = sqrt(Fs.sf);}}); - 0x5: abss({{ Fd.sf = fabs(Fs.sf);}}); - 0x6: movs({{ Fd.sf = Fs.sf;}}); - 0x7: negs({{ Fd.sf = -1 * Fs.sf;}}); + 0x0: add_s({{ Fd.sf = Fs.sf + Ft.sf;}}); + 0x1: sub_s({{ Fd.sf = Fs.sf - Ft.sf;}}); + 0x2: mul_s({{ Fd.sf = Fs.sf * Ft.sf;}}); + 0x3: div_s({{ Fd.sf = Fs.sf / Ft.sf;}}); + 0x4: sqrt_s({{ Fd.sf = sqrt(Fs.sf);}}); + 0x5: abs_s({{ Fd.sf = fabs(Fs.sf);}}); + 0x6: mov_s({{ Fd.sf = Fs.sf;}}); + 0x7: neg_s({{ Fd.sf = -1 * Fs.sf;}}); } } 0x1: decode FUNCTION_LO { format Float64Op { 0x0: round_l_s({{ - Fd = convert_and_round(Fs.uw, SINGLE_TO_LONG, RND_NEAREST); + Fd.ud = fpConvert(roundFP(Fs.sf,0), SINGLE_TO_LONG); }}); 0x1: trunc_l_s({{ - Fd = convert_and_round(Fs.uw, SINGLE_TO_LONG, RND_ZERO); + Fd.ud = fpConvert(truncFP(Fs.sf), SINGLE_TO_LONG); }}); 0x2: ceil_l_s({{ - Fd = convert_and_round(Fs.uw, SINGLE_TO_LONG, RND_UP); + Fd.ud = fpConvert(ceil(Fs.sf), SINGLE_TO_LONG); }}); 0x3: floor_l_s({{ - Fd = convert_and_round(Fs.uw, SINGLE_TO_LONG, RND_DOWN); + Fd.ud = fpConvert(floor(Fs.sf), SINGLE_TO_LONG); }}); } format FloatOp { 0x4: round_w_s({{ - Fd = convert_and_round(Fs.uw, SINGLE_TO_WORD, RND_NEAREST); + Fd.uw = fpConvert(roundFP(Fs.sf,0), SINGLE_TO_WORD); }}); 0x5: trunc_w_s({{ - Fd = convert_and_round(Fs.uw, SINGLE_TO_WORD, RND_ZERO); + Fd.uw = fpConvert(truncFP(Fs.sf), SINGLE_TO_WORD); }}); 0x6: ceil_w_s({{ - Fd = convert_and_round(Fs.uw, SINGLE_TO_WORD, RND_UP); + Fd.uw = fpConvert(ceil(Fs.sf), SINGLE_TO_WORD); }}); 0x7: floor_w_s({{ - Fd = convert_and_round(Fs.uw, SINGLE_TO_WORD, RND_DOWN); + Fd.uw = fpConvert(floor(Fs.sf), SINGLE_TO_WORD); }}); } } @@ -552,41 +544,34 @@ decode OPCODE_HI default Unknown::unknown() { 0x2: decode FUNCTION_LO { 0x1: decode MOVCF { format FloatOp { - 0x0: movfs({{if (xc->readMiscReg(FPCR) != CC) Fd = Fs; }}); - 0x1: movts({{if (xc->readMiscReg(FPCR) == CC) Fd = Fs;}}); + 0x0: movf_s({{if (getFPConditionCode(FCSR,CC) == 0) Fd = Fs;}}); + 0x1: movt_s({{if (getFPConditionCode(FCSR,CC) == 1) Fd = Fs;}}); } } - format BasicOp { - 0x2: movzs({{ if (Rt == 0) Fd = Fs; }}); - 0x3: movns({{ if (Rt != 0) Fd = Fs; }}); - } - - format Float64Op { - 0x5: recips({{ Fd = 1 / Fs; }}); - 0x6: rsqrts({{ Fd = 1 / sqrt((double)Fs.ud);}}); + format FloatOp { + 0x2: movz_s({{ if (Rt == 0) Fd = Fs; }}); + 0x3: movn_s({{ if (Rt != 0) Fd = Fs; }}); + 0x5: recip_s({{ Fd = 1 / Fs; }}); + 0x6: rsqrt_s({{ Fd = 1 / sqrt(Fs);}}); } } 0x4: decode FUNCTION_LO { - format FloatOp { + format FloatConvertOp { 0x1: cvt_d_s({{ - int rnd_mode = xc->readMiscReg(FCSR) & 0x03; - Fd.ud = convert_and_round(Fs.sf, SINGLE_TO_DOUBLE, rnd_mode); + Fd.ud = fpConvert(Fs.sf, SINGLE_TO_DOUBLE); }}); 0x4: cvt_w_s({{ - int rnd_mode = xc->readMiscReg(FCSR) & 0x03; - Fd.uw = convert_and_round(Fs.uw, SINGLE_TO_WORD, rnd_mode); + Fd.uw = fpConvert(Fs.sf, SINGLE_TO_WORD); }}); } - //only legal for 64 bit - format Float64Op { + format FloatConvertOp { 0x5: cvt_l_s({{ - int rnd_mode = xc->readMiscReg(FCSR) & 0x03; - Fd.ud = convert_and_round(Fs.uw, SINGLE_TO_LONG, rnd_mode); + Fd.ud = fpConvert(Fs.sf, SINGLE_TO_LONG); }}); 0x6: cvt_ps_st({{ @@ -594,57 +579,167 @@ decode OPCODE_HI default Unknown::unknown() { }}); } } + + 0x6: decode FUNCTION_LO { + format FloatCompareOp { + 0x0: c_f_s({{ cond = 0; }}); + + 0x1: c_un_s({{ + if (isnan(Fs.sf) || isnan(Ft.sf)) + cond = 1; + else + cond = 0; + }}); + + 0x2: c_eq_s({{ + if (isnan(Fs.sf) || isnan(Ft.sf)) + cond = 0; + else + cond = (Fs.sf == Ft.sf); + }}); + + 0x3: c_ueq_s({{ + if (isnan(Fs.sf) || isnan(Ft.sf)) + cond = 1; + else + cond = (Fs.sf == Ft.sf); + }}); + + 0x4: c_olt_s({{ + if (isnan(Fs.sf) || isnan(Ft.sf)) + cond = 0; + else + cond = (Fs.sf < Ft.sf); + }}); + + 0x5: c_ult_s({{ + if (isnan(Fs.sf) || isnan(Ft.sf)) + cond = 1; + else + cond = (Fs.sf < Ft.sf); + }}); + + 0x6: c_ole_s({{ + if (isnan(Fs.sf) || isnan(Ft.sf)) + cond = 0; + else + cond = (Fs.sf <= Ft.sf); + }}); + + 0x7: c_ule_s({{ + if (isnan(Fs.sf) || isnan(Ft.sf)) + cond = 1; + else + cond = (Fs.sf <= Ft.sf); + }}); + } + } + + 0x7: decode FUNCTION_LO { + format FloatCompareWithXcptOp { + 0x0: c_sf_s({{ cond = 0; }}); + + 0x1: c_ngle_s({{ + if (isnan(Fs.sf) || isnan(Ft.sf)) + cond = 1; + else + cond = 0; + }}); + + 0x2: c_seq_s({{ + if (isnan(Fs.sf) || isnan(Ft.sf)) + cond = 0; + else + cond = (Fs.sf == Ft.sf); + }}); + + 0x3: c_ngl_s({{ + if (isnan(Fs.sf) || isnan(Ft.sf)) + cond = 1; + else + cond = (Fs.sf == Ft.sf); + }}); + + 0x4: c_lt_s({{ + if (isnan(Fs.sf) || isnan(Ft.sf)) + cond = 0; + else + cond = (Fs.sf < Ft.sf); + }}); + + 0x5: c_nge_s({{ + if (isnan(Fs.sf) || isnan(Ft.sf)) + cond = 1; + else + cond = (Fs.sf < Ft.sf); + }}); + + 0x6: c_le_s({{ + if (isnan(Fs.sf) || isnan(Ft.sf)) + cond = 0; + else + cond = (Fs.sf <= Ft.sf); + }}); + + 0x7: c_ngt_s({{ + if (isnan(Fs.sf) || isnan(Ft.sf)) + cond = 1; + else + cond = (Fs.sf <= Ft.sf); + }}); + } + } } //Table A-15 MIPS32 COP1 Encoding of Function Field When rs=D 0x1: decode FUNCTION_HI { 0x0: decode FUNCTION_LO { format FloatOp { - 0x0: addd({{ Fd.df = Fs.df + Ft.df;}}); - 0x1: subd({{ Fd.df = Fs.df - Ft.df;}}); - 0x2: muld({{ Fd.df = Fs.df * Ft.df;}}); - 0x3: divd({{ Fd.df = Fs.df / Ft.df;}}); - 0x4: sqrtd({{ Fd.df = sqrt(Fs.df);}}); - 0x5: absd({{ Fd.df = fabs(Fs.df);}}); - 0x6: movd({{ Fd.ud = Fs.ud;}}); - 0x7: negd({{ Fd.df = -1 * Fs.df;}}); + 0x0: add_d({{ Fd.df = Fs.df + Ft.df;}}); + 0x1: sub_d({{ Fd.df = Fs.df - Ft.df;}}); + 0x2: mul_d({{ Fd.df = Fs.df * Ft.df;}}); + 0x3: div_d({{ Fd.df = Fs.df / Ft.df;}}); + 0x4: sqrt_d({{ Fd.df = sqrt(Fs.df);}}); + 0x5: abs_d({{ Fd.df = fabs(Fs.df);}}); + 0x6: mov_d({{ Fd.ud = Fs.ud;}}); + 0x7: neg_d({{ Fd.df = -1 * Fs.df;}}); } } 0x1: decode FUNCTION_LO { - format Float64Op { + format FloatOp { 0x0: round_l_d({{ - Fd.ud = convert_and_round(Fs.ud, DOUBLE_TO_LONG, RND_NEAREST); + Fd.ud = fpConvert(roundFP(Fs.df,0), DOUBLE_TO_LONG); }}); 0x1: trunc_l_d({{ - Fd.ud = convert_and_round(Fs.ud, DOUBLE_TO_LONG, RND_ZERO); + Fd.ud = fpConvert(truncFP(Fs.df), DOUBLE_TO_LONG); }}); 0x2: ceil_l_d({{ - Fd.ud = convert_and_round(Fs.ud, DOUBLE_TO_LONG, RND_UP); + Fd.ud = fpConvert(ceil(Fs.df), DOUBLE_TO_LONG); }}); 0x3: floor_l_d({{ - Fd.ud = convert_and_round(Fs.ud, DOUBLE_TO_LONG, RND_DOWN); + Fd.ud = fpConvert(floor(Fs.df), DOUBLE_TO_LONG); }}); } format FloatOp { 0x4: round_w_d({{ - Fd.uw = convert_and_round(Fs.ud, DOUBLE_TO_WORD, RND_NEAREST); + Fd.uw = fpConvert(roundFP(Fs.df,0), DOUBLE_TO_WORD); }}); 0x5: trunc_w_d({{ - Fd.uw = convert_and_round(Fs.ud, DOUBLE_TO_WORD, RND_ZERO); + Fd.uw = fpConvert(truncFP(Fs.df), DOUBLE_TO_WORD); }}); 0x6: ceil_w_d({{ - Fd.uw = convert_and_round(Fs.ud, DOUBLE_TO_WORD, RND_UP); + Fd.uw = fpConvert(ceil(Fs.df), DOUBLE_TO_WORD); }}); 0x7: floor_w_d({{ - Fd.uw = convert_and_round(Fs.ud, DOUBLE_TO_WORD, RND_DOWN); + Fd.uw = fpConvert(floor(Fs.df), DOUBLE_TO_WORD); }}); } } @@ -652,56 +747,164 @@ decode OPCODE_HI default Unknown::unknown() { 0x2: decode FUNCTION_LO { 0x1: decode MOVCF { format FloatOp { - 0x0: movfd({{if (xc->readMiscReg(FPCR) != CC) Fd.df = Fs.df; }}); - 0x1: movtd({{if (xc->readMiscReg(FPCR) == CC) Fd.df = Fs.df; }}); + 0x0: movf_d({{if (getFPConditionCode(FCSR,CC) == 0) Fd.df = Fs.df; }}); + 0x1: movt_d({{if (getFPConditionCode(FCSR,CC) == 1) Fd.df = Fs.df; }}); } } format BasicOp { - 0x2: movzd({{ if (Rt == 0) Fd.df = Fs.df; }}); - 0x3: movnd({{ if (Rt != 0) Fd.df = Fs.df; }}); + 0x2: movz_d({{ if (Rt == 0) Fd.df = Fs.df; }}); + 0x3: movn_d({{ if (Rt != 0) Fd.df = Fs.df; }}); } - format Float64Op { - 0x5: recipd({{ Fd.df = 1 / Fs.df}}); - 0x6: rsqrtd({{ Fd.df = 1 / sqrt(Fs.df) }}); + format FloatOp { + 0x5: recip_d({{ Fd.df = 1 / Fs.df}}); + 0x6: rsqrt_d({{ Fd.df = 1 / sqrt(Fs.df) }}); } } 0x4: decode FUNCTION_LO { format FloatOp { 0x0: cvt_s_d({{ - int rnd_mode = xc->readMiscReg(FCSR) & 0x03; - Fd.uw = convert_and_round(Fs.ud, DOUBLE_TO_SINGLE, rnd_mode); + Fd.uw = fpConvert(Fs.df, DOUBLE_TO_SINGLE); }}); 0x4: cvt_w_d({{ - int rnd_mode = xc->readMiscReg(FCSR) & 0x03; - Fd.uw = convert_and_round(Fs.ud, DOUBLE_TO_WORD, rnd_mode); + Fd.uw = fpConvert(Fs.df, DOUBLE_TO_WORD); }}); - } - //only legal for 64 bit - format Float64Op { 0x5: cvt_l_d({{ - int rnd_mode = xc->readMiscReg(FCSR) & 0x03; - Fd.ud = convert_and_round(Fs.ud, DOUBLE_TO_LONG, rnd_mode); + Fd.ud = fpConvert(Fs.df, DOUBLE_TO_LONG); + }}); + } + } + + 0x6: decode FUNCTION_LO { + format FloatCompareOp { + 0x0: c_f_d({{ cond = 0; }}); + + 0x1: c_un_d({{ + if (isnan(Fs.df) || isnan(Ft.df)) + cond = 1; + else + cond = 0; }}); + + 0x2: c_eq_d({{ + if (isnan(Fs.df) || isnan(Ft.df)) + cond = 0; + else + cond = (Fs.df == Ft.df); + }}); + + 0x3: c_ueq_d({{ + if (isnan(Fs.df) || isnan(Ft.df)) + cond = 1; + else + cond = (Fs.df == Ft.df); + }}); + + 0x4: c_olt_d({{ + if (isnan(Fs.df) || isnan(Ft.df)) + cond = 0; + else + cond = (Fs.df < Ft.df); + }}); + + 0x5: c_ult_d({{ + if (isnan(Fs.df) || isnan(Ft.df)) + cond = 1; + else + cond = (Fs.df < Ft.df); + }}); + + 0x6: c_ole_d({{ + if (isnan(Fs.df) || isnan(Ft.df)) + cond = 0; + else + cond = (Fs.df <= Ft.df); + }}); + + 0x7: c_ule_d({{ + if (isnan(Fs.df) || isnan(Ft.df)) + cond = 1; + else + cond = (Fs.df <= Ft.df); + }}); + } + } + + 0x7: decode FUNCTION_LO { + format FloatCompareWithXcptOp { + 0x0: c_sf_d({{ cond = 0; }}); + + 0x1: c_ngle_d({{ + if (isnan(Fs.df) || isnan(Ft.df)) + cond = 1; + else + cond = 0; + }}); + + 0x2: c_seq_d({{ + if (isnan(Fs.df) || isnan(Ft.df)) + cond = 0; + else + cond = (Fs.df == Ft.df); + }}); + + 0x3: c_ngl_d({{ + if (isnan(Fs.df) || isnan(Ft.df)) + cond = 1; + else + cond = (Fs.df == Ft.df); + }}); + + 0x4: c_lt_d({{ + if (isnan(Fs.df) || isnan(Ft.df)) + cond = 0; + else + cond = (Fs.df < Ft.df); + }}); + + 0x5: c_nge_d({{ + if (isnan(Fs.df) || isnan(Ft.df)) + cond = 1; + else + cond = (Fs.df < Ft.df); + }}); + + 0x6: c_le_d({{ + if (isnan(Fs.df) || isnan(Ft.df)) + cond = 0; + else + cond = (Fs.df <= Ft.df); + }}); + + 0x7: c_ngt_d({{ + if (isnan(Fs.df) || isnan(Ft.df)) + cond = 1; + else + cond = (Fs.df <= Ft.df); + }}); } } } //Table A-16 MIPS32 COP1 Encoding of Function Field When rs=W 0x4: decode FUNCTION { - format FloatOp { + format FloatConvertOp { 0x20: cvt_s_w({{ - int rnd_mode = xc->readMiscReg(FCSR) & 0x03; - Fd.uw = convert_and_round(Fs.uw, WORD_TO_SINGLE, rnd_mode); + Fd.uw = fpConvert(Fs.sf, WORD_TO_SINGLE); }}); 0x21: cvt_d_w({{ - int rnd_mode = xc->readMiscReg(FCSR) & 0x03; - Fd.ud = convert_and_round(Fs.uw, WORD_TO_DOUBLE, rnd_mode); + Fd.ud = fpConvert(Fs.sf, WORD_TO_DOUBLE); + }}); + } + + format Float64ConvertOp { + 0x26: cvt_ps_pw({{ + Fd.ud = fpConvert(Fs.ud, WORD_TO_PS); }}); } } @@ -710,15 +913,17 @@ decode OPCODE_HI default Unknown::unknown() { //Note: "1. Format type L is legal only if 64-bit floating point operations //are enabled." 0x5: decode FUNCTION_HI { - format Float64Op { - 0x10: cvt_s_l({{ - int rnd_mode = xc->readMiscReg(FCSR) & 0x03; - Fd.uw = convert_and_round(Fs.ud, LONG_TO_SINGLE, rnd_mode); + format Float64ConvertOp { + 0x20: cvt_s_l({{ + Fd.uw = fpConvert(Fs.ud, LONG_TO_SINGLE); }}); - 0x11: cvt_d_l({{ - int rnd_mode = xc->readMiscReg(FCSR) & 0x03; - Fd.ud = convert_and_round(Fs.ud, LONG_TO_DOUBLE, rnd_mode); + 0x21: cvt_d_l({{ + Fd.ud = fpConvert(Fs.ud, LONG_TO_DOUBLE); + }}); + + 0x26: cvt_ps_l({{ + Fd.ud = fpConvert(Fs.ud, LONG_TO_PS); }}); } } @@ -729,34 +934,34 @@ decode OPCODE_HI default Unknown::unknown() { 0x6: decode FUNCTION_HI { 0x0: decode FUNCTION_LO { format Float64Op { - 0x0: addps({{ //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = Fs.df + Ft.df; + 0x0: add_ps({{ + Fd1.sf = Fs1.sf + Ft2.sf; + Fd2.sf = Fs2.sf + Ft2.sf; }}); - 0x1: subps({{ //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = Fs.df - Ft.df; + 0x1: sub_ps({{ + Fd1.sf = Fs1.sf - Ft2.sf; + Fd2.sf = Fs2.sf - Ft2.sf; }}); - 0x2: mulps({{ //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = Fs.df * Ft.df; + 0x2: mul_ps({{ + Fd1.sf = Fs1.sf * Ft2.sf; + Fd2.sf = Fs2.sf * Ft2.sf; }}); - 0x5: absps({{ //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = fabs(Fs.df); + 0x5: abs_ps({{ + Fd1.sf = fabs(Fs1.sf); + Fd2.sf = fabs(Fs2.sf); }}); - 0x6: movps({{ //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - //Fd.df = Fs<31:0> | Ft<31:0>; + 0x6: mov_ps({{ + Fd1.sf = Fs1.sf; + Fd2.sf = Fs2.sf; }}); - 0x7: negps({{ //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = -1 * Fs.df; + 0x7: neg_ps({{ + Fd1.sf = -1 * Fs1.sf; + Fd2.sf = -1 * Fs2.sf; }}); } } @@ -764,37 +969,237 @@ decode OPCODE_HI default Unknown::unknown() { 0x2: decode FUNCTION_LO { 0x1: decode MOVCF { format Float64Op { - 0x0: movfps({{if (xc->readMiscReg(FPCR) != CC) Fd = Fs;}}); - 0x1: movtps({{if (xc->readMiscReg(FPCR) == CC) Fd = Fs;}}); + 0x0: movf_ps({{ + if (getFPConditionCode(FCSR, CC) == 0) + Fd1 = Fs1; + if (getFPConditionCode(FCSR, CC+1) == 0) + Fd2 = Fs2; + }}); + + 0x1: movt_ps({{ + if (getFPConditionCode(FCSR, CC) == 1) + Fd1 = Fs1; + if (getFPConditionCode(FCSR, CC+1) == 1) + Fd2 = Fs2; + }}); } } - format BasicOp { - 0x2: movzps({{if (xc->readMiscReg(FPCR) != CC) Fd = Fs; }}); - 0x3: movnps({{if (xc->readMiscReg(FPCR) == CC) Fd = Fs; }}); + format Float64Op { + 0x2: movz_ps({{ + if (getFPConditionCode(FCSR, CC) == 0) + Fd1 = Fs1; + if (getFPConditionCode(FCSR, CC) == 0) + Fd2 = Fs2; + }}); + + 0x3: movn_ps({{ + if (getFPConditionCode(FCSR, CC) == 1) + Fd1 = Fs1; + if (getFPConditionCode(FCSR, CC) == 1) + Fd2 = Fs2; + }}); } } 0x4: decode FUNCTION_LO { 0x0: Float64Op::cvt_s_pu({{ - int rnd_mode = xc->readMiscReg(FCSR) & 0x03; - Fd.uw = convert_and_round(Fs.ud, PUPPER_TO_SINGLE, rnd_mode); + Fd.uw = fpConvert(Fs2.uw, PU_TO_SINGLE); }}); } 0x5: decode FUNCTION_LO { format Float64Op { 0x0: cvt_s_pl({{ - int rnd_mode = xc->readMiscReg(FCSR) & 0x03; - Fd.uw = convert_and_round(Fs.ud, PLOWER_TO_SINGLE, - rnd_mode); + Fd.uw = fpConvert(Fs1.uw, PL_TO_SINGLE); + }}); + + 0x4: pll({{ Fd.ud = (uint64_t) Fs1.uw << 32 | Ft1.uw; }}); + 0x5: plu({{ Fd.ud = (uint64_t) Fs1.uw << 32 | Ft2.uw; }}); + 0x6: pul({{ Fd.ud = (uint64_t) Fs2.uw << 32 | Ft1.uw; }}); + 0x7: puu({{ Fd.ud = (uint64_t) Fs2.uw << 32 | Ft2.uw; }}); + } + } + + 0x6: decode FUNCTION_LO { + format FloatPSCompareOp { + 0x0: c_f_ps({{ cond1 = 0; cond2 = 0; }}); + + 0x1: c_un_ps({{ + if (isnan(Fs1.sf) || isnan(Ft1.sf)) + cond1 = 1; + else + cond1 = 0; + + if (isnan(Fs2.sf) || isnan(Ft2.sf)) + cond2 = 1; + else + cond2 = 0; + + }}); + + 0x2: c_eq_ps({{ + if (isnan(Fs1.sf) || isnan(Ft1.sf)) + cond1 = 0; + else + cond1 = (Fs1.sf == Ft1.sf); + + if (isnan(Fs2.sf) || isnan(Ft2.sf)) + cond2 = 0; + else + cond2 = (Fs2.sf == Ft2.sf); + }}); + + 0x3: c_ueq_ps({{ + if (isnan(Fs1.sf) || isnan(Ft1.sf)) + cond1 = 1; + else + cond1 = (Fs1.sf == Ft1.sf); + + if (isnan(Fs2.sf) || isnan(Ft2.sf)) + cond2 = 1; + else + cond2 = (Fs2.sf == Ft2.sf); + }}); + + 0x4: c_olt_ps({{ + if (isnan(Fs1.sf) || isnan(Ft1.sf)) + cond1 = 0; + else + cond1 = (Fs1.sf < Ft1.sf); + + if (isnan(Fs2.sf) || isnan(Ft2.sf)) + cond2 = 0; + else + cond2 = (Fs2.sf < Ft2.sf); }}); - 0x4: pll({{ Fd.ud = Fs.ud<31:0> << 32 | Ft.ud<31:0>; }}); - 0x5: plu({{ Fd.ud = Fs.ud<31:0> << 32 | Ft.ud<63:32>;}}); - 0x6: pul({{ Fd.ud = Fs.ud<63:32> << 32 | Ft.ud<31:0>; }}); - 0x7: puu({{ Fd.ud = Fs.ud<63:32> << 32 | Ft.ud<63:32>;}}); + 0x5: c_ult_ps({{ + if (isnan(Fs1.sf) || isnan(Ft1.sf)) + cond1 = 1; + else + cond1 = (Fs.sf < Ft.sf); + + if (isnan(Fs2.sf) || isnan(Ft2.sf)) + cond2 = 1; + else + cond2 = (Fs2.sf < Ft2.sf); + }}); + + 0x6: c_ole_ps({{ + if (isnan(Fs.sf) || isnan(Ft.sf)) + cond1 = 0; + else + cond1 = (Fs.sf <= Ft.sf); + + if (isnan(Fs2.sf) || isnan(Ft2.sf)) + cond2 = 0; + else + cond2 = (Fs2.sf <= Ft2.sf); + }}); + + 0x7: c_ule_ps({{ + if (isnan(Fs1.sf) || isnan(Ft1.sf)) + cond1 = 1; + else + cond1 = (Fs1.sf <= Ft1.sf); + + if (isnan(Fs2.sf) || isnan(Ft2.sf)) + cond2 = 1; + else + cond2 = (Fs2.sf <= Ft2.sf); + }}); + } + } + + 0x7: decode FUNCTION_LO { + format FloatPSCompareWithXcptOp { + 0x0: c_sf_ps({{ cond1 = 0; cond2 = 0; }}); + + 0x1: c_ngle_ps({{ + if (isnan(Fs1.sf) || isnan(Ft1.sf)) + cond1 = 1; + else + cond1 = 0; + + if (isnan(Fs2.sf) || isnan(Ft2.sf)) + cond2 = 1; + else + cond2 = 0; + }}); + + 0x2: c_seq_ps({{ + if (isnan(Fs1.sf) || isnan(Ft1.sf)) + cond1 = 0; + else + cond1 = (Fs1.sf == Ft1.sf); + + if (isnan(Fs2.sf) || isnan(Ft2.sf)) + cond2 = 0; + else + cond2 = (Fs2.sf == Ft2.sf); + }}); + + 0x3: c_ngl_ps({{ + if (isnan(Fs1.sf) || isnan(Ft1.sf)) + cond1 = 1; + else + cond1 = (Fs1.sf == Ft1.sf); + + if (isnan(Fs2.sf) || isnan(Ft2.sf)) + cond2 = 1; + else + cond2 = (Fs2.sf == Ft2.sf); + }}); + + 0x4: c_lt_ps({{ + if (isnan(Fs1.sf) || isnan(Ft1.sf)) + cond1 = 0; + else + cond1 = (Fs1.sf < Ft1.sf); + + if (isnan(Fs2.sf) || isnan(Ft2.sf)) + cond2 = 0; + else + cond2 = (Fs2.sf < Ft2.sf); + }}); + + 0x5: c_nge_ps({{ + if (isnan(Fs1.sf) || isnan(Ft1.sf)) + cond1 = 1; + else + cond1 = (Fs1.sf < Ft1.sf); + + if (isnan(Fs2.sf) || isnan(Ft2.sf)) + cond2 = 1; + else + cond2 = (Fs2.sf < Ft2.sf); + }}); + + 0x6: c_le_ps({{ + if (isnan(Fs1.sf) || isnan(Ft1.sf)) + cond1 = 0; + else + cond1 = (Fs1.sf <= Ft1.sf); + + if (isnan(Fs2.sf) || isnan(Ft2.sf)) + cond2 = 0; + else + cond2 = (Fs2.sf <= Ft2.sf); + }}); + + 0x7: c_ngt_ps({{ + if (isnan(Fs1.sf) || isnan(Ft1.sf)) + cond1 = 1; + else + cond1 = (Fs1.sf <= Ft1.sf); + + if (isnan(Fs2.sf) || isnan(Ft2.sf)) + cond2 = 1; + else + cond2 = (Fs2.sf <= Ft2.sf); + }}); } } } @@ -840,23 +1245,17 @@ decode OPCODE_HI default Unknown::unknown() { 0x3: decode FUNCTION_HI { 0x0: decode FUNCTION_LO { format LoadFloatMemory { - 0x0: lwxc1({{ /*F_t<31:0> = Mem.sf; */}}, {{ EA = Rs + Rt; }}); - 0x1: ldxc1({{ /*F_t<63:0> = Mem.df;*/ }}, {{ EA = Rs + Rt; }}); - 0x5: luxc1({{ /*F_t<31:0> = Mem.df; */}}, - {{ //Need to make EA<2:0> = 0 - EA = Rs + Rt; - }}); + 0x0: lwxc1({{ Ft.uw = Mem.uw;}}, {{ EA = Rs + Rt; }}); + 0x1: ldxc1({{ Ft.ud = Mem.ud;}}, {{ EA = Rs + Rt; }}); + 0x5: luxc1({{ Ft.uw = Mem.ud;}}, {{ EA = Rs + Rt; }}); } } 0x1: decode FUNCTION_LO { format StoreFloatMemory { - 0x0: swxc1({{ /*Mem.sf = Ft<31:0>; */}},{{ EA = Rs + Rt; }}); - 0x1: sdxc1({{ /*Mem.df = Ft<63:0> */}}, {{ EA = Rs + Rt; }}); - 0x5: suxc1({{ /*Mem.df = F_t<63:0>;*/}}, - {{ //Need to make sure EA<2:0> = 0 - EA = Rs + Rt; - }}); + 0x0: swxc1({{ Mem.uw = Ft.uw;}}, {{ EA = Rs + Rt; }}); + 0x1: sdxc1({{ Mem.ud = Ft.ud;}}, {{ EA = Rs + Rt; }}); + 0x5: suxc1({{ Mem.ud = Ft.ud;}}, {{ EA = Rs + Rt; }}); } 0x7: WarnUnimpl::prefx(); @@ -867,49 +1266,44 @@ decode OPCODE_HI default Unknown::unknown() { format BasicOp { 0x4: decode FUNCTION_LO { - 0x0: madd_s({{ Fd.sf = (Fs.sf * Fs.sf) + Fr.sf; }}); - 0x1: madd_d({{ Fd.df = (Fs.df * Fs.df) + Fr.df; }}); + 0x0: madd_s({{ Fd.sf = (Fs.sf * Ft.sf) + Fr.sf; }}); + 0x1: madd_d({{ Fd.df = (Fs.df * Ft.df) + Fr.df; }}); 0x6: madd_ps({{ - //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = (Fs.df * Fs.df) + Fr.df; + Fd1.sf = (Fs1.df * Ft1.df) + Fr1.df; + Fd2.sf = (Fs2.df * Ft2.df) + Fr2.df; }}); } 0x5: decode FUNCTION_LO { - 0x0: msub_s({{ Fd.sf = (Fs.sf * Fs.sf) - Fr.sf; }}); - 0x1: msub_d({{ Fd.df = (Fs.df * Fs.df) - Fr.df; }}); + 0x0: msub_s({{ Fd.sf = (Fs.sf * Ft.sf) - Fr.sf; }}); + 0x1: msub_d({{ Fd.df = (Fs.df * Ft.df) - Fr.df; }}); 0x6: msub_ps({{ - //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = (Fs.df * Fs.df) - Fr.df; + Fd1.sf = (Fs1.df * Ft1.df) - Fr1.df; + Fd2.sf = (Fs2.df * Ft2.df) - Fr2.df; }}); } 0x6: decode FUNCTION_LO { - 0x0: nmadd_s({{ Fd.sf = (-1 * Fs.sf * Fs.sf) - Fr.sf; }}); - 0x1: nmadd_d({{ Fd.df = (-1 * Fs.df * Fs.df) + Fr.df; }}); + 0x0: nmadd_s({{ Fd.sf = (-1 * Fs.sf * Ft.sf) - Fr.sf; }}); + 0x1: nmadd_d({{ Fd.df = (-1 * Fs.df * Ft.df) + Fr.df; }}); 0x6: nmadd_ps({{ - //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = (-1 * Fs.df * Fs.df) + Fr.df; + Fd1.sf = -1 * ((Fs1.df * Ft1.df) + Fr1.df); + Fd2.sf = -1 * ((Fs2.df * Ft2.df) + Fr2.df); }}); } 0x7: decode FUNCTION_LO { - 0x0: nmsub_s({{ Fd.sf = (-1 * Fs.sf * Fs.sf) - Fr.sf; }}); - 0x1: nmsub_d({{ Fd.df = (-1 * Fs.df * Fs.df) - Fr.df; }}); + 0x0: nmsub_s({{ Fd.sf = (-1 * Fs.sf * Ft.sf) - Fr.sf; }}); + 0x1: nmsub_d({{ Fd.df = (-1 * Fs.df * Ft.df) - Fr.df; }}); 0x6: nmsub_ps({{ - //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = (-1 * Fs.df * Fs.df) + Fr.df; + Fd1.sf = -1 * ((Fs1.df * Ft1.df) - Fr1.df); + Fd2.sf = -1 * ((Fs2.df * Ft2.df) - Fr2.df); }}); } } } } - //MIPS obsolete instructions format BranchLikely { 0x4: beql({{ cond = (Rs.sw == 0); }}); 0x5: bnel({{ cond = (Rs.sw != 0); }}); @@ -926,59 +1320,63 @@ decode OPCODE_HI default Unknown::unknown() { 0x0: decode FUNCTION_LO { format IntOp { 0x0: madd({{ - int64_t temp1 = xc->readMiscReg(Hi) << 32 | xc->readMiscReg(Lo) >> 32; + int64_t temp1 = (int64_t) HI << 32 | LO; temp1 = temp1 + (Rs.sw * Rt.sw); - xc->setMiscReg(Hi,temp1<63:32>); - xc->setMiscReg(Lo,temp1<31:0>); - }}); + HI = temp1<63:32>; + LO = temp1<31:0>; + }}); 0x1: maddu({{ - int64_t temp1 = xc->readMiscReg(Hi) << 32 | xc->readMiscReg(Lo) >> 32; + int64_t temp1 = (int64_t) HI << 32 | LO; temp1 = temp1 + (Rs.uw * Rt.uw); - xc->setMiscReg(Hi,temp1<63:32>); - xc->setMiscReg(Lo,temp1<31:0>); - }}); + HI = temp1<63:32>; + LO = temp1<31:0>; + }}); 0x2: mul({{ Rd.sw = Rs.sw * Rt.sw; }}); 0x4: msub({{ - int64_t temp1 = xc->readMiscReg(Hi) << 32 | xc->readMiscReg(Lo) >> 32; + int64_t temp1 = (int64_t) HI << 32 | LO; temp1 = temp1 - (Rs.sw * Rt.sw); - xc->setMiscReg(Hi,temp1<63:32>); - xc->setMiscReg(Lo,temp1<31:0>); - }}); + HI = temp1<63:32>; + LO = temp1<31:0>; + }}); 0x5: msubu({{ - int64_t temp1 = xc->readMiscReg(Hi) << 32 | xc->readMiscReg(Lo) >> 32; + int64_t temp1 = (int64_t) HI << 32 | LO; temp1 = temp1 - (Rs.uw * Rt.uw); - xc->setMiscReg(Hi,temp1<63:32>); - xc->setMiscReg(Lo,temp1<31:0>); - }}); + HI = temp1<63:32>; + LO = temp1<31:0>; + }}); } } 0x4: decode FUNCTION_LO { format BasicOp { 0x0: clz({{ - /*int cnt = 0; - int idx = 0; - while ( Rs.uw<idx> != 1) { - cnt++; - idx--; + int cnt = 0; + uint32_t mask = 0x80000000; + for (int i=0; i < 32; i++) { + if( (Rs & mask) == 0) { + cnt++; + } else { + break; + } } - - Rd.uw = cnt;*/ + Rd.uw = cnt; }}); 0x1: clo({{ - /*int cnt = 0; - int idx = 0; - while ( Rs.uw<idx> != 0) { - cnt++; - idx--; + int cnt = 0; + uint32_t mask = 0x80000000; + for (int i=0; i < 32; i++) { + if( (Rs & mask) != 0) { + cnt++; + } else { + break; + } } - - Rd.uw = cnt;*/ + Rd.uw = cnt; }}); } } @@ -1012,8 +1410,8 @@ decode OPCODE_HI default Unknown::unknown() { 0x02: FailUnimpl::wsbh(); format BasicOp { - 0x10: seb({{ Rd.sw = Rt<7:0>}}); - 0x18: seh({{ Rd.sw = Rt<15:0>}}); + 0x10: seb({{ Rd.sw = Rt.sw<7:0>}}); + 0x18: seh({{ Rd.sw = Rt.sw<15:0>}}); } } @@ -1033,8 +1431,6 @@ decode OPCODE_HI default Unknown::unknown() { uint32_t unalign_addr = Rs + disp; uint32_t offset = unalign_addr & 0x00000003; #if BYTE_ORDER == BIG_ENDIAN - std::cout << "Big Endian Byte Order\n"; - switch(offset) { case 0: @@ -1060,8 +1456,6 @@ decode OPCODE_HI default Unknown::unknown() { panic("lwl: bad offset"); } #elif BYTE_ORDER == LITTLE_ENDIAN - std::cout << "Little Endian Byte Order\n"; - switch(offset) { case 0: @@ -1119,8 +1513,6 @@ decode OPCODE_HI default Unknown::unknown() { }}, {{ EA = (Rs + disp) & ~3; }}); } - - 0x7: FailUnimpl::reserved(); } 0x5: decode OPCODE_LO default FailUnimpl::reserved() { @@ -1274,7 +1666,7 @@ decode OPCODE_HI default Unknown::unknown() { } 0x6: decode OPCODE_LO default FailUnimpl::reserved() { - 0x0: FailUnimpl::ll(); + 0x0: LoadMemory::ll({{Rt.uw = Mem.uw}},mem_flags=LOCKED); format LoadFloatMemory { 0x1: lwc1({{ Ft.uw = Mem.uw; }}); @@ -1284,7 +1676,7 @@ decode OPCODE_HI default Unknown::unknown() { 0x7: decode OPCODE_LO default FailUnimpl::reserved() { - 0x0: FailUnimpl::sc(); + 0x0: StoreMemory::sc({{ Mem.uw = Rt.uw; Rt.uw = 1; }}); format StoreFloatMemory { 0x1: swc1({{ Mem.uw = Ft.uw; }}); diff --git a/arch/mips/isa/formats/branch.isa b/arch/mips/isa/formats/branch.isa index 39db88c23..8cfa37a20 100644 --- a/arch/mips/isa/formats/branch.isa +++ b/arch/mips/isa/formats/branch.isa @@ -261,7 +261,7 @@ def format Branch(code,*flags) {{ #Add Link Code if Link instruction strlen = len(name) if name[strlen-2:] == 'al': - code += 'r31 = NNPC;\n' + code += 'R31 = NNPC;\n' #Condition code code = 'bool cond;\n' + code @@ -285,7 +285,7 @@ def format BranchLikely(code,*flags) {{ #Add Link Code if Link instruction strlen = len(name) if name[strlen-3:] == 'all': - code += 'r31 = NNPC;\n' + code += 'R31 = NNPC;\n' #Condition code code = 'bool cond;\n' + code @@ -307,7 +307,7 @@ def format Jump(code,*flags) {{ #Add Link Code if Link instruction strlen = len(name) if strlen > 1 and name[1:] == 'al': - code = 'r31 = NNPC;\n' + code + code = 'R31 = NNPC;\n' + code iop = InstObjParams(name, Name, 'Jump', CodeBlock(code),\ diff --git a/arch/mips/isa/formats/fp.isa b/arch/mips/isa/formats/fp.isa index 65b259e20..9f2c24755 100644 --- a/arch/mips/isa/formats/fp.isa +++ b/arch/mips/isa/formats/fp.isa @@ -39,6 +39,34 @@ def format FloatOp(code, *flags) {{ exec_output = BasicExecute.subst(iop) }}; +def format FloatCompareOp(code, *flags) {{ + code = 'bool cond;\n' + code + code += 'FCSR = makeCCVector(FCSR, CC,cond);\n' + iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + +def format FloatCompareWithXcptOp(code, *flags) {{ + code = 'bool cond;\n' + code + code += 'FCSR = makeCCVector(FCSR, CC,cond);\n' + iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + +def format FloatConvertOp(code, *flags) {{ + iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + // Primary format for float64 operate instructions: def format Float64Op(code, *flags) {{ iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags) @@ -47,3 +75,35 @@ def format Float64Op(code, *flags) {{ decode_block = BasicDecode.subst(iop) exec_output = BasicExecute.subst(iop) }}; + +def format Float64ConvertOp(code, *flags) {{ + code = 'bool cond;\n' + code + code += 'FCSR = makeCCVector(FCSR, CC,cond);\n' + iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + +def format FloatPSCompareOp(code, *flags) {{ + code = 'bool cond1;\nbool cond2;\n' + code + code += 'FCSR = makeCCVector(FCSR, CC+1, cond1);\n' + code += 'FCSR = makeCCVector(FCSR, CC, cond2);\n' + iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + +def format FloatPSCompareWithXcptOp(code, *flags) {{ + code = 'bool cond1;\nbool cond2;\n' + code + code += 'FCSR = makeCCVector(FCSR, CC+1, cond1);\n' + code += 'FCSR = makeCCVector(FCSR, CC, cond2);\n' + iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; diff --git a/arch/mips/isa/operands.isa b/arch/mips/isa/operands.isa index 2fa3238dc..0f9c74b48 100644 --- a/arch/mips/isa/operands.isa +++ b/arch/mips/isa/operands.isa @@ -13,22 +13,49 @@ def operand_types {{ }}; def operands {{ + #General Purpose Integer Reg Operands 'Rd': ('IntReg', 'uw', 'RD', 'IsInteger', 1), 'Rs': ('IntReg', 'uw', 'RS', 'IsInteger', 2), 'Rt': ('IntReg', 'uw', 'RT', 'IsInteger', 3), - 'r31': ('IntReg', 'uw','R31','IsInteger', 4), - 'R0': ('IntReg', 'uw','R0', 'IsInteger', 5), + + #Operands used for Link or Syscall Insts + 'R31': ('IntReg', 'uw','31','IsInteger', 4), 'R2': ('IntReg', 'uw','2', 'IsInteger', 5), + #Special Integer Reg operands + 'HI': ('IntReg', 'uw','32', 'IsInteger', 6), + 'LO': ('IntReg', 'uw','33', 'IsInteger', 7), + + #Immediate Value operand 'IntImm': ('IntReg', 'uw', 'INTIMM', 'IsInteger', 3), + #Floating Point Reg Operands 'Fd': ('FloatReg', 'sf', 'FD', 'IsFloating', 1), 'Fs': ('FloatReg', 'sf', 'FS', 'IsFloating', 2), 'Ft': ('FloatReg', 'sf', 'FT', 'IsFloating', 3), 'Fr': ('FloatReg', 'sf', 'FR', 'IsFloating', 3), + #Special Floating Point Control Reg Operands + 'FIR': ('FloatReg', 'uw', '32', 'IsFloating', 1), + 'FCCR': ('FloatReg', 'uw', '33', 'IsFloating', 2), + 'FEXR': ('FloatReg', 'uw', '34', 'IsFloating', 3), + 'FENR': ('FloatReg', 'uw', '35', 'IsFloating', 3), + 'FCSR': ('FloatReg', 'uw', '36', 'IsFloating', 3), + + #Operands For Paired Singles FP Operations + 'Fd1': ('FloatReg', 'sf', 'FD', 'IsFloating', 4), + 'Fd2': ('FloatReg', 'sf', 'FD+1', 'IsFloating', 4), + 'Fs1': ('FloatReg', 'sf', 'FS', 'IsFloating', 5), + 'Fs2': ('FloatReg', 'sf', 'FS+1', 'IsFloating', 5), + 'Ft1': ('FloatReg', 'sf', 'FT', 'IsFloating', 6), + 'Ft2': ('FloatReg', 'sf', 'FT+1', 'IsFloating', 6), + 'Fr1': ('FloatReg', 'sf', 'FR', 'IsFloating', 7), + 'Fr2': ('FloatReg', 'sf', 'FR+1', 'IsFloating', 7), + + #Memory Operand 'Mem': ('Mem', 'uw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4), + #Program Counter Operands 'NPC': ('NPC', 'uw', None, ( None, None, 'IsControl' ), 4), 'NNPC':('NNPC', 'uw', None, ( None, None, 'IsControl' ), 4) }}; diff --git a/arch/mips/isa_traits.cc b/arch/mips/isa_traits.cc index fcc3007ca..216a6e2ec 100644 --- a/arch/mips/isa_traits.cc +++ b/arch/mips/isa_traits.cc @@ -61,81 +61,75 @@ MipsISA::MiscRegFile::copyMiscRegs(ExecContext *xc) } uint64_t -MipsISA::convert_and_round(uint32_t fp_val, ConvertType cvt_type, int rnd_mode) +MipsISA::fpConvert(double fp_val, ConvertType cvt_type) { - uint64_t ret_val = 0; - switch (cvt_type) { case SINGLE_TO_DOUBLE: - uint64_t single_sign = fp_val & 0x80000000; - - uint64_t single_exp = (fp_val & 0x7F800000) >> 22; - single_exp -= 127; - - uint64_t single_mantissa = fp_val & 0x007FFFFF; - - uint64_t double_exp = single_exp + 1023; - double_exp = double_exp << 51; - - uint64_t double_val = single_sign << 63 | double_exp | single_mantissa; - - return double_val; + double sdouble_val = fp_val; + void *sdouble_ptr = &sdouble_val; + uint64_t sdp_bits = *(uint64_t *) sdouble_ptr; + return sdp_bits; + + case SINGLE_TO_WORD: + int32_t sword_val = (int32_t) fp_val; + void *sword_ptr = &sword_val; + uint64_t sword_bits= *(uint32_t *) sword_ptr; + return sword_bits; + + case WORD_TO_SINGLE: + float wfloat_val = fp_val; + void *wfloat_ptr = &wfloat_val; + uint64_t wfloat_bits = *(uint32_t *) wfloat_ptr; + return wfloat_bits; + + case WORD_TO_DOUBLE: + double wdouble_val = fp_val; + void *wdouble_ptr = &wdouble_val; + uint64_t wdp_bits = *(uint64_t *) wdouble_ptr; + return wdp_bits; default: - panic("Invalid Floating Point Conversion Type (%d) being used.\n",cvt_type); - return ret_val; + panic("Invalid Floating Point Conversion Type (%d). See \"types.hh\" for List of Conversions\n",cvt_type); + return 0; } } -uint64_t -MipsISA::convert_and_round(uint64_t fp_val, ConvertType cvt_type, int rnd_mode) +double +MipsISA::roundFP(double val, int digits) { + double digit_offset = pow(10.0,digits); + val = val * digit_offset; + val = val + 0.5; + val = floor(val); + val = val / digit_offset; + return val; +} - uint64_t ret_val = 0; - - switch (cvt_type) - { - case SINGLE_TO_DOUBLE: - uint64_t single_sign = fp_val & 0x80000000; - - uint64_t single_exp = (fp_val & 0x7F800000) >> 22; - single_exp -= 127; - - uint64_t single_mantissa = fp_val & 0x007FFFFF; - - uint64_t double_exp = single_exp + 1023; - double_exp = double_exp << 51; - - uint64_t double_val = single_sign << 63 | double_exp | single_mantissa; - - return double_val; - - default: - panic("Invalid Floating Point Conversion Type (%d) being used.\n",cvt_type); - return ret_val; - } +double +MipsISA::truncFP(double val) +{ + int trunc_val = (int) val; + return (double) trunc_val; } +bool +MipsISA::getFPConditionCode(uint32_t fcsr_reg, int cc) +{ + //uint32_t cc_bits = xc->readFloatReg(35); + return false;//regFile.floatRegfile.getConditionCode(cc); +} -uint64_t -MipsISA::convert_and_round(double fp_val, ConvertType cvt_type, int rnd_mode) +uint32_t +MipsISA::makeCCVector(uint32_t fcsr, int num, bool val) { - switch (cvt_type) - { - case SINGLE_TO_DOUBLE: - double double_val = fp_val; - void *double_ptr = &double_val; - uint64_t dp_bits = *(uint64_t *) double_ptr ; - return dp_bits; + int shift = (num == 0) ? 22 : num + 23; - default: - panic("Invalid Floating Point Conversion Type (%d) being used.\n",cvt_type); - return 0; - } -} + fcsr = fcsr | (val << shift); + return fcsr; +} #if FULL_SYSTEM diff --git a/arch/mips/isa_traits.hh b/arch/mips/isa_traits.hh index 33c490dcc..148c405df 100644 --- a/arch/mips/isa_traits.hh +++ b/arch/mips/isa_traits.hh @@ -31,7 +31,7 @@ #include "arch/mips/constants.hh" #include "arch/mips/types.hh" -#include "arch/mips/regfile.hh" +#include "arch/mips/regfile/regfile.hh" #include "arch/mips/faults.hh" #include "arch/mips/utility.hh" #include "base/misc.hh" @@ -137,9 +137,11 @@ namespace MipsISA void copyRegs(ExecContext *src, ExecContext *dest); - uint64_t convert_and_round(uint32_t fp_val, ConvertType cvt_type, int rnd_mode = 0); - uint64_t convert_and_round(uint64_t fp_val, ConvertType cvt_type, int rnd_mode = 0); - uint64_t convert_and_round(double fp_val, ConvertType cvt_type, int rnd_mode = 0); + uint64_t fpConvert(double fp_val, ConvertType cvt_type); + double roundFP(double val, int digits); + double truncFP(double val); + bool getFPConditionCode(uint32_t fcsr_reg, int cc); + uint32_t makeCCVector(uint32_t fcsr, int num, bool val); // Machine operations diff --git a/arch/mips/regfile/float_regfile.hh b/arch/mips/regfile/float_regfile.hh new file mode 100644 index 000000000..15c6f97f4 --- /dev/null +++ b/arch/mips/regfile/float_regfile.hh @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __ARCH_MIPS_FLOAT_REGFILE_HH__ +#define __ARCH_MIPS_FLOAT_REGFILE_HH__ + +#include "arch/mips/types.hh" +#include "arch/mips/constants.hh" +#include "base/misc.hh" +#include "config/full_system.hh" +#include "sim/byteswap.hh" +#include "sim/faults.hh" +#include "sim/host.hh" + +class Checkpoint; +class ExecContext; +class Regfile; + +namespace MipsISA +{ + class FloatRegFile + { + protected: + FloatReg32 regs[NumFloatRegs]; + + public: + + void clear() + { + bzero(regs, sizeof(regs)); + } + + double readReg(int floatReg, int width) + { + switch(width) + { + case SingleWidth: + void *float_ptr = ®s[floatReg]; + return *(float *) float_ptr; + + case DoubleWidth: + uint64_t double_val = (FloatReg64)regs[floatReg + 1] << 32 | regs[floatReg]; + void *double_ptr = &double_val; + return *(double *) double_ptr; + + default: + panic("Attempted to read a %d bit floating point register!", width); + } + } + + FloatRegBits readRegBits(int floatReg, int width) + { + if (floatReg < NumFloatArchRegs - 1) { + switch(width) + { + case SingleWidth: + return regs[floatReg]; + + case DoubleWidth: + return (FloatReg64)regs[floatReg + 1] << 32 | regs[floatReg]; + + default: + panic("Attempted to read a %d bit floating point register!", width); + } + } else { + if (width > SingleWidth) + assert("Control Regs are only 32 bits wide"); + + return regs[floatReg]; + } + } + + Fault setReg(int floatReg, const FloatReg &val, int width) + { + + switch(width) + { + case SingleWidth: + float temp = val; + void *float_ptr = &temp; + regs[floatReg] = *(FloatReg32 *) float_ptr; + break; + + case DoubleWidth: + const void *double_ptr = &val; + FloatReg64 temp_double = *(FloatReg64 *) double_ptr; + regs[floatReg + 1] = temp_double >> 32; + regs[floatReg] = temp_double; + break; + + default: + panic("Attempted to read a %d bit floating point register!", width); + } + + return NoFault; + } + + Fault setRegBits(int floatReg, const FloatRegBits &val, int width) + { + using namespace std; + + switch(width) + { + case SingleWidth: + regs[floatReg] = val; + break; + + case DoubleWidth: + regs[floatReg + 1] = val >> 32; + regs[floatReg] = val; + break; + + default: + panic("Attempted to read a %d bit floating point register!", width); + } + return NoFault; + } + + void serialize(std::ostream &os); + + void unserialize(Checkpoint *cp, const std::string §ion); + }; + + enum MiscFloatRegNums { + FIR = NumFloatArchRegs, + FCCR, + FEXR, + FENR, + FCSR + }; + +} // namespace MipsISA + +#endif diff --git a/arch/mips/int_regfile.hh b/arch/mips/regfile/int_regfile.hh index cff9eb0d2..3cd87734d 100644 --- a/arch/mips/int_regfile.hh +++ b/arch/mips/regfile/int_regfile.hh @@ -31,6 +31,7 @@ #include "arch/mips/types.hh" #include "arch/mips/constants.hh" +#include "base/misc.hh" #include "sim/faults.hh" class Checkpoint; @@ -43,8 +44,6 @@ namespace MipsISA { protected: IntReg regs[NumIntRegs]; - IntReg hi; - IntReg lo; public: IntReg readReg(int intReg) @@ -58,33 +57,17 @@ namespace MipsISA return NoFault; } - IntReg readHi() - { - return hi; - } - - Fault setHi(const IntReg &val) - { - hi = val; - return NoFault; - } - - IntReg readLo() - { - return lo; - } - - Fault setLo(const IntReg &val) - { - lo = val; - return NoFault; - } - void serialize(std::ostream &os); void unserialize(Checkpoint *cp, const std::string §ion); }; + + enum MiscIntRegNums { + HI = NumIntArchRegs, + LO + }; + } // namespace MipsISA #endif diff --git a/arch/mips/misc_regfile.hh b/arch/mips/regfile/misc_regfile.hh index 9f054e5f7..9f054e5f7 100644 --- a/arch/mips/misc_regfile.hh +++ b/arch/mips/regfile/misc_regfile.hh diff --git a/arch/mips/regfile.hh b/arch/mips/regfile/regfile.hh index 3dcf8ef18..e77571b33 100644 --- a/arch/mips/regfile.hh +++ b/arch/mips/regfile/regfile.hh @@ -31,9 +31,9 @@ #include "arch/mips/types.hh" #include "arch/mips/constants.hh" -#include "arch/mips/int_regfile.hh" -#include "arch/mips/float_regfile.hh" -#include "arch/mips/misc_regfile.hh" +#include "arch/mips/regfile/int_regfile.hh" +#include "arch/mips/regfile/float_regfile.hh" +#include "arch/mips/regfile/misc_regfile.hh" #include "sim/faults.hh" class Checkpoint; @@ -58,31 +58,7 @@ namespace MipsISA MiscReg readMiscReg(int miscReg) { - if (miscReg < CtrlReg_DepTag) - return miscRegFile.readReg(miscReg); - else { - switch (miscReg) - { - case Hi: - return intRegFile.readHi(); - - case Lo: - return intRegFile.readLo(); - - case FIR: - return floatRegFile.readFIR(); - - case FCSR: - return floatRegFile.readFCSR(); - - case FPCR: - return floatRegFile.readFPCR(); - - default: - panic("Invalid Misc. Reg. Access\n"); - return 0; - } - } + return miscRegFile.readReg(miscReg); } MiscReg readMiscRegWithEffect(int miscReg, @@ -94,31 +70,7 @@ namespace MipsISA Fault setMiscReg(int miscReg, const MiscReg &val) { - if (miscReg < CtrlReg_DepTag) - return miscRegFile.setReg(miscReg, val); - else { - switch (miscReg) - { - case Hi: - return intRegFile.setHi(val); - - case Lo: - return intRegFile.setLo(val); - - case FIR: - return floatRegFile.setFIR(val); - - case FCSR: - return floatRegFile.setFCSR(val); - - case FPCR: - return floatRegFile.setFPCR(val); - - default: - panic("Invalid Misc. Reg. Access\n"); - return 0; - } - } + return miscRegFile.setReg(miscReg, val); } Fault setMiscRegWithEffect(int miscReg, const MiscReg &val, diff --git a/arch/mips/types.hh b/arch/mips/types.hh index 021ecad1c..4d5fb3456 100644 --- a/arch/mips/types.hh +++ b/arch/mips/types.hh @@ -68,13 +68,15 @@ namespace MipsISA LONG_TO_SINGLE, LONG_TO_DOUBLE, LONG_TO_WORD, + LONG_TO_PS, WORD_TO_SINGLE, WORD_TO_DOUBLE, WORD_TO_LONG, + WORD_TO_PS, - PLOWER_TO_SINGLE, - PUPPER_TO_SINGLE + PL_TO_SINGLE, + PU_TO_SINGLE }; //used in FP convert & round function diff --git a/arch/sparc/faults.cc b/arch/sparc/faults.cc index e83bba800..67a89ab0e 100644 --- a/arch/sparc/faults.cc +++ b/arch/sparc/faults.cc @@ -215,11 +215,6 @@ TrapType TrapInstruction::_baseTrapType = 0x100; FaultPriority TrapInstruction::_priority = 16; FaultStat TrapInstruction::_count; -FaultName UnimpFault::_name = "Unimplemented Simulator feature"; -TrapType UnimpFault::_trapType = 0x000; -FaultPriority UnimpFault::_priority = 0; -FaultStat UnimpFault::_count; - #if FULL_SYSTEM void SparcFault::invoke(ExecContext * xc) @@ -245,12 +240,15 @@ void SparcFault::invoke(ExecContext * xc) xc->regs.npc = xc->regs.pc + sizeof(MachInst);*/ } -void UnimpFault::invoke(ExecContext * xc) +#endif + +#if !FULL_SYSTEM + +void TrapInstruction::invoke(ExecContext * xc) { - panic("Unimpfault: %s\n", panicStr.c_str()); + xc->syscall(syscall_num); } - #endif } // namespace SparcISA diff --git a/arch/sparc/faults.hh b/arch/sparc/faults.hh index 87de8daaa..e8fb8dfc5 100644 --- a/arch/sparc/faults.hh +++ b/arch/sparc/faults.hh @@ -573,37 +573,19 @@ class TrapInstruction : public EnumeratedFault static TrapType _baseTrapType; static FaultPriority _priority; static FaultStat _count; + uint64_t syscall_num; TrapType baseTrapType() {return _baseTrapType;} public: - TrapInstruction(uint32_t n) : EnumeratedFault(n) {;} + TrapInstruction(uint32_t n, uint64_t syscall) : + EnumeratedFault(n), syscall_num(syscall) {;} FaultName name() {return _name;} FaultPriority priority() {return _priority;} FaultStat & countStat() {return _count;} -}; - -class UnimpFault : public SparcFault -{ - private: - static FaultName _name; - static TrapType _trapType; - static FaultPriority _priority; - static FaultStat _count; - std::string panicStr; - public: - UnimpFault(std::string _str) - : panicStr(_str) - { } - - FaultName name() {return _name;} - TrapType trapType() {return _trapType;} - FaultPriority priority() {return _priority;} - FaultStat & countStat() {return _count;} -#if FULL_SYSTEM +#if !FULL_SYSTEM void invoke(ExecContext * xc); #endif }; - } // SparcISA namespace #endif // __FAULTS_HH__ diff --git a/arch/sparc/isa/base.isa b/arch/sparc/isa/base.isa index cb370a3e7..8ea11b40e 100644 --- a/arch/sparc/isa/base.isa +++ b/arch/sparc/isa/base.isa @@ -99,14 +99,16 @@ def template ROrImmDecode {{ let {{ def splitOutImm(code): - matcher = re.compile(r'Rs(?P<rNum>\d)_or_imm(?P<iNum>\d+)') + matcher = re.compile(r'Rs(?P<rNum>\d)_or_imm(?P<iNum>\d+)(?P<typeQual>\.\w+)?') rOrImmMatch = matcher.search(code) if (rOrImmMatch == None): return (False, code, '', '', '') rString = rOrImmMatch.group("rNum") + if (rOrImmMatch.group("typeQual") != None): + rString += rOrImmMatch.group("typeQual") iString = rOrImmMatch.group("iNum") orig_code = code - code = matcher.sub('Rs' + rOrImmMatch.group("rNum"), orig_code) + code = matcher.sub('Rs' + rString, orig_code) imm_code = matcher.sub('imm', orig_code) return (True, code, imm_code, rString, iString) }}; diff --git a/arch/sparc/isa/decoder.isa b/arch/sparc/isa/decoder.isa index b9e83afd6..52ca5d7cd 100644 --- a/arch/sparc/isa/decoder.isa +++ b/arch/sparc/isa/decoder.isa @@ -119,11 +119,11 @@ decode OP default Unknown::unknown() } }}); 0x0F: sdiv({{ - if(Rs2_or_imm13 == 0) + if(Rs2_or_imm13.sdw == 0) fault = new DivisionByZero; else { - Rd.udw = ((YValue << 32) | Rs1.sdw<31:0>) / Rs2_or_imm13; + Rd.udw = ((int64_t)((YValue << 32) | Rs1.sdw<31:0>)) / Rs2_or_imm13.sdw; if(Rd.udw<63:31> != 0) Rd.udw = 0x7FFFFFFF; else if(Rd.udw<63:> && Rd.udw<62:31> != 0xFFFFFFFF) @@ -166,13 +166,13 @@ decode OP default Unknown::unknown() {{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}} ); 0x1A: umulcc({{ - uint64_t resTemp, val2 = Rs2_or_imm13; - Rd = resTemp = Rs1.udw<31:0> * val2<31:0>; + uint64_t resTemp; + Rd = resTemp = Rs1.udw<31:0> * Rs2_or_imm13.udw<31:0>; YValue = resTemp<63:32>;}}, {{0}},{{0}},{{0}},{{0}}); 0x1B: smulcc({{ - int64_t resTemp, val2 = Rs2_or_imm13; - Rd = resTemp = Rs1.sdw<31:0> * val2<31:0>; + int64_t resTemp; + Rd = resTemp = Rs1.sdw<31:0> * Rs2_or_imm13.sdw<31:0>; YValue = resTemp<63:32>;}}, {{0}},{{0}},{{0}},{{0}}); 0x1C: subccc({{ @@ -185,11 +185,11 @@ decode OP default Unknown::unknown() {{Rs1<63:> != val2<63:> && Rs1<63:> != resTemp<63:>}} ); 0x1D: udivxcc({{ - if(Rs2_or_imm13 == 0) fault = new DivisionByZero; - else Rd = Rs1.udw / Rs2_or_imm13;}} + if(Rs2_or_imm13.udw == 0) fault = new DivisionByZero; + else Rd = Rs1.udw / Rs2_or_imm13.udw;}} ,{{0}},{{0}},{{0}},{{0}}); 0x1E: udivcc({{ - uint32_t resTemp, val2 = Rs2_or_imm13; + uint32_t resTemp, val2 = Rs2_or_imm13.udw; int32_t overflow; if(val2 == 0) fault = new DivisionByZero; else @@ -205,7 +205,7 @@ decode OP default Unknown::unknown() {{0}} ); 0x1F: sdivcc({{ - int32_t resTemp, val2 = Rs2_or_imm13; + int32_t resTemp, val2 = Rs2_or_imm13.sdw; int32_t overflow, underflow; if(val2 == 0) fault = new DivisionByZero; else @@ -363,8 +363,8 @@ decode OP default Unknown::unknown() } } 0x2D: sdivx({{ - if(Rs2_or_imm13 == 0) fault = new DivisionByZero; - else Rd.sdw = Rs1.sdw / Rs2_or_imm13; + if(Rs2_or_imm13.sdw == 0) fault = new DivisionByZero; + else Rd.sdw = Rs1.sdw / Rs2_or_imm13.sdw; }}); 0x2E: decode RS1 { 0x0: IntOp::popc({{ @@ -382,12 +382,12 @@ decode OP default Unknown::unknown() } 0x2F: decode RCOND3 { - 0x1: movreq({{Rd = (Rs1 == 0) ? Rs2_or_imm10 : Rd;}}); - 0x2: movrle({{Rd = (Rs1 <= 0) ? Rs2_or_imm10 : Rd;}}); - 0x3: movrl({{Rd = (Rs1 < 0) ? Rs2_or_imm10 : Rd;}}); - 0x5: movrne({{Rd = (Rs1 != 0) ? Rs2_or_imm10 : Rd;}}); - 0x6: movrg({{Rd = (Rs1 > 0) ? Rs2_or_imm10 : Rd;}}); - 0x7: movrge({{Rd = (Rs1 >= 0) ? Rs2_or_imm10 : Rd;}}); + 0x1: movreq({{Rd = (Rs1.sdw == 0) ? Rs2_or_imm10 : Rd;}}); + 0x2: movrle({{Rd = (Rs1.sdw <= 0) ? Rs2_or_imm10 : Rd;}}); + 0x3: movrl({{Rd = (Rs1.sdw < 0) ? Rs2_or_imm10 : Rd;}}); + 0x5: movrne({{Rd = (Rs1.sdw != 0) ? Rs2_or_imm10 : Rd;}}); + 0x6: movrg({{Rd = (Rs1.sdw > 0) ? Rs2_or_imm10 : Rd;}}); + 0x7: movrge({{Rd = (Rs1.sdw >= 0) ? Rs2_or_imm10 : Rd;}}); } 0x30: decode RD { 0x0: wry({{Y = Rs1 ^ Rs2_or_imm13;}}); @@ -492,10 +492,6 @@ decode OP default Unknown::unknown() xc->syscall(R1); #endif } - else - { - DPRINTF(Sparc, "Didn't fire on %s\n", CondTestAbbrev[machInst<25:28>]); - } }}); 0x2: Trap::tccx({{ if(passesCondition(CcrXcc, COND2)) diff --git a/base/loader/elf_object.cc b/base/loader/elf_object.cc index 3f6131088..165501e1c 100644 --- a/base/loader/elf_object.cc +++ b/base/loader/elf_object.cc @@ -82,8 +82,7 @@ ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data) //what it must be. if (ehdr.e_machine == EM_SPARC64 || ehdr.e_machine == EM_SPARC || - ehdr.e_machine == EM_SPARCV9 || - ehdr.e_machine == EM_SPARC32PLUS) { + ehdr.e_machine == EM_SPARCV9) { arch = ObjectFile::SPARC; } else if (ehdr.e_machine == EM_MIPS && ehdr.e_ident[EI_CLASS] == ELFCLASS32) { diff --git a/dev/ide_disk.hh b/dev/ide_disk.hh index 3d67abece..891c462b5 100644 --- a/dev/ide_disk.hh +++ b/dev/ide_disk.hh @@ -33,6 +33,7 @@ #ifndef __IDE_DISK_HH__ #define __IDE_DISK_HH__ +#include "base/statistics.hh" #include "dev/disk_image.hh" #include "dev/ide_atareg.h" #include "dev/ide_ctrl.hh" @@ -231,6 +232,13 @@ class IdeDisk : public SimObject /** Interrupt pending */ bool intrPending; + Stats::Scalar<> dmaReadFullPages; + Stats::Scalar<> dmaReadBytes; + Stats::Scalar<> dmaReadTxs; + Stats::Scalar<> dmaWriteFullPages; + Stats::Scalar<> dmaWriteBytes; + Stats::Scalar<> dmaWriteTxs; + public: /** * Create and initialize this Disk. @@ -252,6 +260,12 @@ class IdeDisk : public SimObject void reset(int id); /** + * Register statistics. + */ + void regStats(); + + + /** * Set the controller for this device * @param c The IDE controller */ diff --git a/dev/sinic.cc b/dev/sinic.cc index b5b6c6cf5..66ca88dbe 100644 --- a/dev/sinic.cc +++ b/dev/sinic.cc @@ -81,7 +81,8 @@ Base::Base(Params *p) } Device::Device(Params *p) - : Base(p), rxFifo(p->rx_fifo_size), txFifo(p->tx_fifo_size), + : Base(p), plat(p->plat), physmem(p->physmem), rxUnique(0), txUnique(0), + virtualRegs(p->virtual_count < 1 ? 1 : p->virtual_count), rxKickTick(0), txKickTick(0), txEvent(this), rxDmaEvent(this), txDmaEvent(this), dmaReadDelay(p->dma_read_delay), dmaReadFactor(p->dma_read_factor), @@ -268,12 +269,9 @@ void Device::prepareIO(int cpu, int index) { int size = virtualRegs.size(); - if (index < size) - return; - - virtualRegs.resize(index + 1); - for (int i = size; i <= index; ++i) - virtualRegs[i].rxPacket = rxFifo.end(); + if (index > size) + panic("Trying to access a vnic that doesn't exist %d > %d\n", + index, size); } void @@ -286,7 +284,10 @@ Device::prepareRead(int cpu, int index) // update rx registers uint64_t rxdone = vnic.RxDone; - rxdone = set_RxDone_Packets(rxdone, rxFifo.packets()); + rxdone = set_RxDone_Packets(rxdone, rxFifo.countPacketsAfter(rxFifoPtr)); + rxdone = set_RxDone_Empty(rxdone, rxFifo.empty()); + rxdone = set_RxDone_High(rxdone, rxFifo.size() > regs.RxFifoMark); + rxdone = set_RxDone_NotHigh(rxdone, rxLow); regs.RxData = vnic.RxData; regs.RxDone = rxdone; regs.RxWait = rxdone; @@ -325,17 +326,18 @@ Device::read(Packet &pkt) pkt.allocate(); if (!regValid(raddr)) - panic("invalid register: cpu=%d, da=%#x pa=%#x size=%d", - cpu, daddr, pkt.addr, pkt.size); + panic("invalid register: cpu=%d vnic=%d da=%#x pa=%#x size=%d", + cpu, index, daddr, pkt.addr, pkt.size); const Regs::Info &info = regInfo(raddr); if (!info.read) - panic("reading %s (write only): cpu=%d da=%#x pa=%#x size=%d", - info.name, cpu, daddr, pkt.addr, pkt.size); + panic("read %s (write only): " + "cpu=%d vnic=%d da=%#x pa=%#x size=%d", + info.name, cpu, index, daddr, pkt.addr, pkt.size); - if (pkt.size != info.size) - panic("invalid size for reg %s: cpu=%d da=%#x pa=%#x size=%d", - info.name, cpu, daddr, pkt.addr, pkt.size); + panic("read %s (invalid size): " + "cpu=%d vnic=%d da=%#x pa=%#x size=%d", + info.name, cpu, index, daddr, pkt.addr, pkt.size); prepareRead(cpu, index); @@ -353,8 +355,8 @@ Device::read(Packet &pkt) } DPRINTF(EthernetPIO, - "read %s cpu=%d da=%#x pa=%#x size=%d val=%#x\n", - info.name, cpu, daddr, pkt.addr, pkt.size, value); + "read %s: cpu=%d vnic=%d da=%#x pa=%#x size=%d val=%#x\n", + info.name, cpu, index, daddr, pkt.addr, pkt.size, value); // reading the interrupt status register has the side effect of // clearing it @@ -416,18 +418,20 @@ Device::write(Packet &pkt) const Regs::Info &info = regInfo(raddr); if (!info.write) - panic("write %s (read only): cpu=%d da=%#x pa=%#x size=%d", - info.name, cpu, daddr, pkt.addr, pkt.size); + panic("write %s (read only): " + "cpu=%d vnic=%d da=%#x pa=%#x size=%d", + info.name, cpu, index, daddr, pkt.addr, pkt.size); if (pkt.size != info.size) - panic("invalid size for reg %s: cpu=%d da=%#x pa=%#x size=%d", - info.name, cpu, daddr, pkt.addr, pkt.size); + panic("write %s (invalid size): " + "cpu=%d vnic=%d da=%#x pa=%#x size=%d", + info.name, cpu, index, daddr, pkt.addr, pkt.size); VirtualReg &vnic = virtualRegs[index]; DPRINTF(EthernetPIO, - "write %s: cpu=%d val=%#x da=%#x pa=%#x size=%d\n", - info.name, cpu, info.size == 4 ? pkt.get<uint32_t>() : + "write %s vnic %d: cpu=%d val=%#x da=%#x pa=%#x size=%d\n", + info.name, index, cpu, info.size == 4 ? pkt.get<uint32_t>() : pkt.get<uint64_t>(), daddr, pkt.addr, pkt.size); prepareWrite(cpu, index); @@ -454,10 +458,32 @@ Device::write(Packet &pkt) panic("receive machine busy with another request! rxState=%s", RxStateStrings[rxState]); + vnic.rxUnique = rxUnique++; vnic.RxDone = Regs::RxDone_Busy; vnic.RxData = pkt.get<uint64_t>(); - rxList.push_back(index); - if (rxEnable && rxState == rxIdle) { + + if (Regs::get_RxData_Vaddr(reg64)) { + Addr vaddr = Regs::get_RxData_Addr(reg64); + Addr paddr = vtophys(req->xc, vaddr); + DPRINTF(EthernetPIO, "write RxData vnic %d (rxunique %d): " + "vaddr=%#x, paddr=%#x\n", + index, vnic.rxUnique, vaddr, paddr); + + vnic.RxData = Regs::set_RxData_Addr(vnic.RxData, paddr); + } else { + DPRINTF(EthernetPIO, "write RxData vnic %d (rxunique %d)\n", + index, vnic.rxUnique); + } + + if (vnic.rxPacket == rxFifo.end()) { + DPRINTF(EthernetPIO, "request new packet...appending to rxList\n"); + rxList.push_back(index); + } else { + DPRINTF(EthernetPIO, "packet exists...appending to rxBusy\n"); + rxBusy.push_back(index); + } + + if (rxEnable && (rxState == rxIdle || rxState == rxFifoBlock)) { rxState = rxFifoBlock; rxKick(); } @@ -468,8 +494,23 @@ Device::write(Packet &pkt) panic("transmit machine busy with another request! txState=%s", TxStateStrings[txState]); + vnic.txUnique = txUnique++; vnic.TxDone = Regs::TxDone_Busy; - vnic.TxData = pkt.get<uint64_t>(); + + if (Regs::get_TxData_Vaddr(pkt.get<uint64_t>())) { + panic("vtophys won't work here in newmem.\n"); + /*Addr vaddr = Regs::get_TxData_Addr(reg64); + Addr paddr = vtophys(req->xc, vaddr); + DPRINTF(EthernetPIO, "write TxData vnic %d (rxunique %d): " + "vaddr=%#x, paddr=%#x\n", + index, vnic.txUnique, vaddr, paddr); + + vnic.TxData = Regs::set_TxData_Addr(vnic.TxData, paddr);*/ + } else { + DPRINTF(EthernetPIO, "write TxData vnic %d (rxunique %d)\n", + index, vnic.txUnique); + } + if (txList.empty() || txList.front() != index) txList.push_back(index); if (txEnable && txState == txIdle && txList.front() == index) { @@ -695,10 +736,21 @@ Device::reset() regs.Config |= Config_TxThread; if (params()->rss) regs.Config |= Config_RSS; + if (params()->zero_copy) + regs.Config |= Config_ZeroCopy; + if (params()->delay_copy) + regs.Config |= Config_DelayCopy; + if (params()->virtual_addr) + regs.Config |= Config_Vaddr; + + if (params()->delay_copy && params()->zero_copy) + panic("Can't delay copy and zero copy"); + regs.IntrMask = Intr_Soft | Intr_RxHigh | Intr_RxPacket | Intr_TxLow; regs.RxMaxCopy = params()->rx_max_copy; regs.TxMaxCopy = params()->tx_max_copy; regs.RxMaxIntr = params()->rx_max_intr; + regs.VirtualCount = params()->virtual_count; regs.RxFifoSize = params()->rx_fifo_size; regs.TxFifoSize = params()->tx_fifo_size; regs.RxFifoMark = params()->rx_fifo_threshold; @@ -706,6 +758,8 @@ Device::reset() regs.HwAddr = params()->eaddr; rxList.clear(); + rxBusy.clear(); + rxActive = -1; txList.clear(); rxState = rxIdle; @@ -715,6 +769,7 @@ Device::reset() rxFifoPtr = rxFifo.end(); txFifo.clear(); rxEmpty = false; + rxLow = true; txFull = false; int size = virtualRegs.size(); @@ -729,7 +784,7 @@ Device::rxDmaDone() { assert(rxState == rxCopy); rxState = rxCopyDone; - DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n", + DPRINTF(EthernetDMA, "end rx dma write paddr=%#x len=%d\n", rxDmaAddr, rxDmaLen); DDUMP(EthernetData, rxDmaData, rxDmaLen); @@ -743,13 +798,13 @@ Device::rxDmaDone() void Device::rxKick() { - VirtualReg *vnic; + VirtualReg *vnic = NULL; - DPRINTF(EthernetSM, "receive kick rxState=%s (rxFifo.size=%d)\n", + DPRINTF(EthernetSM, "rxKick: rxState=%s (rxFifo.size=%d)\n", RxStateStrings[rxState], rxFifo.size()); if (rxKickTick > curTick) { - DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n", + DPRINTF(EthernetSM, "rxKick: exiting, can't run till %d\n", rxKickTick); return; } @@ -758,16 +813,50 @@ Device::rxKick() if (rxState == rxIdle) goto exit; - assert(!rxList.empty()); - vnic = &virtualRegs[rxList.front()]; + if (rxActive == -1) { + if (rxState != rxFifoBlock) + panic("no active vnic while in state %s", RxStateStrings[rxState]); - DPRINTF(EthernetSM, "processing rxState=%s for virtual nic %d\n", - RxStateStrings[rxState], rxList.front()); + DPRINTF(EthernetSM, "processing rxState=%s\n", + RxStateStrings[rxState]); + } else { + vnic = &virtualRegs[rxActive]; + DPRINTF(EthernetSM, + "processing rxState=%s for vnic %d (rxunique %d)\n", + RxStateStrings[rxState], rxActive, vnic->rxUnique); + } switch (rxState) { case rxFifoBlock: - if (vnic->rxPacket != rxFifo.end()) { + if (DTRACE(EthernetSM)) { + PacketFifo::iterator end = rxFifo.end(); + int size = virtualRegs.size(); + for (int i = 0; i < size; ++i) { + VirtualReg *vn = &virtualRegs[i]; + if (vn->rxPacket != end && + !Regs::get_RxDone_Busy(vn->RxDone)) { + DPRINTF(EthernetSM, + "vnic %d (rxunique %d), has outstanding packet %d\n", + i, vn->rxUnique, + rxFifo.countPacketsBefore(vn->rxPacket)); + } + } + } + + if (!rxBusy.empty()) { + rxActive = rxBusy.front(); + rxBusy.pop_front(); + vnic = &virtualRegs[rxActive]; + + if (vnic->rxPacket == rxFifo.end()) + panic("continuing vnic without packet\n"); + + DPRINTF(EthernetSM, + "continue processing for vnic %d (rxunique %d)\n", + rxActive, vnic->rxUnique); + rxState = rxBeginCopy; + break; } @@ -776,8 +865,19 @@ Device::rxKick() goto exit; } + if (rxList.empty()) + panic("Not idle, but nothing to do!"); + assert(!rxFifo.empty()); + rxActive = rxList.front(); + rxList.pop_front(); + vnic = &virtualRegs[rxActive]; + + DPRINTF(EthernetSM, + "processing new packet for vnic %d (rxunique %d)\n", + rxActive, vnic->rxUnique); + // Grab a new packet from the fifo. vnic->rxPacket = rxFifoPtr++; vnic->rxPacketOffset = 0; @@ -788,6 +888,7 @@ Device::rxKick() /* scope for variables */ { IpPtr ip(*vnic->rxPacket); if (ip) { + DPRINTF(Ethernet, "ID is %d\n", ip->id()); vnic->rxDoneData |= Regs::RxDone_IpPacket; rxIpChecksums++; if (cksum(ip) != 0) { @@ -797,6 +898,10 @@ Device::rxKick() TcpPtr tcp(ip); UdpPtr udp(ip); if (tcp) { + DPRINTF(Ethernet, + "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n", + tcp->sport(), tcp->dport(), tcp->seq(), + tcp->ack()); vnic->rxDoneData |= Regs::RxDone_TcpPacket; rxTcpChecksums++; if (cksum(tcp) != 0) { @@ -826,6 +931,11 @@ Device::rxKick() vnic->rxPacketBytes); rxDmaData = (*vnic->rxPacket)->data + vnic->rxPacketOffset; rxState = rxCopy; + if (rxDmaAddr == 1LL) { + rxState = rxCopyDone; + break; + } + dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaEvent, rxDmaData); break; @@ -835,31 +945,44 @@ Device::rxKick() goto exit; case rxCopyDone: - vnic->RxDone = vnic->rxDoneData | rxDmaLen; + vnic->RxDone = vnic->rxDoneData; vnic->RxDone |= Regs::RxDone_Complete; if (vnic->rxPacketBytes == rxDmaLen) { - DPRINTF(EthernetSM, "rxKick: packet complete on vnic %d\n", - rxList.front()); + // Packet is complete. Indicate how many bytes were copied + vnic->RxDone = Regs::set_RxDone_CopyLen(vnic->RxDone, rxDmaLen); + + DPRINTF(EthernetSM, + "rxKick: packet complete on vnic %d (rxunique %d)\n", + rxActive, vnic->rxUnique); rxFifo.remove(vnic->rxPacket); vnic->rxPacket = rxFifo.end(); } else { - vnic->RxDone |= Regs::RxDone_More; vnic->rxPacketBytes -= rxDmaLen; vnic->rxPacketOffset += rxDmaLen; + vnic->RxDone |= Regs::RxDone_More; + vnic->RxDone = Regs::set_RxDone_CopyLen(vnic->RxDone, + vnic->rxPacketBytes); DPRINTF(EthernetSM, - "rxKick: packet not complete on vnic %d: %d bytes left\n", - rxList.front(), vnic->rxPacketBytes); + "rxKick: packet not complete on vnic %d (rxunique %d): " + "%d bytes left\n", + rxActive, vnic->rxUnique, vnic->rxPacketBytes); } - rxList.pop_front(); - rxState = rxList.empty() ? rxIdle : rxFifoBlock; + rxActive = -1; + rxState = rxBusy.empty() && rxList.empty() ? rxIdle : rxFifoBlock; if (rxFifo.empty()) { devIntrPost(Regs::Intr_RxEmpty); rxEmpty = true; } + if (rxFifo.size() < params()->rx_fifo_low_mark) + rxLow = true; + + if (rxFifo.size() > params()->rx_fifo_threshold) + rxLow = false; + devIntrPost(Regs::Intr_RxDMA); break; @@ -920,8 +1043,10 @@ Device::transmit() DPRINTF(Ethernet, "ID is %d\n", ip->id()); TcpPtr tcp(ip); if (tcp) { - DPRINTF(Ethernet, "Src Port=%d, Dest Port=%d\n", - tcp->sport(), tcp->dport()); + DPRINTF(Ethernet, + "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n", + tcp->sport(), tcp->dport(), tcp->seq(), + tcp->ack()); } } } @@ -950,11 +1075,11 @@ void Device::txKick() { VirtualReg *vnic; - DPRINTF(EthernetSM, "transmit kick txState=%s (txFifo.size=%d)\n", + DPRINTF(EthernetSM, "txKick: txState=%s (txFifo.size=%d)\n", TxStateStrings[txState], txFifo.size()); if (txKickTick > curTick) { - DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n", + DPRINTF(EthernetSM, "txKick: exiting, can't run till %d\n", txKickTick); return; } @@ -968,7 +1093,7 @@ Device::txKick() switch (txState) { case txFifoBlock: - assert(Regs::get_TxDone_Busy(vnic->TxData)); + assert(Regs::get_TxDone_Busy(vnic->TxDone)); if (!txPacket) { // Grab a new packet from the fifo. txPacket = new EthPacketData(16384); @@ -1213,6 +1338,8 @@ Base::unserialize(Checkpoint *cp, const std::string §ion) void Device::serialize(std::ostream &os) { + int count; + // Serialize the PciDev base class Base::serialize(os); @@ -1233,6 +1360,7 @@ Device::serialize(std::ostream &os) SERIALIZE_SCALAR(regs.RxMaxCopy); SERIALIZE_SCALAR(regs.TxMaxCopy); SERIALIZE_SCALAR(regs.RxMaxIntr); + SERIALIZE_SCALAR(regs.VirtualCount); SERIALIZE_SCALAR(regs.RxData); SERIALIZE_SCALAR(regs.RxDone); SERIALIZE_SCALAR(regs.TxData); @@ -1252,8 +1380,6 @@ Device::serialize(std::ostream &os) paramOut(os, reg + ".TxData", vnic->TxData); paramOut(os, reg + ".TxDone", vnic->TxDone); - PacketFifo::iterator rxFifoPtr; - bool rxPacketExists = vnic->rxPacket != rxFifo.end(); paramOut(os, reg + ".rxPacketExists", rxPacketExists); if (rxPacketExists) { @@ -1272,18 +1398,26 @@ Device::serialize(std::ostream &os) paramOut(os, reg + ".rxDoneData", vnic->rxDoneData); } - VirtualList::iterator i, end; - int count; + int rxFifoPtr = rxFifo.countPacketsBefore(this->rxFifoPtr); + SERIALIZE_SCALAR(rxFifoPtr); - int rxListSize = rxList.size(); - SERIALIZE_SCALAR(rxListSize); + SERIALIZE_SCALAR(rxActive); + + VirtualList::iterator i, end; for (count = 0, i = rxList.begin(), end = rxList.end(); i != end; ++i) paramOut(os, csprintf("rxList%d", count++), *i); + int rxListSize = count; + SERIALIZE_SCALAR(rxListSize); + + for (count = 0, i = rxBusy.begin(), end = rxBusy.end(); i != end; ++i) + paramOut(os, csprintf("rxBusy%d", count++), *i); + int rxBusySize = count; + SERIALIZE_SCALAR(rxBusySize); - int txListSize = txList.size(); - SERIALIZE_SCALAR(txListSize); for (count = 0, i = txList.begin(), end = txList.end(); i != end; ++i) paramOut(os, csprintf("txList%d", count++), *i); + int txListSize = count; + SERIALIZE_SCALAR(txListSize); /* * Serialize rx state machine @@ -1291,6 +1425,7 @@ Device::serialize(std::ostream &os) int rxState = this->rxState; SERIALIZE_SCALAR(rxState); SERIALIZE_SCALAR(rxEmpty); + SERIALIZE_SCALAR(rxLow); rxFifo.serialize("rxFifo", os); /* @@ -1331,11 +1466,14 @@ Device::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(regs.RxMaxCopy); UNSERIALIZE_SCALAR(regs.TxMaxCopy); UNSERIALIZE_SCALAR(regs.RxMaxIntr); + UNSERIALIZE_SCALAR(regs.VirtualCount); UNSERIALIZE_SCALAR(regs.RxData); UNSERIALIZE_SCALAR(regs.RxDone); UNSERIALIZE_SCALAR(regs.TxData); UNSERIALIZE_SCALAR(regs.TxDone); + UNSERIALIZE_SCALAR(rxActive); + int rxListSize; UNSERIALIZE_SCALAR(rxListSize); rxList.clear(); @@ -1345,6 +1483,15 @@ Device::unserialize(Checkpoint *cp, const std::string §ion) rxList.push_back(value); } + int rxBusySize; + UNSERIALIZE_SCALAR(rxBusySize); + rxBusy.clear(); + for (int i = 0; i < rxBusySize; ++i) { + int value; + paramIn(cp, section, csprintf("rxBusy%d", i), value); + rxBusy.push_back(value); + } + int txListSize; UNSERIALIZE_SCALAR(txListSize); txList.clear(); @@ -1360,9 +1507,16 @@ Device::unserialize(Checkpoint *cp, const std::string §ion) int rxState; UNSERIALIZE_SCALAR(rxState); UNSERIALIZE_SCALAR(rxEmpty); + UNSERIALIZE_SCALAR(rxLow); this->rxState = (RxState) rxState; rxFifo.unserialize("rxFifo", cp, section); + int rxFifoPtr; + UNSERIALIZE_SCALAR(rxFifoPtr); + this->rxFifoPtr = rxFifo.begin(); + for (int i = 0; i < rxFifoPtr; ++i) + ++this->rxFifoPtr; + /* * Unserialize tx state machine */ @@ -1400,6 +1554,9 @@ Device::unserialize(Checkpoint *cp, const std::string §ion) paramIn(cp, section, reg + ".TxData", vnic->TxData); paramIn(cp, section, reg + ".TxDone", vnic->TxDone); + vnic->rxUnique = rxUnique++; + vnic->txUnique = txUnique++; + bool rxPacketExists; paramIn(cp, section, reg + ".rxPacketExists", rxPacketExists); if (rxPacketExists) { @@ -1488,6 +1645,8 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device) Param<uint32_t> rx_fifo_size; Param<uint32_t> tx_fifo_size; Param<uint32_t> rx_fifo_threshold; + Param<uint32_t> rx_fifo_low_mark; + Param<uint32_t> tx_fifo_high_mark; Param<uint32_t> tx_fifo_threshold; Param<bool> rx_filter; @@ -1495,6 +1654,10 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device) Param<bool> rx_thread; Param<bool> tx_thread; Param<bool> rss; + Param<uint32_t> virtual_count; + Param<bool> zero_copy; + Param<bool> delay_copy; + Param<bool> virtual_addr; END_DECLARE_SIM_OBJECT_PARAMS(Device) @@ -1525,13 +1688,19 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(Device) INIT_PARAM(rx_fifo_size, "max size in bytes of rxFifo"), INIT_PARAM(tx_fifo_size, "max size in bytes of txFifo"), INIT_PARAM(rx_fifo_threshold, "max size in bytes of rxFifo"), + INIT_PARAM(rx_fifo_low_mark, "max size in bytes of rxFifo"), + INIT_PARAM(tx_fifo_high_mark, "max size in bytes of txFifo"), INIT_PARAM(tx_fifo_threshold, "max size in bytes of txFifo"), INIT_PARAM(rx_filter, "Enable Receive Filter"), INIT_PARAM(hardware_address, "Ethernet Hardware Address"), INIT_PARAM(rx_thread, ""), INIT_PARAM(tx_thread, ""), - INIT_PARAM(rss, "") + INIT_PARAM(rss, ""), + INIT_PARAM(virtual_count, ""), + INIT_PARAM(zero_copy, ""), + INIT_PARAM(delay_copy, ""), + INIT_PARAM(virtual_addr, "") END_INIT_SIM_OBJECT_PARAMS(Device) @@ -1564,6 +1733,8 @@ CREATE_SIM_OBJECT(Device) params->rx_fifo_size = rx_fifo_size; params->tx_fifo_size = tx_fifo_size; params->rx_fifo_threshold = rx_fifo_threshold; + params->rx_fifo_low_mark = rx_fifo_low_mark; + params->tx_fifo_high_mark = tx_fifo_high_mark; params->tx_fifo_threshold = tx_fifo_threshold; params->rx_filter = rx_filter; @@ -1571,6 +1742,10 @@ CREATE_SIM_OBJECT(Device) params->rx_thread = rx_thread; params->tx_thread = tx_thread; params->rss = rss; + params->virtual_count = virtual_count; + params->zero_copy = zero_copy; + params->delay_copy = delay_copy; + params->virtual_addr = virtual_addr; return new Device(params); } diff --git a/dev/sinic.hh b/dev/sinic.hh index 63a8585dc..a786c3e44 100644 --- a/dev/sinic.hh +++ b/dev/sinic.hh @@ -117,7 +117,7 @@ class Device : public Base uint32_t RxMaxCopy; // 0x10 uint32_t TxMaxCopy; // 0x14 uint32_t RxMaxIntr; // 0x18 - uint32_t Reserved0; // 0x1c + uint32_t VirtualCount; // 0x1c uint32_t RxFifoSize; // 0x20 uint32_t TxFifoSize; // 0x24 uint32_t RxFifoMark; // 0x28 @@ -142,6 +142,9 @@ class Device : public Base int rxPacketBytes; uint64_t rxDoneData; + Counter rxUnique; + Counter txUnique; + VirtualReg() : RxData(0), RxDone(0), TxData(0), TxDone(0), rxPacketOffset(0), rxPacketBytes(0), rxDoneData(0) @@ -149,8 +152,12 @@ class Device : public Base }; typedef std::vector<VirtualReg> VirtualRegs; typedef std::list<int> VirtualList; + Counter rxUnique; + Counter txUnique; VirtualRegs virtualRegs; VirtualList rxList; + VirtualList rxBusy; + int rxActive; VirtualList txList; uint8_t ®Data8(Addr daddr) { return *((uint8_t *)®s + daddr); } @@ -162,6 +169,7 @@ class Device : public Base PacketFifo rxFifo; PacketFifo::iterator rxFifoPtr; bool rxEmpty; + bool rxLow; Addr rxDmaAddr; uint8_t *rxDmaData; int rxDmaLen; @@ -318,6 +326,8 @@ class Device : public Base uint32_t rx_fifo_size; uint32_t tx_fifo_size; uint32_t rx_fifo_threshold; + uint32_t rx_fifo_low_mark; + uint32_t tx_fifo_high_mark; uint32_t tx_fifo_threshold; Tick dma_read_delay; Tick dma_read_factor; @@ -326,6 +336,10 @@ class Device : public Base bool rx_thread; bool tx_thread; bool rss; + uint32_t virtual_count; + bool zero_copy; + bool delay_copy; + bool virtual_addr; }; protected: diff --git a/dev/sinicreg.hh b/dev/sinicreg.hh index f90432398..d41eb5b16 100644 --- a/dev/sinicreg.hh +++ b/dev/sinicreg.hh @@ -55,38 +55,40 @@ namespace Sinic { namespace Regs { -static const int VirtualMask = 0xff; static const int VirtualShift = 8; +static const int VirtualMask = 0xff; // Registers -__SINIC_REG32(Config, 0x00); // 32: configuration register -__SINIC_REG32(Command, 0x04); // 32: command register -__SINIC_REG32(IntrStatus, 0x08); // 32: interrupt status -__SINIC_REG32(IntrMask, 0x0c); // 32: interrupt mask -__SINIC_REG32(RxMaxCopy, 0x10); // 32: max bytes per rx copy -__SINIC_REG32(TxMaxCopy, 0x14); // 32: max bytes per tx copy -__SINIC_REG32(RxMaxIntr, 0x18); // 32: max receives per interrupt -__SINIC_REG32(Reserved0, 0x1c); // 32: reserved -__SINIC_REG32(RxFifoSize, 0x20); // 32: rx fifo capacity in bytes -__SINIC_REG32(TxFifoSize, 0x24); // 32: tx fifo capacity in bytes -__SINIC_REG32(RxFifoMark, 0x28); // 32: rx fifo high watermark -__SINIC_REG32(TxFifoMark, 0x2c); // 32: tx fifo low watermark -__SINIC_REG32(RxData, 0x30); // 64: receive data -__SINIC_REG32(RxDone, 0x38); // 64: receive done -__SINIC_REG32(RxWait, 0x40); // 64: receive done (busy wait) -__SINIC_REG32(TxData, 0x48); // 64: transmit data -__SINIC_REG32(TxDone, 0x50); // 64: transmit done -__SINIC_REG32(TxWait, 0x58); // 64: transmit done (busy wait) -__SINIC_REG32(HwAddr, 0x60); // 64: mac address -__SINIC_REG32(Size, 0x68); // register addres space size +__SINIC_REG32(Config, 0x00); // 32: configuration register +__SINIC_REG32(Command, 0x04); // 32: command register +__SINIC_REG32(IntrStatus, 0x08); // 32: interrupt status +__SINIC_REG32(IntrMask, 0x0c); // 32: interrupt mask +__SINIC_REG32(RxMaxCopy, 0x10); // 32: max bytes per rx copy +__SINIC_REG32(TxMaxCopy, 0x14); // 32: max bytes per tx copy +__SINIC_REG32(RxMaxIntr, 0x18); // 32: max receives per interrupt +__SINIC_REG32(VirtualCount, 0x1c); // 32: number of virutal NICs +__SINIC_REG32(RxFifoSize, 0x20); // 32: rx fifo capacity in bytes +__SINIC_REG32(TxFifoSize, 0x24); // 32: tx fifo capacity in bytes +__SINIC_REG32(RxFifoMark, 0x28); // 32: rx fifo high watermark +__SINIC_REG32(TxFifoMark, 0x2c); // 32: tx fifo low watermark +__SINIC_REG32(RxData, 0x30); // 64: receive data +__SINIC_REG32(RxDone, 0x38); // 64: receive done +__SINIC_REG32(RxWait, 0x40); // 64: receive done (busy wait) +__SINIC_REG32(TxData, 0x48); // 64: transmit data +__SINIC_REG32(TxDone, 0x50); // 64: transmit done +__SINIC_REG32(TxWait, 0x58); // 64: transmit done (busy wait) +__SINIC_REG32(HwAddr, 0x60); // 64: mac address +__SINIC_REG32(Size, 0x68); // register addres space size // Config register bits +__SINIC_VAL32(Config_ZeroCopy, 12, 1); // enable zero copy +__SINIC_VAL32(Config_DelayCopy,11, 1); // enable delayed copy __SINIC_VAL32(Config_RSS, 10, 1); // enable receive side scaling __SINIC_VAL32(Config_RxThread, 9, 1); // enable receive threads __SINIC_VAL32(Config_TxThread, 8, 1); // enable transmit thread __SINIC_VAL32(Config_Filter, 7, 1); // enable receive filter __SINIC_VAL32(Config_Vlan, 6, 1); // enable vlan tagging -__SINIC_VAL32(Config_Virtual, 5, 1); // enable virtual addressing +__SINIC_VAL32(Config_Vaddr, 5, 1); // enable virtual addressing __SINIC_VAL32(Config_Desc, 4, 1); // enable tx/rx descriptors __SINIC_VAL32(Config_Poll, 3, 1); // enable polling __SINIC_VAL32(Config_IntEn, 2, 1); // enable interrupts @@ -112,13 +114,15 @@ __SINIC_REG32(Intr_NoDelay, 0x01cc); // interrupts that aren't coalesced __SINIC_REG32(Intr_Res, ~0x01ff); // reserved interrupt bits // RX Data Description -__SINIC_VAL64(RxData_Len, 40, 20); // 0 - 1M -__SINIC_VAL64(RxData_Addr, 0, 40); // Address 1TB +__SINIC_VAL64(RxData_Vaddr, 60, 1); // Addr is virtual +__SINIC_VAL64(RxData_Len, 40, 20); // 0 - 256k +__SINIC_VAL64(RxData_Addr, 0, 40); // Address 1TB // TX Data Description __SINIC_VAL64(TxData_More, 63, 1); // Packet not complete (will dma more) __SINIC_VAL64(TxData_Checksum, 62, 1); // do checksum -__SINIC_VAL64(TxData_Len, 40, 20); // 0 - 1M +__SINIC_VAL64(TxData_Vaddr, 60, 1); // Addr is virtual +__SINIC_VAL64(TxData_Len, 40, 20); // 0 - 256k __SINIC_VAL64(TxData_Addr, 0, 40); // Address 1TB // RX Done/Busy Information @@ -126,9 +130,9 @@ __SINIC_VAL64(RxDone_Packets, 32, 16); // number of packets in rx fifo __SINIC_VAL64(RxDone_Busy, 31, 1); // receive dma busy copying __SINIC_VAL64(RxDone_Complete, 30, 1); // valid data (packet complete) __SINIC_VAL64(RxDone_More, 29, 1); // Packet has more data (dma again) -__SINIC_VAL64(RxDone_Res0, 28, 1); // reserved -__SINIC_VAL64(RxDone_Res1, 27, 1); // reserved -__SINIC_VAL64(RxDone_Res2, 26, 1); // reserved +__SINIC_VAL64(RxDone_Empty, 28, 1); // rx fifo is empty +__SINIC_VAL64(RxDone_High, 27, 1); // rx fifo is above the watermark +__SINIC_VAL64(RxDone_NotHigh, 26, 1); // rxfifo never hit the high watermark __SINIC_VAL64(RxDone_TcpError, 25, 1); // TCP packet error (bad checksum) __SINIC_VAL64(RxDone_UdpError, 24, 1); // UDP packet error (bad checksum) __SINIC_VAL64(RxDone_IpError, 23, 1); // IP packet error (bad checksum) @@ -175,7 +179,7 @@ regInfo(Addr daddr) { 4, true, false, "RxMaxCopy" }, { 4, true, false, "TxMaxCopy" }, { 4, true, false, "RxMaxIntr" }, - invalid, + { 4, true, false, "VirtualCount" }, { 4, true, false, "RxFifoSize" }, { 4, true, false, "TxFifoSize" }, { 4, true, false, "RxFifoMark" }, diff --git a/python/m5/objects/Ethernet.py b/python/m5/objects/Ethernet.py index 0667fc6d7..4286c71c8 100644 --- a/python/m5/objects/Ethernet.py +++ b/python/m5/objects/Ethernet.py @@ -101,8 +101,14 @@ class Sinic(EtherDevBase): rx_max_copy = Param.MemorySize('1514B', "rx max copy") tx_max_copy = Param.MemorySize('16kB', "tx max copy") rx_max_intr = Param.UInt32(10, "max rx packets per interrupt") - rx_fifo_threshold = Param.MemorySize('48kB', "rx fifo high threshold") - tx_fifo_threshold = Param.MemorySize('16kB', "tx fifo low threshold") + rx_fifo_threshold = Param.MemorySize('384kB', "rx fifo high threshold") + rx_fifo_low_mark = Param.MemorySize('128kB', "rx fifo low threshold") + tx_fifo_high_mark = Param.MemorySize('384kB', "tx fifo high threshold") + tx_fifo_threshold = Param.MemorySize('128kB', "tx fifo low threshold") + virtual_count = Param.UInt32(1, "Virtualized SINIC") + zero_copy = Param.Bool(False, "Zero copy receive") + delay_copy = Param.Bool(False, "Delayed copy transmit") + virtual_addr = Param.Bool(False, "Virtual addressing") class SinicInt(EtherInt): type = 'SinicInt' diff --git a/sim/faults.cc b/sim/faults.cc index f7e9a0691..cb095f852 100644 --- a/sim/faults.cc +++ b/sim/faults.cc @@ -45,3 +45,8 @@ void FaultBase::invoke(ExecContext * xc) assert(!xc->misspeculating()); } #endif + +void UnimpFault::invoke(ExecContext * xc) +{ + panic("Unimpfault: %s\n", panicStr.c_str()); +} diff --git a/sim/faults.hh b/sim/faults.hh index 18601e8f1..9b3bc9103 100644 --- a/sim/faults.hh +++ b/sim/faults.hh @@ -64,4 +64,17 @@ class FaultBase : public RefCounted FaultBase * const NoFault = 0; +class UnimpFault : public FaultBase +{ + private: + std::string panicStr; + public: + UnimpFault(std::string _str) + : panicStr(_str) + { } + + FaultName name() {return "Unimplemented simulator feature";} + void invoke(ExecContext * xc); +}; + #endif // __FAULTS_HH__ diff --git a/sim/serialize.cc b/sim/serialize.cc index ec7241498..c4ef124bb 100644 --- a/sim/serialize.cc +++ b/sim/serialize.cc @@ -51,8 +51,9 @@ using namespace std; -int Serializable::maxCount = 0; -int Serializable::count = 0; +int Serializable::ckptMaxCount = 0; +int Serializable::ckptCount = 0; +int Serializable::ckptPrevCount = -1; void Serializable::nameOut(ostream &os) @@ -241,8 +242,11 @@ Serializable::serializeAll() globals.serialize(outstream); SimObject::serializeAll(outstream); - if (maxCount && ++count >= maxCount) + assert(Serializable::ckptPrevCount + 1 == Serializable::ckptCount); + Serializable::ckptPrevCount++; + if (ckptMaxCount && ++ckptCount >= ckptMaxCount) SimExit(curTick + 1, "Maximum number of checkpoints dropped"); + } @@ -352,7 +356,7 @@ SerializeParamContext::checkParams() if (serialize_cycle > 0) Checkpoint::setup(serialize_cycle, serialize_period); - Serializable::maxCount = serialize_count; + Serializable::ckptMaxCount = serialize_count; } void diff --git a/sim/serialize.hh b/sim/serialize.hh index bc82bf9b8..d8f5f8fc5 100644 --- a/sim/serialize.hh +++ b/sim/serialize.hh @@ -119,8 +119,9 @@ class Serializable static Serializable *create(Checkpoint *cp, const std::string §ion); - static int count; - static int maxCount; + static int ckptCount; + static int ckptMaxCount; + static int ckptPrevCount; static void serializeAll(); static void unserializeGlobals(Checkpoint *cp); }; diff --git a/sim/sim_object.cc b/sim/sim_object.cc index 151ba68a7..17d58ba4f 100644 --- a/sim/sim_object.cc +++ b/sim/sim_object.cc @@ -34,6 +34,7 @@ #include "base/misc.hh" #include "base/trace.hh" #include "base/stats/events.hh" +#include "base/serializer.hh" #include "sim/configfile.hh" #include "sim/host.hh" #include "sim/sim_object.hh" @@ -248,4 +249,10 @@ SimObject::recordEvent(const std::string &stat) Stats::recordEvent(stat); } +void +SimObject::drain(Serializer *serializer) +{ + serializer->signalDrained(); +} + DEFINE_SIM_OBJECT_CLASS_NAME("SimObject", SimObject) diff --git a/sim/sim_object.hh b/sim/sim_object.hh index 5db62dd51..76aba7ea1 100644 --- a/sim/sim_object.hh +++ b/sim/sim_object.hh @@ -41,6 +41,8 @@ #include "sim/serialize.hh" #include "sim/startup.hh" +class Serializer; + /* * Abstract superclass for simulation objects. Represents things that * correspond to physical components and can be specified via the @@ -96,6 +98,13 @@ class SimObject : public Serializable, protected StartupCallback // static: call nameOut() & serialize() on all SimObjects static void serializeAll(std::ostream &); + // Methods to drain objects in order to take checkpoints + // Or switch from timing -> atomic memory model + virtual void drain(Serializer *serializer); + virtual void resume() { return;} ; + virtual void serializationComplete() + { assert(0 && "Unimplemented"); }; + #ifdef DEBUG public: bool doDebugBreak; diff --git a/util/stats/barchart.py b/util/stats/barchart.py index 5d6dd0ab1..a477d1f3b 100644 --- a/util/stats/barchart.py +++ b/util/stats/barchart.py @@ -233,7 +233,7 @@ class BarChart(ChartOptions): inner_axes.set_yticks(ticks) inner_axes.set_yticklabels(self.yticks) elif self.ylim is not None: - self.inner_axes.set_ylim(self.ylim) + inner_axes.set_ylim(self.ylim) if self.xticks is not None: outer_axes.set_xticks(arange(cshape[2]) + .5) @@ -242,9 +242,9 @@ class BarChart(ChartOptions): if self.xsubticks is not None: numticks = (cshape[0] + 1) * cshape[2] inner_axes.set_xticks(arange(numticks) * width + 2 * center) - self.xsubticks.append('') - inner_axes.set_xticklabels(self.xsubticks * cshape[2], fontsize=7, - rotation=90) + xsubticks = list(self.xsubticks) + [ '' ] + inner_axes.set_xticklabels(xsubticks * cshape[2], fontsize=7, + rotation=30) if self.legend is not None: if dim == 1: |