changeset 4207f9bfcceb in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=4207f9bfcceb
description:
        arch, cpu: Factor out the ExecContext into a proper base class

        We currently generate and compile one version of the ISA code per CPU
        model. This is obviously wasting a lot of resources at compile
        time. This changeset factors out the interface into a separate
        ExecContext class, which also serves as documentation for the
        interface between CPUs and the ISA code. While doing so, this
        changeset also fixes up interface inconsistencies between the
        different CPU models.

        The main argument for using one set of ISA code per CPU model has
        always been performance as this avoid indirect branches in the
        generated code. However, this argument does not hold water. Booting
        Linux on a simulated ARM system running in atomic mode
        (opt/10.linux-boot/realview-simple-atomic) is actually 2% faster
        (compiled using clang 3.4) after applying this patch. Additionally,
        compilation time is decreased by 35%.

diffstat:

 SConstruct                          |   12 +-
 src/arch/SConscript                 |   13 +-
 src/arch/arm/isa/includes.isa       |    1 +
 src/arch/isa_parser.py              |   22 ++-
 src/cpu/SConscript                  |   64 +--------
 src/cpu/base_dyn_inst.hh            |   43 +----
 src/cpu/checker/SConsopts           |    4 +-
 src/cpu/checker/cpu.hh              |   27 ++-
 src/cpu/exec_context.cc             |   40 +++++
 src/cpu/exec_context.hh             |  264 +++++++++++++++++++++++++++--------
 src/cpu/inorder/SConsopts           |    5 +-
 src/cpu/inorder/inorder_dyn_inst.cc |    5 +-
 src/cpu/inorder/inorder_dyn_inst.hh |   46 ++++-
 src/cpu/minor/SConsopts             |    5 +-
 src/cpu/minor/exec_context.hh       |   25 +-
 src/cpu/nocpu/SConsopts             |    2 +-
 src/cpu/o3/SConsopts                |    5 +-
 src/cpu/o3/dyn_inst.hh              |   15 +-
 src/cpu/ozone/SConsopts             |    8 +-
 src/cpu/simple/SConsopts            |   10 +-
 src/cpu/simple/base.hh              |   30 ++--
 src/cpu/simple_thread.cc            |   16 ++
 src/cpu/static_inst.hh              |   38 ++--
 23 files changed, 406 insertions(+), 294 deletions(-)

diffs (truncated from 1355 to 300 lines):

diff -r 98771a936b61 -r 4207f9bfcceb SConstruct
--- a/SConstruct        Wed Sep 03 07:42:21 2014 -0400
+++ b/SConstruct        Wed Sep 03 07:42:22 2014 -0400
@@ -1025,17 +1025,10 @@
 
     # Dict of available CPU model objects.  Accessible as CpuModel.dict.
     dict = {}
-    list = []
-    defaults = []
 
     # Constructor.  Automatically adds models to CpuModel.dict.
-    def __init__(self, name, filename, includes, strings, default=False):
+    def __init__(self, name, default=False):
         self.name = name           # name of model
-        self.filename = filename   # filename for output exec code
-        self.includes = includes   # include files needed in exec file
-        # The 'strings' dict holds all the per-CPU symbols we can
-        # substitute into templates etc.
-        self.strings = strings
 
         # This cpu is enabled by default
         self.default = default
@@ -1044,7 +1037,6 @@
         if name in CpuModel.dict:
             raise AttributeError, "CpuModel '%s' already registered" % name
         CpuModel.dict[name] = self
-        CpuModel.list.append(name)
 
 Export('CpuModel')
 
