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_store_action(self):
- """ decode store 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 [ funct3_sb, funct3_sh, funct3_sw, ]:
- c[op] = self.decode_action.eq(decode_action_store)
+ 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
"""
- c = {}
- # load opcode
- for op in [ funct3_lb, funct3_lbu, funct3_lh, funct3_lhu, funct3_lw, ]:
- c[op] = self.decode_action.eq(decode_action_load)
- # default
- c["default"] = \
- self.decode_action.eq(decode_action_trap_illegal_instruction)
+ return self._decode_funct3([ funct3_lb, funct3_lbu, funct3_lh,
+ funct3_lhu, funct3_lw, ],
+ decode_action_load)
- return Case(self.funct3, c)
+ 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[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 `decode_action calculate_action(
input [6:0] funct7,
input [2:0] funct3,
input [6:0] opcode);
begin
case(opcode)
- `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,
-
"""
/*
* Copyright 2018 Jacob Lifshay
funct3_bge = Constant(0x5, 3)
funct3_bltu = Constant(0x6, 3)
funct3_bgeu = Constant(0x7, 3)
+
funct3_lb = Constant(0x0, 3)
funct3_lh = Constant(0x1, 3)
funct3_lw = Constant(0x2, 3)
funct3_lbu = Constant(0x4, 3)
funct3_lhu = Constant(0x5, 3)
+
funct3_sb = Constant(0x0, 3)
funct3_sh = Constant(0x1, 3)
funct3_sw = Constant(0x2, 3)
+
funct3_addi = Constant(0x0, 3)
funct3_slli = Constant(0x1, 3)
funct3_slti = Constant(0x2, 3)
funct3_srli_srai = Constant(0x5, 3)
funct3_ori = Constant(0x6, 3)
funct3_andi = Constant(0x7, 3)
+
funct3_add_sub = Constant(0x0, 3)
funct3_sll = Constant(0x1, 3)
funct3_slt = Constant(0x2, 3)
funct3_srl_sra = Constant(0x5, 3)
funct3_or = Constant(0x6, 3)
funct3_and = Constant(0x7, 3)
+
funct3_fence = Constant(0x0, 3)
funct3_fence_i = Constant(0x1, 3)
+
funct3_ecall_ebreak = Constant(0x0, 3)
funct3_csrrw = Constant(0x1, 3)
funct3_csrrs = Constant(0x2, 3)