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