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
Esempio n. 2
0
    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
Esempio n. 3
0
    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()
Esempio n. 5
0
    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()
Esempio n. 6
0
    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')
Esempio n. 7
0
    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')
Esempio n. 8
0
    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 = []
Esempio n. 9
0
    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 = []
Esempio n. 10
0
    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)
Esempio n. 11
0
    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)
Esempio n. 12
0
    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)
Esempio n. 13
0
    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)
Esempio n. 14
0
    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)