Compare commits

...

4 Commits

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

@ -271,5 +271,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))

@ -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, (

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