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 def calculate_immediate(instruction
, immediate
):
33 """ calculate immediate
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
)
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
,
47 ci
[op
] = immediate
.eq(im
)
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
)
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
)
63 im
= Cat(Constant(0, 1), instruction
[12:], )
64 for op
in [opcode_auipc
, opcode_lui
]:
65 ci
[op
] = immediate
.eq(im
)
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
)
75 # R4-type: no immediate
76 for op
in [opcode_madd
, opcode_msub
, opcode_nmsub
, opcode_nmadd
]:
77 ci
[op
] = immediate
.eq(no_imm
)
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
)
87 for op
in [ "default", ]:
88 ci
[op
] = immediate
.eq(no_imm
)
92 class CPUDecoder(Module
):
95 self
.instruction
= Signal(32)
96 self
.funct7
= Signal(7)
97 self
.funct3
= Signal(3)
101 self
.immediate
= Signal(32)
102 self
.opcode
= Signal(7)
103 self
.decode_action
= Signal(decode_action
)
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])
112 # add combinatorial decode opcode case statement
113 ci
= calculate_immediate(self
.instruction
, self
.immediate
)
114 self
.comb
+= Case(self
.opcode
, ci
)
116 self
.comb
+= self
.calculate_action()
118 def calculate_store_action(self
):
119 """ decode store action
123 for op
in [ funct3_sb
, funct3_sh
, funct3_sw
, ]:
124 c
[op
] = self
.decode_action
.eq(decode_action_store
)
127 self
.decode_action
.eq(decode_action_trap_illegal_instruction
)
129 return Case(self
.funct3
, c
)
131 def calculate_load_action(self
):
132 """ decode load action
136 for op
in [ funct3_lb
, funct3_lbu
, funct3_lh
, funct3_lhu
, funct3_lw
, ]:
137 c
[op
] = self
.decode_action
.eq(decode_action_load
)
140 self
.decode_action
.eq(decode_action_trap_illegal_instruction
)
142 return Case(self
.funct3
, c
)
144 def calculate_op_action(self
):
148 immz
= Constant(0, 12)
149 regz
= Constant(0, 5)
152 If((self
.funct7
== Constant(0, 7)),
153 self
.decode_action
.eq(decode_action_op_op_imm
)).\
155 self
.decode_action
.eq(decode_action_trap_illegal_instruction
))
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
)).\
162 self
.decode_action
.eq(decode_action_trap_illegal_instruction
))
165 self
.decode_action
.eq(decode_action_op_op_imm
)
167 return Case(self
.funct3
, c
)
169 def calculate_misc_action(self
):
170 """ decode misc mem action
173 immz
= Constant(0, 12)
174 regz
= Constant(0, 5)
177 If((self
.immediate
[8:12] == immz
) & (self
.rs1
== regz
) & \
179 self
.decode_action
.eq(decode_action_fence
)).\
181 self
.decode_action
.eq(decode_action_trap_illegal_instruction
))
183 c
[funct3_fence_i
] = \
184 If((self
.immediate
[0:12] == immz
) & (self
.rs1
== regz
) & \
186 self
.decode_action
.eq(decode_action_fence_i
)).\
188 self
.decode_action
.eq(decode_action_trap_illegal_instruction
))
191 self
.decode_action
.eq(decode_action_trap_illegal_instruction
)
193 return Case(self
.funct3
, c
)
195 def calculate_action(self
):
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()
208 return Case(self
.opcode
, c
)
212 function `decode_action calculate_action(
218 input [31:0] immediate,
222 `opcode_branch: begin
230 calculate_action = `decode_action_branch;
232 calculate_action = `decode_action_trap_illegal_instruction;
236 if(funct3 == `funct3_jalr)
237 calculate_action = `decode_action_jalr;
239 calculate_action = `decode_action_trap_illegal_instruction;
242 calculate_action = `decode_action_jal;
244 `opcode_system: begin
246 `funct3_ecall_ebreak:
247 if((rs1 != 0) | (rd != 0) | ((immediate & ~32'b1) != 0))
248 calculate_action = `decode_action_trap_illegal_instruction;
250 calculate_action = `decode_action_trap_ecall_ebreak;
257 calculate_action = `decode_action_csr;
259 calculate_action = `decode_action_trap_illegal_instruction;
265 `opcode_48b_escape_0,
276 `opcode_reserved_10101,
278 `opcode_48b_escape_1,
279 `opcode_reserved_11010,
280 `opcode_reserved_11101,
282 `opcode_80b_escape: begin
283 calculate_action = `decode_action_trap_illegal_instruction;
286 calculate_action = `decode_action_trap_illegal_instruction;
291 assign decode_action = calculate_action(funct7,
303 if __name__
== "__main__":
304 example
= CPUDecoder()
305 print(verilog
.convert(example
,
315 example
.decode_action
,