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
11 changed files with 83 additions and 107 deletions
|
@ -34,8 +34,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
machine(L1Cache, "AMD Hammer-like protocol")
|
machine(L1Cache, "AMD Hammer-like protocol")
|
||||||
: int cache_response_latency,
|
: int cache_response_latency = 12,
|
||||||
int issue_latency
|
int issue_latency = 2
|
||||||
{
|
{
|
||||||
|
|
||||||
// NETWORK BUFFERS
|
// NETWORK BUFFERS
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
machine(Directory, "AMD Hammer-like protocol")
|
machine(Directory, "AMD Hammer-like protocol")
|
||||||
: int memory_controller_latency
|
: int memory_controller_latency = 12
|
||||||
{
|
{
|
||||||
|
|
||||||
MessageBuffer forwardFromDir, network="To", virtual_network="2", ordered="false";
|
MessageBuffer forwardFromDir, network="To", virtual_network="2", ordered="false";
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
|
|
||||||
|
|
||||||
machine(DMA, "DMA Controller")
|
machine(DMA, "DMA Controller")
|
||||||
: int request_latency
|
: int request_latency = 6
|
||||||
{
|
{
|
||||||
|
|
||||||
MessageBuffer responseFromDir, network="From", virtual_network="4", ordered="true", no_vector="true";
|
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
|
print " %s" % name
|
||||||
|
|
||||||
target.extend(sorted(slicc.files()))
|
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
|
return target, source
|
||||||
|
|
||||||
def slicc_action(target, source, env):
|
def slicc_action(target, source, env):
|
||||||
|
@ -108,5 +127,10 @@ env.Append(BUILDERS={'SLICC' : slicc_builder})
|
||||||
nodes = env.SLICC([], [ Value(protocol) ] + sources)
|
nodes = env.SLICC([], [ Value(protocol) ] + sources)
|
||||||
env.Depends(nodes, slicc_depends)
|
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)
|
Source(f)
|
||||||
|
elif s.endswith('.py'):
|
||||||
|
SimObject(f)
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@ class AbstractController : public SimObject, public Consumer {
|
||||||
public:
|
public:
|
||||||
typedef RubyControllerParams Params;
|
typedef RubyControllerParams Params;
|
||||||
AbstractController(const Params *p) : SimObject(p) {}
|
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
|
// returns the number of controllers created of the specific subtype
|
||||||
// virtual int getNumberOfControllers() const = 0;
|
// virtual int getNumberOfControllers() const = 0;
|
||||||
|
|
|
@ -29,10 +29,11 @@ from slicc.ast.AST import AST
|
||||||
from slicc.symbols import Var
|
from slicc.symbols import Var
|
||||||
|
|
||||||
class FormalParamAST(AST):
|
class FormalParamAST(AST):
|
||||||
def __init__(self, slicc, type_ast, ident):
|
def __init__(self, slicc, type_ast, ident, default = None):
|
||||||
super(FormalParamAST, self).__init__(slicc)
|
super(FormalParamAST, self).__init__(slicc)
|
||||||
self.type_ast = type_ast
|
self.type_ast = type_ast
|
||||||
self.ident = ident
|
self.ident = ident
|
||||||
|
self.default = default
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "[FormalParamAST: %s]" % self.ident
|
return "[FormalParamAST: %s]" % self.ident
|
||||||
|
|
|
@ -43,6 +43,7 @@ class MachineAST(DeclAST):
|
||||||
def files(self, parent=None):
|
def files(self, parent=None):
|
||||||
s = set(('%s_Controller.cc' % self.ident,
|
s = set(('%s_Controller.cc' % self.ident,
|
||||||
'%s_Controller.hh' % self.ident,
|
'%s_Controller.hh' % self.ident,
|
||||||
|
'%s_Controller.py' % self.ident,
|
||||||
'%s_Profiler.cc' % self.ident,
|
'%s_Profiler.cc' % self.ident,
|
||||||
'%s_Profiler.hh' % self.ident,
|
'%s_Profiler.hh' % self.ident,
|
||||||
'%s_Transitions.cc' % self.ident,
|
'%s_Transitions.cc' % self.ident,
|
||||||
|
|
|
@ -115,8 +115,6 @@ class SLICC(Grammar):
|
||||||
|
|
||||||
def files(self):
|
def files(self):
|
||||||
f = set([
|
f = set([
|
||||||
'ControllerFactory.cc',
|
|
||||||
'ControllerFactory.hh',
|
|
||||||
'MachineType.cc',
|
'MachineType.cc',
|
||||||
'MachineType.hh',
|
'MachineType.hh',
|
||||||
'Types.hh' ])
|
'Types.hh' ])
|
||||||
|
@ -418,6 +416,10 @@ class SLICC(Grammar):
|
||||||
"param : type ident"
|
"param : type ident"
|
||||||
p[0] = ast.FormalParamAST(self, p[1], p[2])
|
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
|
# Idents and lists
|
||||||
def p_idents__braced(self, p):
|
def p_idents__braced(self, p):
|
||||||
"idents : '{' identx '}'"
|
"idents : '{' identx '}'"
|
||||||
|
|
|
@ -124,6 +124,7 @@ class StateMachine(Symbol):
|
||||||
self.table = table
|
self.table = table
|
||||||
|
|
||||||
def writeCodeFiles(self, path):
|
def writeCodeFiles(self, path):
|
||||||
|
self.printControllerPython(path)
|
||||||
self.printControllerHH(path)
|
self.printControllerHH(path)
|
||||||
self.printControllerCC(path)
|
self.printControllerCC(path)
|
||||||
self.printCSwitch(path)
|
self.printCSwitch(path)
|
||||||
|
@ -134,6 +135,29 @@ class StateMachine(Symbol):
|
||||||
for func in self.functions:
|
for func in self.functions:
|
||||||
func.writeCodeFiles(path)
|
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):
|
def printControllerHH(self, path):
|
||||||
'''Output the method declarations for the class declaration'''
|
'''Output the method declarations for the class declaration'''
|
||||||
code = code_formatter()
|
code = code_formatter()
|
||||||
|
@ -152,6 +176,8 @@ class StateMachine(Symbol):
|
||||||
#ifndef ${ident}_CONTROLLER_H
|
#ifndef ${ident}_CONTROLLER_H
|
||||||
#define ${ident}_CONTROLLER_H
|
#define ${ident}_CONTROLLER_H
|
||||||
|
|
||||||
|
#include "params/$c_ident.hh"
|
||||||
|
|
||||||
#include "mem/ruby/common/Global.hh"
|
#include "mem/ruby/common/Global.hh"
|
||||||
#include "mem/ruby/common/Consumer.hh"
|
#include "mem/ruby/common/Consumer.hh"
|
||||||
#include "mem/ruby/slicc_interface/AbstractController.hh"
|
#include "mem/ruby/slicc_interface/AbstractController.hh"
|
||||||
|
@ -174,9 +200,10 @@ class $c_ident : public AbstractController {
|
||||||
#ifdef CHECK_COHERENCE
|
#ifdef CHECK_COHERENCE
|
||||||
#endif /* CHECK_COHERENCE */
|
#endif /* CHECK_COHERENCE */
|
||||||
public:
|
public:
|
||||||
$c_ident(const string & name);
|
typedef ${c_ident}Params Params;
|
||||||
|
$c_ident(const Params *p);
|
||||||
static int getNumControllers();
|
static int getNumControllers();
|
||||||
void init(Network* net_ptr, const vector<string> & argv);
|
void init();
|
||||||
MessageBuffer* getMandatoryQueue() const;
|
MessageBuffer* getMandatoryQueue() const;
|
||||||
const int & getVersion() const;
|
const int & getVersion() const;
|
||||||
const string toString() const;
|
const string toString() const;
|
||||||
|
@ -278,16 +305,30 @@ static int m_num_controllers;
|
||||||
seen_types.add(var.type.ident)
|
seen_types.add(var.type.ident)
|
||||||
|
|
||||||
code('''
|
code('''
|
||||||
|
$c_ident *
|
||||||
|
${c_ident}Params::create()
|
||||||
|
{
|
||||||
|
return new $c_ident(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int $c_ident::m_num_controllers = 0;
|
int $c_ident::m_num_controllers = 0;
|
||||||
|
|
||||||
stringstream ${ident}_transitionComment;
|
stringstream ${ident}_transitionComment;
|
||||||
#define APPEND_TRANSITION_COMMENT(str) (${ident}_transitionComment << str)
|
#define APPEND_TRANSITION_COMMENT(str) (${ident}_transitionComment << str)
|
||||||
/** \\brief constructor */
|
/** \\brief constructor */
|
||||||
$c_ident::$c_ident(const string &name)
|
$c_ident::$c_ident(const Params *p)
|
||||||
: m_name(name)
|
: 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()
|
code.indent()
|
||||||
|
for param in self.config_parameters:
|
||||||
|
code('m_${{param.name}} = p->${{param.name}};')
|
||||||
|
|
||||||
code('m_num_controllers++;')
|
code('m_num_controllers++;')
|
||||||
for var in self.objects:
|
for var in self.objects:
|
||||||
|
@ -298,44 +339,10 @@ $c_ident::$c_ident(const string &name)
|
||||||
code('''
|
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.type = MachineType_${ident};
|
||||||
m_machineID.num = m_version;
|
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
|
// Objects
|
||||||
s_profiler.setVersion(m_version);
|
s_profiler.setVersion(m_version);
|
||||||
|
|
|
@ -133,63 +133,6 @@ class SymbolTable(object):
|
||||||
for symbol in self.sym_vec:
|
for symbol in self.sym_vec:
|
||||||
symbol.writeCodeFiles(path)
|
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):
|
def writeHTMLFiles(self, path):
|
||||||
machines = list(self.getAllType(StateMachine))
|
machines = list(self.getAllType(StateMachine))
|
||||||
if len(machines) > 1:
|
if len(machines) > 1:
|
||||||
|
|
|
@ -478,7 +478,6 @@ ostream& operator<<(ostream& out, const ${{self.c_ident}}& obj);
|
||||||
''')
|
''')
|
||||||
|
|
||||||
if self.isMachineType:
|
if self.isMachineType:
|
||||||
code('#include "mem/protocol/ControllerFactory.hh"')
|
|
||||||
for enum in self.enums.itervalues():
|
for enum in self.enums.itervalues():
|
||||||
code('#include "mem/protocol/${{enum.ident}}_Controller.hh"')
|
code('#include "mem/protocol/${{enum.ident}}_Controller.hh"')
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue