1 """TestRunner class, runs TestIssuer instructions
5 * https://bugs.libre-soc.org/show_bug.cgi?id=363
6 * https://bugs.libre-soc.org/show_bug.cgi?id=686#c51
8 from nmigen
import Module
, Signal
9 from nmigen
.hdl
.xfrm
import ResetInserter
12 # NOTE: to use cxxsim, export NMIGEN_SIM_MODE=cxxsim from the shell
13 # Also, check out the cxxsim nmigen branch, and latest yosys from git
14 from nmutil
.sim_tmp_alternative
import Simulator
, Settle
16 from openpower
.decoder
.isa
.caller
import SVP64State
17 from openpower
.decoder
.isa
.all
import ISA
18 from openpower
.endian
import bigendian
20 from soc
.simple
.issuer
import TestIssuerInternal
22 from soc
.config
.test
.test_loadstore
import TestMemPspec
23 from soc
.simple
.test
.test_core
import (setup_regs
, check_regs
, check_mem
,
26 from soc
.fu
.compunits
.test
.test_compunit
import (setup_tst_memory
,
28 from soc
.debug
.dmi
import DBGCore
, DBGCtrl
, DBGStat
29 from nmutil
.util
import wrap
30 from soc
.experiment
.test
.test_mmu_dcache
import wb_get
31 from openpower
.test
.state
import TestState
, StateRunner
32 from openpower
.test
.runner
import TestRunnerBase
35 def setup_i_memory(imem
, startaddr
, instructions
):
37 print("insn before, init mem", mem
.depth
, mem
.width
, mem
,
39 for i
in range(mem
.depth
):
40 yield mem
._array
[i
].eq(0)
42 startaddr
//= 4 # instructions are 32-bit
45 for ins
in instructions
:
46 if isinstance(ins
, tuple):
50 insn
= insn
& 0xffffffff
51 yield mem
._array
[startaddr
].eq(insn
)
54 print("instr: %06x 0x%x %s" % (4*startaddr
, insn
, code
))
56 startaddr
= startaddr
& mask
61 for ins
in instructions
:
62 if isinstance(ins
, tuple):
66 insn
= insn
& 0xffffffff
67 msbs
= (startaddr
>> 1) & mask
68 val
= yield mem
._array
[msbs
]
70 print("before set", hex(4*startaddr
),
71 hex(msbs
), hex(val
), hex(insn
))
72 lsb
= 1 if (startaddr
& 1) else 0
73 val
= (val |
(insn
<< (lsb
*32)))
75 yield mem
._array
[msbs
].eq(val
)
78 print("after set", hex(4*startaddr
), hex(msbs
), hex(val
))
79 print("instr: %06x 0x%x %s %08x" % (4*startaddr
, insn
, code
, val
))
81 startaddr
= startaddr
& mask
84 def set_dmi(dmi
, addr
, data
):
86 yield dmi
.addr_i
.eq(addr
)
87 yield dmi
.din
.eq(data
)
96 yield dmi
.addr_i
.eq(0)
102 def get_dmi(dmi
, addr
):
103 yield dmi
.req_i
.eq(1)
104 yield dmi
.addr_i
.eq(addr
)
108 ack
= yield dmi
.ack_o
113 data
= yield dmi
.dout
# get data after ack valid for 1 cycle
114 yield dmi
.req_i
.eq(0)
115 yield dmi
.addr_i
.eq(0)
121 class HDLRunner(StateRunner
):
122 def __init__(self
, dut
, m
, pspec
):
123 super().__init
__("hdl", HDLRunner
)
126 self
.pc_i
= Signal(32)
127 self
.svstate_i
= Signal(64)
129 #hard_reset = Signal(reset_less=True)
130 self
.issuer
= TestIssuerInternal(pspec
)
131 # use DMI RESET command instead, this does actually work though
132 #issuer = ResetInserter({'coresync': hard_reset,
133 # 'sync': hard_reset})(issuer)
134 m
.submodules
.issuer
= self
.issuer
135 self
.dmi
= self
.issuer
.dbg
.dmi
138 comb
+= self
.issuer
.pc_i
.data
.eq(self
.pc_i
)
139 comb
+= self
.issuer
.svstate_i
.data
.eq(self
.svstate_i
)
141 def prepare_for_test(self
, test
):
144 # set up bigendian (TODO: don't do this, use MSR)
145 yield self
.issuer
.core_bigendian_i
.eq(bigendian
)
153 def setup_during_test(self
):
154 yield from set_dmi(self
.dmi
, DBGCore
.CTRL
, 1<<DBGCtrl
.STOP
)
157 def run_test(self
, instructions
):
158 """run_hdl_state - runs a TestIssuer nmigen HDL simulation
161 imem
= self
.issuer
.imem
._get
_memory
()
162 core
= self
.issuer
.core
163 dmi
= self
.issuer
.dbg
.dmi
164 pdecode2
= self
.issuer
.pdecode2
168 # establish the TestIssuer context (mem, regs etc)
170 pc
= 0 # start address
171 counter
= 0 # test to pause/start
173 yield from setup_i_memory(imem
, pc
, instructions
)
174 yield from setup_tst_memory(l0
, self
.test
.mem
)
175 yield from setup_regs(pdecode2
, core
, self
.test
)
178 yield self
.pc_i
.eq(pc
)
179 yield self
.issuer
.pc_i
.ok
.eq(1)
181 # copy initial SVSTATE
182 initial_svstate
= copy(self
.test
.svstate
)
183 if isinstance(initial_svstate
, int):
184 initial_svstate
= SVP64State(initial_svstate
)
185 yield self
.svstate_i
.eq(initial_svstate
.value
)
186 yield self
.issuer
.svstate_i
.ok
.eq(1)
189 print("instructions", instructions
)
191 # run the loop of the instructions on the current test
192 index
= (yield self
.issuer
.cur_state
.pc
) // 4
193 while index
< len(instructions
):
194 ins
, code
= instructions
[index
]
196 print("hdl instr: 0x{:X}".format(ins
& 0xffffffff))
202 yield from set_dmi(dmi
, DBGCore
.CTRL
,
204 yield self
.issuer
.pc_i
.ok
.eq(0) # no change PC after this
205 yield self
.issuer
.svstate_i
.ok
.eq(0) # ditto
209 counter
= counter
+ 1
211 # wait until executed
212 while not (yield self
.issuer
.insn_done
):
217 index
= (yield self
.issuer
.cur_state
.pc
) // 4
219 terminated
= yield self
.issuer
.dbg
.terminated_o
220 print("terminated", terminated
)
222 if index
< len(instructions
):
223 # Get HDL mem and state
224 state
= yield from TestState("hdl", core
, self
.dut
,
226 hdl_states
.append(state
)
228 if index
>= len(instructions
):
229 print ("index over, send dmi stop")
231 yield from set_dmi(dmi
, DBGCore
.CTRL
,
236 terminated
= yield self
.issuer
.dbg
.terminated_o
237 print("terminated(2)", terminated
)
244 yield from set_dmi(self
.dmi
, DBGCore
.CTRL
, 1<<DBGCtrl
.STOP
)
248 # TODO, here is where the static (expected) results
249 # can be checked: register check (TODO, memory check)
250 # see https://bugs.libre-soc.org/show_bug.cgi?id=686#c51
251 # yield from check_regs(self, sim, core, test, code,
252 # >>>expected_data<<<)
255 cr
= yield from get_dmi(self
.dmi
, DBGCore
.CR
)
256 print("after test %s cr value %x" % (self
.test
.name
, cr
))
259 xer
= yield from get_dmi(self
.dmi
, DBGCore
.XER
)
260 print("after test %s XER value %x" % (self
.test
.name
, xer
))
262 # test of dmi reg get
263 for int_reg
in range(32):
264 yield from set_dmi(self
.dmi
, DBGCore
.GSPR_IDX
, int_reg
)
265 value
= yield from get_dmi(self
.dmi
, DBGCore
.GSPR_DATA
)
267 print("after test %s reg %2d value %x" %
268 (self
.test
.name
, int_reg
, value
))
271 yield from set_dmi(self
.dmi
, DBGCore
.CTRL
, 1<<DBGCtrl
.RESET
)
275 class TestRunner(TestRunnerBase
):
276 def __init__(self
, tst_data
, microwatt_mmu
=False, rom
=None,
277 svp64
=True, run_hdl
=True, run_sim
=True):
280 super().__init
__(tst_data
, microwatt_mmu
=microwatt_mmu
,
282 svp64
=svp64
, run_hdl
=run_hdl
, run_sim
=run_sim
)