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
):
33 """ decodes a 32-bit instruction into an immediate and other constituent
34 parts, including the opcode and funct3 and funct7, followed by
35 a further (hierarchical) breakdown of the action required to be taken.
36 unidentified actions are decoded as an illegal instruction trap.
40 self
.instruction
= Signal(32)
41 self
.funct7
= Signal(7)
42 self
.funct3
= Signal(3)
46 self
.immediate
= Signal(32)
47 self
.opcode
= Signal(7)
48 self
.decode_action
= Signal(decode_action
)
50 # decode bits of instruction
51 self
.comb
+= self
.funct7
.eq(self
.instruction
[25:32])
52 self
.comb
+= self
.funct3
.eq(self
.instruction
[12:15])
53 self
.comb
+= self
.rd
.eq (self
.instruction
[7:12])
54 self
.comb
+= self
.rs1
.eq (self
.instruction
[15:20])
55 self
.comb
+= self
.rs2
.eq (self
.instruction
[20:25])
56 self
.comb
+= self
.opcode
.eq(self
.instruction
[0:7])
58 # add combinatorial decode opcode case statements for immed and action
59 self
.comb
+= self
.calculate_immediate()
60 self
.comb
+= self
.calculate_action()
62 def calculate_immediate(self
):
63 """ calculate immediate
68 # R-type: no immediate
69 for op
in [opcode_amo
, opcode_op
, opcode_op_32
, opcode_op_fp
]:
70 ci
[op
] = self
.immediate
.eq(no_imm
)
73 im
= Cat(self
.instruction
[20:], Replicate(self
.instruction
[31], 20))
74 for op
in [opcode_load
, opcode_load_fp
, opcode_misc_mem
,
75 opcode_op_imm
, opcode_op_imm_32
, opcode_jalr
,
77 ci
[op
] = self
.immediate
.eq(im
)
80 im
= Cat(self
.instruction
[7:12], self
.instruction
[25:31],
81 Replicate(self
.instruction
[31], 21))
82 for op
in [opcode_store
, opcode_store_fp
]:
83 ci
[op
] = self
.immediate
.eq(im
)
86 im
= Cat(Constant(0, 1),
87 self
.instruction
[8:12], self
.instruction
[25:31],
88 self
.instruction
[7], Replicate(self
.instruction
[31], 20))
89 for op
in [opcode_branch
, ]:
90 ci
[op
] = self
.immediate
.eq(im
)
93 im
= Cat(Constant(0, 1), self
.instruction
[12:], )
94 for op
in [opcode_auipc
, opcode_lui
]:
95 ci
[op
] = self
.immediate
.eq(im
)
98 im
= Cat(Constant(0, 1),
99 self
.instruction
[21:25], self
.instruction
[25:31],
100 self
.instruction
[20], self
.instruction
[12:20],
101 Replicate(self
.instruction
[31], 12))
102 for op
in [opcode_jal
, ]:
103 ci
[op
] = self
.immediate
.eq(im
)
105 # R4-type: no immediate
106 for op
in [opcode_madd
, opcode_msub
, opcode_nmsub
, opcode_nmadd
]:
107 ci
[op
] = self
.immediate
.eq(no_imm
)
110 for op
in [ opcode_custom_0
, opcode_48b_escape_0
, opcode_custom_1
,
111 opcode_64b_escape
, opcode_reserved_10101
, opcode_rv128_0
,
112 opcode_48b_escape_1
, opcode_reserved_11010
,
113 opcode_reserved_11101
, opcode_rv128_1
, opcode_80b_escape
]:
114 ci
[op
] = self
.immediate
.eq(no_imm
)
117 for op
in [ "default", ]:
118 ci
[op
] = self
.immediate
.eq(no_imm
)
120 return Case(self
.opcode
, ci
)
122 def _decode_funct3(self
, options
, action
):
123 """ decode by list of cases
128 c
[op
] = self
.decode_action
.eq(action
)
131 self
.decode_action
.eq(decode_action_trap_illegal_instruction
)
133 return Case(self
.funct3
, c
)
135 def calculate_store_action(self
):
136 """ decode store action
138 return self
._decode
_funct
3([ funct3_sb
, funct3_sh
, funct3_sw
, ],
141 def calculate_load_action(self
):
142 """ decode load action
144 return self
._decode
_funct
3([ funct3_lb
, funct3_lbu
, funct3_lh
,
145 funct3_lhu
, funct3_lw
, ],
148 def calculate_branch_action(self
):
149 """ decode branch action
151 return self
._decode
_funct
3([ funct3_beq
, funct3_bne
, funct3_blt
,
152 funct3_bge
, funct3_bltu
, funct3_bgeu
],
153 decode_action_branch
)
155 def calculate_jalr_action(self
):
156 """ decode jalr action
158 return self
._decode
_funct
3([ funct3_jalr
, ],
161 def calculate_op_action(self
):
165 immz
= Constant(0, 12)
166 regz
= Constant(0, 5)
169 If((self
.funct7
== Constant(0, 7)),
170 self
.decode_action
.eq(decode_action_op_op_imm
)).\
172 self
.decode_action
.eq(decode_action_trap_illegal_instruction
))
174 c
[funct3_srli_srai
] = \
175 If((self
.funct7
== Constant(0, 7) | \
176 (self
.funct7
== Constant(0x20, 7))),
177 self
.decode_action
.eq(decode_action_op_op_imm
)).\
179 self
.decode_action
.eq(decode_action_trap_illegal_instruction
))
182 self
.decode_action
.eq(decode_action_op_op_imm
)
184 return Case(self
.funct3
, c
)
186 def calculate_misc_action(self
):
187 """ decode misc mem action
190 immz
= Constant(0, 12)
191 regz
= Constant(0, 5)
194 If((self
.immediate
[8:12] == immz
) & (self
.rs1
== regz
) & \
196 self
.decode_action
.eq(decode_action_fence
)).\
198 self
.decode_action
.eq(decode_action_trap_illegal_instruction
))
200 c
[funct3_fence_i
] = \
201 If((self
.immediate
[0:12] == immz
) & (self
.rs1
== regz
) & \
203 self
.decode_action
.eq(decode_action_fence_i
)).\
205 self
.decode_action
.eq(decode_action_trap_illegal_instruction
))
208 self
.decode_action
.eq(decode_action_trap_illegal_instruction
)
210 return Case(self
.funct3
, c
)
212 def calculate_system_action(self
):
213 """ decode system action
217 regz
= Constant(0, 5)
219 c
[funct3_ecall_ebreak
] = \
220 If((self
.immediate
!= ~b1
) |
(self
.rs1
!= regz
) | \
222 self
.decode_action
.eq(decode_action_trap_illegal_instruction
)).\
224 self
.decode_action
.eq(decode_action_trap_ecall_ebreak
))
226 for op
in [ funct3_csrrw
, funct3_csrrs
, funct3_csrrc
,
227 funct3_csrrwi
, funct3_csrrsi
, funct3_csrrci
]:
228 c
[op
] = self
.decode_action
.eq(decode_action_csr
)
231 self
.decode_action
.eq(decode_action_trap_illegal_instruction
)
233 return Case(self
.funct3
, c
)
235 def calculate_action(self
):
236 """ calculate action based on opcode.
238 this is a first level case statement that calls down to 2nd
239 level case (and in some cases if logic) mostly using funct3
240 (funct7 in the case of arith ops).
243 c
[opcode_load
] = self
.calculate_load_action()
244 c
[opcode_misc_mem
] = self
.calculate_misc_action()
245 c
[opcode_op_imm
] = self
.calculate_op_action()
246 c
[opcode_op
] = self
.calculate_op_action()
247 c
[opcode_lui
] = self
.decode_action
.eq(decode_action_lui_auipc
)
248 c
[opcode_auipc
] = self
.decode_action
.eq(decode_action_lui_auipc
)
249 c
[opcode_store
] = self
.calculate_store_action()
250 c
[opcode_branch
] = self
.calculate_branch_action()
251 c
[opcode_jalr
] = self
.calculate_jalr_action()
252 c
[opcode_jal
] = self
.decode_action
.eq(decode_action_jal
)
253 c
[opcode_system
] = self
.calculate_system_action()
255 # big batch of unrecognised opcodes: throw trap.
256 for o
in [ opcode_load_fp
, opcode_custom_0
, opcode_op_imm_32
,
257 opcode_48b_escape_0
, opcode_store_fp
, opcode_custom_1
,
258 opcode_amo
, opcode_op_32
, opcode_64b_escape
,
259 opcode_madd
, opcode_msub
, opcode_nmsub
,
260 opcode_nmadd
, opcode_op_fp
, opcode_reserved_10101
,
261 opcode_rv128_0
, opcode_48b_escape_1
, opcode_reserved_11010
,
262 opcode_reserved_11101
, opcode_rv128_1
, opcode_80b_escape
,
264 c
[o
] = self
.decode_action
.eq(decode_action_trap_illegal_instruction
)
266 return Case(self
.opcode
, c
)
268 if __name__
== "__main__":
269 example
= CPUDecoder()
270 print(verilog
.convert(example
,
280 example
.decode_action
,