From: Kevin Lim Date: Wed, 15 Feb 2006 18:05:21 +0000 (-0500) Subject: Gives separate methods for initiating and completing a memory access, which will... X-Git-Tag: m5_2.0_beta1~87^2~89^2~7^2~1 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=2d04f186748c70b3d8afecd39b94436c33848d93;p=gem5.git Gives separate methods for initiating and completing a memory access, which will be helpful for the merged memory model. arch/alpha/isa/mem.isa: Include methods that allow a memory operation to be split between the part that initiates the access, and the part that completes the access. In these functions the Mem variable is explicitly declared; in the default execute functions, the Mem variable is still handled through %(op_decl)s. arch/isa_parser.py: Include recording the type of the memory access variable so that it can be used if it needs to be explicitly declared in a template. Have memory operands consider themselves neither a source nor a destination to avoid including themselves on the op_src_decl list or the op_dest_decl list. Record op_src_decl and op_dest_decl lists to allow for declaring only source or destination operands. This is needed for the split memory access methods. --HG-- extra : convert_revision : f674f7a2f747ae40ba8c3a0933b0337c87ee0b6c --- diff --git a/arch/alpha/isa/mem.isa b/arch/alpha/isa/mem.isa index 45afd378c..1889daefc 100644 --- a/arch/alpha/isa/mem.isa +++ b/arch/alpha/isa/mem.isa @@ -164,9 +164,24 @@ def template LoadStoreDeclare {{ %(class_name)s(MachInst machInst); %(BasicExecDeclare)s + + %(InitiateAccDeclare)s + + %(CompleteAccDeclare)s }; }}; + +def template InitiateAccDeclare {{ + Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const; +}}; + + +def template CompleteAccDeclare {{ + Fault completeAcc(uint8_t *, %(CPU_exec_context)s *, Trace::InstRecord *) const; +}}; + + def template LoadStoreConstructor {{ /** TODO: change op_class to AddrGenOp or something (requires * creating new member of OpClass enum in op_class.hh, updating @@ -267,6 +282,54 @@ def template LoadExecute {{ }}; +def template LoadInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = No_Fault; + %(mem_acc_type)s Mem = 0; + + %(fp_enable_check)s; + %(op_src_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (fault == No_Fault) { + fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags); + } + + return fault; + } +}}; + + +def template LoadCompleteAcc {{ + Fault %(class_name)s::completeAcc(uint8_t *data, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = No_Fault; + %(mem_acc_type)s Mem = 0; + + %(fp_enable_check)s; + %(op_dest_decl)s; + + memcpy(&Mem, data, sizeof(Mem)); + + if (fault == No_Fault) { + %(memacc_code)s; + } + + if (fault == No_Fault) { + %(op_wb)s; + } + + return fault; + } +}}; + + def template StoreMemAccExecute {{ Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, @@ -339,6 +402,60 @@ def template StoreExecute {{ } }}; +def template StoreInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = No_Fault; + uint64_t write_result = 0; + %(mem_acc_type)s Mem = 0; + + %(fp_enable_check)s; + %(op_src_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (fault == No_Fault) { + %(memacc_code)s; + } + + if (fault == No_Fault) { + fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, + memAccessFlags, &write_result); + if (traceData) { traceData->setData(Mem); } + } + + return fault; + } +}}; + + +def template StoreCompleteAcc {{ + Fault %(class_name)s::completeAcc(uint8_t *data, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = No_Fault; + uint64_t write_result = 0; + + %(fp_enable_check)s; + %(op_dest_decl)s; + + memcpy(&write_result, data, sizeof(write_result)); + + if (fault == No_Fault) { + %(postacc_code)s; + } + + if (fault == No_Fault) { + %(op_wb)s; + } + + return fault; + } +}}; + def template MiscMemAccExecute {{ Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, @@ -380,6 +497,36 @@ def template MiscExecute {{ } }}; +def template MiscInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = No_Fault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (fault == No_Fault) { + %(memacc_code)s; + } + + return No_Fault; + } +}}; + + +def template MiscCompleteAcc {{ + Fault %(class_name)s::completeAcc(uint8_t *data, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + return No_Fault; + } +}}; + // load instructions use Ra as dest, so check for // Ra == 31 to detect nops def template LoadNopCheckDecode {{ @@ -455,13 +602,17 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, # select templates memAccExecTemplate = eval(exec_template_base + 'MemAccExecute') fullExecTemplate = eval(exec_template_base + 'Execute') + initiateAccTemplate = eval(exec_template_base + 'InitiateAcc') + completeAccTemplate = eval(exec_template_base + 'CompleteAcc') # (header_output, decoder_output, decode_block, exec_output) return (LoadStoreDeclare.subst(iop), LoadStoreConstructor.subst(iop), decode_template.subst(iop), EACompExecute.subst(ea_iop) + memAccExecTemplate.subst(memacc_iop) - + fullExecTemplate.subst(iop)) + + fullExecTemplate.subst(iop) + + initiateAccTemplate.subst(iop) + + completeAccTemplate.subst(iop)) }}; diff --git a/arch/isa_parser.py b/arch/isa_parser.py index 030bb5a7c..96d3e8438 100755 --- a/arch/isa_parser.py +++ b/arch/isa_parser.py @@ -1138,6 +1138,7 @@ class Operand(object): # template must be careful not to use it if it doesn't apply. if self.isMem(): self.mem_acc_size = self.makeAccSize() + self.mem_acc_type = self.ctype # Finalize additional fields (primarily code fields). This step # is done separately since some of these fields may depend on the @@ -1148,15 +1149,23 @@ class Operand(object): self.constructor = self.makeConstructor() self.op_decl = self.makeDecl() + if self.isMem(): + self.is_src = '' + self.is_dest = '' + if self.is_src: self.op_rd = self.makeRead() + self.op_src_decl = self.makeDecl() else: self.op_rd = '' + self.op_src_decl = '' if self.is_dest: self.op_wb = self.makeWrite() + self.op_dest_decl = self.makeDecl() else: self.op_wb = '' + self.op_dest_decl = '' def isMem(self): return 0 @@ -1589,6 +1598,14 @@ class CodeBlock: self.op_decl = self.operands.concatAttrStrings('op_decl') + is_src = lambda op: op.is_src + is_dest = lambda op: op.is_dest + + self.op_src_decl = \ + self.operands.concatSomeAttrStrings(is_src, 'op_src_decl') + self.op_dest_decl = \ + self.operands.concatSomeAttrStrings(is_dest, 'op_dest_decl') + self.op_rd = self.operands.concatAttrStrings('op_rd') self.op_wb = self.operands.concatAttrStrings('op_wb') @@ -1596,6 +1613,7 @@ class CodeBlock: if self.operands.memOperand: self.mem_acc_size = self.operands.memOperand.mem_acc_size + self.mem_acc_type = self.operands.memOperand.mem_acc_type # Make a basic guess on the operand class (function unit type). # These are good enough for most cases, and will be overridden