Add support for CPU models to execute the effective
authorSteve Reinhardt <stever@eecs.umich.edu>
Fri, 4 Feb 2005 01:47:11 +0000 (20:47 -0500)
committerSteve Reinhardt <stever@eecs.umich.edu>
Fri, 4 Feb 2005 01:47:11 +0000 (20:47 -0500)
address calculation and memory access portions separately.
Not currently used by any CPU models, but Kevin says he needs this.

Also clean up handling of execution tracing for memory accesses
(move it all into isa_desc and out of CPU models).

Got rid of some ancient unused code too.

arch/alpha/isa_desc:
    Add execute() methods to EAComp and MemAcc portions of memory
    access instructions, to allow CPU models to execute the effective
    address calculation and memory access portions separately.

    Requires the execution context to remember the effective address
    across the two invocations.  Added setEA() and getEA() methods to
    execution context to support this.  A model that does not use the
    split execution model can panic if these methods are called.

    Also added hook to call traceData->setAddr() after EA computation
    on any load or store operation.
arch/isa_parser.py:
    Call traceData->setData() on memory writes (stores).
cpu/simple_cpu/simple_cpu.cc:
    Get rid of unused code.
cpu/simple_cpu/simple_cpu.hh:
    Add (non-functional) setEA() and getEA() methods for new
    split memory access execution support.

--HG--
extra : convert_revision : bc2d2c758c4ca753812b9fa81f21038e55929ff0

arch/alpha/isa_desc
arch/isa_parser.py
cpu/simple_cpu/simple_cpu.cc
cpu/simple_cpu/simple_cpu.hh

index 5154d78d197e8cf69262809cf4dbff9275876d25..5602a6ba685438b048c95089fdc01ec7484c2395 100644 (file)
@@ -790,48 +790,14 @@ output header {{
       protected:
        /// Constructor
        MemoryNoDisp(const char *mnem, MachInst _machInst, OpClass __opClass,
-                    StaticInstPtr<AlphaISA> _eaCompPtr,
-                    StaticInstPtr<AlphaISA> _memAccPtr)
+                    StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr,
+                    StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr)
            : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr)
        {
        }
 
        std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
     };
-
-
-    /**
-     * Base class for "fake" effective-address computation
-     * instructions returnded by eaCompInst().
-     */
-    class EACompBase : public AlphaStaticInst
-    {
-      public:
-       /// Constructor
-       EACompBase(MachInst machInst)
-           : AlphaStaticInst("(eacomp)", machInst, IntAluOp)
-       {
-       }
-
-       %(BasicExecDeclare)s
-    };
-
-    /**
-     * Base class for "fake" memory-access instructions returnded by
-     * memAccInst().
-     */
-    class MemAccBase : public AlphaStaticInst
-    {
-      public:
-       /// Constructor
-       MemAccBase(MachInst machInst, OpClass __opClass)
-           : AlphaStaticInst("(memacc)", machInst, __opClass)
-       {
-       }
-
-       %(BasicExecDeclare)s
-    };
-
 }};
 
 
@@ -850,21 +816,6 @@ output decoder {{
     }
 }};
 
-output exec {{
-    Fault
-    EACompBase::execute(%(CPU_exec_context)s *, Trace::InstRecord *)
-    {
-       panic("attempt to execute eacomp");
-    }
-
-    Fault
-    MemAccBase::execute(%(CPU_exec_context)s *, Trace::InstRecord *)
-    {
-       panic("attempt to execute memacc");
-    }
-}};
-
-
 def format LoadAddress(code) {{
     iop = InstObjParams(name, Name, 'MemoryDisp32', CodeBlock(code))
     header_output = BasicDeclare.subst(iop)
@@ -885,21 +836,25 @@ def template LoadStoreDeclare {{
        /**
         * "Fake" effective address computation class for "%(mnemonic)s".
         */
-       class EAComp : public EACompBase
+       class EAComp : public %(base_class)s
        {
          public:
            /// Constructor
            EAComp(MachInst machInst);
+
+            %(BasicExecDeclare)s
        };
 
        /**
         * "Fake" memory access instruction class for "%(mnemonic)s".
         */
-       class MemAcc : public MemAccBase
+       class MemAcc : public %(base_class)s
        {
          public:
            /// Constructor
            MemAcc(MachInst machInst);
+
+            %(BasicExecDeclare)s
        };
 
       public:
@@ -912,14 +867,17 @@ def template LoadStoreDeclare {{
 }};
 
 def template LoadStoreConstructor {{
+    /** TODO: change op_class to AddrGenOp or something (requires
+     * creating new member of OpClass enum in op_class.hh, updating
+     * config files, etc.). */
     inline %(class_name)s::EAComp::EAComp(MachInst machInst)
-       : EACompBase(machInst)
+       : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp)
     {
        %(ea_constructor)s;
     }
 
     inline %(class_name)s::MemAcc::MemAcc(MachInst machInst)
-       : MemAccBase(machInst, %(op_class)s)
+       : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s)
     {
        %(memacc_constructor)s;
     }
@@ -932,6 +890,64 @@ def template LoadStoreConstructor {{
     }
 }};
 
+
+def template EACompExecute {{
+    Fault
+    %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc,
+                                  Trace::InstRecord *traceData)
+    {
+       Addr EA;
+       Fault fault = No_Fault;
+
+       %(fp_enable_check)s;
+       %(op_decl)s;
+       %(op_rd)s;
+       %(code)s;
+
+       if (fault == No_Fault) {
+           %(op_wb)s;
+           xc->setEA(EA);
+       }
+
+       return fault;
+    }
+}};
+
+def template MemAccExecute {{
+    Fault
+    %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
+                                  Trace::InstRecord *traceData)
+    {
+       Addr EA;
+       Fault fault = No_Fault;
+
+       %(fp_enable_check)s;
+       %(op_decl)s;
+       %(op_nonmem_rd)s;
+       EA = xc->getEA();
+       
+       if (fault == No_Fault) {
+           %(op_mem_rd)s;
+           %(code)s;
+       }
+
+       if (fault == No_Fault) {
+           %(op_mem_wb)s;
+       }
+
+       if (fault == No_Fault) {
+           %(postacc_code)s;
+       }
+
+       if (fault == No_Fault) {
+           %(op_nonmem_wb)s;
+       }
+
+       return fault;
+    }
+}};
+
+
 def template LoadStoreExecute {{
     Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
                                  Trace::InstRecord *traceData)
@@ -1022,18 +1038,33 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code = '',
 
     # Would be nice to autogenerate this list, but oh well.
     valid_mem_flags = ['LOCKED', 'NO_FAULT', 'EVICT_NEXT', 'PF_EXCLUSIVE']
-    inst_flags = []
-    mem_flags = []
-    for f in flags:
-       if f in valid_mem_flags:
-           mem_flags.append(f)
-        else:
-            inst_flags.append(f)
+    mem_flags =  [f for f in flags if f in valid_mem_flags]
+    inst_flags = [f for f in flags if f not in valid_mem_flags]
+
+    # add hook to get effective addresses into execution trace output.
+    ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n'
 
+    # generate code block objects
     ea_cblk = CodeBlock(ea_code)
     memacc_cblk = CodeBlock(memacc_code)
     postacc_cblk = CodeBlock(postacc_code)
 
+    # Some CPU models execute the memory operation as an atomic unit,
+    # while others want to separate them into an effective address
+    # computation and a memory access operation.  As a result, we need
+    # to generate three StaticInst objects.  Note that the latter two
+    # are nested inside the larger "atomic" one.
+
+    # generate InstObjParams for EAComp object
+    ea_iop = InstObjParams(name, Name, base_class, ea_cblk, inst_flags)
+    
+    # generate InstObjParams for MemAcc object
+    memacc_iop = InstObjParams(name, Name, base_class, memacc_cblk, inst_flags)
+    # in the split execution model, the MemAcc portion is responsible
+    # for the post-access code.
+    memacc_iop.postacc_code = postacc_cblk.code
+
+    # generate InstObjParams for unified execution
     cblk = CodeBlock(ea_code + memacc_code + postacc_code)
     iop = InstObjParams(name, Name, base_class, cblk, inst_flags)
 
@@ -1043,13 +1074,17 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code = '',
     iop.memacc_code = memacc_cblk.code
     iop.postacc_code = postacc_cblk.code
 
-    mem_flags = string.join(mem_flags, '|')
-    if mem_flags != '':
-        iop.constructor += '\n\tmemAccessFlags = ' + mem_flags + ';'
+    if mem_flags:
+        s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';'
+        iop.constructor += s
+        memacc_iop.constructor += s
 
     # (header_output, decoder_output, decode_block, exec_output)
     return (LoadStoreDeclare.subst(iop), LoadStoreConstructor.subst(iop),
-           decode_template.subst(iop), exec_template.subst(iop))
+           decode_template.subst(iop),
+            EACompExecute.subst(ea_iop)
+            + MemAccExecute.subst(memacc_iop)
+            + exec_template.subst(iop))
 }};
 
 
