1 """Cascading Power ISA Decoder
3 This module uses CSV tables in a hierarchical/peer cascading fashion,
4 to create a multi-level instruction decoder by recognising appropriate
5 patterns. The output is a flattened (1-level) series of fields suitable
6 for a simple RISC engine.
8 This is based on Anton Blanchard's excellent microwatt work:
9 https://github.com/antonblanchard/microwatt/blob/master/decode1.vhdl
11 The basic principle is that the python code does the heavy lifting
12 (reading the CSV files, constructing the hierarchy), creating the HDL
13 AST with for-loops generating switch-case statements.
15 PowerDecoder takes a *list* of CSV files with an associated bit-range
16 that it is requested to match against the "opcode" row of the CSV file.
17 This pattern can be either an integer, a binary number, *or* a wildcard
18 nmigen Case pattern of the form "001--1-100".
20 Subdecoders are *additional* cases with further decoding. The "pattern"
21 argument is specified as one of the Case statements (a peer of the opcode
22 row in the CSV file), and thus further fields of the opcode may be decoded
23 giving increasing levels of detail.
27 [ (extra.csv: bit-fields entire 32-bit range
29 000000---------------01000000000 -> ILLEGAL instruction
30 01100000000000000000000000000000 -> SIM_CONFIG instruction
31 ................................ ->
33 (major.csv: first 6 bits ONLY
35 001100 -> ALU,OP_ADD (add)
36 001101 -> ALU,OP_ADD (another type of add)
40 001011 this must match *MAJOR*.CSV
41 [ (minor_19.csv: bits 21 through 30 inclusive:
43 0b0000000000 -> ALU,OP_MCRF
46 (minor_19_00000.csv: bits 21 through 25 inclusive:
48 0b00010 -> ALU,add_pcis
56 from nmigen
import Module
, Elaboratable
, Signal
57 from nmigen
.cli
import rtlil
58 from soc
.decoder
.power_enums
import (Function
, Form
, InternalOp
,
59 In1Sel
, In2Sel
, In3Sel
, OutSel
, RC
, LdstLen
,
60 CryIn
, get_csv
, single_bit_flags
,
61 get_signal_name
, default_values
)
62 from collections
import namedtuple
63 from soc
.decoder
.power_fields
import DecodeFields
64 from soc
.decoder
.power_fieldsn
import SigDecode
, SignalBitRange
66 Subdecoder
= namedtuple("Subdecoder", ["pattern", "opcodes", "opint",
67 "bitsel", "suffix", "subdecoders"])
71 """PowerOp: spec for execution. op type (ADD etc.) reg specs etc.
75 self
.function_unit
= Signal(Function
, reset_less
=True)
76 self
.internal_op
= Signal(InternalOp
, reset_less
=True)
77 self
.form
= Signal(Form
, reset_less
=True)
78 self
.in1_sel
= Signal(In1Sel
, reset_less
=True)
79 self
.in2_sel
= Signal(In2Sel
, reset_less
=True)
80 self
.in3_sel
= Signal(In3Sel
, reset_less
=True)
81 self
.out_sel
= Signal(OutSel
, reset_less
=True)
82 self
.ldst_len
= Signal(LdstLen
, reset_less
=True)
83 self
.rc_sel
= Signal(RC
, reset_less
=True)
84 self
.cry_in
= Signal(CryIn
, reset_less
=True)
85 for bit
in single_bit_flags
:
86 name
= get_signal_name(bit
)
87 setattr(self
, name
, Signal(reset_less
=True, name
=name
))
89 def _eq(self
, row
=None):
92 res
= [self
.function_unit
.eq(Function
[row
['unit']]),
93 self
.form
.eq(Form
[row
['form']]),
94 self
.internal_op
.eq(InternalOp
[row
['internal op']]),
95 self
.in1_sel
.eq(In1Sel
[row
['in1']]),
96 self
.in2_sel
.eq(In2Sel
[row
['in2']]),
97 self
.in3_sel
.eq(In3Sel
[row
['in3']]),
98 self
.out_sel
.eq(OutSel
[row
['out']]),
99 self
.ldst_len
.eq(LdstLen
[row
['ldst len']]),
100 self
.rc_sel
.eq(RC
[row
['rc']]),
101 self
.cry_in
.eq(CryIn
[row
['cry in']]),
103 for bit
in single_bit_flags
:
104 sig
= getattr(self
, get_signal_name(bit
))
105 res
.append(sig
.eq(int(row
.get(bit
, 0))))
108 def eq(self
, otherop
):
109 res
= [self
.function_unit
.eq(otherop
.function_unit
),
110 self
.form
.eq(otherop
.form
),
111 self
.internal_op
.eq(otherop
.internal_op
),
112 self
.in1_sel
.eq(otherop
.in1_sel
),
113 self
.in2_sel
.eq(otherop
.in2_sel
),
114 self
.in3_sel
.eq(otherop
.in3_sel
),
115 self
.out_sel
.eq(otherop
.out_sel
),
116 self
.rc_sel
.eq(otherop
.rc_sel
),
117 self
.ldst_len
.eq(otherop
.ldst_len
),
118 self
.cry_in
.eq(otherop
.cry_in
)]
119 for bit
in single_bit_flags
:
120 sig
= getattr(self
, get_signal_name(bit
))
121 res
.append(sig
.eq(getattr(otherop
, get_signal_name(bit
))))
125 regular
= [self
.function_unit
,
134 single_bit_ports
= [getattr(self
, get_signal_name(x
))
135 for x
in single_bit_flags
]
136 return regular
+ single_bit_ports
139 class PowerDecoder(Elaboratable
):
140 """PowerDecoder - decodes an incoming opcode into the type of operation
143 def __init__(self
, width
, dec
):
144 if not isinstance(dec
, list):
147 self
.opcode_in
= Signal(width
, reset_less
=True)
151 if d
.suffix
is not None and d
.suffix
>= width
:
155 def suffix_mask(self
, d
):
156 return ((1 << d
.suffix
) - 1)
158 def divide_opcodes(self
, d
):
160 mask
= self
.suffix_mask(d
)
161 print("mask", hex(mask
))
162 for row
in d
.opcodes
:
163 opcode
= row
['opcode']
164 if d
.opint
and '-' not in opcode
:
165 opcode
= int(opcode
, 0)
167 opcode
= opcode
>> d
.suffix
168 if key
not in divided
:
172 divided
[key
].append(r
)
175 def elaborate(self
, platform
):
179 # note: default opcode is "illegal" as this is a combinatorial block
181 # go through the list of CSV decoders first
183 opcode_switch
= Signal(d
.bitsel
[1] - d
.bitsel
[0],
185 comb
+= opcode_switch
.eq(self
.opcode_in
[d
.bitsel
[0]:d
.bitsel
[1]])
187 opcodes
= self
.divide_opcodes(d
)
188 opc_in
= Signal(d
.suffix
, reset_less
=True)
189 comb
+= opc_in
.eq(opcode_switch
[:d
.suffix
])
190 with m
.Switch(opc_in
):
191 for key
, row
in opcodes
.items():
192 bitsel
= (d
.suffix
+d
.bitsel
[0], d
.bitsel
[1])
193 sd
= Subdecoder(pattern
=None, opcodes
=row
,
194 bitsel
=bitsel
, suffix
=None,
195 opint
=False, subdecoders
=[])
196 subdecoder
= PowerDecoder(width
=32, dec
=sd
)
197 setattr(m
.submodules
, "dec_sub%d" % key
, subdecoder
)
198 comb
+= subdecoder
.opcode_in
.eq(self
.opcode_in
)
200 comb
+= self
.op
.eq(subdecoder
.op
)
202 # TODO: arguments, here (all of them) need to be a list.
203 # a for-loop around the *list* of decoder args.
204 with m
.Switch(opcode_switch
):
205 self
.handle_subdecoders(m
, d
)
206 for row
in d
.opcodes
:
207 opcode
= row
['opcode']
208 if d
.opint
and '-' not in opcode
:
209 opcode
= int(opcode
, 0)
213 comb
+= self
.op
._eq
(row
)
216 def handle_subdecoders(self
, m
, d
):
217 for dec
in d
.subdecoders
:
218 subdecoder
= PowerDecoder(self
.width
, dec
)
219 if isinstance(dec
, list): # XXX HACK: take first pattern
221 setattr(m
.submodules
, "dec%d" % dec
.pattern
, subdecoder
)
222 m
.d
.comb
+= subdecoder
.opcode_in
.eq(self
.opcode_in
)
223 with m
.Case(dec
.pattern
):
224 m
.d
.comb
+= self
.op
.eq(subdecoder
.op
)
227 return [self
.opcode_in
] + self
.op
.ports()
230 class TopPowerDecoder(PowerDecoder
, DecodeFields
):
232 def __init__(self
, width
, dec
):
233 PowerDecoder
.__init
__(self
, width
, dec
)
234 DecodeFields
.__init
__(self
, SignalBitRange
, [self
.opcode_in
])
238 def create_pdecode():
240 # minor 19 has extra patterns
242 m19
.append(Subdecoder(pattern
=19, opcodes
=get_csv("minor_19.csv"),
243 opint
=True, bitsel
=(1, 11), suffix
=None, subdecoders
=[]))
244 m19
.append(Subdecoder(pattern
=19, opcodes
=get_csv("minor_19_00000.csv"),
245 opint
=True, bitsel
=(1, 6), suffix
=None, subdecoders
=[]))
250 Subdecoder(pattern
=30, opcodes
=get_csv("minor_30.csv"),
251 opint
=True, bitsel
=(1, 6), suffix
=None, subdecoders
=[]),
252 Subdecoder(pattern
=31, opcodes
=get_csv("minor_31.csv"),
253 opint
=True, bitsel
=(1, 11), suffix
=0b00101, subdecoders
=[]),
254 Subdecoder(pattern
=58, opcodes
=get_csv("minor_58.csv"),
255 opint
=True, bitsel
=(0, 2), suffix
=None, subdecoders
=[]),
256 Subdecoder(pattern
=62, opcodes
=get_csv("minor_62.csv"),
257 opint
=True, bitsel
=(0, 2), suffix
=None, subdecoders
=[]),
260 # top level: extra merged with major
262 opcodes
= get_csv("major.csv")
263 dec
.append(Subdecoder(pattern
=None, opint
=True, opcodes
=opcodes
,
264 bitsel
=(26, 32), suffix
=None, subdecoders
=pminor
))
265 opcodes
= get_csv("extra.csv")
266 dec
.append(Subdecoder(pattern
=None, opint
=False, opcodes
=opcodes
,
267 bitsel
=(0, 32), suffix
=None, subdecoders
=[]))
269 return TopPowerDecoder(32, dec
)
272 if __name__
== '__main__':
273 pdecode
= create_pdecode()
274 vl
= rtlil
.convert(pdecode
, ports
=pdecode
.ports())
275 with
open("decoder.il", "w") as f
: