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):
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,
features=("stall",))
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(
insn = self.insn,
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,
muldiv_altops = self.dut.pfv.muldiv_altops,
)
@ -217,6 +217,7 @@ class _SysRegTest(Elaboratable):
def __init__(self, check, *, reg):
self._dut = getattr(check.dut .pfv, reg)
self._spec = getattr(check.spec.pfv, reg)
self._width = check.dut.pfv.gpr_width

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

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

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


__all__ = [
"RLWINM", "RLWINM_", "RLWNM", "RLWNM_", "RLWIMI", "RLWIMI_",
"SLW" , "SLW_" ,
"SRW" , "SRW_" , "SRAWI", "SRAWI_", "SRAW" , "SRAW_" ,
"RLWINM", "RLWINM_", "RLWNM" , "RLWNM_" , "RLWIMI", "RLWIMI_",
"RLDICL", "RLDICL_", "RLDICR", "RLDICR_", "RLDIC" , "RLDIC_" ,
"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 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 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 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 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),
]

with m.If(dut.pfv.stb & ~dut.pfv.intr):
with m.If(dut.pfv.stb):
with m.If(dut.pfv.cia == storage.addr):
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)

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(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(1))
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(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

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 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 MTTAR (WordInsn): _fields = (f.PO(31), f.RS(), f.SPR(815), f.XO_XFX(467))
class MFTAR (WordInsn): _fields = (f.PO(31), f.RT(), f.SPR(815), f.XO_XFX(339))
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(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 PO (InsnField): _shape = unsigned( 6); _offset = 0; _name = "PO"
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 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 RB (InsnField): _shape = unsigned( 5); _offset = 16; _name = "RB"
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 SI (InsnField): _shape = signed(16); _offset = 16; _name = "SI"
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 UI (InsnField): _shape = unsigned(16); _offset = 16; _name = "UI"
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_XL (InsnField): _shape = unsigned(10); _offset = 21; _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):

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

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

elif isinstance(self.insn, CMPEQB):
_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))

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))

byte_offset = Signal(3)
half_offset = Signal(2)
word_offset = Signal(1)

# If `pfv.mem_aligned` is set, `pfv.mem.addr` points to the dword containing EA.
# If `pfv.mem_aligned` is unset, `pfv.mem.addr` is equal to EA.
# The value of `pfv.mem.addr` must be equal to EA, rounded down to a multiple of
# ``2 ** pfv.mem_alignment``.

m.d.comb += self.pfv.mem.addr[3:].eq(ea[3:])

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

# Raise an Alignment Interrupt if EA is misaligned to the size of the storage operand
# and to ``2 ** pfv.mem_alignment``.

byte_offset = Signal(3)
half_offset = Signal(2)
word_offset = Signal(1)

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

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

ea_misaligned = Signal()

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

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

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

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

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

with m.Else():
src = Signal(unsigned(64))
shamt = Signal(unsigned( 6))
shamt = Signal(unsigned( 7))
rotl = Signal(unsigned(64))
mask = 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)

if isinstance(self.insn, (RLWINM, RLWINM_, RLWNM, RLWNM_, RLWIMI, RLWIMI_,
SLW, SLW_, SRW, SRW_, SRAWI, SRAWI_, SRAW, SRAW_)):
m.d.comb += [
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_)):
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_)):
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[: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:
assert False

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

if isinstance(self.insn, (RLWINM, RLWINM_, RLWNM, RLWNM_, RLWIMI, RLWIMI_)):
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_)):
m.d.comb += mask.eq(Mux(shamt[5], 0, _mask(32, 63-shamt)))
elif isinstance(self.insn, (SRW, SRW_, SRAW, SRAW_)):
m.d.comb += mask.eq(Mux(shamt[5], 0, _mask(shamt+32, 63)))
elif isinstance(self.insn, (SRAWI, SRAWI_)):
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:
assert False

# Rotation

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

if isinstance(self.insn, (
RLWINM, RLWINM_, RLWNM, RLWNM_, RLWIMI, RLWIMI_,
SLW, SLW_,
)):
m.d.comb += rotl.eq(_rotl32(src, shamt))
if isinstance(self.insn, (RLWINM, RLWINM_, RLWNM, RLWNM_, RLWIMI, RLWIMI_,
SLW, SLW_)):
m.d.comb += rotl.eq(_rotl(src, shamt[:5]))
elif isinstance(self.insn, (RLDICL, RLDICL_, RLDICR, RLDICR_, RLDIC, RLDIC_,
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_)):
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:
assert False

@ -126,21 +163,25 @@ class RotateShiftSpec(InsnSpec, Elaboratable):
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)
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 += result.eq(rotl & mask | self.pfv.ra.r_data & ~mask)
elif isinstance(self.insn, (SRAWI, SRAWI_, SRAW, SRAW_)):
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:
assert False

# Write CR0

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_data = Record([("so", 1), ("eq_", 1), ("gt", 1), ("lt", 1)])

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

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_data.ca .eq(carry),

@ -109,11 +109,12 @@ class Interface(Record):
gpr_width : int
General-purpose register width. Either 32 or 64. Compliance with Power ISA versions above
v2.7B requires 64-bit wide GPRs.
mem_aligned : bool
If ``True``, an Alignment interrupt is expected if the effective address of a Load/Store
operation is not aligned to its operand; ``mem.addr`` is also expected to be aligned to
8 bytes. If ``False``, ``mem.addr`` is expected to point to the least- or most-significant
byte of the storage operand, depending on the current endian mode.
mem_alignment : log2 of int
Memory alignment. This parameter restricts the alignment of Load/Store accesses to either
``2 ** pfv.mem_alignment`` bytes, or to the size of their operand. Otherwise, an Alignment
interrupt is triggered. A core that can transparently handle misaligned accesses may set
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
If ``True``, an illegal instruction triggers an Hypervisor Emulation Assistance interrupt.
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`)
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):
if gpr_width not in (32, 64):
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.mem_aligned = bool(mem_aligned)
self.mem_alignment = mem_alignment
self.illegal_insn_heai = bool(illegal_insn_heai)
self.muldiv_altops = bool(muldiv_altops)


Loading…
Cancel
Save