a2699a9185c2f9841dfb59b2c0170c479b3ed05d
[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, default_values)
5 from collections import namedtuple
6
7 Subdecoder = namedtuple("Subdecoder", ["pattern", "csv", "opint", "bitsel"])
8
9
10 class PowerOp:
11 """PowerOp: spec for execution. op type (ADD etc.) reg specs etc.
12 """
13
14 def __init__(self):
15 self.function_unit = Signal(Function, reset_less=True)
16 self.internal_op = Signal(InternalOp, reset_less=True)
17 self.in1_sel = Signal(In1Sel, reset_less=True)
18 self.in2_sel = Signal(In2Sel, reset_less=True)
19 self.in3_sel = Signal(In3Sel, reset_less=True)
20 self.out_sel = Signal(OutSel, reset_less=True)
21 self.ldst_len = Signal(LdstLen, reset_less=True)
22 self.rc_sel = Signal(RC, reset_less=True)
23 self.cry_in = Signal(CryIn, reset_less=True)
24 for bit in single_bit_flags:
25 name = get_signal_name(bit)
26 setattr(self, name, Signal(reset_less=True, name=name))
27
28 def _eq(self, row=None):
29 if row is None:
30 row = default_values
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, *,
80 bitsel, subdecoders=[],
81 opint=True,
82 suffix=None):
83 self.opint = opint # true if the opcode needs to be converted to int
84 self.opcodes = opcodes
85 self.opcode_in = Signal(width, reset_less=True)
86
87 self.op = PowerOp()
88 self.suffix = suffix
89 if suffix is not None and suffix[1] - suffix[0] >= width:
90 self.suffix = None
91 self.bitsel = bitsel
92 self.subdecoders = subdecoders
93 self.width = width
94
95 def suffix_mask(self):
96 return ((1 << self.suffix[1]) - 1) - ((1 << self.suffix[0]) - 1)
97
98 def divide_opcodes(self):
99 divided = {}
100 mask = self.suffix_mask()
101 print ("mask", hex(mask))
102 for row in self.opcodes:
103 opcode = row['opcode']
104 if self.opint and '-' not in opcode:
105 opcode = int(opcode, 0)
106 key = opcode & mask >> (self.suffix[0])
107 opcode = opcode >> self.suffix[1]
108 if key not in divided:
109 divided[key] = []
110 r = row.copy()
111 r['opcode'] = opcode
112 divided[key].append(r)
113 return divided
114
115 def elaborate(self, platform):
116 m = Module()
117 comb = m.d.comb
118
119 # if self.suffix:
120 # opcodes = self.divide_opcodes()
121 # opc_in = Signal(self.suffix[1] - self.suffix[0], reset_less=True)
122 # comb += opc_in.eq(self.opcode_in[self.suffix[0]:self.suffix[1]])
123 # with m.Switch(opc_in):
124 # for key, row in opcodes.items():
125 # subdecoder = PowerDecoder(width=self.width - opc_in.width,
126 # opcodes=row,
127 # opint=False,
128 # suffix=self.suffix)
129 # setattr(m.submodules, "dec%d" % key, subdecoder)
130 # comb += subdecoder.opcode_in.eq(self.opcode_in[self.suffix[1]:])
131 # with m.Case(key):
132 # comb += self.op.eq(subdecoder.op)
133
134 # else:
135 opcode_switch = Signal(self.bitsel[1] - self.bitsel[0], reset_less=True)
136 comb += opcode_switch.eq(self.opcode_in[self.bitsel[0]:self.bitsel[1]])
137 with m.Switch(opcode_switch):
138 self.handle_subdecoders(m)
139 for row in self.opcodes:
140 opcode = row['opcode']
141 if self.opint and '-' not in opcode:
142 opcode = int(opcode, 0)
143 if not row['unit']:
144 continue
145 with m.Case(opcode):
146 comb += self.op._eq(row)
147 with m.Default():
148 comb += self.op._eq(None)
149 return m
150
151 def handle_subdecoders(self, m):
152 for dec in self.subdecoders:
153 subdecoder = PowerDecoder(width=self.width,
154 opcodes=dec.csv,
155 opint=dec.opint,
156 bitsel=dec.bitsel)
157
158 setattr(m.submodules, "dec%d" % dec.pattern, subdecoder)
159 m.d.comb += subdecoder.opcode_in.eq(self.opcode_in)
160 with m.Case(dec.pattern):
161 m.d.comb += self.op.eq(subdecoder.op)
162
163 def ports(self):
164 return [self.opcode_in] + self.op.ports()
165
166
167 pminor = [
168 Subdecoder(pattern=19, csv=get_csv("minor_19.csv"),
169 opint=True, bitsel=(1, 11)),
170 Subdecoder(pattern=30, csv=get_csv("minor_30.csv"),
171 opint=True, bitsel=(1, 5)),
172 Subdecoder(pattern=31, csv=get_csv("minor_31.csv"),
173 opint=True, bitsel=(1, 11)),
174 Subdecoder(pattern=58, csv=get_csv("minor_58.csv"),
175 opint=True, bitsel=(0, 2)),
176 Subdecoder(pattern=62, csv=get_csv("minor_62.csv"),
177 opint=True, bitsel=(0, 2)),
178 ]
179
180 opcodes = get_csv("major.csv")
181 pdecode = PowerDecoder(32, opcodes, bitsel=(26, 32), subdecoders=pminor)