From 4af6717bc9b97c12fdb2dea0291c449410974c92 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Wed, 6 May 2020 13:34:28 +0100 Subject: [PATCH] remove unneeded minerva code --- src/soc/minerva/core.py | 833 ------------------ src/soc/minerva/csr.py | 94 -- src/soc/minerva/isa.py | 221 ----- src/soc/minerva/stage.py | 100 --- src/soc/minerva/test/test_units_divider.py | 243 ----- src/soc/minerva/test/test_units_multiplier.py | 261 ------ src/soc/minerva/units/adder.py | 31 - src/soc/minerva/units/compare.py | 36 - src/soc/minerva/units/decoder.py | 261 ------ src/soc/minerva/units/divider.py | 144 --- src/soc/minerva/units/exception.py | 124 --- src/soc/minerva/units/logic.py | 28 - src/soc/minerva/units/multiplier.py | 86 -- src/soc/minerva/units/shifter.py | 39 - src/soc/minerva/units/trigger.py | 109 --- 15 files changed, 2610 deletions(-) delete mode 100644 src/soc/minerva/core.py delete mode 100644 src/soc/minerva/csr.py delete mode 100644 src/soc/minerva/isa.py delete mode 100644 src/soc/minerva/stage.py delete mode 100644 src/soc/minerva/test/test_units_divider.py delete mode 100644 src/soc/minerva/test/test_units_multiplier.py delete mode 100644 src/soc/minerva/units/adder.py delete mode 100644 src/soc/minerva/units/compare.py delete mode 100644 src/soc/minerva/units/decoder.py delete mode 100644 src/soc/minerva/units/divider.py delete mode 100644 src/soc/minerva/units/exception.py delete mode 100644 src/soc/minerva/units/logic.py delete mode 100644 src/soc/minerva/units/multiplier.py delete mode 100644 src/soc/minerva/units/shifter.py delete mode 100644 src/soc/minerva/units/trigger.py diff --git a/src/soc/minerva/core.py b/src/soc/minerva/core.py deleted file mode 100644 index c270f3b2..00000000 --- a/src/soc/minerva/core.py +++ /dev/null @@ -1,833 +0,0 @@ -from functools import reduce -from operator import or_ -from itertools import tee - -from nmigen import Elaboratable, Module, Record, Mux, Const, Signal, Memory -from nmigen.lib.coding import PriorityEncoder - -from soc.minerva.stage import Stage -from soc.minerva.csr import CSRFile -from soc.minerva.units.adder import Adder -from soc.minerva.units.compare import CompareUnit -from soc.minerva.units.debug import DebugUnit -from soc.minerva.units.decoder import InstructionDecoder -from soc.minerva.units.divider import Divider, DummyDivider -from soc.minerva.units.exception import ExceptionUnit -from soc.minerva.units.fetch import BareFetchUnit, CachedFetchUnit, PCSelector -from soc.minerva.units.rvficon import RVFIController, rvfi_layout -from soc.minerva.units.loadstore import (BareLoadStoreUnit, CachedLoadStoreUnit, - DataSelector) -from soc.minerva.units.logic import LogicUnit -from soc.minerva.units.multiplier import DummyMultiplier, Multiplier -from soc.minerva.units.predict import BranchPredictor -from soc.minerva.units.shifter import Shifter -from soc.minerva.units.trigger import TriggerUnit - -from soc.minerva.units.debug.jtag import jtag_layout -from soc.minerva.wishbone import wishbone_layout - - -__all__ = ["Minerva"] - - -_af_layout = [ - ("pc", (33, True)), -] - - -_fd_layout = [ - ("pc", 32), - ("instruction", 32), - ("fetch_error", 1), - ("fetch_badaddr", 30) -] - - -_dx_layout = [ - ("pc", 32), - ("instruction", 32), - ("fetch_error", 1), - ("fetch_badaddr", 30), - ("illegal", 1), - ("rd", 5), - ("rs1", 5), - ("rd_we", 1), - ("rs1_re", 1), - ("src1", 32), - ("src2", 32), - ("immediate", 32), - ("bypass_x", 1), - ("bypass_m", 1), - ("funct3", 3), - ("load", 1), - ("store", 1), - ("adder", 1), - ("adder_sub", 1), - ("logic", 1), - ("multiply", 1), - ("divide", 1), - ("shift", 1), - ("direction", 1), - ("sext", 1), - ("jump", 1), - ("compare", 1), - ("branch", 1), - ("branch_target", 32), - ("branch_predict_taken", 1), - ("fence_i", 1), - ("csr", 1), - ("csr_adr", 12), - ("csr_we", 1), - ("ecall", 1), - ("ebreak", 1), - ("mret", 1), -] - - -_xm_layout = [ - ("pc", 32), - ("instruction", 32), - ("fetch_error", 1), - ("fetch_badaddr", 30), - ("illegal", 1), - ("loadstore_misaligned", 1), - ("ecall", 1), - ("ebreak", 1), - ("rd", 5), - ("rd_we", 1), - ("bypass_m", 1), - ("funct3", 3), - ("result", 32), - ("shift", 1), - ("load", 1), - ("store", 1), - ("store_data", 32), - ("compare", 1), - ("multiply", 1), - ("divide", 1), - ("condition_met", 1), - ("branch_target", 32), - ("branch_taken", 1), - ("branch_predict_taken", 1), - ("csr", 1), - ("csr_adr", 12), - ("csr_we", 1), - ("csr_result", 32), - ("mret", 1), - ("exception", 1) -] - - -_mw_layout = [ - ("pc", 32), - ("rd", 5), - ("rd_we", 1), - ("funct3", 3), - ("result", 32), - ("load", 1), - ("load_data", 32), - ("multiply", 1), - ("exception", 1) -] - - -class Minerva(Elaboratable): - def __init__(self, reset_address=0x00000000, - with_icache=False, - icache_nways=1, icache_nlines=256, icache_nwords=8, icache_base=0, icache_limit=2**31, - with_dcache=False, - dcache_nways=1, dcache_nlines=256, dcache_nwords=8, dcache_base=0, dcache_limit=2**31, - with_muldiv=False, - with_debug=False, - with_trigger=False, nb_triggers=8, - with_rvfi=False): - self.external_interrupt = Signal(32) - self.timer_interrupt = Signal() - self.software_interrupt = Signal() - self.ibus = Record(wishbone_layout) - self.dbus = Record(wishbone_layout) - - if with_debug: - self.jtag = Record(jtag_layout) - - if with_rvfi: - self.rvfi = Record(rvfi_layout) - - self.reset_address = reset_address - self.with_icache = with_icache - self.icache_args = icache_nways, icache_nlines, icache_nwords, icache_base, icache_limit - self.with_dcache = with_dcache - self.dcache_args = dcache_nways, dcache_nlines, dcache_nwords, dcache_base, dcache_limit - self.with_muldiv = with_muldiv - self.with_debug = with_debug - self.with_trigger = with_trigger - self.nb_triggers = nb_triggers - self.with_rvfi = with_rvfi - - def elaborate(self, platform): - cpu = Module() - - # pipeline stages - - a = cpu.submodules.a = Stage(None, _af_layout) - f = cpu.submodules.f = Stage(_af_layout, _fd_layout) - d = cpu.submodules.d = Stage(_fd_layout, _dx_layout) - x = cpu.submodules.x = Stage(_dx_layout, _xm_layout) - m = cpu.submodules.m = Stage(_xm_layout, _mw_layout) - w = cpu.submodules.w = Stage(_mw_layout, None) - stages = a, f, d, x, m, w - - sources, sinks = tee(stages) - next(sinks) - for s1, s2 in zip(sources, sinks): - cpu.d.comb += s1.source.connect(s2.sink) - - a.source.pc.reset = self.reset_address - 4 - cpu.d.comb += a.valid.eq(Const(1)) - - # units - - pc_sel = cpu.submodules.pc_sel = PCSelector() - data_sel = cpu.submodules.data_sel = DataSelector() - adder = cpu.submodules.adder = Adder() - compare = cpu.submodules.compare = CompareUnit() - decoder = cpu.submodules.decoder = InstructionDecoder(self.with_muldiv) - exception = cpu.submodules.exception = ExceptionUnit() - logic = cpu.submodules.logic = LogicUnit() - predict = cpu.submodules.predict = BranchPredictor() - shifter = cpu.submodules.shifter = Shifter() - - if self.with_icache: - fetch = cpu.submodules.fetch = CachedFetchUnit(*self.icache_args) - else: - fetch = cpu.submodules.fetch = BareFetchUnit() - - if self.with_dcache: - loadstore = cpu.submodules.loadstore = CachedLoadStoreUnit( - *self.dcache_args) - else: - loadstore = cpu.submodules.loadstore = BareLoadStoreUnit() - - if self.with_muldiv: - multiplier = Multiplier() if not self.with_rvfi else DummyMultiplier() - divider = Divider() if not self.with_rvfi else DummyDivider() - cpu.submodules.multiplier = multiplier - cpu.submodules.divider = divider - - if self.with_debug: - debug = cpu.submodules.debug = DebugUnit() - - if self.with_trigger: - trigger = cpu.submodules.trigger = TriggerUnit(self.nb_triggers) - - if self.with_rvfi: - rvficon = cpu.submodules.rvficon = RVFIController() - - # register files - - gprf = Memory(width=32, depth=32) - gprf_rp1 = gprf.read_port() - gprf_rp2 = gprf.read_port() - gprf_wp = gprf.write_port() - cpu.submodules += gprf_rp1, gprf_rp2, gprf_wp - - csrf = cpu.submodules.csrf = CSRFile() - csrf_rp = csrf.read_port() - csrf_wp = csrf.write_port() - - csrf.add_csrs(exception.iter_csrs()) - if self.with_debug: - csrf.add_csrs(debug.iter_csrs()) - if self.with_trigger: - csrf.add_csrs(trigger.iter_csrs()) - - # pipeline logic - - cpu.d.comb += [ - pc_sel.f_pc.eq(f.sink.pc), - pc_sel.d_pc.eq(d.sink.pc), - pc_sel.d_branch_predict_taken.eq( - predict.d_branch_taken & ~predict.d_fetch_misaligned), - pc_sel.d_branch_target.eq(predict.d_branch_target), - pc_sel.d_valid.eq(d.valid), - pc_sel.x_pc.eq(x.sink.pc), - pc_sel.x_fence_i.eq(x.sink.fence_i), - pc_sel.x_valid.eq(x.valid), - pc_sel.m_branch_predict_taken.eq(m.sink.branch_predict_taken), - pc_sel.m_branch_taken.eq(m.sink.branch_taken), - pc_sel.m_branch_target.eq(m.sink.branch_target), - pc_sel.m_exception.eq(exception.m_raise), - pc_sel.m_mret.eq(m.sink.mret), - pc_sel.m_valid.eq(m.valid), - pc_sel.mtvec_r_base.eq(exception.mtvec.r.base), - pc_sel.mepc_r_base.eq(exception.mepc.r.base) - ] - - cpu.d.comb += [ - fetch.a_pc.eq(pc_sel.a_pc), - fetch.a_stall.eq(a.stall), - fetch.a_valid.eq(a.valid), - fetch.f_stall.eq(f.stall), - fetch.f_valid.eq(f.valid), - fetch.ibus.connect(self.ibus) - ] - - m.stall_on(fetch.a_busy & a.valid) - m.stall_on(fetch.f_busy & f.valid) - - if self.with_icache: - flush_icache = x.sink.fence_i & x.valid & ~x.stall - if self.with_debug: - flush_icache |= debug.resumereq - - cpu.d.comb += [ - fetch.a_flush.eq(flush_icache), - fetch.f_pc.eq(f.sink.pc) - ] - - cpu.d.comb += [ - decoder.instruction.eq(d.sink.instruction) - ] - - if self.with_debug: - with cpu.If(debug.halt & debug.halted): - cpu.d.comb += gprf_rp1.addr.eq(debug.gprf_addr) - with cpu.Elif(~d.stall): - cpu.d.comb += gprf_rp1.addr.eq(fetch.f_instruction[15:20]) - with cpu.Else(): - cpu.d.comb += gprf_rp1.addr.eq(decoder.rs1) - - cpu.d.comb += debug.gprf_dat_r.eq(gprf_rp1.data) - else: - with cpu.If(~d.stall): - cpu.d.comb += gprf_rp1.addr.eq(fetch.f_instruction[15:20]) - with cpu.Else(): - cpu.d.comb += gprf_rp1.addr.eq(decoder.rs1) - - with cpu.If(~d.stall): - cpu.d.comb += gprf_rp2.addr.eq(fetch.f_instruction[20:25]) - with cpu.Else(): - cpu.d.comb += gprf_rp2.addr.eq(decoder.rs2) - - with cpu.If(~f.stall): - cpu.d.sync += csrf_rp.addr.eq(fetch.f_instruction[20:32]) - cpu.d.comb += csrf_rp.en.eq(decoder.csr & d.valid) - - # CSR set/clear instructions are translated to logic operations. - x_csr_set_clear = x.sink.funct3[1] - x_csr_clear = x_csr_set_clear & x.sink.funct3[0] - x_csr_fmt_i = x.sink.funct3[2] - x_csr_src1 = Mux(x_csr_fmt_i, x.sink.rs1, x.sink.src1) - x_csr_src1 = Mux(x_csr_clear, ~x_csr_src1, x_csr_src1) - x_csr_logic_op = x.sink.funct3 | 0b100 - - cpu.d.comb += [ - logic.op.eq(Mux(x.sink.csr, x_csr_logic_op, x.sink.funct3)), - logic.src1.eq(Mux(x.sink.csr, x_csr_src1, x.sink.src1)), - logic.src2.eq(x.sink.src2) - ] - - cpu.d.comb += [ - adder.sub.eq(x.sink.adder & x.sink.adder_sub | - x.sink.compare | x.sink.branch), - adder.src1.eq(x.sink.src1), - adder.src2.eq(Mux(x.sink.store, x.sink.immediate, x.sink.src2)) - ] - - if self.with_muldiv: - cpu.d.comb += [ - multiplier.x_op.eq(x.sink.funct3), - multiplier.x_src1.eq(x.sink.src1), - multiplier.x_src2.eq(x.sink.src2), - multiplier.x_stall.eq(x.stall), - multiplier.m_stall.eq(m.stall) - ] - - cpu.d.comb += [ - divider.x_op.eq(x.sink.funct3), - divider.x_src1.eq(x.sink.src1), - divider.x_src2.eq(x.sink.src2), - divider.x_valid.eq(x.sink.valid), - divider.x_stall.eq(x.stall) - ] - - m.stall_on(divider.m_busy) - - cpu.d.comb += [ - shifter.x_direction.eq(x.sink.direction), - shifter.x_sext.eq(x.sink.sext), - shifter.x_shamt.eq(x.sink.src2), - shifter.x_src1.eq(x.sink.src1), - shifter.x_stall.eq(x.stall) - ] - - cpu.d.comb += [ - # compare.op is shared by compare and branch instructions. - compare.op.eq( - Mux(x.sink.compare, x.sink.funct3 << 1, x.sink.funct3)), - compare.zero.eq(x.sink.src1 == x.sink.src2), - compare.negative.eq(adder.result[-1]), - compare.overflow.eq(adder.overflow), - compare.carry.eq(adder.carry) - ] - - cpu.d.comb += [ - exception.external_interrupt.eq(self.external_interrupt), - exception.timer_interrupt.eq(self.timer_interrupt), - exception.software_interrupt.eq(self.software_interrupt), - exception.m_fetch_misaligned.eq( - m.sink.branch_taken & m.sink.branch_target[:2].bool()), - exception.m_fetch_error.eq(m.sink.fetch_error), - exception.m_fetch_badaddr.eq(m.sink.fetch_badaddr), - exception.m_load_misaligned.eq( - m.sink.load & m.sink.loadstore_misaligned), - exception.m_load_error.eq(loadstore.m_load_error), - exception.m_store_misaligned.eq( - m.sink.store & m.sink.loadstore_misaligned), - exception.m_store_error.eq(loadstore.m_store_error), - exception.m_loadstore_badaddr.eq(loadstore.m_badaddr), - exception.m_branch_target.eq(m.sink.branch_target), - exception.m_illegal.eq(m.sink.illegal), - exception.m_ecall.eq(m.sink.ecall), - exception.m_pc.eq(m.sink.pc), - exception.m_instruction.eq(m.sink.instruction), - exception.m_result.eq(m.sink.result), - exception.m_mret.eq(m.sink.mret), - exception.m_stall.eq(m.sink.stall), - exception.m_valid.eq(m.valid) - ] - - m_ebreak = m.sink.ebreak - if self.with_debug: - # If dcsr.ebreakm is set, EBREAK instructions enter Debug Mode. - # We do not want to raise an exception in this case because Debug Mode - # should be invisible to software execution. - m_ebreak &= ~debug.dcsr_ebreakm - if self.with_trigger: - m_ebreak |= trigger.trap - cpu.d.comb += exception.m_ebreak.eq(m_ebreak) - - m.kill_on(m.source.exception & m.source.valid) - - cpu.d.comb += [ - data_sel.x_offset.eq(adder.result[:2]), - data_sel.x_funct3.eq(x.sink.funct3), - data_sel.x_store_operand.eq(x.sink.src2), - data_sel.w_offset.eq(w.sink.result[:2]), - data_sel.w_funct3.eq(w.sink.funct3), - data_sel.w_load_data.eq(w.sink.load_data) - ] - - cpu.d.comb += [ - loadstore.x_addr.eq(adder.result), - loadstore.x_mask.eq(data_sel.x_mask), - loadstore.x_load.eq(x.sink.load), - loadstore.x_store.eq(x.sink.store), - loadstore.x_store_data.eq(data_sel.x_store_data), - loadstore.x_stall.eq(x.stall), - loadstore.x_valid.eq(x.valid), - loadstore.m_stall.eq(m.stall), - loadstore.m_valid.eq(m.valid) - ] - - m.stall_on(loadstore.x_busy & x.valid) - m.stall_on(loadstore.m_busy & m.valid) - - if self.with_dcache: - if self.with_debug: - cpu.d.comb += loadstore.x_flush.eq(debug.resumereq) - - cpu.d.comb += [ - loadstore.x_fence_i.eq(x.sink.fence_i), - loadstore.m_addr.eq(m.sink.result), - loadstore.m_load.eq(m.sink.load), - loadstore.m_store.eq(m.sink.store), - ] - - x.stall_on(loadstore.x_busy & x.valid) - - for s in a, f: - s.kill_on(x.sink.fence_i & x.valid) - - if self.with_debug: - with cpu.If(debug.halt & debug.halted): - cpu.d.comb += debug.dbus.connect(self.dbus) - with cpu.Else(): - cpu.d.comb += loadstore.dbus.connect(self.dbus) - else: - cpu.d.comb += loadstore.dbus.connect(self.dbus) - - # RAW hazard management - - x_raw_rs1 = Signal() - m_raw_rs1 = Signal() - w_raw_rs1 = Signal() - x_raw_rs2 = Signal() - m_raw_rs2 = Signal() - w_raw_rs2 = Signal() - - x_raw_csr = Signal() - m_raw_csr = Signal() - - x_lock = Signal() - m_lock = Signal() - - cpu.d.comb += [ - x_raw_rs1.eq((x.sink.rd != 0) & ( - x.sink.rd == decoder.rs1) & x.sink.rd_we), - m_raw_rs1.eq((m.sink.rd != 0) & ( - m.sink.rd == decoder.rs1) & m.sink.rd_we), - w_raw_rs1.eq((w.sink.rd != 0) & ( - w.sink.rd == decoder.rs1) & w.sink.rd_we), - - x_raw_rs2.eq((x.sink.rd != 0) & ( - x.sink.rd == decoder.rs2) & x.sink.rd_we), - m_raw_rs2.eq((m.sink.rd != 0) & ( - m.sink.rd == decoder.rs2) & m.sink.rd_we), - w_raw_rs2.eq((w.sink.rd != 0) & ( - w.sink.rd == decoder.rs2) & w.sink.rd_we), - - x_raw_csr.eq((x.sink.csr_adr == decoder.immediate) - & x.sink.csr_we), - m_raw_csr.eq((m.sink.csr_adr == decoder.immediate) - & m.sink.csr_we), - - x_lock.eq(~x.sink.bypass_x & (decoder.rs1_re & x_raw_rs1 | - decoder.rs2_re & x_raw_rs2) | decoder.csr & x_raw_csr), - m_lock.eq(~m.sink.bypass_m & (decoder.rs1_re & m_raw_rs1 | - decoder.rs2_re & m_raw_rs2) | decoder.csr & m_raw_csr) - ] - - if self.with_debug: - d.stall_on((x_lock & x.valid | m_lock & m.valid) - & d.valid & ~debug.dcsr_step) - else: - d.stall_on((x_lock & x.valid | m_lock & m.valid) & d.valid) - - # result selection - - x_result = Signal(32) - m_result = Signal(32) - w_result = Signal(32) - x_csr_result = Signal(32) - - with cpu.If(x.sink.jump): - cpu.d.comb += x_result.eq(x.sink.pc + 4) - with cpu.Elif(x.sink.logic): - cpu.d.comb += x_result.eq(logic.result) - with cpu.Elif(x.sink.csr): - cpu.d.comb += x_result.eq(x.sink.src2) - with cpu.Else(): - cpu.d.comb += x_result.eq(adder.result) - - with cpu.If(m.sink.compare): - cpu.d.comb += m_result.eq(m.sink.condition_met) - if self.with_muldiv: - with cpu.Elif(m.sink.divide): - cpu.d.comb += m_result.eq(divider.m_result) - with cpu.Elif(m.sink.shift): - cpu.d.comb += m_result.eq(shifter.m_result) - with cpu.Else(): - cpu.d.comb += m_result.eq(m.sink.result) - - with cpu.If(w.sink.load): - cpu.d.comb += w_result.eq(data_sel.w_load_result) - if self.with_muldiv: - with cpu.Elif(w.sink.multiply): - cpu.d.comb += w_result.eq(multiplier.w_result) - with cpu.Else(): - cpu.d.comb += w_result.eq(w.sink.result) - - with cpu.If(x_csr_set_clear): - cpu.d.comb += x_csr_result.eq(logic.result) - with cpu.Else(): - cpu.d.comb += x_csr_result.eq(x_csr_src1) - - cpu.d.comb += [ - csrf_wp.en.eq(m.sink.csr & m.sink.csr_we & m.valid & - ~exception.m_raise & ~m.stall), - csrf_wp.addr.eq(m.sink.csr_adr), - csrf_wp.data.eq(m.sink.csr_result) - ] - - if self.with_debug: - with cpu.If(debug.halt & debug.halted): - cpu.d.comb += [ - gprf_wp.addr.eq(debug.gprf_addr), - gprf_wp.en.eq(debug.gprf_we), - gprf_wp.data.eq(debug.gprf_dat_w) - ] - with cpu.Else(): - cpu.d.comb += [ - gprf_wp.en.eq((w.sink.rd != 0) & w.sink.rd_we & - w.valid & ~w.sink.exception), - gprf_wp.addr.eq(w.sink.rd), - gprf_wp.data.eq(w_result) - ] - else: - cpu.d.comb += [ - gprf_wp.en.eq((w.sink.rd != 0) & w.sink.rd_we & w.valid), - gprf_wp.addr.eq(w.sink.rd), - gprf_wp.data.eq(w_result) - ] - - # D stage operand selection - - d_src1 = Signal(32) - d_src2 = Signal(32) - - with cpu.If(decoder.lui): - cpu.d.comb += d_src1.eq(0) - with cpu.Elif(decoder.auipc): - cpu.d.comb += d_src1.eq(d.sink.pc) - with cpu.Elif(decoder.rs1_re & (decoder.rs1 == 0)): - cpu.d.comb += d_src1.eq(0) - with cpu.Elif(x_raw_rs1 & x.valid): - cpu.d.comb += d_src1.eq(x_result) - with cpu.Elif(m_raw_rs1 & m.valid): - cpu.d.comb += d_src1.eq(m_result) - with cpu.Elif(w_raw_rs1 & w.valid): - cpu.d.comb += d_src1.eq(w_result) - with cpu.Else(): - cpu.d.comb += d_src1.eq(gprf_rp1.data) - - with cpu.If(decoder.csr): - cpu.d.comb += d_src2.eq(csrf_rp.data) - with cpu.Elif(~decoder.rs2_re): - cpu.d.comb += d_src2.eq(decoder.immediate) - with cpu.Elif(decoder.rs2 == 0): - cpu.d.comb += d_src2.eq(0) - with cpu.Elif(x_raw_rs2 & x.valid): - cpu.d.comb += d_src2.eq(x_result) - with cpu.Elif(m_raw_rs2 & m.valid): - cpu.d.comb += d_src2.eq(m_result) - with cpu.Elif(w_raw_rs2 & w.valid): - cpu.d.comb += d_src2.eq(w_result) - with cpu.Else(): - cpu.d.comb += d_src2.eq(gprf_rp2.data) - - # branch prediction - - cpu.d.comb += [ - predict.d_branch.eq(decoder.branch), - predict.d_jump.eq(decoder.jump), - predict.d_offset.eq(decoder.immediate), - predict.d_pc.eq(d.sink.pc), - predict.d_rs1_re.eq(decoder.rs1_re) - ] - - a.kill_on(predict.d_branch_taken & ~ - predict.d_fetch_misaligned & d.valid) - for s in a, f: - s.kill_on(m.sink.branch_predict_taken & ~ - m.sink.branch_taken & m.valid) - for s in a, f, d: - s.kill_on(~m.sink.branch_predict_taken & - m.sink.branch_taken & m.valid) - s.kill_on((exception.m_raise | m.sink.mret) & m.valid) - - # debug unit - - if self.with_debug: - cpu.d.comb += [ - debug.jtag.connect(self.jtag), - debug.x_pc.eq(x.sink.pc), - debug.x_ebreak.eq(x.sink.ebreak), - debug.x_stall.eq(x.stall), - debug.m_branch_taken.eq(m.sink.branch_taken), - debug.m_branch_target.eq(m.sink.branch_target), - debug.m_mret.eq(m.sink.mret), - debug.m_exception.eq(exception.m_raise), - debug.m_pc.eq(m.sink.pc), - debug.m_valid.eq(m.valid), - debug.mepc_r_base.eq(exception.mepc.r.base), - debug.mtvec_r_base.eq(exception.mtvec.r.base) - ] - - if self.with_trigger: - cpu.d.comb += debug.trigger_haltreq.eq(trigger.haltreq) - else: - cpu.d.comb += debug.trigger_haltreq.eq(Const(0)) - - csrf_debug_rp = csrf.read_port() - csrf_debug_wp = csrf.write_port() - cpu.d.comb += [ - csrf_debug_rp.addr.eq(debug.csrf_addr), - csrf_debug_rp.en.eq(debug.csrf_re), - debug.csrf_dat_r.eq(csrf_debug_rp.data), - csrf_debug_wp.addr.eq(debug.csrf_addr), - csrf_debug_wp.en.eq(debug.csrf_we), - csrf_debug_wp.data.eq(debug.csrf_dat_w) - ] - - x.stall_on(debug.halt) - m.stall_on(debug.dcsr_step & m.valid & ~debug.halt) - for s in a, f, d, x: - s.kill_on(debug.killall) - - halted = x.stall & ~reduce(or_, (s.valid for s in (m, w))) - cpu.d.sync += debug.halted.eq(halted) - - with cpu.If(debug.resumereq): - with cpu.If(~debug.dbus_busy): - cpu.d.comb += debug.resumeack.eq(1) - cpu.d.sync += a.source.pc.eq(debug.dpc_value - 4) - - if self.with_trigger: - cpu.d.comb += [ - trigger.x_pc.eq(x.sink.pc), - trigger.x_valid.eq(x.valid), - ] - - if self.with_rvfi: - cpu.d.comb += [ - rvficon.d_insn.eq(decoder.instruction), - rvficon.d_rs1_addr.eq(Mux(decoder.rs1_re, decoder.rs1, 0)), - rvficon.d_rs2_addr.eq(Mux(decoder.rs2_re, decoder.rs2, 0)), - rvficon.d_rs1_rdata.eq(Mux(decoder.rs1_re, d_src1, 0)), - rvficon.d_rs2_rdata.eq(Mux(decoder.rs2_re, d_src2, 0)), - rvficon.d_stall.eq(d.stall), - rvficon.x_mem_addr.eq(loadstore.x_addr[2:] << 2), - rvficon.x_mem_wmask.eq( - Mux(loadstore.x_store, loadstore.x_mask, 0)), - rvficon.x_mem_rmask.eq( - Mux(loadstore.x_load, loadstore.x_mask, 0)), - rvficon.x_mem_wdata.eq(loadstore.x_store_data), - rvficon.x_stall.eq(x.stall), - rvficon.m_mem_rdata.eq(loadstore.m_load_data), - rvficon.m_fetch_misaligned.eq(exception.m_fetch_misaligned), - rvficon.m_illegal_insn.eq(m.sink.illegal), - rvficon.m_load_misaligned.eq(exception.m_load_misaligned), - rvficon.m_store_misaligned.eq(exception.m_store_misaligned), - rvficon.m_exception.eq(exception.m_raise), - rvficon.m_mret.eq(m.sink.mret), - rvficon.m_branch_taken.eq(m.sink.branch_taken), - rvficon.m_branch_target.eq(m.sink.branch_target), - rvficon.m_pc_rdata.eq(m.sink.pc), - rvficon.m_stall.eq(m.stall), - rvficon.m_valid.eq(m.valid), - rvficon.w_rd_addr.eq(Mux(gprf_wp.en, gprf_wp.addr, 0)), - rvficon.w_rd_wdata.eq(Mux(gprf_wp.en, gprf_wp.data, 0)), - rvficon.mtvec_r_base.eq(exception.mtvec.r.base), - rvficon.mepc_r_value.eq(exception.mepc.r), - rvficon.rvfi.connect(self.rvfi) - ] - - # pipeline registers - - # A/F - with cpu.If(~a.stall): - cpu.d.sync += a.source.pc.eq(fetch.a_pc) - - # F/D - with cpu.If(~f.stall): - cpu.d.sync += [ - f.source.pc.eq(f.sink.pc), - f.source.instruction.eq(fetch.f_instruction), - f.source.fetch_error.eq(fetch.f_fetch_error), - f.source.fetch_badaddr.eq(fetch.f_badaddr) - ] - - # D/X - with cpu.If(~d.stall): - cpu.d.sync += [ - d.source.pc.eq(d.sink.pc), - d.source.instruction.eq(d.sink.instruction), - d.source.fetch_error.eq(d.sink.fetch_error), - d.source.fetch_badaddr.eq(d.sink.fetch_badaddr), - d.source.illegal.eq(decoder.illegal), - d.source.rd.eq(decoder.rd), - d.source.rs1.eq(decoder.rs1), - d.source.rd_we.eq(decoder.rd_we), - d.source.rs1_re.eq(decoder.rs1_re), - d.source.immediate.eq(decoder.immediate), - d.source.bypass_x.eq(decoder.bypass_x), - d.source.bypass_m.eq(decoder.bypass_m), - d.source.funct3.eq(decoder.funct3), - d.source.load.eq(decoder.load), - d.source.store.eq(decoder.store), - d.source.adder.eq(decoder.adder), - d.source.adder_sub.eq(decoder.adder_sub), - d.source.compare.eq(decoder.compare), - d.source.logic.eq(decoder.logic), - d.source.shift.eq(decoder.shift), - d.source.direction.eq(decoder.direction), - d.source.sext.eq(decoder.sext), - d.source.jump.eq(decoder.jump), - d.source.branch.eq(decoder.branch), - d.source.fence_i.eq(decoder.fence_i), - d.source.csr.eq(decoder.csr), - d.source.csr_adr.eq(decoder.immediate), - d.source.csr_we.eq(decoder.csr_we), - d.source.ecall.eq(decoder.ecall), - d.source.ebreak.eq(decoder.ebreak), - d.source.mret.eq(decoder.mret), - d.source.src1.eq(d_src1), - d.source.src2.eq(d_src2), - d.source.branch_predict_taken.eq( - predict.d_branch_taken & ~predict.d_fetch_misaligned), - d.source.branch_target.eq(predict.d_branch_target) - ] - if self.with_muldiv: - cpu.d.sync += [ - d.source.multiply.eq(decoder.multiply), - d.source.divide.eq(decoder.divide) - ] - - # X/M - with cpu.If(~x.stall): - cpu.d.sync += [ - x.source.pc.eq(x.sink.pc), - x.source.instruction.eq(x.sink.instruction), - x.source.fetch_error.eq(x.sink.fetch_error), - x.source.fetch_badaddr.eq(x.sink.fetch_badaddr), - x.source.illegal.eq(x.sink.illegal), - x.source.loadstore_misaligned.eq(data_sel.x_misaligned), - x.source.ecall.eq(x.sink.ecall), - x.source.ebreak.eq(x.sink.ebreak), - x.source.rd.eq(x.sink.rd), - x.source.rd_we.eq(x.sink.rd_we), - x.source.bypass_m.eq(x.sink.bypass_m | x.sink.bypass_x), - x.source.funct3.eq(x.sink.funct3), - x.source.load.eq(x.sink.load), - x.source.store.eq(x.sink.store), - x.source.store_data.eq(loadstore.x_store_data), - x.source.compare.eq(x.sink.compare), - x.source.shift.eq(x.sink.shift), - x.source.mret.eq(x.sink.mret), - x.source.condition_met.eq(compare.condition_met), - x.source.branch_taken.eq( - x.sink.jump | x.sink.branch & compare.condition_met), - x.source.branch_target.eq( - Mux(x.sink.jump & x.sink.rs1_re, adder.result[1:] << 1, x.sink.branch_target)), - x.source.branch_predict_taken.eq(x.sink.branch_predict_taken), - x.source.csr.eq(x.sink.csr), - x.source.csr_adr.eq(x.sink.csr_adr), - x.source.csr_we.eq(x.sink.csr_we), - x.source.csr_result.eq(x_csr_result), - x.source.result.eq(x_result) - ] - if self.with_muldiv: - cpu.d.sync += [ - x.source.multiply.eq(x.sink.multiply), - x.source.divide.eq(x.sink.divide) - ] - - # M/W - with cpu.If(~m.stall): - cpu.d.sync += [ - m.source.pc.eq(m.sink.pc), - m.source.rd.eq(m.sink.rd), - m.source.load.eq(m.sink.load), - m.source.funct3.eq(m.sink.funct3), - m.source.load_data.eq(loadstore.m_load_data), - m.source.rd_we.eq(m.sink.rd_we), - m.source.result.eq(m_result), - m.source.exception.eq(exception.m_raise) - ] - if self.with_muldiv: - cpu.d.sync += [ - m.source.multiply.eq(m.sink.multiply) - ] - - return cpu diff --git a/src/soc/minerva/csr.py b/src/soc/minerva/csr.py deleted file mode 100644 index 120f4263..00000000 --- a/src/soc/minerva/csr.py +++ /dev/null @@ -1,94 +0,0 @@ -from enum import Enum -from collections import OrderedDict - -from nmigen import (Const, Elaboratable, Module, Mux, - Record, Signal,) -from nmigen.utils import bits_for - - -__all__ = ["CSRAccess", "CSR", "AutoCSR", "CSRFile"] - - -CSRAccess = Enum("CSRAccess", ("WIRI", "WPRI", "WLRL", "WARL")) - - -class CSR(): - def __init__(self, addr, description, name): - fields = [] - mask = 0 - offset = 0 - for name, shape, access in description: - if isinstance(shape, int): - shape = shape, False - nbits, signed = shape - fields.append((name, shape)) - if access in {CSRAccess.WLRL, CSRAccess.WARL}: - mask |= ((1 << nbits) - 1) << offset - offset += nbits - - self.addr = addr - self.rmask = self.wmask = Const(mask) - self.r = Record(fields) - self.w = Record(fields) - self.re = Signal() - self.we = Signal() - - -class AutoCSR(): - def iter_csrs(self): - for v in vars(self).values(): - if isinstance(v, CSR): - yield v - elif hasattr(v, "iter_csrs"): - yield from v.iter_csrs() - - -class CSRFile(Elaboratable): - def __init__(self, width=32, depth=2**12): - self.width = width - self.depth = depth - self._csr_map = OrderedDict() - self._read_ports = [] - self._write_ports = [] - - def add_csrs(self, csrs): - for csr in csrs: - if not isinstance(csr, CSR): - raise TypeError("Object {!r} is not a CSR".format(csr)) - if csr.addr in self._csr_map: - raise ValueError("CSR address 0x{:x} has already been allocated" - .format(csr.addr)) - self._csr_map[csr.addr] = csr - - def read_port(self): - port = Record([("addr", bits_for(self.depth)), ("en", 1), ("data", self.width)]) - self._read_ports.append(port) - return port - - def write_port(self): - port = Record([("addr", bits_for(self.depth)), ("en", 1), ("data", self.width)]) - self._write_ports.append(port) - return port - - def elaborate(self, platform): - m = Module() - - for rp in self._read_ports: - with m.Switch(rp.addr): - for addr, csr in self._csr_map.items(): - with m.Case(addr): - m.d.comb += [ - csr.re.eq(rp.en), - rp.data.eq(csr.r & csr.rmask) - ] - - for wp in self._write_ports: - with m.Switch(wp.addr): - for addr, csr in self._csr_map.items(): - with m.Case(addr): - m.d.comb += [ - csr.we.eq(wp.en), - csr.w.eq(wp.data & csr.wmask) - ] - - return m diff --git a/src/soc/minerva/isa.py b/src/soc/minerva/isa.py deleted file mode 100644 index 625a4e18..00000000 --- a/src/soc/minerva/isa.py +++ /dev/null @@ -1,221 +0,0 @@ -from soc.minerva.csr import CSRAccess - - -__all__ = [ - "Opcode", "Funct3", "Funct7", "Funct12", "CSRIndex", "Cause", - "flat_layout", "misa_layout", "mstatus_layout", "mtvec_layout", "mepc_layout", - "mip_layout", "mie_layout", "mcause_layout", "dcsr_layout", "tdata1_layout" -] - -class Opcode: - LUI = 0b01101 - AUIPC = 0b00101 - JAL = 0b11011 - JALR = 0b11001 - BRANCH = 0b11000 - LOAD = 0b00000 - STORE = 0b01000 - OP_IMM_32 = 0b00100 - OP_32 = 0b01100 - MISC_MEM = 0b00011 - SYSTEM = 0b11100 - - -class Funct3: - BEQ = B = ADD = FENCE = PRIV = MUL = 0b000 - BNE = H = SLL = FENCEI = CSRRW = MULH = 0b001 - _ = W = SLT = _ = CSRRS = MULHSU = 0b010 - _ = _ = SLTU = _ = CSRRC = MULHU = 0b011 - BLT = BU = XOR = _ = _ = DIV = 0b100 - BGE = HU = SR = _ = CSRRWI = DIVU = 0b101 - BLTU = _ = OR = _ = CSRRSI = REM = 0b110 - BGEU = _ = AND = _ = CSRRCI = REMU = 0b111 - - -class Funct7: - SRL = ADD = 0b0000000 - MULDIV = 0b0000001 - SRA = SUB = 0b0100000 - - -class Funct12: - ECALL = 0b000000000000 - EBREAK = 0b000000000001 - MRET = 0b001100000010 - WFI = 0b000100000101 - - -class CSRIndex: - MVENDORID = 0xF11 - MARCHID = 0xF12 - MIMPID = 0xF13 - MHARTID = 0xF14 - MSTATUS = 0x300 - MISA = 0x301 - MEDELEG = 0x302 - MIDELEG = 0x303 - MIE = 0x304 - MTVEC = 0x305 - MCOUTEREN = 0x306 - MSCRATCH = 0x340 - MEPC = 0x341 - MCAUSE = 0x342 - MTVAL = 0x343 - MIP = 0x344 - # µarch specific - IRQ_MASK = 0x330 - IRQ_PENDING = 0x360 - # trigger module - TSELECT = 0x7a0 - TDATA1 = 0x7a1 - TDATA2 = 0x7a2 - TDATA3 = 0x7a3 - TINFO = 0x7a4 - MCONTEXT = 0x7a8 - # debug module - DCSR = 0x7b0 - DPC = 0x7b1 - - -class Cause: - FETCH_MISALIGNED = 0 - FETCH_ACCESS_FAULT = 1 - ILLEGAL_INSTRUCTION = 2 - BREAKPOINT = 3 - LOAD_MISALIGNED = 4 - LOAD_ACCESS_FAULT = 5 - STORE_MISALIGNED = 6 - STORE_ACCESS_FAULT = 7 - ECALL_FROM_U = 8 - ECALL_FROM_S = 9 - ECALL_FROM_M = 11 - FETCH_PAGE_FAULT = 12 - LOAD_PAGE_FAULT = 13 - STORE_PAGE_FAULT = 15 - # interrupts - U_SOFTWARE_INTERRUPT = 0 - S_SOFTWARE_INTERRUPT = 1 - M_SOFTWARE_INTERRUPT = 3 - U_TIMER_INTERRUPT = 4 - S_TIMER_INTERRUPT = 5 - M_TIMER_INTERRUPT = 7 - U_EXTERNAL_INTERRUPT = 8 - S_EXTERNAL_INTERRUPT = 9 - M_EXTERNAL_INTERRUPT = 11 - - -# CSR layouts - -flat_layout = [ - ("value", 32, CSRAccess.WARL) -] - - -misa_layout = [ - ("extensions", 26, CSRAccess.WARL), - ("wiri0", 4, CSRAccess.WIRI), - ("mxl", 2, CSRAccess.WARL) -] - - -mstatus_layout = [ - ("uie", 1, CSRAccess.WARL), # User Interrupt Enable - ("sie", 1, CSRAccess.WARL), # Supervisor Interrupt Enable - ("wpri0", 1, CSRAccess.WPRI), - ("mie", 1, CSRAccess.WARL), # Machine Interrupt Enable - ("upie", 1, CSRAccess.WARL), # User Previous Interrupt Enable - ("spie", 1, CSRAccess.WARL), # Supervisor Previous Interrupt Enable - ("wpri1", 1, CSRAccess.WPRI), - ("mpie", 1, CSRAccess.WARL), # Machine Previous Interrupt Enable - ("spp", 1, CSRAccess.WARL), # Supervisor Previous Privilege - ("wpri2", 2, CSRAccess.WPRI), - ("mpp", 2, CSRAccess.WARL), # Machine Previous Privilege - ("fs", 2, CSRAccess.WARL), # FPU Status - ("xs", 2, CSRAccess.WARL), # user-mode eXtensions Status - ("mprv", 1, CSRAccess.WARL), # Modify PRiVilege - ("sum", 1, CSRAccess.WARL), # Supervisor User Memory access - ("mxr", 1, CSRAccess.WARL), # Make eXecutable Readable - ("tvm", 1, CSRAccess.WARL), # Trap Virtual Memory - ("tw", 1, CSRAccess.WARL), # Timeout Wait - ("tsr", 1, CSRAccess.WARL), # Trap SRET - ("wpri3", 8, CSRAccess.WPRI), - ("sd", 1, CSRAccess.WARL) # State Dirty (set if XS or FS are set to dirty) -] - - -mtvec_layout = [ - ("mode", 2, CSRAccess.WARL), - ("base", 30, CSRAccess.WARL) -] - - -mepc_layout = [ - ("zero", 2, CSRAccess.WIRI), # 16-bit instructions are not supported - ("base", 30, CSRAccess.WARL) -] - - -mip_layout = [ - ("usip", 1, CSRAccess.WARL), - ("ssip", 1, CSRAccess.WARL), - ("wiri0", 1, CSRAccess.WIRI), - ("msip", 1, CSRAccess.WARL), - ("utip", 1, CSRAccess.WARL), - ("stip", 1, CSRAccess.WARL), - ("wiri1", 1, CSRAccess.WIRI), - ("mtip", 1, CSRAccess.WARL), - ("ueip", 1, CSRAccess.WARL), - ("seip", 1, CSRAccess.WARL), - ("wiri2", 1, CSRAccess.WIRI), - ("meip", 1, CSRAccess.WARL), - ("wiri3", 20, CSRAccess.WIRI) -] - - -mie_layout = [ - ("usie", 1, CSRAccess.WARL), - ("ssie", 1, CSRAccess.WARL), - ("wpri0", 1, CSRAccess.WPRI), - ("msie", 1, CSRAccess.WARL), - ("utie", 1, CSRAccess.WARL), - ("stie", 1, CSRAccess.WARL), - ("wpri1", 1, CSRAccess.WPRI), - ("mtie", 1, CSRAccess.WARL), - ("ueie", 1, CSRAccess.WARL), - ("seie", 1, CSRAccess.WARL), - ("wpri2", 1, CSRAccess.WPRI), - ("meie", 1, CSRAccess.WARL), - ("wpri3", 20, CSRAccess.WPRI) -] - - -mcause_layout = [ - ("ecode", 31, CSRAccess.WARL), - ("interrupt", 1, CSRAccess.WARL) -] - - -dcsr_layout = [ - ("prv", 2, CSRAccess.WARL), # Privilege level before Debug Mode was entered - ("step", 1, CSRAccess.WARL), # Execute a single instruction and re-enter Debug Mode - ("nmip", 1, CSRAccess.WLRL), # A non-maskable interrupt is pending - ("mprven", 1, CSRAccess.WARL), # Use mstatus.mprv in Debug Mode - ("zero0", 1, CSRAccess.WPRI), - ("cause", 3, CSRAccess.WLRL), # Explains why Debug Mode was entered - ("stoptime", 1, CSRAccess.WARL), # Stop timer increment during Debug Mode - ("stopcount", 1, CSRAccess.WARL), # Stop counter increment during Debug Mode - ("stepie", 1, CSRAccess.WARL), # Enable interrupts during single stepping - ("ebreaku", 1, CSRAccess.WARL), # EBREAKs in U-mode enter Debug Mode - ("ebreaks", 1, CSRAccess.WARL), # EBREAKs in S-mode enter Debug Mode - ("zero1", 1, CSRAccess.WPRI), - ("ebreakm", 1, CSRAccess.WARL), # EBREAKs in M-mode enter Debug Mode - ("zero2", 12, CSRAccess.WPRI), - ("xdebugver", 4, CSRAccess.WLRL) # External Debug specification version -] - - -tdata1_layout = [ - ("data", 27, CSRAccess.WARL), - ("dmode", 1, CSRAccess.WARL), - ("type", 4, CSRAccess.WARL) -] diff --git a/src/soc/minerva/stage.py b/src/soc/minerva/stage.py deleted file mode 100644 index 3b108d77..00000000 --- a/src/soc/minerva/stage.py +++ /dev/null @@ -1,100 +0,0 @@ -from functools import reduce -from operator import or_ - -from nmigen import Elaboratable, Module, Mux, Record, Signal -from nmigen.hdl.rec import DIR_FANIN, DIR_FANOUT, DIR_NONE - - -__all__ = ["Stage"] - - -def _make_m2s(layout): - r = [] - for f in layout: - if isinstance(f[1], (int, tuple)): - r.append((f[0], f[1], DIR_FANOUT)) - else: - r.append((f[0], _make_m2s(f[1]))) - return r - - -class _EndpointDescription: - def __init__(self, payload_layout): - self.payload_layout = payload_layout - - def get_full_layout(self): - reserved = {"valid", "stall", "kill"} - attributed = set() - for f in self.payload_layout: - if f[0] in attributed: - raise ValueError(f[0] + " already attributed in payload layout") - if f[0] in reserved: - raise ValueError(f[0] + " cannot be used in endpoint layout") - attributed.add(f[0]) - - full_layout = [ - ("valid", 1, DIR_FANOUT), - ("stall", 1, DIR_FANIN), - ("kill", 1, DIR_FANOUT), - ("payload", _make_m2s(self.payload_layout)) - ] - return full_layout - - -class _Endpoint(Record): - def __init__(self, layout): - self.description = _EndpointDescription(layout) - super().__init__(self.description.get_full_layout()) - - def __getattr__(self, name): - try: - return super().__getattr__(name) - except AttributeError: - return self.fields["payload"][name] - - -class Stage(Elaboratable): - def __init__(self, sink_layout, source_layout): - self.kill = Signal() - self.stall = Signal() - self.valid = Signal() - - if sink_layout is None and source_layout is None: - raise ValueError - if sink_layout is not None: - self.sink = _Endpoint(sink_layout) - if source_layout is not None: - self.source = _Endpoint(source_layout) - - self._kill_sources = [] - self._stall_sources = [] - - def kill_on(self, cond): - self._kill_sources.append(cond) - - def stall_on(self, cond): - self._stall_sources.append(cond) - - def elaborate(self, platform): - m = Module() - - if hasattr(self, "sink"): - m.d.comb += [ - self.valid.eq(self.sink.valid & ~self.sink.kill), - self.sink.stall.eq(self.stall) - ] - - if hasattr(self, "source"): - with m.If(~self.stall): - m.d.sync += self.source.valid.eq(self.valid) - with m.Elif(~self.source.stall | self.kill): - m.d.sync += self.source.valid.eq(0) - self.stall_on(self.source.stall) - m.d.comb += [ - self.source.kill.eq(self.kill), - self.kill.eq(reduce(or_, self._kill_sources, 0)) - ] - - m.d.comb += self.stall.eq(reduce(or_, self._stall_sources, 0)) - - return m diff --git a/src/soc/minerva/test/test_units_divider.py b/src/soc/minerva/test/test_units_divider.py deleted file mode 100644 index 1dec3738..00000000 --- a/src/soc/minerva/test/test_units_divider.py +++ /dev/null @@ -1,243 +0,0 @@ -from nmigen import * -from nmigen.back.pysim import * -from nmigen.test.utils import * - -from ..units.divider import * -from ..isa import Funct3 - - -def tst_op(funct3, src1, src2, result): - def test(self): - with Simulator(self.dut) as sim: - def process(): - yield self.dut.x_op.eq(funct3) - yield self.dut.x_src1.eq(src1) - yield self.dut.x_src2.eq(src2) - yield self.dut.x_valid.eq(1) - yield self.dut.x_stall.eq(0) - yield Tick() - yield self.dut.x_valid.eq(0) - yield Tick() - while (yield self.dut.m_busy): - yield Tick() - self.assertEqual((yield self.dut.m_result), result) - sim.add_clock(1e-6) - sim.add_sync_process(process) - sim.run() - return test - - -class DividerTestCase(FHDLTestCase): - def setUp(self): - self.dut = Divider() - - # Test cases are taken from the riscv-compliance testbench: - # https://github.com/riscv/riscv-compliance/tree/master/riscv-test-suite/rv32im - - # DIV ------------------------------------------------------------------------ - - test_div_0 = tst_op(Funct3.DIV, 0x00000000, 0x00000000, result=0xffffffff) - test_div_1 = tst_op(Funct3.DIV, 0x00000000, 0x00000001, result=0x00000000) - test_div_2 = tst_op(Funct3.DIV, 0x00000000, 0xffffffff, result=0x00000000) - test_div_3 = tst_op(Funct3.DIV, 0x00000000, 0x7fffffff, result=0x00000000) - test_div_4 = tst_op(Funct3.DIV, 0x00000000, 0x80000000, result=0x00000000) - - test_div_5 = tst_op(Funct3.DIV, 0x00000001, 0x00000000, result=0xffffffff) - test_div_6 = tst_op(Funct3.DIV, 0x00000001, 0x00000001, result=0x00000001) - test_div_7 = tst_op(Funct3.DIV, 0x00000001, 0xffffffff, result=0xffffffff) - test_div_8 = tst_op(Funct3.DIV, 0x00000001, 0x7fffffff, result=0x00000000) - test_div_9 = tst_op(Funct3.DIV, 0x00000001, 0x80000000, result=0x00000000) - - test_div_10 = tst_op(Funct3.DIV, 0xffffffff, - 0x00000000, result=0xffffffff) - test_div_11 = tst_op(Funct3.DIV, 0xffffffff, - 0x00000001, result=0xffffffff) - test_div_12 = tst_op(Funct3.DIV, 0xffffffff, - 0xffffffff, result=0x00000001) - test_div_13 = tst_op(Funct3.DIV, 0xffffffff, - 0x7fffffff, result=0x00000000) - test_div_14 = tst_op(Funct3.DIV, 0xffffffff, - 0x80000000, result=0x00000000) - - test_div_15 = tst_op(Funct3.DIV, 0x7fffffff, - 0x00000000, result=0xffffffff) - test_div_16 = tst_op(Funct3.DIV, 0x7fffffff, - 0x00000001, result=0x7fffffff) - test_div_17 = tst_op(Funct3.DIV, 0x7fffffff, - 0xffffffff, result=0x80000001) - test_div_18 = tst_op(Funct3.DIV, 0x7fffffff, - 0x7fffffff, result=0x00000001) - test_div_19 = tst_op(Funct3.DIV, 0x7fffffff, - 0x80000000, result=0x00000000) - - test_div_20 = tst_op(Funct3.DIV, 0x80000000, - 0x00000000, result=0xffffffff) - test_div_21 = tst_op(Funct3.DIV, 0x80000000, - 0x00000001, result=0x80000000) - test_div_22 = tst_op(Funct3.DIV, 0x80000000, - 0xffffffff, result=0x80000000) - test_div_23 = tst_op(Funct3.DIV, 0x80000000, - 0x7fffffff, result=0xffffffff) - test_div_24 = tst_op(Funct3.DIV, 0x80000000, - 0x80000000, result=0x00000001) - - # DIVU ----------------------------------------------------------------------- - - test_divu_0 = tst_op(Funct3.DIVU, 0x00000000, - 0x00000000, result=0xffffffff) - test_divu_1 = tst_op(Funct3.DIVU, 0x00000000, - 0x00000001, result=0x00000000) - test_divu_2 = tst_op(Funct3.DIVU, 0x00000000, - 0xffffffff, result=0x00000000) - test_divu_3 = tst_op(Funct3.DIVU, 0x00000000, - 0x7fffffff, result=0x00000000) - test_divu_4 = tst_op(Funct3.DIVU, 0x00000000, - 0x80000000, result=0x00000000) - - test_divu_5 = tst_op(Funct3.DIVU, 0x00000001, - 0x00000000, result=0xffffffff) - test_divu_6 = tst_op(Funct3.DIVU, 0x00000001, - 0x00000001, result=0x00000001) - test_divu_7 = tst_op(Funct3.DIVU, 0x00000001, - 0xffffffff, result=0x00000000) - test_divu_8 = tst_op(Funct3.DIVU, 0x00000001, - 0x7fffffff, result=0x00000000) - test_divu_9 = tst_op(Funct3.DIVU, 0x00000001, - 0x80000000, result=0x00000000) - - test_divu_10 = tst_op(Funct3.DIVU, 0xffffffff, - 0x00000000, result=0xffffffff) - test_divu_11 = tst_op(Funct3.DIVU, 0xffffffff, - 0x00000001, result=0xffffffff) - test_divu_12 = tst_op(Funct3.DIVU, 0xffffffff, - 0xffffffff, result=0x00000001) - test_divu_13 = tst_op(Funct3.DIVU, 0xffffffff, - 0x7fffffff, result=0x00000002) - test_divu_14 = tst_op(Funct3.DIVU, 0xffffffff, - 0x80000000, result=0x00000001) - - test_divu_15 = tst_op(Funct3.DIVU, 0x7fffffff, - 0x00000000, result=0xffffffff) - test_divu_16 = tst_op(Funct3.DIVU, 0x7fffffff, - 0x00000001, result=0x7fffffff) - test_divu_17 = tst_op(Funct3.DIVU, 0x7fffffff, - 0xffffffff, result=0x00000000) - test_divu_18 = tst_op(Funct3.DIVU, 0x7fffffff, - 0x7fffffff, result=0x00000001) - test_divu_19 = tst_op(Funct3.DIVU, 0x7fffffff, - 0x80000000, result=0x00000000) - - test_divu_20 = tst_op(Funct3.DIVU, 0x80000000, - 0x00000000, result=0xffffffff) - test_divu_21 = tst_op(Funct3.DIVU, 0x80000000, - 0x00000001, result=0x80000000) - test_divu_22 = tst_op(Funct3.DIVU, 0x80000000, - 0xffffffff, result=0x00000000) - test_divu_23 = tst_op(Funct3.DIVU, 0x80000000, - 0x7fffffff, result=0x00000001) - test_divu_24 = tst_op(Funct3.DIVU, 0x80000000, - 0x80000000, result=0x00000001) - - # REM ------------------------------------------------------------------------ - - test_rem_0 = tst_op(Funct3.REM, 0x00000000, 0x00000000, result=0x00000000) - test_rem_1 = tst_op(Funct3.REM, 0x00000000, 0x00000001, result=0x00000000) - test_rem_2 = tst_op(Funct3.REM, 0x00000000, 0xffffffff, result=0x00000000) - test_rem_3 = tst_op(Funct3.REM, 0x00000000, 0x7fffffff, result=0x00000000) - test_rem_4 = tst_op(Funct3.REM, 0x00000000, 0x80000000, result=0x00000000) - - test_rem_5 = tst_op(Funct3.REM, 0x00000001, 0x00000000, result=0x00000001) - test_rem_6 = tst_op(Funct3.REM, 0x00000001, 0x00000001, result=0x00000000) - test_rem_7 = tst_op(Funct3.REM, 0x00000001, 0xffffffff, result=0x00000000) - test_rem_8 = tst_op(Funct3.REM, 0x00000001, 0x7fffffff, result=0x00000001) - test_rem_9 = tst_op(Funct3.REM, 0x00000001, 0x80000000, result=0x00000001) - - test_rem_10 = tst_op(Funct3.REM, 0xffffffff, - 0x00000000, result=0xffffffff) - test_rem_11 = tst_op(Funct3.REM, 0xffffffff, - 0x00000001, result=0x00000000) - test_rem_12 = tst_op(Funct3.REM, 0xffffffff, - 0xffffffff, result=0x00000000) - test_rem_13 = tst_op(Funct3.REM, 0xffffffff, - 0x7fffffff, result=0xffffffff) - test_rem_14 = tst_op(Funct3.REM, 0xffffffff, - 0x80000000, result=0xffffffff) - - test_rem_15 = tst_op(Funct3.REM, 0x7fffffff, - 0x00000000, result=0x7fffffff) - test_rem_16 = tst_op(Funct3.REM, 0x7fffffff, - 0x00000001, result=0x00000000) - test_rem_17 = tst_op(Funct3.REM, 0x7fffffff, - 0xffffffff, result=0x00000000) - test_rem_18 = tst_op(Funct3.REM, 0x7fffffff, - 0x7fffffff, result=0x00000000) - test_rem_19 = tst_op(Funct3.REM, 0x7fffffff, - 0x80000000, result=0x7fffffff) - - test_rem_20 = tst_op(Funct3.REM, 0x80000000, - 0x00000000, result=0x80000000) - test_rem_21 = tst_op(Funct3.REM, 0x80000000, - 0x00000001, result=0x00000000) - test_rem_22 = tst_op(Funct3.REM, 0x80000000, - 0xffffffff, result=0x00000000) - test_rem_23 = tst_op(Funct3.REM, 0x80000000, - 0x7fffffff, result=0xffffffff) - test_rem_24 = tst_op(Funct3.REM, 0x80000000, - 0x80000000, result=0x00000000) - - # REMU ----------------------------------------------------------------------- - - test_remu_0 = tst_op(Funct3.REMU, 0x00000000, - 0x00000000, result=0x00000000) - test_remu_1 = tst_op(Funct3.REMU, 0x00000000, - 0x00000001, result=0x00000000) - test_remu_2 = tst_op(Funct3.REMU, 0x00000000, - 0xffffffff, result=0x00000000) - test_remu_3 = tst_op(Funct3.REMU, 0x00000000, - 0x7fffffff, result=0x00000000) - test_remu_4 = tst_op(Funct3.REMU, 0x00000000, - 0x80000000, result=0x00000000) - - test_remu_5 = tst_op(Funct3.REMU, 0x00000001, - 0x00000000, result=0x00000001) - test_remu_6 = tst_op(Funct3.REMU, 0x00000001, - 0x00000001, result=0x00000000) - test_remu_7 = tst_op(Funct3.REMU, 0x00000001, - 0xffffffff, result=0x00000001) - test_remu_8 = tst_op(Funct3.REMU, 0x00000001, - 0x7fffffff, result=0x00000001) - test_remu_9 = tst_op(Funct3.REMU, 0x00000001, - 0x80000000, result=0x00000001) - - test_remu_10 = tst_op(Funct3.REMU, 0xffffffff, - 0x00000000, result=0xffffffff) - test_remu_11 = tst_op(Funct3.REMU, 0xffffffff, - 0x00000001, result=0x00000000) - test_remu_12 = tst_op(Funct3.REMU, 0xffffffff, - 0xffffffff, result=0x00000000) - test_remu_13 = tst_op(Funct3.REMU, 0xffffffff, - 0x7fffffff, result=0x00000001) - test_remu_14 = tst_op(Funct3.REMU, 0xffffffff, - 0x80000000, result=0x7fffffff) - - test_remu_15 = tst_op(Funct3.REMU, 0x7fffffff, - 0x00000000, result=0x7fffffff) - test_remu_16 = tst_op(Funct3.REMU, 0x7fffffff, - 0x00000001, result=0x00000000) - test_remu_17 = tst_op(Funct3.REMU, 0x7fffffff, - 0xffffffff, result=0x7fffffff) - test_remu_18 = tst_op(Funct3.REMU, 0x7fffffff, - 0x7fffffff, result=0x00000000) - test_remu_19 = tst_op(Funct3.REMU, 0x7fffffff, - 0x80000000, result=0x7fffffff) - - test_remu_20 = tst_op(Funct3.REMU, 0x80000000, - 0x00000000, result=0x80000000) - test_remu_21 = tst_op(Funct3.REMU, 0x80000000, - 0x00000001, result=0x00000000) - test_remu_22 = tst_op(Funct3.REMU, 0x80000000, - 0xffffffff, result=0x80000000) - test_remu_23 = tst_op(Funct3.REMU, 0x80000000, - 0x7fffffff, result=0x00000001) - test_remu_24 = tst_op(Funct3.REMU, 0x80000000, - 0x80000000, result=0x00000000) diff --git a/src/soc/minerva/test/test_units_multiplier.py b/src/soc/minerva/test/test_units_multiplier.py deleted file mode 100644 index f2a352ca..00000000 --- a/src/soc/minerva/test/test_units_multiplier.py +++ /dev/null @@ -1,261 +0,0 @@ -from nmigen import * -from nmigen.back.pysim import * -from nmigen.test.utils import * - -from ..units.multiplier import * -from ..isa import Funct3 - - -def tst_op(funct3, src1, src2, result): - def test(self): - with Simulator(self.dut) as sim: - def process(): - yield self.dut.x_op.eq(funct3) - yield self.dut.x_src1.eq(src1) - yield self.dut.x_src2.eq(src2) - yield self.dut.x_stall.eq(0) - yield Tick() - yield self.dut.m_stall.eq(0) - yield Tick() - yield Tick() - self.assertEqual((yield self.dut.w_result), result) - sim.add_clock(1e-6) - sim.add_sync_process(process) - sim.run() - return test - - -class MultiplierTestCase(FHDLTestCase): - def setUp(self): - self.dut = Multiplier() - - # Test cases are taken from the riscv-compliance testbench: - # https://github.com/riscv/riscv-compliance/tree/master/riscv-test-suite/rv32im - - # MUL ---------------------------------------------------------------------------- - - test_mul_0 = tst_op(Funct3.MUL, 0x00000000, - 0x00000000, result=0x00000000) - test_mul_1 = tst_op(Funct3.MUL, 0x00000000, - 0x00000001, result=0x00000000) - test_mul_2 = tst_op(Funct3.MUL, 0x00000000, - 0xffffffff, result=0x00000000) - test_mul_3 = tst_op(Funct3.MUL, 0x00000000, - 0x7fffffff, result=0x00000000) - test_mul_4 = tst_op(Funct3.MUL, 0x00000000, - 0x80000000, result=0x00000000) - - test_mul_5 = tst_op(Funct3.MUL, 0x00000001, - 0x00000000, result=0x00000000) - test_mul_6 = tst_op(Funct3.MUL, 0x00000001, - 0x00000001, result=0x00000001) - test_mul_7 = tst_op(Funct3.MUL, 0x00000001, - 0xffffffff, result=0xffffffff) - test_mul_8 = tst_op(Funct3.MUL, 0x00000001, - 0x7fffffff, result=0x7fffffff) - test_mul_9 = tst_op(Funct3.MUL, 0x00000001, - 0x80000000, result=0x80000000) - - test_mul_10 = tst_op(Funct3.MUL, 0xffffffff, - 0x00000000, result=0x00000000) - test_mul_11 = tst_op(Funct3.MUL, 0xffffffff, - 0x00000001, result=0xffffffff) - test_mul_12 = tst_op(Funct3.MUL, 0xffffffff, - 0xffffffff, result=0x00000001) - test_mul_13 = tst_op(Funct3.MUL, 0xffffffff, - 0x7fffffff, result=0x80000001) - test_mul_14 = tst_op(Funct3.MUL, 0xffffffff, - 0x80000000, result=0x80000000) - - test_mul_15 = tst_op(Funct3.MUL, 0x7fffffff, - 0x00000000, result=0x00000000) - test_mul_16 = tst_op(Funct3.MUL, 0x7fffffff, - 0x00000001, result=0x7fffffff) - test_mul_17 = tst_op(Funct3.MUL, 0x7fffffff, - 0xffffffff, result=0x80000001) - test_mul_18 = tst_op(Funct3.MUL, 0x7fffffff, - 0x7fffffff, result=0x00000001) - test_mul_19 = tst_op(Funct3.MUL, 0x7fffffff, - 0x80000000, result=0x80000000) - - test_mul_20 = tst_op(Funct3.MUL, 0x80000000, - 0x00000000, result=0x00000000) - test_mul_21 = tst_op(Funct3.MUL, 0x80000000, - 0x00000001, result=0x80000000) - test_mul_22 = tst_op(Funct3.MUL, 0x80000000, - 0xffffffff, result=0x80000000) - test_mul_23 = tst_op(Funct3.MUL, 0x80000000, - 0x7fffffff, result=0x80000000) - test_mul_24 = tst_op(Funct3.MUL, 0x80000000, - 0x80000000, result=0x00000000) - - # MULH --------------------------------------------------------------------------- - - test_mulh_0 = tst_op(Funct3.MULH, 0x00000000, - 0x00000000, result=0x00000000) - test_mulh_1 = tst_op(Funct3.MULH, 0x00000000, - 0x00000001, result=0x00000000) - test_mulh_2 = tst_op(Funct3.MULH, 0x00000000, - 0xffffffff, result=0x00000000) - test_mulh_3 = tst_op(Funct3.MULH, 0x00000000, - 0x7fffffff, result=0x00000000) - test_mulh_4 = tst_op(Funct3.MULH, 0x00000000, - 0x80000000, result=0x00000000) - - test_mulh_5 = tst_op(Funct3.MULH, 0x00000001, - 0x00000000, result=0x00000000) - test_mulh_6 = tst_op(Funct3.MULH, 0x00000001, - 0x00000001, result=0x00000000) - test_mulh_7 = tst_op(Funct3.MULH, 0x00000001, - 0xffffffff, result=0xffffffff) - test_mulh_8 = tst_op(Funct3.MULH, 0x00000001, - 0x7fffffff, result=0x00000000) - test_mulh_9 = tst_op(Funct3.MULH, 0x00000001, - 0x80000000, result=0xffffffff) - - test_mulh_10 = tst_op(Funct3.MULH, 0xffffffff, - 0x00000000, result=0x00000000) - test_mulh_11 = tst_op(Funct3.MULH, 0xffffffff, - 0x00000001, result=0xffffffff) - test_mulh_12 = tst_op(Funct3.MULH, 0xffffffff, - 0xffffffff, result=0x00000000) - test_mulh_13 = tst_op(Funct3.MULH, 0xffffffff, - 0x7fffffff, result=0xffffffff) - test_mulh_14 = tst_op(Funct3.MULH, 0xffffffff, - 0x80000000, result=0x00000000) - - test_mulh_15 = tst_op(Funct3.MULH, 0x7fffffff, - 0x00000000, result=0x00000000) - test_mulh_16 = tst_op(Funct3.MULH, 0x7fffffff, - 0x00000001, result=0x00000000) - test_mulh_17 = tst_op(Funct3.MULH, 0x7fffffff, - 0xffffffff, result=0xffffffff) - test_mulh_18 = tst_op(Funct3.MULH, 0x7fffffff, - 0x7fffffff, result=0x3fffffff) - test_mulh_19 = tst_op(Funct3.MULH, 0x7fffffff, - 0x80000000, result=0xc0000000) - - test_mulh_20 = tst_op(Funct3.MULH, 0x80000000, - 0x00000000, result=0x00000000) - test_mulh_21 = tst_op(Funct3.MULH, 0x80000000, - 0x00000001, result=0xffffffff) - test_mulh_22 = tst_op(Funct3.MULH, 0x80000000, - 0xffffffff, result=0x00000000) - test_mulh_23 = tst_op(Funct3.MULH, 0x80000000, - 0x7fffffff, result=0xc0000000) - test_mulh_24 = tst_op(Funct3.MULH, 0x80000000, - 0x80000000, result=0x40000000) - - # MULHSU ------------------------------------------------------------------------- - - test_mulhsu_0 = tst_op(Funct3.MULHSU, 0x00000000, - 0x00000000, result=0x00000000) - test_mulhsu_1 = tst_op(Funct3.MULHSU, 0x00000000, - 0x00000001, result=0x00000000) - test_mulhsu_2 = tst_op(Funct3.MULHSU, 0x00000000, - 0xffffffff, result=0x00000000) - test_mulhsu_3 = tst_op(Funct3.MULHSU, 0x00000000, - 0x7fffffff, result=0x00000000) - test_mulhsu_4 = tst_op(Funct3.MULHSU, 0x00000000, - 0x80000000, result=0x00000000) - - test_mulhsu_5 = tst_op(Funct3.MULHSU, 0x00000001, - 0x00000000, result=0x00000000) - test_mulhsu_6 = tst_op(Funct3.MULHSU, 0x00000001, - 0x00000001, result=0x00000000) - test_mulhsu_7 = tst_op(Funct3.MULHSU, 0x00000001, - 0xffffffff, result=0x00000000) - test_mulhsu_8 = tst_op(Funct3.MULHSU, 0x00000001, - 0x7fffffff, result=0x00000000) - test_mulhsu_9 = tst_op(Funct3.MULHSU, 0x00000001, - 0x80000000, result=0x00000000) - - test_mulhsu_10 = tst_op(Funct3.MULHSU, 0xffffffff, - 0x00000000, result=0x00000000) - test_mulhsu_11 = tst_op(Funct3.MULHSU, 0xffffffff, - 0x00000001, result=0xffffffff) - test_mulhsu_12 = tst_op(Funct3.MULHSU, 0xffffffff, - 0xffffffff, result=0xffffffff) - test_mulhsu_13 = tst_op(Funct3.MULHSU, 0xffffffff, - 0x7fffffff, result=0xffffffff) - test_mulhsu_14 = tst_op(Funct3.MULHSU, 0xffffffff, - 0x80000000, result=0xffffffff) - - test_mulhsu_15 = tst_op(Funct3.MULHSU, 0x7fffffff, - 0x00000000, result=0x00000000) - test_mulhsu_16 = tst_op(Funct3.MULHSU, 0x7fffffff, - 0x00000001, result=0x00000000) - test_mulhsu_17 = tst_op(Funct3.MULHSU, 0x7fffffff, - 0xffffffff, result=0x7ffffffe) - test_mulhsu_18 = tst_op(Funct3.MULHSU, 0x7fffffff, - 0x7fffffff, result=0x3fffffff) - test_mulhsu_19 = tst_op(Funct3.MULHSU, 0x7fffffff, - 0x80000000, result=0x3fffffff) - - test_mulhsu_20 = tst_op(Funct3.MULHSU, 0x80000000, - 0x00000000, result=0x00000000) - test_mulhsu_21 = tst_op(Funct3.MULHSU, 0x80000000, - 0x00000001, result=0xffffffff) - test_mulhsu_22 = tst_op(Funct3.MULHSU, 0x80000000, - 0xffffffff, result=0x80000000) - test_mulhsu_23 = tst_op(Funct3.MULHSU, 0x80000000, - 0x7fffffff, result=0xc0000000) - test_mulhsu_24 = tst_op(Funct3.MULHSU, 0x80000000, - 0x80000000, result=0xc0000000) - - # MULHU -------------------------------------------------------------------------- - - test_mulhu_0 = tst_op(Funct3.MULHU, 0x00000000, - 0x00000000, result=0x00000000) - test_mulhu_1 = tst_op(Funct3.MULHU, 0x00000000, - 0x00000001, result=0x00000000) - test_mulhu_2 = tst_op(Funct3.MULHU, 0x00000000, - 0xffffffff, result=0x00000000) - test_mulhu_3 = tst_op(Funct3.MULHU, 0x00000000, - 0x7fffffff, result=0x00000000) - test_mulhu_4 = tst_op(Funct3.MULHU, 0x00000000, - 0x80000000, result=0x00000000) - - test_mulhu_5 = tst_op(Funct3.MULHU, 0x00000001, - 0x00000000, result=0x00000000) - test_mulhu_6 = tst_op(Funct3.MULHU, 0x00000001, - 0x00000001, result=0x00000000) - test_mulhu_7 = tst_op(Funct3.MULHU, 0x00000001, - 0xffffffff, result=0x00000000) - test_mulhu_8 = tst_op(Funct3.MULHU, 0x00000001, - 0x7fffffff, result=0x00000000) - test_mulhu_9 = tst_op(Funct3.MULHU, 0x00000001, - 0x80000000, result=0x00000000) - - test_mulhu_10 = tst_op(Funct3.MULHU, 0xffffffff, - 0x00000000, result=0x00000000) - test_mulhu_11 = tst_op(Funct3.MULHU, 0xffffffff, - 0x00000001, result=0x00000000) - test_mulhu_12 = tst_op(Funct3.MULHU, 0xffffffff, - 0xffffffff, result=0xfffffffe) - test_mulhu_13 = tst_op(Funct3.MULHU, 0xffffffff, - 0x7fffffff, result=0x7ffffffe) - test_mulhu_14 = tst_op(Funct3.MULHU, 0xffffffff, - 0x80000000, result=0x7fffffff) - - test_mulhu_15 = tst_op(Funct3.MULHU, 0x7fffffff, - 0x00000000, result=0x00000000) - test_mulhu_16 = tst_op(Funct3.MULHU, 0x7fffffff, - 0x00000001, result=0x00000000) - test_mulhu_17 = tst_op(Funct3.MULHU, 0x7fffffff, - 0xffffffff, result=0x7ffffffe) - test_mulhu_18 = tst_op(Funct3.MULHU, 0x7fffffff, - 0x7fffffff, result=0x3fffffff) - test_mulhu_19 = tst_op(Funct3.MULHU, 0x7fffffff, - 0x80000000, result=0x3fffffff) - - test_mulhu_20 = tst_op(Funct3.MULHU, 0x80000000, - 0x00000000, result=0x00000000) - test_mulhu_21 = tst_op(Funct3.MULHU, 0x80000000, - 0x00000001, result=0x00000000) - test_mulhu_22 = tst_op(Funct3.MULHU, 0x80000000, - 0xffffffff, result=0x7fffffff) - test_mulhu_23 = tst_op(Funct3.MULHU, 0x80000000, - 0x7fffffff, result=0x3fffffff) - test_mulhu_24 = tst_op(Funct3.MULHU, 0x80000000, - 0x80000000, result=0x40000000) diff --git a/src/soc/minerva/units/adder.py b/src/soc/minerva/units/adder.py deleted file mode 100644 index eabdc6c2..00000000 --- a/src/soc/minerva/units/adder.py +++ /dev/null @@ -1,31 +0,0 @@ -from nmigen import Elaboratable, Module, Signal, Cat - - -__all__ = ["Adder"] - - -class Adder(Elaboratable): - def __init__(self): - self.sub = Signal() - self.src1 = Signal(32) - self.src2 = Signal(32) - - self.result = Signal(32) - self.carry = Signal() - self.overflow = Signal() - - def elaborate(self, platform): - m = Module() - - with m.If(self.sub): - m.d.comb += [ - Cat(self.result, self.carry).eq(self.src1 - self.src2), - self.overflow.eq((self.src1[-1] != self.src2[-1]) & (self.result[-1] == self.src2[-1])) - ] - with m.Else(): - m.d.comb += [ - Cat(self.result, self.carry).eq(self.src1 + self.src2), - self.overflow.eq(~self.src1[-1] & self.src2[-1] & self.result[-1]) - ] - - return m diff --git a/src/soc/minerva/units/compare.py b/src/soc/minerva/units/compare.py deleted file mode 100644 index b8ba2171..00000000 --- a/src/soc/minerva/units/compare.py +++ /dev/null @@ -1,36 +0,0 @@ -from nmigen import Elaboratable, Module, Signal - -from ..isa import Funct3 - - -__all__ = ["CompareUnit"] - - -class CompareUnit(Elaboratable): - def __init__(self): - self.op = Signal(3) - self.zero = Signal() - self.negative = Signal() - self.overflow = Signal() - self.carry = Signal() - - self.condition_met = Signal() - - def elaborate(self, platform): - m = Module() - - with m.Switch(self.op): - with m.Case(Funct3.BEQ): - m.d.comb += self.condition_met.eq(self.zero) - with m.Case(Funct3.BNE): - m.d.comb += self.condition_met.eq(~self.zero) - with m.Case(Funct3.BLT): - m.d.comb += self.condition_met.eq(~self.zero & (self.negative != self.overflow)) - with m.Case(Funct3.BGE): - m.d.comb += self.condition_met.eq(self.negative == self.overflow) - with m.Case(Funct3.BLTU): - m.d.comb += self.condition_met.eq(~self.zero & self.carry) - with m.Case(Funct3.BGEU): - m.d.comb += self.condition_met.eq(~self.carry) - - return m diff --git a/src/soc/minerva/units/decoder.py b/src/soc/minerva/units/decoder.py deleted file mode 100644 index 7975d2d6..00000000 --- a/src/soc/minerva/units/decoder.py +++ /dev/null @@ -1,261 +0,0 @@ -from functools import reduce -from itertools import starmap -from operator import or_ - -from nmigen import Elaboratable, Module, Signal, Cat - -from ..isa import Opcode, Funct3, Funct7, Funct12 - - -__all__ = ["InstructionDecoder"] - - -class Type: - R = 0 - I = 1 - S = 2 - B = 3 - U = 4 - J = 5 - - -class InstructionDecoder(Elaboratable): - def __init__(self, with_muldiv): - self.with_muldiv = with_muldiv - - self.instruction = Signal(32) - - self.rd = Signal(5) - self.rd_we = Signal() - self.rs1 = Signal(5) - self.rs1_re = Signal() - self.rs2 = Signal(5) - self.rs2_re = Signal() - self.immediate = Signal((32, True)) - self.bypass_x = Signal() - self.bypass_m = Signal() - self.load = Signal() - self.store = Signal() - self.fence_i = Signal() - self.adder = Signal() - self.adder_sub = Signal() - self.logic = Signal() - self.multiply = Signal() - self.divide = Signal() - self.shift = Signal() - self.direction = Signal() - self.sext = Signal() - self.lui = Signal() - self.auipc = Signal() - self.jump = Signal() - self.branch = Signal() - self.compare = Signal() - self.csr = Signal() - self.csr_we = Signal() - self.privileged = Signal() - self.ecall = Signal() - self.ebreak = Signal() - self.mret = Signal() - self.funct3 = Signal(3) - self.illegal = Signal() - - def elaborate(self, platform): - m = Module() - - opcode = Signal(5) - funct3 = Signal(3) - funct7 = Signal(7) - funct12 = Signal(12) - - iimm12 = Signal((12, True)) - simm12 = Signal((12, True)) - bimm12 = Signal((13, True)) - uimm20 = Signal(20) - jimm20 = Signal((21, True)) - - insn = self.instruction - fmt = Signal(range(Type.J + 1)) - - m.d.comb += [ - opcode.eq(insn[2:7]), - funct3.eq(insn[12:15]), - funct7.eq(insn[25:32]), - funct12.eq(insn[20:32]), - - iimm12.eq(insn[20:32]), - simm12.eq(Cat(insn[7:12], insn[25:32])), - bimm12.eq(Cat(0, insn[8:12], insn[25:31], insn[7], insn[31])), - uimm20.eq(insn[12:32]), - jimm20.eq(Cat(0, insn[21:31], insn[20], insn[12:20], insn[31])), - ] - - with m.Switch(opcode): - with m.Case(Opcode.LUI): - m.d.comb += fmt.eq(Type.U) - with m.Case(Opcode.AUIPC): - m.d.comb += fmt.eq(Type.U) - with m.Case(Opcode.JAL): - m.d.comb += fmt.eq(Type.J) - with m.Case(Opcode.JALR): - m.d.comb += fmt.eq(Type.I) - with m.Case(Opcode.BRANCH): - m.d.comb += fmt.eq(Type.B) - with m.Case(Opcode.LOAD): - m.d.comb += fmt.eq(Type.I) - with m.Case(Opcode.STORE): - m.d.comb += fmt.eq(Type.S) - with m.Case(Opcode.OP_IMM_32): - m.d.comb += fmt.eq(Type.I) - with m.Case(Opcode.OP_32): - m.d.comb += fmt.eq(Type.R) - with m.Case(Opcode.MISC_MEM): - m.d.comb += fmt.eq(Type.I) - with m.Case(Opcode.SYSTEM): - m.d.comb += fmt.eq(Type.I) - - with m.Switch(fmt): - with m.Case(Type.I): - m.d.comb += self.immediate.eq(iimm12) - with m.Case(Type.S): - m.d.comb += self.immediate.eq(simm12) - with m.Case(Type.B): - m.d.comb += self.immediate.eq(bimm12) - with m.Case(Type.U): - m.d.comb += self.immediate.eq(uimm20 << 12) - with m.Case(Type.J): - m.d.comb += self.immediate.eq(jimm20) - - m.d.comb += [ - self.rd.eq(insn[7:12]), - self.rs1.eq(insn[15:20]), - self.rs2.eq(insn[20:25]), - - self.rd_we.eq(reduce(or_, (fmt == T for T in (Type.R, Type.I, Type.U, Type.J)))), - self.rs1_re.eq(reduce(or_, (fmt == T for T in (Type.R, Type.I, Type.S, Type.B)))), - self.rs2_re.eq(reduce(or_, (fmt == T for T in (Type.R, Type.S, Type.B)))), - - self.funct3.eq(funct3) - ] - - def matcher(encodings): - return reduce(or_, starmap( - lambda opc, f3=None, f7=None, f12=None: - (opcode == opc if opc is not None else 1) \ - & (funct3 == f3 if f3 is not None else 1) \ - & (funct7 == f7 if f7 is not None else 1) \ - & (funct12 == f12 if f12 is not None else 1), - encodings)) - - m.d.comb += [ - self.compare.eq(matcher([ - (Opcode.OP_IMM_32, Funct3.SLT, None), # slti - (Opcode.OP_IMM_32, Funct3.SLTU, None), # sltiu - (Opcode.OP_32, Funct3.SLT, 0), # slt - (Opcode.OP_32, Funct3.SLTU, 0) # sltu - ])), - self.branch.eq(matcher([ - (Opcode.BRANCH, Funct3.BEQ, None), # beq - (Opcode.BRANCH, Funct3.BNE, None), # bne - (Opcode.BRANCH, Funct3.BLT, None), # blt - (Opcode.BRANCH, Funct3.BGE, None), # bge - (Opcode.BRANCH, Funct3.BLTU, None), # bltu - (Opcode.BRANCH, Funct3.BGEU, None) # bgeu - ])), - - self.adder.eq(matcher([ - (Opcode.OP_IMM_32, Funct3.ADD, None), # addi - (Opcode.OP_32, Funct3.ADD, Funct7.ADD), # add - (Opcode.OP_32, Funct3.ADD, Funct7.SUB) # sub - ])), - self.adder_sub.eq(self.rs2_re & (funct7 == Funct7.SUB)), - - self.logic.eq(matcher([ - (Opcode.OP_IMM_32, Funct3.XOR, None), # xori - (Opcode.OP_IMM_32, Funct3.OR, None), # ori - (Opcode.OP_IMM_32, Funct3.AND, None), # andi - (Opcode.OP_32, Funct3.XOR, 0), # xor - (Opcode.OP_32, Funct3.OR, 0), # or - (Opcode.OP_32, Funct3.AND, 0) # and - ])), - ] - - if self.with_muldiv: - m.d.comb += [ - self.multiply.eq(matcher([ - (Opcode.OP_32, Funct3.MUL, Funct7.MULDIV), # mul - (Opcode.OP_32, Funct3.MULH, Funct7.MULDIV), # mulh - (Opcode.OP_32, Funct3.MULHSU, Funct7.MULDIV), # mulhsu - (Opcode.OP_32, Funct3.MULHU, Funct7.MULDIV), # mulhu - ])), - - self.divide.eq(matcher([ - (Opcode.OP_32, Funct3.DIV, Funct7.MULDIV), # div - (Opcode.OP_32, Funct3.DIVU, Funct7.MULDIV), # divu - (Opcode.OP_32, Funct3.REM, Funct7.MULDIV), # rem - (Opcode.OP_32, Funct3.REMU, Funct7.MULDIV) # remu - ])), - ] - - m.d.comb += [ - self.shift.eq(matcher([ - (Opcode.OP_IMM_32, Funct3.SLL, 0), # slli - (Opcode.OP_IMM_32, Funct3.SR, Funct7.SRL), # srli - (Opcode.OP_IMM_32, Funct3.SR, Funct7.SRA), # srai - (Opcode.OP_32, Funct3.SLL, 0), # sll - (Opcode.OP_32, Funct3.SR, Funct7.SRL), # srl - (Opcode.OP_32, Funct3.SR, Funct7.SRA) # sra - ])), - self.direction.eq(funct3 == Funct3.SR), - self.sext.eq(funct7 == Funct7.SRA), - - self.lui.eq(opcode == Opcode.LUI), - self.auipc.eq(opcode == Opcode.AUIPC), - - self.jump.eq(matcher([ - (Opcode.JAL, None), # jal - (Opcode.JALR, 0) # jalr - ])), - - self.load.eq(matcher([ - (Opcode.LOAD, Funct3.B), # lb - (Opcode.LOAD, Funct3.BU), # lbu - (Opcode.LOAD, Funct3.H), # lh - (Opcode.LOAD, Funct3.HU), # lhu - (Opcode.LOAD, Funct3.W) # lw - ])), - self.store.eq(matcher([ - (Opcode.STORE, Funct3.B), # sb - (Opcode.STORE, Funct3.H), # sh - (Opcode.STORE, Funct3.W) # sw - ])), - - self.fence_i.eq(matcher([ - (Opcode.MISC_MEM, Funct3.FENCEI) # fence.i - ])), - - self.csr.eq(matcher([ - (Opcode.SYSTEM, Funct3.CSRRW), # csrrw - (Opcode.SYSTEM, Funct3.CSRRS), # csrrs - (Opcode.SYSTEM, Funct3.CSRRC), # csrrc - (Opcode.SYSTEM, Funct3.CSRRWI), # csrrwi - (Opcode.SYSTEM, Funct3.CSRRSI), # csrrsi - (Opcode.SYSTEM, Funct3.CSRRCI) # csrrci - ])), - self.csr_we.eq(~funct3[1] | (self.rs1 != 0)), - - self.privileged.eq((opcode == Opcode.SYSTEM) & (funct3 == Funct3.PRIV)), - self.ecall.eq(self.privileged & (funct12 == Funct12.ECALL)), - self.ebreak.eq(self.privileged & (funct12 == Funct12.EBREAK)), - self.mret.eq(self.privileged & (funct12 == Funct12.MRET)), - - self.bypass_x.eq(self.adder | self.logic | self.lui | self.auipc | self.csr), - self.bypass_m.eq(self.compare | self.divide | self.shift), - - self.illegal.eq((self.instruction[:2] != 0b11) | ~reduce(or_, ( - self.compare, self.branch, self.adder, self.logic, self.multiply, self.divide, self.shift, - self.lui, self.auipc, self.jump, self.load, self.store, - self.csr, self.ecall, self.ebreak, self.mret - ))) - ] - - return m diff --git a/src/soc/minerva/units/divider.py b/src/soc/minerva/units/divider.py deleted file mode 100644 index 42deafbd..00000000 --- a/src/soc/minerva/units/divider.py +++ /dev/null @@ -1,144 +0,0 @@ -from nmigen import Elaboratable, Module, Signal, Mux, Cat, C - -from ..isa import Funct3 - - -__all__ = ["DividerInterface", "Divider", "DummyDivider"] - - -class DividerInterface: - def __init__(self): - self.x_op = Signal(3) - self.x_src1 = Signal(32) - self.x_src2 = Signal(32) - self.x_valid = Signal() - self.x_stall = Signal() - - self.m_result = Signal(32) - self.m_busy = Signal() - - -class Divider(DividerInterface, Elaboratable): - def elaborate(self, platform): - m = Module() - - x_enable = Signal() - x_modulus = Signal() - x_signed = Signal() - - with m.Switch(self.x_op): - with m.Case(Funct3.DIV): - m.d.comb += x_enable.eq(1), x_signed.eq(1) - with m.Case(Funct3.DIVU): - m.d.comb += x_enable.eq(1) - with m.Case(Funct3.REM): - m.d.comb += x_enable.eq(1), x_modulus.eq(1), x_signed.eq(1) - with m.Case(Funct3.REMU): - m.d.comb += x_enable.eq(1), x_modulus.eq(1) - - x_negative = Signal() - with m.If(x_modulus): - m.d.comb += x_negative.eq(x_signed & self.x_src1[31]) - with m.Else(): - m.d.comb += x_negative.eq(x_signed & (self.x_src1[31] ^ self.x_src2[31])) - - x_dividend = Signal(32) - x_divisor = Signal(32) - m.d.comb += [ - x_dividend.eq(Mux(x_signed & self.x_src1[31], -self.x_src1, self.x_src1)), - x_divisor.eq(Mux(x_signed & self.x_src2[31], -self.x_src2, self.x_src2)) - ] - - m_modulus = Signal() - m_negative = Signal() - - timer = Signal(range(33), reset=32) - quotient = Signal(32) - divisor = Signal(32) - remainder = Signal(32) - difference = Signal(33) - - with m.FSM() as fsm: - with m.State("IDLE"): - with m.If(x_enable & self.x_valid & ~self.x_stall): - m.d.sync += [ - m_modulus.eq(x_modulus), - m_negative.eq(x_negative) - ] - with m.If(x_divisor == 0): - # Division by zero - m.d.sync += [ - quotient.eq(-1), - remainder.eq(self.x_src1) - ] - with m.Elif(x_signed & (self.x_src1 == -2**31) & (self.x_src2 == -1)): - # Signed overflow - m.d.sync += [ - quotient.eq(self.x_src1), - remainder.eq(0) - ] - with m.Elif(x_dividend == 0): - m.d.sync += [ - quotient.eq(0), - remainder.eq(0) - ] - with m.Else(): - m.d.sync += [ - quotient.eq(x_dividend), - remainder.eq(0), - divisor.eq(x_divisor), - timer.eq(timer.reset) - ] - m.next = "DIVIDE" - - with m.State("DIVIDE"): - m.d.comb += self.m_busy.eq(1) - with m.If(timer != 0): - m.d.sync += timer.eq(timer - 1) - m.d.comb += difference.eq(Cat(quotient[31], remainder) - divisor) - with m.If(difference[32]): - m.d.sync += [ - remainder.eq(Cat(quotient[31], remainder)), - quotient.eq(Cat(0, quotient)) - ] - with m.Else(): - m.d.sync += [ - remainder.eq(difference), - quotient.eq(Cat(1, quotient)) - ] - with m.Else(): - m.d.sync += [ - quotient.eq(Mux(m_negative, -quotient, quotient)), - remainder.eq(Mux(m_negative, -remainder, remainder)) - ] - m.next = "IDLE" - - m.d.comb += self.m_result.eq(Mux(m_modulus, remainder, quotient)) - - return m - - -class DummyDivider(DividerInterface, Elaboratable): - def elaborate(self, platform): - m = Module() - - x_result = Signal.like(self.m_result) - - with m.Switch(self.x_op): - # As per the RVFI specification (§ "Alternative Arithmetic Operations"). - # https://github.com/SymbioticEDA/riscv-formal/blob/master/docs/rvfi.md - with m.Case(Funct3.DIV): - m.d.comb += x_result.eq((self.x_src1 - self.x_src2) ^ C(0x7f8529ec)) - with m.Case(Funct3.DIVU): - m.d.comb += x_result.eq((self.x_src1 - self.x_src2) ^ C(0x10e8fd70)) - with m.Case(Funct3.REM): - m.d.comb += x_result.eq((self.x_src1 - self.x_src2) ^ C(0x8da68fa5)) - with m.Case(Funct3.REMU): - m.d.comb += x_result.eq((self.x_src1 - self.x_src2) ^ C(0x3138d0e1)) - - with m.If(~self.x_stall): - m.d.sync += self.m_result.eq(x_result) - - m.d.comb += self.m_busy.eq(C(0)) - - return m diff --git a/src/soc/minerva/units/exception.py b/src/soc/minerva/units/exception.py deleted file mode 100644 index 1bee8402..00000000 --- a/src/soc/minerva/units/exception.py +++ /dev/null @@ -1,124 +0,0 @@ -from nmigen import Elaboratable, Module, Signal -from nmigen.lib.coding import PriorityEncoder - -from ..csr import AutoCSR, CSR -from ..isa import (Cause, - mstatus_layout, misa_layout, mie_layout, - mtvec_layout, flat_layout, mepc_layout, mcause_layout, - flat_layout, mip_layout, flat_layout) - - -__all__ = ["ExceptionUnit"] - - -class ExceptionUnit(Elaboratable, AutoCSR): - def __init__(self): - self.mstatus = CSR(0x300, mstatus_layout, name="mstatus") - self.misa = CSR(0x301, misa_layout, name="misa") # FIXME move elsewhere - self.mie = CSR(0x304, mie_layout, name="mie") - self.mtvec = CSR(0x305, mtvec_layout, name="mtvec") - self.mscratch = CSR(0x340, flat_layout, name="mscratch") # FIXME move elsewhere - self.mepc = CSR(0x341, mepc_layout, name="mepc") - self.mcause = CSR(0x342, mcause_layout, name="mcause") - self.mtval = CSR(0x343, flat_layout, name="mtval") - self.mip = CSR(0x344, mip_layout, name="mip") - self.irq_mask = CSR(0x330, flat_layout, name="irq_mask") - self.irq_pending = CSR(0x360, flat_layout, name="irq_pending") - - self.external_interrupt = Signal(32) - self.timer_interrupt = Signal() - self.software_interrupt = Signal() - - self.m_fetch_misaligned = Signal() - self.m_fetch_error = Signal() - self.m_fetch_badaddr = Signal(30) - self.m_load_misaligned = Signal() - self.m_load_error = Signal() - self.m_store_misaligned = Signal() - self.m_store_error = Signal() - self.m_loadstore_badaddr = Signal(30) - self.m_branch_target = Signal(32) - self.m_illegal = Signal() - self.m_ebreak = Signal() - self.m_ecall = Signal() - self.m_pc = Signal(32) - self.m_instruction = Signal(32) - self.m_result = Signal(32) - self.m_mret = Signal() - self.m_stall = Signal() - self.m_valid = Signal() - - self.m_raise = Signal() - - def elaborate(self, platform): - m = Module() - - for csr in self.iter_csrs(): - with m.If(csr.we): - m.d.sync += csr.r.eq(csr.w) - - trap_pe = m.submodules.trap_pe = PriorityEncoder(16) - m.d.comb += [ - trap_pe.i[Cause.FETCH_MISALIGNED ].eq(self.m_fetch_misaligned), - trap_pe.i[Cause.FETCH_ACCESS_FAULT ].eq(self.m_fetch_error), - trap_pe.i[Cause.ILLEGAL_INSTRUCTION].eq(self.m_illegal), - trap_pe.i[Cause.BREAKPOINT ].eq(self.m_ebreak), - trap_pe.i[Cause.LOAD_MISALIGNED ].eq(self.m_load_misaligned), - trap_pe.i[Cause.LOAD_ACCESS_FAULT ].eq(self.m_load_error), - trap_pe.i[Cause.STORE_MISALIGNED ].eq(self.m_store_misaligned), - trap_pe.i[Cause.STORE_ACCESS_FAULT ].eq(self.m_store_error), - trap_pe.i[Cause.ECALL_FROM_M ].eq(self.m_ecall) - ] - - m.d.sync += [ - self.irq_pending.r.eq(self.external_interrupt & self.irq_mask.r), - self.mip.r.msip.eq(self.software_interrupt), - self.mip.r.mtip.eq(self.timer_interrupt), - self.mip.r.meip.eq(self.irq_pending.r.bool()) - ] - - interrupt_pe = m.submodules.interrupt_pe = PriorityEncoder(16) - m.d.comb += [ - interrupt_pe.i[Cause.M_SOFTWARE_INTERRUPT].eq(self.mip.r.msip & self.mie.r.msie), - interrupt_pe.i[Cause.M_TIMER_INTERRUPT ].eq(self.mip.r.mtip & self.mie.r.mtie), - interrupt_pe.i[Cause.M_EXTERNAL_INTERRUPT].eq(self.mip.r.meip & self.mie.r.meie) - ] - - m.d.comb += self.m_raise.eq(~trap_pe.n | ~interrupt_pe.n & self.mstatus.r.mie) - - with m.If(self.m_valid & ~self.m_stall): - with m.If(self.m_raise): - m.d.sync += [ - self.mstatus.r.mpie.eq(self.mstatus.r.mie), - self.mstatus.r.mie.eq(0), - self.mepc.r.base.eq(self.m_pc[2:]) - ] - with m.If(~trap_pe.n): - m.d.sync += [ - self.mcause.r.ecode.eq(trap_pe.o), - self.mcause.r.interrupt.eq(0) - ] - with m.Switch(trap_pe.o): - with m.Case(Cause.FETCH_MISALIGNED): - m.d.sync += self.mtval.r.eq(self.m_branch_target) - with m.Case(Cause.FETCH_ACCESS_FAULT): - m.d.sync += self.mtval.r.eq(self.m_fetch_badaddr << 2) - with m.Case(Cause.ILLEGAL_INSTRUCTION): - m.d.sync += self.mtval.r.eq(self.m_instruction) - with m.Case(Cause.BREAKPOINT): - m.d.sync += self.mtval.r.eq(self.m_pc) - with m.Case(Cause.LOAD_MISALIGNED, Cause.STORE_MISALIGNED): - m.d.sync += self.mtval.r.eq(self.m_result) - with m.Case(Cause.LOAD_ACCESS_FAULT, Cause.STORE_ACCESS_FAULT): - m.d.sync += self.mtval.r.eq(self.m_loadstore_badaddr << 2) - with m.Case(): - m.d.sync += self.mtval.r.eq(0) - with m.Else(): - m.d.sync += [ - self.mcause.r.ecode.eq(interrupt_pe.o), - self.mcause.r.interrupt.eq(1) - ] - with m.Elif(self.m_mret): - m.d.sync += self.mstatus.r.mie.eq(self.mstatus.r.mpie) - - return m diff --git a/src/soc/minerva/units/logic.py b/src/soc/minerva/units/logic.py deleted file mode 100644 index 143cd7f8..00000000 --- a/src/soc/minerva/units/logic.py +++ /dev/null @@ -1,28 +0,0 @@ -from nmigen import Elaboratable, Module, Signal - -from ..isa import Funct3 - - -__all__ = ["LogicUnit"] - - -class LogicUnit(Elaboratable): - def __init__(self): - self.op = Signal(3) - self.src1 = Signal(32) - self.src2 = Signal(32) - - self.result = Signal(32) - - def elaborate(self, platform): - m = Module() - - with m.Switch(self.op): - with m.Case(Funct3.XOR): - m.d.comb += self.result.eq(self.src1 ^ self.src2) - with m.Case(Funct3.OR): - m.d.comb += self.result.eq(self.src1 | self.src2) - with m.Case(Funct3.AND): - m.d.comb += self.result.eq(self.src1 & self.src2) - - return m diff --git a/src/soc/minerva/units/multiplier.py b/src/soc/minerva/units/multiplier.py deleted file mode 100644 index f5a0a59e..00000000 --- a/src/soc/minerva/units/multiplier.py +++ /dev/null @@ -1,86 +0,0 @@ -from nmigen import Elaboratable, Module, Signal, Cat, Mux, C, signed - -from ..isa import Funct3 - - -__all__ = ["MultiplierInterface", "Multiplier", "DummyMultiplier"] - - -class MultiplierInterface: - def __init__(self): - self.x_op = Signal(3) - self.x_src1 = Signal(32) - self.x_src2 = Signal(32) - self.x_stall = Signal() - self.m_stall = Signal() - - self.w_result = Signal(32) - - -class Multiplier(MultiplierInterface, Elaboratable): - def elaborate(self, platform): - m = Module() - - x_low = Signal() - x_src1_signed = Signal() - x_src2_signed = Signal() - - m.d.comb += [ - x_low.eq(self.x_op == Funct3.MUL), - x_src1_signed.eq((self.x_op == Funct3.MULH) | - (self.x_op == Funct3.MULHSU)), - x_src2_signed.eq(self.x_op == Funct3.MULH) - ] - - x_src1 = Signal(signed(33)) - x_src2 = Signal(signed(33)) - - m.d.comb += [ - x_src1.eq(Cat(self.x_src1, x_src1_signed & self.x_src1[31])), - x_src2.eq(Cat(self.x_src2, x_src2_signed & self.x_src2[31])) - ] - - m_low = Signal() - m_prod = Signal(signed(66)) - - with m.If(~self.x_stall): - m.d.sync += [ - m_low.eq(x_low), - m_prod.eq(x_src1 * x_src2) - ] - - with m.If(~self.m_stall): - m.d.sync += self.w_result.eq(Mux(m_low, m_prod[:32], m_prod[32:])) - - return m - - -class DummyMultiplier(MultiplierInterface, Elaboratable): - def elaborate(self, platform): - m = Module() - - x_result = Signal.like(self.w_result) - m_result = Signal.like(self.w_result) - - with m.Switch(self.x_op): - # As per the RVFI specification (§ "Alternative Arithmetic Operations"). - # https://github.com/SymbioticEDA/riscv-formal/blob/master/docs/rvfi.md - with m.Case(Funct3.MUL): - m.d.comb += x_result.eq((self.x_src1 + - self.x_src2) ^ C(0x5876063e)) - with m.Case(Funct3.MULH): - m.d.comb += x_result.eq((self.x_src1 + - self.x_src2) ^ C(0xf6583fb7)) - with m.Case(Funct3.MULHSU): - m.d.comb += x_result.eq((self.x_src1 - - self.x_src2) ^ C(0xecfbe137)) - with m.Case(Funct3.MULHU): - m.d.comb += x_result.eq((self.x_src1 + - self.x_src2) ^ C(0x949ce5e8)) - - with m.If(~self.x_stall): - m.d.sync += m_result.eq(x_result) - with m.If(~self.m_stall): - m.d.sync += self.w_result.eq(m_result) - - return m diff --git a/src/soc/minerva/units/shifter.py b/src/soc/minerva/units/shifter.py deleted file mode 100644 index 4ecd9fc0..00000000 --- a/src/soc/minerva/units/shifter.py +++ /dev/null @@ -1,39 +0,0 @@ -from nmigen import Elaboratable, Module, Signal, Mux, Repl, Cat - - -__all__ = ["Shifter"] - - -class Shifter(Elaboratable): - def __init__(self): - self.x_direction = Signal() - self.x_sext = Signal() - self.x_shamt = Signal(5) - self.x_src1 = Signal(32) - self.x_stall = Signal() - - self.m_result = Signal(32) - - def elaborate(self, platform): - m = Module() - - x_operand = Signal(32) - x_filler = Signal() - m_direction = Signal() - m_result = Signal(32) - - m.d.comb += [ - # left shifts are equivalent to right shifts with reversed bits - x_operand.eq(Mux(self.x_direction, self.x_src1, self.x_src1[::-1])), - x_filler.eq(Mux(self.x_direction & self.x_sext, self.x_src1[-1], 0)) - ] - - with m.If(~self.x_stall): - m.d.sync += [ - m_direction.eq(self.x_direction), - m_result.eq(Cat(x_operand, Repl(x_filler, 32)) >> self.x_shamt) - ] - - m.d.comb += self.m_result.eq(Mux(m_direction, m_result, m_result[::-1])) - - return m diff --git a/src/soc/minerva/units/trigger.py b/src/soc/minerva/units/trigger.py deleted file mode 100644 index 203b6081..00000000 --- a/src/soc/minerva/units/trigger.py +++ /dev/null @@ -1,109 +0,0 @@ -from functools import reduce -from operator import or_ - -from nmigen import Elaboratable, Module, Signal, Record - -from ..csr import AutoCSR, CSR -from ..isa import flat_layout, tdata1_layout - - -__all__ = ["TriggerUnit"] - - -class Type: - NOP = 0 - LEGACY = 1 - MATCH = 2 - INSN_COUNT = 3 - INTERRUPT = 4 - EXCEPTION = 5 - - -mcontrol_layout = [ - ("load", 1), - ("store", 1), - ("execute", 1), - ("u", 1), - ("s", 1), - ("zero0", 1), - ("m", 1), - ("match", 4), - ("chain", 1), - ("action", 4), - ("size", 2), - ("timing", 1), - ("select", 1), - ("hit", 1), - ("maskmax", 6) -] - - -class TriggerUnit(Elaboratable, AutoCSR): - def __init__(self, nb_triggers): - self.nb_triggers = nb_triggers - - self.tselect = CSR(0x7a0, flat_layout, name="tselect") - self.tdata1 = CSR(0x7a1, tdata1_layout, name="tdata1") - self.tdata2 = CSR(0x7a2, flat_layout, name="tdata2") - - self.x_pc = Signal(32) - self.x_valid = Signal() - - self.haltreq = Signal() - self.trap = Signal() - - def elaborate(self, platform): - m = Module() - - triggers = [Record.like(self.tdata1.r) for _ in range(self.nb_triggers)] - for t in triggers: - # We only support address/data match triggers. - m.d.comb += t.type.eq(Type.MATCH) - - def do_trigger_update(trigger): - m.d.sync += trigger.dmode.eq(self.tdata1.w.dmode) - mcontrol = Record([("i", mcontrol_layout), ("o", mcontrol_layout)]) - m.d.comb += [ - mcontrol.i.eq(self.tdata1.w.data), - mcontrol.o.execute.eq(mcontrol.i.execute), - mcontrol.o.m.eq(mcontrol.i.m), - mcontrol.o.action.eq(mcontrol.i.action), - ] - m.d.sync += trigger.data.eq(mcontrol.o) - - with m.Switch(self.tselect.r.value): - for i, t in enumerate(triggers): - with m.Case(i): - m.d.comb += self.tdata1.r.eq(t) - with m.If(self.tdata1.we): - do_trigger_update(t) - - with m.If(self.tselect.we): - with m.If(self.tselect.w.value < self.nb_triggers): - m.d.sync += self.tselect.r.value.eq(self.tselect.w.value) - - with m.If(self.tdata2.we): - m.d.sync += self.tdata2.r.eq(self.tdata2.w) - - hit = Signal() - halt = Signal() - - with m.Switch(self.tdata1.r.type): - with m.Case(Type.MATCH): - mcontrol = Record(mcontrol_layout) - m.d.comb += mcontrol.eq(self.tdata1.r.data) - match = Signal() - with m.If(mcontrol.execute): - m.d.comb += match.eq(self.tdata2.r == self.x_pc & self.x_valid) - m.d.comb += [ - hit.eq(match & mcontrol.m), - halt.eq(mcontrol.action) - ] - - with m.If(hit): - with m.If(halt): - m.d.comb += self.haltreq.eq(self.tdata1.r.dmode) - with m.Else(): - m.d.comb += self.trap.eq(1) - - return m -- 2.30.2