add cpu decode cases
[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 def calculate_immediate(instruction, immediate):
33 """ calculate immediate
34 """
35 ci = {}
36 no_imm = 0x0
37
38 # R-type: no immediate
39 for op in [opcode_amo, opcode_op, opcode_op_32, opcode_op_fp]:
40 ci[op] = immediate.eq(no_imm)
41
42 # I-type
43 im = Cat(instruction[20:], Replicate(instruction[31], 20))
44 for op in [opcode_load, opcode_load_fp, opcode_misc_mem,
45 opcode_op_imm, opcode_op_imm_32, opcode_jalr,
46 opcode_system]:
47 ci[op] = immediate.eq(im)
48
49 # S-type
50 im = Cat(instruction[7:12], instruction[25:31],
51 Replicate(instruction[31], 21))
52 for op in [opcode_store, opcode_store_fp]:
53 ci[op] = immediate.eq(im)
54
55 # B-type
56 im = Cat(Constant(0, 1),
57 instruction[8:12], instruction[25:31],
58 instruction[7], Replicate(instruction[31], 20))
59 for op in [opcode_branch, ]:
60 ci[op] = immediate.eq(im)
61
62 # U-type
63 im = Cat(Constant(0, 1), instruction[12:], )
64 for op in [opcode_auipc, opcode_lui]:
65 ci[op] = immediate.eq(im)
66
67 # J-type
68 im = Cat(Constant(0, 1),
69 instruction[21:25], instruction[25:31],
70 instruction[20], instruction[12:20],
71 Replicate(instruction[31], 12))
72 for op in [opcode_jal, ]:
73 ci[op] = immediate.eq(im)
74
75 # R4-type: no immediate
76 for op in [opcode_madd, opcode_msub, opcode_nmsub, opcode_nmadd]:
77 ci[op] = immediate.eq(no_imm)
78
79 # unknown
80 for op in [ opcode_custom_0, opcode_48b_escape_0, opcode_custom_1,
81 opcode_64b_escape, opcode_reserved_10101, opcode_rv128_0,
82 opcode_48b_escape_1, opcode_reserved_11010,
83 opcode_reserved_11101, opcode_rv128_1, opcode_80b_escape]:
84 ci[op] = immediate.eq(no_imm)
85
86 # default
87 for op in [ "default", ]:
88 ci[op] = immediate.eq(no_imm)
89
90 return ci
91
92 class CPUDecoder(Module):
93
94 def __init__(self):
95 self.instruction = Signal(32)
96 self.funct7 = Signal(7)
97 self.funct3 = Signal(3)
98 self.rd = Signal(5)
99 self.rs1 = Signal(5)
100 self.rs2 = Signal(5)
101 self.immediate = Signal(32)
102 self.opcode = Signal(7)
103 self.decode_action = Signal(decode_action)
104
105 self.comb += self.funct7.eq(self.instruction[25:32])
106 self.comb += self.funct3.eq(self.instruction[12:15])
107 self.comb += self.rd.eq(self.instruction[7:12])
108 self.comb += self.rs1.eq(self.instruction[15:20])
109 self.comb += self.rs2.eq(self.instruction[20:25])
110 self.comb += self.opcode.eq(self.instruction[0:7])
111
112 # add combinatorial decode opcode case statement
113 ci = calculate_immediate(self.instruction, self.immediate)
114 self.comb += Case(self.opcode, ci)
115
116 self.comb += self.calculate_action()
117
118 def calculate_store_action(self):
119 """ decode store action
120 """
121 c = {}
122 # load opcode
123 for op in [ funct3_sb, funct3_sh, funct3_sw, ]:
124 c[op] = self.decode_action.eq(decode_action_store)
125 # default
126 c["default"] = \
127 self.decode_action.eq(decode_action_trap_illegal_instruction)
128
129 return Case(self.funct3, c)
130
131 def calculate_load_action(self):
132 """ decode load action
133 """
134 c = {}
135 # load opcode
136 for op in [ funct3_lb, funct3_lbu, funct3_lh, funct3_lhu, funct3_lw, ]:
137 c[op] = self.decode_action.eq(decode_action_load)
138 # default
139 c["default"] = \
140 self.decode_action.eq(decode_action_trap_illegal_instruction)
141
142 return Case(self.funct3, c)
143
144 def calculate_op_action(self):
145 """ decode op action
146 """
147 c = {}
148 immz = Constant(0, 12)
149 regz = Constant(0, 5)
150 # fence
151 c[funct3_slli] = \
152 If((self.funct7 == Constant(0, 7)),
153 self.decode_action.eq(decode_action_op_op_imm)).\
154 Else(
155 self.decode_action.eq(decode_action_trap_illegal_instruction))
156 # fence.i
157 c[funct3_srli_srai] = \
158 If((self.funct7 == Constant(0, 7) | \
159 (self.funct7 == Constant(0x20, 7))),
160 self.decode_action.eq(decode_action_op_op_imm)).\
161 Else(
162 self.decode_action.eq(decode_action_trap_illegal_instruction))
163 # default
164 c["default"] = \
165 self.decode_action.eq(decode_action_op_op_imm)
166
167 return Case(self.funct3, c)
168
169 def calculate_misc_action(self):
170 """ decode misc mem action
171 """
172 c = {}
173 immz = Constant(0, 12)
174 regz = Constant(0, 5)
175 # fence
176 c[funct3_fence] = \
177 If((self.immediate[8:12] == immz) & (self.rs1 == regz) & \
178 (self.rd == regz),
179 self.decode_action.eq(decode_action_fence)).\
180 Else(
181 self.decode_action.eq(decode_action_trap_illegal_instruction))
182 # fence.i
183 c[funct3_fence_i] = \
184 If((self.immediate[0:12] == immz) & (self.rs1 == regz) & \
185 (self.rd == regz),
186 self.decode_action.eq(decode_action_fence_i)).\
187 Else(
188 self.decode_action.eq(decode_action_trap_illegal_instruction))
189 # default
190 c["default"] = \
191 self.decode_action.eq(decode_action_trap_illegal_instruction)
192
193 return Case(self.funct3, c)
194
195 def calculate_action(self):
196 """ calculate action
197 """
198 c = {}
199 # load opcode
200 c[opcode_load] = self.calculate_load_action()
201 c[opcode_misc_mem] = self.calculate_misc_action()
202 c[opcode_op_imm] = self.calculate_op_action()
203 c[opcode_op] = self.calculate_op_action()
204 c[opcode_lui] = self.decode_action.eq(decode_action_lui_auipc)
205 c[opcode_auipc] = self.decode_action.eq(decode_action_lui_auipc)
206 c[opcode_store] = self.calculate_store_action()
207
208 return Case(self.opcode, c)
209
210 """
211
212 function `decode_action calculate_action(
213 input [6:0] funct7,
214 input [2:0] funct3,
215 input [4:0] rd,
216 input [4:0] rs1,
217 input [4:0] rs2,
218 input [31:0] immediate,
219 input [6:0] opcode);
220 begin
221 case(opcode)
222 `opcode_branch: begin
223 case(funct3)
224 `funct3_beq,
225 `funct3_bne,
226 `funct3_blt,
227 `funct3_bge,
228 `funct3_bltu,
229 `funct3_bgeu:
230 calculate_action = `decode_action_branch;
231 default:
232 calculate_action = `decode_action_trap_illegal_instruction;
233 endcase
234 end
235 `opcode_jalr: begin
236 if(funct3 == `funct3_jalr)
237 calculate_action = `decode_action_jalr;
238 else
239 calculate_action = `decode_action_trap_illegal_instruction;
240 end
241 `opcode_jal: begin
242 calculate_action = `decode_action_jal;
243 end
244 `opcode_system: begin
245 case(funct3)
246 `funct3_ecall_ebreak:
247 if((rs1 != 0) | (rd != 0) | ((immediate & ~32'b1) != 0))
248 calculate_action = `decode_action_trap_illegal_instruction;
249 else
250 calculate_action = `decode_action_trap_ecall_ebreak;
251 `funct3_csrrw,
252 `funct3_csrrs,
253 `funct3_csrrc,
254 `funct3_csrrwi,
255 `funct3_csrrsi,
256 `funct3_csrrci:
257 calculate_action = `decode_action_csr;
258 default:
259 calculate_action = `decode_action_trap_illegal_instruction;
260 endcase
261 end
262 `opcode_load_fp,
263 `opcode_custom_0,
264 `opcode_op_imm_32,
265 `opcode_48b_escape_0,
266 `opcode_store_fp,
267 `opcode_custom_1,
268 `opcode_amo,
269 `opcode_op_32,
270 `opcode_64b_escape,
271 `opcode_madd,
272 `opcode_msub,
273 `opcode_nmsub,
274 `opcode_nmadd,
275 `opcode_op_fp,
276 `opcode_reserved_10101,
277 `opcode_rv128_0,
278 `opcode_48b_escape_1,
279 `opcode_reserved_11010,
280 `opcode_reserved_11101,
281 `opcode_rv128_1,
282 `opcode_80b_escape: begin
283 calculate_action = `decode_action_trap_illegal_instruction;
284 end
285 default:
286 calculate_action = `decode_action_trap_illegal_instruction;
287 endcase
288 end
289 endfunction
290
291 assign decode_action = calculate_action(funct7,
292 funct3,
293 rd,
294 rs1,
295 rs2,
296 immediate,
297 opcode);
298
299 endmodule
300 """
301
302
303 if __name__ == "__main__":
304 example = CPUDecoder()
305 print(verilog.convert(example,
306 {
307 example.instruction,
308 example.funct7,
309 example.funct3,
310 example.rd,
311 example.rs1,
312 example.rs2,
313 example.immediate,
314 example.opcode,
315 example.decode_action,
316 }))