You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
71 lines
2.4 KiB
Python
71 lines
2.4 KiB
Python
2 years ago
|
from amaranth import *
|
||
|
from amaranth.asserts import *
|
||
|
|
||
|
from power_fv.check import PowerFVCheck
|
||
|
from power_fv.check._timer import Timer
|
||
|
|
||
|
|
||
|
__all__ = ["CausalityCheck"]
|
||
|
|
||
|
|
||
|
class CausalityCheck(PowerFVCheck, name=("causal",)):
|
||
|
"""Causal consistency check.
|
||
|
|
||
|
Checks that an instruction that writes to a GPR has completed before any subsequent
|
||
|
instruction (by program order) can read it.
|
||
|
"""
|
||
|
|
||
|
def testbench(self):
|
||
|
return CausalityTestbench(self)
|
||
|
|
||
|
|
||
|
class CausalityTestbench(Elaboratable):
|
||
|
def __init__(self, check):
|
||
|
if not isinstance(check, CausalityCheck):
|
||
|
raise TypeError("Check must be an instance of CausalityCheck, not {!r}"
|
||
|
.format(check))
|
||
|
self.check = check
|
||
|
self.name = "causal_tb"
|
||
|
|
||
|
def elaborate(self, platform):
|
||
|
m = Module()
|
||
|
|
||
|
m.submodules.t_post = t_post = Timer(self.check.depth - 1)
|
||
|
m.submodules.dut = dut = self.check.dut
|
||
|
|
||
|
write_order = AnyConst(dut.pfv.order.shape())
|
||
|
write_index = AnyConst(unsigned(5))
|
||
|
read_before = Signal()
|
||
|
|
||
|
gpr_write = Record([("ra", 1), ("rb", 1), ("rs", 1), ("rt", 1)])
|
||
|
gpr_read = Record.like(gpr_write)
|
||
|
|
||
|
m.d.comb += [
|
||
|
gpr_write.ra.eq(dut.pfv.ra.w_stb & (dut.pfv.ra.index == write_index)),
|
||
|
gpr_write.rb.eq(dut.pfv.rb.w_stb & (dut.pfv.rb.index == write_index)),
|
||
|
gpr_write.rs.eq(dut.pfv.rs.w_stb & (dut.pfv.rs.index == write_index)),
|
||
|
gpr_write.rt.eq(dut.pfv.rt.w_stb & (dut.pfv.rt.index == write_index)),
|
||
|
|
||
|
gpr_read .ra.eq(dut.pfv.ra.r_stb & (dut.pfv.ra.index == write_index)),
|
||
|
gpr_read .rb.eq(dut.pfv.rb.r_stb & (dut.pfv.rb.index == write_index)),
|
||
|
gpr_read .rs.eq(dut.pfv.rs.r_stb & (dut.pfv.rs.index == write_index)),
|
||
|
gpr_read .rt.eq(dut.pfv.rt.r_stb & (dut.pfv.rt.index == write_index)),
|
||
|
]
|
||
|
|
||
|
with m.If(dut.pfv.stb & (dut.pfv.order > write_order) & ~dut.pfv.skip):
|
||
|
with m.If(gpr_read.any()):
|
||
|
m.d.sync += read_before.eq(1)
|
||
|
|
||
|
with m.If(t_post.zero):
|
||
|
m.d.comb += [
|
||
|
Assume(dut.pfv.stb),
|
||
|
Assume(dut.pfv.order == write_order),
|
||
|
Assume(~dut.pfv.skip),
|
||
|
Assume(gpr_write.any()),
|
||
|
Assert(~read_before),
|
||
|
]
|
||
|
|
||
|
m.d.comb += Assert(~Past(t_post.zero))
|
||
|
|
||
|
return m
|