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.opcode = Signal(7)
self.decode_action = Signal(decode_action)
+ # decode bits of instruction
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.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)
+ # add combinatorial decode opcode case statements for immed and action
+ self.comb += self.calculate_immediate()
+ self.comb += self.calculate_action()
+
+ def calculate_immediate(self):
+ """ 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] = self.immediate.eq(no_imm)
+
+ # I-type
+ im = Cat(self.instruction[20:], Replicate(self.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] = self.immediate.eq(im)
+
+ # S-type
+ im = Cat(self.instruction[7:12], self.instruction[25:31],
+ Replicate(self.instruction[31], 21))
+ for op in [opcode_store, opcode_store_fp]:
+ ci[op] = self.immediate.eq(im)
+
+ # B-type
+ im = Cat(Constant(0, 1),
+ self.instruction[8:12], self.instruction[25:31],
+ self.instruction[7], Replicate(self.instruction[31], 20))
+ for op in [opcode_branch, ]:
+ ci[op] = self.immediate.eq(im)
+
+ # U-type
+ im = Cat(Constant(0, 1), self.instruction[12:], )
+ for op in [opcode_auipc, opcode_lui]:
+ ci[op] = self.immediate.eq(im)
+
+ # J-type
+ im = Cat(Constant(0, 1),
+ self.instruction[21:25], self.instruction[25:31],
+ self.instruction[20], self.instruction[12:20],
+ Replicate(self.instruction[31], 12))
+ for op in [opcode_jal, ]:
+ ci[op] = self.immediate.eq(im)
+
+ # R4-type: no immediate
+ for op in [opcode_madd, opcode_msub, opcode_nmsub, opcode_nmadd]:
+ ci[op] = self.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] = self.immediate.eq(no_imm)
+
+ # default
+ for op in [ "default", ]:
+ ci[op] = self.immediate.eq(no_imm)
+
+ return Case(self.opcode, ci)
+
+ def _decode_funct3(self, options, action):
+ """ decode by list of cases
+ """
+ c = {}
+ # load opcode
+ for op in options:
+ c[op] = self.decode_action.eq(action)
+ # default
+ c["default"] = \
+ self.decode_action.eq(decode_action_trap_illegal_instruction)
+
+ return Case(self.funct3, c)
+
+ def calculate_store_action(self):
+ """ decode store action
+ """
+ return self._decode_funct3([ funct3_sb, funct3_sh, funct3_sw, ],
+ decode_action_store)
+
+ def calculate_load_action(self):
+ """ decode load action
+ """
+ return self._decode_funct3([ funct3_lb, funct3_lbu, funct3_lh,
+ funct3_lhu, funct3_lw, ],
+ decode_action_load)
+
+ def calculate_branch_action(self):
+ """ decode branch action
+ """
+ return self._decode_funct3([ funct3_beq, funct3_bne, funct3_blt,
+ funct3_bge, funct3_bltu, funct3_bgeu ],
+ decode_action_branch)
+
+ def calculate_jalr_action(self):
+ """ decode jalr action
+ """
+ return self._decode_funct3([ funct3_jalr, ],
+ decode_action_jalr)
+
+ def calculate_op_action(self):
+ """ decode op action
+ """
+ c = {}
+ immz = Constant(0, 12)
+ regz = Constant(0, 5)
+ # fence
+ c[funct3_slli] = \
+ If((self.funct7 == Constant(0, 7)),
+ self.decode_action.eq(decode_action_op_op_imm)).\
+ Else(
+ self.decode_action.eq(decode_action_trap_illegal_instruction))
+ # fence.i
+ c[funct3_srli_srai] = \
+ If((self.funct7 == Constant(0, 7) | \
+ (self.funct7 == Constant(0x20, 7))),
+ self.decode_action.eq(decode_action_op_op_imm)).\
+ Else(
+ self.decode_action.eq(decode_action_trap_illegal_instruction))
+ # default
+ c["default"] = \
+ self.decode_action.eq(decode_action_op_op_imm)
+
+ return Case(self.funct3, c)
+
+ def calculate_misc_action(self):
+ """ decode misc mem action
+ """
+ c = {}
+ immz = Constant(0, 12)
+ regz = Constant(0, 5)
+ # fence
+ c[funct3_fence] = \
+ If((self.immediate[8:12] == immz) & (self.rs1 == regz) & \
+ (self.rd == regz),
+ self.decode_action.eq(decode_action_fence)).\
+ Else(
+ self.decode_action.eq(decode_action_trap_illegal_instruction))
+ # fence.i
+ c[funct3_fence_i] = \
+ If((self.immediate[0:12] == immz) & (self.rs1 == regz) & \
+ (self.rd == regz),
+ self.decode_action.eq(decode_action_fence_i)).\
+ Else(
+ self.decode_action.eq(decode_action_trap_illegal_instruction))
+ # default
+ c["default"] = \
+ self.decode_action.eq(decode_action_trap_illegal_instruction)
+
+ return Case(self.funct3, c)
+
+ def calculate_action(self):
+ """ calculate action
+ """
+ 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_op] = self.calculate_op_action()
+ c[opcode_lui] = self.decode_action.eq(decode_action_lui_auipc)
+ c[opcode_auipc] = self.decode_action.eq(decode_action_lui_auipc)
+ c[opcode_store] = self.calculate_store_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)
+
+ return Case(self.opcode, c)
"""
-
- 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 [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:
endcase
end
endfunction
-
+
assign decode_action = calculate_action(funct7,
funct3,
rd,
rs2,
immediate,
opcode);
-
+
endmodule
"""
if __name__ == "__main__":
example = CPUDecoder()
print(verilog.convert(example,
- {
+ {
example.instruction,
example.funct7,
example.funct3,