munge alu_fsm Shifter into looking like CompALU API compliant
[soc.git] / src / soc / experiment / alu_fsm.py
1 """Simple example of a FSM-based ALU
2
3 This demonstrates a design that follows the valid/ready protocol of the
4 ALU, but with a FSM implementation, instead of a pipeline. It is also
5 intended to comply with both the CompALU API and the nmutil Pipeline API
6 (Liskov Substitution Principle)
7
8 The basic rules are:
9
10 1) p.ready_o is asserted on the initial ("Idle") state, otherwise it keeps low.
11 2) n.valid_o is asserted on the final ("Done") state, otherwise it keeps low.
12 3) The FSM stays in the Idle state while p.valid_i is low, otherwise
13 it accepts the input data and moves on.
14 4) The FSM stays in the Done state while n.ready_i is low, otherwise
15 it releases the output data and goes back to the Idle state.
16
17 """
18
19 from nmigen import Elaboratable, Signal, Module
20 from nmigen.back.pysim import Simulator
21 from soc.fu.cr.cr_input_record import CompCROpSubset
22
23
24 class Dummy:
25 pass
26
27
28 class Shifter(Elaboratable):
29 """Simple sequential shifter
30
31 Prev port data:
32 * p.data_i.data: Value to be shifted
33 * p.data_i.shift: Shift amount
34 * p.data_i.dir: Shift direction
35
36 Next port data:
37 * n.data_o: Shifted value
38 """
39 class PrevData:
40 def __init__(self, width):
41 self.data = Signal(width, name="p_data_i")
42 self.shift = Signal(width, name="p_shift_i")
43 self.dir = Signal(name="p_dir_i")
44 self.ctx = Dummy() # comply with CompALU API
45
46 def _get_data(self):
47 return [self.data, self.shift]
48
49 class NextData:
50 def __init__(self, width):
51 self.data = Signal(width, name="n_data_o")
52
53 def _get_data(self):
54 return [self.data]
55
56 class PrevPort:
57 def __init__(self, width):
58 self.data_i = Shifter.PrevData(width)
59 self.valid_i = Signal(name="p_valid_i")
60 self.ready_o = Signal(name="p_ready_o")
61
62 class NextPort:
63 def __init__(self, width):
64 self.data_o = Shifter.NextData(width)
65 self.valid_o = Signal(name="n_valid_o")
66 self.ready_i = Signal(name="n_ready_i")
67
68 def __init__(self, width):
69 self.width = width
70 self.p = self.PrevPort(width)
71 self.n = self.NextPort(width)
72
73 # more pieces to make this example class comply with the CompALU API
74 self.op = CompCROpSubset()
75 self.p.data_i.ctx.op = self.op
76 self.i = self.p.data_i._get_data()
77 self.out = self.n.data_o._get_data()
78
79 def elaborate(self, platform):
80 m = Module()
81 # TODO: Implement Module
82 return m
83
84 def __iter__(self):
85 yield self.p.data_i.data
86 yield self.p.data_i.shift
87 yield self.p.data_i.dir
88 yield self.p.valid_i
89 yield self.p.ready_o
90 yield self.n.ready_i
91 yield self.n.valid_o
92 yield self.n.data_o.data
93
94 def ports(self):
95 return list(self)
96
97
98 def test_shifter():
99 m = Module()
100 m.submodules.shf = dut = Shifter(8)
101 print("Shifter port names:")
102 for port in dut:
103 print("-", port.name)
104 sim = Simulator(m)
105 # Todo: Implement Simulation
106
107
108 if __name__ == "__main__":
109 test_shifter()