From 18b2d94b8cc748a81468b0fa7a4778d07bac43ec Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Mon, 23 Oct 2006 11:17:15 -0400 Subject: Move around more SPARC memory code, and make block memory operations work with the timing cpu --HG-- extra : convert_revision : 37358504c4d05d78d08c19ba3d0c99d38c4babf5 --- src/arch/sparc/isa/formats/mem/basicmem.isa | 20 ++--- src/arch/sparc/isa/formats/mem/blockmem.isa | 115 ++++++++++------------------ src/arch/sparc/isa/formats/mem/util.isa | 71 +++++++++++++---- 3 files changed, 105 insertions(+), 101 deletions(-) (limited to 'src/arch/sparc/isa/formats') diff --git a/src/arch/sparc/isa/formats/mem/basicmem.isa b/src/arch/sparc/isa/formats/mem/basicmem.isa index b524f309a..c13194d0f 100644 --- a/src/arch/sparc/isa/formats/mem/basicmem.isa +++ b/src/arch/sparc/isa/formats/mem/basicmem.isa @@ -146,26 +146,18 @@ def template MemDeclare {{ }}; let {{ - # XXX Need to take care of pstate.hpriv as well. The lower ASIs are split - # into ones that are available in priv and hpriv, and those that are only - # available in hpriv - privilegedString = '''if(bits(Pstate,2,2) == 0 && (EXT_ASI & 0x80) == 0) - return new PrivilegedAction; - if(AsiIsAsIfUser(EXT_ASI) && !bits(Pstate,2,2)) - return new PrivilegedAction;''' - - def doMemFormat(code, execute, priv, name, Name, opt_flags): + def doMemFormat(code, execute, faultCode, name, Name, opt_flags): addrCalcReg = 'EA = Rs1 + Rs2;' addrCalcImm = 'EA = Rs1 + imm;' iop = InstObjParams(name, Name, 'Mem', code, - opt_flags, {"priv_check": priv, "ea_code": addrCalcReg}) + opt_flags, {"fault_check": faultCode, "ea_code": addrCalcReg}) iop_imm = InstObjParams(name, Name + "Imm", 'MemImm', code, - opt_flags, {"priv_check": priv, "ea_code": addrCalcImm}) + opt_flags, {"fault_check": faultCode, "ea_code": addrCalcImm}) header_output = MemDeclare.subst(iop) + MemDeclare.subst(iop_imm) decoder_output = BasicConstructor.subst(iop) + BasicConstructor.subst(iop_imm) decode_block = ROrImmDecode.subst(iop) exec_output = doSplitExecute(code, addrCalcReg, addrCalcImm, execute, - priv, name, name + "Imm", Name, Name + "Imm", opt_flags) + faultCode, name, name + "Imm", Name, Name + "Imm", opt_flags) return (header_output, decoder_output, exec_output, decode_block) }}; @@ -174,7 +166,7 @@ def format LoadAlt(code, *opt_flags) {{ decoder_output, exec_output, decode_block) = doMemFormat(code, LoadExecute, - privelegedString, name, Name, opt_flags) + AlternateAsiPrivFaultCheck, name, Name, opt_flags) }}; def format StoreAlt(code, *opt_flags) {{ @@ -182,7 +174,7 @@ def format StoreAlt(code, *opt_flags) {{ decoder_output, exec_output, decode_block) = doMemFormat(code, StoreExecute, - privilegedString, name, Name, opt_flags) + AlternateAsiPrivFaultCheck, name, Name, opt_flags) }}; def format Load(code, *opt_flags) {{ diff --git a/src/arch/sparc/isa/formats/mem/blockmem.isa b/src/arch/sparc/isa/formats/mem/blockmem.isa index 8584662a1..93ad1b2b8 100644 --- a/src/arch/sparc/isa/formats/mem/blockmem.isa +++ b/src/arch/sparc/isa/formats/mem/blockmem.isa @@ -166,6 +166,8 @@ def template BlockMemDeclare {{ //Constructor %(class_name)s_0(ExtMachInst machInst); %(BasicExecDeclare)s + %(InitiateAccDeclare)s + %(CompleteAccDeclare)s }; class %(class_name)s_1 : public %(base_class)sMicro @@ -174,6 +176,8 @@ def template BlockMemDeclare {{ //Constructor %(class_name)s_1(ExtMachInst machInst); %(BasicExecDeclare)s + %(InitiateAccDeclare)s + %(CompleteAccDeclare)s }; class %(class_name)s_2 : public %(base_class)sMicro @@ -182,6 +186,8 @@ def template BlockMemDeclare {{ //Constructor %(class_name)s_2(ExtMachInst machInst); %(BasicExecDeclare)s + %(InitiateAccDeclare)s + %(CompleteAccDeclare)s }; class %(class_name)s_3 : public %(base_class)sMicro @@ -190,6 +196,8 @@ def template BlockMemDeclare {{ //Constructor %(class_name)s_3(ExtMachInst machInst); %(BasicExecDeclare)s + %(InitiateAccDeclare)s + %(CompleteAccDeclare)s }; class %(class_name)s_4 : public %(base_class)sMicro @@ -198,6 +206,8 @@ def template BlockMemDeclare {{ //Constructor %(class_name)s_4(ExtMachInst machInst); %(BasicExecDeclare)s + %(InitiateAccDeclare)s + %(CompleteAccDeclare)s }; class %(class_name)s_5 : public %(base_class)sMicro @@ -206,6 +216,8 @@ def template BlockMemDeclare {{ //Constructor %(class_name)s_5(ExtMachInst machInst); %(BasicExecDeclare)s + %(InitiateAccDeclare)s + %(CompleteAccDeclare)s }; class %(class_name)s_6 : public %(base_class)sMicro @@ -214,6 +226,8 @@ def template BlockMemDeclare {{ //Constructor %(class_name)s_6(ExtMachInst machInst); %(BasicExecDeclare)s + %(InitiateAccDeclare)s + %(CompleteAccDeclare)s }; class %(class_name)s_7 : public %(base_class)sMicro @@ -222,6 +236,8 @@ def template BlockMemDeclare {{ //Constructor %(class_name)s_7(ExtMachInst machInst); %(BasicExecDeclare)s + %(InitiateAccDeclare)s + %(CompleteAccDeclare)s }; }; }}; @@ -255,72 +271,12 @@ def template BlockMemMicroConstructor {{ } }}; -def template MicroLoadExecute {{ - Fault %(class_name)s::%(class_name)s_%(micro_pc)s::execute( - %(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const - { - Fault fault = NoFault; - Addr EA; - %(op_decl)s; - %(op_rd)s; - %(ea_code)s; - %(fault_check)s; - DPRINTF(Sparc, "The address is 0x%x\n", EA); - xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0); - %(code)s; - - if(fault == NoFault) - { - //Write the resulting state to the execution context - %(op_wb)s; - } - - return fault; - } -}}; - -def template MicroStoreExecute {{ - Fault %(class_name)s::%(class_name)s_%(micro_pc)s::execute( - %(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const - { - Fault fault = NoFault; - uint64_t write_result = 0; - Addr EA; - %(op_decl)s; - %(op_rd)s; - %(ea_code)s; - %(fault_check)s; - DPRINTF(Sparc, "The address is 0x%x\n", EA); - %(code)s; - - if(fault == NoFault) - { - xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result); - //Write the resulting state to the execution context - %(op_wb)s; - } - - return fault; - } -}}; - let {{ - def doBlockMemFormat(code, execute, name, Name, opt_flags): + def doBlockMemFormat(code, faultCode, execute, name, Name, opt_flags): # XXX Need to take care of pstate.hpriv as well. The lower ASIs # are split into ones that are available in priv and hpriv, and # those that are only available in hpriv - faultCheck = '''if(bits(Pstate,2,2) == 0 && (EXT_ASI & 0x80) == 0) - return new PrivilegedAction; - if(AsiIsAsIfUser((ASI)EXT_ASI) && !bits(Pstate,2,2)) - return new PrivilegedAction; - //The LSB can be zero, since it's really the MSB in doubles - //and quads - if(RD & 0xe) - return new IllegalInstruction; - if(EA & 0x3f) - return new MemAddressNotAligned; - ''' addrCalcReg = 'EA = Rs1 + Rs2 + offset;' addrCalcImm = 'EA = Rs1 + imm + offset;' iop = InstObjParams(name, Name, 'BlockMem', code, opt_flags) @@ -330,39 +286,52 @@ let {{ decode_block = ROrImmDecode.subst(iop) matcher = re.compile(r'Frd_N') exec_output = '' - for microPC in range(8): + for microPc in range(8): flag_code = '' - if (microPC == 7): + if (microPc == 7): flag_code = "flags[IsLastMicroOp] = true;" - pcedCode = matcher.sub("Frd_%d" % microPC, code) + pcedCode = matcher.sub("Frd_%d" % microPc, code) iop = InstObjParams(name, Name, 'BlockMem', pcedCode, opt_flags, {"ea_code": addrCalcReg, - "fault_check": faultCheck, "micro_pc": microPC, + "fault_check": faultCode, "micro_pc": microPc, "set_flags": flag_code}) iop_imm = InstObjParams(name, Name + 'Imm', 'BlockMemImm', pcedCode, opt_flags, {"ea_code": addrCalcImm, - "fault_check": faultCheck, "micro_pc": microPC, + "fault_check": faultCode, "micro_pc": microPc, "set_flags": flag_code}) - exec_output += execute.subst(iop) - exec_output += execute.subst(iop_imm) decoder_output += BlockMemMicroConstructor.subst(iop) decoder_output += BlockMemMicroConstructor.subst(iop_imm) - faultCheck = '' + exec_output += doSplitExecute( + pcedCode, addrCalcReg, addrCalcImm, execute, faultCode, + makeMicroName(name, microPc), + makeMicroName(name + "Imm", microPc), + makeMicroName(Name, microPc), + makeMicroName(Name + "Imm", microPc), + opt_flags); + faultCode = '' return (header_output, decoder_output, exec_output, decode_block) }}; def format BlockLoad(code, *opt_flags) {{ + # We need to make sure to check the highest priority fault last. + # That way, if other faults have been detected, they'll be overwritten + # rather than the other way around. + faultCode = AlternateASIPrivFaultCheck + BlockAlignmentFaultCheck (header_output, decoder_output, exec_output, - decode_block) = doBlockMemFormat(code, MicroLoadExecute, - name, Name, opt_flags) + decode_block) = doBlockMemFormat(code, faultCode, + LoadExecute, name, Name, opt_flags) }}; def format BlockStore(code, *opt_flags) {{ + # We need to make sure to check the highest priority fault last. + # That way, if other faults have been detected, they'll be overwritten + # rather than the other way around. + faultCode = AlternateASIPrivFaultCheck + BlockAlignmentFaultCheck (header_output, decoder_output, exec_output, - decode_block) = doBlockMemFormat(code, MicroStoreExecute, - name, Name, opt_flags) + decode_block) = doBlockMemFormat(code, faultCode, + StoreExecute, name, Name, opt_flags) }}; diff --git a/src/arch/sparc/isa/formats/mem/util.isa b/src/arch/sparc/isa/formats/mem/util.isa index 296ae1888..241a25d17 100644 --- a/src/arch/sparc/isa/formats/mem/util.isa +++ b/src/arch/sparc/isa/formats/mem/util.isa @@ -42,11 +42,17 @@ def template LoadExecute {{ Addr EA; %(op_decl)s; %(op_rd)s; - %(priv_check)s; %(ea_code)s; DPRINTF(Sparc, "The address is 0x%x\n", EA); - fault = xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0); - %(code)s; + %(fault_check)s; + if(fault == NoFault) + { + fault = xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0); + } + if(fault == NoFault) + { + %(code)s; + } if(fault == NoFault) { //Write the resulting state to the execution context @@ -64,9 +70,12 @@ def template LoadExecute {{ uint%(mem_acc_size)s_t Mem; %(ea_decl)s; %(ea_rd)s; - %(priv_check)s; %(ea_code)s; - fault = xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0); + %(fault_check)s; + if(fault == NoFault) + { + fault = xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0); + } return fault; } @@ -96,11 +105,13 @@ def template StoreExecute {{ Addr EA; %(op_decl)s; %(op_rd)s; - %(priv_check)s; %(ea_code)s; DPRINTF(Sparc, "The address is 0x%x\n", EA); - %(code)s; - + %(fault_check)s; + if(fault == NoFault) + { + %(code)s; + } if(fault == NoFault) { fault = xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result); @@ -122,10 +133,13 @@ def template StoreExecute {{ Addr EA; %(op_decl)s; %(op_rd)s; - %(priv_check)s; %(ea_code)s; DPRINTF(Sparc, "The address is 0x%x\n", EA); - %(code)s; + %(fault_check)s; + if(fault == NoFault) + { + %(code)s; + } if(fault == NoFault) { fault = xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result); @@ -155,23 +169,52 @@ def template CompleteAccDeclare {{ Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const; }}; +//Here are some code snippets which check for various fault conditions +let {{ + # The LSB can be zero, since it's really the MSB in doubles and quads + # and we're dealing with doubles + BlockAlignmentFaultCheck = ''' + if(RD & 0xe) + fault = new IllegalInstruction; + else if(EA & 0x3f) + fault = new MemAddressNotAligned; + ''' + # XXX Need to take care of pstate.hpriv as well. The lower ASIs + # are split into ones that are available in priv and hpriv, and + # those that are only available in hpriv + AlternateASIPrivFaultCheck = ''' + if(bits(Pstate,2,2) == 0 && (EXT_ASI & 0x80) == 0) + fault = new PrivilegedAction; + else if(AsiIsAsIfUser((ASI)EXT_ASI) && !bits(Pstate,2,2)) + fault = new PrivilegedAction; + ''' + +}}; + +//A simple function to generate the name of the macro op of a certain +//instruction at a certain micropc +let {{ + def makeMicroName(name, microPc): + return name + "::" + name + "_" + str(microPc) +}}; + //This function properly generates the execute functions for one of the //templates above. This is needed because in one case, ea computation, -//privelege checks and the actual code all occur in the same function, +//fault checks and the actual code all occur in the same function, //and in the other they're distributed across two. Also note that for //execute functions, the name of the base class doesn't matter. let {{ def doSplitExecute(code, eaRegCode, eaImmCode, execute, - priv, nameReg, nameImm, NameReg, NameImm, opt_flags): + faultCode, nameReg, nameImm, NameReg, NameImm, opt_flags): codeIop = InstObjParams(nameReg, NameReg, '', code, opt_flags) executeCode = '' for (eaCode, name, Name) in ( (eaRegCode, nameReg, NameReg), (eaImmCode, nameImm, NameImm)): eaIop = InstObjParams(name, Name, '', eaCode, - opt_flags, {"priv_check": priv}) + opt_flags, {"fault_check": faultCode}) iop = InstObjParams(name, Name, '', code, opt_flags, - {"priv_check": priv, "ea_code" : eaCode}) + {"fault_check": faultCode, "ea_code" : eaCode}) (iop.ea_decl, iop.ea_rd, iop.ea_wb) = (eaIop.op_decl, eaIop.op_rd, eaIop.op_wb) -- cgit v1.2.3