ruby: Make SLICC-generated objects SimObjects.
Also add SLICC support for state-machine parameter defaults (passed through to Python as SimObject Param defaults).
This commit is contained in:
parent
98c94cfe3c
commit
c6f1d959be
|
@ -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
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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')):
|
||||
for f in nodes:
|
||||
s = str(f)
|
||||
if s.endswith('.cc'):
|
||||
Source(f)
|
||||
elif s.endswith('.py'):
|
||||
SimObject(f)
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 '}'"
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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"')
|
||||
|
||||
|
|
Loading…
Reference in a new issue