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 """HDLRunner: Implements methods for the setup, preparation, and
123 running of tests using nmigen HDL simulation.
125 def __init__(self
, dut
, m
, pspec
):
126 super().__init
__("hdl", HDLRunner
)
129 self
.pc_i
= Signal(32)
130 self
.svstate_i
= Signal(64)
132 #hard_reset = Signal(reset_less=True)
133 self
.issuer
= TestIssuerInternal(pspec
)
134 # use DMI RESET command instead, this does actually work though
135 #issuer = ResetInserter({'coresync': hard_reset,
136 # 'sync': hard_reset})(issuer)
137 m
.submodules
.issuer
= self
.issuer
138 self
.dmi
= self
.issuer
.dbg
.dmi
141 comb
+= self
.issuer
.pc_i
.data
.eq(self
.pc_i
)
142 comb
+= self
.issuer
.svstate_i
.data
.eq(self
.svstate_i
)
144 def prepare_for_test(self
, test
):
147 # set up bigendian (TODO: don't do this, use MSR)
148 yield self
.issuer
.core_bigendian_i
.eq(bigendian
)
156 def setup_during_test(self
):
157 yield from set_dmi(self
.dmi
, DBGCore
.CTRL
, 1<<DBGCtrl
.STOP
)
160 def run_test(self
, instructions
):
161 """run_hdl_state - runs a TestIssuer nmigen HDL simulation
164 imem
= self
.issuer
.imem
._get
_memory
()
165 core
= self
.issuer
.core
166 dmi
= self
.issuer
.dbg
.dmi
167 pdecode2
= self
.issuer
.pdecode2
171 # establish the TestIssuer context (mem, regs etc)
173 pc
= 0 # start address
174 counter
= 0 # test to pause/start
176 yield from setup_i_memory(imem
, pc
, instructions
)
177 yield from setup_tst_memory(l0
, self
.test
.mem
)
178 yield from setup_regs(pdecode2
, core
, self
.test
)
181 yield self
.pc_i
.eq(pc
)
182 yield self
.issuer
.pc_i
.ok
.eq(1)
184 # copy initial SVSTATE
185 initial_svstate
= copy(self
.test
.svstate
)
186 if isinstance(initial_svstate
, int):
187 initial_svstate
= SVP64State(initial_svstate
)
188 yield self
.svstate_i
.eq(initial_svstate
.value
)
189 yield self
.issuer
.svstate_i
.ok
.eq(1)
192 print("instructions", instructions
)
194 # run the loop of the instructions on the current test
195 index
= (yield self
.issuer
.cur_state
.pc
) // 4
196 while index
< len(instructions
):
197 ins
, code
= instructions
[index
]
199 print("hdl instr: 0x{:X}".format(ins
& 0xffffffff))
205 yield from set_dmi(dmi
, DBGCore
.CTRL
,
207 yield self
.issuer
.pc_i
.ok
.eq(0) # no change PC after this
208 yield self
.issuer
.svstate_i
.ok
.eq(0) # ditto
212 counter
= counter
+ 1
214 # wait until executed
215 while not (yield self
.issuer
.insn_done
):
220 index
= (yield self
.issuer
.cur_state
.pc
) // 4
222 terminated
= yield self
.issuer
.dbg
.terminated_o
223 print("terminated", terminated
)
225 if index
< len(instructions
):
226 # Get HDL mem and state
227 state
= yield from TestState("hdl", core
, self
.dut
,
229 hdl_states
.append(state
)
231 if index
>= len(instructions
):
232 print ("index over, send dmi stop")
234 yield from set_dmi(dmi
, DBGCore
.CTRL
,
239 terminated
= yield self
.issuer
.dbg
.terminated_o
240 print("terminated(2)", terminated
)
247 yield from set_dmi(self
.dmi
, DBGCore
.CTRL
, 1<<DBGCtrl
.STOP
)
251 # TODO, here is where the static (expected) results
252 # can be checked: register check (TODO, memory check)
253 # see https://bugs.libre-soc.org/show_bug.cgi?id=686#c51
254 # yield from check_regs(self, sim, core, test, code,
255 # >>>expected_data<<<)
258 cr
= yield from get_dmi(self
.dmi
, DBGCore
.CR
)
259 print("after test %s cr value %x" % (self
.test
.name
, cr
))
262 xer
= yield from get_dmi(self
.dmi
, DBGCore
.XER
)
263 print("after test %s XER value %x" % (self
.test
.name
, xer
))
265 # test of dmi reg get
266 for int_reg
in range(32):
267 yield from set_dmi(self
.dmi
, DBGCore
.GSPR_IDX
, int_reg
)
268 value
= yield from get_dmi(self
.dmi
, DBGCore
.GSPR_DATA
)
270 print("after test %s reg %2d value %x" %
271 (self
.test
.name
, int_reg
, value
))
274 yield from set_dmi(self
.dmi
, DBGCore
.CTRL
, 1<<DBGCtrl
.RESET
)
278 class TestRunner(TestRunnerBase
):
279 def __init__(self
, tst_data
, microwatt_mmu
=False, rom
=None,
280 svp64
=True, run_hdl
=True, run_sim
=True):
283 super().__init
__(tst_data
, microwatt_mmu
=microwatt_mmu
,
285 svp64
=svp64
, run_hdl
=run_hdl
, run_sim
=run_sim
)