+class MStatus:
+ def __init__(self, comb, sync):
+ self.comb = comb
+ self.sync = sync
+ self.mpie = Signal(name="mstatus_mpie")
+ self.mie = Signal(name="mstatus_mie")
+ self.mprv = Signal(name="mstatus_mprv")
+ self.tsr = Signal(name="mstatus_tsr")
+ self.tw = Signal(name="mstatus_tw")
+ self.tvm = Signal(name="mstatus_tvm")
+ self.mxr = Signal(name="mstatus_mxr")
+ self._sum = Signal(name="mstatus_sum")
+ self.xs = Signal(name="mstatus_xs")
+ self.fs = Signal(name="mstatus_fs")
+ self.mpp = Signal(2, name="mstatus_mpp")
+ self.spp = Signal(name="mstatus_spp")
+ self.spie = Signal(name="mstatus_spie")
+ self.upie = Signal(name="mstatus_upie")
+ self.sie = Signal(name="mstatus_sie")
+ self.uie = Signal(name="mstatus_uie")
+
+ for n in dir(self):
+ if n in ['make', 'mpp', 'comb', 'sync'] or n.startswith("_"):
+ continue
+ self.comb += getattr(self, n).eq(0x0)
+ self.comb += self.mpp.eq(0b11)
+
+ self.sync += self.mie.eq(0)
+ self.sync += self.mpie.eq(0)
+
+ def make(self):
+ return Cat(
+ self.uie, self.sie, Constant(0), self.mie,
+ self.upie, self.spie, Constant(0), self.mpie,
+ self.spp, Constant(0, 2), self.mpp,
+ self.fs, self.xs, self.mprv, self._sum,
+ self.mxr, self.tvm, self.tw, self.tsr,
+ Constant(0, 8),
+ (self.xs == Constant(0b11, 2)) | (self.fs == Constant(0b11, 2))
+ )
+
+
+class MIE:
+ def __init__(self, comb, sync):
+ self.comb = comb
+ self.sync = sync
+ self.meie = Signal(name="mie_meie")
+ self.mtie = Signal(name="mie_mtie")
+ self.msie = Signal(name="mie_msie")
+ self.ueie = Signal(name="mie_ueie")
+ self.stie = Signal(name="mie_stie")
+ self.utie = Signal(name="mie_utie")
+ self.ssie = Signal(name="mie_ssie")
+ self.usie = Signal(name="mie_usie")
+
+ for n in dir(self):
+ if n in ['make', 'comb', 'sync'] or n.startswith("_"):
+ continue
+ self.comb += getattr(self, n).eq(0x0)
+
+ self.sync += self.meie.eq(0)
+ self.sync += self.mtie.eq(0)
+ self.sync += self.msie.eq(0)
+
+class MIP:
+ def __init__(self, comb, sync):
+ self.comb = comb
+ self.sync = sync
+ self.meip = Signal(name="mip_meip") # TODO: implement ext interrupts
+ self.seip = Signal(name="mip_seip")
+ self.ueip = Signal(name="mip_uiep")
+ self.mtip = Signal(name="mip_mtip") # TODO: implement timer interrupts
+ self.stip = Signal(name="mip_stip")
+ self.msip = Signal(name="mip_stip")
+ self.utip = Signal(name="mip_utip")
+ self.ssip = Signal(name="mip_ssip")
+ self.usip = Signal(name="mip_usip")
+
+ for n in dir(self):
+ if n in ['comb', 'sync'] or n.startswith("_"):
+ continue
+ self.comb += getattr(self, n).eq(0x0)
+
+
+class M:
+ def __init__(self, comb, sync):
+ self.comb = comb
+ self.sync = sync
+ self.mcause = Signal(32)
+ self.mepc = Signal(32)
+ self.mscratch = Signal(32)
+ self.sync += self.mcause.eq(0)
+ 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.sync = sync
+ self.misa = Signal(32)
+ cl = []
+ for l in list(string.ascii_lowercase):
+ value = 1 if l == 'i' else 0
+ cl.append(Constant(value))
+ cl.append(Constant(0, 4))
+ cl.append(Constant(0b01, 2))
+ self.comb += self.misa.eq(Cat(cl))
+
+
+class Fetch:
+ def __init__(self, comb, sync):
+ self.comb = comb
+ self.sync = sync
+ self.action = Signal(fetch_action, name="fetch_action")
+ self.target_pc = Signal(32, name="fetch_target_pc")
+ self.output_pc = Signal(32, name="fetch_output_pc")
+ 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 CSR:
+ def __init__(self, comb, sync, dc, register_rs1):
+ self.comb = comb
+ self.sync = sync
+ self.number = Signal(12, name="csr_number")
+ self.input_value = Signal(32, name="csr_input_value")
+ self.reads = Signal(name="csr_reads")
+ self.writes = Signal(name="csr_writes")
+ self.op_is_valid = Signal(name="csr_op_is_valid")
+
+ self.comb += self.number.eq(dc.immediate)
+ self.comb += self.input_value.eq(Mux(dc.funct3[2],
+ dc.rs1,
+ register_rs1))
+ self.comb += self.reads.eq(dc.funct3[1] | (dc.rd != 0))
+ self.comb += self.writes.eq(~dc.funct3[1] | (dc.rs1 != 0))
+
+ self.comb += self.get_csr_op_is_valid()
+
+ def get_csr_op_is_valid(self):
+ """ determines if a CSR is valid
+ """
+ c = {}
+ # 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] = self.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] = self.op_is_valid.eq(~self.writes)
+
+ # valid csrs
+ for f in [csr_misa, csr_mstatus, csr_mie, csr_mtvec,
+ csr_mscratch, csr_mepc, csr_mcause, csr_mip]:
+ c[f] = self.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] = self.op_is_valid.eq(0)
+
+ return Case(self.number, c)
+
+ def evaluate_csr_funct3_op(self, funct3, previous_value, written_value):
+ c = { "default": Constant(0, 32)}
+ for f in [F3.csrrw, F3.csrrwi]: c[f] = written_value
+ for f in [F3.csrrs, F3.csrrsi]: c[f] = written_value | previous_value
+ for f in [F3.csrrc, F3.csrrci]: c[f] = ~written_value & previous_value
+ return Case(funct3, c)
+
+
+class MInfo:
+ def __init__(self, comb):
+ self.comb = comb
+ # TODO
+ self.cycle_counter = Signal(64); # TODO: implement cycle_counter
+ self.time_counter = Signal(64); # TODO: implement time_counter
+ self.instret_counter = Signal(64); # TODO: implement instret_counter
+
+ self.mvendorid = Signal(32)
+ self.marchid = Signal(32)
+ self.mimpid = Signal(32)
+ self.mhartid = Signal(32)
+ self.comb += self.mvendorid.eq(Constant(0, 32))
+ self.comb += self.marchid.eq(Constant(0, 32))
+ self.comb += self.mimpid.eq(Constant(0, 32))
+ self.comb += self.mhartid.eq(Constant(0, 32))
+