From ee0d414fa8dac2371b439778374ec585b358e549 Mon Sep 17 00:00:00 2001 From: David Hashe Date: Mon, 20 Jul 2015 09:15:18 -0500 Subject: slicc: support for transitions with a wildcard next state This patches adds support for transitions of the form: transition(START, EVENTS, *) { ACTIONS } This allows a machine to collapse states that differ only in the next state transition to collapse into one, and can help shorten/simplfy some protocols significantly. 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 transition actions. --- src/mem/slicc/parser.py | 9 +++++++-- src/mem/slicc/symbols/State.py | 8 ++++++++ src/mem/slicc/symbols/StateMachine.py | 13 +++++++++++-- src/mem/slicc/symbols/Transition.py | 15 ++++++++++++++- 4 files changed, 40 insertions(+), 5 deletions(-) (limited to 'src/mem/slicc') diff --git a/src/mem/slicc/parser.py b/src/mem/slicc/parser.py index 10dd99ece..1ce8bf1bd 100644 --- a/src/mem/slicc/parser.py +++ b/src/mem/slicc/parser.py @@ -278,7 +278,7 @@ class SLICC(Grammar): p[0] = ast.OutPortDeclAST(self, p[3], p[5], p[7], p[8]) def p_decl__trans0(self, p): - "decl : TRANS '(' idents ',' idents ',' ident ')' idents" + "decl : TRANS '(' idents ',' idents ',' ident_or_star ')' idents" p[0] = ast.TransitionDeclAST(self, [], p[3], p[5], p[7], p[9]) def p_decl__trans1(self, p): @@ -286,7 +286,7 @@ class SLICC(Grammar): p[0] = ast.TransitionDeclAST(self, [], p[3], p[5], None, p[7]) def p_decl__trans2(self, p): - "decl : TRANS '(' idents ',' idents ',' ident ')' idents idents" + "decl : TRANS '(' idents ',' idents ',' ident_or_star ')' idents idents" p[0] = ast.TransitionDeclAST(self, p[9], p[3], p[5], p[7], p[10]) def p_decl__trans3(self, p): @@ -506,6 +506,11 @@ class SLICC(Grammar): "ident : IDENT" p[0] = p[1] + def p_ident_or_star(self, p): + """ident_or_star : ident + | STAR""" + p[0] = p[1] + # Pair and pair lists def p_pairs__list(self, p): "pairs : ',' pairsx" diff --git a/src/mem/slicc/symbols/State.py b/src/mem/slicc/symbols/State.py index 123693256..164c585f6 100644 --- a/src/mem/slicc/symbols/State.py +++ b/src/mem/slicc/symbols/State.py @@ -30,5 +30,13 @@ from slicc.symbols.Symbol import Symbol class State(Symbol): def __repr__(self): return "[State: %s]" % self.ident + def isWildcard(self): + return False + +class WildcardState(State): + def __repr__(self): + return "[State: *]" + def isWildcard(self): + return True __all__ = [ "State" ] diff --git a/src/mem/slicc/symbols/StateMachine.py b/src/mem/slicc/symbols/StateMachine.py index 174d66e0f..8a4d7d9b5 100644 --- a/src/mem/slicc/symbols/StateMachine.py +++ b/src/mem/slicc/symbols/StateMachine.py @@ -1310,8 +1310,17 @@ ${ident}_Controller::doTransitionWorker(${ident}_Event event, 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};') + 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 diff --git a/src/mem/slicc/symbols/Transition.py b/src/mem/slicc/symbols/Transition.py index 901d4a0e8..9ecd6c54b 100644 --- a/src/mem/slicc/symbols/Transition.py +++ b/src/mem/slicc/symbols/Transition.py @@ -26,6 +26,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from slicc.symbols.Symbol import Symbol +from slicc.symbols.State import WildcardState class Transition(Symbol): def __init__(self, table, machine, state, event, nextState, actions, @@ -35,7 +36,19 @@ class Transition(Symbol): self.state = machine.states[state] self.event = machine.events[event] - self.nextState = machine.states[nextState] + if nextState == '*': + # check to make sure there is a getNextState function declared + found = False + for func in machine.functions: + if func.c_ident == 'getNextState': + found = True + break + if found == False: + fatal("Machine uses a wildcard transition without getNextState defined") + self.nextState = WildcardState(machine.symtab, + '*', location) + else: + self.nextState = machine.states[nextState] self.actions = [ machine.actions[a] for a in actions ] self.request_types = [ machine.request_types[s] for s in request_types ] self.resources = {} -- cgit v1.2.3