no real point adding reset for internal pipeline variables
[ieee754fpu.git] / src / add / pipeline.py
1 """ Example 5: Making use of PyRTL and Introspection. """
2
3 from nmigen import Signal
4 from nmigen.compat.fhdl.bitcontainer import value_bits_sign
5
6 # The following example shows how pyrtl can be used to make some interesting
7 # hardware structures using python introspection. In particular, this example
8 # makes a N-stage pipeline structure. Any specific pipeline is then a derived
9 # class of SimplePipeline where methods with names starting with "stage" are
10 # stages, and new members with names not starting with "_" are to be registered
11 # for the next stage.
12
13 class SimplePipeline(object):
14 """ Pipeline builder with auto generation of pipeline registers.
15 """
16
17 def __init__(self, pipe):
18 self._pipe = pipe
19 self._pipeline_register_map = {}
20 self._current_stage_num = 0
21
22 def _setup(self):
23 stage_list = []
24 for method in dir(self):
25 if method.startswith('stage'):
26 stage_list.append(method)
27 for stage in sorted(stage_list):
28 stage_method = getattr(self, stage)
29 stage_method()
30 self._current_stage_num += 1
31
32 def __getattr__(self, name):
33 try:
34 return self._pipeline_register_map[self._current_stage_num][name]
35 except KeyError:
36 raise AttributeError(
37 'error, no pipeline register "%s" defined for stage %d'
38 % (name, self._current_stage_num))
39
40 def __setattr__(self, name, value):
41 if name.startswith('_'):
42 # do not do anything tricky with variables starting with '_'
43 object.__setattr__(self, name, value)
44 else:
45 next_stage = self._current_stage_num + 1
46 pipereg_id = str(self._current_stage_num) + 'to' + str(next_stage)
47 rname = 'pipereg_' + pipereg_id + '_' + name
48 new_pipereg = Signal(value_bits_sign(value), name=rname,
49 reset_less=True)
50 if next_stage not in self._pipeline_register_map:
51 self._pipeline_register_map[next_stage] = {}
52 self._pipeline_register_map[next_stage][name] = new_pipereg
53 self._pipe.sync += new_pipereg.eq(value)
54