1 from nmigen
import Signal
, Module
, Record
2 from nmigen
.back
.pysim
import Simulator
, Delay
3 from nmigen
.compat
.sim
import run_simulation
, Settle
4 from nmutil
.formaltest
import FHDLTestCase
5 from nmigen
.cli
import rtlil
7 from soc
.config
.test
.test_loadstore
import TestMemPspec
8 from soc
.config
.loadstore
import ConfigMemoryPortInterface
11 def wait_busy(port
, no
=False,debug
=None):
14 busy
= yield port
.busy_o
15 print("busy", no
, busy
, cnt
, debug
)
23 def wait_addr(port
,debug
=None):
26 addr_ok
= yield port
.addr_ok_o
27 print("addrok", addr_ok
,cnt
,debug
)
37 ldok
= yield port
.ld
.ok
38 exc_happened
= yield port
.exc_o
.happened
39 print("ldok", ldok
, "exception", exc_happened
, "count", cnt
)
41 if ldok
or exc_happened
:
46 def pi_st(port1
, addr
, data
, datalen
, msr_pr
=0):
48 # have to wait until not busy
49 yield from wait_busy(port1
, no
=False) # wait until not busy
51 # set up a ST on the port. address first:
52 yield port1
.is_st_i
.eq(1) # indicate ST
53 yield port1
.data_len
.eq(datalen
) # ST length (1/2/4/8)
54 yield port1
.msr_pr
.eq(msr_pr
) # MSR PR bit (1==>virt, 0==>real)
56 yield port1
.addr
.data
.eq(addr
) # set address
57 yield port1
.addr
.ok
.eq(1) # set ok
59 yield from wait_addr(port1
) # wait until addr ok
60 # yield # not needed, just for checking
61 # yield # not needed, just for checking
62 # assert "ST" for one cycle (required by the API)
63 yield port1
.st
.data
.eq(data
)
64 yield port1
.st
.ok
.eq(1)
66 yield port1
.st
.ok
.eq(0)
67 yield from wait_busy(port1
, True) # wait while busy
70 def pi_dcbz(port1
, addr
, msr_pr
=0):
72 # have to wait until not busy
73 yield from wait_busy(port1
, no
=False,debug
="busy") # wait until not busy
75 # set up a ST on the port. address first:
76 yield port1
.is_st_i
.eq(1) # indicate ST
77 yield port1
.msr_pr
.eq(msr_pr
) # MSR PR bit (1==>virt, 0==>real)
79 yield port1
.is_dcbz
.eq(1) # set dcbz
81 yield port1
.addr
.data
.eq(addr
) # set address
82 yield port1
.addr
.ok
.eq(1) # set ok
85 # guess: this is not needed
86 # yield from wait_addr(port1,debug="addr") # wait until addr ok
88 # just write some dummy data -- remove
89 print("dummy write begin")
90 yield port1
.st
.data
.eq(0)
91 yield port1
.st
.ok
.eq(1)
93 yield port1
.st
.ok
.eq(0)
94 print("dummy write end")
96 yield from wait_busy(port1
, no
=True, debug
="not_busy") # wait while busy
98 # can go straight to reset.
99 yield port1
.is_st_i
.eq(0) # end
100 yield port1
.addr
.ok
.eq(0) # set !ok
101 yield port1
.is_dcbz
.eq(0) # reset dcbz too
104 def pi_ld(port1
, addr
, datalen
, msr_pr
=0):
106 # have to wait until not busy
107 yield from wait_busy(port1
, no
=False) # wait until not busy
109 # set up a LD on the port. address first:
110 yield port1
.is_ld_i
.eq(1) # indicate LD
111 yield port1
.data_len
.eq(datalen
) # LD length (1/2/4/8)
112 yield port1
.msr_pr
.eq(msr_pr
) # MSR PR bit (1==>virt, 0==>real)
114 yield port1
.addr
.data
.eq(addr
) # set address
115 yield port1
.addr
.ok
.eq(1) # set ok
117 yield from wait_addr(port1
) # wait until addr ok
119 yield from wait_ldok(port1
) # wait until ld ok
120 data
= yield port1
.ld
.data
121 exc_happened
= yield port1
.exc_o
.happened
124 yield port1
.is_ld_i
.eq(0) # end
125 yield port1
.addr
.ok
.eq(0) # set !ok
129 yield from wait_busy(port1
, no
=False) # wait while not busy
134 def pi_ldst(arg
, dut
, msr_pr
=0):
136 # do two half-word stores at consecutive addresses, then two loads
142 yield from pi_st(dut
, addr1
, data
, 2, msr_pr
)
143 yield from pi_st(dut
, addr2
, data2
, 2, msr_pr
)
144 result
= yield from pi_ld(dut
, addr1
, 2, msr_pr
)
145 result2
= yield from pi_ld(dut
, addr2
, 2, msr_pr
)
146 arg
.assertEqual(data
, result
, "data %x != %x" % (result
, data
))
147 arg
.assertEqual(data2
, result2
, "data2 %x != %x" % (result2
, data2
))
149 # now load both in a 32-bit load to make sure they're really consecutive
150 data3
= data |
(data2
<< 16)
151 result3
= yield from pi_ld(dut
, addr1
, 4, msr_pr
)
152 arg
.assertEqual(data3
, result3
, "data3 %x != %x" % (result3
, data3
))
155 def tst_config_pi(testcls
, ifacetype
):
156 """set up a configureable memory test of type ifacetype
159 pspec
= TestMemPspec(ldst_ifacetype
=ifacetype
,
164 cmpi
= ConfigMemoryPortInterface(pspec
)
165 dut
.submodules
.pi
= cmpi
.pi
166 if hasattr(cmpi
, 'lsmem'): # hmmm not happy about this
167 dut
.submodules
.lsmem
= cmpi
.lsmem
.lsi
168 vl
= rtlil
.convert(dut
, ports
=[]) # dut.ports())
169 with
open("test_pi_%s.il" % ifacetype
, "w") as f
:
172 run_simulation(dut
, {"sync": pi_ldst(testcls
, cmpi
.pi
.pi
)},
173 vcd_name
='test_pi_%s.vcd' % ifacetype
)
176 class TestPIMem(unittest
.TestCase
):
178 def test_pi_mem(self
):
179 tst_config_pi(self
, 'testpi')
181 def test_pi2ls(self
):
182 tst_config_pi(self
, 'testmem')
184 def test_pi2ls_bare_wb(self
):
185 tst_config_pi(self
, 'test_bare_wb')
188 if __name__
== '__main__':