more cpu decode conversion
[rv32.git] / cpu_decoder.py
1 """
2 /*
3 * Copyright 2018 Jacob Lifshay
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 */
24 `timescale 1ns / 100ps
25 """
26 from migen import *
27 from migen.fhdl import verilog
28
29 from riscvdefs import *
30 from cpudefs import *
31
32 class CPUDecoder(Module):
33
34 def __init__(self):
35 self.instruction = Signal(32)
36 self.funct7 = Signal(7)
37 self.funct3 = Signal(3)
38 self.rd = Signal(5)
39 self.rs1 = Signal(5)
40 self.rs2 = Signal(5)
41 self.immediate = Signal(32)
42 self.opcode = Signal(7)
43 self.decode_action = Signal(decode_action)
44
45 # decode bits of instruction
46 self.comb += self.funct7.eq(self.instruction[25:32])
47 self.comb += self.funct3.eq(self.instruction[12:15])
48 self.comb += self.rd.eq (self.instruction[7:12])
49 self.comb += self.rs1.eq (self.instruction[15:20])
50 self.comb += self.rs2.eq (self.instruction[20:25])
51 self.comb += self.opcode.eq(self.instruction[0:7])
52
53 # add combinatorial decode opcode case statements for immed and action
54 self.comb += self.calculate_immediate()
55 self.comb += self.calculate_action()
56
57 def calculate_immediate(self):
58 """ calculate immediate
59 """
60 ci = {}
61 no_imm = 0x0
62
63 # R-type: no immediate
64 for op in [opcode_amo, opcode_op, opcode_op_32, opcode_op_fp]:
65 ci[op] = self.immediate.eq(no_imm)
66
67 # I-type
68 im = Cat(self.instruction[20:], Replicate(self.instruction[31], 20))
69 for op in [opcode_load, opcode_load_fp, opcode_misc_mem,
70 opcode_op_imm, opcode_op_imm_32, opcode_jalr,
71 opcode_system]:
72 ci[op] = self.immediate.eq(im)
73
74 # S-type
75 im = Cat(self.instruction[7:12], self.instruction[25:31],
76 Replicate(self.instruction[31], 21))
77 for op in [opcode_store, opcode_store_fp]:
78 ci[op] = self.immediate.eq(im)
79
80 # B-type
81 im = Cat(Constant(0, 1),
82 self.instruction[8:12], self.instruction[25:31],
83 self.instruction[7], Replicate(self.instruction[31], 20))
84 for op in [opcode_branch, ]:
85 ci[op] = self.immediate.eq(im)
86
87 # U-type
88 im = Cat(Constant(0, 1), self.instruction[12:], )
89 for op in [opcode_auipc, opcode_lui]:
90 ci[op] = self.immediate.eq(im)
91
92 # J-type
93 im = Cat(Constant(0, 1),
94 self.instruction[21:25], self.instruction[25:31],
95 self.instruction[20], self.instruction[12:20],
96 Replicate(self.instruction[31], 12))
97 for op in [opcode_jal, ]:
98 ci[op] = self.immediate.eq(im)
99
100 # R4-type: no immediate
101 for op in [opcode_madd, opcode_msub, opcode_nmsub, opcode_nmadd]:
102 ci[op] = self.immediate.eq(no_imm)
103
104 # unknown
105 for op in [ opcode_custom_0, opcode_48b_escape_0, opcode_custom_1,
106 opcode_64b_escape, opcode_reserved_10101, opcode_rv128_0,
107 opcode_48b_escape_1, opcode_reserved_11010,
108 opcode_reserved_11101, opcode_rv128_1, opcode_80b_escape]:
109 ci[op] = self.immediate.eq(no_imm)
110
111 # default
112 for op in [ "default", ]:
113 ci[op] = self.immediate.eq(no_imm)
114
115 return Case(self.opcode, ci)
116
117 def _decode_funct3(self, options, action):
118 """ decode by list of cases
119 """
120 c = {}
121 # load opcode
122 for op in options:
123 c[op] = self.decode_action.eq(action)
124 # default
125 c["default"] = \
126 self.decode_action.eq(decode_action_trap_illegal_instruction)
127
128 return Case(self.funct3, c)
129
130 def calculate_store_action(self):
131 """ decode store action
132 """
133 return self._decode_funct3([ funct3_sb, funct3_sh, funct3_sw, ],
134 decode_action_store)
135
136 def calculate_load_action(self):
137 """ decode load action
138 """
139 return self._decode_funct3([ funct3_lb, funct3_lbu, funct3_lh,
140 funct3_lhu, funct3_lw, ],
141 decode_action_load)
142
143 def calculate_branch_action(self):
144 """ decode branch action
145 """
146 return self._decode_funct3([ funct3_beq, funct3_bne, funct3_blt,
147 funct3_bge, funct3_bltu, funct3_bgeu ],
148 decode_action_branch)
149
150 def calculate_jalr_action(self):
151 """ decode jalr action
152 """
153 return self._decode_funct3([ funct3_jalr, ],
154 decode_action_jalr)
155
156 def calculate_op_action(self):
157 """ decode op action
158 """
159 c = {}
160 immz = Constant(0, 12)
161 regz = Constant(0, 5)
162 # fence
163 c[funct3_slli] = \
164 If((self.funct7 == Constant(0, 7)),
165 self.decode_action.eq(decode_action_op_op_imm)).\
166 Else(
167 self.decode_action.eq(decode_action_trap_illegal_instruction))
168 # fence.i
169 c[funct3_srli_srai] = \
170 If((self.funct7 == Constant(0, 7) | \
171 (self.funct7 == Constant(0x20, 7))),
172 self.decode_action.eq(decode_action_op_op_imm)).\
173 Else(
174 self.decode_action.eq(decode_action_trap_illegal_instruction))
175 # default
176 c["default"] = \
177 self.decode_action.eq(decode_action_op_op_imm)
178
179 return Case(self.funct3, c)
180
181 def calculate_misc_action(self):
182 """ decode misc mem action
183 """
184 c = {}
185 immz = Constant(0, 12)
186 regz = Constant(0, 5)
187 # fence
188 c[funct3_fence] = \
189 If((self.immediate[8:12] == immz) & (self.rs1 == regz) & \
190 (self.rd == regz),
191 self.decode_action.eq(decode_action_fence)).\
192 Else(
193 self.decode_action.eq(decode_action_trap_illegal_instruction))
194 # fence.i
195 c[funct3_fence_i] = \
196 If((self.immediate[0:12] == immz) & (self.rs1 == regz) & \
197 (self.rd == regz),
198 self.decode_action.eq(decode_action_fence_i)).\
199 Else(
200 self.decode_action.eq(decode_action_trap_illegal_instruction))
201 # default
202 c["default"] = \
203 self.decode_action.eq(decode_action_trap_illegal_instruction)
204
205 return Case(self.funct3, c)
206
207 def calculate_action(self):
208 """ calculate action
209 """
210 c = {}
211 # load opcode
212 c[opcode_load] = self.calculate_load_action()
213 c[opcode_misc_mem] = self.calculate_misc_action()
214 c[opcode_op_imm] = self.calculate_op_action()
215 c[opcode_op] = self.calculate_op_action()
216 c[opcode_lui] = self.decode_action.eq(decode_action_lui_auipc)
217 c[opcode_auipc] = self.decode_action.eq(decode_action_lui_auipc)
218 c[opcode_store] = self.calculate_store_action()
219 c[opcode_branch] = self.calculate_branch_action()
220 c[opcode_jalr] = self.calculate_jalr_action()
221 c[opcode_jal] = self.decode_action.eq(decode_action_jal)
222
223 return Case(self.opcode, c)
224
225 """
226
227 function `decode_action calculate_action(
228 input [6:0] funct7,
229 input [2:0] funct3,
230 input [4:0] rd,
231 input [4:0] rs1,
232 input [4:0] rs2,
233 input [31:0] immediate,
234 input [6:0] opcode);
235 begin
236 case(opcode)
237 `opcode_system: begin
238 case(funct3)
239 `funct3_ecall_ebreak:
240 if((rs1 != 0) | (rd != 0) | ((immediate & ~32'b1) != 0))
241 calculate_action = `decode_action_trap_illegal_instruction;
242 else
243 calculate_action = `decode_action_trap_ecall_ebreak;
244 `funct3_csrrw,
245 `funct3_csrrs,
246 `funct3_csrrc,
247 `funct3_csrrwi,
248 `funct3_csrrsi,
249 `funct3_csrrci:
250 calculate_action = `decode_action_csr;
251 default:
252 calculate_action = `decode_action_trap_illegal_instruction;
253 endcase
254 end
255 `opcode_load_fp,
256 `opcode_custom_0,
257 `opcode_op_imm_32,
258 `opcode_48b_escape_0,
259 `opcode_store_fp,
260 `opcode_custom_1,
261 `opcode_amo,
262 `opcode_op_32,
263 `opcode_64b_escape,
264 `opcode_madd,
265 `opcode_msub,
266 `opcode_nmsub,
267 `opcode_nmadd,
268 `opcode_op_fp,
269 `opcode_reserved_10101,
270 `opcode_rv128_0,
271 `opcode_48b_escape_1,
272 `opcode_reserved_11010,
273 `opcode_reserved_11101,
274 `opcode_rv128_1,
275 `opcode_80b_escape: begin
276 calculate_action = `decode_action_trap_illegal_instruction;
277 end
278 default:
279 calculate_action = `decode_action_trap_illegal_instruction;
280 endcase
281 end
282 endfunction
283
284 assign decode_action = calculate_action(funct7,
285 funct3,
286 rd,
287 rs1,
288 rs2,
289 immediate,
290 opcode);
291
292 endmodule
293 """
294
295
296 if __name__ == "__main__":
297 example = CPUDecoder()
298 print(verilog.convert(example,
299 {
300 example.instruction,
301 example.funct7,
302 example.funct3,
303 example.rd,
304 example.rs1,
305 example.rs2,
306 example.immediate,
307 example.opcode,
308 example.decode_action,
309 }))