self.sync += self.mepc.eq(0) # 32'hXXXXXXXX;
self.sync += self.mscratch.eq(0) # 32'hXXXXXXXX;
+
class Misa:
def __init__(self, comb, sync):
self.comb = comb
self.output_instruction = Signal(32, name="fetch_ouutput_instruction")
self.output_state = Signal(fetch_output_state,name="fetch_output_state")
+ def get_fetch_action(self, dc, load_store_misaligned, mi,
+ branch_taken, misaligned_jump_target,
+ csr_op_is_valid):
+ c = {}
+ c["default"] = self.action.eq(FA.default) # XXX should be 32'XXXXXXXX?
+ c[FOS.empty] = self.action.eq(FA.default)
+ c[FOS.trap] = self.action.eq(FA.ack_trap)
+
+ # illegal instruction -> error trap
+ i= If((dc.act & DA.trap_illegal_instruction) != 0,
+ self.action.eq(FA.error_trap)
+ )
+
+ # ecall / ebreak -> noerror trap
+ i = i.Elif((dc.act & DA.trap_ecall_ebreak) != 0,
+ self.action.eq(FA.noerror_trap))
+
+ # load/store: check alignment, check wait
+ i = i.Elif((dc.act & (DA.load | DA.store)) != 0,
+ If((load_store_misaligned | ~mi.rw_address_valid),
+ self.action.eq(FA.error_trap) # misaligned or invalid addr
+ ).Elif(mi.rw_wait,
+ self.action.eq(FA.wait) # wait
+ ).Else(
+ self.action.eq(FA.default) # ok
+ )
+ )
+
+ # fence
+ i = i.Elif((dc.act & DA.fence) != 0,
+ self.action.eq(FA.fence))
+
+ # branch -> misaligned=error, otherwise jump
+ i = i.Elif((dc.act & DA.branch) != 0,
+ If(misaligned_jump_target,
+ self.action.eq(FA.error_trap)
+ ).Else(
+ self.action.eq(FA.jump)
+ )
+ )
+
+ # jal/jalr -> misaligned=error, otherwise jump
+ i = i.Elif((dc.act & (DA.jal | DA.jalr)) != 0,
+ If(misaligned_jump_target,
+ self.action.eq(FA.error_trap)
+ ).Else(
+ self.action.eq(FA.jump)
+ )
+ )
+
+ # csr -> opvalid=ok, else error trap
+ i = i.Elif((dc.act & DA.csr) != 0,
+ If(csr_op_is_valid,
+ self.action.eq(FA.default)
+ ).Else(
+ self.action.eq(FA.error_trap)
+ )
+ )
+
+ c[FOS.valid] = i
+
+ return Case(self.output_state, c)
+
class CPU(Module):
"""
"""
def get_ls_misaligned(self, ls, funct3, load_store_address_low_2):
+ """ returns whether a load/store is misaligned
+ """
return Case(funct3[:2],
{ F3.sb: ls.eq(Constant(0)),
F3.sh: ls.eq(load_store_address_low_2[0] != 0),
for f in [F3.csrrc, F3.csrrci]: c[f] = ~written_value & previous_value
return Case(funct3, c)
- def get_fetch_action(self, ft, dc, load_store_misaligned, mi,
- branch_taken, misaligned_jump_target,
- csr_op_is_valid):
+ def handle_trap(self, m, ms, ft, dc, load_store_misaligned):
+ s = [ms.mpie.eq(ms.mie),
+ ms.mie.eq(0),
+ m.mepc.eq(Mux(ft.action == FA.noerror_trap,
+ ft.output_pc + 4,
+ ft.output_pc))]
+
+ # fetch action ack trap
+ i = If(ft.action == FA.ack_trap,
+ m.mcause.eq(cause_instruction_access_fault)
+ )
+
+ # ecall/ebreak
+ i = i.Elif((dc.act & DA.trap_ecall_ebreak) != 0,
+ m.mcause.eq(Mux(dc.immediate[0],
+ cause_machine_environment_call,
+ cause_breakpoint))
+ )
+
+ # load
+ i = i.Elif((dc.act & DA.load) != 0,
+ If(load_store_misaligned,
+ m.mcause.eq(cause_load_address_misaligned)
+ ).Else(
+ m.mcause.eq(cause_load_access_fault)
+ )
+ )
+
+ # store
+ i = i.Elif((dc.act & DA.store) != 0,
+ If(load_store_misaligned,
+ m.mcause.eq(cause_store_amo_address_misaligned)
+ ).Else(
+ m.mcause.eq(cause_store_amo_access_fault)
+ )
+ )
+
+ # jal/jalr -> misaligned=error, otherwise jump
+ i = i.Elif((dc.act & (DA.jal | DA.jalr | DA.branch)) != 0,
+ m.mcause.eq(cause_instruction_address_misaligned)
+ )
+
+ # defaults to illegal instruction
+ i = i.Else(m.mcause.eq(cause_illegal_instruction))
+
+ s.append(i)
+ return s
+
+ def get_csr_op_is_valid(self, csr_op_is_valid, csr_number,
+ csr_reads, csr_writes):
+ """ determines if a CSR is valid
+ """
c = {}
- """
- case(fetch_output_state)
- `fetch_output_state_empty:
- get_fetch_action = `fetch_action_default;
- `fetch_output_state_trap:
- get_fetch_action = `fetch_action_ack_trap;
- `fetch_output_state_valid: begin
- if((decode_action & `decode_action_trap_illegal_instruction) != 0) begin
- get_fetch_action = `fetch_action_error_trap;
- end
- else if((decode_action & `decode_action_trap_ecall_ebreak) != 0) begin
- get_fetch_action = `fetch_action_noerror_trap;
- end
- else if((decode_action & (`decode_action_load | `decode_action_store)) != 0) begin
- if(load_store_misaligned | ~memory_interface_rw_address_valid) begin
- get_fetch_action = `fetch_action_error_trap;
- end
- else if(memory_interface_rw_wait) begin
- get_fetch_action = `fetch_action_wait;
- end
- else begin
- get_fetch_action = `fetch_action_default;
- end
- end
- else if((decode_action & `decode_action_fence_i) != 0) begin
- get_fetch_action = `fetch_action_fence;
- end
- else if((decode_action & `decode_action_branch) != 0) begin
- if(branch_taken) begin
- if(misaligned_jump_target) begin
- get_fetch_action = `fetch_action_error_trap;
- end
- else begin
- get_fetch_action = `fetch_action_jump;
- end
- end
- else
- begin
- get_fetch_action = `fetch_action_default;
- end
- end
- else if((decode_action & (`decode_action_jal | `decode_action_jalr)) != 0) begin
- if(misaligned_jump_target) begin
- get_fetch_action = `fetch_action_error_trap;
- end
- else begin
- get_fetch_action = `fetch_action_jump;
- end
- end
- else if((decode_action & `decode_action_csr) != 0) begin
- if(csr_op_is_valid)
- get_fetch_action = `fetch_action_default;
- else
- get_fetch_action = `fetch_action_error_trap;
- end
- else begin
- get_fetch_action = `fetch_action_default;
- end
- end
- default:
- get_fetch_action = 32'hXXXXXXXX;
- endcase
- end
- endfunction
- """
+ # invalid csrs
+ for f in [csr_ustatus, csr_fflags, csr_frm, csr_fcsr,
+ csr_uie, csr_utvec, csr_uscratch, csr_uepc,
+ csr_ucause, csr_utval, csr_uip, csr_sstatus,
+ csr_sedeleg, csr_sideleg, csr_sie, csr_stvec,
+ csr_scounteren, csr_sscratch, csr_sepc, csr_scause,
+ csr_stval, csr_sip, csr_satp, csr_medeleg,
+ csr_mideleg, csr_dcsr, csr_dpc, csr_dscratch]:
+ c[f] = csr_op_is_valid.eq(0)
+
+ # not-writeable -> ok
+ for f in [csr_cycle, csr_time, csr_instret, csr_cycleh,
+ csr_timeh, csr_instreth, csr_mvendorid, csr_marchid,
+ csr_mimpid, csr_mhartid]:
+ c[f] = csr_op_is_valid.eq(~csr_writes)
+
+ # valid csrs
+ for f in [csr_misa, csr_mstatus, csr_mie, csr_mtvec,
+ csr_mscratch, csr_mepc, csr_mcause, csr_mip]:
+ c[f] = csr_op_is_valid.eq(1)
+
+ # not implemented / default
+ for f in [csr_mcounteren, csr_mtval, csr_mcycle, csr_minstret,
+ csr_mcycleh, csr_minstreth, "default"]:
+ c[f] = csr_op_is_valid.eq(0)
+
+ return Case(csr_number, c)
def __init__(self):
self.clk = ClockSignal()
self.comb += loaded_value.eq(Cat(b0, b1, b2))
self.comb += mi.rw_active.eq(~self.reset
- & (ft.output_state == fetch_output_state_valid)
+ & (ft.output_state == FOS.valid)
& ~load_store_misaligned
& ((dc.act & (DA.load | DA.store)) != 0))
csr_op_is_valid = Signal()
+ self.comb += ft.get_fetch_action(dc, load_store_misaligned, mi,
+ branch_taken, misaligned_jump_target,
+ csr_op_is_valid)
+
+ #self.comb += self.handle_trap(m, mstatus, ft, dc, load_store_misaligned)
+ # CSR decoding
+ csr_number = Signal(12)
+ csr_input_value = Signal(32)
+ csr_reads = Signal()
+ csr_writes = Signal()
+
+ self.comb += csr_number.eq(dc.immediate)
+ self.comb += csr_input_value.eq(Mux(dc.funct3[2],
+ dc.rs1,
+ register_rs1))
+ self.comb += csr_reads.eq(dc.funct3[1] | (dc.rd != 0))
+ self.comb += csr_writes.eq(~dc.funct3[1] | (dc.rs1 != 0))
+
+ self.comb += self.get_csr_op_is_valid(csr_op_is_valid, csr_number,
+ csr_reads, csr_writes)
+
if __name__ == "__main__":
example = CPU()
print(verilog.convert(example,
"""
- function `fetch_action get_fetch_action(
- input `fetch_output_state fetch_output_state,
- input `decode_action decode_action,
- input load_store_misaligned,
- input memory_interface_rw_address_valid,
- input memory_interface_rw_wait,
- input branch_taken,
- input misaligned_jump_target,
- input csr_op_is_valid
- );
- begin
- case(fetch_output_state)
- `fetch_output_state_empty:
- get_fetch_action = `fetch_action_default;
- `fetch_output_state_trap:
- get_fetch_action = `fetch_action_ack_trap;
- `fetch_output_state_valid: begin
- if((decode_action & `decode_action_trap_illegal_instruction) != 0) begin
- get_fetch_action = `fetch_action_error_trap;
- end
- else if((decode_action & `decode_action_trap_ecall_ebreak) != 0) begin
- get_fetch_action = `fetch_action_noerror_trap;
- end
- else if((decode_action & (`decode_action_load | `decode_action_store)) != 0) begin
- if(load_store_misaligned | ~memory_interface_rw_address_valid) begin
- get_fetch_action = `fetch_action_error_trap;
- end
- else if(memory_interface_rw_wait) begin
- get_fetch_action = `fetch_action_wait;
- end
- else begin
- get_fetch_action = `fetch_action_default;
- end
- end
- else if((decode_action & `decode_action_fence_i) != 0) begin
- get_fetch_action = `fetch_action_fence;
- end
- else if((decode_action & `decode_action_branch) != 0) begin
- if(branch_taken) begin
- if(misaligned_jump_target) begin
- get_fetch_action = `fetch_action_error_trap;
- end
- else begin
- get_fetch_action = `fetch_action_jump;
- end
- end
- else
- begin
- get_fetch_action = `fetch_action_default;
- end
- end
- else if((decode_action & (`decode_action_jal | `decode_action_jalr)) != 0) begin
- if(misaligned_jump_target) begin
- get_fetch_action = `fetch_action_error_trap;
- end
- else begin
- get_fetch_action = `fetch_action_jump;
- end
- end
- else if((decode_action & `decode_action_csr) != 0) begin
- if(csr_op_is_valid)
- get_fetch_action = `fetch_action_default;
- else
- get_fetch_action = `fetch_action_error_trap;
- end
- else begin
- get_fetch_action = `fetch_action_default;
- end
- end
- default:
- get_fetch_action = 32'hXXXXXXXX;
- endcase
- end
- endfunction
-
- assign fetch_action = get_fetch_action(
- fetch_output_state,
- decode_action,
- load_store_misaligned,
- memory_interface_rw_address_valid,
- memory_interface_rw_wait,
- branch_taken,
- misaligned_jump_target,
- csr_op_is_valid
- );
-
- task handle_trap;
- begin
- mstatus_mpie = mstatus_mie;
- mstatus_mie = 0;
- mepc = (fetch_action == `fetch_action_noerror_trap) ? fetch_output_pc + 4 : fetch_output_pc;
- if(fetch_action == `fetch_action_ack_trap) begin
- mcause = `cause_instruction_access_fault;
- end
- else if((decode_action & `decode_action_trap_illegal_instruction) != 0) begin
- mcause = `cause_illegal_instruction;
- end
- else if((decode_action & `decode_action_trap_ecall_ebreak) != 0) begin
- mcause = decoder_immediate[0] ? `cause_machine_environment_call : `cause_breakpoint;
- end
- else if((decode_action & `decode_action_load) != 0) begin
- if(load_store_misaligned)
- mcause = `cause_load_address_misaligned;
- else
- mcause = `cause_load_access_fault;
- end
- else if((decode_action & `decode_action_store) != 0) begin
- if(load_store_misaligned)
- mcause = `cause_store_amo_address_misaligned;
- else
- mcause = `cause_store_amo_access_fault;
- end
- else if((decode_action & (`decode_action_branch | `decode_action_jal | `decode_action_jalr)) != 0) begin
- mcause = `cause_instruction_address_misaligned;
- end
- else begin
- mcause = `cause_illegal_instruction;
- end
- end
- endtask
-
- wire [11:0] csr_number = decoder_immediate;
- wire [31:0] csr_input_value = decoder_funct3[2] ? decoder_rs1 : register_rs1;
- wire csr_reads = decoder_funct3[1] | (decoder_rd != 0);
- wire csr_writes = ~decoder_funct3[1] | (decoder_rs1 != 0);
-
- function get_csr_op_is_valid(input [11:0] csr_number, input csr_reads, input csr_writes);
- begin
- case(csr_number)
- `csr_ustatus,
- `csr_fflags,
- `csr_frm,
- `csr_fcsr,
- `csr_uie,
- `csr_utvec,
- `csr_uscratch,
- `csr_uepc,
- `csr_ucause,
- `csr_utval,
- `csr_uip,
- `csr_sstatus,
- `csr_sedeleg,
- `csr_sideleg,
- `csr_sie,
- `csr_stvec,
- `csr_scounteren,
- `csr_sscratch,
- `csr_sepc,
- `csr_scause,
- `csr_stval,
- `csr_sip,
- `csr_satp,
- `csr_medeleg,
- `csr_mideleg,
- `csr_dcsr,
- `csr_dpc,
- `csr_dscratch:
- get_csr_op_is_valid = 0;
- `csr_cycle,
- `csr_time,
- `csr_instret,
- `csr_cycleh,
- `csr_timeh,
- `csr_instreth,
- `csr_mvendorid,
- `csr_marchid,
- `csr_mimpid,
- `csr_mhartid:
- get_csr_op_is_valid = ~csr_writes;
- `csr_misa,
- `csr_mstatus,
- `csr_mie,
- `csr_mtvec,
- `csr_mscratch,
- `csr_mepc,
- `csr_mcause,
- `csr_mip:
- get_csr_op_is_valid = 1;
- `csr_mcounteren,
- `csr_mtval,
- `csr_mcycle,
- `csr_minstret,
- `csr_mcycleh,
- `csr_minstreth:
- // TODO: CSRs not implemented yet
- get_csr_op_is_valid = 0;
- endcase
- end
- endfunction
-
- assign csr_op_is_valid = get_csr_op_is_valid(csr_number, csr_reads, csr_writes);
-
wire [63:0] cycle_counter = 0; // TODO: implement cycle_counter
wire [63:0] time_counter = 0; // TODO: implement time_counter
wire [63:0] instret_counter = 0; // TODO: implement instret_counter