@@ -1086,7 +1078,7 @@
     EnumVariable('TARGET_ISA', 'Target ISA', 'alpha', all_isa_list),
     ListVariable('CPU_MODELS', 'CPU models',
                  sorted(n for n,m in CpuModel.dict.iteritems() if m.default),
-                 sorted(CpuModel.list)),
+                 sorted(CpuModel.dict.keys())),
     BoolVariable('EFENCE', 'Link with Electric Fence malloc debugger',
                  False),
     BoolVariable('SS_COMPATIBLE_FP',
diff -r 98771a936b61 -r 4207f9bfcceb src/arch/SConscript
--- a/src/arch/SConscript       Wed Sep 03 07:42:21 2014 -0400
+++ b/src/arch/SConscript       Wed Sep 03 07:42:22 2014 -0400
@@ -95,13 +95,11 @@
 # The emitter patches up the sources & targets to include the
 # autogenerated files as targets and isa parser itself as a source.
 def isa_desc_emitter(target, source, env):
-    cpu_models = list(env['CPU_MODELS'])
-    cpu_models.append('CheckerCPU')
-
     # List the isa parser as a source.
-    source += [ isa_parser ]
-    # Add in the CPU models.
-    source += [ Value(m) for m in cpu_models ]
+    source += [
+        isa_parser,
+        Value("ExecContext"),
+        ]
 
     # Specify different targets depending on if we're running the ISA
     # parser for its dependency information, or for the generated files.
@@ -137,8 +135,7 @@
 
     # Skip over the ISA description itself and the parser to the CPU models.
     models = [ s.get_contents() for s in source[2:] ]
-    cpu_models = [CpuModel.dict[cpu] for cpu in models]
-    parser = isa_parser.ISAParser(target[0].dir.abspath, cpu_models)
+    parser = isa_parser.ISAParser(target[0].dir.abspath)
     parser.parse_isa_desc(source[0].abspath)
 isa_desc_action = MakeAction(isa_desc_action_func, Transform("ISA DESC", 1))
 
diff -r 98771a936b61 -r 4207f9bfcceb src/arch/arm/isa/includes.isa
--- a/src/arch/arm/isa/includes.isa     Wed Sep 03 07:42:21 2014 -0400
+++ b/src/arch/arm/isa/includes.isa     Wed Sep 03 07:42:22 2014 -0400
@@ -90,6 +90,7 @@
 #include "arch/arm/utility.hh"
 #include "arch/generic/memhelpers.hh"
 #include "base/condcodes.hh"
+#include "cpu/base.hh"
 #include "sim/pseudo_inst.hh"
 #if defined(linux)
 #include <fenv.h>
diff -r 98771a936b61 -r 4207f9bfcceb src/arch/isa_parser.py
--- a/src/arch/isa_parser.py    Wed Sep 03 07:42:21 2014 -0400
+++ b/src/arch/isa_parser.py    Wed Sep 03 07:42:22 2014 -0400
@@ -1178,13 +1178,25 @@
 #
 
 class ISAParser(Grammar):
-    def __init__(self, output_dir, cpu_models):
+    class CpuModel(object):
+        def __init__(self, name, filename, includes, strings):
+            self.name = name
+            self.filename = filename
+            self.includes = includes
+            self.strings = strings
+
+    def __init__(self, output_dir):
         super(ISAParser, self).__init__()
         self.output_dir = output_dir
 
         self.filename = None # for output file watermarking/scaremongering
 
-        self.cpuModels = cpu_models
+        self.cpuModels = [
+            ISAParser.CpuModel('ExecContext',
+                               'generic_cpu_exec.cc',
+                               '#include "cpu/exec_context.hh"',
+                               { "CPU_exec_context" : "ExecContext" }),
+            ]
 
         # variable to hold templates
         self.templateMap = {}
@@ -2376,8 +2388,6 @@
             e.exit(self.fileNameStack)
 
 # Called as script: get args from command line.
-# Args are: <path to cpu_models.py> <isa desc file> <output dir> <cpu models>
+# Args are: <isa desc file> <output dir>
 if __name__ == '__main__':
-    execfile(sys.argv[1])  # read in CpuModel definitions
-    cpu_models = [CpuModel.dict[cpu] for cpu in sys.argv[4:]]
-    ISAParser(sys.argv[3], cpu_models).parse_isa_desc(sys.argv[2])
+    ISAParser(sys.argv[2]).parse_isa_desc(sys.argv[1])
diff -r 98771a936b61 -r 4207f9bfcceb src/cpu/SConscript
--- a/src/cpu/SConscript        Wed Sep 03 07:42:21 2014 -0400
+++ b/src/cpu/SConscript        Wed Sep 03 07:42:22 2014 -0400
@@ -35,71 +35,8 @@
     Source('intr_control_noisa.cc')
     Return()
 
-#################################################################
-#
-# Generate StaticInst execute() method signatures.
-#
-# There must be one signature for each CPU model compiled in.
-# Since the set of compiled-in models is flexible, we generate a
-# header containing the appropriate set of signatures on the fly.
-#
-#################################################################
-
-# Template for execute() signature.
-exec_sig_template = '''
-virtual Fault execute(%(type)s *xc, Trace::InstRecord *traceData) const = 0;
-virtual Fault eaComp(%(type)s *xc, Trace::InstRecord *traceData) const
-{ panic("eaComp not defined!"); M5_DUMMY_RETURN };
-virtual Fault initiateAcc(%(type)s *xc, Trace::InstRecord *traceData) const
-{ panic("initiateAcc not defined!"); M5_DUMMY_RETURN };
-virtual Fault completeAcc(Packet *pkt, %(type)s *xc,
-                          Trace::InstRecord *traceData) const
-{ panic("completeAcc not defined!"); M5_DUMMY_RETURN };
-'''
-
-mem_ini_sig_template = '''
-virtual Fault eaComp(%(type)s *xc, Trace::InstRecord *traceData) const
-{ panic("eaComp not defined!"); M5_DUMMY_RETURN };
-virtual Fault initiateAcc(%s *xc, Trace::InstRecord *traceData) const { 
panic("Not defined!"); M5_DUMMY_RETURN };
-'''
-
-mem_comp_sig_template = '''
-virtual Fault completeAcc(uint8_t *data, %s *xc, Trace::InstRecord *traceData) 
const { panic("Not defined!"); return NoFault; M5_DUMMY_RETURN };
-'''
-
-# Generate a temporary CPU list, including the CheckerCPU if
-# it's enabled.  This isn't used for anything else other than StaticInst
-# headers.
-temp_cpu_list = env['CPU_MODELS'][:]
-temp_cpu_list.append('CheckerCPU')
 SimObject('CheckerCPU.py')
 
-# Generate header.
-def gen_cpu_exec_signatures(target, source, env):
-    f = open(str(target[0]), 'w')
-    print >> f, '''
-#ifndef __CPU_STATIC_INST_EXEC_SIGS_HH__
-#define __CPU_STATIC_INST_EXEC_SIGS_HH__
-'''
-    for cpu in temp_cpu_list:
-        xc_type = CpuModel.dict[cpu].strings['CPU_exec_context']
-        print >> f, exec_sig_template % { 'type' : xc_type }
-    print >> f, '''
-#endif  // __CPU_STATIC_INST_EXEC_SIGS_HH__
-'''
-
-# Generate string that gets printed when header is rebuilt
-def gen_sigs_string(target, source, env):
-    return " [GENERATE] static_inst_exec_sigs.hh: " \
-           + ', '.join(temp_cpu_list)
-
-# Add command to generate header to environment.
-env.Command('static_inst_exec_sigs.hh', (),
-            Action(gen_cpu_exec_signatures, gen_sigs_string,
-                   varlist = temp_cpu_list))
-
-env.Depends('static_inst_exec_sigs.hh', Value(env['CPU_MODELS']))
-
 SimObject('BaseCPU.py')
 SimObject('FuncUnit.py')
 SimObject('ExeTracer.py')
@@ -112,6 +49,7 @@
 Source('base.cc')
 Source('cpuevent.cc')
 Source('exetrace.cc')
+Source('exec_context.cc')
 Source('func_unit.cc')
 Source('inteltrace.cc')
 Source('intr_control.cc')
diff -r 98771a936b61 -r 4207f9bfcceb src/cpu/base_dyn_inst.hh
--- a/src/cpu/base_dyn_inst.hh  Wed Sep 03 07:42:21 2014 -0400
+++ b/src/cpu/base_dyn_inst.hh  Wed Sep 03 07:42:22 2014 -0400
@@ -56,6 +56,7 @@
 #include "config/the_isa.hh"
 #include "cpu/checker/cpu.hh"
 #include "cpu/o3/comm.hh"
+#include "cpu/exec_context.hh"
 #include "cpu/exetrace.hh"
 #include "cpu/inst_seq.hh"
 #include "cpu/op_class.hh"
@@ -73,7 +74,7 @@
  */
 
 template <class Impl>
-class BaseDynInst : public RefCounted
+class BaseDynInst : public ExecContext, public RefCounted
 {
   public:
     // Typedef for the CPU.
@@ -82,10 +83,6 @@
 
     // Logical register index type.
     typedef TheISA::RegIndex RegIndex;
-    // Integer register type.
-    typedef TheISA::IntReg IntReg;
-    // Floating point register type.
-    typedef TheISA::FloatReg FloatReg;
 
     // The DynInstPtr type.
     typedef typename Impl::DynInstPtr DynInstPtr;
@@ -634,43 +631,25 @@
     }
 
     /** Records an integer register being set to a value. */
-    void setIntRegOperand(const StaticInst *si, int idx, uint64_t val)
+    void setIntRegOperand(const StaticInst *si, int idx, IntReg val)
     {
         setResult<uint64_t>(val);
     }
 
     /** Records a CC register being set to a value. */
-    void setCCRegOperand(const StaticInst *si, int idx, uint64_t val)
+    void setCCRegOperand(const StaticInst *si, int idx, CCReg val)
     {
         setResult<uint64_t>(val);
     }
 
     /** Records an fp register being set to a value. */
-    void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val,
-                            int width)
-    {
-        if (width == 32 || width == 64) {
-            setResult<double>(val);
-        } else {
-            panic("Unsupported width!");
-        }
-    }
-
-    /** Records an fp register being set to a value. */
     void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val)
     {
         setResult<double>(val);
     }
 
     /** Records an fp register being set to an integer value. */
-    void setFloatRegOperandBits(const StaticInst *si, int idx, uint64_t val,
-                                int width)
-    {
-        setResult<uint64_t>(val);
-    }
-
-    /** Records an fp register being set to an integer value. */
-    void setFloatRegOperandBits(const StaticInst *si, int idx, uint64_t val)
+    void setFloatRegOperandBits(const StaticInst *si, int idx, FloatRegBits 
val)
     {
         setResult<uint64_t>(val);
     }
@@ -802,10 +781,10 @@
     bool isSquashedInROB() const { return status[SquashedInROB]; }
 
     /** Read the PC state of this instruction. */
-    const TheISA::PCState pcState() const { return pc; }
+    TheISA::PCState pcState() const { return pc; }
 
     /** Set the PC state of this instruction. */
-    const void pcState(const TheISA::PCState &val) { pc = val; }
+    void pcState(const TheISA::PCState &val) { pc = val; }
 
     /** Read the PC of this instruction. */
     const Addr instAddr() const { return pc.instAddr(); }
@@ -844,10 +823,10 @@
 
   public:
_______________________________________________
gem5-dev mailing list
gem5-dev@gem5.org
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to