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):
13 busy
= yield port
.busy_o
14 print("busy", no
, busy
)
22 addr_ok
= yield port
.addr_ok_o
23 print("addrok", addr_ok
)
32 ldok
= yield port
.ld
.ok
33 exc_happened
= yield port
.exc_o
.happened
34 print("ldok", ldok
, "exception", exc_happened
, "count", cnt
)
36 if ldok
or exc_happened
:
41 def pi_st(port1
, addr
, data
, datalen
, msr_pr
=0):
43 # have to wait until not busy
44 yield from wait_busy(port1
, no
=False) # wait until not busy
46 # set up a ST on the port. address first:
47 yield port1
.is_st_i
.eq(1) # indicate ST
48 yield port1
.data_len
.eq(datalen
) # ST length (1/2/4/8)
49 yield port1
.msr_pr
.eq(msr_pr
) # MSR PR bit (1==>virt, 0==>real)
51 yield port1
.addr
.data
.eq(addr
) # set address
52 yield port1
.addr
.ok
.eq(1) # set ok
54 yield from wait_addr(port1
) # wait until addr ok
55 # yield # not needed, just for checking
56 # yield # not needed, just for checking
57 # assert "ST" for one cycle (required by the API)
58 yield port1
.st
.data
.eq(data
)
59 yield port1
.st
.ok
.eq(1)
61 yield port1
.st
.ok
.eq(0)
62 yield from wait_busy(port1
, True) # wait while busy
65 def pi_dcbz(port1
, addr
, data
, datalen
, msr_pr
=0):
67 # have to wait until not busy
68 yield from wait_busy(port1
, no
=False) # wait until not busy
70 # set up a ST on the port. address first:
71 yield port1
.is_st_i
.eq(1) # indicate ST
72 yield port1
.data_len
.eq(datalen
) # ST length (1/2/4/8)
73 yield port1
.msr_pr
.eq(msr_pr
) # MSR PR bit (1==>virt, 0==>real)
75 yield port1
.is_dcbz
.eq(1) # set dcbz
77 yield port1
.addr
.data
.eq(addr
) # set address
78 yield port1
.addr
.ok
.eq(1) # set ok
80 yield from wait_addr(port1
) # wait until addr ok
81 # yield # not needed, just for checking
82 # yield # not needed, just for checking
83 # assert "ST" for one cycle (required by the API)
84 yield port1
.st
.data
.eq(data
)
85 yield port1
.st
.ok
.eq(1)
87 yield port1
.st
.ok
.eq(0)
88 yield from wait_busy(port1
, True) # wait while busy
90 # can go straight to reset.
91 yield port1
.is_st_i
.eq(0) # end
92 yield port1
.addr
.ok
.eq(0) # set !ok
93 yield port1
.is_dcbz
.eq(0) # reset dcbz too
96 def pi_ld(port1
, addr
, datalen
, msr_pr
=0):
98 # have to wait until not busy
99 yield from wait_busy(port1
, no
=False) # wait until not busy
101 # set up a LD on the port. address first:
102 yield port1
.is_ld_i
.eq(1) # indicate LD
103 yield port1
.data_len
.eq(datalen
) # LD length (1/2/4/8)
104 yield port1
.msr_pr
.eq(msr_pr
) # MSR PR bit (1==>virt, 0==>real)
106 yield port1
.addr
.data
.eq(addr
) # set address
107 yield port1
.addr
.ok
.eq(1) # set ok
109 yield from wait_addr(port1
) # wait until addr ok
111 yield from wait_ldok(port1
) # wait until ld ok
112 data
= yield port1
.ld
.data
113 exc_happened
= yield port1
.exc_o
.happened
116 yield port1
.is_ld_i
.eq(0) # end
117 yield port1
.addr
.ok
.eq(0) # set !ok
121 yield from wait_busy(port1
, no
=False) # wait while not busy
126 def pi_ldst(arg
, dut
, msr_pr
=0):
128 # do two half-word stores at consecutive addresses, then two loads
134 yield from pi_st(dut
, addr1
, data
, 2, msr_pr
)
135 yield from pi_st(dut
, addr2
, data2
, 2, msr_pr
)
136 result
= yield from pi_ld(dut
, addr1
, 2, msr_pr
)
137 result2
= yield from pi_ld(dut
, addr2
, 2, msr_pr
)
138 arg
.assertEqual(data
, result
, "data %x != %x" % (result
, data
))
139 arg
.assertEqual(data2
, result2
, "data2 %x != %x" % (result2
, data2
))
141 # now load both in a 32-bit load to make sure they're really consecutive
142 data3
= data |
(data2
<< 16)
143 result3
= yield from pi_ld(dut
, addr1
, 4, msr_pr
)
144 arg
.assertEqual(data3
, result3
, "data3 %x != %x" % (result3
, data3
))
147 def tst_config_pi(testcls
, ifacetype
):
148 """set up a configureable memory test of type ifacetype
151 pspec
= TestMemPspec(ldst_ifacetype
=ifacetype
,
156 cmpi
= ConfigMemoryPortInterface(pspec
)
157 dut
.submodules
.pi
= cmpi
.pi
158 if hasattr(cmpi
, 'lsmem'): # hmmm not happy about this
159 dut
.submodules
.lsmem
= cmpi
.lsmem
.lsi
160 vl
= rtlil
.convert(dut
, ports
=[]) # dut.ports())
161 with
open("test_pi_%s.il" % ifacetype
, "w") as f
:
164 run_simulation(dut
, {"sync": pi_ldst(testcls
, cmpi
.pi
.pi
)},
165 vcd_name
='test_pi_%s.vcd' % ifacetype
)
168 class TestPIMem(unittest
.TestCase
):
170 def test_pi_mem(self
):
171 tst_config_pi(self
, 'testpi')
173 def test_pi2ls(self
):
174 tst_config_pi(self
, 'testmem')
176 def test_pi2ls_bare_wb(self
):
177 tst_config_pi(self
, 'test_bare_wb')
180 if __name__
== '__main__':