1431a0386d595a1252c19c1254d0c050295d748e
1 # Proof of correctness for SPR pipeline, main stage
6 * https://bugs.libre-soc.org/show_bug.cgi?id=418
11 from nmigen
import (Elaboratable
, Module
, Signal
, Cat
)
12 from nmigen
.asserts
import Assert
, AnyConst
, Assume
13 from nmigen
.cli
import rtlil
15 from nmutil
.formaltest
import FHDLTestCase
17 from soc
.fu
.spr
.main_stage
import SPRMainStage
18 from soc
.fu
.spr
.pipe_data
import SPRPipeSpec
19 from soc
.fu
.spr
.spr_input_record
import CompSPROpSubset
21 from openpower
.decoder
.power_decoder2
import decode_spr_num
22 from openpower
.decoder
.power_enums
import MicrOp
, SPR
, XER_bits
23 from openpower
.decoder
.power_fields
import DecodeFields
24 from openpower
.decoder
.power_fieldsn
import SignalBitRange
26 # use POWER numbering. sigh.
28 return 63-XER_bits
[name
]
31 class Driver(Elaboratable
):
33 Defines a module to drive the device under test and assert properties
37 def elaborate(self
, platform
):
41 # cookie-cutting most of this from alu formal proof_main_stage.py
43 rec
= CompSPROpSubset()
44 # Setup random inputs for dut.op
47 comb
+= p
.eq(AnyConst(width
))
49 pspec
= SPRPipeSpec(id_wid
=2)
50 m
.submodules
.dut
= dut
= SPRMainStage(pspec
)
52 # frequently used aliases
54 ca_in
= dut
.i
.xer_ca
[0] # CA carry in
55 ca32_in
= dut
.i
.xer_ca
[1] # CA32 carry in 32
56 so_in
= dut
.i
.xer_so
# SO sticky overflow
57 ov_in
= dut
.i
.xer_ov
[0] # XER OV in
58 ov32_in
= dut
.i
.xer_ov
[1] # XER OV32 in
62 comb
+= [a
.eq(AnyConst(64)),
63 ca_in
.eq(AnyConst(0b11)),
64 so_in
.eq(AnyConst(1))]
66 # and for the context muxid
67 width
= dut
.i
.ctx
.muxid
.width
68 comb
+= dut
.i
.ctx
.muxid
.eq(AnyConst(width
))
70 # assign the PowerDecode2 operation subset
71 comb
+= dut
.i
.ctx
.op
.eq(rec
)
73 # check that the operation (op) is passed through (and muxid)
74 comb
+= Assert(dut
.o
.ctx
.op
== dut
.i
.ctx
.op
)
75 comb
+= Assert(dut
.o
.ctx
.muxid
== dut
.i
.ctx
.muxid
)
78 fields
= DecodeFields(SignalBitRange
, [dut
.i
.ctx
.op
.insn
])
81 spr
= Signal(len(xfx
.SPR
))
82 comb
+= spr
.eq(decode_spr_num(xfx
.SPR
))
84 with m
.Switch(dut
.i
.ctx
.op
.insn_type
):
87 with m
.Case(MicrOp
.OP_MTSPR
):
89 with m
.Case(SPR
.CTR
, SPR
.LR
, SPR
.TAR
, SPR
.SRR0
, SPR
.SRR1
):
91 Assert(dut
.o
.fast1
.data
== a
),
92 Assert(dut
.o
.fast1
.ok
),
94 # If a fast-path SPR is referenced, no other OKs
96 Assert(~dut
.o
.xer_so
.ok
),
97 Assert(~dut
.o
.xer_ov
.ok
),
98 Assert(~dut
.o
.xer_ca
.ok
),
100 with m
.Case(SPR
.XER
):
102 Assert(dut
.o
.xer_so
.data
== a
[xer_bit('SO')]),
103 Assert(dut
.o
.xer_so
.ok
),
104 Assert(dut
.o
.xer_ov
.data
== Cat(
105 a
[xer_bit('OV')], a
[xer_bit('OV32')]
107 Assert(dut
.o
.xer_ov
.ok
),
108 Assert(dut
.o
.xer_ca
.data
== Cat(
109 a
[xer_bit('CA')], a
[xer_bit('CA32')]
111 Assert(dut
.o
.xer_ca
.ok
),
113 # XER is not a fast-path SPR.
114 Assert(~dut
.o
.fast1
.ok
),
119 with m
.Case(MicrOp
.OP_MFSPR
):
122 with m
.Case(SPR
.CTR
, SPR
.LR
, SPR
.TAR
, SPR
.SRR0
, SPR
.SRR1
):
123 comb
+= Assert(o
.data
== dut
.i
.fast1
)
124 with m
.Case(SPR
.XER
):
133 Assert(o
[xer_bit(b
)] == bits
[b
])
141 class SPRMainStageTestCase(FHDLTestCase
):
142 def test_formal(self
):
143 self
.assertFormal(Driver(), mode
="bmc", depth
=100)
144 self
.assertFormal(Driver(), mode
="cover", depth
=100)
146 def test_ilang(self
):
147 vl
= rtlil
.convert(Driver(), ports
=[])
148 with
open("spr_main_stage.il", "w") as f
:
152 if __name__
== '__main__':