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
69 # can go straight to reset.
70 yield port1
.is_st_i
.eq(0) # end
71 yield port1
.addr
.ok
.eq(0) # set !ok
72 yield port1
.is_dcbz
.eq(0) # reset dcbz too
76 def pi_dcbz(port1
, addr
, msr_pr
=0):
78 # have to wait until not busy
79 yield from wait_busy(port1
, no
=False,debug
="busy") # wait until not busy
81 # set up a ST on the port. address first:
82 yield port1
.is_st_i
.eq(1) # indicate ST
83 yield port1
.msr_pr
.eq(msr_pr
) # MSR PR bit (1==>virt, 0==>real)
85 yield port1
.is_dcbz
.eq(1) # set dcbz
87 yield port1
.addr
.data
.eq(addr
) # set address
88 yield port1
.addr
.ok
.eq(1) # set ok
91 # guess: this is not needed
92 # yield from wait_addr(port1,debug="addr") # wait until addr ok
94 # just write some dummy data -- remove
95 print("dummy write begin")
96 yield port1
.st
.data
.eq(0)
97 yield port1
.st
.ok
.eq(1)
99 yield port1
.st
.ok
.eq(0)
100 print("dummy write end")
102 yield from wait_busy(port1
, no
=True, debug
="not_busy") # wait while busy
104 # can go straight to reset.
105 yield port1
.is_st_i
.eq(0) # end
106 yield port1
.addr
.ok
.eq(0) # set !ok
107 yield port1
.is_dcbz
.eq(0) # reset dcbz too
110 def pi_ld(port1
, addr
, datalen
, msr_pr
=0):
112 # have to wait until not busy
113 yield from wait_busy(port1
, no
=False) # wait until not busy
115 # set up a LD on the port. address first:
116 yield port1
.is_ld_i
.eq(1) # indicate LD
117 yield port1
.data_len
.eq(datalen
) # LD length (1/2/4/8)
118 yield port1
.msr_pr
.eq(msr_pr
) # MSR PR bit (1==>virt, 0==>real)
120 yield port1
.addr
.data
.eq(addr
) # set address
121 yield port1
.addr
.ok
.eq(1) # set ok
123 yield from wait_addr(port1
) # wait until addr ok
125 yield from wait_ldok(port1
) # wait until ld ok
126 data
= yield port1
.ld
.data
127 exc_happened
= yield port1
.exc_o
.happened
130 yield port1
.is_ld_i
.eq(0) # end
131 yield port1
.addr
.ok
.eq(0) # set !ok
135 yield from wait_busy(port1
, no
=False) # wait while not busy
140 def pi_ldst(arg
, dut
, msr_pr
=0):
142 # do two half-word stores at consecutive addresses, then two loads
148 yield from pi_st(dut
, addr1
, data
, 2, msr_pr
)
149 yield from pi_st(dut
, addr2
, data2
, 2, msr_pr
)
150 result
= yield from pi_ld(dut
, addr1
, 2, msr_pr
)
151 result2
= yield from pi_ld(dut
, addr2
, 2, msr_pr
)
152 arg
.assertEqual(data
, result
, "data %x != %x" % (result
, data
))
153 arg
.assertEqual(data2
, result2
, "data2 %x != %x" % (result2
, data2
))
155 # now load both in a 32-bit load to make sure they're really consecutive
156 data3
= data |
(data2
<< 16)
157 result3
= yield from pi_ld(dut
, addr1
, 4, msr_pr
)
158 arg
.assertEqual(data3
, result3
, "data3 %x != %x" % (result3
, data3
))
161 def tst_config_pi(testcls
, ifacetype
):
162 """set up a configureable memory test of type ifacetype
165 pspec
= TestMemPspec(ldst_ifacetype
=ifacetype
,
170 cmpi
= ConfigMemoryPortInterface(pspec
)
171 dut
.submodules
.pi
= cmpi
.pi
172 if hasattr(cmpi
, 'lsmem'): # hmmm not happy about this
173 dut
.submodules
.lsmem
= cmpi
.lsmem
.lsi
174 vl
= rtlil
.convert(dut
, ports
=[]) # dut.ports())
175 with
open("test_pi_%s.il" % ifacetype
, "w") as f
:
178 run_simulation(dut
, {"sync": pi_ldst(testcls
, cmpi
.pi
.pi
)},
179 vcd_name
='test_pi_%s.vcd' % ifacetype
)
182 class TestPIMem(unittest
.TestCase
):
184 def test_pi_mem(self
):
185 tst_config_pi(self
, 'testpi')
187 def test_pi2ls(self
):
188 tst_config_pi(self
, 'testmem')
190 def test_pi2ls_bare_wb(self
):
191 tst_config_pi(self
, 'test_bare_wb')
194 if __name__
== '__main__':