Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

genlib/fsm: add entering/ongoing/leaving methods

  • Loading branch information...
commit 4fb3e970b130e9dad74c452d4c306fe5fdfc7e60 1 parent 9142278
Sébastien Bourdeauducq authored September 06, 2013
4  examples/basic/fsm.py
@@ -9,6 +9,8 @@ def __init__(self):
9 9
 		self.submodules += myfsm
10 10
 		myfsm.act("FOO", self.s.eq(1), NextState("BAR"))
11 11
 		myfsm.act("BAR", self.s.eq(0), NextState("FOO"))
  12
+		self.entering_foo = myfsm.entering("FOO")
  13
+		self.leaving_bar = myfsm.leaving("BAR")
12 14
 
13 15
 example = Example()
14  
-print(verilog.convert(example, {example.s}))
  16
+print(verilog.convert(example, {example.s, example.entering_foo, example.leaving_bar}))
42  migen/genlib/fsm.py
@@ -35,6 +35,9 @@ def __init__(self, reset_state=None):
35 35
 		self.state_aliases = dict()
36 36
 		self.reset_state = reset_state
37 37
 
  38
+		self.entering_signals = OrderedDict()
  39
+		self.leaving_signals = OrderedDict()
  40
+
38 41
 	def act(self, state, *statements):
39 42
 		if self.finalized:
40 43
 			raise FinalizeError
@@ -56,14 +59,37 @@ def delayed_enter(self, name, target, delay):
56 59
 				state = next_state
57 60
 		else:
58 61
 			self.state_aliases[name] = target
  62
+
  63
+	def ongoing(self, state):
  64
+		is_ongoing = Signal()
  65
+		self.act(state, is_ongoing.eq(1))
  66
+		return is_ongoing
  67
+
  68
+	def _entering_leaving(self, d, state):
  69
+		if state not in self.actions:
  70
+			self.actions[state] = []
  71
+		try:
  72
+			return d[state]
  73
+		except KeyError:
  74
+			is_el = Signal()
  75
+			d[state] = is_el
  76
+			return is_el
  77
+
  78
+	def entering(self, state):
  79
+		return self._entering_leaving(self.entering_signals, state)
  80
+
  81
+	def leaving(self, state):
  82
+		return self._entering_leaving(self.leaving_signals, state)
59 83
 	
60 84
 	def do_finalize(self):
61 85
 		nstates = len(self.actions)
  86
+		if self.reset_state is None:
  87
+			reset_state = next(iter(self.actions.keys()))
  88
+		else:
  89
+			reset_state = self.reset_state
62 90
 
63 91
 		self.encoding = dict((s, n) for n, s in enumerate(self.actions.keys()))
64  
-		self.state = Signal(max=nstates)
65  
-		if self.reset_state is not None:
66  
-			self.state.reset = self.encoding[self.reset_state]
  92
+		self.state = Signal(max=nstates, reset=self.encoding[reset_state])
67 93
 		self.next_state = Signal(max=nstates)
68 94
 
69 95
 		lns = _LowerNextState(self.next_state, self.encoding, self.state_aliases)
@@ -73,3 +99,13 @@ def do_finalize(self):
73 99
 			Case(self.state, cases)
74 100
 		]
75 101
 		self.sync += self.state.eq(self.next_state)
  102
+
  103
+		# drive entering/leaving signals
  104
+		for state, is_entering in self.entering_signals.items():
  105
+			encoded = self.encoding[state]
  106
+			self.sync += is_entering.eq((self.next_state == encoded) & (self.state != encoded))
  107
+		if reset_state in self.entering_signals:
  108
+			self.entering_signals[reset_state].reset = 1
  109
+		for state, is_leaving in self.leaving_signals.items():
  110
+			encoded = self.encoding[state]
  111
+			self.sync += is_leaving.eq((self.next_state != encoded) & (self.state == encoded))

0 notes on commit 4fb3e97

Please sign in to comment.
Something went wrong with that request. Please try again.