minor reorg, add alu
[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 """ 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.
37 """
38
39 def __init__(self):
40 self.instruction = Signal(32)
41 self.funct7 = Signal(7)
42 self.funct3 = Signal(3)
43 self.rd = Signal(5)
44 self.rs1 = Signal(5)
45 self.rs2 = Signal(5)
46 self.immediate = Signal(32)
47 self.opcode = Signal(7)
48 self.decode_action = Signal(decode_action)
49
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])
57
58 # add combinatorial decode opcode case statements for immed and action
59 self.comb += self.calculate_immediate()
60 self.comb += self.calculate_action()
61
62 def calculate_immediate(self):
63 """ calculate immediate
64 """
65 ci = {}
66 no_imm = Constant(0x0, 32)
67
68 # R-type: no immediate
69 for op in [OP.amo, OP.op, OP.op_32, OP.op_fp]:
70 ci[op] = self.immediate.eq(no_imm)
71
72 # I-type: sign-extended bits 20-31
73 im = Cat(self.instruction[20:], Replicate(self.instruction[31], 20))
74 for op in [OP.load, OP.load_fp, OP.misc_mem,
75 OP.op_imm, OP.op_imm_32, OP.jalr,
76 OP.system]:
77 ci[op] = self.immediate.eq(im)
78
79 # S-type
80 im = Cat(self.instruction[7:12], self.instruction[25:31],
81 Replicate(self.instruction[31], 21))
82 for op in [OP.store, OP.store_fp]:
83 ci[op] = self.immediate.eq(im)
84
85 # B-type
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 [OP.branch, ]:
90 ci[op] = self.immediate.eq(im)
91
92 # U-type
93 im = Cat(Constant(0, 1), self.instruction[12:], )
94 for op in [OP.auipc, OP.lui]:
95 ci[op] = self.immediate.eq(im)
96
97 # J-type
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 [OP.jal, ]:
103 ci[op] = self.immediate.eq(im)
104
105 # R4-type: no immediate
106 for op in [OP.madd, OP.msub, OP.nmsub, OP.nmadd]:
107 ci[op] = self.immediate.eq(no_imm)
108
109 # unknown
110 for op in [ OP.custom_0, OP.op_48b_escape_0, OP.custom_1,
111 OP.op_64b_escape, OP.reserved_10101, OP.rv128_0,
112 OP.op_48b_escape_1, OP.reserved_11010,
113 OP.reserved_11101, OP.rv128_1, OP.op_80b_escape]:
114 ci[op] = self.immediate.eq(no_imm)
115
116 # default
117 for op in [ "default", ]:
118 ci[op] = self.immediate.eq(no_imm)
119
120 return Case(self.opcode, ci)
121
122 def _decode_funct3(self, action, options):
123 """ decode by list of cases
124 """
125 c = {}
126 # load opcode
127 for op in options:
128 c[op] = self.decode_action.eq(action)
129 # default
130 c["default"] = self.decode_action.eq(DA.trap_illegal_instruction)
131
132 return Case(self.funct3, c)
133
134 def calculate_store_action(self):
135 """ decode store action
136 """
137 return self._decode_funct3(DA.store, [F3.sb, F3.sh, F3.sw, ])
138
139 def calculate_load_action(self):
140 """ decode load action
141 """
142 return self._decode_funct3(DA.load, [F3.lb, F3.lbu, F3.lh,
143 F3.lhu, F3.lw, ])
144
145 def calculate_branch_action(self):
146 """ decode branch action
147 """
148 return self._decode_funct3(DA.branch, [F3.beq, F3.bne, F3.blt,
149 F3.bge, F3.bltu, F3.bgeu ])
150
151 def calculate_jalr_action(self):
152 """ decode jalr action
153 """
154 return self._decode_funct3(DA.jalr, [F3.jalr, ])
155
156 def calculate_op_action(self):
157 """ decode op action: the arith ops, and, or, add, xor, sr/sl etc.
158 """
159 c = {}
160 immz = Constant(0, 12)
161 regz = Constant(0, 5)
162 # slli
163 c[F3.slli] = \
164 If((self.funct7 == Constant(0, 7)),
165 self.decode_action.eq(DA.op_op_imm)
166 ).Else(
167 self.decode_action.eq(DA.trap_illegal_instruction))
168 # srli/srai
169 c[F3.srli_srai] = \
170 If((self.funct7 == Constant(0, 7) | \
171 (self.funct7 == Constant(0x20, 7))),
172 self.decode_action.eq(DA.op_op_imm)
173 ).Else(
174 self.decode_action.eq(DA.trap_illegal_instruction))
175 # default
176 c["default"] = self.decode_action.eq(DA.op_op_imm)
177
178 return Case(self.funct3, c)
179
180 def calculate_misc_action(self):
181 """ decode misc mem action: fence and fence_i
182 """
183 c = {}
184 immz = Constant(0, 12)
185 regz = Constant(0, 5)
186 # fence
187 c[F3.fence] = \
188 If((self.immediate[8:12] == immz) & (self.rs1 == regz) & \
189 (self.rd == regz),
190 self.decode_action.eq(DA.fence)
191 ).Else(
192 self.decode_action.eq(DA.trap_illegal_instruction))
193 # fence.i
194 c[F3.fence_i] = \
195 If((self.immediate[0:12] == immz) & (self.rs1 == regz) & \
196 (self.rd == regz),
197 self.decode_action.eq(DA.fence_i)
198 ).Else(
199 self.decode_action.eq(DA.trap_illegal_instruction))
200 # default
201 c["default"] = self.decode_action.eq(DA.trap_illegal_instruction)
202
203 return Case(self.funct3, c)
204
205 def calculate_system_action(self):
206 """ decode opcode system: ebreak and csrs
207 """
208 c = {}
209 b1 = Constant(1, 32)
210 regz = Constant(0, 5)
211 # ebreak
212 c[F3.ecall_ebreak] = \
213 If((self.immediate == ~b1) & (self.rs1 == regz) & \
214 (self.rd == regz),
215 self.decode_action.eq(DA.trap_ecall_ebreak)
216 ).Else(
217 self.decode_action.eq(DA.trap_illegal_instruction))
218 # csrs
219 for op in [ F3.csrrw, F3.csrrs, F3.csrrc,
220 F3.csrrwi, F3.csrrsi, F3.csrrci]:
221 c[op] = self.decode_action.eq(DA.csr)
222 # default
223 c["default"] = self.decode_action.eq(DA.trap_illegal_instruction)
224
225 return Case(self.funct3, c)
226
227 def calculate_action(self):
228 """ calculate action based on opcode.
229
230 this is a first level case statement that calls down to 2nd
231 level case (and in some cases if logic) mostly using funct3
232 (funct7 in the case of arith ops).
233 """
234 c = {}
235 c[OP.load ] = self.calculate_load_action()
236 c[OP.misc_mem] = self.calculate_misc_action()
237 c[OP.op_imm ] = self.calculate_op_action()
238 c[OP.op ] = self.calculate_op_action()
239 c[OP.lui ] = self.decode_action.eq(DA.lui_auipc)
240 c[OP.auipc ] = self.decode_action.eq(DA.lui_auipc)
241 c[OP.store ] = self.calculate_store_action()
242 c[OP.branch ] = self.calculate_branch_action()
243 c[OP.jalr ] = self.calculate_jalr_action()
244 c[OP.jal ] = self.decode_action.eq(DA.jal)
245 c[OP.system ] = self.calculate_system_action()
246
247 # big batch of unrecognised opcodes: throw trap.
248 for o in [ OP.load_fp, OP.custom_0, OP.op_imm_32,
249 OP.op_48b_escape_0, OP.store_fp, OP.custom_1,
250 OP.amo, OP.op_32, OP.op_64b_escape,
251 OP.madd, OP.msub, OP.nmsub,
252 OP.nmadd, OP.op_fp, OP.reserved_10101,
253 OP.rv128_0, OP.op_48b_escape_1, OP.reserved_11010,
254 OP.reserved_11101, OP.rv128_1, OP.op_80b_escape,
255 "default", ]:
256 c[o] = self.decode_action.eq(DA.trap_illegal_instruction)
257
258 return Case(self.opcode, c)
259
260 if __name__ == "__main__":
261 example = CPUDecoder()
262 print(verilog.convert(example,
263 {
264 example.instruction,
265 example.funct7,
266 example.funct3,
267 example.rd,
268 example.rs1,
269 example.rs2,
270 example.immediate,
271 example.opcode,
272 example.decode_action,
273 }))