def __init__(self, symtab, ident, location, pairs, config_parameters): super(StateMachine, self).__init__(symtab, ident, location, pairs) self.table = None 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) else: var = Var(symtab, param.name, location, param.type_ast.type, "m_%s" % param.name, {}, self) self.symtab.registerSym(param.name, 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.TBEType = None self.EntryType = None
def __init__(self, table, ident, location, pairs, machine=None): super(Type, self).__init__(table, ident, location, pairs) self.c_ident = ident self.abstract_ident = "" if machine: if self.isExternal or self.isPrimitive: if "external_name" in self: self.c_ident = self["external_name"] else: # Append with machine name self.c_ident = "%s_%s" % (machine, ident) self.pairs.setdefault("desc", "No description avaliable") # check for interface that this Type implements if "interface" in self: interface = self["interface"] if interface in ("Message", "NetworkMessage"): self["message"] = "yes" if interface == "NetworkMessage": self["networkmessage"] = "yes" # FIXME - all of the following id comparisons are fragile hacks if self.ident in ("CacheMemory", "NewCacheMemory", "TLCCacheMemory", "DNUCACacheMemory", "DNUCABankCacheMemory", "L2BankCacheMemory", "CompressedCacheMemory", "PrefetchCacheMemory"): self["cache"] = "yes" if self.ident in ("TBETable", "DNUCATBETable", "DNUCAStopTable"): self["tbe"] = "yes" if self.ident == "NewTBETable": self["newtbe"] = "yes" if self.ident == "TimerTable": self["timer"] = "yes" if self.ident == "DirectoryMemory": self["dir"] = "yes" if self.ident == "PersistentTable": self["persistent"] = "yes" if self.ident == "Prefetcher": self["prefetcher"] = "yes" if self.ident == "DNUCA_Movement": self["mover"] = "yes" self.isMachineType = (ident == "MachineType") self.data_members = orderdict() # Methods self.methods = {} # Enums self.enums = orderdict()
def __init__(self, table, ident, location, pairs, machine=None): super(Type, self).__init__(table, ident, location, pairs) self.c_ident = ident self.abstract_ident = "" if machine: if self.isExternal or self.isPrimitive: if "external_name" in self: self.c_ident = self["external_name"] else: # Append with machine name self.c_ident = "%s_%s" % (machine, ident) self.pairs.setdefault("desc", "No description avaliable") # check for interface that this Type implements if "interface" in self: interface = self["interface"] if interface in ("Message", "NetworkMessage"): self["message"] = "yes" if interface == "NetworkMessage": self["networkmessage"] = "yes" # FIXME - all of the following id comparisons are fragile hacks if self.ident in ("CacheMemory"): self["cache"] = "yes" if self.ident in ("TBETable"): self["tbe"] = "yes" if self.ident == "TimerTable": self["timer"] = "yes" if self.ident == "DirectoryMemory": self["dir"] = "yes" if self.ident == "PersistentTable": self["persistent"] = "yes" if self.ident == "Prefetcher": self["prefetcher"] = "yes" self.isMachineType = (ident == "MachineType") self.isStateDecl = ("state_decl" in self) self.statePermPairs = [] self.data_members = orderdict() # Methods self.methods = {} self.functions = {} # Enums self.enums = orderdict()
def __init__(self, table, ident, location, pairs, machine=None): super(Type, self).__init__(table, ident, location, pairs) self.c_ident = ident self.abstract_ident = "" if machine: if self.isExternal or self.isPrimitive: if "external_name" in self: self.c_ident = self["external_name"] else: # Append with machine name self.c_ident = "%s_%s" % (machine, ident) self.pairs.setdefault("desc", "No description avaliable") # check for interface that this Type implements if "interface" in self: interface = self["interface"] if interface in ("Message"): self["message"] = "yes" # FIXME - all of the following id comparisons are fragile hacks if self.ident in ("CacheMemory"): self["cache"] = "yes" if self.ident in ("TBETable"): self["tbe"] = "yes" if self.ident == "TimerTable": self["timer"] = "yes" if self.ident == "DirectoryMemory": self["dir"] = "yes" if self.ident == "PersistentTable": self["persistent"] = "yes" if self.ident == "Prefetcher": self["prefetcher"] = "yes" if self.ident == "RCTable": self["RCtable"] = "yes" self.isMachineType = (ident == "MachineType") self.isStateDecl = ("state_decl" in self) self.statePermPairs = [] self.data_members = orderdict() self.methods = {} self.enums = orderdict()
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.ident, location, param.type_ast.type, "(*m_%s_ptr)" % param.ident, {}, self) else: 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 = [] # Data members in the State Machine that have been declared inside # the {} machine. Note that these along with the config params # form the entire set of data members of the machine. self.objects = [] self.TBEType = None self.EntryType = None self.debug_flags = set() self.debug_flags.add('RubyGenerated') self.debug_flags.add('RubySlicc')
def __init__(self, symtab, ident, location, pairs, config_parameters): super(StateMachine, self).__init__(symtab, ident, location, pairs) self.table = None self.config_parameters = config_parameters for param in config_parameters: if param.pointer: var = Var(symtab, param.name, location, param.type_ast.type, "(*m_%s_ptr)" % param.name, {}, self) else: var = Var(symtab, param.name, location, param.type_ast.type, "m_%s" % param.name, {}, self) self.symtab.registerSym(param.name, var) self.states = orderdict() self.events = orderdict() self.actions = orderdict() self.transitions = [] self.in_ports = [] self.functions = [] self.objects = [] self.message_buffer_names = []
def printCSwitch(self, path): '''Output switch statement for transition table''' code = self.symtab.codeFormatter() ident = self.ident code(''' // Auto generated C++ code started by $__file__:$__line__ // ${ident}: ${{self.short}} #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}_Event.hh" #include "mem/protocol/${ident}_State.hh" #include "mem/protocol/Types.hh" #include "mem/ruby/system/RubySystem.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, ''') 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(''' Addr addr) { ''') code.indent() if self.TBEType != None and self.EntryType != None: code( '${ident}_State state = getState(m_tbe_ptr, m_cache_entry_ptr, addr);' ) elif self.TBEType != None: code('${ident}_State state = getState(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: %#x\\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);') port_to_buf_map, in_msg_bufs, msg_bufs = self.getBufferMaps(ident) 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 %#x %s\\n", curTick(), m_version, "${ident}", ${ident}_Event_to_string(event), ${ident}_State_to_string(state), ${ident}_State_to_string(next_state), printAddress(addr), GET_TRANSITION_COMMENT()); CLEAR_TRANSITION_COMMENT(); ''') if self.TBEType != None and self.EntryType != None: code('setState(m_tbe_ptr, m_cache_entry_ptr, addr, next_state);') code('setAccessPermission(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);') code(''' } else if (result == TransitionResult_ResourceStall) { DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %#x %s\\n", curTick(), m_version, "${ident}", ${ident}_Event_to_string(event), ${ident}_State_to_string(state), ${ident}_State_to_string(next_state), printAddress(addr), "Resource Stall"); } else if (result == TransitionResult_ProtocolStall) { DPRINTF(RubyGenerated, "stalling\\n"); DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %#x %s\\n", curTick(), m_version, "${ident}", ${ident}_Event_to_string(event), ${ident}_State_to_string(state), ${ident}_State_to_string(next_state), printAddress(addr), "Protocol Stall"); } 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(''' Addr addr) { switch(HASH_FUN(state, event)) { ''') # This map will allow suppress generating duplicate code cases = orderdict() for trans in self.transitions: case_string = "%s_State_%s, %s_Event_%s" % \ (self.ident, trans.state.ident, self.ident, trans.event.ident) case = self.symtab.codeFormatter() # Only set next_state if it changes if trans.state != trans.nextState: if trans.nextState.isWildcard(): # When * is encountered as an end state of a transition, # the next state is determined by calling the # machine-specific getNextState function. The next state # is determined before any actions of the transition # execute, and therefore the next state calculation cannot # depend on any of the transitionactions. case('next_state = getNextState(addr);') else: 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(): val = ''' if (!%s.areNSlotsAvailable(%s, clockEdge())) 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 # since Map's keys() on a vector of pointers is not deterministic 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 action.ident == "z_stall": stall = True break if stall: case('return TransitionResult_ProtocolStall;') else: 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) # Look to see if this transition code is unique. if case not in cases: cases[case] = [] cases[case].append(case_string) # Walk through all of the unique code blocks and spit out the # corresponding case statement elements for case, transitions in cases.iteritems(): # Iterative over all the multiple transitions that share # the same code for trans in transitions: code(' case HASH_FUN($trans):') code(' $case\n') code(''' default: panic("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 printCSwitch(self, path): '''Output switch statement for transition table''' 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 "mem/protocol/${ident}_Controller.hh" #include "mem/protocol/${ident}_State.hh" #include "mem/protocol/${ident}_Event.hh" #include "mem/protocol/Types.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) { ${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()); } 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"); } } return result; } TransitionResult ${ident}_Controller::doTransitionWorker(${ident}_Event event, ${ident}_State state, ${ident}_State& next_state, const Address& addr) { switch(HASH_FUN(state, event)) { ''') # This map will allow suppress generating duplicate code cases = orderdict() for trans in self.transitions: case_string = "%s_State_%s, %s_Event_%s" % \ (self.ident, trans.state.ident, self.ident, trans.event.ident) 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 # Check for resources case_sorter = [] res = trans.resources for key,val in res.iteritems(): if key.type.ident != "DNUCAStopTable": val = ''' if (!%s.areNSlotsAvailable(%s)) return TransitionResult_ResourceStall; ''' % (key.code, val) case_sorter.append(val) # Emit the code sequences in a sorted order. This makes the # output deterministic (without this the output order can vary # since Map's keys() on a vector of pointers is not deterministic for c in sorted(case_sorter): case("$c") # Figure out if we stall stall = False for action in actions: if action.ident == "z_stall": stall = True break if stall: case('return TransitionResult_ProtocolStall;') else: for action in actions: case('${{action.ident}}(addr);') case('return TransitionResult_Valid;') case = str(case) # Look to see if this transition code is unique. if case not in cases: cases[case] = [] cases[case].append(case_string) # Walk through all of the unique code blocks and spit out the # corresponding case statement elements for case,transitions in cases.iteritems(): # Iterative over all the multiple transitions that share # the same code for trans in transitions: code(' case HASH_FUN($trans):') code(' $case') 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\"); } return TransitionResult_Valid; } ''') code.write(path, "%s_Transitions.cc" % self.ident)
def printCSwitch(self, path): '''Output switch statement for transition table''' code = self.symtab.codeFormatter() ident = self.ident code(''' // Auto generated C++ code started by $__file__:$__line__ // ${ident}: ${{self.short}} #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}_Event.hh" #include "mem/protocol/${ident}_State.hh" #include "mem/protocol/Types.hh" #include "mem/ruby/system/RubySystem.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, ''') 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(''' Addr addr) { ''') code.indent() if self.TBEType != None and self.EntryType != None: code('${ident}_State state = getState(m_tbe_ptr, m_cache_entry_ptr, addr);') elif self.TBEType != None: code('${ident}_State state = getState(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: %#x\\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);') port_to_buf_map, in_msg_bufs, msg_bufs = self.getBufferMaps(ident) 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 %#x %s\\n", curTick(), m_version, "${ident}", ${ident}_Event_to_string(event), ${ident}_State_to_string(state), ${ident}_State_to_string(next_state), printAddress(addr), GET_TRANSITION_COMMENT()); CLEAR_TRANSITION_COMMENT(); ''') if self.TBEType != None and self.EntryType != None: code('setState(m_tbe_ptr, m_cache_entry_ptr, addr, next_state);') code('setAccessPermission(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);') code(''' } else if (result == TransitionResult_ResourceStall) { DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %#x %s\\n", curTick(), m_version, "${ident}", ${ident}_Event_to_string(event), ${ident}_State_to_string(state), ${ident}_State_to_string(next_state), printAddress(addr), "Resource Stall"); } else if (result == TransitionResult_ProtocolStall) { DPRINTF(RubyGenerated, "stalling\\n"); DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %#x %s\\n", curTick(), m_version, "${ident}", ${ident}_Event_to_string(event), ${ident}_State_to_string(state), ${ident}_State_to_string(next_state), printAddress(addr), "Protocol Stall"); } 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(''' Addr addr) { switch(HASH_FUN(state, event)) { ''') # This map will allow suppress generating duplicate code cases = orderdict() for trans in self.transitions: case_string = "%s_State_%s, %s_Event_%s" % \ (self.ident, trans.state.ident, self.ident, trans.event.ident) case = self.symtab.codeFormatter() # Only set next_state if it changes if trans.state != trans.nextState: if trans.nextState.isWildcard(): # When * is encountered as an end state of a transition, # the next state is determined by calling the # machine-specific getNextState function. The next state # is determined before any actions of the transition # execute, and therefore the next state calculation cannot # depend on any of the transitionactions. case('next_state = getNextState(addr);') else: 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(): val = ''' if (!%s.areNSlotsAvailable(%s, clockEdge())) 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 # since Map's keys() on a vector of pointers is not deterministic 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 action.ident == "z_stall": stall = True break if stall: case('return TransitionResult_ProtocolStall;') else: 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) # Look to see if this transition code is unique. if case not in cases: cases[case] = [] cases[case].append(case_string) # Walk through all of the unique code blocks and spit out the # corresponding case statement elements for case,transitions in cases.iteritems(): # Iterative over all the multiple transitions that share # the same code for trans in transitions: code(' case HASH_FUN($trans):') code(' $case\n') code(''' default: panic("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 printCSwitch(self, path): '''Output switch statement for transition table''' 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 "mem/protocol/${ident}_Controller.hh" #include "mem/protocol/${ident}_State.hh" #include "mem/protocol/${ident}_Event.hh" #include "mem/protocol/Types.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) { ${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()); } 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"); } } return result; } TransitionResult ${ident}_Controller::doTransitionWorker(${ident}_Event event, ${ident}_State state, ${ident}_State& next_state, const Address& addr) { switch(HASH_FUN(state, event)) { ''') # This map will allow suppress generating duplicate code cases = orderdict() for trans in self.transitions: case_string = "%s_State_%s, %s_Event_%s" % \ (self.ident, trans.state.ident, self.ident, trans.event.ident) 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 # Check for resources case_sorter = [] res = trans.resources for key, val in res.iteritems(): if key.type.ident != "DNUCAStopTable": val = ''' if (!%s.areNSlotsAvailable(%s)) return TransitionResult_ResourceStall; ''' % (key.code, val) case_sorter.append(val) # Emit the code sequences in a sorted order. This makes the # output deterministic (without this the output order can vary # since Map's keys() on a vector of pointers is not deterministic for c in sorted(case_sorter): case("$c") # Figure out if we stall stall = False for action in actions: if action.ident == "z_stall": stall = True break if stall: case('return TransitionResult_ProtocolStall;') else: for action in actions: case('${{action.ident}}(addr);') case('return TransitionResult_Valid;') case = str(case) # Look to see if this transition code is unique. if case not in cases: cases[case] = [] cases[case].append(case_string) # Walk through all of the unique code blocks and spit out the # corresponding case statement elements for case, transitions in cases.iteritems(): # Iterative over all the multiple transitions that share # the same code for trans in transitions: code(' case HASH_FUN($trans):') code(' $case') 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\"); } return TransitionResult_Valid; } ''') code.write(path, "%s_Transitions.cc" % self.ident)
def printCSwitch(self, path): """Output switch statement for transition table""" code = self.symtab.codeFormatter() ident = self.ident code( """ // Auto generated C++ code started by $__file__:$__line__ // ${ident}: ${{self.short}} #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}_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, """ ) 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) { """ ) 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(); """ ) 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);") 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"); } return result; } 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)) { """ ) # This map will allow suppress generating duplicate code cases = orderdict() for trans in self.transitions: case_string = "%s_State_%s, %s_Event_%s" % (self.ident, trans.state.ident, self.ident, trans.event.ident) 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)) 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 # since Map's keys() on a vector of pointers is not deterministic 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 action.ident == "z_stall": stall = True break if stall: case("return TransitionResult_ProtocolStall;") else: 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) # Look to see if this transition code is unique. if case not in cases: cases[case] = [] cases[case].append(case_string) # Walk through all of the unique code blocks and spit out the # corresponding case statement elements for case, transitions in cases.iteritems(): # Iterative over all the multiple transitions that share # the same code for trans in transitions: code(" case HASH_FUN($trans):") code(" $case") code( """ default: 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)