CSR decoding
[rv32.git] / pipestage.py
1 """ Example 5: Making use of PyRTL and Introspection. """
2
3 from copy import deepcopy
4 from migen import Module, Signal
5 from migen.fhdl import verilog
6 from migen.fhdl.bitcontainer import value_bits_sign
7
8
9 # The following example shows how pyrtl can be used to make some interesting
10 # hardware structures using python introspection. In particular, this example
11 # makes a N-stage pipeline structure. Any specific pipeline is then a derived
12 # class of SimplePipeline where methods with names starting with "stage" are
13 # stages, and new members with names not starting with "_" are to be registered
14 # for the next stage.
15
16 class SimplePipeline(object):
17 """ Pipeline builder with auto generation of pipeline registers. """
18
19 def __init__(self, pipe):
20 self._pipe = pipe
21 self._pipeline_register_map = {}
22 self._current_stage_num = 0
23
24 def _setup(self):
25 stage_list = []
26 for method in dir(self):
27 if method.startswith('stage'):
28 stage_list.append(method)
29 for stage in sorted(stage_list):
30 stage_method = getattr(self, stage)
31 stage_method()
32 self._current_stage_num += 1
33
34 def __getattr__(self, name):
35 try:
36 return self._pipeline_register_map[self._current_stage_num][name]
37 except KeyError:
38 raise AttributeError(
39 'error, no pipeline register "%s" defined for stage %d'
40 % (name, self._current_stage_num))
41
42 def __setattr__(self, name, value):
43 if name.startswith('_'):
44 # do not do anything tricky with variables starting with '_'
45 object.__setattr__(self, name, value)
46 else:
47 next_stage = self._current_stage_num + 1
48 pipereg_id = str(self._current_stage_num) + 'to' + str(next_stage)
49 rname = 'pipereg_' + pipereg_id + '_' + name
50 new_pipereg = Signal(value_bits_sign(value), name_override=rname)
51 if next_stage not in self._pipeline_register_map:
52 self._pipeline_register_map[next_stage] = {}
53 self._pipeline_register_map[next_stage][name] = new_pipereg
54 self._pipe.sync += new_pipereg.eq(value)
55
56
57 class SimplePipelineExample(SimplePipeline):
58 """ A very simple pipeline to show how registers are inferred. """
59
60 def __init__(self, pipe):
61 super(SimplePipelineExample, self).__init__(pipe)
62 self._loopback = Signal(4)
63 self._setup()
64
65 def stage0(self):
66 self.n = ~self._loopback
67
68 def stage1(self):
69 self.n = self.n + 1
70
71 def stage2(self):
72 self.n = self.n << 1
73
74 def stage3(self):
75 self.n = ~self.n
76
77 def stage4(self):
78 self._pipe.sync += self._loopback.eq(self.n + 3)
79
80 class PipeModule(Module):
81 def __init__(self):
82 Module.__init__(self)
83
84 if __name__ == "__main__":
85 example = PipeModule()
86 pipe = SimplePipelineExample(example)
87 print(verilog.convert(example,
88 {
89 pipe._loopback,
90 }))