3 * Copyright 2018 Jacob Lifshay
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:
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
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
24 `timescale 1ns / 100ps
27 from migen
.fhdl
import verilog
29 from riscvdefs
import *
32 class CPUDecoder(Module
):
35 self
.instruction
= Signal(32)
36 self
.funct7
= Signal(7)
37 self
.funct3
= Signal(3)
41 self
.immediate
= Signal(32)
42 self
.opcode
= Signal(7)
43 self
.decode_action
= Signal(decode_action
)
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])
53 # add combinatorial decode opcode case statements for immed and action
54 self
.comb
+= self
.calculate_immediate()
55 self
.comb
+= self
.calculate_action()
57 def calculate_immediate(self
):
58 """ calculate immediate
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
)
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
,
72 ci
[op
] = self
.immediate
.eq(im
)
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
)
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
)
88 im
= Cat(Constant(0, 1), self
.instruction
[12:], )
89 for op
in [opcode_auipc
, opcode_lui
]:
90 ci
[op
] = self
.immediate
.eq(im
)
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
)
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
)
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
)
112 for op
in [ "default", ]:
113 ci
[op
] = self
.immediate
.eq(no_imm
)
115 return Case(self
.opcode
, ci
)
117 def _decode_funct3(self
, options
, action
):
118 """ decode by list of cases
123 c
[op
] = self
.decode_action
.eq(action
)
126 self
.decode_action
.eq(decode_action_trap_illegal_instruction
)
128 return Case(self
.funct3
, c
)
130 def calculate_store_action(self
):
131 """ decode store action
133 return self
._decode
_funct
3([ funct3_sb
, funct3_sh
, funct3_sw
, ],
136 def calculate_load_action(self
):
137 """ decode load action
139 return self
._decode
_funct
3([ funct3_lb
, funct3_lbu
, funct3_lh
,
140 funct3_lhu
, funct3_lw
, ],
143 def calculate_branch_action(self
):
144 """ decode branch action
146 return self
._decode
_funct
3([ funct3_beq
, funct3_bne
, funct3_blt
,
147 funct3_bge
, funct3_bltu
, funct3_bgeu
],
148 decode_action_branch
)
150 def calculate_jalr_action(self
):
151 """ decode jalr action
153 return self
._decode
_funct
3([ funct3_jalr
, ],
156 def calculate_op_action(self
):
160 immz
= Constant(0, 12)
161 regz
= Constant(0, 5)
164 If((self
.funct7
== Constant(0, 7)),
165 self
.decode_action
.eq(decode_action_op_op_imm
)).\
167 self
.decode_action
.eq(decode_action_trap_illegal_instruction
))
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
)).\
174 self
.decode_action
.eq(decode_action_trap_illegal_instruction
))
177 self
.decode_action
.eq(decode_action_op_op_imm
)
179 return Case(self
.funct3
, c
)
181 def calculate_misc_action(self
):
182 """ decode misc mem action
185 immz
= Constant(0, 12)
186 regz
= Constant(0, 5)
189 If((self
.immediate
[8:12] == immz
) & (self
.rs1
== regz
) & \
191 self
.decode_action
.eq(decode_action_fence
)).\
193 self
.decode_action
.eq(decode_action_trap_illegal_instruction
))
195 c
[funct3_fence_i
] = \
196 If((self
.immediate
[0:12] == immz
) & (self
.rs1
== regz
) & \
198 self
.decode_action
.eq(decode_action_fence_i
)).\
200 self
.decode_action
.eq(decode_action_trap_illegal_instruction
))
203 self
.decode_action
.eq(decode_action_trap_illegal_instruction
)
205 return Case(self
.funct3
, c
)
207 def calculate_action(self
):
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
)
223 return Case(self
.opcode
, c
)
227 function `decode_action calculate_action(
233 input [31:0] immediate,
237 `opcode_system: begin
239 `funct3_ecall_ebreak:
240 if((rs1 != 0) | (rd != 0) | ((immediate & ~32'b1) != 0))
241 calculate_action = `decode_action_trap_illegal_instruction;
243 calculate_action = `decode_action_trap_ecall_ebreak;
250 calculate_action = `decode_action_csr;
252 calculate_action = `decode_action_trap_illegal_instruction;
258 `opcode_48b_escape_0,
269 `opcode_reserved_10101,
271 `opcode_48b_escape_1,
272 `opcode_reserved_11010,
273 `opcode_reserved_11101,
275 `opcode_80b_escape: begin
276 calculate_action = `decode_action_trap_illegal_instruction;
279 calculate_action = `decode_action_trap_illegal_instruction;
284 assign decode_action = calculate_action(funct7,
296 if __name__
== "__main__":
297 example
= CPUDecoder()
298 print(verilog
.convert(example
,
308 example
.decode_action
,