Skip to content

Commit 2a0a612

Browse files
committed
In FSM and Seq, Else is realized as a property, and actual Else operation is synthesized when add() is called. So FSM.goto() and related methods can use Else condition, as well as value assignment.
1 parent f19c407 commit 2a0a612

File tree

5 files changed

+185
-61
lines changed

5 files changed

+185
-61
lines changed

tests/extension/fsm_/as_module/fsm_as_module.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ def mkLed():
3333
fsm.goto_next()
3434

3535
# jump by using label "init"
36-
fsm.goto(dst=init, cond=(count < 1024), else_dst=fsm.next).inc()
36+
fsm.goto(dst=init, cond=(count < 1024), else_dst=fsm.next)
37+
fsm.inc()
3738

3839
fsm(led(led + 1))
3940
# jump by using label "here"

tests/extension/fsm_/branch/fsm_branch.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ def add_if_else(fsm, ifelse):
2323
index_merge = fsm.current + len(ifelse.true_statements) + len(ifelse.false_statements) + 1
2424
index_true = fsm.current + 1 if ifelse.true_statements else index_merge
2525

26-
fsm.goto( dst=index_true, cond=ifelse.condition, else_dst=index_else ).inc()
26+
fsm.goto( dst=index_true, cond=ifelse.condition, else_dst=index_else )
27+
fsm.inc()
2728

2829
# then
2930
for i, s in enumerate(ifelse.true_statements):
@@ -32,7 +33,8 @@ def add_if_else(fsm, ifelse):
3233
fsm.goto_next()
3334
else:
3435
fsm( *s )
35-
fsm.goto(index_merge).inc()
36+
fsm.goto(index_merge)
37+
fsm.inc()
3638

3739
# else
3840
for i, s in enumerate(ifelse.false_statements):

veriloggen/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343

4444
# Abstract Extension
4545
from .seq.seq import Seq, TmpSeq, make_condition
46-
from .fsm.fsm import FSM, TmpFSM
46+
from .fsm.fsm import FSM, TmpFSM, State
4747
from .pipeline.pipeline import Pipeline
4848

4949
# Extension reset

veriloggen/fsm/fsm.py

