import slicc.generate.html as html
import re
-python_class_map = {"int": "Int",
+python_class_map = {
+ "int": "Int",
+ "uint32_t" : "UInt32",
"std::string": "String",
"bool": "Bool",
"CacheMemory": "RubyCache",
"Sequencer": "RubySequencer",
"DirectoryMemory": "RubyDirectoryMemory",
"MemoryControl": "MemoryControl",
- "DMASequencer": "DMASequencer"
- }
+ "DMASequencer": "DMASequencer",
+ "Prefetcher":"Prefetcher",
+ "Cycles":"Cycles",
+ }
class StateMachine(Symbol):
def __init__(self, symtab, ident, location, pairs, config_parameters):
super(StateMachine, self).__init__(symtab, ident, location, pairs)
self.table = None
+
+ # Data members in the State Machine that have been declared before
+ # the opening brace '{' of the machine. Note that these along with
+ # the members in self.objects form the entire set of data members.
self.config_parameters = config_parameters
+ self.prefetchers = []
+
for param in config_parameters:
if param.pointer:
- var = Var(symtab, param.name, location, param.type_ast.type,
- "(*m_%s_ptr)" % param.name, {}, self)
+ var = Var(symtab, param.ident, location, param.type_ast.type,
+ "(*m_%s_ptr)" % param.ident, {}, self)
else:
- var = Var(symtab, param.name, location, param.type_ast.type,
- "m_%s" % param.name, {}, self)
- self.symtab.registerSym(param.name, var)
+ var = Var(symtab, param.ident, location, param.type_ast.type,
+ "m_%s" % param.ident, {}, self)
+
+ self.symtab.registerSym(param.ident, var)
+
+ if str(param.type_ast.type) == "Prefetcher":
+ self.prefetchers.append(var)
self.states = orderdict()
self.events = orderdict()
self.transitions = []
self.in_ports = []
self.functions = []
+
+ # Data members in the State Machine that have been declared inside
+ # the {} machine. Note that these along with the config params
+ # form the entire set of data members of the machine.
self.objects = []
self.TBEType = None
self.EntryType = None
- self.message_buffer_names = []
-
def __repr__(self):
return "[StateMachine: %s]" % self.ident
self.functions.append(func)
def addObject(self, obj):
+ self.symtab.registerSym(str(obj), obj)
self.objects.append(obj)
def addType(self, type):
self.printControllerCC(path, includes)
self.printCSwitch(path)
self.printCWakeup(path, includes)
- self.printProfilerCC(path)
- self.printProfilerHH(path)
- self.printProfileDumperCC(path)
- self.printProfileDumperHH(path)
def printControllerPython(self, path):
code = self.symtab.codeFormatter()
ident = self.ident
+
py_ident = "%s_Controller" % ident
c_ident = "%s_Controller" % self.ident
+
code('''
from m5.params import *
from m5.SimObject import SimObject
class $py_ident(RubyController):
type = '$py_ident'
+ cxx_header = 'mem/protocol/${c_ident}.hh'
''')
code.indent()
for param in self.config_parameters:
dflt_str = ''
- if param.default is not None:
- dflt_str = str(param.default) + ', '
- if python_class_map.has_key(param.type_ast.type.c_ident):
+
+ if param.rvalue is not None:
+ dflt_str = str(param.rvalue.inline()) + ', '
+
+ if param.type_ast.type.c_ident == "MessageBuffer":
+ if param["network"] == "To":
+ code('${{param.ident}} = MasterPort(${dflt_str}"")')
+ else:
+ code('${{param.ident}} = SlavePort(${dflt_str}"")')
+
+ elif python_class_map.has_key(param.type_ast.type.c_ident):
python_type = python_class_map[param.type_ast.type.c_ident]
- code('${{param.name}} = Param.${{python_type}}(${dflt_str}"")')
+ code('${{param.ident}} = Param.${{python_type}}(${dflt_str}"")')
+
else:
self.error("Unknown c++ to python class conversion for c++ " \
"type: '%s'. Please update the python_class_map " \
ident = self.ident
c_ident = "%s_Controller" % self.ident
- self.message_buffer_names = []
-
code('''
/** \\file $c_ident.hh
*
#include <sstream>
#include <string>
-#include "mem/protocol/${ident}_ProfileDumper.hh"
-#include "mem/protocol/${ident}_Profiler.hh"
#include "mem/protocol/TransitionResult.hh"
#include "mem/protocol/Types.hh"
#include "mem/ruby/common/Consumer.hh"
for var in self.objects:
if var.type.ident not in seen_types and not var.type.isPrimitive:
code('#include "mem/protocol/${{var.type.c_ident}}.hh"')
- seen_types.add(var.type.ident)
+ seen_types.add(var.type.ident)
# for adding information to the protocol debug trace
code('''
class $c_ident : public AbstractController
{
-// the coherence checker needs to call isBlockExclusive() and isBlockShared()
-// making the Chip a friend class is an easy way to do this for now
-
-public:
+ public:
typedef ${c_ident}Params Params;
$c_ident(const Params *p);
static int getNumControllers();
void init();
+
MessageBuffer* getMandatoryQueue() const;
- const int & getVersion() const;
- const std::string toString() const;
- const std::string getName() const;
- void stallBuffer(MessageBuffer* buf, Address addr);
- void wakeUpBuffers(Address addr);
- void wakeUpAllBuffers();
- void initNetworkPtr(Network* net_ptr) { m_net_ptr = net_ptr; }
+ void setNetQueue(const std::string& name, MessageBuffer *b);
+
void print(std::ostream& out) const;
- void printConfig(std::ostream& out) const;
void wakeup();
- void printStats(std::ostream& out) const;
- void clearStats();
- void blockOnQueue(Address addr, MessageBuffer* port);
- void unblock(Address addr);
+ void resetStats();
+ void regStats();
+ void collateStats();
+
void recordCacheTrace(int cntrl, CacheRecorder* tr);
Sequencer* getSequencer() const;
+ bool functionalReadBuffers(PacketPtr&);
+ uint32_t functionalWriteBuffers(PacketPtr&);
+
+ void countTransition(${ident}_State state, ${ident}_Event event);
+ void possibleTransition(${ident}_State state, ${ident}_Event event);
+ uint64 getEventCount(${ident}_Event event);
+ bool isPossible(${ident}_State state, ${ident}_Event event);
+ uint64 getTransitionCount(${ident}_State state, ${ident}_Event event);
+
private:
''')
code('${{param.type_ast.type}} m_${{param.ident}};')
code('''
-int m_number_of_TBEs;
-
TransitionResult doTransition(${ident}_Event event,
''')
''')
code('''
- const Address& addr);
+ const Address addr);
TransitionResult doTransitionWorker(${ident}_Event event,
${ident}_State state,
code('''
const Address& addr);
-std::string m_name;
-int m_transitions_per_cycle;
-int m_buffer_size;
-int m_recycle_latency;
-std::map<std::string, std::string> m_cfg;
-NodeID m_version;
-Network* m_net_ptr;
-MachineID m_machineID;
-bool m_is_blocking;
-std::map<Address, MessageBuffer*> m_block_map;
-typedef std::vector<MessageBuffer*> MsgVecType;
-typedef std::map< Address, MsgVecType* > WaitingBufType;
-WaitingBufType m_waiting_buffers;
-int m_max_in_port_rank;
-int m_cur_in_port_rank;
-static ${ident}_ProfileDumper s_profileDumper;
-${ident}_Profiler m_profiler;
+int m_counters[${ident}_State_NUM][${ident}_Event_NUM];
+int m_event_counters[${ident}_Event_NUM];
+bool m_possible[${ident}_State_NUM][${ident}_Event_NUM];
+
+static std::vector<Stats::Vector *> eventVec;
+static std::vector<std::vector<Stats::Vector *> > transVec;
static int m_num_controllers;
// Internal functions
void unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr);
''')
+ # Prototype the actions that the controller can take
code('''
// Actions
if self.TBEType != None and self.EntryType != None:
for action in self.actions.itervalues():
code('/** \\brief ${{action.desc}} */')
- code('void ${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr);')
+ code('void ${{action.ident}}(${{self.TBEType.c_ident}}*& '
+ 'm_tbe_ptr, ${{self.EntryType.c_ident}}*& '
+ 'm_cache_entry_ptr, const Address& addr);')
elif self.TBEType != None:
for action in self.actions.itervalues():
code('/** \\brief ${{action.desc}} */')
- code('void ${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, const Address& addr);')
+ code('void ${{action.ident}}(${{self.TBEType.c_ident}}*& '
+ 'm_tbe_ptr, const Address& addr);')
elif self.EntryType != None:
for action in self.actions.itervalues():
code('/** \\brief ${{action.desc}} */')
- code('void ${{action.ident}}(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr);')
+ code('void ${{action.ident}}(${{self.EntryType.c_ident}}*& '
+ 'm_cache_entry_ptr, const Address& addr);')
else:
for action in self.actions.itervalues():
code('/** \\brief ${{action.desc}} */')
// Objects
''')
for var in self.objects:
- th = var.get("template_hack", "")
- code('${{var.type.c_ident}}$th* m_${{var.c_ident}}_ptr;')
-
- if var.type.ident == "MessageBuffer":
- self.message_buffer_names.append("m_%s_ptr" % var.c_ident)
+ th = var.get("template", "")
+ code('${{var.type.c_ident}}$th* m_${{var.ident}}_ptr;')
code.dedent()
code('};')
code('#include "mem/protocol/${{var.type.c_ident}}.hh"')
seen_types.add(var.type.ident)
+ num_in_ports = len(self.in_ports)
+
code('''
$c_ident *
${c_ident}Params::create()
}
int $c_ident::m_num_controllers = 0;
-${ident}_ProfileDumper $c_ident::s_profileDumper;
+std::vector<Stats::Vector *> $c_ident::eventVec;
+std::vector<std::vector<Stats::Vector *> > $c_ident::transVec;
// for adding information to the protocol debug trace
stringstream ${ident}_transitionComment;
+
+#ifndef NDEBUG
#define APPEND_TRANSITION_COMMENT(str) (${ident}_transitionComment << str)
+#else
+#define APPEND_TRANSITION_COMMENT(str) do {} while (0)
+#endif
/** \\brief constructor */
$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;
- m_is_blocking = false;
- m_name = "${ident}";
+ m_machineID.type = MachineType_${ident};
+ m_machineID.num = m_version;
+ m_num_controllers++;
+
+ m_in_ports = $num_in_ports;
''')
- #
- # max_port_rank is used to size vectors and thus should be one plus the
- # largest port rank
- #
- max_port_rank = self.in_ports[0].pairs["max_port_rank"] + 1
- code(' m_max_in_port_rank = $max_port_rank;')
code.indent()
#
# After initializing the universal machine parameters, initialize the
- # this machines config parameters. Also detemine if these configuration
- # params include a sequencer. This information will be used later for
- # contecting the sequencer back to the L1 cache controller.
+ # this machines config parameters. Also if these configuration params
+ # include a sequencer, connect the it to the controller.
#
- contains_dma_sequencer = False
- sequencers = []
for param in self.config_parameters:
- if param.name == "dma_sequencer":
- contains_dma_sequencer = True
- elif re.compile("sequencer").search(param.name):
- sequencers.append(param.name)
+
+ # Do not initialize messgage buffers since they are initialized
+ # when the port based connections are made.
+ if param.type_ast.type.c_ident == "MessageBuffer":
+ continue
+
if param.pointer:
- code('m_${{param.name}}_ptr = p->${{param.name}};')
+ code('m_${{param.ident}}_ptr = p->${{param.ident}};')
else:
- code('m_${{param.name}} = p->${{param.name}};')
-
- #
- # For the l1 cache controller, add the special atomic support which
- # includes passing the sequencer a pointer to the controller.
- #
- if self.ident == "L1Cache":
- if not sequencers:
- self.error("The L1Cache controller must include the sequencer " \
- "configuration parameter")
+ code('m_${{param.ident}} = p->${{param.ident}};')
- for seq in sequencers:
+ if re.compile("sequencer").search(param.ident):
+ code('m_${{param.ident}}_ptr->setController(this);')
+
+ for var in self.objects:
+ if var.ident.find("mandatoryQueue") >= 0:
code('''
-m_${{seq}}_ptr->setController(this);
- ''')
+m_${{var.ident}}_ptr = new ${{var.type.c_ident}}();
+m_${{var.ident}}_ptr->setReceiver(this);
+''')
+
+ code('''
+
+for (int state = 0; state < ${ident}_State_NUM; state++) {
+ for (int event = 0; event < ${ident}_Event_NUM; event++) {
+ m_possible[state][event] = false;
+ m_counters[state][event] = 0;
+ }
+}
+for (int event = 0; event < ${ident}_Event_NUM; event++) {
+ m_event_counters[event] = 0;
+}
+''')
+ code.dedent()
+ code('''
+}
+
+void
+$c_ident::setNetQueue(const std::string& name, MessageBuffer *b)
+{
+ MachineType machine_type = string_to_MachineType("${{self.ident}}");
+ int base M5_VAR_USED = MachineType_base_number(machine_type);
+
+''')
+ code.indent()
+
+ # set for maintaining the vnet, direction pairs already seen for this
+ # machine. This map helps in implementing the check for avoiding
+ # multiple message buffers being mapped to the same vnet.
+ vnet_dir_set = set()
+
+ for var in self.config_parameters:
+ if "network" in var:
+ vtype = var.type_ast.type
+ vid = "m_%s_ptr" % var.ident
- else:
- for seq in sequencers:
code('''
-m_${{seq}}_ptr->setController(this);
- ''')
+if ("${{var.ident}}" == name) {
+ $vid = b;
+ assert($vid != NULL);
+''')
+ code.indent()
+ # Network port object
+ network = var["network"]
+ ordered = var["ordered"]
- #
- # For the DMA controller, pass the sequencer a pointer to the
- # controller.
- #
- if self.ident == "DMA":
- if not contains_dma_sequencer:
- self.error("The DMA controller must include the sequencer " \
- "configuration parameter")
+ if "virtual_network" in var:
+ vnet = var["virtual_network"]
+ vnet_type = var["vnet_type"]
- code('''
-m_dma_sequencer_ptr->setController(this);
+ assert (vnet, network) not in vnet_dir_set
+ vnet_dir_set.add((vnet,network))
+
+ code('''
+m_net_ptr->set${network}NetQueue(m_version + base, $ordered, $vnet,
+ "$vnet_type", b);
''')
-
- code('m_num_controllers++;')
- for var in self.objects:
- if var.ident.find("mandatoryQueue") >= 0:
- code('m_${{var.c_ident}}_ptr = new ${{var.type.c_ident}}();')
+ # Set the end
+ if network == "To":
+ code('$vid->setSender(this);')
+ else:
+ code('$vid->setReceiver(this);')
+
+ # Set ordering
+ code('$vid->setOrdering(${{var["ordered"]}});')
+
+ # Set randomization
+ if "random" in var:
+ # A buffer
+ code('$vid->setRandomization(${{var["random"]}});')
+
+ # Set Priority
+ if "rank" in var:
+ code('$vid->setPriority(${{var["rank"]}})')
+
+ # Set buffer size
+ code('$vid->resize(m_buffer_size);')
+
+ if "recycle_latency" in var:
+ code('$vid->setRecycleLatency( ' \
+ 'Cycles(${{var["recycle_latency"]}}));')
+ else:
+ code('$vid->setRecycleLatency(m_recycle_latency);')
+
+ # set description (may be overriden later by port def)
+ code('''
+$vid->setDescription("[Version " + to_string(m_version) + ", ${ident}, name=${{var.ident}}]");
+''')
+ code.dedent()
+ code('}\n')
code.dedent()
code('''
void
$c_ident::init()
{
- MachineType machine_type;
- int base;
-
- m_machineID.type = MachineType_${ident};
- m_machineID.num = m_version;
-
// initialize objects
- m_profiler.setVersion(m_version);
- s_profileDumper.registerProfiler(&m_profiler);
''')
code.indent()
+
for var in self.objects:
vtype = var.type
- vid = "m_%s_ptr" % var.c_ident
+ vid = "m_%s_ptr" % var.ident
if "network" not in var:
# Not a network port object
if "primitive" in vtype:
code('(*$vid) = ${{var["default"]}};')
else:
# Normal Object
- # added by SS
- if "factory" in var:
- code('$vid = ${{var["factory"]}};')
- elif var.ident.find("mandatoryQueue") < 0:
- th = var.get("template_hack", "")
+ if var.ident.find("mandatoryQueue") < 0:
+ th = var.get("template", "")
expr = "%s = new %s%s" % (vid, vtype.c_ident, th)
-
args = ""
if "non_obj" not in vtype and not vtype.isEnumeration:
- if expr.find("TBETable") >= 0:
- args = "m_number_of_TBEs"
- else:
- args = var.get("constructor_hack", "")
-
+ args = var.get("constructor", "")
code('$expr($args);')
code('assert($vid != NULL);')
code('*$vid = ${{vtype["default"]}}; // $comment')
# Set ordering
- if "ordered" in var and "trigger_queue" not in var:
+ if "ordered" in var:
# A buffer
code('$vid->setOrdering(${{var["ordered"]}});')
code('$vid->setRandomization(${{var["random"]}});')
# Set Priority
- if vtype.isBuffer and \
- "rank" in var and "trigger_queue" not in var:
+ if vtype.isBuffer and "rank" in var:
code('$vid->setPriority(${{var["rank"]}});')
- else:
- # Network port object
- network = var["network"]
- ordered = var["ordered"]
- vnet = var["virtual_network"]
- vnet_type = var["vnet_type"]
-
- assert var.machine is not None
- code('''
-machine_type = string_to_MachineType("${{var.machine.ident}}");
-base = MachineType_base_number(machine_type);
-$vid = m_net_ptr->get${network}NetQueue(m_version + base, $ordered, $vnet, "$vnet_type");
-''')
-
- code('assert($vid != NULL);')
-
- # Set ordering
- if "ordered" in var:
- # A buffer
- code('$vid->setOrdering(${{var["ordered"]}});')
-
- # Set randomization
- if "random" in var:
- # A buffer
- code('$vid->setRandomization(${{var["random"]}});')
-
- # Set Priority
- if "rank" in var:
- code('$vid->setPriority(${{var["rank"]}})')
-
- # Set buffer size
- if vtype.isBuffer:
- code('''
-if (m_buffer_size > 0) {
- $vid->resize(m_buffer_size);
-}
-''')
-
- # set description (may be overriden later by port def)
- code('''
-$vid->setDescription("[Version " + to_string(m_version) + ", ${ident}, name=${{var.c_ident}}]");
-
-''')
+ # Set sender and receiver for trigger queue
+ if var.ident.find("triggerQueue") >= 0:
+ code('$vid->setSender(this);')
+ code('$vid->setReceiver(this);')
+ elif vtype.c_ident == "TimerTable":
+ code('$vid->setClockObj(this);')
+ elif var.ident.find("optionalQueue") >= 0:
+ code('$vid->setSender(this);')
+ code('$vid->setReceiver(this);')
if vtype.isBuffer:
if "recycle_latency" in var:
- code('$vid->setRecycleLatency(${{var["recycle_latency"]}});')
+ code('$vid->setRecycleLatency( ' \
+ 'Cycles(${{var["recycle_latency"]}}));')
else:
code('$vid->setRecycleLatency(m_recycle_latency);')
-
- # Set the queue consumers
+ # Set the prefetchers
code()
- for port in self.in_ports:
- code('${{port.code}}.setConsumer(this);')
+ for prefetcher in self.prefetchers:
+ code('${{prefetcher.code}}.setController(this);')
- # Set the queue descriptions
code()
for port in self.in_ports:
+ # Set the queue consumers
+ code('${{port.code}}.setConsumer(this);')
+ # Set the queue descriptions
code('${{port.code}}.setDescription("[Version " + to_string(m_version) + ", $ident, $port]");')
# Initialize the transition profiling
if not stall:
state = "%s_State_%s" % (self.ident, trans.state.ident)
event = "%s_Event_%s" % (self.ident, trans.event.ident)
- code('m_profiler.possibleTransition($state, $event);')
+ code('possibleTransition($state, $event);')
code.dedent()
- code('}')
+ code('''
+ AbstractController::init();
+ resetStats();
+}
+''')
- has_mandatory_q = False
+ mq_ident = "NULL"
for port in self.in_ports:
if port.code.find("mandatoryQueue_ptr") >= 0:
- has_mandatory_q = True
-
- if has_mandatory_q:
- mq_ident = "m_%s_mandatoryQueue_ptr" % self.ident
- else:
- mq_ident = "NULL"
+ mq_ident = "m_mandatoryQueue_ptr"
seq_ident = "NULL"
for param in self.config_parameters:
- if param.name == "sequencer":
+ if param.ident == "sequencer":
assert(param.pointer)
- seq_ident = "m_%s_ptr" % param.name
+ seq_ident = "m_%s_ptr" % param.ident
code('''
-int
-$c_ident::getNumControllers()
-{
- return m_num_controllers;
-}
-MessageBuffer*
-$c_ident::getMandatoryQueue() const
+void
+$c_ident::regStats()
{
- return $mq_ident;
-}
+ AbstractController::regStats();
-Sequencer*
-$c_ident::getSequencer() const
-{
- return $seq_ident;
-}
+ if (m_version == 0) {
+ for (${ident}_Event event = ${ident}_Event_FIRST;
+ event < ${ident}_Event_NUM; ++event) {
+ Stats::Vector *t = new Stats::Vector();
+ t->init(m_num_controllers);
+ t->name(g_system_ptr->name() + ".${c_ident}." +
+ ${ident}_Event_to_string(event));
+ t->flags(Stats::pdf | Stats::total | Stats::oneline |
+ Stats::nozero);
+
+ eventVec.push_back(t);
+ }
-const int &
-$c_ident::getVersion() const
-{
- return m_version;
-}
+ for (${ident}_State state = ${ident}_State_FIRST;
+ state < ${ident}_State_NUM; ++state) {
-const string
-$c_ident::toString() const
-{
- return "$c_ident";
-}
+ transVec.push_back(std::vector<Stats::Vector *>());
-const string
-$c_ident::getName() const
-{
- return m_name;
-}
+ for (${ident}_Event event = ${ident}_Event_FIRST;
+ event < ${ident}_Event_NUM; ++event) {
-void
-$c_ident::stallBuffer(MessageBuffer* buf, Address addr)
-{
- if (m_waiting_buffers.count(addr) == 0) {
- MsgVecType* msgVec = new MsgVecType;
- msgVec->resize(m_max_in_port_rank, NULL);
- m_waiting_buffers[addr] = msgVec;
+ Stats::Vector *t = new Stats::Vector();
+ t->init(m_num_controllers);
+ t->name(g_system_ptr->name() + ".${c_ident}." +
+ ${ident}_State_to_string(state) +
+ "." + ${ident}_Event_to_string(event));
+
+ t->flags(Stats::pdf | Stats::total | Stats::oneline |
+ Stats::nozero);
+ transVec[state].push_back(t);
+ }
+ }
}
- (*(m_waiting_buffers[addr]))[m_cur_in_port_rank] = buf;
}
void
-$c_ident::wakeUpBuffers(Address addr)
+$c_ident::collateStats()
{
- if (m_waiting_buffers.count(addr) > 0) {
- //
- // Wake up all possible lower rank (i.e. lower priority) buffers that could
- // be waiting on this message.
- //
- for (int in_port_rank = m_cur_in_port_rank - 1;
- in_port_rank >= 0;
- in_port_rank--) {
- if ((*(m_waiting_buffers[addr]))[in_port_rank] != NULL) {
- (*(m_waiting_buffers[addr]))[in_port_rank]->reanalyzeMessages(addr);
+ for (${ident}_Event event = ${ident}_Event_FIRST;
+ event < ${ident}_Event_NUM; ++event) {
+ for (unsigned int i = 0; i < m_num_controllers; ++i) {
+ std::map<uint32_t, AbstractController *>::iterator it =
+ g_abs_controls[MachineType_${ident}].find(i);
+ assert(it != g_abs_controls[MachineType_${ident}].end());
+ (*eventVec[event])[i] =
+ (($c_ident *)(*it).second)->getEventCount(event);
+ }
+ }
+
+ for (${ident}_State state = ${ident}_State_FIRST;
+ state < ${ident}_State_NUM; ++state) {
+
+ for (${ident}_Event event = ${ident}_Event_FIRST;
+ event < ${ident}_Event_NUM; ++event) {
+
+ for (unsigned int i = 0; i < m_num_controllers; ++i) {
+ std::map<uint32_t, AbstractController *>::iterator it =
+ g_abs_controls[MachineType_${ident}].find(i);
+ assert(it != g_abs_controls[MachineType_${ident}].end());
+ (*transVec[state][event])[i] =
+ (($c_ident *)(*it).second)->getTransitionCount(state, event);
}
}
- delete m_waiting_buffers[addr];
- m_waiting_buffers.erase(addr);
}
}
void
-$c_ident::wakeUpAllBuffers()
+$c_ident::countTransition(${ident}_State state, ${ident}_Event event)
{
- //
- // Wake up all possible buffers that could be waiting on any message.
- //
-
- std::vector<MsgVecType*> wokeUpMsgVecs;
-
- if(m_waiting_buffers.size() > 0) {
- for (WaitingBufType::iterator buf_iter = m_waiting_buffers.begin();
- buf_iter != m_waiting_buffers.end();
- ++buf_iter) {
- for (MsgVecType::iterator vec_iter = buf_iter->second->begin();
- vec_iter != buf_iter->second->end();
- ++vec_iter) {
- if (*vec_iter != NULL) {
- (*vec_iter)->reanalyzeAllMessages();
- }
- }
- wokeUpMsgVecs.push_back(buf_iter->second);
- }
+ assert(m_possible[state][event]);
+ m_counters[state][event]++;
+ m_event_counters[event]++;
+}
+void
+$c_ident::possibleTransition(${ident}_State state,
+ ${ident}_Event event)
+{
+ m_possible[state][event] = true;
+}
- for (std::vector<MsgVecType*>::iterator wb_iter = wokeUpMsgVecs.begin();
- wb_iter != wokeUpMsgVecs.end();
- ++wb_iter) {
- delete (*wb_iter);
- }
+uint64
+$c_ident::getEventCount(${ident}_Event event)
+{
+ return m_event_counters[event];
+}
- m_waiting_buffers.clear();
- }
+bool
+$c_ident::isPossible(${ident}_State state, ${ident}_Event event)
+{
+ return m_possible[state][event];
}
-void
-$c_ident::blockOnQueue(Address addr, MessageBuffer* port)
+uint64
+$c_ident::getTransitionCount(${ident}_State state,
+ ${ident}_Event event)
{
- m_is_blocking = true;
- m_block_map[addr] = port;
+ return m_counters[state][event];
}
-void
-$c_ident::unblock(Address addr)
+int
+$c_ident::getNumControllers()
{
- m_block_map.erase(addr);
- if (m_block_map.size() == 0) {
- m_is_blocking = false;
- }
+ return m_num_controllers;
}
-void
-$c_ident::print(ostream& out) const
+MessageBuffer*
+$c_ident::getMandatoryQueue() const
{
- out << "[$c_ident " << m_version << "]";
+ return $mq_ident;
}
-void
-$c_ident::printConfig(ostream& out) const
+Sequencer*
+$c_ident::getSequencer() const
{
- out << "$c_ident config: " << m_name << endl;
- out << " version: " << m_version << endl;
- map<string, string>::const_iterator it;
- for (it = m_cfg.begin(); it != m_cfg.end(); it++)
- out << " " << it->first << ": " << it->second << endl;
+ return $seq_ident;
}
void
-$c_ident::printStats(ostream& out) const
+$c_ident::print(ostream& out) const
{
-''')
- #
- # Cache and Memory Controllers have specific profilers associated with
- # them. Print out these stats before dumping state transition stats.
- #
- for param in self.config_parameters:
- if param.type_ast.type.ident == "CacheMemory" or \
- param.type_ast.type.ident == "DirectoryMemory" or \
- param.type_ast.type.ident == "MemoryControl":
- assert(param.pointer)
- code(' m_${{param.ident}}_ptr->printStats(out);')
+ out << "[$c_ident " << m_version << "]";
+}
- code('''
- if (m_version == 0) {
- s_profileDumper.dumpStats(out);
+void $c_ident::resetStats()
+{
+ for (int state = 0; state < ${ident}_State_NUM; state++) {
+ for (int event = 0; event < ${ident}_Event_NUM; event++) {
+ m_counters[state][event] = 0;
+ }
}
-}
-void $c_ident::clearStats() {
-''')
- #
- # Cache and Memory Controllers have specific profilers associated with
- # them. These stats must be cleared too.
- #
- for param in self.config_parameters:
- if param.type_ast.type.ident == "CacheMemory" or \
- param.type_ast.type.ident == "MemoryControl":
- assert(param.pointer)
- code(' m_${{param.ident}}_ptr->clearStats();')
+ for (int event = 0; event < ${ident}_Event_NUM; event++) {
+ m_event_counters[event] = 0;
+ }
- code('''
- m_profiler.clearStats();
+ AbstractController::resetStats();
}
''')
for func in self.functions:
code(func.generateCode())
+ # Function for functional reads from messages buffered in the controller
+ code('''
+bool
+$c_ident::functionalReadBuffers(PacketPtr& pkt)
+{
+''')
+ for var in self.objects:
+ vtype = var.type
+ if vtype.isBuffer:
+ vid = "m_%s_ptr" % var.ident
+ code('if ($vid->functionalRead(pkt)) { return true; }')
+
+ for var in self.config_parameters:
+ vtype = var.type_ast.type
+ if vtype.isBuffer:
+ vid = "m_%s_ptr" % var.ident
+ code('if ($vid->functionalRead(pkt)) { return true; }')
+
+ code('''
+ return false;
+}
+''')
+
+ # Function for functional writes to messages buffered in the controller
+ code('''
+uint32_t
+$c_ident::functionalWriteBuffers(PacketPtr& pkt)
+{
+ uint32_t num_functional_writes = 0;
+''')
+ for var in self.objects:
+ vtype = var.type
+ if vtype.isBuffer:
+ vid = "m_%s_ptr" % var.ident
+ code('num_functional_writes += $vid->functionalWrite(pkt);')
+
+ for var in self.config_parameters:
+ vtype = var.type_ast.type
+ if vtype.isBuffer:
+ vid = "m_%s_ptr" % var.ident
+ code('num_functional_writes += $vid->functionalWrite(pkt);')
+
+ code('''
+ return num_functional_writes;
+}
+''')
+
code.write(path, "%s.cc" % c_ident)
def printCWakeup(self, path, includes):
assert(counter <= m_transitions_per_cycle);
if (counter == m_transitions_per_cycle) {
// Count how often we are fully utilized
- g_system_ptr->getProfiler()->controllerBusy(m_machineID);
+ m_fully_busy_cycles++;
// Wakeup in another cycle and try again
- scheduleEvent(1);
+ scheduleEvent(Cycles(1));
break;
}
''')
code.indent()
code('// ${ident}InPort $port')
if port.pairs.has_key("rank"):
- code('m_cur_in_port_rank = ${{port.pairs["rank"]}};')
+ code('m_cur_in_port = ${{port.pairs["rank"]}};')
else:
- code('m_cur_in_port_rank = 0;')
+ code('m_cur_in_port = 0;')
code('${{port["c_code_in_port"]}}')
code.dedent()
${{self.TBEType.c_ident}}* m_tbe_ptr,
''')
code('''
- const Address &addr)
+ const Address addr)
{
''')
+ code.indent()
+
if self.TBEType != None and self.EntryType != None:
code('${ident}_State state = getState(m_tbe_ptr, m_cache_entry_ptr, addr);')
elif self.TBEType != None:
code('${ident}_State state = getState(addr);')
code('''
- ${ident}_State next_state = state;
+${ident}_State next_state = state;
- DPRINTF(RubyGenerated, "%s, Time: %lld, state: %s, event: %s, addr: %s\\n",
- *this, g_system_ptr->getTime(), ${ident}_State_to_string(state),
- ${ident}_Event_to_string(event), addr);
+DPRINTF(RubyGenerated, "%s, Time: %lld, state: %s, event: %s, addr: %s\\n",
+ *this, curCycle(), ${ident}_State_to_string(state),
+ ${ident}_Event_to_string(event), addr);
- TransitionResult result =
+TransitionResult result =
''')
if self.TBEType != None and self.EntryType != None:
code('doTransitionWorker(event, state, next_state, m_tbe_ptr, m_cache_entry_ptr, addr);')
code('doTransitionWorker(event, state, next_state, addr);')
code('''
- if (result == TransitionResult_Valid) {
- DPRINTF(RubyGenerated, "next_state: %s\\n",
- ${ident}_State_to_string(next_state));
- m_profiler.countTransition(state, event);
- DPRINTFR(ProtocolTrace, "%15d %3s %10s%20s %6s>%-6s %s %s\\n",
- curTick(), m_version, "${ident}",
- ${ident}_Event_to_string(event),
- ${ident}_State_to_string(state),
- ${ident}_State_to_string(next_state),
- addr, GET_TRANSITION_COMMENT());
-
- CLEAR_TRANSITION_COMMENT();
+
+if (result == TransitionResult_Valid) {
+ DPRINTF(RubyGenerated, "next_state: %s\\n",
+ ${ident}_State_to_string(next_state));
+ countTransition(state, event);
+
+ DPRINTFR(ProtocolTrace, "%15d %3s %10s%20s %6s>%-6s %s %s\\n",
+ curTick(), m_version, "${ident}",
+ ${ident}_Event_to_string(event),
+ ${ident}_State_to_string(state),
+ ${ident}_State_to_string(next_state),
+ addr, GET_TRANSITION_COMMENT());
+
+ CLEAR_TRANSITION_COMMENT();
''')
if self.TBEType != None and self.EntryType != None:
code('setState(m_tbe_ptr, m_cache_entry_ptr, addr, next_state);')
code('setAccessPermission(addr, next_state);')
code('''
- } else if (result == TransitionResult_ResourceStall) {
- DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %s\\n",
- curTick(), m_version, "${ident}",
- ${ident}_Event_to_string(event),
- ${ident}_State_to_string(state),
- ${ident}_State_to_string(next_state),
- addr, "Resource Stall");
- } else if (result == TransitionResult_ProtocolStall) {
- DPRINTF(RubyGenerated, "stalling\\n");
- DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %s\\n",
- curTick(), m_version, "${ident}",
- ${ident}_Event_to_string(event),
- ${ident}_State_to_string(state),
- ${ident}_State_to_string(next_state),
- addr, "Protocol Stall");
- }
+} else if (result == TransitionResult_ResourceStall) {
+ DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %s\\n",
+ curTick(), m_version, "${ident}",
+ ${ident}_Event_to_string(event),
+ ${ident}_State_to_string(state),
+ ${ident}_State_to_string(next_state),
+ addr, "Resource Stall");
+} else if (result == TransitionResult_ProtocolStall) {
+ DPRINTF(RubyGenerated, "stalling\\n");
+ DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %s\\n",
+ curTick(), m_version, "${ident}",
+ ${ident}_Event_to_string(event),
+ ${ident}_State_to_string(state),
+ ${ident}_State_to_string(next_state),
+ addr, "Protocol Stall");
+}
- return result;
+return result;
+''')
+ code.dedent()
+ code('''
}
TransitionResult
case_sorter = []
res = trans.resources
for key,val in res.iteritems():
- if key.type.ident != "DNUCAStopTable":
- val = '''
+ val = '''
if (!%s.areNSlotsAvailable(%s))
return TransitionResult_ResourceStall;
''' % (key.code, val)
# the same code
for trans in transitions:
code(' case HASH_FUN($trans):')
- code(' $case')
+ code(' $case\n')
code('''
default:
fatal("Invalid transition\\n"
"%s time: %d addr: %s event: %s state: %s\\n",
- name(), g_system_ptr->getTime(), addr, event, state);
+ name(), curCycle(), addr, event, state);
}
+
return TransitionResult_Valid;
}
''')
code.write(path, "%s_Transitions.cc" % self.ident)
- def printProfileDumperHH(self, path):
- code = self.symtab.codeFormatter()
- ident = self.ident
-
- code('''
-// Auto generated C++ code started by $__file__:$__line__
-// ${ident}: ${{self.short}}
-
-#ifndef __${ident}_PROFILE_DUMPER_HH__
-#define __${ident}_PROFILE_DUMPER_HH__
-
-#include <cassert>
-#include <iostream>
-#include <vector>
-
-#include "${ident}_Event.hh"
-#include "${ident}_Profiler.hh"
-
-typedef std::vector<${ident}_Profiler *> ${ident}_profilers;
-
-class ${ident}_ProfileDumper
-{
- public:
- ${ident}_ProfileDumper();
- void registerProfiler(${ident}_Profiler* profiler);
- void dumpStats(std::ostream& out) const;
-
- private:
- ${ident}_profilers m_profilers;
-};
-
-#endif // __${ident}_PROFILE_DUMPER_HH__
-''')
- code.write(path, "%s_ProfileDumper.hh" % self.ident)
-
- def printProfileDumperCC(self, path):
- code = self.symtab.codeFormatter()
- ident = self.ident
-
- code('''
-// Auto generated C++ code started by $__file__:$__line__
-// ${ident}: ${{self.short}}
-
-#include "mem/protocol/${ident}_ProfileDumper.hh"
-
-${ident}_ProfileDumper::${ident}_ProfileDumper()
-{
-}
-
-void
-${ident}_ProfileDumper::registerProfiler(${ident}_Profiler* profiler)
-{
- m_profilers.push_back(profiler);
-}
-
-void
-${ident}_ProfileDumper::dumpStats(std::ostream& out) const
-{
- out << " --- ${ident} ---\\n";
- out << " - Event Counts -\\n";
- for (${ident}_Event event = ${ident}_Event_FIRST;
- event < ${ident}_Event_NUM;
- ++event) {
- out << (${ident}_Event) event << " [";
- uint64 total = 0;
- for (int i = 0; i < m_profilers.size(); i++) {
- out << m_profilers[i]->getEventCount(event) << " ";
- total += m_profilers[i]->getEventCount(event);
- }
- out << "] " << total << "\\n";
- }
- out << "\\n";
- out << " - Transitions -\\n";
- for (${ident}_State state = ${ident}_State_FIRST;
- state < ${ident}_State_NUM;
- ++state) {
- for (${ident}_Event event = ${ident}_Event_FIRST;
- event < ${ident}_Event_NUM;
- ++event) {
- if (m_profilers[0]->isPossible(state, event)) {
- out << (${ident}_State) state << " "
- << (${ident}_Event) event << " [";
- uint64 total = 0;
- for (int i = 0; i < m_profilers.size(); i++) {
- out << m_profilers[i]->getTransitionCount(state, event) << " ";
- total += m_profilers[i]->getTransitionCount(state, event);
- }
- out << "] " << total << "\\n";
- }
- }
- out << "\\n";
- }
-}
-''')
- code.write(path, "%s_ProfileDumper.cc" % self.ident)
-
- def printProfilerHH(self, path):
- code = self.symtab.codeFormatter()
- ident = self.ident
-
- code('''
-// Auto generated C++ code started by $__file__:$__line__
-// ${ident}: ${{self.short}}
-
-#ifndef __${ident}_PROFILER_HH__
-#define __${ident}_PROFILER_HH__
-
-#include <cassert>
-#include <iostream>
-
-#include "mem/protocol/${ident}_Event.hh"
-#include "mem/protocol/${ident}_State.hh"
-#include "mem/ruby/common/TypeDefines.hh"
-
-class ${ident}_Profiler
-{
- public:
- ${ident}_Profiler();
- void setVersion(int version);
- void countTransition(${ident}_State state, ${ident}_Event event);
- void possibleTransition(${ident}_State state, ${ident}_Event event);
- uint64 getEventCount(${ident}_Event event);
- bool isPossible(${ident}_State state, ${ident}_Event event);
- uint64 getTransitionCount(${ident}_State state, ${ident}_Event event);
- void clearStats();
-
- private:
- int m_counters[${ident}_State_NUM][${ident}_Event_NUM];
- int m_event_counters[${ident}_Event_NUM];
- bool m_possible[${ident}_State_NUM][${ident}_Event_NUM];
- int m_version;
-};
-
-#endif // __${ident}_PROFILER_HH__
-''')
- code.write(path, "%s_Profiler.hh" % self.ident)
-
- def printProfilerCC(self, path):
- code = self.symtab.codeFormatter()
- ident = self.ident
-
- code('''
-// Auto generated C++ code started by $__file__:$__line__
-// ${ident}: ${{self.short}}
-
-#include <cassert>
-
-#include "mem/protocol/${ident}_Profiler.hh"
-
-${ident}_Profiler::${ident}_Profiler()
-{
- for (int state = 0; state < ${ident}_State_NUM; state++) {
- for (int event = 0; event < ${ident}_Event_NUM; event++) {
- m_possible[state][event] = false;
- m_counters[state][event] = 0;
- }
- }
- for (int event = 0; event < ${ident}_Event_NUM; event++) {
- m_event_counters[event] = 0;
- }
-}
-
-void
-${ident}_Profiler::setVersion(int version)
-{
- m_version = version;
-}
-
-void
-${ident}_Profiler::clearStats()
-{
- for (int state = 0; state < ${ident}_State_NUM; state++) {
- for (int event = 0; event < ${ident}_Event_NUM; event++) {
- m_counters[state][event] = 0;
- }
- }
-
- for (int event = 0; event < ${ident}_Event_NUM; event++) {
- m_event_counters[event] = 0;
- }
-}
-void
-${ident}_Profiler::countTransition(${ident}_State state, ${ident}_Event event)
-{
- assert(m_possible[state][event]);
- m_counters[state][event]++;
- m_event_counters[event]++;
-}
-void
-${ident}_Profiler::possibleTransition(${ident}_State state,
- ${ident}_Event event)
-{
- m_possible[state][event] = true;
-}
-
-uint64
-${ident}_Profiler::getEventCount(${ident}_Event event)
-{
- return m_event_counters[event];
-}
-
-bool
-${ident}_Profiler::isPossible(${ident}_State state, ${ident}_Event event)
-{
- return m_possible[state][event];
-}
-
-uint64
-${ident}_Profiler::getTransitionCount(${ident}_State state,
- ${ident}_Event event)
-{
- return m_counters[state][event];
-}
-
-''')
- code.write(path, "%s_Profiler.cc" % self.ident)
# **************************
# ******* HTML Files *******