StateMachine.py revision 11113:5a2e1b1b5c43
113531Sjairo.balart@metempsy.com# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 213531Sjairo.balart@metempsy.com# Copyright (c) 2009 The Hewlett-Packard Development Company 313531Sjairo.balart@metempsy.com# Copyright (c) 2013 Advanced Micro Devices, Inc. 413531Sjairo.balart@metempsy.com# All rights reserved. 513531Sjairo.balart@metempsy.com# 613531Sjairo.balart@metempsy.com# Redistribution and use in source and binary forms, with or without 713531Sjairo.balart@metempsy.com# modification, are permitted provided that the following conditions are 813531Sjairo.balart@metempsy.com# met: redistributions of source code must retain the above copyright 913531Sjairo.balart@metempsy.com# notice, this list of conditions and the following disclaimer; 1013531Sjairo.balart@metempsy.com# redistributions in binary form must reproduce the above copyright 1113531Sjairo.balart@metempsy.com# notice, this list of conditions and the following disclaimer in the 1213531Sjairo.balart@metempsy.com# documentation and/or other materials provided with the distribution; 1313531Sjairo.balart@metempsy.com# neither the name of the copyright holders nor the names of its 1413531Sjairo.balart@metempsy.com# contributors may be used to endorse or promote products derived from 1513531Sjairo.balart@metempsy.com# this software without specific prior written permission. 1613531Sjairo.balart@metempsy.com# 1713531Sjairo.balart@metempsy.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1813531Sjairo.balart@metempsy.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1913531Sjairo.balart@metempsy.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2013531Sjairo.balart@metempsy.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2113531Sjairo.balart@metempsy.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2213531Sjairo.balart@metempsy.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2313531Sjairo.balart@metempsy.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2413531Sjairo.balart@metempsy.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2513531Sjairo.balart@metempsy.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2613531Sjairo.balart@metempsy.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2713531Sjairo.balart@metempsy.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2813531Sjairo.balart@metempsy.com 2913531Sjairo.balart@metempsy.comfrom m5.util import orderdict 3013756Sjairo.balart@metempsy.com 3113531Sjairo.balart@metempsy.comfrom slicc.symbols.Symbol import Symbol 3213531Sjairo.balart@metempsy.comfrom slicc.symbols.Var import Var 3313531Sjairo.balart@metempsy.comimport slicc.generate.html as html 3413531Sjairo.balart@metempsy.comimport re 3513531Sjairo.balart@metempsy.com 3613531Sjairo.balart@metempsy.compython_class_map = { 3713531Sjairo.balart@metempsy.com "int": "Int", 3813531Sjairo.balart@metempsy.com "uint32_t" : "UInt32", 3913531Sjairo.balart@metempsy.com "std::string": "String", 4013756Sjairo.balart@metempsy.com "bool": "Bool", 4113756Sjairo.balart@metempsy.com "CacheMemory": "RubyCache", 4213756Sjairo.balart@metempsy.com "WireBuffer": "RubyWireBuffer", 4313756Sjairo.balart@metempsy.com "Sequencer": "RubySequencer", 4413756Sjairo.balart@metempsy.com "DirectoryMemory": "RubyDirectoryMemory", 4513756Sjairo.balart@metempsy.com "MemoryControl": "MemoryControl", 4613756Sjairo.balart@metempsy.com "MessageBuffer": "MessageBuffer", 4713531Sjairo.balart@metempsy.com "DMASequencer": "DMASequencer", 4813756Sjairo.balart@metempsy.com "Prefetcher":"Prefetcher", 4913756Sjairo.balart@metempsy.com "Cycles":"Cycles", 5013756Sjairo.balart@metempsy.com } 5113756Sjairo.balart@metempsy.com 5213756Sjairo.balart@metempsy.comclass StateMachine(Symbol): 5313756Sjairo.balart@metempsy.com def __init__(self, symtab, ident, location, pairs, config_parameters): 5413756Sjairo.balart@metempsy.com super(StateMachine, self).__init__(symtab, ident, location, pairs) 5513531Sjairo.balart@metempsy.com self.table = None 5613531Sjairo.balart@metempsy.com 5713531Sjairo.balart@metempsy.com # Data members in the State Machine that have been declared before 5813531Sjairo.balart@metempsy.com # the opening brace '{' of the machine. Note that these along with 5913531Sjairo.balart@metempsy.com # the members in self.objects form the entire set of data members. 6013531Sjairo.balart@metempsy.com self.config_parameters = config_parameters 6113531Sjairo.balart@metempsy.com 6213531Sjairo.balart@metempsy.com self.prefetchers = [] 6313531Sjairo.balart@metempsy.com 6413531Sjairo.balart@metempsy.com for param in config_parameters: 6513531Sjairo.balart@metempsy.com if param.pointer: 6613531Sjairo.balart@metempsy.com var = Var(symtab, param.ident, location, param.type_ast.type, 6713531Sjairo.balart@metempsy.com "(*m_%s_ptr)" % param.ident, {}, self) 6813531Sjairo.balart@metempsy.com else: 6913531Sjairo.balart@metempsy.com var = Var(symtab, param.ident, location, param.type_ast.type, 7013531Sjairo.balart@metempsy.com "m_%s" % param.ident, {}, self) 7113531Sjairo.balart@metempsy.com 7213531Sjairo.balart@metempsy.com self.symtab.registerSym(param.ident, var) 7313531Sjairo.balart@metempsy.com 7413531Sjairo.balart@metempsy.com if str(param.type_ast.type) == "Prefetcher": 7513531Sjairo.balart@metempsy.com self.prefetchers.append(var) 7613531Sjairo.balart@metempsy.com 7713531Sjairo.balart@metempsy.com self.states = orderdict() 7813531Sjairo.balart@metempsy.com self.events = orderdict() 7913531Sjairo.balart@metempsy.com self.actions = orderdict() 8013531Sjairo.balart@metempsy.com self.request_types = orderdict() 8113531Sjairo.balart@metempsy.com self.transitions = [] 8213531Sjairo.balart@metempsy.com self.in_ports = [] 8313531Sjairo.balart@metempsy.com self.functions = [] 8413531Sjairo.balart@metempsy.com 8513531Sjairo.balart@metempsy.com # Data members in the State Machine that have been declared inside 8613531Sjairo.balart@metempsy.com # the {} machine. Note that these along with the config params 8713531Sjairo.balart@metempsy.com # form the entire set of data members of the machine. 8813531Sjairo.balart@metempsy.com self.objects = [] 8913531Sjairo.balart@metempsy.com self.TBEType = None 9013531Sjairo.balart@metempsy.com self.EntryType = None 9113531Sjairo.balart@metempsy.com self.debug_flags = set() 9213531Sjairo.balart@metempsy.com self.debug_flags.add('RubyGenerated') 9313531Sjairo.balart@metempsy.com self.debug_flags.add('RubySlicc') 9413531Sjairo.balart@metempsy.com 9513531Sjairo.balart@metempsy.com def __repr__(self): 9613531Sjairo.balart@metempsy.com return "[StateMachine: %s]" % self.ident 9713531Sjairo.balart@metempsy.com 9813531Sjairo.balart@metempsy.com def addState(self, state): 9913531Sjairo.balart@metempsy.com assert self.table is None 10013531Sjairo.balart@metempsy.com self.states[state.ident] = state 10113531Sjairo.balart@metempsy.com 10213531Sjairo.balart@metempsy.com def addEvent(self, event): 10313531Sjairo.balart@metempsy.com assert self.table is None 10413531Sjairo.balart@metempsy.com self.events[event.ident] = event 10513531Sjairo.balart@metempsy.com 10613531Sjairo.balart@metempsy.com def addAction(self, action): 10713531Sjairo.balart@metempsy.com assert self.table is None 10813531Sjairo.balart@metempsy.com 10913531Sjairo.balart@metempsy.com # Check for duplicate action 11013531Sjairo.balart@metempsy.com for other in self.actions.itervalues(): 11113531Sjairo.balart@metempsy.com if action.ident == other.ident: 11213531Sjairo.balart@metempsy.com action.warning("Duplicate action definition: %s" % action.ident) 11313531Sjairo.balart@metempsy.com action.error("Duplicate action definition: %s" % action.ident) 11413531Sjairo.balart@metempsy.com if action.short == other.short: 11513531Sjairo.balart@metempsy.com other.warning("Duplicate action shorthand: %s" % other.ident) 11613531Sjairo.balart@metempsy.com other.warning(" shorthand = %s" % other.short) 11713531Sjairo.balart@metempsy.com action.warning("Duplicate action shorthand: %s" % action.ident) 11813531Sjairo.balart@metempsy.com action.error(" shorthand = %s" % action.short) 11913531Sjairo.balart@metempsy.com 12013531Sjairo.balart@metempsy.com self.actions[action.ident] = action 12113531Sjairo.balart@metempsy.com 12213531Sjairo.balart@metempsy.com def addDebugFlag(self, flag): 12313531Sjairo.balart@metempsy.com self.debug_flags.add(flag) 12413531Sjairo.balart@metempsy.com 12513531Sjairo.balart@metempsy.com def addRequestType(self, request_type): 12613531Sjairo.balart@metempsy.com assert self.table is None 12713531Sjairo.balart@metempsy.com self.request_types[request_type.ident] = request_type 12813531Sjairo.balart@metempsy.com 12913531Sjairo.balart@metempsy.com def addTransition(self, trans): 13013531Sjairo.balart@metempsy.com assert self.table is None 13113531Sjairo.balart@metempsy.com self.transitions.append(trans) 13213756Sjairo.balart@metempsy.com 13313531Sjairo.balart@metempsy.com def addInPort(self, var): 13413531Sjairo.balart@metempsy.com self.in_ports.append(var) 13513531Sjairo.balart@metempsy.com 13613531Sjairo.balart@metempsy.com def addFunc(self, func): 13713756Sjairo.balart@metempsy.com # register func in the symbol table 13813531Sjairo.balart@metempsy.com self.symtab.registerSym(str(func), func) 13913531Sjairo.balart@metempsy.com self.functions.append(func) 14013531Sjairo.balart@metempsy.com 14113531Sjairo.balart@metempsy.com def addObject(self, obj): 14213531Sjairo.balart@metempsy.com self.symtab.registerSym(str(obj), obj) 14313531Sjairo.balart@metempsy.com self.objects.append(obj) 14413531Sjairo.balart@metempsy.com 14513531Sjairo.balart@metempsy.com def addType(self, type): 14613531Sjairo.balart@metempsy.com type_ident = '%s' % type.c_ident 14713756Sjairo.balart@metempsy.com 14813756Sjairo.balart@metempsy.com if type_ident == "%s_TBE" %self.ident: 14913531Sjairo.balart@metempsy.com if self.TBEType != None: 15013531Sjairo.balart@metempsy.com self.error("Multiple Transaction Buffer types in a " \ 15113531Sjairo.balart@metempsy.com "single machine."); 15213531Sjairo.balart@metempsy.com self.TBEType = type 15313531Sjairo.balart@metempsy.com 15413531Sjairo.balart@metempsy.com elif "interface" in type and "AbstractCacheEntry" == type["interface"]: 15513531Sjairo.balart@metempsy.com if "main" in type and "false" == type["main"].lower(): 15613531Sjairo.balart@metempsy.com pass # this isn't the EntryType 15713531Sjairo.balart@metempsy.com else: 15813531Sjairo.balart@metempsy.com if self.EntryType != None: 15913531Sjairo.balart@metempsy.com self.error("Multiple AbstractCacheEntry types in a " \ 16013531Sjairo.balart@metempsy.com "single machine."); 16113531Sjairo.balart@metempsy.com self.EntryType = type 16213531Sjairo.balart@metempsy.com 16313531Sjairo.balart@metempsy.com # Needs to be called before accessing the table 16413531Sjairo.balart@metempsy.com def buildTable(self): 16513531Sjairo.balart@metempsy.com assert self.table is None 16613531Sjairo.balart@metempsy.com 16713531Sjairo.balart@metempsy.com table = {} 16813756Sjairo.balart@metempsy.com 16913756Sjairo.balart@metempsy.com for trans in self.transitions: 17013531Sjairo.balart@metempsy.com # Track which actions we touch so we know if we use them 17113531Sjairo.balart@metempsy.com # all -- really this should be done for all symbols as 17213531Sjairo.balart@metempsy.com # part of the symbol table, then only trigger it for 17313531Sjairo.balart@metempsy.com # Actions, States, Events, etc. 17413531Sjairo.balart@metempsy.com 17513531Sjairo.balart@metempsy.com for action in trans.actions: 17613531Sjairo.balart@metempsy.com action.used = True 17713531Sjairo.balart@metempsy.com 17813531Sjairo.balart@metempsy.com index = (trans.state, trans.event) 17913531Sjairo.balart@metempsy.com if index in table: 18013756Sjairo.balart@metempsy.com table[index].warning("Duplicate transition: %s" % table[index]) 18113531Sjairo.balart@metempsy.com trans.error("Duplicate transition: %s" % trans) 18213531Sjairo.balart@metempsy.com table[index] = trans 18313531Sjairo.balart@metempsy.com 18413531Sjairo.balart@metempsy.com # Look at all actions to make sure we used them all 18513531Sjairo.balart@metempsy.com for action in self.actions.itervalues(): 18613531Sjairo.balart@metempsy.com if not action.used: 18713531Sjairo.balart@metempsy.com error_msg = "Unused action: %s" % action.ident 18813531Sjairo.balart@metempsy.com if "desc" in action: 18913756Sjairo.balart@metempsy.com error_msg += ", " + action.desc 19013756Sjairo.balart@metempsy.com action.warning(error_msg) 19113531Sjairo.balart@metempsy.com self.table = table 19213531Sjairo.balart@metempsy.com 19313531Sjairo.balart@metempsy.com # determine the port->msg buffer mappings 19413531Sjairo.balart@metempsy.com def getBufferMaps(self, ident): 19513531Sjairo.balart@metempsy.com msg_bufs = [] 19613531Sjairo.balart@metempsy.com port_to_buf_map = {} 19713531Sjairo.balart@metempsy.com in_msg_bufs = {} 19813531Sjairo.balart@metempsy.com for port in self.in_ports: 19913531Sjairo.balart@metempsy.com buf_name = "m_%s_ptr" % port.pairs["buffer_expr"].name 20013531Sjairo.balart@metempsy.com msg_bufs.append(buf_name) 20113531Sjairo.balart@metempsy.com port_to_buf_map[port] = msg_bufs.index(buf_name) 20213531Sjairo.balart@metempsy.com if buf_name not in in_msg_bufs: 20313531Sjairo.balart@metempsy.com in_msg_bufs[buf_name] = [port] 20413756Sjairo.balart@metempsy.com else: 20513531Sjairo.balart@metempsy.com in_msg_bufs[buf_name].append(port) 20613531Sjairo.balart@metempsy.com return port_to_buf_map, in_msg_bufs, msg_bufs 20713531Sjairo.balart@metempsy.com 20813531Sjairo.balart@metempsy.com def writeCodeFiles(self, path, includes): 20913531Sjairo.balart@metempsy.com self.printControllerPython(path) 21013531Sjairo.balart@metempsy.com self.printControllerHH(path) 21113531Sjairo.balart@metempsy.com self.printControllerCC(path, includes) 21213531Sjairo.balart@metempsy.com self.printCSwitch(path) 21313756Sjairo.balart@metempsy.com self.printCWakeup(path, includes) 21413756Sjairo.balart@metempsy.com 21513531Sjairo.balart@metempsy.com def printControllerPython(self, path): 21613531Sjairo.balart@metempsy.com code = self.symtab.codeFormatter() 21713531Sjairo.balart@metempsy.com ident = self.ident 21813531Sjairo.balart@metempsy.com 21913531Sjairo.balart@metempsy.com py_ident = "%s_Controller" % ident 22013531Sjairo.balart@metempsy.com c_ident = "%s_Controller" % self.ident 22113531Sjairo.balart@metempsy.com 22213531Sjairo.balart@metempsy.com code(''' 22313531Sjairo.balart@metempsy.comfrom m5.params import * 22413531Sjairo.balart@metempsy.comfrom m5.SimObject import SimObject 22513531Sjairo.balart@metempsy.comfrom Controller import RubyController 22613531Sjairo.balart@metempsy.com 22713756Sjairo.balart@metempsy.comclass $py_ident(RubyController): 22813531Sjairo.balart@metempsy.com type = '$py_ident' 22913531Sjairo.balart@metempsy.com cxx_header = 'mem/protocol/${c_ident}.hh' 23013531Sjairo.balart@metempsy.com''') 23113531Sjairo.balart@metempsy.com code.indent() 23213531Sjairo.balart@metempsy.com for param in self.config_parameters: 23313531Sjairo.balart@metempsy.com dflt_str = '' 23413531Sjairo.balart@metempsy.com 23513531Sjairo.balart@metempsy.com if param.rvalue is not None: 23613531Sjairo.balart@metempsy.com dflt_str = str(param.rvalue.inline()) + ', ' 23713531Sjairo.balart@metempsy.com 23813756Sjairo.balart@metempsy.com if python_class_map.has_key(param.type_ast.type.c_ident): 23913756Sjairo.balart@metempsy.com python_type = python_class_map[param.type_ast.type.c_ident] 24013531Sjairo.balart@metempsy.com code('${{param.ident}} = Param.${{python_type}}(${dflt_str}"")') 24113531Sjairo.balart@metempsy.com 24213531Sjairo.balart@metempsy.com else: 24313531Sjairo.balart@metempsy.com self.error("Unknown c++ to python class conversion for c++ " \ 24413531Sjairo.balart@metempsy.com "type: '%s'. Please update the python_class_map " \ 24513531Sjairo.balart@metempsy.com "in StateMachine.py", param.type_ast.type.c_ident) 24613531Sjairo.balart@metempsy.com 24713531Sjairo.balart@metempsy.com code.dedent() 24813531Sjairo.balart@metempsy.com code.write(path, '%s.py' % py_ident) 24913531Sjairo.balart@metempsy.com 25013531Sjairo.balart@metempsy.com 25113531Sjairo.balart@metempsy.com def printControllerHH(self, path): 25213756Sjairo.balart@metempsy.com '''Output the method declarations for the class declaration''' 25313531Sjairo.balart@metempsy.com code = self.symtab.codeFormatter() 25413531Sjairo.balart@metempsy.com ident = self.ident 25513531Sjairo.balart@metempsy.com c_ident = "%s_Controller" % self.ident 25613531Sjairo.balart@metempsy.com 25713531Sjairo.balart@metempsy.com code(''' 25813531Sjairo.balart@metempsy.com/** \\file $c_ident.hh 25913531Sjairo.balart@metempsy.com * 26013531Sjairo.balart@metempsy.com * Auto generated C++ code started by $__file__:$__line__ 26113531Sjairo.balart@metempsy.com * Created by slicc definition of Module "${{self.short}}" 26213531Sjairo.balart@metempsy.com */ 26313756Sjairo.balart@metempsy.com 26413756Sjairo.balart@metempsy.com#ifndef __${ident}_CONTROLLER_HH__ 26513531Sjairo.balart@metempsy.com#define __${ident}_CONTROLLER_HH__ 26613531Sjairo.balart@metempsy.com 26713531Sjairo.balart@metempsy.com#include <iostream> 26813531Sjairo.balart@metempsy.com#include <sstream> 26913531Sjairo.balart@metempsy.com#include <string> 27013531Sjairo.balart@metempsy.com 27113531Sjairo.balart@metempsy.com#include "mem/protocol/TransitionResult.hh" 27213531Sjairo.balart@metempsy.com#include "mem/protocol/Types.hh" 27313531Sjairo.balart@metempsy.com#include "mem/ruby/common/Consumer.hh" 27413531Sjairo.balart@metempsy.com#include "mem/ruby/slicc_interface/AbstractController.hh" 27513531Sjairo.balart@metempsy.com#include "params/$c_ident.hh" 27613756Sjairo.balart@metempsy.com 27713531Sjairo.balart@metempsy.com''') 27813531Sjairo.balart@metempsy.com 27913531Sjairo.balart@metempsy.com seen_types = set() 28013531Sjairo.balart@metempsy.com for var in self.objects: 28113531Sjairo.balart@metempsy.com if var.type.ident not in seen_types and not var.type.isPrimitive: 28213531Sjairo.balart@metempsy.com code('#include "mem/protocol/${{var.type.c_ident}}.hh"') 28313531Sjairo.balart@metempsy.com seen_types.add(var.type.ident) 28413531Sjairo.balart@metempsy.com 28513531Sjairo.balart@metempsy.com # for adding information to the protocol debug trace 28613756Sjairo.balart@metempsy.com code(''' 28713756Sjairo.balart@metempsy.comextern std::stringstream ${ident}_transitionComment; 28813531Sjairo.balart@metempsy.com 28913531Sjairo.balart@metempsy.comclass $c_ident : public AbstractController 29013531Sjairo.balart@metempsy.com{ 29113531Sjairo.balart@metempsy.com public: 29213531Sjairo.balart@metempsy.com typedef ${c_ident}Params Params; 29313531Sjairo.balart@metempsy.com $c_ident(const Params *p); 29413531Sjairo.balart@metempsy.com static int getNumControllers(); 29513531Sjairo.balart@metempsy.com void init(); 29613531Sjairo.balart@metempsy.com 29713531Sjairo.balart@metempsy.com MessageBuffer *getMandatoryQueue() const; 29813531Sjairo.balart@metempsy.com MessageBuffer *getMemoryQueue() const; 29913531Sjairo.balart@metempsy.com void initNetQueues(); 30013531Sjairo.balart@metempsy.com 30113531Sjairo.balart@metempsy.com void print(std::ostream& out) const; 30213531Sjairo.balart@metempsy.com void wakeup(); 30313531Sjairo.balart@metempsy.com void resetStats(); 30413531Sjairo.balart@metempsy.com void regStats(); 30513531Sjairo.balart@metempsy.com void collateStats(); 30613531Sjairo.balart@metempsy.com 30713531Sjairo.balart@metempsy.com void recordCacheTrace(int cntrl, CacheRecorder* tr); 30813531Sjairo.balart@metempsy.com Sequencer* getSequencer() const; 30913531Sjairo.balart@metempsy.com 31013756Sjairo.balart@metempsy.com int functionalWriteBuffers(PacketPtr&); 31113531Sjairo.balart@metempsy.com 31213531Sjairo.balart@metempsy.com void countTransition(${ident}_State state, ${ident}_Event event); 31313531Sjairo.balart@metempsy.com void possibleTransition(${ident}_State state, ${ident}_Event event); 31413531Sjairo.balart@metempsy.com uint64_t getEventCount(${ident}_Event event); 31513531Sjairo.balart@metempsy.com bool isPossible(${ident}_State state, ${ident}_Event event); 31613531Sjairo.balart@metempsy.com uint64_t getTransitionCount(${ident}_State state, ${ident}_Event event); 31713531Sjairo.balart@metempsy.com 31813531Sjairo.balart@metempsy.comprivate: 31913531Sjairo.balart@metempsy.com''') 32013531Sjairo.balart@metempsy.com 32113756Sjairo.balart@metempsy.com code.indent() 32213756Sjairo.balart@metempsy.com # added by SS 32313531Sjairo.balart@metempsy.com for param in self.config_parameters: 32413531Sjairo.balart@metempsy.com if param.pointer: 32513531Sjairo.balart@metempsy.com code('${{param.type_ast.type}}* m_${{param.ident}}_ptr;') 32613531Sjairo.balart@metempsy.com else: 32713531Sjairo.balart@metempsy.com code('${{param.type_ast.type}} m_${{param.ident}};') 32813531Sjairo.balart@metempsy.com 32913531Sjairo.balart@metempsy.com code(''' 33013531Sjairo.balart@metempsy.comTransitionResult doTransition(${ident}_Event event, 33113531Sjairo.balart@metempsy.com''') 33213531Sjairo.balart@metempsy.com 33313531Sjairo.balart@metempsy.com if self.EntryType != None: 33413531Sjairo.balart@metempsy.com code(''' 33513531Sjairo.balart@metempsy.com ${{self.EntryType.c_ident}}* m_cache_entry_ptr, 33613531Sjairo.balart@metempsy.com''') 33713531Sjairo.balart@metempsy.com if self.TBEType != None: 33813531Sjairo.balart@metempsy.com code(''' 33913531Sjairo.balart@metempsy.com ${{self.TBEType.c_ident}}* m_tbe_ptr, 34013531Sjairo.balart@metempsy.com''') 34113531Sjairo.balart@metempsy.com 34213531Sjairo.balart@metempsy.com code(''' 34313531Sjairo.balart@metempsy.com Addr addr); 34413531Sjairo.balart@metempsy.com 34513531Sjairo.balart@metempsy.comTransitionResult doTransitionWorker(${ident}_Event event, 34613531Sjairo.balart@metempsy.com ${ident}_State state, 34713531Sjairo.balart@metempsy.com ${ident}_State& next_state, 34813531Sjairo.balart@metempsy.com''') 34913531Sjairo.balart@metempsy.com 35013531Sjairo.balart@metempsy.com if self.TBEType != None: 35113531Sjairo.balart@metempsy.com code(''' 35213531Sjairo.balart@metempsy.com ${{self.TBEType.c_ident}}*& m_tbe_ptr, 35313756Sjairo.balart@metempsy.com''') 35413531Sjairo.balart@metempsy.com if self.EntryType != None: 35513531Sjairo.balart@metempsy.com code(''' 35613531Sjairo.balart@metempsy.com ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, 35713531Sjairo.balart@metempsy.com''') 35813531Sjairo.balart@metempsy.com 35913531Sjairo.balart@metempsy.com code(''' 36013756Sjairo.balart@metempsy.com Addr addr); 36113531Sjairo.balart@metempsy.com 36213531Sjairo.balart@metempsy.comint m_counters[${ident}_State_NUM][${ident}_Event_NUM]; 36313531Sjairo.balart@metempsy.comint m_event_counters[${ident}_Event_NUM]; 36413531Sjairo.balart@metempsy.combool m_possible[${ident}_State_NUM][${ident}_Event_NUM]; 36513531Sjairo.balart@metempsy.com 36613531Sjairo.balart@metempsy.comstatic std::vector<Stats::Vector *> eventVec; 36713531Sjairo.balart@metempsy.comstatic std::vector<std::vector<Stats::Vector *> > transVec; 36813531Sjairo.balart@metempsy.comstatic int m_num_controllers; 36913531Sjairo.balart@metempsy.com 37013531Sjairo.balart@metempsy.com// Internal functions 37113531Sjairo.balart@metempsy.com''') 37213531Sjairo.balart@metempsy.com 37313531Sjairo.balart@metempsy.com for func in self.functions: 37413531Sjairo.balart@metempsy.com proto = func.prototype 37513531Sjairo.balart@metempsy.com if proto: 37613756Sjairo.balart@metempsy.com code('$proto') 37713531Sjairo.balart@metempsy.com 37813531Sjairo.balart@metempsy.com if self.EntryType != None: 37913531Sjairo.balart@metempsy.com code(''' 38013531Sjairo.balart@metempsy.com 38113531Sjairo.balart@metempsy.com// Set and Reset for cache_entry variable 38213531Sjairo.balart@metempsy.comvoid set_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, AbstractCacheEntry* m_new_cache_entry); 38313531Sjairo.balart@metempsy.comvoid unset_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr); 38413531Sjairo.balart@metempsy.com''') 38513531Sjairo.balart@metempsy.com 38613531Sjairo.balart@metempsy.com if self.TBEType != None: 38713531Sjairo.balart@metempsy.com code(''' 38813531Sjairo.balart@metempsy.com 38913531Sjairo.balart@metempsy.com// Set and Reset for tbe variable 39013531Sjairo.balart@metempsy.comvoid set_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${ident}_TBE* m_new_tbe); 39113531Sjairo.balart@metempsy.comvoid unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr); 39213531Sjairo.balart@metempsy.com''') 39313531Sjairo.balart@metempsy.com 39413531Sjairo.balart@metempsy.com # Prototype the actions that the controller can take 39513531Sjairo.balart@metempsy.com code(''' 39613531Sjairo.balart@metempsy.com 39713531Sjairo.balart@metempsy.com// Actions 39813531Sjairo.balart@metempsy.com''') 39913531Sjairo.balart@metempsy.com if self.TBEType != None and self.EntryType != None: 40013531Sjairo.balart@metempsy.com for action in self.actions.itervalues(): 40113531Sjairo.balart@metempsy.com code('/** \\brief ${{action.desc}} */') 40213531Sjairo.balart@metempsy.com code('void ${{action.ident}}(${{self.TBEType.c_ident}}*& ' 40313531Sjairo.balart@metempsy.com 'm_tbe_ptr, ${{self.EntryType.c_ident}}*& ' 40413531Sjairo.balart@metempsy.com 'm_cache_entry_ptr, Addr addr);') 40513531Sjairo.balart@metempsy.com elif self.TBEType != None: 40613531Sjairo.balart@metempsy.com for action in self.actions.itervalues(): 40713531Sjairo.balart@metempsy.com code('/** \\brief ${{action.desc}} */') 40813531Sjairo.balart@metempsy.com code('void ${{action.ident}}(${{self.TBEType.c_ident}}*& ' 40913531Sjairo.balart@metempsy.com 'm_tbe_ptr, Addr addr);') 41013531Sjairo.balart@metempsy.com elif self.EntryType != None: 41113531Sjairo.balart@metempsy.com for action in self.actions.itervalues(): 41213531Sjairo.balart@metempsy.com code('/** \\brief ${{action.desc}} */') 41313531Sjairo.balart@metempsy.com code('void ${{action.ident}}(${{self.EntryType.c_ident}}*& ' 41413531Sjairo.balart@metempsy.com 'm_cache_entry_ptr, Addr addr);') 41513531Sjairo.balart@metempsy.com else: 41613531Sjairo.balart@metempsy.com for action in self.actions.itervalues(): 41713531Sjairo.balart@metempsy.com code('/** \\brief ${{action.desc}} */') 41813531Sjairo.balart@metempsy.com code('void ${{action.ident}}(Addr addr);') 41913531Sjairo.balart@metempsy.com 42013531Sjairo.balart@metempsy.com # the controller internal variables 42113531Sjairo.balart@metempsy.com code(''' 42213531Sjairo.balart@metempsy.com 42313531Sjairo.balart@metempsy.com// Objects 42413531Sjairo.balart@metempsy.com''') 42513531Sjairo.balart@metempsy.com for var in self.objects: 42613531Sjairo.balart@metempsy.com th = var.get("template", "") 42713531Sjairo.balart@metempsy.com code('${{var.type.c_ident}}$th* m_${{var.ident}}_ptr;') 42813531Sjairo.balart@metempsy.com 42913531Sjairo.balart@metempsy.com code.dedent() 43013531Sjairo.balart@metempsy.com code('};') 43113531Sjairo.balart@metempsy.com code('#endif // __${ident}_CONTROLLER_H__') 43213531Sjairo.balart@metempsy.com code.write(path, '%s.hh' % c_ident) 43313531Sjairo.balart@metempsy.com 43413531Sjairo.balart@metempsy.com def printControllerCC(self, path, includes): 43513531Sjairo.balart@metempsy.com '''Output the actions for performing the actions''' 43613531Sjairo.balart@metempsy.com 43713531Sjairo.balart@metempsy.com code = self.symtab.codeFormatter() 43813531Sjairo.balart@metempsy.com ident = self.ident 43913531Sjairo.balart@metempsy.com c_ident = "%s_Controller" % self.ident 44013531Sjairo.balart@metempsy.com 44113531Sjairo.balart@metempsy.com code(''' 44213531Sjairo.balart@metempsy.com/** \\file $c_ident.cc 44313531Sjairo.balart@metempsy.com * 44413531Sjairo.balart@metempsy.com * Auto generated C++ code started by $__file__:$__line__ 44513531Sjairo.balart@metempsy.com * Created by slicc definition of Module "${{self.short}}" 44613531Sjairo.balart@metempsy.com */ 44713531Sjairo.balart@metempsy.com 44813531Sjairo.balart@metempsy.com#include <sys/types.h> 44913531Sjairo.balart@metempsy.com#include <unistd.h> 45013531Sjairo.balart@metempsy.com 45113531Sjairo.balart@metempsy.com#include <cassert> 45213531Sjairo.balart@metempsy.com#include <sstream> 45313531Sjairo.balart@metempsy.com#include <string> 45413531Sjairo.balart@metempsy.com#include <typeinfo> 45513531Sjairo.balart@metempsy.com 45613531Sjairo.balart@metempsy.com#include "base/compiler.hh" 45713531Sjairo.balart@metempsy.com#include "base/cprintf.hh" 45813531Sjairo.balart@metempsy.com 45913531Sjairo.balart@metempsy.com''') 46013690Sjairo.balart@metempsy.com for f in self.debug_flags: 46113531Sjairo.balart@metempsy.com code('#include "debug/${{f}}.hh"') 46213531Sjairo.balart@metempsy.com code(''' 46313531Sjairo.balart@metempsy.com#include "mem/protocol/${ident}_Controller.hh" 46413531Sjairo.balart@metempsy.com#include "mem/protocol/${ident}_Event.hh" 46513531Sjairo.balart@metempsy.com#include "mem/protocol/${ident}_State.hh" 46613531Sjairo.balart@metempsy.com#include "mem/protocol/Types.hh" 46713531Sjairo.balart@metempsy.com#include "mem/ruby/system/RubySystem.hh" 46813531Sjairo.balart@metempsy.com 46913531Sjairo.balart@metempsy.com''') 47013531Sjairo.balart@metempsy.com for include_path in includes: 47113531Sjairo.balart@metempsy.com code('#include "${{include_path}}"') 47213531Sjairo.balart@metempsy.com 47313531Sjairo.balart@metempsy.com code(''' 47413531Sjairo.balart@metempsy.com 47513531Sjairo.balart@metempsy.comusing namespace std; 47613690Sjairo.balart@metempsy.com''') 47713531Sjairo.balart@metempsy.com 47813531Sjairo.balart@metempsy.com # include object classes 47913531Sjairo.balart@metempsy.com seen_types = set() 48013531Sjairo.balart@metempsy.com for var in self.objects: 48113531Sjairo.balart@metempsy.com if var.type.ident not in seen_types and not var.type.isPrimitive: 48213531Sjairo.balart@metempsy.com code('#include "mem/protocol/${{var.type.c_ident}}.hh"') 48313531Sjairo.balart@metempsy.com seen_types.add(var.type.ident) 48413531Sjairo.balart@metempsy.com 48513531Sjairo.balart@metempsy.com num_in_ports = len(self.in_ports) 48613531Sjairo.balart@metempsy.com 48713531Sjairo.balart@metempsy.com code(''' 48813756Sjairo.balart@metempsy.com$c_ident * 48913756Sjairo.balart@metempsy.com${c_ident}Params::create() 49013531Sjairo.balart@metempsy.com{ 49113531Sjairo.balart@metempsy.com return new $c_ident(this); 49213531Sjairo.balart@metempsy.com} 49313531Sjairo.balart@metempsy.com 49413531Sjairo.balart@metempsy.comint $c_ident::m_num_controllers = 0; 49513531Sjairo.balart@metempsy.comstd::vector<Stats::Vector *> $c_ident::eventVec; 49613531Sjairo.balart@metempsy.comstd::vector<std::vector<Stats::Vector *> > $c_ident::transVec; 49713531Sjairo.balart@metempsy.com 49813531Sjairo.balart@metempsy.com// for adding information to the protocol debug trace 49913531Sjairo.balart@metempsy.comstringstream ${ident}_transitionComment; 50013531Sjairo.balart@metempsy.com 50113531Sjairo.balart@metempsy.com#ifndef NDEBUG 50213531Sjairo.balart@metempsy.com#define APPEND_TRANSITION_COMMENT(str) (${ident}_transitionComment << str) 50313531Sjairo.balart@metempsy.com#else 50413531Sjairo.balart@metempsy.com#define APPEND_TRANSITION_COMMENT(str) do {} while (0) 50513531Sjairo.balart@metempsy.com#endif 50613531Sjairo.balart@metempsy.com 50713531Sjairo.balart@metempsy.com/** \\brief constructor */ 50813531Sjairo.balart@metempsy.com$c_ident::$c_ident(const Params *p) 50913531Sjairo.balart@metempsy.com : AbstractController(p) 51013531Sjairo.balart@metempsy.com{ 51113531Sjairo.balart@metempsy.com m_machineID.type = MachineType_${ident}; 51213531Sjairo.balart@metempsy.com m_machineID.num = m_version; 51313531Sjairo.balart@metempsy.com m_num_controllers++; 51413531Sjairo.balart@metempsy.com 51513531Sjairo.balart@metempsy.com m_in_ports = $num_in_ports; 51613531Sjairo.balart@metempsy.com''') 51713531Sjairo.balart@metempsy.com code.indent() 51813531Sjairo.balart@metempsy.com 51913531Sjairo.balart@metempsy.com # 52013531Sjairo.balart@metempsy.com # After initializing the universal machine parameters, initialize the 52113531Sjairo.balart@metempsy.com # this machines config parameters. Also if these configuration params 52213531Sjairo.balart@metempsy.com # include a sequencer, connect the it to the controller. 52313531Sjairo.balart@metempsy.com # 52413531Sjairo.balart@metempsy.com for param in self.config_parameters: 52513531Sjairo.balart@metempsy.com if param.pointer: 52613531Sjairo.balart@metempsy.com code('m_${{param.ident}}_ptr = p->${{param.ident}};') 52713531Sjairo.balart@metempsy.com else: 52813531Sjairo.balart@metempsy.com code('m_${{param.ident}} = p->${{param.ident}};') 52913531Sjairo.balart@metempsy.com 53013531Sjairo.balart@metempsy.com if re.compile("sequencer").search(param.ident): 53113531Sjairo.balart@metempsy.com code('m_${{param.ident}}_ptr->setController(this);') 53213531Sjairo.balart@metempsy.com 53313531Sjairo.balart@metempsy.com code(''' 53413531Sjairo.balart@metempsy.com 53513531Sjairo.balart@metempsy.comfor (int state = 0; state < ${ident}_State_NUM; state++) { 53613531Sjairo.balart@metempsy.com for (int event = 0; event < ${ident}_Event_NUM; event++) { 53713531Sjairo.balart@metempsy.com m_possible[state][event] = false; 53813531Sjairo.balart@metempsy.com m_counters[state][event] = 0; 53913531Sjairo.balart@metempsy.com } 54013531Sjairo.balart@metempsy.com} 54113756Sjairo.balart@metempsy.comfor (int event = 0; event < ${ident}_Event_NUM; event++) { 54213531Sjairo.balart@metempsy.com m_event_counters[event] = 0; 54313531Sjairo.balart@metempsy.com} 54413531Sjairo.balart@metempsy.com''') 54513531Sjairo.balart@metempsy.com code.dedent() 54613531Sjairo.balart@metempsy.com code(''' 54713531Sjairo.balart@metempsy.com} 54813756Sjairo.balart@metempsy.com 54913531Sjairo.balart@metempsy.comvoid 55013531Sjairo.balart@metempsy.com$c_ident::initNetQueues() 55113531Sjairo.balart@metempsy.com{ 55213531Sjairo.balart@metempsy.com MachineType machine_type = string_to_MachineType("${{self.ident}}"); 55313531Sjairo.balart@metempsy.com int base M5_VAR_USED = MachineType_base_number(machine_type); 55413531Sjairo.balart@metempsy.com 55513531Sjairo.balart@metempsy.com''') 55613531Sjairo.balart@metempsy.com code.indent() 55713756Sjairo.balart@metempsy.com 55813756Sjairo.balart@metempsy.com # set for maintaining the vnet, direction pairs already seen for this 55913531Sjairo.balart@metempsy.com # machine. This map helps in implementing the check for avoiding 56013531Sjairo.balart@metempsy.com # multiple message buffers being mapped to the same vnet. 56113531Sjairo.balart@metempsy.com vnet_dir_set = set() 56213531Sjairo.balart@metempsy.com 56313531Sjairo.balart@metempsy.com for var in self.config_parameters: 56413531Sjairo.balart@metempsy.com vid = "m_%s_ptr" % var.ident 56513531Sjairo.balart@metempsy.com if "network" in var: 56613531Sjairo.balart@metempsy.com vtype = var.type_ast.type 56713531Sjairo.balart@metempsy.com code('assert($vid != NULL);') 56813531Sjairo.balart@metempsy.com 56913531Sjairo.balart@metempsy.com # Network port object 57013531Sjairo.balart@metempsy.com network = var["network"] 57113531Sjairo.balart@metempsy.com 57213531Sjairo.balart@metempsy.com if "virtual_network" in var: 57313531Sjairo.balart@metempsy.com vnet = var["virtual_network"] 57413531Sjairo.balart@metempsy.com vnet_type = var["vnet_type"] 57513531Sjairo.balart@metempsy.com 57613531Sjairo.balart@metempsy.com assert (vnet, network) not in vnet_dir_set 57713531Sjairo.balart@metempsy.com vnet_dir_set.add((vnet,network)) 57813531Sjairo.balart@metempsy.com 57913531Sjairo.balart@metempsy.com code(''' 58013531Sjairo.balart@metempsy.comm_net_ptr->set${network}NetQueue(m_version + base, $vid->getOrdered(), $vnet, 58113531Sjairo.balart@metempsy.com "$vnet_type", $vid); 58213756Sjairo.balart@metempsy.com''') 58313756Sjairo.balart@metempsy.com # Set Priority 58413531Sjairo.balart@metempsy.com if "rank" in var: 58513531Sjairo.balart@metempsy.com code('$vid->setPriority(${{var["rank"]}})') 58613531Sjairo.balart@metempsy.com 58713531Sjairo.balart@metempsy.com code.dedent() 58813531Sjairo.balart@metempsy.com code(''' 58913531Sjairo.balart@metempsy.com} 59013531Sjairo.balart@metempsy.com 59113531Sjairo.balart@metempsy.comvoid 59213531Sjairo.balart@metempsy.com$c_ident::init() 59313531Sjairo.balart@metempsy.com{ 59413531Sjairo.balart@metempsy.com // initialize objects 59513531Sjairo.balart@metempsy.com''') 59613531Sjairo.balart@metempsy.com 59713531Sjairo.balart@metempsy.com code.indent() 59813531Sjairo.balart@metempsy.com 59913531Sjairo.balart@metempsy.com for var in self.objects: 60013531Sjairo.balart@metempsy.com vtype = var.type 60113531Sjairo.balart@metempsy.com vid = "m_%s_ptr" % var.ident 60213531Sjairo.balart@metempsy.com if "network" not in var: 60313756Sjairo.balart@metempsy.com # Not a network port object 60413531Sjairo.balart@metempsy.com if "primitive" in vtype: 60513531Sjairo.balart@metempsy.com code('$vid = new ${{vtype.c_ident}};') 60613531Sjairo.balart@metempsy.com if "default" in var: 60713531Sjairo.balart@metempsy.com code('(*$vid) = ${{var["default"]}};') 60813531Sjairo.balart@metempsy.com else: 60913531Sjairo.balart@metempsy.com # Normal Object 61013531Sjairo.balart@metempsy.com th = var.get("template", "") 61113756Sjairo.balart@metempsy.com expr = "%s = new %s%s" % (vid, vtype.c_ident, th) 61213756Sjairo.balart@metempsy.com args = "" 61313531Sjairo.balart@metempsy.com if "non_obj" not in vtype and not vtype.isEnumeration: 61413531Sjairo.balart@metempsy.com args = var.get("constructor", "") 61513531Sjairo.balart@metempsy.com 61613531Sjairo.balart@metempsy.com code('$expr($args);') 61713531Sjairo.balart@metempsy.com code('assert($vid != NULL);') 61813531Sjairo.balart@metempsy.com 61913531Sjairo.balart@metempsy.com if "default" in var: 62013531Sjairo.balart@metempsy.com code('*$vid = ${{var["default"]}}; // Object default') 62113531Sjairo.balart@metempsy.com elif "default" in vtype: 62213531Sjairo.balart@metempsy.com comment = "Type %s default" % vtype.ident 62313531Sjairo.balart@metempsy.com code('*$vid = ${{vtype["default"]}}; // $comment') 62413531Sjairo.balart@metempsy.com 62513531Sjairo.balart@metempsy.com # Set the prefetchers 62613531Sjairo.balart@metempsy.com code() 62713531Sjairo.balart@metempsy.com for prefetcher in self.prefetchers: 62813531Sjairo.balart@metempsy.com code('${{prefetcher.code}}.setController(this);') 62913531Sjairo.balart@metempsy.com 63013531Sjairo.balart@metempsy.com code() 63113531Sjairo.balart@metempsy.com for port in self.in_ports: 63213531Sjairo.balart@metempsy.com # Set the queue consumers 63313756Sjairo.balart@metempsy.com code('${{port.code}}.setConsumer(this);') 63413531Sjairo.balart@metempsy.com 63513531Sjairo.balart@metempsy.com # Initialize the transition profiling 63613531Sjairo.balart@metempsy.com code() 63713531Sjairo.balart@metempsy.com for trans in self.transitions: 63813531Sjairo.balart@metempsy.com # Figure out if we stall 63913531Sjairo.balart@metempsy.com stall = False 64013531Sjairo.balart@metempsy.com for action in trans.actions: 64113756Sjairo.balart@metempsy.com if action.ident == "z_stall": 64213756Sjairo.balart@metempsy.com stall = True 64313531Sjairo.balart@metempsy.com 64413531Sjairo.balart@metempsy.com # Only possible if it is not a 'z' case 64513531Sjairo.balart@metempsy.com if not stall: 64613531Sjairo.balart@metempsy.com state = "%s_State_%s" % (self.ident, trans.state.ident) 64713531Sjairo.balart@metempsy.com event = "%s_Event_%s" % (self.ident, trans.event.ident) 64813531Sjairo.balart@metempsy.com code('possibleTransition($state, $event);') 64913531Sjairo.balart@metempsy.com 65013531Sjairo.balart@metempsy.com code.dedent() 65113531Sjairo.balart@metempsy.com code(''' 65213531Sjairo.balart@metempsy.com AbstractController::init(); 65313531Sjairo.balart@metempsy.com resetStats(); 65413531Sjairo.balart@metempsy.com} 65513531Sjairo.balart@metempsy.com''') 65613531Sjairo.balart@metempsy.com 65713531Sjairo.balart@metempsy.com mq_ident = "NULL" 65813531Sjairo.balart@metempsy.com for port in self.in_ports: 65913531Sjairo.balart@metempsy.com if port.code.find("mandatoryQueue_ptr") >= 0: 66013756Sjairo.balart@metempsy.com mq_ident = "m_mandatoryQueue_ptr" 66113531Sjairo.balart@metempsy.com 66213531Sjairo.balart@metempsy.com memq_ident = "NULL" 66313531Sjairo.balart@metempsy.com for port in self.in_ports: 66413531Sjairo.balart@metempsy.com if port.code.find("responseFromMemory_ptr") >= 0: 66513531Sjairo.balart@metempsy.com memq_ident = "m_responseFromMemory_ptr" 66613531Sjairo.balart@metempsy.com 66713531Sjairo.balart@metempsy.com seq_ident = "NULL" 66813531Sjairo.balart@metempsy.com for param in self.config_parameters: 66913756Sjairo.balart@metempsy.com if param.ident == "sequencer": 67013756Sjairo.balart@metempsy.com assert(param.pointer) 67113531Sjairo.balart@metempsy.com seq_ident = "m_%s_ptr" % param.ident 67213531Sjairo.balart@metempsy.com 67313531Sjairo.balart@metempsy.com code(''' 67413531Sjairo.balart@metempsy.com 67513531Sjairo.balart@metempsy.comvoid 67613531Sjairo.balart@metempsy.com$c_ident::regStats() 67713531Sjairo.balart@metempsy.com{ 67813531Sjairo.balart@metempsy.com AbstractController::regStats(); 67913531Sjairo.balart@metempsy.com 68013531Sjairo.balart@metempsy.com if (m_version == 0) { 68113531Sjairo.balart@metempsy.com for (${ident}_Event event = ${ident}_Event_FIRST; 68213531Sjairo.balart@metempsy.com event < ${ident}_Event_NUM; ++event) { 68313531Sjairo.balart@metempsy.com Stats::Vector *t = new Stats::Vector(); 68413531Sjairo.balart@metempsy.com t->init(m_num_controllers); 68513531Sjairo.balart@metempsy.com t->name(params()->ruby_system->name() + ".${c_ident}." + 68613531Sjairo.balart@metempsy.com ${ident}_Event_to_string(event)); 68713531Sjairo.balart@metempsy.com t->flags(Stats::pdf | Stats::total | Stats::oneline | 68813531Sjairo.balart@metempsy.com Stats::nozero); 68913531Sjairo.balart@metempsy.com 69013531Sjairo.balart@metempsy.com eventVec.push_back(t); 69113531Sjairo.balart@metempsy.com } 69213531Sjairo.balart@metempsy.com 69313756Sjairo.balart@metempsy.com for (${ident}_State state = ${ident}_State_FIRST; 69413756Sjairo.balart@metempsy.com state < ${ident}_State_NUM; ++state) { 69513531Sjairo.balart@metempsy.com 69613531Sjairo.balart@metempsy.com transVec.push_back(std::vector<Stats::Vector *>()); 69713531Sjairo.balart@metempsy.com 69813531Sjairo.balart@metempsy.com for (${ident}_Event event = ${ident}_Event_FIRST; 69913531Sjairo.balart@metempsy.com event < ${ident}_Event_NUM; ++event) { 70013531Sjairo.balart@metempsy.com 70113531Sjairo.balart@metempsy.com Stats::Vector *t = new Stats::Vector(); 70213531Sjairo.balart@metempsy.com t->init(m_num_controllers); 70313531Sjairo.balart@metempsy.com t->name(params()->ruby_system->name() + ".${c_ident}." + 70413531Sjairo.balart@metempsy.com ${ident}_State_to_string(state) + 70513531Sjairo.balart@metempsy.com "." + ${ident}_Event_to_string(event)); 70613531Sjairo.balart@metempsy.com 70713531Sjairo.balart@metempsy.com t->flags(Stats::pdf | Stats::total | Stats::oneline | 70813531Sjairo.balart@metempsy.com Stats::nozero); 70913531Sjairo.balart@metempsy.com transVec[state].push_back(t); 71013531Sjairo.balart@metempsy.com } 71113531Sjairo.balart@metempsy.com } 71213531Sjairo.balart@metempsy.com } 71313756Sjairo.balart@metempsy.com} 71413531Sjairo.balart@metempsy.com 71513531Sjairo.balart@metempsy.comvoid 71613531Sjairo.balart@metempsy.com$c_ident::collateStats() 71713531Sjairo.balart@metempsy.com{ 71813531Sjairo.balart@metempsy.com for (${ident}_Event event = ${ident}_Event_FIRST; 71913531Sjairo.balart@metempsy.com event < ${ident}_Event_NUM; ++event) { 72013531Sjairo.balart@metempsy.com for (unsigned int i = 0; i < m_num_controllers; ++i) { 72113531Sjairo.balart@metempsy.com RubySystem *rs = params()->ruby_system; 72213531Sjairo.balart@metempsy.com std::map<uint32_t, AbstractController *>::iterator it = 72313531Sjairo.balart@metempsy.com rs->m_abstract_controls[MachineType_${ident}].find(i); 72413531Sjairo.balart@metempsy.com assert(it != rs->m_abstract_controls[MachineType_${ident}].end()); 72513531Sjairo.balart@metempsy.com (*eventVec[event])[i] = 72613531Sjairo.balart@metempsy.com (($c_ident *)(*it).second)->getEventCount(event); 72713531Sjairo.balart@metempsy.com } 72813531Sjairo.balart@metempsy.com } 72913531Sjairo.balart@metempsy.com 73013531Sjairo.balart@metempsy.com for (${ident}_State state = ${ident}_State_FIRST; 73113531Sjairo.balart@metempsy.com state < ${ident}_State_NUM; ++state) { 73213531Sjairo.balart@metempsy.com 73313531Sjairo.balart@metempsy.com for (${ident}_Event event = ${ident}_Event_FIRST; 73413531Sjairo.balart@metempsy.com event < ${ident}_Event_NUM; ++event) { 73513531Sjairo.balart@metempsy.com 73613531Sjairo.balart@metempsy.com for (unsigned int i = 0; i < m_num_controllers; ++i) { 73713531Sjairo.balart@metempsy.com RubySystem *rs = params()->ruby_system; 73813531Sjairo.balart@metempsy.com std::map<uint32_t, AbstractController *>::iterator it = 73913531Sjairo.balart@metempsy.com rs->m_abstract_controls[MachineType_${ident}].find(i); 74013531Sjairo.balart@metempsy.com assert(it != rs->m_abstract_controls[MachineType_${ident}].end()); 74113531Sjairo.balart@metempsy.com (*transVec[state][event])[i] = 74213531Sjairo.balart@metempsy.com (($c_ident *)(*it).second)->getTransitionCount(state, event); 74313531Sjairo.balart@metempsy.com } 74413531Sjairo.balart@metempsy.com } 74513531Sjairo.balart@metempsy.com } 74613756Sjairo.balart@metempsy.com} 74713531Sjairo.balart@metempsy.com 74813756Sjairo.balart@metempsy.comvoid 74913756Sjairo.balart@metempsy.com$c_ident::countTransition(${ident}_State state, ${ident}_Event event) 75013756Sjairo.balart@metempsy.com{ 75113756Sjairo.balart@metempsy.com assert(m_possible[state][event]); 75213756Sjairo.balart@metempsy.com m_counters[state][event]++; 75313531Sjairo.balart@metempsy.com m_event_counters[event]++; 75413531Sjairo.balart@metempsy.com} 75513531Sjairo.balart@metempsy.comvoid 75613531Sjairo.balart@metempsy.com$c_ident::possibleTransition(${ident}_State state, 75713531Sjairo.balart@metempsy.com ${ident}_Event event) 75813531Sjairo.balart@metempsy.com{ 75913531Sjairo.balart@metempsy.com m_possible[state][event] = true; 76013756Sjairo.balart@metempsy.com} 76113531Sjairo.balart@metempsy.com 76213531Sjairo.balart@metempsy.comuint64_t 76313531Sjairo.balart@metempsy.com$c_ident::getEventCount(${ident}_Event event) 76413531Sjairo.balart@metempsy.com{ 76513531Sjairo.balart@metempsy.com return m_event_counters[event]; 76613531Sjairo.balart@metempsy.com} 76713531Sjairo.balart@metempsy.com 76813531Sjairo.balart@metempsy.combool 76913531Sjairo.balart@metempsy.com$c_ident::isPossible(${ident}_State state, ${ident}_Event event) 77013531Sjairo.balart@metempsy.com{ 77113531Sjairo.balart@metempsy.com return m_possible[state][event]; 77213531Sjairo.balart@metempsy.com} 77313531Sjairo.balart@metempsy.com 77413531Sjairo.balart@metempsy.comuint64_t 77513531Sjairo.balart@metempsy.com$c_ident::getTransitionCount(${ident}_State state, 77613531Sjairo.balart@metempsy.com ${ident}_Event event) 77713531Sjairo.balart@metempsy.com{ 77813531Sjairo.balart@metempsy.com return m_counters[state][event]; 77913531Sjairo.balart@metempsy.com} 78013531Sjairo.balart@metempsy.com 78113531Sjairo.balart@metempsy.comint 78213531Sjairo.balart@metempsy.com$c_ident::getNumControllers() 78313531Sjairo.balart@metempsy.com{ 78413531Sjairo.balart@metempsy.com return m_num_controllers; 78513756Sjairo.balart@metempsy.com} 78613531Sjairo.balart@metempsy.com 78713531Sjairo.balart@metempsy.comMessageBuffer* 78813531Sjairo.balart@metempsy.com$c_ident::getMandatoryQueue() const 78913531Sjairo.balart@metempsy.com{ 79013531Sjairo.balart@metempsy.com return $mq_ident; 79113531Sjairo.balart@metempsy.com} 79213531Sjairo.balart@metempsy.com 79313756Sjairo.balart@metempsy.comMessageBuffer* 79413531Sjairo.balart@metempsy.com$c_ident::getMemoryQueue() const 79513531Sjairo.balart@metempsy.com{ 79613531Sjairo.balart@metempsy.com return $memq_ident; 79713531Sjairo.balart@metempsy.com} 79813531Sjairo.balart@metempsy.com 79913531Sjairo.balart@metempsy.comSequencer* 80013531Sjairo.balart@metempsy.com$c_ident::getSequencer() const 80113531Sjairo.balart@metempsy.com{ 80213531Sjairo.balart@metempsy.com return $seq_ident; 80313531Sjairo.balart@metempsy.com} 80413531Sjairo.balart@metempsy.com 80513531Sjairo.balart@metempsy.comvoid 80613531Sjairo.balart@metempsy.com$c_ident::print(ostream& out) const 80713756Sjairo.balart@metempsy.com{ 80813531Sjairo.balart@metempsy.com out << "[$c_ident " << m_version << "]"; 80913531Sjairo.balart@metempsy.com} 81013531Sjairo.balart@metempsy.com 81113531Sjairo.balart@metempsy.comvoid $c_ident::resetStats() 81213531Sjairo.balart@metempsy.com{ 81313531Sjairo.balart@metempsy.com for (int state = 0; state < ${ident}_State_NUM; state++) { 81413531Sjairo.balart@metempsy.com for (int event = 0; event < ${ident}_Event_NUM; event++) { 81513531Sjairo.balart@metempsy.com m_counters[state][event] = 0; 81613531Sjairo.balart@metempsy.com } 81713531Sjairo.balart@metempsy.com } 81813531Sjairo.balart@metempsy.com 81913531Sjairo.balart@metempsy.com for (int event = 0; event < ${ident}_Event_NUM; event++) { 82013531Sjairo.balart@metempsy.com m_event_counters[event] = 0; 82113531Sjairo.balart@metempsy.com } 82213531Sjairo.balart@metempsy.com 82313531Sjairo.balart@metempsy.com AbstractController::resetStats(); 82413531Sjairo.balart@metempsy.com} 82513531Sjairo.balart@metempsy.com''') 82613531Sjairo.balart@metempsy.com 82713531Sjairo.balart@metempsy.com if self.EntryType != None: 82813531Sjairo.balart@metempsy.com code(''' 82913531Sjairo.balart@metempsy.com 83013531Sjairo.balart@metempsy.com// Set and Reset for cache_entry variable 83113531Sjairo.balart@metempsy.comvoid 83213531Sjairo.balart@metempsy.com$c_ident::set_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, AbstractCacheEntry* m_new_cache_entry) 83313531Sjairo.balart@metempsy.com{ 83413531Sjairo.balart@metempsy.com m_cache_entry_ptr = (${{self.EntryType.c_ident}}*)m_new_cache_entry; 83513531Sjairo.balart@metempsy.com} 83613531Sjairo.balart@metempsy.com 83713531Sjairo.balart@metempsy.comvoid 83813531Sjairo.balart@metempsy.com$c_ident::unset_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr) 83913531Sjairo.balart@metempsy.com{ 84013531Sjairo.balart@metempsy.com m_cache_entry_ptr = 0; 84113531Sjairo.balart@metempsy.com} 84213531Sjairo.balart@metempsy.com''') 84313531Sjairo.balart@metempsy.com 84413531Sjairo.balart@metempsy.com if self.TBEType != None: 84513531Sjairo.balart@metempsy.com code(''' 84613531Sjairo.balart@metempsy.com 84713531Sjairo.balart@metempsy.com// Set and Reset for tbe variable 84813531Sjairo.balart@metempsy.comvoid 84913531Sjairo.balart@metempsy.com$c_ident::set_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.TBEType.c_ident}}* m_new_tbe) 85013531Sjairo.balart@metempsy.com{ 85113531Sjairo.balart@metempsy.com m_tbe_ptr = m_new_tbe; 85213531Sjairo.balart@metempsy.com} 85313531Sjairo.balart@metempsy.com 85413531Sjairo.balart@metempsy.comvoid 85513531Sjairo.balart@metempsy.com$c_ident::unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr) 85613531Sjairo.balart@metempsy.com{ 85713531Sjairo.balart@metempsy.com m_tbe_ptr = NULL; 85813531Sjairo.balart@metempsy.com} 85913531Sjairo.balart@metempsy.com''') 86013531Sjairo.balart@metempsy.com 86113531Sjairo.balart@metempsy.com code(''' 86213531Sjairo.balart@metempsy.com 86313531Sjairo.balart@metempsy.comvoid 86413531Sjairo.balart@metempsy.com$c_ident::recordCacheTrace(int cntrl, CacheRecorder* tr) 86513531Sjairo.balart@metempsy.com{ 86613531Sjairo.balart@metempsy.com''') 86713531Sjairo.balart@metempsy.com # 86813531Sjairo.balart@metempsy.com # Record cache contents for all associated caches. 86913531Sjairo.balart@metempsy.com # 87013531Sjairo.balart@metempsy.com code.indent() 87113531Sjairo.balart@metempsy.com for param in self.config_parameters: 87213531Sjairo.balart@metempsy.com if param.type_ast.type.ident == "CacheMemory": 87313531Sjairo.balart@metempsy.com assert(param.pointer) 87413531Sjairo.balart@metempsy.com code('m_${{param.ident}}_ptr->recordCacheContents(cntrl, tr);') 87513531Sjairo.balart@metempsy.com 87613531Sjairo.balart@metempsy.com code.dedent() 87713531Sjairo.balart@metempsy.com code(''' 87813531Sjairo.balart@metempsy.com} 87913531Sjairo.balart@metempsy.com 88013531Sjairo.balart@metempsy.com// Actions 88113531Sjairo.balart@metempsy.com''') 88213531Sjairo.balart@metempsy.com if self.TBEType != None and self.EntryType != None: 88313531Sjairo.balart@metempsy.com for action in self.actions.itervalues(): 88413531Sjairo.balart@metempsy.com if "c_code" not in action: 88513531Sjairo.balart@metempsy.com continue 88613531Sjairo.balart@metempsy.com 88713531Sjairo.balart@metempsy.com code(''' 88813531Sjairo.balart@metempsy.com/** \\brief ${{action.desc}} */ 88913531Sjairo.balart@metempsy.comvoid 89013531Sjairo.balart@metempsy.com$c_ident::${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, Addr addr) 89113531Sjairo.balart@metempsy.com{ 89213531Sjairo.balart@metempsy.com DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 89313531Sjairo.balart@metempsy.com try { 89413531Sjairo.balart@metempsy.com ${{action["c_code"]}} 89513531Sjairo.balart@metempsy.com } catch (const RejectException & e) { 89613531Sjairo.balart@metempsy.com fatal("Error in action ${{ident}}:${{action.ident}}: " 89713531Sjairo.balart@metempsy.com "executed a peek statement with the wrong message " 89813531Sjairo.balart@metempsy.com "type specified. "); 89913531Sjairo.balart@metempsy.com } 90013531Sjairo.balart@metempsy.com} 90113531Sjairo.balart@metempsy.com 90213531Sjairo.balart@metempsy.com''') 90313531Sjairo.balart@metempsy.com elif self.TBEType != None: 90413531Sjairo.balart@metempsy.com for action in self.actions.itervalues(): 90513531Sjairo.balart@metempsy.com if "c_code" not in action: 90613531Sjairo.balart@metempsy.com continue 90713531Sjairo.balart@metempsy.com 90813531Sjairo.balart@metempsy.com code(''' 90913531Sjairo.balart@metempsy.com/** \\brief ${{action.desc}} */ 91013531Sjairo.balart@metempsy.comvoid 91113531Sjairo.balart@metempsy.com$c_ident::${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, Addr addr) 91213531Sjairo.balart@metempsy.com{ 91313531Sjairo.balart@metempsy.com DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 91413531Sjairo.balart@metempsy.com ${{action["c_code"]}} 91513531Sjairo.balart@metempsy.com} 91613531Sjairo.balart@metempsy.com 91713531Sjairo.balart@metempsy.com''') 91813531Sjairo.balart@metempsy.com elif self.EntryType != None: 91913531Sjairo.balart@metempsy.com for action in self.actions.itervalues(): 92013531Sjairo.balart@metempsy.com if "c_code" not in action: 92113531Sjairo.balart@metempsy.com continue 92213531Sjairo.balart@metempsy.com 92313531Sjairo.balart@metempsy.com code(''' 92413531Sjairo.balart@metempsy.com/** \\brief ${{action.desc}} */ 92513531Sjairo.balart@metempsy.comvoid 92613531Sjairo.balart@metempsy.com$c_ident::${{action.ident}}(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, Addr addr) 92713531Sjairo.balart@metempsy.com{ 92813531Sjairo.balart@metempsy.com DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 92913531Sjairo.balart@metempsy.com ${{action["c_code"]}} 93013531Sjairo.balart@metempsy.com} 93113531Sjairo.balart@metempsy.com 93213531Sjairo.balart@metempsy.com''') 93313531Sjairo.balart@metempsy.com else: 93413531Sjairo.balart@metempsy.com for action in self.actions.itervalues(): 93513531Sjairo.balart@metempsy.com if "c_code" not in action: 93613531Sjairo.balart@metempsy.com continue 93713531Sjairo.balart@metempsy.com 93813531Sjairo.balart@metempsy.com code(''' 93913531Sjairo.balart@metempsy.com/** \\brief ${{action.desc}} */ 94013531Sjairo.balart@metempsy.comvoid 94113531Sjairo.balart@metempsy.com$c_ident::${{action.ident}}(Addr addr) 94213531Sjairo.balart@metempsy.com{ 94313756Sjairo.balart@metempsy.com DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 94413531Sjairo.balart@metempsy.com ${{action["c_code"]}} 94513531Sjairo.balart@metempsy.com} 94613531Sjairo.balart@metempsy.com 94713531Sjairo.balart@metempsy.com''') 94813531Sjairo.balart@metempsy.com for func in self.functions: 94913531Sjairo.balart@metempsy.com code(func.generateCode()) 95013531Sjairo.balart@metempsy.com 95113531Sjairo.balart@metempsy.com # Function for functional writes to messages buffered in the controller 95213531Sjairo.balart@metempsy.com code(''' 95313531Sjairo.balart@metempsy.comint 95413531Sjairo.balart@metempsy.com$c_ident::functionalWriteBuffers(PacketPtr& pkt) 95513531Sjairo.balart@metempsy.com{ 95613531Sjairo.balart@metempsy.com int num_functional_writes = 0; 95713531Sjairo.balart@metempsy.com''') 95813531Sjairo.balart@metempsy.com for var in self.objects: 95913531Sjairo.balart@metempsy.com vtype = var.type 96013531Sjairo.balart@metempsy.com if vtype.isBuffer: 96113531Sjairo.balart@metempsy.com vid = "m_%s_ptr" % var.ident 96213531Sjairo.balart@metempsy.com code('num_functional_writes += $vid->functionalWrite(pkt);') 96313531Sjairo.balart@metempsy.com 96413531Sjairo.balart@metempsy.com for var in self.config_parameters: 96513531Sjairo.balart@metempsy.com vtype = var.type_ast.type 96613531Sjairo.balart@metempsy.com if vtype.isBuffer: 96713531Sjairo.balart@metempsy.com vid = "m_%s_ptr" % var.ident 96813531Sjairo.balart@metempsy.com code('num_functional_writes += $vid->functionalWrite(pkt);') 96913531Sjairo.balart@metempsy.com 97013531Sjairo.balart@metempsy.com code(''' 97113531Sjairo.balart@metempsy.com return num_functional_writes; 97213531Sjairo.balart@metempsy.com} 97313531Sjairo.balart@metempsy.com''') 97413531Sjairo.balart@metempsy.com 97513531Sjairo.balart@metempsy.com code.write(path, "%s.cc" % c_ident) 97613531Sjairo.balart@metempsy.com 97713531Sjairo.balart@metempsy.com def printCWakeup(self, path, includes): 97813531Sjairo.balart@metempsy.com '''Output the wakeup loop for the events''' 97913531Sjairo.balart@metempsy.com 98013531Sjairo.balart@metempsy.com code = self.symtab.codeFormatter() 98113531Sjairo.balart@metempsy.com ident = self.ident 98213531Sjairo.balart@metempsy.com 98313531Sjairo.balart@metempsy.com outputRequest_types = True 98413756Sjairo.balart@metempsy.com if len(self.request_types) == 0: 98513531Sjairo.balart@metempsy.com outputRequest_types = False 98613531Sjairo.balart@metempsy.com 98713531Sjairo.balart@metempsy.com code(''' 98813531Sjairo.balart@metempsy.com// Auto generated C++ code started by $__file__:$__line__ 98913756Sjairo.balart@metempsy.com// ${ident}: ${{self.short}} 99013531Sjairo.balart@metempsy.com 99113531Sjairo.balart@metempsy.com#include <sys/types.h> 99213531Sjairo.balart@metempsy.com#include <unistd.h> 99313531Sjairo.balart@metempsy.com 99413531Sjairo.balart@metempsy.com#include <cassert> 99513531Sjairo.balart@metempsy.com#include <typeinfo> 99613531Sjairo.balart@metempsy.com 99713531Sjairo.balart@metempsy.com#include "base/misc.hh" 99813531Sjairo.balart@metempsy.com 99913531Sjairo.balart@metempsy.com''') 100013531Sjairo.balart@metempsy.com for f in self.debug_flags: 100113531Sjairo.balart@metempsy.com code('#include "debug/${{f}}.hh"') 100213531Sjairo.balart@metempsy.com code(''' 100313531Sjairo.balart@metempsy.com#include "mem/protocol/${ident}_Controller.hh" 100413531Sjairo.balart@metempsy.com#include "mem/protocol/${ident}_Event.hh" 100513531Sjairo.balart@metempsy.com#include "mem/protocol/${ident}_State.hh" 100613531Sjairo.balart@metempsy.com 100713531Sjairo.balart@metempsy.com''') 100813531Sjairo.balart@metempsy.com 100913531Sjairo.balart@metempsy.com if outputRequest_types: 101013531Sjairo.balart@metempsy.com code('''#include "mem/protocol/${ident}_RequestType.hh"''') 101113531Sjairo.balart@metempsy.com 101213531Sjairo.balart@metempsy.com code(''' 101313531Sjairo.balart@metempsy.com#include "mem/protocol/Types.hh" 101413531Sjairo.balart@metempsy.com#include "mem/ruby/system/RubySystem.hh" 101513531Sjairo.balart@metempsy.com 101613531Sjairo.balart@metempsy.com''') 101713531Sjairo.balart@metempsy.com 101813531Sjairo.balart@metempsy.com 101913531Sjairo.balart@metempsy.com for include_path in includes: 102013531Sjairo.balart@metempsy.com code('#include "${{include_path}}"') 102113531Sjairo.balart@metempsy.com 102213531Sjairo.balart@metempsy.com port_to_buf_map, in_msg_bufs, msg_bufs = self.getBufferMaps(ident) 102313531Sjairo.balart@metempsy.com 102413756Sjairo.balart@metempsy.com code(''' 102513756Sjairo.balart@metempsy.com 102613756Sjairo.balart@metempsy.comusing namespace std; 102713756Sjairo.balart@metempsy.com 102813756Sjairo.balart@metempsy.comvoid 102913756Sjairo.balart@metempsy.com${ident}_Controller::wakeup() 103013756Sjairo.balart@metempsy.com{ 103113531Sjairo.balart@metempsy.com int counter = 0; 103213531Sjairo.balart@metempsy.com while (true) { 103313531Sjairo.balart@metempsy.com unsigned char rejected[${{len(msg_bufs)}}]; 103413531Sjairo.balart@metempsy.com memset(rejected, 0, sizeof(unsigned char)*${{len(msg_bufs)}}); 103513531Sjairo.balart@metempsy.com // Some cases will put us into an infinite loop without this limit 103613531Sjairo.balart@metempsy.com assert(counter <= m_transitions_per_cycle); 103713531Sjairo.balart@metempsy.com if (counter == m_transitions_per_cycle) { 103813531Sjairo.balart@metempsy.com // Count how often we are fully utilized 103913531Sjairo.balart@metempsy.com m_fully_busy_cycles++; 104013531Sjairo.balart@metempsy.com 104113531Sjairo.balart@metempsy.com // Wakeup in another cycle and try again 104213531Sjairo.balart@metempsy.com scheduleEvent(Cycles(1)); 104313531Sjairo.balart@metempsy.com break; 104413531Sjairo.balart@metempsy.com } 104513756Sjairo.balart@metempsy.com''') 104613756Sjairo.balart@metempsy.com 104713531Sjairo.balart@metempsy.com code.indent() 104813531Sjairo.balart@metempsy.com code.indent() 104913531Sjairo.balart@metempsy.com 105013531Sjairo.balart@metempsy.com # InPorts 105113531Sjairo.balart@metempsy.com # 105213531Sjairo.balart@metempsy.com for port in self.in_ports: 105313756Sjairo.balart@metempsy.com code.indent() 105413531Sjairo.balart@metempsy.com code('// ${ident}InPort $port') 105513531Sjairo.balart@metempsy.com if port.pairs.has_key("rank"): 105613531Sjairo.balart@metempsy.com code('m_cur_in_port = ${{port.pairs["rank"]}};') 105713531Sjairo.balart@metempsy.com else: 105813531Sjairo.balart@metempsy.com code('m_cur_in_port = 0;') 105913531Sjairo.balart@metempsy.com if port in port_to_buf_map: 106013531Sjairo.balart@metempsy.com code('try {') 106113531Sjairo.balart@metempsy.com code.indent() 106213531Sjairo.balart@metempsy.com code('${{port["c_code_in_port"]}}') 106313531Sjairo.balart@metempsy.com 106413531Sjairo.balart@metempsy.com if port in port_to_buf_map: 106513531Sjairo.balart@metempsy.com code.dedent() 106613531Sjairo.balart@metempsy.com code(''' 106713531Sjairo.balart@metempsy.com } catch (const RejectException & e) { 106813531Sjairo.balart@metempsy.com rejected[${{port_to_buf_map[port]}}]++; 106913531Sjairo.balart@metempsy.com } 107013531Sjairo.balart@metempsy.com''') 107113531Sjairo.balart@metempsy.com code.dedent() 107213756Sjairo.balart@metempsy.com code('') 107313531Sjairo.balart@metempsy.com 107413531Sjairo.balart@metempsy.com code.dedent() 107513531Sjairo.balart@metempsy.com code.dedent() 107613531Sjairo.balart@metempsy.com code(''' 107713531Sjairo.balart@metempsy.com // If we got this far, we have nothing left todo or something went 107813531Sjairo.balart@metempsy.com // wrong''') 107913531Sjairo.balart@metempsy.com for buf_name, ports in in_msg_bufs.items(): 108013531Sjairo.balart@metempsy.com if len(ports) > 1: 108113531Sjairo.balart@metempsy.com # only produce checks when a buffer is shared by multiple ports 108213531Sjairo.balart@metempsy.com code(''' 108313531Sjairo.balart@metempsy.com if (${{buf_name}}->isReady() && rejected[${{port_to_buf_map[ports[0]]}}] == ${{len(ports)}}) 108413531Sjairo.balart@metempsy.com { 108513531Sjairo.balart@metempsy.com // no port claimed the message on the top of this buffer 108613531Sjairo.balart@metempsy.com panic("Runtime Error at Ruby Time: %d. " 108713531Sjairo.balart@metempsy.com "All ports rejected a message. " 108813531Sjairo.balart@metempsy.com "You are probably sending a message type to this controller " 108913531Sjairo.balart@metempsy.com "over a virtual network that do not define an in_port for " 109013531Sjairo.balart@metempsy.com "the incoming message type.\\n", 109113531Sjairo.balart@metempsy.com Cycles(1)); 109213531Sjairo.balart@metempsy.com } 109313531Sjairo.balart@metempsy.com''') 109413531Sjairo.balart@metempsy.com code(''' 109513531Sjairo.balart@metempsy.com break; 109613531Sjairo.balart@metempsy.com } 109713531Sjairo.balart@metempsy.com} 109813531Sjairo.balart@metempsy.com''') 109913531Sjairo.balart@metempsy.com 110013531Sjairo.balart@metempsy.com code.write(path, "%s_Wakeup.cc" % self.ident) 110113531Sjairo.balart@metempsy.com 110213531Sjairo.balart@metempsy.com def printCSwitch(self, path): 110313531Sjairo.balart@metempsy.com '''Output switch statement for transition table''' 110413531Sjairo.balart@metempsy.com 110513531Sjairo.balart@metempsy.com code = self.symtab.codeFormatter() 110613531Sjairo.balart@metempsy.com ident = self.ident 110713531Sjairo.balart@metempsy.com 110813531Sjairo.balart@metempsy.com code(''' 110913531Sjairo.balart@metempsy.com// Auto generated C++ code started by $__file__:$__line__ 111013531Sjairo.balart@metempsy.com// ${ident}: ${{self.short}} 111113531Sjairo.balart@metempsy.com 111213531Sjairo.balart@metempsy.com#include <cassert> 111313531Sjairo.balart@metempsy.com 111413531Sjairo.balart@metempsy.com#include "base/misc.hh" 111513531Sjairo.balart@metempsy.com#include "base/trace.hh" 111613531Sjairo.balart@metempsy.com#include "debug/ProtocolTrace.hh" 111713531Sjairo.balart@metempsy.com#include "debug/RubyGenerated.hh" 111813531Sjairo.balart@metempsy.com#include "mem/protocol/${ident}_Controller.hh" 111913531Sjairo.balart@metempsy.com#include "mem/protocol/${ident}_Event.hh" 112013531Sjairo.balart@metempsy.com#include "mem/protocol/${ident}_State.hh" 112113531Sjairo.balart@metempsy.com#include "mem/protocol/Types.hh" 112213531Sjairo.balart@metempsy.com#include "mem/ruby/system/RubySystem.hh" 112313531Sjairo.balart@metempsy.com 112413531Sjairo.balart@metempsy.com#define HASH_FUN(state, event) ((int(state)*${ident}_Event_NUM)+int(event)) 112513531Sjairo.balart@metempsy.com 112613531Sjairo.balart@metempsy.com#define GET_TRANSITION_COMMENT() (${ident}_transitionComment.str()) 112713531Sjairo.balart@metempsy.com#define CLEAR_TRANSITION_COMMENT() (${ident}_transitionComment.str("")) 112813531Sjairo.balart@metempsy.com 112913531Sjairo.balart@metempsy.comTransitionResult 113013531Sjairo.balart@metempsy.com${ident}_Controller::doTransition(${ident}_Event event, 113113531Sjairo.balart@metempsy.com''') 113213531Sjairo.balart@metempsy.com if self.EntryType != None: 113313531Sjairo.balart@metempsy.com code(''' 113413531Sjairo.balart@metempsy.com ${{self.EntryType.c_ident}}* m_cache_entry_ptr, 113513531Sjairo.balart@metempsy.com''') 113613531Sjairo.balart@metempsy.com if self.TBEType != None: 113713531Sjairo.balart@metempsy.com code(''' 113813531Sjairo.balart@metempsy.com ${{self.TBEType.c_ident}}* m_tbe_ptr, 113913531Sjairo.balart@metempsy.com''') 114013531Sjairo.balart@metempsy.com code(''' 114113531Sjairo.balart@metempsy.com Addr addr) 114213531Sjairo.balart@metempsy.com{ 114313531Sjairo.balart@metempsy.com''') 114413531Sjairo.balart@metempsy.com code.indent() 114513531Sjairo.balart@metempsy.com 114613531Sjairo.balart@metempsy.com if self.TBEType != None and self.EntryType != None: 114713531Sjairo.balart@metempsy.com code('${ident}_State state = getState(m_tbe_ptr, m_cache_entry_ptr, addr);') 1148 elif self.TBEType != None: 1149 code('${ident}_State state = getState(m_tbe_ptr, addr);') 1150 elif self.EntryType != None: 1151 code('${ident}_State state = getState(m_cache_entry_ptr, addr);') 1152 else: 1153 code('${ident}_State state = getState(addr);') 1154 1155 code(''' 1156${ident}_State next_state = state; 1157 1158DPRINTF(RubyGenerated, "%s, Time: %lld, state: %s, event: %s, addr: %s\\n", 1159 *this, curCycle(), ${ident}_State_to_string(state), 1160 ${ident}_Event_to_string(event), addr); 1161 1162TransitionResult result = 1163''') 1164 if self.TBEType != None and self.EntryType != None: 1165 code('doTransitionWorker(event, state, next_state, m_tbe_ptr, m_cache_entry_ptr, addr);') 1166 elif self.TBEType != None: 1167 code('doTransitionWorker(event, state, next_state, m_tbe_ptr, addr);') 1168 elif self.EntryType != None: 1169 code('doTransitionWorker(event, state, next_state, m_cache_entry_ptr, addr);') 1170 else: 1171 code('doTransitionWorker(event, state, next_state, addr);') 1172 1173 port_to_buf_map, in_msg_bufs, msg_bufs = self.getBufferMaps(ident) 1174 1175 code(''' 1176 1177if (result == TransitionResult_Valid) { 1178 DPRINTF(RubyGenerated, "next_state: %s\\n", 1179 ${ident}_State_to_string(next_state)); 1180 countTransition(state, event); 1181 1182 DPRINTFR(ProtocolTrace, "%15d %3s %10s%20s %6s>%-6s %#x %s\\n", 1183 curTick(), m_version, "${ident}", 1184 ${ident}_Event_to_string(event), 1185 ${ident}_State_to_string(state), 1186 ${ident}_State_to_string(next_state), 1187 addr, GET_TRANSITION_COMMENT()); 1188 1189 CLEAR_TRANSITION_COMMENT(); 1190''') 1191 if self.TBEType != None and self.EntryType != None: 1192 code('setState(m_tbe_ptr, m_cache_entry_ptr, addr, next_state);') 1193 code('setAccessPermission(m_cache_entry_ptr, addr, next_state);') 1194 elif self.TBEType != None: 1195 code('setState(m_tbe_ptr, addr, next_state);') 1196 code('setAccessPermission(addr, next_state);') 1197 elif self.EntryType != None: 1198 code('setState(m_cache_entry_ptr, addr, next_state);') 1199 code('setAccessPermission(m_cache_entry_ptr, addr, next_state);') 1200 else: 1201 code('setState(addr, next_state);') 1202 code('setAccessPermission(addr, next_state);') 1203 1204 code(''' 1205} else if (result == TransitionResult_ResourceStall) { 1206 DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %#x %s\\n", 1207 curTick(), m_version, "${ident}", 1208 ${ident}_Event_to_string(event), 1209 ${ident}_State_to_string(state), 1210 ${ident}_State_to_string(next_state), 1211 addr, "Resource Stall"); 1212} else if (result == TransitionResult_ProtocolStall) { 1213 DPRINTF(RubyGenerated, "stalling\\n"); 1214 DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %#x %s\\n", 1215 curTick(), m_version, "${ident}", 1216 ${ident}_Event_to_string(event), 1217 ${ident}_State_to_string(state), 1218 ${ident}_State_to_string(next_state), 1219 addr, "Protocol Stall"); 1220} 1221 1222return result; 1223''') 1224 code.dedent() 1225 code(''' 1226} 1227 1228TransitionResult 1229${ident}_Controller::doTransitionWorker(${ident}_Event event, 1230 ${ident}_State state, 1231 ${ident}_State& next_state, 1232''') 1233 1234 if self.TBEType != None: 1235 code(''' 1236 ${{self.TBEType.c_ident}}*& m_tbe_ptr, 1237''') 1238 if self.EntryType != None: 1239 code(''' 1240 ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, 1241''') 1242 code(''' 1243 Addr addr) 1244{ 1245 switch(HASH_FUN(state, event)) { 1246''') 1247 1248 # This map will allow suppress generating duplicate code 1249 cases = orderdict() 1250 1251 for trans in self.transitions: 1252 case_string = "%s_State_%s, %s_Event_%s" % \ 1253 (self.ident, trans.state.ident, self.ident, trans.event.ident) 1254 1255 case = self.symtab.codeFormatter() 1256 # Only set next_state if it changes 1257 if trans.state != trans.nextState: 1258 if trans.nextState.isWildcard(): 1259 # When * is encountered as an end state of a transition, 1260 # the next state is determined by calling the 1261 # machine-specific getNextState function. The next state 1262 # is determined before any actions of the transition 1263 # execute, and therefore the next state calculation cannot 1264 # depend on any of the transitionactions. 1265 case('next_state = getNextState(addr);') 1266 else: 1267 ns_ident = trans.nextState.ident 1268 case('next_state = ${ident}_State_${ns_ident};') 1269 1270 actions = trans.actions 1271 request_types = trans.request_types 1272 1273 # Check for resources 1274 case_sorter = [] 1275 res = trans.resources 1276 for key,val in res.iteritems(): 1277 val = ''' 1278if (!%s.areNSlotsAvailable(%s, clockEdge())) 1279 return TransitionResult_ResourceStall; 1280''' % (key.code, val) 1281 case_sorter.append(val) 1282 1283 # Check all of the request_types for resource constraints 1284 for request_type in request_types: 1285 val = ''' 1286if (!checkResourceAvailable(%s_RequestType_%s, addr)) { 1287 return TransitionResult_ResourceStall; 1288} 1289''' % (self.ident, request_type.ident) 1290 case_sorter.append(val) 1291 1292 # Emit the code sequences in a sorted order. This makes the 1293 # output deterministic (without this the output order can vary 1294 # since Map's keys() on a vector of pointers is not deterministic 1295 for c in sorted(case_sorter): 1296 case("$c") 1297 1298 # Record access types for this transition 1299 for request_type in request_types: 1300 case('recordRequestType(${ident}_RequestType_${{request_type.ident}}, addr);') 1301 1302 # Figure out if we stall 1303 stall = False 1304 for action in actions: 1305 if action.ident == "z_stall": 1306 stall = True 1307 break 1308 1309 if stall: 1310 case('return TransitionResult_ProtocolStall;') 1311 else: 1312 if self.TBEType != None and self.EntryType != None: 1313 for action in actions: 1314 case('${{action.ident}}(m_tbe_ptr, m_cache_entry_ptr, addr);') 1315 elif self.TBEType != None: 1316 for action in actions: 1317 case('${{action.ident}}(m_tbe_ptr, addr);') 1318 elif self.EntryType != None: 1319 for action in actions: 1320 case('${{action.ident}}(m_cache_entry_ptr, addr);') 1321 else: 1322 for action in actions: 1323 case('${{action.ident}}(addr);') 1324 case('return TransitionResult_Valid;') 1325 1326 case = str(case) 1327 1328 # Look to see if this transition code is unique. 1329 if case not in cases: 1330 cases[case] = [] 1331 1332 cases[case].append(case_string) 1333 1334 # Walk through all of the unique code blocks and spit out the 1335 # corresponding case statement elements 1336 for case,transitions in cases.iteritems(): 1337 # Iterative over all the multiple transitions that share 1338 # the same code 1339 for trans in transitions: 1340 code(' case HASH_FUN($trans):') 1341 code(' $case\n') 1342 1343 code(''' 1344 default: 1345 panic("Invalid transition\\n" 1346 "%s time: %d addr: %s event: %s state: %s\\n", 1347 name(), curCycle(), addr, event, state); 1348 } 1349 1350 return TransitionResult_Valid; 1351} 1352''') 1353 code.write(path, "%s_Transitions.cc" % self.ident) 1354 1355 1356 # ************************** 1357 # ******* HTML Files ******* 1358 # ************************** 1359 def frameRef(self, click_href, click_target, over_href, over_num, text): 1360 code = self.symtab.codeFormatter(fix_newlines=False) 1361 code("""<A href=\"$click_href\" target=\"$click_target\" onmouseover=\" 1362 if (parent.frames[$over_num].location != parent.location + '$over_href') { 1363 parent.frames[$over_num].location='$over_href' 1364 }\"> 1365 ${{html.formatShorthand(text)}} 1366 </A>""") 1367 return str(code) 1368 1369 def writeHTMLFiles(self, path): 1370 # Create table with no row hilighted 1371 self.printHTMLTransitions(path, None) 1372 1373 # Generate transition tables 1374 for state in self.states.itervalues(): 1375 self.printHTMLTransitions(path, state) 1376 1377 # Generate action descriptions 1378 for action in self.actions.itervalues(): 1379 name = "%s_action_%s.html" % (self.ident, action.ident) 1380 code = html.createSymbol(action, "Action") 1381 code.write(path, name) 1382 1383 # Generate state descriptions 1384 for state in self.states.itervalues(): 1385 name = "%s_State_%s.html" % (self.ident, state.ident) 1386 code = html.createSymbol(state, "State") 1387 code.write(path, name) 1388 1389 # Generate event descriptions 1390 for event in self.events.itervalues(): 1391 name = "%s_Event_%s.html" % (self.ident, event.ident) 1392 code = html.createSymbol(event, "Event") 1393 code.write(path, name) 1394 1395 def printHTMLTransitions(self, path, active_state): 1396 code = self.symtab.codeFormatter() 1397 1398 code(''' 1399<HTML> 1400<BODY link="blue" vlink="blue"> 1401 1402<H1 align="center">${{html.formatShorthand(self.short)}}: 1403''') 1404 code.indent() 1405 for i,machine in enumerate(self.symtab.getAllType(StateMachine)): 1406 mid = machine.ident 1407 if i != 0: 1408 extra = " - " 1409 else: 1410 extra = "" 1411 if machine == self: 1412 code('$extra$mid') 1413 else: 1414 code('$extra<A target="Table" href="${mid}_table.html">$mid</A>') 1415 code.dedent() 1416 1417 code(""" 1418</H1> 1419 1420<TABLE border=1> 1421<TR> 1422 <TH> </TH> 1423""") 1424 1425 for event in self.events.itervalues(): 1426 href = "%s_Event_%s.html" % (self.ident, event.ident) 1427 ref = self.frameRef(href, "Status", href, "1", event.short) 1428 code('<TH bgcolor=white>$ref</TH>') 1429 1430 code('</TR>') 1431 # -- Body of table 1432 for state in self.states.itervalues(): 1433 # -- Each row 1434 if state == active_state: 1435 color = "yellow" 1436 else: 1437 color = "white" 1438 1439 click = "%s_table_%s.html" % (self.ident, state.ident) 1440 over = "%s_State_%s.html" % (self.ident, state.ident) 1441 text = html.formatShorthand(state.short) 1442 ref = self.frameRef(click, "Table", over, "1", state.short) 1443 code(''' 1444<TR> 1445 <TH bgcolor=$color>$ref</TH> 1446''') 1447 1448 # -- One column for each event 1449 for event in self.events.itervalues(): 1450 trans = self.table.get((state,event), None) 1451 if trans is None: 1452 # This is the no transition case 1453 if state == active_state: 1454 color = "#C0C000" 1455 else: 1456 color = "lightgrey" 1457 1458 code('<TD bgcolor=$color> </TD>') 1459 continue 1460 1461 next = trans.nextState 1462 stall_action = False 1463 1464 # -- Get the actions 1465 for action in trans.actions: 1466 if action.ident == "z_stall" or \ 1467 action.ident == "zz_recycleMandatoryQueue": 1468 stall_action = True 1469 1470 # -- Print out "actions/next-state" 1471 if stall_action: 1472 if state == active_state: 1473 color = "#C0C000" 1474 else: 1475 color = "lightgrey" 1476 1477 elif active_state and next.ident == active_state.ident: 1478 color = "aqua" 1479 elif state == active_state: 1480 color = "yellow" 1481 else: 1482 color = "white" 1483 1484 code('<TD bgcolor=$color>') 1485 for action in trans.actions: 1486 href = "%s_action_%s.html" % (self.ident, action.ident) 1487 ref = self.frameRef(href, "Status", href, "1", 1488 action.short) 1489 code(' $ref') 1490 if next != state: 1491 if trans.actions: 1492 code('/') 1493 click = "%s_table_%s.html" % (self.ident, next.ident) 1494 over = "%s_State_%s.html" % (self.ident, next.ident) 1495 ref = self.frameRef(click, "Table", over, "1", next.short) 1496 code("$ref") 1497 code("</TD>") 1498 1499 # -- Each row 1500 if state == active_state: 1501 color = "yellow" 1502 else: 1503 color = "white" 1504 1505 click = "%s_table_%s.html" % (self.ident, state.ident) 1506 over = "%s_State_%s.html" % (self.ident, state.ident) 1507 ref = self.frameRef(click, "Table", over, "1", state.short) 1508 code(''' 1509 <TH bgcolor=$color>$ref</TH> 1510</TR> 1511''') 1512 code(''' 1513<!- Column footer-> 1514<TR> 1515 <TH> </TH> 1516''') 1517 1518 for event in self.events.itervalues(): 1519 href = "%s_Event_%s.html" % (self.ident, event.ident) 1520 ref = self.frameRef(href, "Status", href, "1", event.short) 1521 code('<TH bgcolor=white>$ref</TH>') 1522 code(''' 1523</TR> 1524</TABLE> 1525</BODY></HTML> 1526''') 1527 1528 1529 if active_state: 1530 name = "%s_table_%s.html" % (self.ident, active_state.ident) 1531 else: 1532 name = "%s_table.html" % self.ident 1533 code.write(path, name) 1534 1535__all__ = [ "StateMachine" ] 1536