# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-from m5.util import code_formatter, orderdict
+from m5.util import orderdict
from slicc.symbols.Symbol import Symbol
from slicc.symbols.Var import Var
import slicc.generate.html as html
+import re
-python_class_map = {"int": "Int",
- "string": "String",
+python_class_map = {
+ "int": "Int",
+ "uint32_t" : "UInt32",
+ "std::string": "String",
"bool": "Bool",
"CacheMemory": "RubyCache",
+ "WireBuffer": "RubyWireBuffer",
"Sequencer": "RubySequencer",
"DirectoryMemory": "RubyDirectoryMemory",
- "MemoryControl": "RubyMemoryControl",
- "DMASequencer": "DMASequencer"
- }
+ "MemoryControl": "MemoryControl",
+ "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.actions = orderdict()
+ self.request_types = orderdict()
self.transitions = []
self.in_ports = []
self.functions = []
- self.objects = []
- self.message_buffer_names = []
+ # 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
def __repr__(self):
return "[StateMachine: %s]" % self.ident
self.actions[action.ident] = action
+ def addRequestType(self, request_type):
+ assert self.table is None
+ self.request_types[request_type.ident] = request_type
+
def addTransition(self, trans):
assert self.table is None
self.transitions.append(trans)
self.functions.append(func)
def addObject(self, obj):
+ self.symtab.registerSym(str(obj), obj)
self.objects.append(obj)
+ def addType(self, type):
+ type_ident = '%s' % type.c_ident
+
+ if type_ident == "%s_TBE" %self.ident:
+ if self.TBEType != None:
+ self.error("Multiple Transaction Buffer types in a " \
+ "single machine.");
+ self.TBEType = type
+
+ elif "interface" in type and "AbstractCacheEntry" == type["interface"]:
+ if self.EntryType != None:
+ self.error("Multiple AbstractCacheEntry types in a " \
+ "single machine.");
+ self.EntryType = type
+
# Needs to be called before accessing the table
def buildTable(self):
assert self.table is None
action.warning(error_msg)
self.table = table
- def writeCodeFiles(self, path):
+ def writeCodeFiles(self, path, includes):
self.printControllerPython(path)
self.printControllerHH(path)
- self.printControllerCC(path)
+ self.printControllerCC(path, includes)
self.printCSwitch(path)
- self.printCWakeup(path)
- self.printProfilerCC(path)
- self.printProfilerHH(path)
-
- for func in self.functions:
- func.writeCodeFiles(path)
+ self.printCWakeup(path, includes)
def printControllerPython(self, path):
- code = code_formatter()
+ 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 " \
def printControllerHH(self, path):
'''Output the method declarations for the class declaration'''
- code = code_formatter()
+ code = self.symtab.codeFormatter()
ident = self.ident
c_ident = "%s_Controller" % self.ident
- self.message_buffer_names = []
-
code('''
-/** \\file $ident.hh
+/** \\file $c_ident.hh
*
* Auto generated C++ code started by $__file__:$__line__
* Created by slicc definition of Module "${{self.short}}"
*/
-#ifndef ${ident}_CONTROLLER_H
-#define ${ident}_CONTROLLER_H
+#ifndef __${ident}_CONTROLLER_HH__
+#define __${ident}_CONTROLLER_HH__
-#include "params/$c_ident.hh"
+#include <iostream>
+#include <sstream>
+#include <string>
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/common/Consumer.hh"
-#include "mem/ruby/slicc_interface/AbstractController.hh"
#include "mem/protocol/TransitionResult.hh"
#include "mem/protocol/Types.hh"
-#include "mem/protocol/${ident}_Profiler.hh"
+#include "mem/ruby/common/Consumer.hh"
+#include "mem/ruby/common/Global.hh"
+#include "mem/ruby/slicc_interface/AbstractController.hh"
+#include "params/$c_ident.hh"
''')
seen_types = set()
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('''
-extern stringstream ${ident}_transitionComment;
+extern std::stringstream ${ident}_transitionComment;
-class $c_ident : public AbstractController {
-#ifdef CHECK_COHERENCE
-#endif /* CHECK_COHERENCE */
-public:
+class $c_ident : public AbstractController
+{
+ public:
typedef ${c_ident}Params Params;
$c_ident(const Params *p);
static int getNumControllers();
void init();
+
MessageBuffer* getMandatoryQueue() const;
- const int & getVersion() const;
- const string toString() const;
- const string getName() const;
- const MachineType getMachineType() const;
- void initNetworkPtr(Network* net_ptr) { m_net_ptr = net_ptr; }
- void print(ostream& out) const;
- void printConfig(ostream& out) const;
+ void setNetQueue(const std::string& name, MessageBuffer *b);
+
+ void print(std::ostream& out) const;
void wakeup();
- void printStats(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, ${ident}_State state, const Address& addr); // in ${ident}_Transitions.cc
-TransitionResult doTransitionWorker(${ident}_Event event, ${ident}_State state, ${ident}_State& next_state, const Address& addr); // in ${ident}_Transitions.cc
-string m_name;
-int m_transitions_per_cycle;
-int m_buffer_size;
-int m_recycle_latency;
-map< string, string > m_cfg;
-NodeID m_version;
-Network* m_net_ptr;
-MachineID m_machineID;
-bool m_is_blocking;
-map< Address, MessageBuffer* > m_block_map;
-${ident}_Profiler s_profiler;
+TransitionResult doTransition(${ident}_Event event,
+''')
+
+ if self.EntryType != None:
+ code('''
+ ${{self.EntryType.c_ident}}* m_cache_entry_ptr,
+''')
+ if self.TBEType != None:
+ code('''
+ ${{self.TBEType.c_ident}}* m_tbe_ptr,
+''')
+
+ code('''
+ const Address addr);
+
+TransitionResult doTransitionWorker(${ident}_Event event,
+ ${ident}_State state,
+ ${ident}_State& next_state,
+''')
+
+ if self.TBEType != None:
+ code('''
+ ${{self.TBEType.c_ident}}*& m_tbe_ptr,
+''')
+ if self.EntryType != None:
+ code('''
+ ${{self.EntryType.c_ident}}*& m_cache_entry_ptr,
+''')
+
+ code('''
+ const Address& addr);
+
+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
''')
if proto:
code('$proto')
+ if self.EntryType != None:
+ code('''
+
+// Set and Reset for cache_entry variable
+void set_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, AbstractCacheEntry* m_new_cache_entry);
+void unset_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr);
+''')
+
+ if self.TBEType != None:
+ code('''
+
+// Set and Reset for tbe variable
+void set_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${ident}_TBE* m_new_tbe);
+void unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr);
+''')
+
+ # Prototype the actions that the controller can take
code('''
// Actions
''')
- for action in self.actions.itervalues():
- code('/** \\brief ${{action.desc}} */')
- code('void ${{action.ident}}(const Address& addr);')
+ 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);')
+ 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);')
+ 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);')
+ else:
+ for action in self.actions.itervalues():
+ code('/** \\brief ${{action.desc}} */')
+ code('void ${{action.ident}}(const Address& addr);')
# the controller internal variables
code('''
-// Object
+// 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('#endif // ${ident}_CONTROLLER_H')
+ code('#endif // __${ident}_CONTROLLER_H__')
code.write(path, '%s.hh' % c_ident)
- def printControllerCC(self, path):
+ def printControllerCC(self, path, includes):
'''Output the actions for performing the actions'''
- code = code_formatter()
+ code = self.symtab.codeFormatter()
ident = self.ident
c_ident = "%s_Controller" % self.ident
code('''
-/** \\file $ident.cc
+/** \\file $c_ident.cc
*
* Auto generated C++ code started by $__file__:$__line__
* Created by slicc definition of Module "${{self.short}}"
*/
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/slicc_interface/RubySlicc_includes.hh"
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <cassert>
+#include <sstream>
+#include <string>
+
+#include "base/compiler.hh"
+#include "base/cprintf.hh"
+#include "debug/RubyGenerated.hh"
+#include "debug/RubySlicc.hh"
#include "mem/protocol/${ident}_Controller.hh"
-#include "mem/protocol/${ident}_State.hh"
#include "mem/protocol/${ident}_Event.hh"
+#include "mem/protocol/${ident}_State.hh"
#include "mem/protocol/Types.hh"
+#include "mem/ruby/common/Global.hh"
#include "mem/ruby/system/System.hh"
+''')
+ for include_path in includes:
+ code('#include "${{include_path}}"')
+
+ code('''
+
+using namespace std;
''')
# include object classes
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()
return new $c_ident(this);
}
-
int $c_ident::m_num_controllers = 0;
+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_machineID.type = MachineType_${ident};
+ m_machineID.num = m_version;
+ m_num_controllers++;
+
+ m_in_ports = $num_in_ports;
''')
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_sequencer = False
for param in self.config_parameters:
- if param.name == "sequencer" or param.name == "dma_sequencer":
- contains_sequencer = True
+
+ # 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}};')
+ code('m_${{param.ident}} = p->${{param.ident}};')
- #
- # 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 contains_sequencer:
- self.error("The L1Cache controller must include the sequencer " \
- "configuration parameter")
+ 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_${{var.ident}}_ptr = new ${{var.type.c_ident}}();
+m_${{var.ident}}_ptr->setReceiver(this);
+''')
- code('''
-m_sequencer_ptr->setController(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;
+}
''')
- #
- # For the DMA controller, pass the sequencer a pointer to the
- # controller.
- #
- if self.ident == "DMA":
- if not contains_sequencer:
- self.error("The DMA controller must include the sequencer " \
- "configuration parameter")
+ 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('''
-m_dma_sequencer_ptr->setController(this);
''')
-
- 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}}();')
+ 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
+
+ code('''
+if ("${{var.ident}}" == name) {
+ $vid = b;
+ assert($vid != NULL);
+''')
+ code.indent()
+ # Network port object
+ network = var["network"]
+ ordered = var["ordered"]
+
+ if "virtual_network" in var:
+ vnet = var["virtual_network"]
+ vnet_type = var["vnet_type"]
+
+ 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);
+''')
+ # 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()
+void
+$c_ident::init()
{
- m_machineID.type = MachineType_${ident};
- m_machineID.num = m_version;
+ // initialize objects
- // Objects
- s_profiler.setVersion(m_version);
''')
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 = "(%s)" % args
-
- code('$expr$args;')
- else:
- code(';')
+ args = var.get("constructor", "")
+ code('$expr($args);')
code('assert($vid != NULL);')
if "default" in var:
- code('(*$vid) = ${{var["default"]}}; // Object default')
+ code('*$vid = ${{var["default"]}}; // Object default')
elif "default" in vtype:
- code('(*$vid) = ${{vtype["default"]}}; // Type ${{vtype.ident}} default')
+ comment = "Type %s default" % vtype.ident
+ 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"]
-
- assert var.machine is not None
- code('''
-$vid = m_net_ptr->get${network}NetQueue(m_version+MachineType_base_number(string_to_MachineType("${{var.machine.ident}}")), $ordered, $vnet);
-''')
-
- 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->setSize(m_buffer_size);
-}
-''')
+ # 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( ' \
+ 'Cycles(${{var["recycle_latency"]}}));')
+ else:
+ code('$vid->setRecycleLatency(m_recycle_latency);')
- # set description (may be overriden later by port def)
- code('$vid->setDescription("[Version " + int_to_string(m_version) + ", ${ident}, name=${{var.c_ident}}]");')
+ # Set the prefetchers
+ code()
+ for prefetcher in self.prefetchers:
+ code('${{prefetcher.code}}.setController(this);')
- # Set the queue consumers
- code.insert_newline()
+ code()
for port in self.in_ports:
+ # Set the queue consumers
code('${{port.code}}.setConsumer(this);')
-
- # Set the queue descriptions
- code.insert_newline()
- for port in self.in_ports:
- code('${{port.code}}.setDescription("[Version " + int_to_string(m_version) + ", $ident, $port]");')
+ # Set the queue descriptions
+ code('${{port.code}}.setDescription("[Version " + to_string(m_version) + ", $ident, $port]");')
# Initialize the transition profiling
- code.insert_newline()
+ code()
for trans in self.transitions:
# Figure out if we stall
stall = False
if not stall:
state = "%s_State_%s" % (self.ident, trans.state.ident)
event = "%s_Event_%s" % (self.ident, trans.event.ident)
- code('s_profiler.possibleTransition($state, $event);')
-
- # added by SS to initialize recycle_latency of message buffers
- for buf in self.message_buffer_names:
- code("$buf->setRecycleLatency(m_recycle_latency);")
+ 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
+ mq_ident = "m_mandatoryQueue_ptr"
- if has_mandatory_q:
- mq_ident = "m_%s_mandatoryQueue_ptr" % self.ident
- else:
- mq_ident = "NULL"
+ seq_ident = "NULL"
+ for param in self.config_parameters:
+ if param.ident == "sequencer":
+ assert(param.pointer)
+ seq_ident = "m_%s_ptr" % param.ident
code('''
-int $c_ident::getNumControllers() {
- return m_num_controllers;
+
+void
+$c_ident::regStats()
+{
+ AbstractController::regStats();
+
+ 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);
+ }
+
+ for (${ident}_State state = ${ident}_State_FIRST;
+ state < ${ident}_State_NUM; ++state) {
+
+ transVec.push_back(std::vector<Stats::Vector *>());
+
+ 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}_State_to_string(state) +
+ "." + ${ident}_Event_to_string(event));
+
+ t->flags(Stats::pdf | Stats::total | Stats::oneline |
+ Stats::nozero);
+ transVec[state].push_back(t);
+ }
+ }
+ }
}
-MessageBuffer* $c_ident::getMandatoryQueue() const {
- return $mq_ident;
+void
+$c_ident::collateStats()
+{
+ 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);
+ }
+ }
+ }
}
-const int & $c_ident::getVersion() const{
- return m_version;
+void
+$c_ident::countTransition(${ident}_State state, ${ident}_Event event)
+{
+ 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;
}
-const string $c_ident::toString() const{
- return "$c_ident";
+uint64
+$c_ident::getEventCount(${ident}_Event event)
+{
+ return m_event_counters[event];
}
-const string $c_ident::getName() const{
- return m_name;
+bool
+$c_ident::isPossible(${ident}_State state, ${ident}_Event event)
+{
+ return m_possible[state][event];
}
-const MachineType $c_ident::getMachineType() const{
- return MachineType_${ident};
+
+uint64
+$c_ident::getTransitionCount(${ident}_State state,
+ ${ident}_Event event)
+{
+ return m_counters[state][event];
}
-void $c_ident::blockOnQueue(Address addr, MessageBuffer* port) {
- m_is_blocking = true;
- m_block_map[addr] = port;
+int
+$c_ident::getNumControllers()
+{
+ return m_num_controllers;
}
-void $c_ident::unblock(Address addr) {
- m_block_map.erase(addr);
- if (m_block_map.size() == 0) {
- m_is_blocking = false;
- }
+
+MessageBuffer*
+$c_ident::getMandatoryQueue() const
+{
+ return $mq_ident;
}
-void $c_ident::print(ostream& out) const { out << "[$c_ident " << m_version << "]"; }
+Sequencer*
+$c_ident::getSequencer() const
+{
+ return $seq_ident;
+}
+
+void
+$c_ident::print(ostream& out) const
+{
+ out << "[$c_ident " << m_version << "]";
+}
-void $c_ident::printConfig(ostream& out) const {
- out << "$c_ident config: " << m_name << endl;
- out << " version: " << m_version << endl;
- for (map<string, string>::const_iterator it = m_cfg.begin(); it != m_cfg.end(); it++) {
- out << " " << (*it).first << ": " << (*it).second << endl;
+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;
+ }
}
+
+ for (int event = 0; event < ${ident}_Event_NUM; event++) {
+ m_event_counters[event] = 0;
+ }
+
+ AbstractController::resetStats();
}
+''')
+
+ if self.EntryType != None:
+ code('''
-void $c_ident::printStats(ostream& out) const {
+// Set and Reset for cache_entry variable
+void
+$c_ident::set_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, AbstractCacheEntry* m_new_cache_entry)
+{
+ m_cache_entry_ptr = (${{self.EntryType.c_ident}}*)m_new_cache_entry;
+}
+
+void
+$c_ident::unset_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr)
+{
+ m_cache_entry_ptr = 0;
+}
''')
- #
- # 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 == "MemoryControl":
- assert(param.pointer)
- code(' m_${{param.ident}}_ptr->printStats(out);')
- code('''
- s_profiler.dumpStats(out);
+ if self.TBEType != None:
+ code('''
+
+// Set and Reset for tbe variable
+void
+$c_ident::set_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.TBEType.c_ident}}* m_new_tbe)
+{
+ m_tbe_ptr = m_new_tbe;
}
-void $c_ident::clearStats() {
+void
+$c_ident::unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr)
+{
+ m_tbe_ptr = NULL;
+}
+''')
+
+ code('''
+
+void
+$c_ident::recordCacheTrace(int cntrl, CacheRecorder* tr)
+{
''')
#
- # Cache and Memory Controllers have specific profilers associated with
- # them. These stats must be cleared too.
+ # Record cache contents for all associated caches.
#
+ code.indent()
for param in self.config_parameters:
- if param.type_ast.type.ident == "CacheMemory" or \
- param.type_ast.type.ident == "MemoryControl":
+ if param.type_ast.type.ident == "CacheMemory":
assert(param.pointer)
- code(' m_${{param.ident}}_ptr->clearStats();')
+ code('m_${{param.ident}}_ptr->recordCacheContents(cntrl, tr);')
+ code.dedent()
code('''
- s_profiler.clearStats();
}
// Actions
''')
+ if self.TBEType != None and self.EntryType != None:
+ for action in self.actions.itervalues():
+ if "c_code" not in action:
+ continue
- for action in self.actions.itervalues():
- if "c_code" not in action:
- continue
+ code('''
+/** \\brief ${{action.desc}} */
+void
+$c_ident::${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr)
+{
+ DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n");
+ ${{action["c_code"]}}
+}
- code('''
+''')
+ elif self.TBEType != None:
+ for action in self.actions.itervalues():
+ if "c_code" not in action:
+ continue
+
+ code('''
/** \\brief ${{action.desc}} */
-void $c_ident::${{action.ident}}(const Address& addr)
+void
+$c_ident::${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, const Address& addr)
{
- DEBUG_MSG(GENERATED_COMP, HighPrio, "executing");
+ DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n");
${{action["c_code"]}}
}
''')
+ elif self.EntryType != None:
+ for action in self.actions.itervalues():
+ if "c_code" not in action:
+ continue
+
+ code('''
+/** \\brief ${{action.desc}} */
+void
+$c_ident::${{action.ident}}(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr)
+{
+ DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n");
+ ${{action["c_code"]}}
+}
+
+''')
+ else:
+ for action in self.actions.itervalues():
+ if "c_code" not in action:
+ continue
+
+ code('''
+/** \\brief ${{action.desc}} */
+void
+$c_ident::${{action.ident}}(const Address& addr)
+{
+ DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n");
+ ${{action["c_code"]}}
+}
+
+''')
+ 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):
+ def printCWakeup(self, path, includes):
'''Output the wakeup loop for the events'''
- code = code_formatter()
+ code = self.symtab.codeFormatter()
ident = self.ident
+ outputRequest_types = True
+ if len(self.request_types) == 0:
+ outputRequest_types = False
+
code('''
// Auto generated C++ code started by $__file__:$__line__
// ${ident}: ${{self.short}}
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/slicc_interface/RubySlicc_includes.hh"
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <cassert>
+
+#include "base/misc.hh"
+#include "debug/RubySlicc.hh"
#include "mem/protocol/${ident}_Controller.hh"
-#include "mem/protocol/${ident}_State.hh"
#include "mem/protocol/${ident}_Event.hh"
+#include "mem/protocol/${ident}_State.hh"
+''')
+
+ if outputRequest_types:
+ code('''#include "mem/protocol/${ident}_RequestType.hh"''')
+
+ code('''
#include "mem/protocol/Types.hh"
+#include "mem/ruby/common/Global.hh"
#include "mem/ruby/system/System.hh"
+''')
-void ${ident}_Controller::wakeup()
-{
+ for include_path in includes:
+ code('#include "${{include_path}}"')
+
+ code('''
+
+using namespace std;
+
+void
+${ident}_Controller::wakeup()
+{
int counter = 0;
while (true) {
// Some cases will put us into an infinite loop without this limit
assert(counter <= m_transitions_per_cycle);
if (counter == m_transitions_per_cycle) {
- g_system_ptr->getProfiler()->controllerBusy(m_machineID); // Count how often we\'re fully utilized
- g_eventQueue_ptr->scheduleEvent(this, 1); // Wakeup in another cycle and try again
+ // Count how often we are fully utilized
+ m_fully_busy_cycles++;
+
+ // Wakeup in another cycle and try again
+ scheduleEvent(Cycles(1));
break;
}
''')
for port in self.in_ports:
code.indent()
code('// ${ident}InPort $port')
+ if port.pairs.has_key("rank"):
+ code('m_cur_in_port = ${{port.pairs["rank"]}};')
+ else:
+ code('m_cur_in_port = 0;')
code('${{port["c_code_in_port"]}}')
code.dedent()
def printCSwitch(self, path):
'''Output switch statement for transition table'''
- code = code_formatter()
+ code = self.symtab.codeFormatter()
ident = self.ident
code('''
// Auto generated C++ code started by $__file__:$__line__
// ${ident}: ${{self.short}}
-#include "mem/ruby/common/Global.hh"
+#include <cassert>
+
+#include "base/misc.hh"
+#include "base/trace.hh"
+#include "debug/ProtocolTrace.hh"
+#include "debug/RubyGenerated.hh"
#include "mem/protocol/${ident}_Controller.hh"
-#include "mem/protocol/${ident}_State.hh"
#include "mem/protocol/${ident}_Event.hh"
+#include "mem/protocol/${ident}_State.hh"
#include "mem/protocol/Types.hh"
+#include "mem/ruby/common/Global.hh"
#include "mem/ruby/system/System.hh"
#define HASH_FUN(state, event) ((int(state)*${ident}_Event_NUM)+int(event))
#define GET_TRANSITION_COMMENT() (${ident}_transitionComment.str())
#define CLEAR_TRANSITION_COMMENT() (${ident}_transitionComment.str(""))
-TransitionResult ${ident}_Controller::doTransition(${ident}_Event event, ${ident}_State state, const Address& addr
-)
+TransitionResult
+${ident}_Controller::doTransition(${ident}_Event event,
+''')
+ if self.EntryType != None:
+ code('''
+ ${{self.EntryType.c_ident}}* m_cache_entry_ptr,
+''')
+ if self.TBEType != None:
+ code('''
+ ${{self.TBEType.c_ident}}* m_tbe_ptr,
+''')
+ code('''
+ const Address addr)
{
- ${ident}_State next_state = state;
-
- DEBUG_NEWLINE(GENERATED_COMP, MedPrio);
- DEBUG_MSG(GENERATED_COMP, MedPrio, *this);
- DEBUG_EXPR(GENERATED_COMP, MedPrio, g_eventQueue_ptr->getTime());
- DEBUG_EXPR(GENERATED_COMP, MedPrio,state);
- DEBUG_EXPR(GENERATED_COMP, MedPrio,event);
- DEBUG_EXPR(GENERATED_COMP, MedPrio,addr);
-
- TransitionResult result = doTransitionWorker(event, state, next_state, addr);
-
- if (result == TransitionResult_Valid) {
- DEBUG_EXPR(GENERATED_COMP, MedPrio, next_state);
- DEBUG_NEWLINE(GENERATED_COMP, MedPrio);
- s_profiler.countTransition(state, event);
- if (Debug::getProtocolTrace()) {
- g_system_ptr->getProfiler()->profileTransition("${ident}", m_version, addr,
- ${ident}_State_to_string(state),
- ${ident}_Event_to_string(event),
- ${ident}_State_to_string(next_state), GET_TRANSITION_COMMENT());
- }
+''')
+ 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(m_tbe_ptr, addr);')
+ elif self.EntryType != None:
+ code('${ident}_State state = getState(m_cache_entry_ptr, addr);')
+ else:
+ code('${ident}_State state = getState(addr);')
+
+ code('''
+${ident}_State next_state = state;
+
+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 =
+''')
+ if self.TBEType != None and self.EntryType != None:
+ code('doTransitionWorker(event, state, next_state, m_tbe_ptr, m_cache_entry_ptr, addr);')
+ elif self.TBEType != None:
+ code('doTransitionWorker(event, state, next_state, m_tbe_ptr, addr);')
+ elif self.EntryType != None:
+ code('doTransitionWorker(event, state, next_state, m_cache_entry_ptr, addr);')
+ else:
+ code('doTransitionWorker(event, state, next_state, addr);')
+
+ code('''
+
+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();
- ${ident}_setState(addr, next_state);
-
- } else if (result == TransitionResult_ResourceStall) {
- if (Debug::getProtocolTrace()) {
- g_system_ptr->getProfiler()->profileTransition("${ident}", m_version, addr,
- ${ident}_State_to_string(state),
- ${ident}_Event_to_string(event),
- ${ident}_State_to_string(next_state),
- "Resource Stall");
- }
- } else if (result == TransitionResult_ProtocolStall) {
- DEBUG_MSG(GENERATED_COMP, HighPrio, "stalling");
- DEBUG_NEWLINE(GENERATED_COMP, MedPrio);
- if (Debug::getProtocolTrace()) {
- g_system_ptr->getProfiler()->profileTransition("${ident}", m_version, addr,
- ${ident}_State_to_string(state),
- ${ident}_Event_to_string(event),
- ${ident}_State_to_string(next_state),
- "Protocol Stall");
- }
- }
+''')
+ if self.TBEType != None and self.EntryType != None:
+ code('setState(m_tbe_ptr, m_cache_entry_ptr, addr, next_state);')
+ code('setAccessPermission(m_cache_entry_ptr, addr, next_state);')
+ elif self.TBEType != None:
+ code('setState(m_tbe_ptr, addr, next_state);')
+ code('setAccessPermission(addr, next_state);')
+ elif self.EntryType != None:
+ code('setState(m_cache_entry_ptr, addr, next_state);')
+ code('setAccessPermission(m_cache_entry_ptr, addr, next_state);')
+ else:
+ code('setState(addr, next_state);')
+ code('setAccessPermission(addr, next_state);')
- return result;
+ 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");
}
-TransitionResult ${ident}_Controller::doTransitionWorker(${ident}_Event event, ${ident}_State state, ${ident}_State& next_state, const Address& addr
-)
+return result;
+''')
+ code.dedent()
+ code('''
+}
+
+TransitionResult
+${ident}_Controller::doTransitionWorker(${ident}_Event event,
+ ${ident}_State state,
+ ${ident}_State& next_state,
+''')
+
+ if self.TBEType != None:
+ code('''
+ ${{self.TBEType.c_ident}}*& m_tbe_ptr,
+''')
+ if self.EntryType != None:
+ code('''
+ ${{self.EntryType.c_ident}}*& m_cache_entry_ptr,
+''')
+ code('''
+ const Address& addr)
{
switch(HASH_FUN(state, event)) {
''')
case_string = "%s_State_%s, %s_Event_%s" % \
(self.ident, trans.state.ident, self.ident, trans.event.ident)
- case = code_formatter()
+ case = self.symtab.codeFormatter()
# Only set next_state if it changes
if trans.state != trans.nextState:
ns_ident = trans.nextState.ident
case('next_state = ${ident}_State_${ns_ident};')
actions = trans.actions
+ request_types = trans.request_types
# Check for resources
case_sorter = []
res = trans.resources
for key,val in res.iteritems():
- if key.type.ident != "DNUCAStopTable":
- val = '''
-if (!%s.areNSlotsAvailable(%s)) {
+ val = '''
+if (!%s.areNSlotsAvailable(%s))
return TransitionResult_ResourceStall;
-}
''' % (key.code, val)
case_sorter.append(val)
+ # Check all of the request_types for resource constraints
+ for request_type in request_types:
+ val = '''
+if (!checkResourceAvailable(%s_RequestType_%s, addr)) {
+ return TransitionResult_ResourceStall;
+}
+''' % (self.ident, request_type.ident)
+ case_sorter.append(val)
# Emit the code sequences in a sorted order. This makes the
# output deterministic (without this the output order can vary
for c in sorted(case_sorter):
case("$c")
+ # Record access types for this transition
+ for request_type in request_types:
+ case('recordRequestType(${ident}_RequestType_${{request_type.ident}}, addr);')
+
# Figure out if we stall
stall = False
for action in actions:
if stall:
case('return TransitionResult_ProtocolStall;')
else:
- for action in actions:
- case('${{action.ident}}(addr);')
+ if self.TBEType != None and self.EntryType != None:
+ for action in actions:
+ case('${{action.ident}}(m_tbe_ptr, m_cache_entry_ptr, addr);')
+ elif self.TBEType != None:
+ for action in actions:
+ case('${{action.ident}}(m_tbe_ptr, addr);')
+ elif self.EntryType != None:
+ for action in actions:
+ case('${{action.ident}}(m_cache_entry_ptr, addr);')
+ else:
+ for action in actions:
+ case('${{action.ident}}(addr);')
case('return TransitionResult_Valid;')
case = str(case)
# the same code
for trans in transitions:
code(' case HASH_FUN($trans):')
- code(' {')
- code(' $case')
- code(' }')
+ code(' $case\n')
code('''
default:
- WARN_EXPR(m_version);
- WARN_EXPR(g_eventQueue_ptr->getTime());
- WARN_EXPR(addr);
- WARN_EXPR(event);
- WARN_EXPR(state);
- ERROR_MSG(\"Invalid transition\");
+ fatal("Invalid transition\\n"
+ "%s time: %d addr: %s event: %s state: %s\\n",
+ name(), curCycle(), addr, event, state);
}
+
return TransitionResult_Valid;
}
''')
code.write(path, "%s_Transitions.cc" % self.ident)
- def printProfilerHH(self, path):
- code = code_formatter()
- ident = self.ident
-
- code('''
-// Auto generated C++ code started by $__file__:$__line__
-// ${ident}: ${{self.short}}
-
-#ifndef ${ident}_PROFILER_H
-#define ${ident}_PROFILER_H
-
-#include "mem/ruby/common/Global.hh"
-#include "mem/protocol/${ident}_State.hh"
-#include "mem/protocol/${ident}_Event.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);
- void dumpStats(ostream& out) const;
- 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_H
-''')
- code.write(path, "%s_Profiler.hh" % self.ident)
-
- def printProfilerCC(self, path):
- code = code_formatter()
- ident = self.ident
-
- code('''
-// Auto generated C++ code started by $__file__:$__line__
-// ${ident}: ${{self.short}}
-
-#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;
-}
-void ${ident}_Profiler::dumpStats(ostream& out) const
-{
- out << " --- ${ident} " << m_version << " ---" << endl;
- out << " - Event Counts -" << endl;
- for (int event = 0; event < ${ident}_Event_NUM; event++) {
- int count = m_event_counters[event];
- out << (${ident}_Event) event << " " << count << endl;
- }
- out << endl;
- out << " - Transitions -" << endl;
- for (int state = 0; state < ${ident}_State_NUM; state++) {
- for (int event = 0; event < ${ident}_Event_NUM; event++) {
- if (m_possible[state][event]) {
- int count = m_counters[state][event];
- out << (${ident}_State) state << " " << (${ident}_Event) event << " " << count;
- if (count == 0) {
- out << " <-- ";
- }
- out << endl;
- }
- }
- out << endl;
- }
-}
-''')
- code.write(path, "%s_Profiler.cc" % self.ident)
# **************************
# ******* HTML Files *******
# **************************
- def frameRef(self, click_href, click_target, over_href, over_target_num,
- text):
- code = code_formatter(fix_newlines=False)
- code("""<A href=\"$click_href\" target=\"$click_target\" onMouseOver=\"if (parent.frames[$over_target_num].location != parent.location + '$over_href') { parent.frames[$over_target_num].location='$over_href' }\" >${{html.formatShorthand(text)}}</A>""")
+ def frameRef(self, click_href, click_target, over_href, over_num, text):
+ code = self.symtab.codeFormatter(fix_newlines=False)
+ code("""<A href=\"$click_href\" target=\"$click_target\" onmouseover=\"
+ if (parent.frames[$over_num].location != parent.location + '$over_href') {
+ parent.frames[$over_num].location='$over_href'
+ }\">
+ ${{html.formatShorthand(text)}}
+ </A>""")
return str(code)
def writeHTMLFiles(self, path):
code.write(path, name)
def printHTMLTransitions(self, path, active_state):
- code = code_formatter()
+ code = self.symtab.codeFormatter()
code('''
-<HTML><BODY link="blue" vlink="blue">
+<HTML>
+<BODY link="blue" vlink="blue">
<H1 align="center">${{html.formatShorthand(self.short)}}:
''')
else:
color = "white"
- fix = code.nofix()
code('<TD bgcolor=$color>')
for action in trans.actions:
href = "%s_action_%s.html" % (self.ident, action.ident)
ref = self.frameRef(href, "Status", href, "1",
action.short)
- code(' $ref\n')
+ code(' $ref')
if next != state:
if trans.actions:
code('/')
over = "%s_State_%s.html" % (self.ident, next.ident)
ref = self.frameRef(click, "Table", over, "1", next.short)
code("$ref")
- code("</TD>\n")
- code.fix(fix)
+ code("</TD>")
# -- Each row
if state == active_state:
</TR>
''')
code('''
+<!- Column footer->
<TR>
<TH> </TH>
''')