@@ -1460,8 +1495,8 @@ output header {{
 
        /// Constructor
        HwLoadStore(const char *mnem, MachInst _machInst, OpClass __opClass,
-                   StaticInstPtr<AlphaISA> _eaCompPtr,
-                   StaticInstPtr<AlphaISA> _memAccPtr);
+                   StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr,
+                   StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr);
 
        std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
     };
index c0b5131de103c64969b1adf1834e3ef44963aca2..18e4b0a4509fade75a2222492098d6fda679c217 100755 (executable)
@@ -1210,10 +1210,12 @@ class MemOperandTraits(OperandTraits):
     def makeWrite(self, op_desc):
         (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
         eff_type = 'uint%d_t' % size
-        return 'fault = xc->write((%s&)%s, EA, %s_flags,' \
-               ' &%s_write_result);\n' \
+        wb = 'fault = xc->write((%s&)%s, EA, %s_flags, &%s_write_result);\n' \
                % (eff_type, op_desc.munged_name, op_desc.base_name,
                   op_desc.base_name)
+        wb += 'if (traceData) { traceData->setData(%s); }' % \
+              op_desc.munged_name
+        return wb
 
 class NPCOperandTraits(OperandTraits):
     def makeConstructor(self, op_desc):
index e3cce28ae727a500a7dc097cacdb03d92618a73a..f292b25a5af469d1398501914a0deedcabbefdc2 100644 (file)
 
 using namespace std;
 
-template<typename T>
-void
-SimpleCPU::trace_data(T data) {
-    if (traceData) {
-        traceData->setData(data);
-    }
-}
-
 
 SimpleCPU::TickEvent::TickEvent(SimpleCPU *c)
     : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c), multiplier(1)
index 9b6e2423b50cfe11f4d1a6dd14d867b74810323b..a81d6365bc7dacd17f0a03da4c8851c667749c6d 100644 (file)
@@ -102,8 +102,7 @@ class SimpleCPU : public BaseCPU
 
   private:
     Trace::InstRecord *traceData;
-    template<typename T>
-    void trace_data(T data);
+
   public:
     //
     enum Status {
@@ -244,6 +243,11 @@ class SimpleCPU : public BaseCPU
     template <class T>
     Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
 
+    // These functions are only used in CPU models that split
+    // effective address computation from the actual memory access.
+    void setEA(Addr EA) { panic("SimpleCPU::setEA() not implemented\n"); }
+    Addr getEA()       { panic("SimpleCPU::getEA() not implemented\n"); }
+
     void prefetch(Addr addr, unsigned flags)
     {
         // need to do this...