from cpudefs import *
class CPUDecoder(Module):
+ """ decodes a 32-bit instruction into an immediate and other constituent
+ parts, including the opcode and funct3 and funct7, followed by
+ a further (hierarchical) breakdown of the action required to be taken.
+ unidentified actions are decoded as an illegal instruction trap.
+ """
def __init__(self):
self.instruction = Signal(32)
return Case(self.funct3, c)
+ def calculate_system_action(self):
+ """ decode system action
+ """
+ c = {}
+ b1 = Constant(1, 32)
+ regz = Constant(0, 5)
+ # ebreak
+ c[funct3_ecall_ebreak] = \
+ If((self.immediate != ~b1) | (self.rs1 != regz) | \
+ (self.rd != regz),
+ self.decode_action.eq(decode_action_trap_illegal_instruction)).\
+ Else(
+ self.decode_action.eq(decode_action_trap_ecall_ebreak))
+ # csrs
+ for op in [ funct3_csrrw, funct3_csrrs, funct3_csrrc,
+ funct3_csrrwi, funct3_csrrsi, funct3_csrrci]:
+ c[op] = self.decode_action.eq(decode_action_csr)
+ # default
+ c["default"] = \
+ self.decode_action.eq(decode_action_trap_illegal_instruction)
+
+ return Case(self.funct3, c)
+
def calculate_action(self):
- """ calculate action
+ """ calculate action based on opcode.
+
+ this is a first level case statement that calls down to 2nd
+ level case (and in some cases if logic) mostly using funct3
+ (funct7 in the case of arith ops).
"""
c = {}
- # load opcode
c[opcode_load] = self.calculate_load_action()
c[opcode_misc_mem] = self.calculate_misc_action()
c[opcode_op_imm] = self.calculate_op_action()
c[opcode_branch] = self.calculate_branch_action()
c[opcode_jalr] = self.calculate_jalr_action()
c[opcode_jal] = self.decode_action.eq(decode_action_jal)
+ c[opcode_system] = self.calculate_system_action()
+
+ # big batch of unrecognised opcodes: throw trap.
+ for o in [ opcode_load_fp, opcode_custom_0, opcode_op_imm_32,
+ opcode_48b_escape_0, opcode_store_fp, opcode_custom_1,
+ opcode_amo, opcode_op_32, opcode_64b_escape,
+ opcode_madd, opcode_msub, opcode_nmsub,
+ opcode_nmadd, opcode_op_fp, opcode_reserved_10101,
+ opcode_rv128_0, opcode_48b_escape_1, opcode_reserved_11010,
+ opcode_reserved_11101, opcode_rv128_1, opcode_80b_escape,
+ "default", ]:
+ c[o] = self.decode_action.eq(decode_action_trap_illegal_instruction)
return Case(self.opcode, c)
-"""
-
- function `decode_action calculate_action(
- input [6:0] funct7,
- input [2:0] funct3,
- input [4:0] rd,
- input [4:0] rs1,
- input [4:0] rs2,
- input [31:0] immediate,
- input [6:0] opcode);
- begin
- case(opcode)
- `opcode_system: begin
- case(funct3)
- `funct3_ecall_ebreak:
- if((rs1 != 0) | (rd != 0) | ((immediate & ~32'b1) != 0))
- calculate_action = `decode_action_trap_illegal_instruction;
- else
- calculate_action = `decode_action_trap_ecall_ebreak;
- `funct3_csrrw,
- `funct3_csrrs,
- `funct3_csrrc,
- `funct3_csrrwi,
- `funct3_csrrsi,
- `funct3_csrrci:
- calculate_action = `decode_action_csr;
- default:
- calculate_action = `decode_action_trap_illegal_instruction;
- endcase
- end
- `opcode_load_fp,
- `opcode_custom_0,
- `opcode_op_imm_32,
- `opcode_48b_escape_0,
- `opcode_store_fp,
- `opcode_custom_1,
- `opcode_amo,
- `opcode_op_32,
- `opcode_64b_escape,
- `opcode_madd,
- `opcode_msub,
- `opcode_nmsub,
- `opcode_nmadd,
- `opcode_op_fp,
- `opcode_reserved_10101,
- `opcode_rv128_0,
- `opcode_48b_escape_1,
- `opcode_reserved_11010,
- `opcode_reserved_11101,
- `opcode_rv128_1,
- `opcode_80b_escape: begin
- calculate_action = `decode_action_trap_illegal_instruction;
- end
- default:
- calculate_action = `decode_action_trap_illegal_instruction;
- endcase
- end
- endfunction
-
- assign decode_action = calculate_action(funct7,
- funct3,
- rd,
- rs1,
- rs2,
- immediate,
- opcode);
-
- endmodule
-"""
-
-
if __name__ == "__main__":
example = CPUDecoder()
print(verilog.convert(example,