ruby: Make SLICC-generated objects SimObjects.
authorSteve Reinhardt <steve.reinhardt@amd.com>
Sat, 30 Jan 2010 04:29:17 +0000 (20:29 -0800)
committerSteve Reinhardt <steve.reinhardt@amd.com>
Sat, 30 Jan 2010 04:29:17 +0000 (20:29 -0800)
Also add SLICC support for state-machine parameter defaults
(passed through to Python as SimObject Param defaults).

src/mem/protocol/MOESI_hammer-cache.sm
src/mem/protocol/MOESI_hammer-dir.sm
src/mem/protocol/MOESI_hammer-dma.sm
src/mem/protocol/SConscript
src/mem/ruby/slicc_interface/AbstractController.hh
src/mem/slicc/ast/FormalParamAST.py
src/mem/slicc/ast/MachineAST.py
src/mem/slicc/parser.py
src/mem/slicc/symbols/StateMachine.py
src/mem/slicc/symbols/SymbolTable.py
src/mem/slicc/symbols/Type.py

index 3b224080093bfd4769bc0b72f21872fdf43da4cf..afe146880a1c9bae580676383035fcb926d5bd82 100644 (file)
@@ -34,8 +34,8 @@
  */
 
 machine(L1Cache, "AMD Hammer-like protocol") 
