From 9f4eb932a96e88ed7bf05afc5c487b19169390e4 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Fri, 23 Nov 2018 12:21:52 +0000 Subject: [PATCH] add cpu_decoder.py --- cpu_decoder.py | 310 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 310 insertions(+) create mode 100644 cpu_decoder.py diff --git a/cpu_decoder.py b/cpu_decoder.py new file mode 100644 index 0000000..9aebc4c --- /dev/null +++ b/cpu_decoder.py @@ -0,0 +1,310 @@ +""" +/* + * Copyright 2018 Jacob Lifshay + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ +`timescale 1ns / 100ps +""" +from migen import * +from migen.fhdl import verilog + +from riscvdefs import * +from cpudefs import * + +def calculate_immediate(instruction, immediate): + """ calculate immediate + """ + ci = {} + no_imm = 0x0 + + # R-type: no immediate + for op in [opcode_amo, opcode_op, opcode_op_32, opcode_op_fp]: + ci[op] = immediate.eq(no_imm) + + # I-type + im = Cat(instruction[20:], Replicate(instruction[31], 20)) + for op in [opcode_load, opcode_load_fp, opcode_misc_mem, + opcode_op_imm, opcode_op_imm_32, opcode_jalr, + opcode_system]: + ci[op] = immediate.eq(im) + + # S-type + im = Cat(instruction[7:12], instruction[25:31], + Replicate(instruction[31], 21)) + for op in [opcode_store, opcode_store_fp]: + ci[op] = immediate.eq(im) + + # B-type + im = Cat(Constant(0, 1), + instruction[8:12], instruction[25:31], + instruction[7], Replicate(instruction[31], 20)) + for op in [opcode_branch, ]: + ci[op] = immediate.eq(im) + + # U-type + im = Cat(Constant(0, 1), instruction[12:], ) + for op in [opcode_auipc, opcode_lui]: + ci[op] = immediate.eq(im) + + # J-type + im = Cat(Constant(0, 1), + instruction[21:25], instruction[25:31], + instruction[20], instruction[12:20], + Replicate(instruction[31], 12)) + for op in [opcode_jal, ]: + ci[op] = immediate.eq(im) + + # R4-type: no immediate + for op in [opcode_madd, opcode_msub, opcode_nmsub, opcode_nmadd]: + ci[op] = immediate.eq(no_imm) + + # unknown + for op in [ opcode_custom_0, opcode_48b_escape_0, opcode_custom_1, + opcode_64b_escape, opcode_reserved_10101, opcode_rv128_0, + opcode_48b_escape_1, opcode_reserved_11010, + opcode_reserved_11101, opcode_rv128_1, opcode_80b_escape]: + ci[op] = immediate.eq(no_imm) + + # default + for op in [ "default", ]: + ci[op] = immediate.eq(no_imm) + + return ci + + +class CPUDecoder(Module): + + def __init__(self): + self.instruction = Signal(32) + self.funct7 = Signal(7) + self.funct3 = Signal(3) + self.rd = Signal(5) + self.rs1 = Signal(5) + self.rs2 = Signal(5) + self.immediate = Signal(32) + self.opcode = Signal(7) + self.decode_action = Signal(decode_action) + + self.comb += self.funct7.eq(self.instruction[25:32]) + self.comb += self.funct3.eq(self.instruction[12:15]) + self.comb += self.rd.eq(self.instruction[7:12]) + self.comb += self.rs1.eq(self.instruction[15:20]) + self.comb += self.rs2.eq(self.instruction[20:25]) + self.comb += self.opcode.eq(self.instruction[0:7]) + + # add combinatorial decode opcode case statement + ci = calculate_immediate(self.instruction, self.immediate) + self.comb += Case(self.opcode, ci) + +""" + + function [31:0] calculate_immediate(input [31:0] instruction, input [6:0] opcode); + begin + case(opcode) + + `opcode_custom_0, + `opcode_48b_escape_0, + `opcode_custom_1, + `opcode_64b_escape, + `opcode_reserved_10101, + `opcode_rv128_0, + `opcode_48b_escape_1, + `opcode_reserved_11010, + `opcode_reserved_11101, + `opcode_rv128_1, + `opcode_80b_escape: + // unknown + calculate_immediate = 32'hXXXXXXXX; + default: + calculate_immediate = 32'hXXXXXXXX; + endcase + end + endfunction + + assign immediate = calculate_immediate(instruction, opcode); + + 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_load: begin + case(funct3) + `funct3_lb, + `funct3_lbu, + `funct3_lh, + `funct3_lhu, + `funct3_lw: + calculate_action = `decode_action_load; + default: + calculate_action = `decode_action_trap_illegal_instruction; + endcase + end + `opcode_misc_mem: begin + if(funct3 == `funct3_fence) begin + if((immediate[11:8] == 0) & (rs1 == 0) & (rd == 0)) + calculate_action = `decode_action_fence; + else + calculate_action = `decode_action_trap_illegal_instruction; + end + else if(funct3 == `funct3_fence_i) begin + if((immediate[11:0] == 0) & (rs1 == 0) & (rd == 0)) + calculate_action = `decode_action_fence_i; + else + calculate_action = `decode_action_trap_illegal_instruction; + end + else + begin + calculate_action = `decode_action_trap_illegal_instruction; + end + end + `opcode_op_imm, + `opcode_op: begin + if(funct3 == `funct3_slli) begin + if(funct7 == 0) + calculate_action = `decode_action_op_op_imm; + else + calculate_action = `decode_action_trap_illegal_instruction; + end + else if(funct3 == `funct3_srli_srai) begin + if(funct7 == 0 || funct7 == 7'h20) + calculate_action = `decode_action_op_op_imm; + else + calculate_action = `decode_action_trap_illegal_instruction; + end + else begin + calculate_action = `decode_action_op_op_imm; + end + end + `opcode_lui, + `opcode_auipc: begin + calculate_action = `decode_action_lui_auipc; + end + `opcode_store: begin + case(funct3) + `funct3_sb, + `funct3_sh, + `funct3_sw: + calculate_action = `decode_action_store; + default: + calculate_action = `decode_action_trap_illegal_instruction; + endcase + end + `opcode_branch: begin + case(funct3) + `funct3_beq, + `funct3_bne, + `funct3_blt, + `funct3_bge, + `funct3_bltu, + `funct3_bgeu: + calculate_action = `decode_action_branch; + default: + calculate_action = `decode_action_trap_illegal_instruction; + endcase + end + `opcode_jalr: begin + if(funct3 == `funct3_jalr) + calculate_action = `decode_action_jalr; + else + calculate_action = `decode_action_trap_illegal_instruction; + end + `opcode_jal: begin + calculate_action = `decode_action_jal; + end + `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, + { + example.instruction, + example.funct7, + example.funct3, + example.rd, + example.rs1, + example.rs2, + example.immediate, + example.opcode, + example.decode_action, + })) -- 2.30.2