eb99ef039cdf65703b9f2c91c911bcfb284eb12f
5 * https://bugs.libre-soc.org/show_bug.cgi?id=363
6 * https://bugs.libre-soc.org/show_bug.cgi?id=686
9 from nmigen
import Module
, Signal
, Cat
10 from nmigen
.back
.pysim
import Simulator
, Delay
, Settle
11 from nmutil
.formaltest
import FHDLTestCase
12 from nmigen
.cli
import rtlil
14 from openpower
.test
.state
import (SimState
, teststate_check_regs
,
16 from soc
.simple
.test
.teststate
import HDLState
17 from openpower
.decoder
.isa
.caller
import special_sprs
18 from openpower
.decoder
.power_decoder
import create_pdecode
19 from openpower
.decoder
.power_decoder2
import PowerDecode2
20 from openpower
.decoder
.selectable_int
import SelectableInt
21 from openpower
.decoder
.isa
.all
import ISA
22 from openpower
.decoder
.decode2execute1
import IssuerDecode2ToOperand
23 from openpower
.state
import CoreState
25 # note that using SPRreduced has to be done to match the
26 # PowerDecoder2 SPR map
27 from openpower
.decoder
.power_enums
import SPRreduced
as SPR
28 from openpower
.decoder
.power_enums
import spr_dict
, Function
, XER_bits
29 from soc
.config
.test
.test_loadstore
import TestMemPspec
30 from openpower
.endian
import bigendian
31 from soc
.regfile
.regfiles
import StateRegs
33 from soc
.simple
.core
import NonProductionCore
34 from soc
.experiment
.compalu_multi
import find_ok
# hack
36 from soc
.fu
.compunits
.test
.test_compunit
import (setup_tst_memory
,
39 # test with ALU data and Logical data
40 from soc
.fu
.alu
.test
.test_pipe_caller
import ALUTestCase
41 from soc
.fu
.logical
.test
.test_pipe_caller
import LogicalTestCase
42 from soc
.fu
.shift_rot
.test
.test_pipe_caller
import ShiftRotTestCase
43 from soc
.fu
.cr
.test
.test_pipe_caller
import CRTestCase
44 from soc
.fu
.branch
.test
.test_pipe_caller
import BranchTestCase
45 from soc
.fu
.ldst
.test
.test_pipe_caller
import LDSTTestCase
46 from openpower
.test
.general
.overlap_hazards
import (HazardTestCase
,
48 from openpower
.util
import spr_to_fast_reg
50 from openpower
.consts
import StateRegsEnum
52 # list of SPRs that are controlled and managed by the MMU
53 mmu_sprs
= ["PRTBL", "PIDR"]
54 ldst_sprs
= ["DAR", "DSISR"]
57 def set_mmu_spr(name
, i
, val
, core
): # important keep pep8 formatting
58 fsm
= core
.fus
.get_fu("mmu0").alu
59 yield fsm
.mmu
.l_in
.mtspr
.eq(1)
60 yield fsm
.mmu
.l_in
.sprn
.eq(i
)
61 yield fsm
.mmu
.l_in
.rs
.eq(val
)
63 yield fsm
.mmu
.l_in
.mtspr
.eq(0)
65 done
= yield fsm
.mmu
.l_out
.done
70 print("mmu_spr %s %d was updated %x" % (name
, i
, val
))
73 def set_ldst_spr(name
, i
, val
, core
): # important keep pep8 formatting
74 ldst
= core
.fus
.get_fu("mmu0").alu
.ldst
# awkward to get at but it works
75 yield ldst
.sprval_in
.eq(val
)
76 yield ldst
.mmu_set_spr
.eq(1)
78 yield ldst
.mmu_set_dar
.eq(1)
80 yield ldst
.mmu_set_dar
.eq(0)
82 yield ldst
.mmu_set_dsisr
.eq(1)
84 yield ldst
.mmu_set_dsisr
.eq(0)
85 yield ldst
.mmu_set_spr
.eq(0)
86 print("ldst_spr %s %d was updated %x" % (name
, i
, val
))
89 def setup_regs(pdecode2
, core
, test
):
91 # set up INT regfile, "direct" write (bypass rd/write ports)
92 intregs
= core
.regs
.int
95 yield intregs
.regs
[i
].reg
.eq(test
.regs
[i
])
97 yield intregs
.memory
._array
[i
].eq(test
.regs
[i
])
100 # set up MSR in STATE regfile, "direct" write (bypass rd/write ports)
101 stateregs
= core
.regs
.state
102 yield stateregs
.regs
[StateRegsEnum
.MSR
].reg
.eq(test
.msr
)
104 # set up CR regfile, "direct" write across all CRs
106 crregs
= core
.regs
.cr
107 #cr = int('{:32b}'.format(cr)[::-1], 2)
108 print("setup cr reg", hex(cr
))
111 cri
= (cr
>> (i
* 4)) & 0xf
112 #cri = int('{:04b}'.format(cri)[::-1], 2)
113 print("setup cr reg", hex(cri
), i
,
114 crregs
.regs
[i
].reg
.shape())
115 yield crregs
.regs
[i
].reg
.eq(cri
)
117 # set up XER. "direct" write (bypass rd/write ports)
118 xregs
= core
.regs
.xer
119 print("setup sprs", test
.sprs
)
121 if 'XER' in test
.sprs
:
122 xer
= test
.sprs
['XER']
126 if isinstance(xer
, int):
127 xer
= SelectableInt(xer
, 64)
128 sobit
= xer
[XER_bits
['SO']].value
129 yield xregs
.regs
[xregs
.SO
].reg
.eq(sobit
)
130 cabit
= xer
[XER_bits
['CA']].value
131 ca32bit
= xer
[XER_bits
['CA32']].value
132 yield xregs
.regs
[xregs
.CA
].reg
.eq(Cat(cabit
, ca32bit
))
133 ovbit
= xer
[XER_bits
['OV']].value
134 ov32bit
= xer
[XER_bits
['OV32']].value
135 yield xregs
.regs
[xregs
.OV
].reg
.eq(Cat(ovbit
, ov32bit
))
136 print("setting XER so %d ca %d ca32 %d ov %d ov32 %d" %
137 (sobit
, cabit
, ca32bit
, ovbit
, ov32bit
))
139 yield xregs
.regs
[xregs
.SO
].reg
.eq(0)
140 yield xregs
.regs
[xregs
.OV
].reg
.eq(0)
141 yield xregs
.regs
[xregs
.CA
].reg
.eq(0)
143 # setting both fast and slow SPRs from test data
145 fregs
= core
.regs
.fast
146 sregs
= core
.regs
.spr
147 for sprname
, val
in test
.sprs
.items():
148 if isinstance(val
, SelectableInt
):
150 if isinstance(sprname
, int):
151 sprname
= spr_dict
[sprname
].SPR
154 print ('set spr %s val %x' % (sprname
, val
))
156 fast
= spr_to_fast_reg(sprname
)
159 # match behaviour of SPRMap in power_decoder2.py
160 for i
, x
in enumerate(SPR
):
161 if sprname
== x
.name
:
162 print("setting slow SPR %d (%s/%d) to %x" %
163 (i
, sprname
, x
.value
, val
))
164 if sprname
in mmu_sprs
:
165 yield from set_mmu_spr(sprname
, x
.value
, val
, core
)
166 elif sprname
in ldst_sprs
:
167 yield from set_ldst_spr(sprname
, x
.value
, val
, core
)
169 yield sregs
.memory
._array
[i
].eq(val
)
171 print("setting fast reg %d (%s) to %x" %
172 (fast
, sprname
, val
))
174 rval
= fregs
.int.regs
[fast
].reg
176 rval
= fregs
.memory
._array
[fast
]
179 # allow changes to settle before reporting on XER
183 so
= yield xregs
.regs
[xregs
.SO
].reg
184 ov
= yield xregs
.regs
[xregs
.OV
].reg
185 ca
= yield xregs
.regs
[xregs
.CA
].reg
186 oe
= yield pdecode2
.e
.do
.oe
.oe
187 oe_ok
= yield pdecode2
.e
.do
.oe
.oe_ok
189 print("before: so/ov-32/ca-32", so
, bin(ov
), bin(ca
))
190 print("oe:", oe
, oe_ok
)
193 def check_regs(dut
, sim
, core
, test
, code
):
194 # create the two states and compare
195 testdic
= {'sim': sim
, 'hdl': core
}
196 yield from teststate_check_regs(dut
, testdic
, test
, code
)
199 def check_mem(dut
, sim
, core
, test
, code
):
200 # create the two states and compare mem
201 testdic
= {'sim': sim
, 'hdl': core
}
202 yield from teststate_check_mem(dut
, testdic
, test
, code
)
205 def wait_for_busy_hi(cu
):
207 busy_o
= yield cu
.busy_o
208 terminate_o
= yield cu
.core_terminate_o
210 print("busy/terminate:", busy_o
, terminate_o
)
212 print("!busy", busy_o
, terminate_o
)
216 def set_issue(core
, dec2
, sim
):
217 yield core
.issue_i
.eq(1)
219 yield core
.issue_i
.eq(0)
220 yield from wait_for_busy_hi(core
)
223 def wait_for_busy_clear(cu
):
225 busy_o
= yield cu
.o
.busy_o
226 terminate_o
= yield cu
.o
.core_terminate_o
228 print("busy/terminate:", busy_o
, terminate_o
)
234 class TestRunner(FHDLTestCase
):
235 def __init__(self
, tst_data
):
236 super().__init
__("run_all")
237 self
.test_data
= tst_data
242 instruction
= Signal(32)
244 units
= {'alu': 3, 'cr': 1, 'branch': 1, 'trap': 1,
248 'div': 1, 'shiftrot': 1}
250 pspec
= TestMemPspec(ldst_ifacetype
='testpi',
258 cur_state
= CoreState("cur") # current state (MSR/PC/SVSTATE)
259 pdecode2
= PowerDecode2(None, state
=cur_state
,
260 #opkls=IssuerDecode2ToOperand,
261 svp64_en
=True, # self.svp64_en,
262 regreduce_en
=False, #self.regreduce_en
265 m
.submodules
.core
= core
= NonProductionCore(pspec
)
266 m
.submodules
.pdecode2
= pdecode2
267 core
.pdecode2
= pdecode2
270 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
271 comb
+= pdecode2
.dec
.bigendian
.eq(bigendian
) # little / big?
272 comb
+= core
.i
.e
.eq(pdecode2
.e
)
273 comb
+= core
.i
.state
.eq(cur_state
)
274 comb
+= core
.i
.raw_insn_i
.eq(instruction
)
275 comb
+= core
.i
.bigendian_i
.eq(bigendian
)
277 # set the PC StateRegs read port to always send back the PC
278 stateregs
= core
.regs
.state
279 pc_regnum
= StateRegs
.PC
280 comb
+= stateregs
.r_ports
['cia'].ren
.eq(1<<pc_regnum
)
282 # temporary hack: says "go" immediately for both address gen and ST
283 ldst
= core
.fus
.fus
['ldst0']
284 m
.d
.comb
+= ldst
.ad
.go_i
.eq(ldst
.ad
.rel_o
) # link addr-go to rel
285 m
.d
.comb
+= ldst
.st
.go_i
.eq(ldst
.st
.rel_o
) # link store-go to rel
294 for test
in self
.test_data
:
296 program
= test
.program
297 with self
.subTest(test
.name
):
298 sim
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
,
302 gen
= program
.generate_instructions()
303 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
305 yield from setup_tst_memory(l0
, test
.mem
)
306 yield from setup_regs(pdecode2
, core
, test
)
308 index
= sim
.pc
.CIA
.value
// 4
309 while index
< len(instructions
):
310 ins
, code
= instructions
[index
]
312 print("instruction: 0x{:X}".format(ins
& 0xffffffff))
315 # ask the decoder to decode this binary data (endian'd)
316 yield instruction
.eq(ins
) # raw binary instr.
320 # call simulated operation
321 opname
= code
.split(' ')[0]
322 yield from sim
.call(opname
)
323 pc
= sim
.pc
.CIA
.value
324 nia
= sim
.pc
.NIA
.value
327 # set the PC to the same simulated value
328 # (core is not able to do this itself, except
330 print ("after call, pc nia", pc
, nia
)
331 yield stateregs
.regs
[pc_regnum
].reg
.eq(pc
)
334 yield core
.p
.i_valid
.eq(1)
336 o_ready
= yield core
.p
.o_ready
341 o_ready
= yield core
.p
.o_ready
342 yield core
.p
.i_valid
.eq(0)
344 # set operand and get inputs
345 yield from wait_for_busy_clear(core
)
347 # synchronised (non-overlap) is fine to check
348 if not core
.allow_overlap
:
350 yield from check_regs(self
, sim
, core
, test
, code
)
353 yield from check_mem(self
, sim
, core
, test
, code
)
355 # non-overlap mode is only fine to check right at the end
356 if core
.allow_overlap
:
357 # wait until all settled
358 # XXX really this should be in DMI, which should in turn
359 # use issuer.any_busy to not send back "stopped" signal
360 while (yield core
.o
.any_busy_o
):
365 yield from check_regs(self
, sim
, core
, test
, code
)
368 yield from check_mem(self
, sim
, core
, test
, code
)
370 # give a couple extra clock cycles for gtkwave display to be happy
374 sim
.add_sync_process(process
)
375 with sim
.write_vcd("core_simulator.vcd", "core_simulator.gtkw",
380 if __name__
== "__main__":
381 unittest
.main(exit
=False)
382 suite
= unittest
.TestSuite()
383 suite
.addTest(TestRunner(HazardTestCase().test_data
))
384 suite
.addTest(TestRunner(RandomHazardTestCase().test_data
))
385 #suite.addTest(TestRunner(LDSTTestCase().test_data))
386 #suite.addTest(TestRunner(CRTestCase().test_data))
387 #suite.addTest(TestRunner(ShiftRotTestCase().test_data))
388 #suite.addTest(TestRunner(LogicalTestCase().test_data))
389 #suite.addTest(TestRunner(ALUTestCase().test_data))
390 #suite.addTest(TestRunner(BranchTestCase().test_data))
392 runner
= unittest
.TextTestRunner()