-: int cache_response_latency,
-  int issue_latency
+: int cache_response_latency = 12,
+  int issue_latency = 2
 {
 
   // NETWORK BUFFERS
index b9b001e401d8a97251aaa2b07b26d3f8eb7d3036..767d271f975da207fdc93f3d42599acae1a6cadb 100644 (file)
@@ -34,7 +34,7 @@
  */
 
 machine(Directory, "AMD Hammer-like protocol") 
-: int memory_controller_latency
+: int memory_controller_latency = 12
 {
 
   MessageBuffer forwardFromDir, network="To", virtual_network="2", ordered="false";
index b217923a4bc3dc2a38b58283b9d77a9e84fdab6d..079485a0580b4dbe7c8a48f78666a0e4cae93b43 100644 (file)
@@ -28,7 +28,7 @@
 
 
 machine(DMA, "DMA Controller") 
-: int request_latency
+: int request_latency = 6
 {
 
   MessageBuffer responseFromDir, network="From", virtual_network="4", ordered="true", no_vector="true";
index cd9920d225eb3778242ff325e92a4f10f793dd28..453b3711952db97f007ea0c954774a2652f41322 100644 (file)
@@ -70,6 +70,25 @@ def slicc_emitter(target, source, env):
         print "    %s" % name
 
     target.extend(sorted(slicc.files()))
+    pdir = str(protocol_dir)
+    hdir = str(html_dir)
+
+    if not isdir(pdir):
+        os.mkdir(pdir)
+    if not isdir(hdir):
+        os.mkdir(hdir)
+
+    print "SLICC Generator pass 1..."
+    slicc.findMachines()
+
+    print "SLICC Generator pass 2..."
+    slicc.generate()
+
+    print "SLICC writing C++ files..."
+    slicc.writeCodeFiles(pdir)
+
+    print "SLICC writing HTML files..."
+    slicc.writeHTMLFiles(hdir)
     return target, source
 
 def slicc_action(target, source, env):
@@ -108,5 +127,10 @@ env.Append(BUILDERS={'SLICC' : slicc_builder})
 nodes = env.SLICC([], [ Value(protocol) ] + sources)
 env.Depends(nodes, slicc_depends)
 
-for f in sorted(s for s in nodes if str(s).endswith('.cc')):
-    Source(f)
+for f in nodes:
+    s = str(f)
+    if s.endswith('.cc'):
+        Source(f)
+    elif s.endswith('.py'):
+        SimObject(f)
+
index 28c8a103a0b85553d89de287c71a3b5d1c1220c2..bca88e01cb417df7123a38490c3a2fec89bdfce1 100644 (file)
@@ -16,7 +16,6 @@ class AbstractController : public SimObject, public Consumer {
 public:
     typedef RubyControllerParams Params;
     AbstractController(const Params *p) : SimObject(p) {}
-  virtual void init(Network* net_ptr, const vector<string> & argv) = 0;
 
   // returns the number of controllers created of the specific subtype
   //  virtual int getNumberOfControllers() const = 0;
index b169cbb1c1fe9ee1f905ab6bcfbe7242546ea4a3..b821dc19752848b6dbf48c44c72a6035f6083f0c 100644 (file)
@@ -29,10 +29,11 @@ from slicc.ast.AST import AST
 from slicc.symbols import Var
 
 class FormalParamAST(AST):
-    def __init__(self, slicc, type_ast, ident):
+    def __init__(self, slicc, type_ast, ident, default = None):
         super(FormalParamAST, self).__init__(slicc)
         self.type_ast = type_ast
         self.ident = ident
+        self.default = default
 
     def __repr__(self):
         return "[FormalParamAST: %s]" % self.ident
index ee75b6d6afa551ff7554d0362c350eeaf253df46..0fc79c7102004c514de3e921f85cab7a2098e6e6 100644 (file)
@@ -43,6 +43,7 @@ class MachineAST(DeclAST):
     def files(self, parent=None):
         s = set(('%s_Controller.cc' % self.ident,
                  '%s_Controller.hh' % self.ident,
+                 '%s_Controller.py' % self.ident,
                  '%s_Profiler.cc' % self.ident,
                  '%s_Profiler.hh' % self.ident,
                  '%s_Transitions.cc' % self.ident,
index 226106678d2ae410e31397b93dd69aca151c4f3a..891f229734c64fd97b8c8708356ed1c293c30158 100644 (file)
@@ -115,8 +115,6 @@ class SLICC(Grammar):
 
     def files(self):
         f = set([
-            'ControllerFactory.cc',
-            'ControllerFactory.hh',
             'MachineType.cc',
             'MachineType.hh',
             'Types.hh' ])
@@ -418,6 +416,10 @@ class SLICC(Grammar):
         "param : type ident"
         p[0] = ast.FormalParamAST(self, p[1], p[2])
 
+    def p_param__default(self, p):
+        "param : type ident '=' NUMBER"
+        p[0] = ast.FormalParamAST(self, p[1], p[2], p[4])
+
     # Idents and lists
     def p_idents__braced(self, p):
         "idents : '{' identx '}'"
index 73c3fe7200dcfca6d25aaa49e8da3cd9739e6135..0f32cebf6cf4c7cd3b684b8fc9f59324eee8f5fb 100644 (file)
@@ -124,6 +124,7 @@ class StateMachine(Symbol):
         self.table = table
 
     def writeCodeFiles(self, path):
+        self.printControllerPython(path)
         self.printControllerHH(path)
         self.printControllerCC(path)
         self.printCSwitch(path)
@@ -134,6 +135,29 @@ class StateMachine(Symbol):
         for func in self.functions:
             func.writeCodeFiles(path)
 
+    def printControllerPython(self, path):
+        code = code_formatter()
+        ident = self.ident
+        py_ident = "%s_Controller" % ident
+        c_ident = "%s_Controller" % self.ident
+        code('''
+from m5.params import *
+from m5.SimObject import SimObject
+from Controller import RubyController
+
+class $py_ident(RubyController):
+    type = '$py_ident'
+''')
+        code.indent()
+        for param in self.config_parameters:
+            dflt_str = ''
+            if param.default is not None:
+                dflt_str = str(param.default) + ', '
+            code('${{param.name}} = Param.Int(${dflt_str}"")')
+        code.dedent()
+        code.write(path, '%s.py' % py_ident)
+        
+
     def printControllerHH(self, path):
         '''Output the method declarations for the class declaration'''
         code = code_formatter()
@@ -152,6 +176,8 @@ class StateMachine(Symbol):
 #ifndef ${ident}_CONTROLLER_H
 #define ${ident}_CONTROLLER_H
 
+#include "params/$c_ident.hh"
+
 #include "mem/ruby/common/Global.hh"
 #include "mem/ruby/common/Consumer.hh"
 #include "mem/ruby/slicc_interface/AbstractController.hh"
@@ -174,9 +200,10 @@ class $c_ident : public AbstractController {
 #ifdef CHECK_COHERENCE
 #endif /* CHECK_COHERENCE */
 public:
-    $c_ident(const string & name);
+    typedef ${c_ident}Params Params;
+    $c_ident(const Params *p);
     static int getNumControllers();
-    void init(Network* net_ptr, const vector<string> & argv);
+    void init();
     MessageBuffer* getMandatoryQueue() const;
     const int & getVersion() const;
     const string toString() const;
@@ -278,16 +305,30 @@ static int m_num_controllers;
             seen_types.add(var.type.ident)
 
         code('''
+$c_ident *
+${c_ident}Params::create()
+{
+    return new $c_ident(this);
+}
+
+
 int $c_ident::m_num_controllers = 0;
 
 stringstream ${ident}_transitionComment;
 #define APPEND_TRANSITION_COMMENT(str) (${ident}_transitionComment << str)
 /** \\brief constructor */
-$c_ident::$c_ident(const string &name)
-    : m_name(name)
+$c_ident::$c_ident(const Params *p)
+    : AbstractController(p)
 {
+    m_version = p->version;
+    m_transitions_per_cycle = p->transitions_per_cycle;
+    m_buffer_size = p->buffer_size;
+    m_recycle_latency = p->recycle_latency;
+    m_number_of_TBEs = p->number_of_TBEs;
 ''')
         code.indent()
+        for param in self.config_parameters:
+            code('m_${{param.name}} = p->${{param.name}};')
 
         code('m_num_controllers++;')
         for var in self.objects:
@@ -298,44 +339,10 @@ $c_ident::$c_ident(const string &name)
         code('''
 }
 
-void $c_ident::init(Network *net_ptr, const vector<string> &argv)
+void $c_ident::init()
 {
-    for (size_t i = 0; i < argv.size(); i += 2) {
-        if (argv[i] == "version")
-            m_version = atoi(argv[i+1].c_str());
-        else if (argv[i] == "transitions_per_cycle")
-            m_transitions_per_cycle = atoi(argv[i+1].c_str());
-        else if (argv[i] == "buffer_size")
-            m_buffer_size = atoi(argv[i+1].c_str());
-        else if (argv[i] == "recycle_latency")
-            m_recycle_latency = atoi(argv[i+1].c_str());
-        else if (argv[i] == "number_of_TBEs")
-            m_number_of_TBEs = atoi(argv[i+1].c_str());
-''')
-
-        code.indent()
-        code.indent()
-        for param in self.config_parameters:
-            code('else if (argv[i] == "${{param.name}}")')
-            if param.type_ast.type.ident == "int":
-                code('    m_${{param.name}} = atoi(argv[i+1].c_str());')
-            elif param.type_ast.type.ident == "bool":
-                code('    m_${{param.name}} = string_to_bool(argv[i+1]);')
-            else:
-                self.error("only int and bool parameters are "\
-                           "currently supported")
-        code.dedent()
-        code.dedent()
-        code('''
-    }
-
-    m_net_ptr = net_ptr;
     m_machineID.type = MachineType_${ident};
     m_machineID.num = m_version;
-    for (size_t i = 0; i < argv.size(); i += 2) {
-        if (argv[i] != "version")
-            m_cfg[argv[i]] = argv[i+1];
-    }
 
     // Objects
     s_profiler.setVersion(m_version);
index 6b1bf13e63c87691353195b4b63e6b834a880d18..deb971eb9b2d68838f43aa807f4f849ab47437ef 100644 (file)
@@ -133,63 +133,6 @@ class SymbolTable(object):
         for symbol in self.sym_vec:
             symbol.writeCodeFiles(path)
 
-        self.writeControllerFactory(path)
-
-    def writeControllerFactory(self, path):
-        code = code_formatter()
-
-        code('''
-/** \\file ControllerFactory.hh
- * Auto generatred C++ code started by $__file__:$__line__
- */
-
-#ifndef CONTROLLERFACTORY_H
-#define CONTROLLERFACTORY_H
-
-#include <string>
-class Network;
-class AbstractController;
-
-class ControllerFactory {
-  public:
-    static AbstractController *createController(const std::string &controller_type, const std::string &name);
-};
-#endif // CONTROLLERFACTORY_H''')
-        code.write(path, "ControllerFactory.hh")
-
-        code = code_formatter()
-        code('''
-/** \\file ControllerFactory.cc
- * Auto generatred C++ code started by $__file__:$__line__
- */
-
-#include "mem/protocol/ControllerFactory.hh"
-#include "mem/ruby/slicc_interface/AbstractController.hh"
-#include "mem/protocol/MachineType.hh"
-''')
-
-        controller_types = []
-        for symbol in self.getAllType(StateMachine):
-            code('#include "mem/protocol/${{symbol.ident}}_Controller.hh"')
-            controller_types.append(symbol.ident)
-
-        code('''
-AbstractController *ControllerFactory::createController(const std::string &controller_type, const std::string &name) {
-''')
-
-        for ct in controller_types:
-            code('''
-    if (controller_type == "$ct")
-        return new ${ct}_Controller(name);
-''')
-
-        code('''
-    assert(0); // invalid controller type
-    return NULL;
-}
-''')
-        code.write(path, "ControllerFactory.cc")
-
     def writeHTMLFiles(self, path):
         machines = list(self.getAllType(StateMachine))
         if len(machines) > 1:
index bafc6ea9eed891ed9910498d65cee5e24d22c834..fc45c59df97a5955c168c359ecfa8e8d78e12eb6 100644 (file)
@@ -478,7 +478,6 @@ ostream& operator<<(ostream& out, const ${{self.c_ident}}& obj);
 ''')
 
         if self.isMachineType:
-            code('#include "mem/protocol/ControllerFactory.hh"')
             for enum in self.enums.itervalues():
                 code('#include "mem/protocol/${{enum.ident}}_Controller.hh"')