Lines changed: 158 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ def __init__(self, m, name, clk, rst, width=32, initname='init',
7575
self.last_cond = []
7676
self.last_kwargs = {}
7777
self.last_if_statement = None
78+
self.next_else = False
7879
self.elif_cond = None
7980
self.next_kwargs = {}
8081

@@ -85,61 +86,111 @@ def __init__(self, m, name, clk, rst, width=32, initname='init',
8586

8687
# -------------------------------------------------------------------------
8788
def goto(self, dst, cond=None, else_dst=None):
89+
if isinstance(dst, State):
90+
dst = dst.index
91+
8892
if cond is None and 'cond' in self.next_kwargs:
8993
cond = self.next_kwargs['cond']
94+
95+
if 'index' in self.next_kwargs:
96+
index = self.next_kwargs['index']
97+
else:
98+
index = None
99+
90100
self._clear_next_kwargs()
91-
self._clear_last_if_statement()
92-
self._clear_last_cond()
101+
# self._clear_last_if_statement()
102+
# self._clear_last_cond()
103+
# self._clear_elif_cond()
93104

94-
src = self.current
95-
return self._go(src, dst, cond, else_dst)
105+
if index is None:
106+
src = self.current
107+
else:
108+
src = index
109+
110+
self._go(src, dst, cond, else_dst)
111+
return State(self, dst)
96112

97113
def goto_init(self, cond=None):
98114
if cond is None and 'cond' in self.next_kwargs:
99115
cond = self.next_kwargs['cond']
116+
117+
if 'index' in self.next_kwargs:
118+
index = self.next_kwargs['index']
119+
else:
120+
index = None
121+
100122
self._clear_next_kwargs()
101-
self._clear_last_if_statement()
102-
self._clear_last_cond()
123+
# self._clear_last_if_statement()
124+
# self._clear_last_cond()
125+
# self._clear_elif_cond()
126+
127+
if index is None:
128+
src = self.current
129+
else:
130+
src = index
103131

104-
src = self.current
105132
dst = 0
106-
return self._go(src, dst, cond)
133+
self._go(src, dst, cond)
134+
return State(self, dst)
107135

108136
def goto_next(self, cond=None):
109137
if cond is None and 'cond' in self.next_kwargs:
110138
cond = self.next_kwargs['cond']
139+
140+
if 'index' in self.next_kwargs:
141+
index = self.next_kwargs['index']
142+
else:
143+
index = None
144+
111145
self._clear_next_kwargs()
112-
self._clear_last_if_statement()
113-
self._clear_last_cond()
146+
# self._clear_last_if_statement()
147+
# self._clear_last_cond()
148+
# self._clear_elif_cond()
149+
150+
if index is None:
151+
src = self.current
152+
else:
153+
src = index
114154

115-
src = self.current
116-
dst = self.current + 1
117-
ret = self._go(src, dst, cond=cond)
155+
dst = src + 1
156+
self._go(src, dst, cond=cond)
118157
self.inc()
119-
return ret
158+
return State(self, dst)
120159

121160
def goto_from(self, src, dst, cond=None, else_dst=None):
161+
if isinstance(src, State):
162+
src = src.index
163+
164+
if isinstance(dst, State):
165+
dst = dst.index
166+
122167
if cond is None and 'cond' in self.next_kwargs:
123168
cond = self.next_kwargs['cond']
169+
124170
self._clear_next_kwargs()
125-
self._clear_last_if_statement()
126-
self._clear_last_cond()
171+
# self._clear_last_if_statement()
172+
# self._clear_last_cond()
173+
# self._clear_elif_cond()
127174

128-
return self._go(src, dst, cond, else_dst)
175+
self._go(src, dst, cond, else_dst)
176+
return State(self, dst)
129177

130178
def inc(self):
131-
self._set_index(None)
179+
return self._set_index(None)
132180

133181
# -------------------------------------------------------------------------
134182
def add(self, *statement, **kwargs):
135-
""" add new assignments """
183+
""" Adding new assignments. This method is usually called via __call__(). """
136184
kwargs.update(self.next_kwargs)
137185
self.last_kwargs = kwargs
138186
self._clear_next_kwargs()
139187

140188
# if there is no attributes, Elif object is reused.
141189
has_args = not (len(kwargs) == 0 or # has no args
142-
(len(kwargs) == 1 and 'cond' in kwargs)) # has only 'cond'
190+
(len(kwargs) == 1 and 'cond' in kwargs) or # has only 'cond'
191+
(len(kwargs) == 1 and 'index' in kwargs) or # has only 'index'
192+
(len(kwargs) == 2 and
193+
'cond' in kwargs and 'index' in kwargs)) # has only 'cond' and 'index'
143194

144195
if self.elif_cond is not None and not has_args:
145196
next_call = self.last_if_statement.Elif(self.elif_cond)
@@ -149,6 +200,14 @@ def add(self, *statement, **kwargs):
149200
self._clear_elif_cond()
150201
return self
151202

203+
if self.next_else and not has_args:
204+
next_call = self.last_if_statement.Else
205+
next_call(*statement)
206+
self._add_dst_var(statement)
207+
self._clear_last_if_statement()
208+
self._clear_elif_cond()
209+
return self
210+
152211
self._clear_last_if_statement()
153212
return self._add_statement(statement, **kwargs)
154213

@@ -179,7 +238,8 @@ def If(self, *cond):
179238

180239
return self
181240

182-
def Else(self, *statement, **kwargs):
241+
@property
242+
def Else(self):
183243
self._clear_elif_cond()
184244

185245
if len(self.last_cond) == 0:
@@ -192,25 +252,20 @@ def Else(self, *statement, **kwargs):
192252
# Else statement is separated.
193253
if 'delay' in self.last_kwargs and self.last_kwargs['delay'] > 0:
194254
prev_cond = self.last_cond
195-
ret = self.Then()(*statement)
255+
ret = self.Then()
196256
self.last_cond = prev_cond
197257
return ret
198258

199-
# if there is additional attribute, Else statement is separated.
200-
has_args = not (len(self.next_kwargs) == 0 or # has no args
201-
(len(self.next_kwargs) == 1 and 'cond' in kwargs)) # has only 'cond'
259+
# if not isinstance(self.last_if_statement, vtypes.If):
260+
# raise ValueError("Last if-statement is not If")
202261

203-
if has_args:
204-
prev_cond = self.last_cond
205-
ret = self.Then()(*statement)
206-
self.last_cond = prev_cond
207-
return ret
262+
# self.next_else = True
208263

209-
if not isinstance(self.last_if_statement, vtypes.If):
210-
raise ValueError("Last if-statement is not If")
264+
if isinstance(self.last_if_statement, vtypes.If):
265+
self.next_else = True
211266

212-
self.last_if_statement.Else(*statement)
213-
self._add_dst_var(statement)
267+
cond = self._make_cond(self.last_cond)
268+
self.next_kwargs['cond'] = cond
214269

215270
return self
216271

@@ -224,18 +279,21 @@ def Elif(self, *cond):
224279
self.last_cond.append(vtypes.Not(old))
225280
self.last_cond.append(cond)
226281

227-
# if the true-statement has delay attributes, Else statement is
228-
# separated.
282+
# if the true-statement has delay attributes,
283+
# Else statement is separated.
229284
if 'delay' in self.last_kwargs and self.last_kwargs['delay'] > 0:
230285
prev_cond = self.last_cond
231286
ret = self.Then()
232287
self.last_cond = prev_cond
233288
return ret
234289

235-
if not isinstance(self.last_if_statement, vtypes.If):
236-
raise ValueError("Last if-statement is not If")
290+
# if not isinstance(self.last_if_statement, vtypes.If):
291+
# raise ValueError("Last if-statement is not If")
237292

238-
self.elif_cond = cond
293+
# self.elif_cond = cond
294+
295+
if isinstance(self.last_if_statement, vtypes.If):
296+
self.elif_cond = cond
239297

240298
cond = self._make_cond(self.last_cond)
241299
self.next_kwargs['cond'] = cond
@@ -264,6 +322,10 @@ def EagerVal(self, value=True):
264322
self.next_kwargs['eager_val'] = value
265323
return self
266324

325+
def When(self, index):
326+
self.next_kwargs['index'] = index
327+
return self
328+
267329
def Clear(self):
268330
self._clear_next_kwargs()
269331
self._clear_last_if_statement()
@@ -272,13 +334,21 @@ def Clear(self):
272334
return self
273335

274336
# -------------------------------------------------------------------------
337+
@property
338+
def Always(self):
339+
return self.seq
340+
341+
@property
342+
def init(self):
343+
return State(self, 0)
344+
275345
@property
276346
def current(self):
277-
return self.state_count
347+
return State(self, self.state_count)
278348

279349
@property
280350
def next(self):
281-
return self.current + 1
351+
return State(self, self.state_count + 1)
282352

283353
@property
284354
def current_delay(self):
@@ -806,6 +876,7 @@ def _clear_next_kwargs(self):
806876

807877
def _clear_last_if_statement(self):
808878
self.last_if_statement = None
879+
self.next_else = False
809880

810881
def _clear_last_cond(self):
811882
self.last_cond = []
@@ -824,9 +895,15 @@ def _make_cond(self, condlist):
824895

825896
# -------------------------------------------------------------------------
826897
def _set_index(self, index=None):
898+
self._clear_next_kwargs()
899+
self._clear_last_if_statement()
900+
self._clear_last_cond()
901+
self._clear_elif_cond()
902+
827903
if index is None:
828904
self.state_count += 1
829905
return self.state_count
906+
830907
self.state_count = index
831908
return self.state_count
832909

@@ -970,3 +1047,43 @@ def __getitem__(self, index):
9701047

9711048
def __len__(self):
9721049
return self.state_count + 1
1050+
1051+
1052+
class State(vtypes.VeriloggenNode):
1053+
""" FSM with a specic state index """
1054+
1055+
def __init__(self, fsm, index):
1056+
while isinstance(fsm, State):
1057+
fsm = fsm.fsm
1058+
1059+
while isinstance(index, State):
1060+
index = index.index
1061+
1062+
if not isinstance(fsm, FSM):
1063+
raise TypeError("'fsm' must be FSM, not '%s'" % str(type(fsm)))
1064+
1065+
if not isinstance(index, int):
1066+
raise TypeError("'index' must be int, not '%s'" % str(type(index)))
1067+
1068+
self.fsm = fsm
1069+
self.index = index
1070+
1071+
def __getattr__(self, attr):
1072+
self.fsm.When(self.index)
1073+
return getattr(self.fsm, attr)
1074+
1075+
def __call__(self, *statement, **kwargs):
1076+
self.fsm.When(self.index)
1077+
return self.fsm.__call__(*statement, **kwargs)
1078+
1079+
def __add__(self, r):
1080+
if isinstance(r, State):
1081+
r = r.index
1082+
1083+
return self.index + r
1084+
1085+
def __sub__(self, r):
1086+
if isinstance(r, State):
1087+
r = r.index
1088+
1089+
return self.index - r

0 commit comments

Comments
 (0)