Compare commits

...

11 Commits

@ -0,0 +1,111 @@
check unique --depth=15 --skip=10
check gpr --depth=15
#check cia --depth=15
check causal --depth=15

check insn:add --depth=15
check insn:add_ --depth=15
check insn:addc --depth=15
check insn:addc_ --depth=15
check insn:adde --depth=15
check insn:adde_ --depth=15
check insn:addex --depth=15
check insn:addi --depth=15
check insn:addic --depth=15
check insn:addic_ --depth=15
check insn:addis --depth=15
check insn:addme --depth=15
check insn:addme_ --depth=15
check insn:addze --depth=15
check insn:addze_ --depth=15
check insn:neg --depth=15
check insn:neg_ --depth=15
check insn:subf --depth=15
check insn:subf_ --depth=15
check insn:subfc --depth=15
check insn:subfc_ --depth=15
check insn:subfe --depth=15
check insn:subfe_ --depth=15
check insn:subfic --depth=15
check insn:subfme --depth=15
check insn:subfme_ --depth=15
check insn:subfze --depth=15
check insn:subfze_ --depth=15

check insn:and --depth=15
check insn:and_ --depth=15
check insn:andc --depth=15
check insn:andc_ --depth=15
check insn:andi_ --depth=15
check insn:andis_ --depth=15
check insn:eqv --depth=15
check insn:eqv_ --depth=15
check insn:nand --depth=15
check insn:nand_ --depth=15
check insn:nor --depth=15
check insn:nor_ --depth=15
check insn:or --depth=15
check insn:or_ --depth=15
check insn:orc --depth=15
check insn:orc_ --depth=15
check insn:ori --depth=15
check insn:oris --depth=15
check insn:xor --depth=15
check insn:xor_ --depth=15
check insn:xori --depth=15
check insn:xoris --depth=15

check insn:brh --depth=15
check insn:brw --depth=15
check insn:extsb --depth=15
check insn:extsb_ --depth=15
check insn:extsh --depth=15
check insn:extsh_ --depth=15

check insn:crand --depth=15
check insn:crandc --depth=15
check insn:creqv --depth=15
check insn:crnand --depth=15
check insn:crnor --depth=15
check insn:cror --depth=15
check insn:crorc --depth=15
check insn:crxor --depth=15

check insn:mcrf --depth=15

check insn:b --depth=15
check insn:ba --depth=15

check insn:cmpi --depth=15
check insn:cmpli --depth=15
check insn:cmp --depth=15
check insn:cmpl --depth=15

check insn:lbz --depth=15
check insn:lbzx --depth=15
check insn:lha --depth=15
check insn:lhax --depth=15
check insn:lhz --depth=15
check insn:lhzx --depth=15
check insn:lwz --depth=15
check insn:lwbrx --depth=15
check insn:stb --depth=15
check insn:sth --depth=15
check insn:stw --depth=15

check insn:rlwimi --depth=15
check insn:rlwimi_ --depth=15
check insn:rlwinm --depth=15
check insn:rlwinm_ --depth=15
check insn:rlwnm --depth=15
check insn:rlwnm_ --depth=15
check insn:slw --depth=15
check insn:slw_ --depth=15
check insn:sraw --depth=15
check insn:sraw_ --depth=15
check insn:srawi --depth=15
check insn:srawi_ --depth=15
check insn:srw --depth=15
check insn:srw_ --depth=15

build --build-dir=./build

@ -0,0 +1,14 @@
from pathlib import PurePath
from power_fv.session import PowerFVSession

from .core import DinoflyCore
from .check.storage import *


class DinoflySession(PowerFVSession, core_cls=DinoflyCore):
pass


if __name__ == "__main__":
PROG = "python -m {}".format(PurePath(__file__).parent.name)
DinoflySession().main(prog=PROG)

@ -0,0 +1,166 @@
from amaranth import *
from amaranth.asserts import *
from amaranth.utils import log2_int

from amaranth_soc import wishbone

from power_fv.check.storage import *

from ..core import *


__all__ = [
"InsnStorageCheck_Dinofly", "InsnStorageTestbench_Dinofly", "InsnStorageModel_Dinofly",
"DataStorageCheck_Dinofly", "DataStorageTestbench_Dinofly", "DataStorageModel_Dinofly",
]


class InsnStorageCheck_Dinofly(InsnStorageCheck, name=("dinofly", "storage", "insn")):
def __init__(self, *, depth, skip, core, **kwargs):
if not isinstance(core, DinoflyCore):
raise TypeError("Core must be an instance of DinoflyCore, not {!r}"
.format(core))
super().__init__(depth=depth, skip=skip, core=core, **kwargs)

def testbench(self):
return InsnStorageTestbench_Dinofly(self)


class InsnStorageTestbench_Dinofly(InsnStorageTestbench):
def __init__(self, check):
if not isinstance(check, InsnStorageCheck_Dinofly):
raise TypeError("Check must be an instance of InsnStorageCheck_Dinofly, not {!r}"
.format(check))
super().__init__(check)

def storage(self):
return InsnStorageModel_Dinofly(
ibus_addr_width=self.check.dut.ibus.addr_width,
ibus_data_width=self.check.dut.ibus.data_width,
ibus_granularity=self.check.dut.ibus.granularity,
)


class InsnStorageModel_Dinofly(InsnStorageModel, Elaboratable):
def __init__(self, *, ibus_addr_width=30, ibus_data_width=32, ibus_granularity=8):
self.addr = Signal(64)
self.data = Signal(32)
self._ibus = wishbone.Interface(addr_width=ibus_addr_width, data_width=ibus_data_width,
granularity=ibus_granularity)

def connect(self, dut):
assert isinstance(dut, DinoflyWrapper)
assert dut.ibus.addr_width == self._ibus.addr_width
assert dut.ibus.data_width == self._ibus.data_width
assert dut.ibus.granularity == self._ibus.granularity

return self._ibus.eq(dut.ibus)

def elaborate(self, platform):
m = Module()

with m.If(self._ibus.ack):
m.d.comb += [
Assume(self._ibus.cyc & Past(self._ibus.cyc)),
Assume(self._ibus.stb & Past(self._ibus.stb)),
Assume(~Past(self._ibus.ack)),
]

