Compare commits

...

4 Commits

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

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

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

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