+ def main_block(self, mtvec, mip, minfo, misa, csr, mi, m, mstatus, mie,
+ ft, dc,
+ load_store_misaligned,
+ loaded_value, alu_result,
+ lui_auipc_result):
+ c = {}
+ c[FOS.empty] = []
+ c[FOS.trap] = self.handle_trap(m, mstatus, ft, dc,
+ load_store_misaligned)
+ c[FOS.valid] = self.handle_valid(mtvec, mip, minfo, misa, csr, mi, m,
+ mstatus, mie, ft, dc,
+ load_store_misaligned,
+ loaded_value,
+ alu_result,
+ lui_auipc_result)
+ return Case(ft.output_state, c)
+
+ def write_register(self, rd, val):
+ return [self.regs.rd.eq(rd),
+ self.regs.wval.eq(val),
+ self.regs.w_en.eq(1)
+ ]
+
+ def handle_valid(self, mtvec, mip, minfo, misa, csr, mi, m, mstatus, mie,
+ ft, dc,
+ load_store_misaligned,
+ loaded_value, alu_result,
+ lui_auipc_result):
+ # fetch action ack trap
+ i = If((ft.action == FA.ack_trap) | (ft.action == FA.noerror_trap),
+ [self.handle_trap(m, mstatus, ft, dc,
+ load_store_misaligned),
+ self.regs.w_en.eq(0) # no writing to registers
+ ]
+ )
+
+ # load
+ i = i.Elif((dc.act & DA.load) != 0,
+ If(~mi.rw_wait,
+ self.write_register(dc.rd, loaded_value)
+ )
+ )
+
+ # op or op_immediate
+ i = i.Elif((dc.act & DA.op_op_imm) != 0,
+ self.write_register(dc.rd, alu_result)
+ )
+
+ # lui or auipc
+ i = i.Elif((dc.act & DA.lui_auipc) != 0,
+ self.write_register(dc.rd, lui_auipc_result)
+ )
+
+ # jal/jalr
+ i = i.Elif((dc.act & (DA.jal | DA.jalr)) != 0,
+ self.write_register(dc.rd, ft.output_pc + 4)
+ )
+
+ i = i.Elif((dc.act & DA.csr) != 0,
+ self.handle_csr(mtvec, mip, minfo, misa, mstatus, mie, m,
+ dc, csr)
+ )
+
+ # fence, store, branch
+ i = i.Elif((dc.act & (DA.fence | DA.fence_i |
+ DA.store | DA.branch)) != 0,
+ # do nothing
+ self.regs.w_en.eq(0) # no writing to registers
+ )
+
+ return i
+
+ def handle_csr(self, mtvec, mip, minfo, misa, mstatus, mie, m, dc, csr):
+ csr_output_value = Signal(32)
+ csr_written_value = Signal(32)
+ c = {}
+
+ # cycle
+ c[csr_cycle] = csr_output_value.eq(minfo.cycle_counter[0:32])
+ c[csr_cycleh] = csr_output_value.eq(minfo.cycle_counter[32:64])
+ # time
+ c[csr_time] = csr_output_value.eq(minfo.time_counter[0:32])
+ c[csr_timeh] = csr_output_value.eq(minfo.time_counter[32:64])
+ # instret
+ c[csr_instret] = csr_output_value.eq(minfo.instret_counter[0:32])
+ c[csr_instreth] = csr_output_value.eq(minfo.instret_counter[32:64])
+ # mvendorid/march/mimpl/mhart
+ c[csr_mvendorid] = csr_output_value.eq(minfo.mvendorid)
+ c[csr_marchid ] = csr_output_value.eq(minfo.marchid )
+ c[csr_mimpid ] = csr_output_value.eq(minfo.mimpid )
+ c[csr_mhartid ] = csr_output_value.eq(minfo.mhartid )
+ # misa
+ c[csr_misa ] = csr_output_value.eq(misa.misa)
+ # mstatus
+ c[csr_mstatus ] = [
+ csr_output_value.eq(mstatus.make()),
+ csr.evaluate_csr_funct3_op(dc.funct3, csr_output_value,
+ csr_written_value),
+ mstatus.mpie.eq(csr_written_value[7]),
+ mstatus.mie.eq(csr_written_value[3])
+ ]
+ # mie
+ c[csr_mie ] = [
+ csr_output_value.eq(mie.make()),
+ csr.evaluate_csr_funct3_op(dc.funct3, csr_output_value,
+ csr_written_value),
+ mie.meie.eq(csr_written_value[11]),
+ mie.mtie.eq(csr_written_value[7]),
+ mie.msie.eq(csr_written_value[3]),
+ ]
+ # mtvec
+ c[csr_mtvec ] = csr_output_value.eq(mtvec)
+ # mscratch
+ c[csr_mscratch ] = [
+ csr_output_value.eq(m.mscratch),
+ csr.evaluate_csr_funct3_op(dc.funct3, csr_output_value,
+ csr_written_value),
+ If(csr.writes,
+ m.mscratch.eq(csr_written_value),
+ )
+ ]
+ # mepc
+ c[csr_mepc ] = [
+ csr_output_value.eq(m.mepc),
+ csr.evaluate_csr_funct3_op(dc.funct3, csr_output_value,
+ csr_written_value),
+ If(csr.writes,
+ m.mepc.eq(csr_written_value),
+ )
+ ]
+
+ # mcause
+ c[csr_mcause ] = [
+ csr_output_value.eq(m.mcause),
+ csr.evaluate_csr_funct3_op(dc.funct3, csr_output_value,
+ csr_written_value),
+ If(csr.writes,
+ m.mcause.eq(csr_written_value),
+ )
+ ]
+
+ # mip
+ c[csr_mip ] = [
+ csr_output_value.eq(mip.make()),
+ csr.evaluate_csr_funct3_op(dc.funct3, csr_output_value,
+ csr_written_value),
+ ]
+
+ return [Case(csr.number, c),
+ If(csr.reads,
+ self.write_register(dc.rd, csr_output_value)
+ )]
+
+ """
+ `csr_mip: begin
+ csr_output_value = 0;
+ csr_output_value[11] = mip_meip;
+ csr_output_value[9] = mip_seip;
+ csr_output_value[8] = mip_ueip;
+ csr_output_value[7] = mip_mtip;
+ csr_output_value[5] = mip_stip;
+ csr_output_value[4] = mip_utip;
+ csr_output_value[3] = mip_msip;
+ csr_output_value[1] = mip_ssip;
+ csr_output_value[0] = mip_usip;
+ end
+ endcase