gran_bits = log2_int(self._ibus.data_width // self._ibus.granularity)

m.d.comb += [
self.addr.eq(AnyConst(self._ibus.addr_width + gran_bits)),
self.data.eq(AnyConst(32)),
]

with m.If(self._ibus.cyc & self._ibus.stb & self._ibus.ack & ~ResetSignal("sync")):
if self._ibus.data_width == 32:
with m.If(self.addr == Cat(Const(0b00, 2), self._ibus.adr)):
m.d.comb += Assume(self._ibus.dat_r == self.data)
elif self._ibus.data_width == 64:
with m.If(self.addr == Cat(Const(0b000, 3), self._ibus.adr)):
m.d.comb += Assume(self._ibus.dat_r[:32] == self.data)
with m.If(self.addr == Cat(Const(0b100, 3), self._ibus.adr)):
m.d.comb += Assume(self._ibus.dat_r[32:] == self.data)
else:
assert False

return m


class DataStorageCheck_Dinofly(DataStorageCheck, name=("dinofly", "storage", "data")):
def __init__(self, *, depth, skip, core, **kwargs):
if not isinstance(core, DinoflyCore):
raise TypeError("Core must be an instance of DinoflyCore, not {!r}"
.format(core))
super().__init__(depth=depth, skip=skip, core=core, **kwargs)

def testbench(self):
return DataStorageTestbench_Dinofly(self)


class DataStorageTestbench_Dinofly(DataStorageTestbench):
def __init__(self, check):
if not isinstance(check, DataStorageCheck_Dinofly):
raise TypeError("Check must be an instance of DataStorageCheck_Dinofly, not {!r}"
.format(check))
super().__init__(check)

def storage(self):
return DataStorageModel_Dinofly(
dbus_addr_width=self.check.dut.dbus.addr_width,
dbus_data_width=self.check.dut.dbus.data_width,
dbus_granularity=self.check.dut.dbus.granularity,
)


class DataStorageModel_Dinofly(DataStorageModel, Elaboratable):
def __init__(self, *, dbus_addr_width=30, dbus_data_width=32, dbus_granularity=8):
self.addr = Signal(64)
self._dbus = wishbone.Interface(addr_width=dbus_addr_width, data_width=dbus_data_width,
granularity=dbus_granularity)

def connect(self, dut):
assert isinstance(dut, DinoflyWrapper)
assert dut.dbus.addr_width == self._dbus.addr_width
assert dut.dbus.data_width == self._dbus.data_width
assert dut.dbus.granularity == self._dbus.granularity

return self._dbus.eq(dut.dbus)

def elaborate(self, platform):
m = Module()

dbus_read = Signal()
dbus_write = Signal()

m.d.comb += [
dbus_read .eq(self._dbus.cyc & self._dbus.stb & self._dbus.ack),
dbus_write.eq(self._dbus.cyc & self._dbus.stb & self._dbus.ack & self._dbus.we),
]

with m.If(self._dbus.ack):
m.d.comb += [
Assume(self._dbus.cyc & Past(self._dbus.cyc)),
Assume(self._dbus.stb & Past(self._dbus.stb)),
Assume(~Past(self._dbus.ack)),
]

gran_bits = log2_int(self._dbus.data_width // self._dbus.granularity)
addr_hit = Signal()
value = Signal(self._dbus.data_width)

m.d.comb += [
self.addr.eq(AnyConst(self._dbus.addr_width + gran_bits)),
addr_hit .eq(self._dbus.adr == self.addr[gran_bits:]),
]

with m.If(dbus_read & addr_hit & ~ResetSignal("sync")):
m.d.comb += Assume(self._dbus.dat_r == value)

with m.If(dbus_write & addr_hit):
for i, sel_bit in enumerate(self._dbus.sel):
with m.If(sel_bit):
m.d.sync += value[i*8:i*8+8].eq(self._dbus.dat_w[i*8:i*8+8])

return m

@ -0,0 +1,40 @@
from amaranth import *
from amaranth.asserts import *

from dinofly.core import DinoflyCPU

from power_fv.core import PowerFVCore


__all__ = ["DinoflyWrapper"]


class DinoflyWrapper(Elaboratable):
def __init__(self, **kwargs):
self._cpu = DinoflyCPU(with_pfv=True)
self.pfv = self._cpu.pfv
self.ibus = self._cpu.ibus
self.dbus = self._cpu.dbus

def elaborate(self, platform):
m = Module()

m.submodules.cpu = self._cpu

m.d.comb += [
self.ibus.dat_r.eq(AnySeq(self.ibus.data_width)),
self.ibus.ack .eq(AnySeq(1)),
self.ibus.err .eq(AnySeq(1)),

self.dbus.dat_r.eq(AnySeq(self.dbus.data_width)),
self.dbus.ack .eq(AnySeq(1)),
self.dbus.err .eq(AnySeq(1)),
]

return m


class DinoflyCore(PowerFVCore):
@classmethod
def wrapper(cls, **kwargs):
return DinoflyWrapper(**kwargs)

@ -138,7 +138,7 @@ class MicrowattWrapper(Elaboratable):
""") """)


def __init__(self, *, bus_fairness=False, **kwargs): def __init__(self, *, bus_fairness=False, **kwargs):
self.pfv = pfv.Interface(mem_aligned=False, illegal_insn_heai=False, muldiv_altops=True) self.pfv = pfv.Interface(mem_alignment=0, illegal_insn_heai=False, muldiv_altops=True)
self.wb_insn = wishbone.Interface(addr_width=29, data_width=64, granularity=8, self.wb_insn = wishbone.Interface(addr_width=29, data_width=64, granularity=8,
features=("stall",)) features=("stall",))
self.wb_data = wishbone.Interface(addr_width=29, data_width=64, granularity=8, self.wb_data = wishbone.Interface(addr_width=29, data_width=64, granularity=8,

@ -31,7 +31,7 @@ class InsnCheck(PowerFVCheck, metaclass=InsnCheckMeta):
self.spec = self.spec_cls( self.spec = self.spec_cls(
insn = self.insn, insn = self.insn,
gpr_width = self.dut.pfv.gpr_width, gpr_width = self.dut.pfv.gpr_width,
mem_aligned = self.dut.pfv.mem_aligned, mem_alignment = self.dut.pfv.mem_alignment,
illegal_insn_heai = self.dut.pfv.illegal_insn_heai, illegal_insn_heai = self.dut.pfv.illegal_insn_heai,
muldiv_altops = self.dut.pfv.muldiv_altops, muldiv_altops = self.dut.pfv.muldiv_altops,
) )
@ -215,8 +215,9 @@ class _MemPortTest(Elaboratable):


class _SysRegTest(Elaboratable): class _SysRegTest(Elaboratable):
def __init__(self, check, *, reg): def __init__(self, check, *, reg):
self._dut = getattr(check.dut .pfv, reg) self._dut = getattr(check.dut .pfv, reg)
self._spec = getattr(check.spec.pfv, reg) self._spec = getattr(check.spec.pfv, reg)
self._width = check.dut.pfv.gpr_width


self.valid = Record([ self.valid = Record([
("read" , [("r_mask", 1)]), ("read" , [("r_mask", 1)]),
@ -238,6 +239,7 @@ class _SysRegTest(Elaboratable):
]) ])


def contains(a, mask, b=None): def contains(a, mask, b=None):
mask &= 2**self._width - 1
if b is None: if b is None:
b = mask b = mask
return a & mask == b & mask return a & mask == b & mask

@ -4,9 +4,12 @@ from power_fv.check.insn import InsnCheck




__all__ = [ __all__ = [
"RLWINM", "RLWINM_", "RLWNM", "RLWNM_", "RLWIMI", "RLWIMI_", "RLWINM", "RLWINM_", "RLWNM" , "RLWNM_" , "RLWIMI", "RLWIMI_",
"SLW" , "SLW_" , "RLDICL", "RLDICL_", "RLDICR", "RLDICR_", "RLDIC" , "RLDIC_" ,
"SRW" , "SRW_" , "SRAWI", "SRAWI_", "SRAW" , "SRAW_" , "RLDCL" , "RLDCL_" , "RLDCR" , "RLDCR_" , "RLDIMI", "RLDIMI_",
"SLW" , "SLW_" , "SLD" , "SLD_" ,
"SRW" , "SRW_" , "SRAWI" , "SRAWI_" , "SRAW" , "SRAW_" ,
"SRD" , "SRD_" , "SRADI" , "SRADI_" , "SRAD" , "SRAD_" ,
] ]




@ -16,11 +19,31 @@ class RLWNM (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.RLWNM ): pass
class RLWNM_ (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.RLWNM_ ): pass class RLWNM_ (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.RLWNM_ ): pass
class RLWIMI (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.RLWIMI ): pass class RLWIMI (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.RLWIMI ): pass
class RLWIMI_(InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.RLWIMI_): pass class RLWIMI_(InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.RLWIMI_): pass
class RLDICL (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.RLDICL ): pass
class RLDICL_(InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.RLDICL_): pass
class RLDICR (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.RLDICR ): pass
class RLDICR_(InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.RLDICR_): pass
class RLDIC (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.RLDIC ): pass
class RLDIC_ (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.RLDIC_ ): pass
class RLDCL (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.RLDCL ): pass
class RLDCL_ (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.RLDCL_ ): pass
class RLDCR (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.RLDCR ): pass
class RLDCR_ (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.RLDCR_ ): pass
class RLDIMI (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.RLDIMI ): pass
class RLDIMI_(InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.RLDIMI_): pass
class SLW (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.SLW ): pass class SLW (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.SLW ): pass
class SLW_ (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.SLW_ ): pass class SLW_ (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.SLW_ ): pass
class SLD (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.SLD ): pass
class SLD_ (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.SLD_ ): pass
class SRW (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.SRW ): pass class SRW (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.SRW ): pass
class SRW_ (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.SRW_ ): pass class SRW_ (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.SRW_ ): pass
class SRAWI (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.SRAWI ): pass class SRAWI (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.SRAWI ): pass
class SRAWI_ (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.SRAWI_ ): pass class SRAWI_ (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.SRAWI_ ): pass
class SRAW (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.SRAW ): pass class SRAW (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.SRAW ): pass
class SRAW_ (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.SRAW_ ): pass class SRAW_ (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.SRAW_ ): pass
class SRD (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.SRD ): pass
class SRD_ (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.SRD_ ): pass
class SRADI (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.SRADI ): pass
class SRADI_ (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.SRADI_ ): pass
class SRAD (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.SRAD ): pass
class SRAD_ (InsnCheck, spec_cls=RotateShiftSpec, insn_cls=const.SRAD_ ): pass

@ -57,10 +57,10 @@ class InsnStorageTestbench(Elaboratable, metaclass=ABCMeta):
prefixed.eq(insn_po == 1), prefixed.eq(insn_po == 1),
] ]


with m.If(dut.pfv.stb & ~dut.pfv.intr): with m.If(dut.pfv.stb):
with m.If(dut.pfv.cia == storage.addr): with m.If(dut.pfv.cia == storage.addr):
m.d.comb += Assert(dut.pfv.insn[32:] == storage.data) m.d.comb += Assert(dut.pfv.insn[32:] == storage.data)
with m.If(prefixed & (dut.pfv.cia + 4 == storage.addr)): with m.If(prefixed & (dut.pfv.cia + 4 == storage.addr) & ~dut.pfv.intr):
m.d.comb += Assert(dut.pfv.insn[:32] == storage.data) m.d.comb += Assert(dut.pfv.insn[:32] == storage.data)


return m return m

@ -236,6 +236,19 @@ class RLWNM_ (WordInsn): _fields = (f.PO(23), f.RS(), f.RA(), f.RB(), f.MB(), f
class RLWIMI (WordInsn): _fields = (f.PO(20), f.RS(), f.RA(), f.SH(), f.MB(), f.ME(), f.Rc(0)) class RLWIMI (WordInsn): _fields = (f.PO(20), f.RS(), f.RA(), f.SH(), f.MB(), f.ME(), f.Rc(0))
class RLWIMI_ (WordInsn): _fields = (f.PO(20), f.RS(), f.RA(), f.SH(), f.MB(), f.ME(), f.Rc(1)) class RLWIMI_ (WordInsn): _fields = (f.PO(20), f.RS(), f.RA(), f.SH(), f.MB(), f.ME(), f.Rc(1))


class RLDICL (WordInsn): _fields = (f.PO(30), f.RS(), f.RA(), f.sh1(), f.mb0(), f.mb1(), f.XO_MD(0), f.sh0(), f.Rc(0))
class RLDICL_ (WordInsn): _fields = (f.PO(30), f.RS(), f.RA(), f.sh1(), f.mb0(), f.mb1(), f.XO_MD(0), f.sh0(), f.Rc(1))
class RLDICR (WordInsn): _fields = (f.PO(30), f.RS(), f.RA(), f.sh1(), f.me0(), f.me1(), f.XO_MD(1), f.sh0(), f.Rc(0))
class RLDICR_ (WordInsn): _fields = (f.PO(30), f.RS(), f.RA(), f.sh1(), f.me0(), f.me1(), f.XO_MD(1), f.sh0(), f.Rc(1))
class RLDIC (WordInsn): _fields = (f.PO(30), f.RS(), f.RA(), f.sh1(), f.mb0(), f.mb1(), f.XO_MD(2), f.sh0(), f.Rc(0))
class RLDIC_ (WordInsn): _fields = (f.PO(30), f.RS(), f.RA(), f.sh1(), f.mb0(), f.mb1(), f.XO_MD(2), f.sh0(), f.Rc(1))
class RLDCL (WordInsn): _fields = (f.PO(30), f.RS(), f.RA(), f.RB(), f.mb0(), f.mb1(), f.XO_MDS(8), f.Rc(0))
class RLDCL_ (WordInsn): _fields = (f.PO(30), f.RS(), f.RA(), f.RB(), f.mb0(), f.mb1(), f.XO_MDS(8), f.Rc(1))
class RLDCR (WordInsn): _fields = (f.PO(30), f.RS(), f.RA(), f.RB(), f.me0(), f.me1(), f.XO_MDS(9), f.Rc(0))
class RLDCR_ (WordInsn): _fields = (f.PO(30), f.RS(), f.RA(), f.RB(), f.me0(), f.me1(), f.XO_MDS(9), f.Rc(1))
class RLDIMI (WordInsn): _fields = (f.PO(30), f.RS(), f.RA(), f.sh1(), f.mb0(), f.mb1(), f.XO_MD(3), f.sh0(), f.Rc(0))
class RLDIMI_ (WordInsn): _fields = (f.PO(30), f.RS(), f.RA(), f.sh1(), f.mb0(), f.mb1(), f.XO_MD(3), f.sh0(), f.Rc(1))

class SLW (WordInsn): _fields = (f.PO(31), f.RS(), f.RA(), f.RB(), f.XO_X( 24), f.Rc(0)) class SLW (WordInsn): _fields = (f.PO(31), f.RS(), f.RA(), f.RB(), f.XO_X( 24), f.Rc(0))
class SLW_ (WordInsn): _fields = (f.PO(31), f.RS(), f.RA(), f.RB(), f.XO_X( 24), f.Rc(1)) class SLW_ (WordInsn): _fields = (f.PO(31), f.RS(), f.RA(), f.RB(), f.XO_X( 24), f.Rc(1))
class SRW (WordInsn): _fields = (f.PO(31), f.RS(), f.RA(), f.RB(), f.XO_X(536), f.Rc(0)) class SRW (WordInsn): _fields = (f.PO(31), f.RS(), f.RA(), f.RB(), f.XO_X(536), f.Rc(0))
@ -245,6 +258,15 @@ class SRAWI_ (WordInsn): _fields = (f.PO(31), f.RS(), f.RA(), f.SH(), f.XO_X(82
class SRAW (WordInsn): _fields = (f.PO(31), f.RS(), f.RA(), f.RB(), f.XO_X(792), f.Rc(0)) class SRAW (WordInsn): _fields = (f.PO(31), f.RS(), f.RA(), f.RB(), f.XO_X(792), f.Rc(0))
class SRAW_ (WordInsn): _fields = (f.PO(31), f.RS(), f.RA(), f.RB(), f.XO_X(792), f.Rc(1)) class SRAW_ (WordInsn): _fields = (f.PO(31), f.RS(), f.RA(), f.RB(), f.XO_X(792), f.Rc(1))


class SLD (WordInsn): _fields = (f.PO(31), f.RS(), f.RA(), f.RB(), f.XO_X( 27), f.Rc(0))
class SLD_ (WordInsn): _fields = (f.PO(31), f.RS(), f.RA(), f.RB(), f.XO_X( 27), f.Rc(1))
class SRD (WordInsn): _fields = (f.PO(31), f.RS(), f.RA(), f.RB(), f.XO_X(539), f.Rc(0))
class SRD_ (WordInsn): _fields = (f.PO(31), f.RS(), f.RA(), f.RB(), f.XO_X(539), f.Rc(1))
class SRADI (WordInsn): _fields = (f.PO(31), f.RS(), f.RA(), f.sh1(), f.XO_XS(413), f.sh0(), f.Rc(0))
class SRADI_ (WordInsn): _fields = (f.PO(31), f.RS(), f.RA(), f.sh1(), f.XO_XS(413), f.sh0(), f.Rc(1))
class SRAD (WordInsn): _fields = (f.PO(31), f.RS(), f.RA(), f.RB(), f.XO_X(794), f.Rc(0))
class SRAD_ (WordInsn): _fields = (f.PO(31), f.RS(), f.RA(), f.RB(), f.XO_X(794), f.Rc(1))

# BCD Assist # BCD Assist


class CDTBCD (WordInsn): _fields = (f.PO(31), f.RS(), f.RA(), f.XO_X(282)) class CDTBCD (WordInsn): _fields = (f.PO(31), f.RS(), f.RA(), f.XO_X(282))
@ -271,5 +293,5 @@ class MTSRR0 (WordInsn): _fields = (f.PO(31), f.RS(), f.SPR( 26), f.XO_XFX(467)
class MFSRR0 (WordInsn): _fields = (f.PO(31), f.RT(), f.SPR( 26), f.XO_XFX(339)) class MFSRR0 (WordInsn): _fields = (f.PO(31), f.RT(), f.SPR( 26), f.XO_XFX(339))
class MTSRR1 (WordInsn): _fields = (f.PO(31), f.RS(), f.SPR( 27), f.XO_XFX(467)) class MTSRR1 (WordInsn): _fields = (f.PO(31), f.RS(), f.SPR( 27), f.XO_XFX(467))
class MFSRR1 (WordInsn): _fields = (f.PO(31), f.RT(), f.SPR( 27), f.XO_XFX(339)) class MFSRR1 (WordInsn): _fields = (f.PO(31), f.RT(), f.SPR( 27), f.XO_XFX(339))
class MTTAR (WordInsn): _fields = (f.PO(31), f.RS(), f.SPR(815), f.XO_XFX(467)) class MTTAR (WordInsn): _fields = (f.PO(31), f.RS(), f.SPR(814), f.XO_XFX(467))
class MFTAR (WordInsn): _fields = (f.PO(31), f.RT(), f.SPR(815), f.XO_XFX(339)) class MFTAR (WordInsn): _fields = (f.PO(31), f.RT(), f.SPR(814), f.XO_XFX(339))

@ -28,7 +28,11 @@ class LK (InsnField): _shape = unsigned( 1); _offset = 31; _name = "LK"
class OE (InsnField): _shape = unsigned( 1); _offset = 21; _name = "OE" class OE (InsnField): _shape = unsigned( 1); _offset = 21; _name = "OE"
class PO (InsnField): _shape = unsigned( 6); _offset = 0; _name = "PO" class PO (InsnField): _shape = unsigned( 6); _offset = 0; _name = "PO"
class MB (InsnField): _shape = unsigned( 5); _offset = 21; _name = "MB" class MB (InsnField): _shape = unsigned( 5); _offset = 21; _name = "MB"
class mb0 (InsnField): _shape = unsigned( 1); _offset = 26; _name = "mb0"
class mb1 (InsnField): _shape = unsigned( 5); _offset = 21; _name = "mb1"
class ME (InsnField): _shape = unsigned( 5); _offset = 26; _name = "ME" class ME (InsnField): _shape = unsigned( 5); _offset = 26; _name = "ME"
class me0 (InsnField): _shape = unsigned( 1); _offset = 26; _name = "me0"
class me1 (InsnField): _shape = unsigned( 5); _offset = 21; _name = "me1"
class RA (InsnField): _shape = unsigned( 5); _offset = 11; _name = "RA" class RA (InsnField): _shape = unsigned( 5); _offset = 11; _name = "RA"
class RB (InsnField): _shape = unsigned( 5); _offset = 16; _name = "RB" class RB (InsnField): _shape = unsigned( 5); _offset = 16; _name = "RB"
class Rc (InsnField): _shape = unsigned( 1); _offset = 31; _name = "Rc" class Rc (InsnField): _shape = unsigned( 1); _offset = 31; _name = "Rc"
@ -38,6 +42,8 @@ class SC_30 (InsnField): _shape = unsigned( 1); _offset = 30; _name = "_30"
class SC_31 (InsnField): _shape = unsigned( 1); _offset = 31; _name = "_31" class SC_31 (InsnField): _shape = unsigned( 1); _offset = 31; _name = "_31"
class SI (InsnField): _shape = signed(16); _offset = 16; _name = "SI" class SI (InsnField): _shape = signed(16); _offset = 16; _name = "SI"
class SH (InsnField): _shape = unsigned( 5); _offset = 16; _name = "SH" class SH (InsnField): _shape = unsigned( 5); _offset = 16; _name = "SH"
class sh0 (InsnField): _shape = unsigned( 1); _offset = 30; _name = "sh0"
class sh1 (InsnField): _shape = unsigned( 5); _offset = 16; _name = "sh1"
class TO (InsnField): _shape = unsigned( 5); _offset = 6; _name = "TO" class TO (InsnField): _shape = unsigned( 5); _offset = 6; _name = "TO"
class UI (InsnField): _shape = unsigned(16); _offset = 16; _name = "UI" class UI (InsnField): _shape = unsigned(16); _offset = 16; _name = "UI"
class XFX_11(InsnField): _shape = unsigned( 1); _offset = 11; _name = "_11" class XFX_11(InsnField): _shape = unsigned( 1); _offset = 11; _name = "_11"
@ -47,6 +53,9 @@ class XO_X (InsnField): _shape = unsigned(10); _offset = 21; _name = "XO"
class XO_XFX(InsnField): _shape = unsigned(10); _offset = 21; _name = "XO" class XO_XFX(InsnField): _shape = unsigned(10); _offset = 21; _name = "XO"
class XO_XL (InsnField): _shape = unsigned(10); _offset = 21; _name = "XO" class XO_XL (InsnField): _shape = unsigned(10); _offset = 21; _name = "XO"
class XO_Z23(InsnField): _shape = unsigned( 8); _offset = 23; _name = "XO" class XO_Z23(InsnField): _shape = unsigned( 8); _offset = 23; _name = "XO"
class XO_MD (InsnField): _shape = unsigned( 3); _offset = 27; _name = "XO"
class XO_MDS(InsnField): _shape = unsigned( 4); _offset = 27; _name = "XO"
class XO_XS (InsnField): _shape = unsigned( 9); _offset = 21; _name = "XO"




class SPR(InsnField): class SPR(InsnField):

@ -23,8 +23,8 @@ class CompareSpec(InsnSpec, Elaboratable):
self.pfv.xer.r_mask.so.eq(1), self.pfv.xer.r_mask.so.eq(1),
] ]


src_a = Signal(64) src_a = Signal(self.pfv.gpr_width)
src_b = Signal(64) src_b = Signal(self.pfv.gpr_width)
result = Record([ result = Record([
("so", 1), ("so", 1),
("eq_", 1), ("eq_", 1),
@ -120,7 +120,7 @@ class CompareSpec(InsnSpec, Elaboratable):


elif isinstance(self.insn, CMPEQB): elif isinstance(self.insn, CMPEQB):
_match = 0 _match = 0
for i in range(64//8): for i in range(self.pfv.gpr_width//8):
_match |= (src_a == src_b.word_select(i, width=8)) _match |= (src_a == src_b.word_select(i, width=8))


m.d.comb += result.eq(Cat(Const(0, 2), _match, Const(0, 1))) m.d.comb += result.eq(Cat(Const(0, 2), _match, Const(0, 1)))

@ -118,33 +118,27 @@ class LoadStoreSpec(InsnSpec, Elaboratable):


m.d.comb += ea.eq(iea(ea_base + ea_offset, self.pfv.msr.r_data.sf)) m.d.comb += ea.eq(iea(ea_base + ea_offset, self.pfv.msr.r_data.sf))


byte_offset = Signal(3) # The value of `pfv.mem.addr` must be equal to EA, rounded down to a multiple of
half_offset = Signal(2) # ``2 ** pfv.mem_alignment``.
word_offset = Signal(1)


# If `pfv.mem_aligned` is set, `pfv.mem.addr` points to the dword containing EA. m.d.comb += [
# If `pfv.mem_aligned` is unset, `pfv.mem.addr` is equal to EA. self.pfv.mem.addr[self.pfv.mem_alignment:].eq(ea[self.pfv.mem_alignment:]),
self.pfv.mem.addr[:self.pfv.mem_alignment].eq(0),
]


m.d.comb += self.pfv.mem.addr[3:].eq(ea[3:]) # Raise an Alignment Interrupt if EA is misaligned to the size of the storage operand
# and to ``2 ** pfv.mem_alignment``.


if self.pfv.mem_aligned: byte_offset = Signal(3)
m.d.comb += [ half_offset = Signal(2)
self.pfv.mem.addr[:3].eq(0), word_offset = Signal(1)
byte_offset.eq(ea[:3]),
]
else:
m.d.comb += [
self.pfv.mem.addr[:3].eq(ea[:3]),
byte_offset.eq(0),
]


m.d.comb += [ m.d.comb += [
byte_offset.eq(ea[:self.pfv.mem_alignment]),
half_offset.eq(byte_offset[1:]), half_offset.eq(byte_offset[1:]),
word_offset.eq(byte_offset[2:]), word_offset.eq(byte_offset[2:]),
] ]


# Raise an Alignment Interrupt if EA is misaligned wrt. `pfv.mem`

ea_misaligned = Signal() ea_misaligned = Signal()


if isinstance(self.insn, ( if isinstance(self.insn, (
@ -205,35 +199,35 @@ class LoadStoreSpec(InsnSpec, Elaboratable):
load_result = Signal(64) load_result = Signal(64)


m.d.comb += [ m.d.comb += [
load_byte.eq(self.pfv.mem.r_data.word_select(byte_offset, width= 8)), load_byte.eq(self.pfv.mem.r_data.word_select(7 - byte_offset, width= 8)),
load_half.eq(self.pfv.mem.r_data.word_select(half_offset, width=16)), load_half.eq(self.pfv.mem.r_data.word_select(3 - half_offset, width=16)),
load_word.eq(self.pfv.mem.r_data.word_select(word_offset, width=32)), load_word.eq(self.pfv.mem.r_data.word_select(1 - word_offset, width=32)),
] ]


if isinstance(self.insn, (LBZ, LBZX, LBZU, LBZUX)): if isinstance(self.insn, (LBZ, LBZX, LBZU, LBZUX)):
m.d.comb += [ m.d.comb += [
self.pfv.mem.r_mask.word_select(byte_offset, width=1).eq(0x1), self.pfv.mem.r_mask.word_select(7 - byte_offset, width=1).eq(0x1),
load_result.eq(load_byte.as_unsigned()), load_result.eq(load_byte.as_unsigned()),
] ]
elif isinstance(self.insn, (LHZ, LHZX, LHZU, LHZUX)): elif isinstance(self.insn, (LHZ, LHZX, LHZU, LHZUX)):
m.d.comb += [ m.d.comb += [
self.pfv.mem.r_mask.word_select(half_offset, width=2).eq(0x3), self.pfv.mem.r_mask.word_select(3 - half_offset, width=2).eq(0x3),
load_result.eq(byte_reversed(load_half, ~msr_le).as_unsigned()), load_result.eq(byte_reversed(load_half, msr_le).as_unsigned()),
] ]
elif isinstance(self.insn, (LHA, LHAX, LHAU, LHAUX)): elif isinstance(self.insn, (LHA, LHAX, LHAU, LHAUX)):
m.d.comb += [ m.d.comb += [
self.pfv.mem.r_mask.word_select(half_offset, width=2).eq(0x3), self.pfv.mem.r_mask.word_select(3 - half_offset, width=2).eq(0x3),
load_result.eq(byte_reversed(load_half, ~msr_le).as_signed()) load_result.eq(byte_reversed(load_half, msr_le).as_signed())
] ]
elif isinstance(self.insn, (LWZ, LWZX, LWZU, LWZUX)): elif isinstance(self.insn, (LWZ, LWZX, LWZU, LWZUX)):
m.d.comb += [ m.d.comb += [
self.pfv.mem.r_mask.word_select(word_offset, width=4).eq(0xf), self.pfv.mem.r_mask.word_select(1 - word_offset, width=4).eq(0xf),
load_result.eq(byte_reversed(load_word, ~msr_le).as_unsigned()), load_result.eq(byte_reversed(load_word, msr_le).as_unsigned()),
] ]
elif isinstance(self.insn, LWBRX): elif isinstance(self.insn, LWBRX):
m.d.comb += [ m.d.comb += [
self.pfv.mem.r_mask.word_select(word_offset, width=4).eq(0xf), self.pfv.mem.r_mask.word_select(1 - word_offset, width=4).eq(0xf),
load_result.eq(byte_reversed(load_word, msr_le).as_unsigned()), load_result.eq(byte_reversed(load_word, ~msr_le).as_unsigned()),
] ]
else: else:
assert False assert False
@ -267,28 +261,28 @@ class LoadStoreSpec(InsnSpec, Elaboratable):


if isinstance(self.insn, (STB, STBX, STBU, STBUX)): if isinstance(self.insn, (STB, STBX, STBU, STBUX)):
m.d.comb += [ m.d.comb += [
self.pfv.mem.w_mask.word_select(byte_offset, width=1).eq(0x1), self.pfv.mem.w_mask.word_select(7 - byte_offset, width=1).eq(0x1),
self.pfv.mem.w_data.eq(store_byte), self.pfv.mem.w_data.eq(store_byte),
] ]
elif isinstance(self.insn, (STH, STHX, STHU, STHUX)): elif isinstance(self.insn, (STH, STHX, STHU, STHUX)):
m.d.comb += [ m.d.comb += [
self.pfv.mem.w_mask.word_select(half_offset, width=2).eq(0x3), self.pfv.mem.w_mask.word_select(3 - half_offset, width=2).eq(0x3),
self.pfv.mem.w_data.eq(byte_reversed(store_half, ~msr_le)), self.pfv.mem.w_data.eq(byte_reversed(store_half, msr_le)),
] ]
elif isinstance(self.insn, (STW, STWX, STWU, STWUX)): elif isinstance(self.insn, (STW, STWX, STWU, STWUX)):
m.d.comb += [ m.d.comb += [
self.pfv.mem.w_mask.word_select(word_offset, width=4).eq(0xf), self.pfv.mem.w_mask.word_select(1 - word_offset, width=4).eq(0xf),
self.pfv.mem.w_data.eq(byte_reversed(store_word, ~msr_le)), self.pfv.mem.w_data.eq(byte_reversed(store_word, msr_le)),
] ]
elif isinstance(self.insn, STHBRX): elif isinstance(self.insn, STHBRX):
m.d.comb += [ m.d.comb += [
self.pfv.mem.w_mask.word_select(half_offset, width=2).eq(0x3), self.pfv.mem.w_mask.word_select(3 - half_offset, width=2).eq(0x3),
self.pfv.mem.w_data.eq(byte_reversed(store_half, msr_le)), self.pfv.mem.w_data.eq(byte_reversed(store_half, ~msr_le)),
] ]
elif isinstance(self.insn, STWBRX): elif isinstance(self.insn, STWBRX):
m.d.comb += [ m.d.comb += [
self.pfv.mem.w_mask.word_select(word_offset, width=4).eq(0xf), self.pfv.mem.w_mask.word_select(1 - word_offset, width=4).eq(0xf),
self.pfv.mem.w_data.eq(byte_reversed(store_word, msr_le)), self.pfv.mem.w_data.eq(byte_reversed(store_word, ~msr_le)),
] ]
else: else:
assert False assert False

@ -58,29 +58,51 @@ class RotateShiftSpec(InsnSpec, Elaboratable):


with m.Else(): with m.Else():
src = Signal(unsigned(64)) src = Signal(unsigned(64))
shamt = Signal(unsigned( 6)) shamt = Signal(unsigned( 7))
rotl = Signal(unsigned(64)) rotl = Signal(unsigned(64))
mask = Signal(unsigned(64)) mask = Signal(unsigned(64))
result = Signal(unsigned(64)) result = Signal(unsigned(64))


# Source operand : (RS)(32:63)||(RS)(32:63) # Source operand : (RS)(32:63)||(RS)(32:63) or (RS)


m.d.comb += [ if isinstance(self.insn, (RLWINM, RLWINM_, RLWNM, RLWNM_, RLWIMI, RLWIMI_,
self.pfv.rs.index.eq(self.insn.RS), SLW, SLW_, SRW, SRW_, SRAWI, SRAWI_, SRAW, SRAW_)):
self.pfv.rs.r_stb.eq(1), m.d.comb += [
src.eq(self.pfv.rs.r_data), self.pfv.rs.index.eq(self.insn.RS),
] self.pfv.rs.r_stb.eq(1),
src.eq(Cat(self.pfv.rs.r_data[:32], self.pfv.rs.r_data[:32])),
]
elif isinstance(self.insn, (RLDICL, RLDICL_, RLDICR, RLDICR_, RLDIC, RLDIC_,
RLDCL, RLDCL_, RLDCR, RLDCR_, RLDIMI, RLDIMI_,
SLD, SLD_, SRD, SRD_, SRADI, SRADI_, SRAD, SRAD_)):
m.d.comb += [
self.pfv.rs.index.eq(self.insn.RS),
self.pfv.rs.r_stb.eq(1),
src.eq(self.pfv.rs.r_data),
]
else:
assert False


# Shift amount : SH or (RB)(59:63) # Shift amount : SH or (RB)(59:63) or (RB)(58:63)


if isinstance(self.insn, (RLWINM, RLWINM_, RLWIMI, RLWIMI_, SRAWI, SRAWI_)): if isinstance(self.insn, (RLWINM, RLWINM_, RLWIMI, RLWIMI_, SRAWI, SRAWI_)):
m.d.comb += shamt.eq(self.insn.SH) m.d.comb += shamt.eq(self.insn.SH)
elif isinstance(self.insn, (RLDICL, RLDICL_, RLDICR, RLDICR_, RLDIC, RLDIC_,
RLDIMI, RLDIMI_, SRADI, SRADI_)):
m.d.comb += shamt.eq(Cat(self.insn.sh1, self.insn.sh0))
elif isinstance(self.insn, (RLWNM, RLWNM_, SLW, SLW_, SRW, SRW_, SRAW, SRAW_)): elif isinstance(self.insn, (RLWNM, RLWNM_, SLW, SLW_, SRW, SRW_, SRAW, SRAW_)):
m.d.comb += [ m.d.comb += [
self.pfv.rb.index.eq(self.insn.RB), self.pfv.rb.index.eq(self.insn.RB),
self.pfv.rb.r_stb.eq(1), self.pfv.rb.r_stb.eq(1),
shamt.eq(self.pfv.rb.r_data[:6]), shamt.eq(self.pfv.rb.r_data[:6]),
] ]
elif isinstance(self.insn, (RLDCL, RLDCL_, RLDCR, RLDCR_, SLD, SLD_, SRD, SRD_,
SRAD, SRAD_)):
m.d.comb += [
self.pfv.rb.index.eq(self.insn.RB),
self.pfv.rb.r_stb.eq(1),
shamt.eq(self.pfv.rb.r_data[:7]),
]
else: else:
assert False assert False


@ -93,28 +115,43 @@ class RotateShiftSpec(InsnSpec, Elaboratable):


if isinstance(self.insn, (RLWINM, RLWINM_, RLWNM, RLWNM_, RLWIMI, RLWIMI_)): if isinstance(self.insn, (RLWINM, RLWINM_, RLWNM, RLWNM_, RLWIMI, RLWIMI_)):
m.d.comb += mask.eq(_mask(self.insn.MB+32, self.insn.ME+32)) m.d.comb += mask.eq(_mask(self.insn.MB+32, self.insn.ME+32))
elif isinstance(self.insn, (RLDICL, RLDICL_, RLDCL, RLDCL_)):
m.d.comb += mask.eq(_mask(Cat(self.insn.mb1, self.insn.mb0), 63))
elif isinstance(self.insn, (RLDICR, RLDICR_, RLDCR, RLDCR_)):
m.d.comb += mask.eq(_mask(0, Cat(self.insn.me1, self.insn.me0)))
elif isinstance(self.insn, (RLDIC, RLDIC_, RLDIMI, RLDIMI_)):
m.d.comb += mask.eq(_mask(Cat(self.insn.mb1, self.insn.mb0), 63-shamt))
elif isinstance(self.insn, (SLW, SLW_)): elif isinstance(self.insn, (SLW, SLW_)):
m.d.comb += mask.eq(Mux(shamt[5], 0, _mask(32, 63-shamt))) m.d.comb += mask.eq(Mux(shamt[5], 0, _mask(32, 63-shamt)))
elif isinstance(self.insn, (SRW, SRW_, SRAW, SRAW_)): elif isinstance(self.insn, (SRW, SRW_, SRAW, SRAW_)):
m.d.comb += mask.eq(Mux(shamt[5], 0, _mask(shamt+32, 63))) m.d.comb += mask.eq(Mux(shamt[5], 0, _mask(shamt+32, 63)))
elif isinstance(self.insn, (SRAWI, SRAWI_)): elif isinstance(self.insn, (SRAWI, SRAWI_)):
m.d.comb += mask.eq(_mask(shamt+32, 63)) m.d.comb += mask.eq(_mask(shamt+32, 63))
elif isinstance(self.insn, (SLD, SLD_)):
m.d.comb += mask.eq(Mux(shamt[6], 0, _mask(0, 63-shamt)))
elif isinstance(self.insn, (SRD, SRD_, SRAD, SRAD_)):
m.d.comb += mask.eq(Mux(shamt[6], 0, _mask(shamt, 63)))
elif isinstance(self.insn, (SRADI, SRADI_)):
m.d.comb += mask.eq(_mask(shamt, 63))
else: else:
assert False assert False


# Rotation # Rotation


def _rotl32(src, n): def _rotl(src, n):
v = Repl(src[:32], 2) return ((src << n) | (src >> 64-n)) & Repl(1, 64)
return ((v << n) | (v >> 64-n)) & Repl(1, 64)


if isinstance(self.insn, ( if isinstance(self.insn, (RLWINM, RLWINM_, RLWNM, RLWNM_, RLWIMI, RLWIMI_,
RLWINM, RLWINM_, RLWNM, RLWNM_, RLWIMI, RLWIMI_, SLW, SLW_)):
SLW, SLW_, m.d.comb += rotl.eq(_rotl(src, shamt[:5]))
)): elif isinstance(self.insn, (RLDICL, RLDICL_, RLDICR, RLDICR_, RLDIC, RLDIC_,
m.d.comb += rotl.eq(_rotl32(src, shamt)) RLDCL, RLDCL_, RLDCR, RLDCR_, RLDIMI, RLDIMI_,
SLD, SLD_)):
m.d.comb += rotl.eq(_rotl(src, shamt[:6]))
elif isinstance(self.insn, (SRW, SRW_, SRAWI, SRAWI_, SRAW, SRAW_)): elif isinstance(self.insn, (SRW, SRW_, SRAWI, SRAWI_, SRAW, SRAW_)):
m.d.comb += rotl.eq(_rotl32(src, 64-shamt)) m.d.comb += rotl.eq(_rotl(src, 64-shamt[:5]))
elif isinstance(self.insn, (SRD, SRD_, SRADI, SRADI_, SRAD, SRAD_)):
m.d.comb += rotl.eq(_rotl(src, 64-shamt[:6]))
else: else:
assert False assert False


@ -126,21 +163,25 @@ class RotateShiftSpec(InsnSpec, Elaboratable):
self.pfv.ra.w_data.eq(result), self.pfv.ra.w_data.eq(result),
] ]


if isinstance(self.insn, (RLWINM, RLWINM_, RLWNM, RLWNM_, SLW, SLW_, SRW, SRW_)): if isinstance(self.insn, (RLWINM, RLWINM_, RLWNM, RLWNM_, RLDICL, RLDICL_,
RLDICR, RLDICR_, RLDIC, RLDIC_, RLDCL, RLDCL_,
RLDCR, RLDCR_, SLW, SLW_, SRW, SRW_, SLD, SLD_, SRD, SRD_)):
m.d.comb += result.eq(rotl & mask) m.d.comb += result.eq(rotl & mask)
elif isinstance(self.insn, (RLWIMI, RLWIMI_)): elif isinstance(self.insn, (RLWIMI, RLWIMI_, RLDIMI, RLDIMI_)):
m.d.comb += self.pfv.ra.r_stb.eq(1) m.d.comb += self.pfv.ra.r_stb.eq(1)
m.d.comb += result.eq(rotl & mask | self.pfv.ra.r_data & ~mask) m.d.comb += result.eq(rotl & mask | self.pfv.ra.r_data & ~mask)
elif isinstance(self.insn, (SRAWI, SRAWI_, SRAW, SRAW_)): elif isinstance(self.insn, (SRAWI, SRAWI_, SRAW, SRAW_)):
m.d.comb += result.eq(rotl & mask | Repl(src[31], 64) & ~mask) m.d.comb += result.eq(rotl & mask | Repl(src[31], 64) & ~mask)
elif isinstance(self.insn, (SRADI, SRADI_, SRAD, SRAD_)):
m.d.comb += result.eq(rotl & mask | Repl(src[63], 64) & ~mask)
else: else:
assert False assert False


# Write CR0 # Write CR0


if isinstance(self.insn, ( if isinstance(self.insn, (
RLWINM_, RLWNM_, RLWIMI_, SLW_, SRW_, SRAWI_, SRAW_, RLWINM_, RLWNM_, RLWIMI_, RLDICL_, RLDICR_, RLDIC_, RLDCL_, RLDCR_, RLDIMI_,
)): SLW_, SRW_, SRAWI_, SRAW_, SLD_, SRD_, SRADI_, SRAD_)):
cr0_w_mask = Record([("so", 1), ("eq_", 1), ("gt", 1), ("lt", 1)]) cr0_w_mask = Record([("so", 1), ("eq_", 1), ("gt", 1), ("lt", 1)])
cr0_w_data = Record([("so", 1), ("eq_", 1), ("gt", 1), ("lt", 1)]) cr0_w_data = Record([("so", 1), ("eq_", 1), ("gt", 1), ("lt", 1)])


@ -163,7 +204,18 @@ class RotateShiftSpec(InsnSpec, Elaboratable):
carry = Signal() carry = Signal()


m.d.comb += [ m.d.comb += [
carry.eq(src[31] & (rotl & ~mask)[:32].any()), carry.eq(Mux(shamt[5], 0, src[31] & (rotl & ~mask)[:32].any())),

self.pfv.xer.w_mask.ca .eq(1),
self.pfv.xer.w_data.ca .eq(carry),
self.pfv.xer.w_mask.ca32.eq(1),
self.pfv.xer.w_data.ca32.eq(carry),
]
elif isinstance(self.insn, (SRADI, SRADI_, SRAD, SRAD_)):
carry = Signal()

m.d.comb += [
carry.eq(Mux(shamt[6], 0, src[63] & (rotl & ~mask).any())),


self.pfv.xer.w_mask.ca .eq(1), self.pfv.xer.w_mask.ca .eq(1),
self.pfv.xer.w_data.ca .eq(carry), self.pfv.xer.w_data.ca .eq(carry),

@ -109,11 +109,12 @@ class Interface(Record):
gpr_width : int gpr_width : int
General-purpose register width. Either 32 or 64. Compliance with Power ISA versions above General-purpose register width. Either 32 or 64. Compliance with Power ISA versions above
v2.7B requires 64-bit wide GPRs. v2.7B requires 64-bit wide GPRs.
mem_aligned : bool mem_alignment : log2 of int
If ``True``, an Alignment interrupt is expected if the effective address of a Load/Store Memory alignment. This parameter restricts the alignment of Load/Store accesses to either
operation is not aligned to its operand; ``mem.addr`` is also expected to be aligned to ``2 ** pfv.mem_alignment`` bytes, or to the size of their operand. Otherwise, an Alignment
8 bytes. If ``False``, ``mem.addr`` is expected to point to the least- or most-significant interrupt is triggered. A core that can transparently handle misaligned accesses may set
byte of the storage operand, depending on the current endian mode. this value to 0, whereas one that requires software intervention may set it to the width
of its data bus (as a log2).
illegal_insn_heai : bool illegal_insn_heai : bool
If ``True``, an illegal instruction triggers an Hypervisor Emulation Assistance interrupt. If ``True``, an illegal instruction triggers an Hypervisor Emulation Assistance interrupt.
Otherwise, it triggers an Illegal Instruction type Program interrupt (which was removed in Otherwise, it triggers an Illegal Instruction type Program interrupt (which was removed in
@ -218,13 +219,16 @@ class Interface(Record):
srr1 : Record(:func:`reg_port_layout`) srr1 : Record(:func:`reg_port_layout`)
Save/Restore Register 1 access. Save/Restore Register 1 access.
""" """
def __init__(self, *, gpr_width=64, mem_aligned=False, illegal_insn_heai=False, def __init__(self, *, gpr_width=64, mem_alignment=0, illegal_insn_heai=False,
muldiv_altops=False, name=None, src_loc_at=0): muldiv_altops=False, name=None, src_loc_at=0):
if gpr_width not in (32, 64): if gpr_width not in (32, 64):
raise ValueError("GPR width must be 32 or 64, not {!r}".format(gpr_width)) raise ValueError("GPR width must be 32 or 64, not {!r}".format(gpr_width))
if mem_alignment not in (0, 1, 2, 3):
raise ValueError("Memory alignment must be an integer between 0 and 3, not {!r}"
.format(mem_alignment))


self.gpr_width = gpr_width self.gpr_width = gpr_width
self.mem_aligned = bool(mem_aligned) self.mem_alignment = mem_alignment
self.illegal_insn_heai = bool(illegal_insn_heai) self.illegal_insn_heai = bool(illegal_insn_heai)
self.muldiv_altops = bool(muldiv_altops) self.muldiv_altops = bool(muldiv_altops)



Loading…
Cancel
Save