From a325393c42c92a221751fcb61d03aba3d8424116 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Nguyen?= Date: Mon, 25 Jul 2022 15:16:52 +0200 Subject: [PATCH] Add checks for multiplication/division instructions. --- cores/microwatt/checks.pfv | 2 +- cores/microwatt/microwatt/core.py | 4 +- power_fv/check/insn/__init__.py | 2 +- power_fv/check/insn/all.py | 1 + power_fv/check/insn/muldiv.py | 46 +++++ power_fv/insn/const.py | 32 ++++ power_fv/insn/spec/muldiv.py | 295 ++++++++++++++++++++++++++++++ power_fv/pfv.py | 3 +- 8 files changed, 381 insertions(+), 4 deletions(-) create mode 100644 power_fv/check/insn/muldiv.py create mode 100644 power_fv/insn/spec/muldiv.py diff --git a/cores/microwatt/checks.pfv b/cores/microwatt/checks.pfv index 93f5c38..5b5602a 100644 --- a/cores/microwatt/checks.pfv +++ b/cores/microwatt/checks.pfv @@ -1,7 +1,7 @@ check unique --depth=15 --skip=12 check cia --depth=15 check gpr --depth=15 -check insn --depth=15 --exclude=brh,brw,setbc,setbcr,setnbc,setnbcr +check insn --depth=17 --exclude=brh,brw,setbc,setbcr,setnbc,setnbcr check microwatt:storage:data --depth=15 diff --git a/cores/microwatt/microwatt/core.py b/cores/microwatt/microwatt/core.py index f2e7da1..1d1aeeb 100644 --- a/cores/microwatt/microwatt/core.py +++ b/cores/microwatt/microwatt/core.py @@ -102,6 +102,7 @@ class MicrowattWrapper(Elaboratable): HAS_BTC => {has_btc}, HAS_SHORT_MULT => false, HAS_POWERFV => true, + HAS_ALTOPS => true, LOG_LENGTH => 0, ICACHE_NUM_LINES => {icache_num_lines}, ICACHE_NUM_WAYS => {icache_num_ways}, @@ -133,7 +134,8 @@ class MicrowattWrapper(Elaboratable): end architecture behave; """) - self.pfv = pfv.Interface(mem_aligned=False, illegal_insn_heai=False) + def __init__(self, *, bus_fairness=False, **kwargs): + self.pfv = pfv.Interface(mem_aligned=False, illegal_insn_heai=False, muldiv_altops=True) self.wb_insn = wishbone.Interface(addr_width=29, data_width=64, granularity=8, features=("stall",)) self.wb_data = wishbone.Interface(addr_width=29, data_width=64, granularity=8, diff --git a/power_fv/check/insn/__init__.py b/power_fv/check/insn/__init__.py index f3b99b4..09203f8 100644 --- a/power_fv/check/insn/__init__.py +++ b/power_fv/check/insn/__init__.py @@ -28,7 +28,7 @@ class InsnCheck(PowerFVCheck, metaclass=InsnCheckMeta): def __init__(self, *, depth, skip, core, **kwargs): super().__init__(depth=depth, skip=skip, core=core, **kwargs) self.insn = self.insn_cls() - self.spec = self.spec_cls(self.insn, mem_aligned=self.dut.pfv.mem_aligned) + self.spec = self.spec_cls(self.insn, mem_aligned=self.dut.pfv.mem_aligned, muldiv_altops=self.dut.pfv.muldiv_altops) def testbench(self): return InsnTestbench(self) diff --git a/power_fv/check/insn/all.py b/power_fv/check/insn/all.py index 5b45a55..01e5d56 100644 --- a/power_fv/check/insn/all.py +++ b/power_fv/check/insn/all.py @@ -1,4 +1,5 @@ from .addsub import * +from .muldiv import * from .branch import * from .syscall import * from .loadstore import * diff --git a/power_fv/check/insn/muldiv.py b/power_fv/check/insn/muldiv.py new file mode 100644 index 0000000..8b4466a --- /dev/null +++ b/power_fv/check/insn/muldiv.py @@ -0,0 +1,46 @@ +from power_fv.insn import const +from power_fv.insn.spec.muldiv import MultiplySpec, DivideSpec +from power_fv.check.insn import InsnCheck + + +__all__ = [ + "MULLI" , + "MULLW" , "MULLW_" , "MULLWO" , "MULLWO_" , + "MULHW" , "MULHW_" , "MULHWU" , "MULHWU_" , + "DIVW" , "DIVW_" , "DIVWO" , "DIVWO_" , + "DIVWU" , "DIVWU_" , "DIVWUO" , "DIVWUO_" , + "DIVWE" , "DIVWE_" , "DIVWEO" , "DIVWEO_" , + "DIVWEU", "DIVWEU_", "DIVWEUO", "DIVWEUO_", + "MODSW" , "MODUW" , +] + + +class MULLI (InsnCheck, spec_cls=MultiplySpec, insn_cls=const.MULLI ): pass +class MULLW (InsnCheck, spec_cls=MultiplySpec, insn_cls=const.MULLW ): pass +class MULLW_ (InsnCheck, spec_cls=MultiplySpec, insn_cls=const.MULLW_ ): pass +class MULLWO (InsnCheck, spec_cls=MultiplySpec, insn_cls=const.MULLWO ): pass +class MULLWO_ (InsnCheck, spec_cls=MultiplySpec, insn_cls=const.MULLWO_): pass +class MULHW (InsnCheck, spec_cls=MultiplySpec, insn_cls=const.MULHW ): pass +class MULHW_ (InsnCheck, spec_cls=MultiplySpec, insn_cls=const.MULHW_ ): pass +class MULHWU (InsnCheck, spec_cls=MultiplySpec, insn_cls=const.MULHWU ): pass +class MULHWU_ (InsnCheck, spec_cls=MultiplySpec, insn_cls=const.MULHWU_): pass + +class DIVW (InsnCheck, spec_cls=DivideSpec, insn_cls=const.DIVW ): pass +class DIVW_ (InsnCheck, spec_cls=DivideSpec, insn_cls=const.DIVW_ ): pass +class DIVWO (InsnCheck, spec_cls=DivideSpec, insn_cls=const.DIVWO ): pass +class DIVWO_ (InsnCheck, spec_cls=DivideSpec, insn_cls=const.DIVWO_ ): pass +class DIVWU (InsnCheck, spec_cls=DivideSpec, insn_cls=const.DIVWU ): pass +class DIVWU_ (InsnCheck, spec_cls=DivideSpec, insn_cls=const.DIVWU_ ): pass +class DIVWUO (InsnCheck, spec_cls=DivideSpec, insn_cls=const.DIVWUO ): pass +class DIVWUO_ (InsnCheck, spec_cls=DivideSpec, insn_cls=const.DIVWUO_ ): pass +class DIVWE (InsnCheck, spec_cls=DivideSpec, insn_cls=const.DIVWE ): pass +class DIVWE_ (InsnCheck, spec_cls=DivideSpec, insn_cls=const.DIVWE_ ): pass +class DIVWEO (InsnCheck, spec_cls=DivideSpec, insn_cls=const.DIVWEO ): pass +class DIVWEO_ (InsnCheck, spec_cls=DivideSpec, insn_cls=const.DIVWEO_ ): pass +class DIVWEU (InsnCheck, spec_cls=DivideSpec, insn_cls=const.DIVWEU ): pass +class DIVWEU_ (InsnCheck, spec_cls=DivideSpec, insn_cls=const.DIVWEU_ ): pass +class DIVWEUO (InsnCheck, spec_cls=DivideSpec, insn_cls=const.DIVWEUO ): pass +class DIVWEUO_(InsnCheck, spec_cls=DivideSpec, insn_cls=const.DIVWEUO_): pass + +class MODSW (InsnCheck, spec_cls=DivideSpec, insn_cls=const.MODSW): pass +class MODUW (InsnCheck, spec_cls=DivideSpec, insn_cls=const.MODUW): pass diff --git a/power_fv/insn/const.py b/power_fv/insn/const.py index 4cf40c6..63f5dfe 100644 --- a/power_fv/insn/const.py +++ b/power_fv/insn/const.py @@ -143,6 +143,38 @@ class NEG_ (WordInsn): _fields = (f.PO(31), f.RT(), f.RA(), f.RB(), f.OE(0), class NEGO (WordInsn): _fields = (f.PO(31), f.RT(), f.RA(), f.RB(), f.OE(1), f.XO(104), f.Rc(0)) class NEGO_ (WordInsn): _fields = (f.PO(31), f.RT(), f.RA(), f.RB(), f.OE(1), f.XO(104), f.Rc(1)) +# Multiply / Divide / Modulo + +class MULLI (WordInsn): _fields = (f.PO( 7), f.RT(), f.RA(), f.SI()) +class MULLW (WordInsn): _fields = (f.PO(31), f.RT(), f.RA(), f.RB(), f.OE(0), f.XO(235), f.Rc(0)) +class MULLW_ (WordInsn): _fields = (f.PO(31), f.RT(), f.RA(), f.RB(), f.OE(0), f.XO(235), f.Rc(1)) +class MULLWO (WordInsn): _fields = (f.PO(31), f.RT(), f.RA(), f.RB(), f.OE(1), f.XO(235), f.Rc(0)) +class MULLWO_ (WordInsn): _fields = (f.PO(31), f.RT(), f.RA(), f.RB(), f.OE(1), f.XO(235), f.Rc(1)) +class MULHW (WordInsn): _fields = (f.PO(31), f.RT(), f.RA(), f.RB(), f.XO( 75), f.Rc(0)) +class MULHW_ (WordInsn): _fields = (f.PO(31), f.RT(), f.RA(), f.RB(), f.XO( 75), f.Rc(1)) +class MULHWU (WordInsn): _fields = (f.PO(31), f.RT(), f.RA(), f.RB(), f.XO( 11), f.Rc(0)) +class MULHWU_ (WordInsn): _fields = (f.PO(31), f.RT(), f.RA(), f.RB(), f.XO( 11), f.Rc(1)) + +class DIVW (WordInsn): _fields = (f.PO(31), f.RT(), f.RA(), f.RB(), f.OE(0), f.XO(491), f.Rc(0)) +class DIVW_ (WordInsn): _fields = (f.PO(31), f.RT(), f.RA(), f.RB(), f.OE(0), f.XO(491), f.Rc(1)) +class DIVWO (WordInsn): _fields = (f.PO(31), f.RT(), f.RA(), f.RB(), f.OE(1), f.XO(491), f.Rc(0)) +class DIVWO_ (WordInsn): _fields = (f.PO(31), f.RT(), f.RA(), f.RB(), f.OE(1), f.XO(491), f.Rc(1)) +class DIVWU (WordInsn): _fields = (f.PO(31), f.RT(), f.RA(), f.RB(), f.OE(0), f.XO(459), f.Rc(0)) +class DIVWU_ (WordInsn): _fields = (f.PO(31), f.RT(), f.RA(), f.RB(), f.OE(0), f.XO(459), f.Rc(1)) +class DIVWUO (WordInsn): _fields = (f.PO(31), f.RT(), f.RA(), f.RB(), f.OE(1), f.XO(459), f.Rc(0)) +class DIVWUO_ (WordInsn): _fields = (f.PO(31), f.RT(), f.RA(), f.RB(), f.OE(1), f.XO(459), f.Rc(1)) +class DIVWE (WordInsn): _fields = (f.PO(31), f.RT(), f.RA(), f.RB(), f.OE(0), f.XO(427), f.Rc(0)) +class DIVWE_ (WordInsn): _fields = (f.PO(31), f.RT(), f.RA(), f.RB(), f.OE(0), f.XO(427), f.Rc(1)) +class DIVWEO (WordInsn): _fields = (f.PO(31), f.RT(), f.RA(), f.RB(), f.OE(1), f.XO(427), f.Rc(0)) +class DIVWEO_ (WordInsn): _fields = (f.PO(31), f.RT(), f.RA(), f.RB(), f.OE(1), f.XO(427), f.Rc(1)) +class DIVWEU (WordInsn): _fields = (f.PO(31), f.RT(), f.RA(), f.RB(), f.OE(0), f.XO(395), f.Rc(0)) +class DIVWEU_ (WordInsn): _fields = (f.PO(31), f.RT(), f.RA(), f.RB(), f.OE(0), f.XO(395), f.Rc(1)) +class DIVWEUO (WordInsn): _fields = (f.PO(31), f.RT(), f.RA(), f.RB(), f.OE(1), f.XO(395), f.Rc(0)) +class DIVWEUO_(WordInsn): _fields = (f.PO(31), f.RT(), f.RA(), f.RB(), f.OE(1), f.XO(395), f.Rc(1)) + +class MODSW (WordInsn): _fields = (f.PO(31), f.RT(), f.RA(), f.RB(), f.XO_X(779)) +class MODUW (WordInsn): _fields = (f.PO(31), f.RT(), f.RA(), f.RB(), f.XO_X(267)) + # Compare class CMPI (WordInsn): _fields = (f.PO(11), f.BF(), f.L_D10(), f.RA(), f.SI()) diff --git a/power_fv/insn/spec/muldiv.py b/power_fv/insn/spec/muldiv.py new file mode 100644 index 0000000..42d03f9 --- /dev/null +++ b/power_fv/insn/spec/muldiv.py @@ -0,0 +1,295 @@ +from amaranth import * +from amaranth.asserts import Assume + +from power_fv import pfv +from power_fv.insn.const import * + +from . import InsnSpec +from .utils import iea + + +__all__ = ["MultiplySpec", "DivideSpec"] + + +class MultiplySpec(InsnSpec, Elaboratable): + def elaborate(self, platform): + m = Module() + + m.d.comb += [ + self.pfv.stb .eq(1), + self.pfv.insn.eq(Cat(Const(0, 32), self.insn.as_value())), + self.pfv.intr.eq(0), + self.pfv.nia .eq(iea(self.pfv.cia + 4, self.pfv.msr.r_data.sf)), + self.pfv.msr.r_mask.sf.eq(1), + ] + + src_a = Signal(64) + src_b = Signal(64) + result = Signal(64) + ov_32 = Signal() + + # Operand A : (RA) or EXTS((RA)(32:63)) or EXTZ((RA)(32:63)) + + m.d.comb += [ + self.pfv.ra.index.eq(self.insn.RA), + self.pfv.ra.r_stb.eq(1), + ] + + if isinstance(self.insn, MULLI): + m.d.comb += src_a.eq(self.pfv.ra.r_data) + elif isinstance(self.insn, ( + MULLW , MULLW_ , MULLWO, MULLWO_, + MULHW, MULHW_, + )): + m.d.comb += src_a.eq(self.pfv.ra.r_data[:32].as_signed()) + elif isinstance(self.insn, (MULHWU, MULHWU_)): + m.d.comb += src_a.eq(self.pfv.ra.r_data[:32].as_unsigned()) + else: + assert False + + # Operand B : EXTS(SI) or EXTS((RB)(32:63)) or EXTZ((RB)(32:63)) + + if isinstance(self.insn, MULLI): + m.d.comb += src_b.eq(self.insn.SI) + elif isinstance(self.insn, ( + MULLW, MULLW_, MULLWO, MULLWO_, + MULHW, MULHW_, + )): + m.d.comb += [ + self.pfv.rb.index .eq(self.insn.RB), + self.pfv.rb.r_stb.eq(1), + src_b.eq(self.pfv.rb.r_data[:32].as_signed()), + ] + elif isinstance(self.insn, (MULHWU, MULHWU_)): + m.d.comb += [ + self.pfv.rb.index.eq(self.insn.RB), + self.pfv.rb.r_stb.eq(1), + src_b.eq(self.pfv.rb.r_data[:32].as_unsigned()) + ] + else: + assert False + + if self.pfv.muldiv_altops: + altop_res = Signal(64) + altop_mask = Signal(64) + ca_32 = Signal() + + if isinstance(self.insn, MULLI): + m.d.comb += altop_mask.eq(0xef31a883837039a0) + elif isinstance(self.insn, (MULLW, MULLW_)): + m.d.comb += altop_mask.eq(0x4931591f31f56de1) + elif isinstance(self.insn, (MULLWO, MULLWO_)): + m.d.comb += altop_mask.eq(0x37291ea821fbaf9d) + elif isinstance(self.insn, (MULHW, MULHW_)): + m.d.comb += altop_mask.eq(0x3426dcf55920989c) + elif isinstance(self.insn, (MULHWU, MULHWU_)): + m.d.comb += altop_mask.eq(0x491edb8a5f695d49) + else: + assert False + + # Result : (Operand A + Operand B) ^ Altop Mask + + m.d.comb += [ + altop_res.eq(src_a + src_b), + ca_32.eq(altop_res[32] ^ src_a[32] ^ src_b[32]), + ov_32.eq((ca_32 ^ altop_res[31]) & ~(src_a[31] ^ src_b[31])), + + result.eq(altop_res ^ altop_mask), + ] + + else: + raise NotImplementedError + + # Write the result to RT + + m.d.comb += [ + self.pfv.rt.index .eq(self.insn.RT), + self.pfv.rt.w_stb .eq(1), + self.pfv.rt.w_data.eq(result), + ] + + # Set XER.{SO,OV,OV32} if the result overflows 32 bits + + if isinstance(self.insn, (MULLWO, MULLWO_)): + m.d.comb += [ + self.pfv.xer.w_mask.ov .eq(1), + self.pfv.xer.w_data.ov .eq(ov_32), + self.pfv.xer.w_mask.ov32.eq(1), + self.pfv.xer.w_data.ov32.eq(ov_32), + ] + with m.If(ov_32): + m.d.comb += [ + self.pfv.xer.w_mask.so.eq(1), + self.pfv.xer.w_data.so.eq(1), + ] + + # Write CR0 + + if isinstance(self.insn, (MULLW_, MULLWO_, MULHW_, MULHWU_)): + cr0_w_mask = Record([("so", 1), ("eq_", 1), ("gt", 1), ("lt", 1)]) + cr0_w_data = Record([("so", 1), ("eq_", 1), ("gt", 1), ("lt", 1)]) + + m.d.comb += [ + self.pfv.xer.r_mask.so.eq(1), + + cr0_w_mask .eq(0b1111), + cr0_w_data.so .eq(Mux(self.pfv.xer.w_mask.so, self.pfv.xer.w_data.so, self.pfv.xer.r_data.so)), + cr0_w_data.eq_.eq(~Mux(self.pfv.msr.r_data.sf, result[:64].any(), result[:32].any())), + cr0_w_data.gt .eq(~(cr0_w_data.lt | cr0_w_data.eq_)), + cr0_w_data.lt .eq(Mux(self.pfv.msr.r_data.sf, result[63], result[31])), + + self.pfv.cr.w_mask.cr0.eq(cr0_w_mask), + self.pfv.cr.w_data.cr0.eq(cr0_w_data), + ] + + return m + + +class DivideSpec(InsnSpec, Elaboratable): + def elaborate(self, platform): + m = Module() + + m.d.comb += [ + self.pfv.stb .eq(1), + self.pfv.insn.eq(Cat(Const(0, 32), self.insn.as_value())), + self.pfv.intr.eq(0), + self.pfv.nia .eq(iea(self.pfv.cia + 4, self.pfv.msr.r_data.sf)), + self.pfv.msr.r_mask.sf.eq(1), + ] + + dividend = Signal(64) + divisor = Signal(64) + result = Signal(64) + ov_32 = Signal() + + # Dividend : (RA)(32:63) or (RA)(32:63)<<32 + + m.d.comb += [ + self.pfv.ra.index.eq(self.insn.RA), + self.pfv.ra.r_stb.eq(1), + ] + + if isinstance(self.insn, (DIVW, DIVW_, DIVWO, DIVWO_, MODSW)): + m.d.comb += dividend.eq(self.pfv.ra.r_data[:32].as_signed()) + elif isinstance(self.insn, (DIVWU, DIVWU_, DIVWUO, DIVWUO_, MODUW)): + m.d.comb += dividend.eq(self.pfv.ra.r_data[:32].as_unsigned()) + elif isinstance(self.insn, ( + DIVWE , DIVWE_ , DIVWEO , DIVWEO_ , + DIVWEU, DIVWEU_, DIVWEUO, DIVWEUO_, + )): + m.d.comb += dividend.eq(Cat(Const(0, 32), self.pfv.ra.r_data[:32])) + else: + assert False + + # Divisor : (RB)(32:63) + + m.d.comb += [ + self.pfv.rb.index.eq(self.insn.RB), + self.pfv.rb.r_stb.eq(1), + ] + + if isinstance(self.insn, ( + DIVW , DIVW_ , DIVWO , DIVWO_ , + DIVWE, DIVWE_, DIVWEO, DIVWEO_, + MODSW, + )): + m.d.comb += divisor.eq(self.pfv.rb.r_data[:32].as_signed()) + elif isinstance(self.insn, ( + DIVWU , DIVWU_ , DIVWUO , DIVWUO_ , + DIVWEU, DIVWEU_, DIVWEUO, DIVWEUO_, + MODUW , + )): + m.d.comb += divisor.eq(self.pfv.rb.r_data[:32].as_unsigned()) + else: + assert False + + if self.pfv.muldiv_altops: + altop_mask = Signal(64) + altop_res = Signal(signed(64)) + ca_32 = Signal() + + if isinstance(self.insn, (DIVW, DIVW_)): + m.d.comb += altop_mask.eq(0x75a5d4895a3e15ba) + elif isinstance(self.insn, (DIVWO, DIVWO_)): + m.d.comb += altop_mask.eq(0x7098f59fd4822d48) + elif isinstance(self.insn, (DIVWU, DIVWU_)): + m.d.comb += altop_mask.eq(0x769c76af68d11402) + elif isinstance(self.insn, (DIVWUO, DIVWUO_)): + m.d.comb += altop_mask.eq(0x6ec48c33b1fe6a8f) + elif isinstance(self.insn, (DIVWE, DIVWE_)): + m.d.comb += altop_mask.eq(0xdfd9d577965d84d2) + elif isinstance(self.insn, (DIVWEO, DIVWEO_)): + m.d.comb += altop_mask.eq(0x88ec39a41f3b07fd) + elif isinstance(self.insn, (DIVWEU, DIVWEU_)): + m.d.comb += altop_mask.eq(0x8fc71f88b966fcf0) + elif isinstance(self.insn, (DIVWEUO, DIVWEUO_)): + m.d.comb += altop_mask.eq(0x893cca367133b0d3) + elif isinstance(self.insn, MODSW): + m.d.comb += altop_mask.eq(0x5ba1758b11ae4e43) + elif isinstance(self.insn, MODUW): + m.d.comb += altop_mask.eq(0x1feb9d95f9f0cea5) + else: + assert False + + # Result : (Dividend - Divisor) ^ Altop Mask + + m.d.comb += [ + altop_res.eq(dividend.as_signed() - divisor.as_signed()), + ca_32.eq(altop_res[32] ^ dividend[32] ^ divisor[32]), + ov_32.eq((ca_32 ^ altop_res[31]) & ~(dividend[31] ^ divisor[31])), + + result.eq(altop_res ^ altop_mask), + ] + + else: + raise NotImplementedError + + # Write the result to RT + + m.d.comb += [ + self.pfv.rt.index .eq(self.insn.RT), + self.pfv.rt.w_stb .eq(1), + self.pfv.rt.w_data.eq(result), + ] + + # Set XER.{SO,OV,OV32} if the result overflows 32 bits + + if isinstance(self.insn, ( + DIVWO , DIVWO_ , DIVWUO , DIVWUO_ , + DIVWEO, DIVWEO_, DIVWEUO, DIVWEUO_, + )): + m.d.comb += [ + self.pfv.xer.w_mask.ov .eq(1), + self.pfv.xer.w_data.ov .eq(ov_32), + self.pfv.xer.w_mask.ov32.eq(1), + self.pfv.xer.w_data.ov32.eq(ov_32), + ] + with m.If(ov_32): + m.d.comb += [ + self.pfv.xer.w_mask.so.eq(1), + self.pfv.xer.w_data.so.eq(1), + ] + + # Write CR0 + + if isinstance(self.insn, ( + DIVW_ , DIVWO_ , DIVWU_ , DIVWUO_ , + DIVWE_, DIVWEO_, DIVWEU_, DIVWEUO_, + )): + cr0_w_mask = Record([("so", 1), ("eq_", 1), ("gt", 1), ("lt", 1)]) + cr0_w_data = Record([("so", 1), ("eq_", 1), ("gt", 1), ("lt", 1)]) + + m.d.comb += [ + self.pfv.xer.r_mask.so.eq(1), + + cr0_w_mask .eq(0b1111), + cr0_w_data.so .eq(Mux(self.pfv.xer.w_mask.so, self.pfv.xer.w_data.so, self.pfv.xer.r_data.so)), + cr0_w_data.eq_.eq(~Mux(self.pfv.msr.r_data.sf, result[:64].any(), result[:32].any())), + cr0_w_data.gt .eq(~(cr0_w_data.lt | cr0_w_data.eq_)), + cr0_w_data.lt .eq(Mux(self.pfv.msr.r_data.sf, result[63], result[31])), + + self.pfv.cr.w_mask.cr0.eq(cr0_w_mask), + self.pfv.cr.w_data.cr0.eq(cr0_w_data), + ] + + return m diff --git a/power_fv/pfv.py b/power_fv/pfv.py index 209aaeb..0aae4f6 100644 --- a/power_fv/pfv.py +++ b/power_fv/pfv.py @@ -51,10 +51,11 @@ class Interface(Record): Instruction strobe. Asserted when the processor retires an instruction. Other signals are only valid when ``stb`` is asserted. """ - def __init__(self, *, mem_aligned=False, illegal_insn_heai=False, + def __init__(self, *, mem_aligned=False, illegal_insn_heai=False, muldiv_altops=False, name=None, src_loc_at=0): self.mem_aligned = bool(mem_aligned) self.illegal_insn_heai = bool(illegal_insn_heai) + self.muldiv_altops = bool(muldiv_altops) layout = [ ("stb" , unsigned( 1)),