Add recursive decoding
[soc.git] / src / decoder / power_decoder.py
1 from nmigen import Module, Elaboratable, Signal
2 from power_enums import (Function, InternalOp, In1Sel, In2Sel, In3Sel,
3 OutSel, RC, LdstLen, CryIn, get_csv, single_bit_flags,
4 get_signal_name)
5
6
7 class PowerOp:
8 """PowerOp: spec for execution. op type (ADD etc.) reg specs etc.
9 """
10
11 def __init__(self):
12 self.function_unit = Signal(Function, reset_less=True)
13 self.internal_op = Signal(InternalOp, reset_less=True)
14 self.in1_sel = Signal(In1Sel, reset_less=True)
15 self.in2_sel = Signal(In2Sel, reset_less=True)
16 self.in3_sel = Signal(In3Sel, reset_less=True)
17 self.out_sel = Signal(OutSel, reset_less=True)
18 self.ldst_len = Signal(LdstLen, reset_less=True)
19 self.rc_sel = Signal(RC, reset_less=True)
20 self.cry_in = Signal(CryIn, reset_less=True)
21 for bit in single_bit_flags:
22 name = get_signal_name(bit)
23 setattr(self, name, Signal(reset_less=True, name=name))
24
25 def _eq(self, row=None):
26 if row is None:
27 row = {'unit': "NONE", 'internal op': "OP_ILLEGAL",
28 'in1': "RA", 'in2': 'NONE', 'in3': 'NONE', 'out': 'NONE',
29 'ldst len': 'NONE',
30 'rc' : 'NONE', 'cry in' : 'ZERO'}
31 res = [self.function_unit.eq(Function[row['unit']]),
32 self.internal_op.eq(InternalOp[row['internal op']]),
33 self.in1_sel.eq(In1Sel[row['in1']]),
34 self.in2_sel.eq(In2Sel[row['in2']]),
35 self.in3_sel.eq(In3Sel[row['in3']]),
36 self.out_sel.eq(OutSel[row['out']]),
37 self.ldst_len.eq(LdstLen[row['ldst len']]),
38 self.rc_sel.eq(RC[row['rc']]),
39 self.cry_in.eq(CryIn[row['cry in']]),
40 ]
41 for bit in single_bit_flags:
42 sig = getattr(self, get_signal_name(bit))
43 res.append(sig.eq(int(row.get(bit, 0))))
44 return res
45
46 def eq(self, otherop):
47 res = [self.function_unit.eq(otherop.function_unit),
48 self.internal_op.eq(otherop.internal_op),
49 self.in1_sel.eq(otherop.in1_sel),
50 self.in2_sel.eq(otherop.in2_sel),
51 self.in3_sel.eq(otherop.in3_sel),
52 self.out_sel.eq(otherop.out_sel),
53 self.rc_sel.eq(otherop.rc_sel),
54 self.ldst_len.eq(otherop.ldst_len),
55 self.cry_in.eq(otherop.cry_in)]
56 for bit in single_bit_flags:
57 sig = getattr(self, get_signal_name(bit))
58 res.append(sig.eq(getattr(otherop, get_signal_name(bit))))
59 return res
60
61 def ports(self):
62 regular = [self.function_unit,
63 self.in1_sel,
64 self.in2_sel,
65 self.in3_sel,
66 self.out_sel,
67 self.ldst_len,
68 self.rc_sel,
69 self.internal_op]
70 single_bit_ports = [getattr(self, get_signal_name(x))
71 for x in single_bit_flags]
72 return regular + single_bit_ports
73
74
75 class PowerDecoder(Elaboratable):
76 """PowerDecoder - decodes an incoming opcode into the type of operation
77 """
78
79 def __init__(self, width, opcodes, opint=True, suffix=None):
80 self.opint = opint # true if the opcode needs to be converted to int
81 self.opcodes = opcodes
82 self.opcode_in = Signal(width, reset_less=True)
83
84 self.op = PowerOp()
85 self.suffix = suffix
86 if suffix[1] - suffix[0] >= width:
87 self.suffix = None
88 self.width = width
89
90 def suffix_mask(self):
91 return ((1 << self.suffix[1]) - 1) - ((1 << self.suffix[0]) - 1)
92
93 def divide_opcodes(self):
94 divided = {}
95 mask = self.suffix_mask()
96 for row in self.opcodes:
97 opcode = row['opcode']
98 if self.opint:
99 opcode = int(opcode, 0)
100 key = opcode & mask >> (self.suffix[0])
101 opcode = opcode >> self.suffix[1]
102 if key not in divided:
103 divided[key] = []
104 r = row.copy()
105 r['opcode'] = opcode
106 divided[key].append(r)
107 return divided
108
109 def elaborate(self, platform):
110 m = Module()
111 comb = m.d.comb
112
113 if self.suffix:
114 opcodes = self.divide_opcodes()
115 opc_in = Signal(self.suffix[1] - self.suffix[0], reset_less=True)
116 comb += opc_in.eq(self.opcode_in[self.suffix[0]:self.suffix[1]])
117 with m.Switch(opc_in):
118 for key, row in opcodes.items():
119 subdecoder = PowerDecoder(width=self.width - opc_in.width,
120 opcodes=row,
121 opint=False,
122 suffix=self.suffix)
123 setattr(m.submodules, "dec%d" % key, subdecoder)
124 comb += subdecoder.opcode_in.eq(self.opcode_in[self.suffix[1]:])
125 with m.Case(key):
126 comb += self.op.eq(subdecoder.op)
127
128 else:
129 with m.Switch(self.opcode_in):
130 for row in self.opcodes:
131 opcode = row['opcode']
132 if self.opint:
133 opcode = int(opcode, 0)
134 if not row['unit']:
135 continue
136 with m.Case(opcode):
137 comb += self.op._eq(row)
138 with m.Default():
139 comb += self.op._eq(None)
140 return m
141
142 def ports(self):
143 return [self.opcode_in] + self.op.ports()
144
145 # how about this?
146 # if False:
147 # pminor = (0, 6, [(19, "minor_19", (1,11)), # pass to 'splitter' function
148 # (30, "minor_30", (1,4)),
149 # (31, "minor_31", (1,11)), # pass to 'splitter' function
150 # (58, "minor_58", (0,1)),
151 # (62, "minor_62", (0,1)),
152 # ]
153
154 # pdecode = PowerDecoder(6, "major", subcoders = pminor)