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", "DSISR", "DAR", "PIDR"]
56 def set_mmu_spr(name
, i
, val
, core
): # important keep pep8 formatting
57 fsm
= core
.fus
.get_fu("mmu0").alu
58 yield fsm
.mmu
.l_in
.mtspr
.eq(1)
59 yield fsm
.mmu
.l_in
.sprn
.eq(i
)
60 yield fsm
.mmu
.l_in
.rs
.eq(val
)
62 yield fsm
.mmu
.l_in
.mtspr
.eq(0)
63 print("mmu_spr %s %d was updated %x" % (name
, i
, val
))
66 def setup_regs(pdecode2
, core
, test
):
68 # set up INT regfile, "direct" write (bypass rd/write ports)
69 intregs
= core
.regs
.int
72 yield intregs
.regs
[i
].reg
.eq(test
.regs
[i
])
74 yield intregs
.memory
._array
[i
].eq(test
.regs
[i
])
77 # set up MSR in STATE regfile, "direct" write (bypass rd/write ports)
78 stateregs
= core
.regs
.state
79 yield stateregs
.regs
[StateRegsEnum
.MSR
].reg
.eq(test
.msr
)
81 # set up CR regfile, "direct" write across all CRs
84 #cr = int('{:32b}'.format(cr)[::-1], 2)
85 print("setup cr reg", hex(cr
))
88 cri
= (cr
>> (i
* 4)) & 0xf
89 #cri = int('{:04b}'.format(cri)[::-1], 2)
90 print("setup cr reg", hex(cri
), i
,
91 crregs
.regs
[i
].reg
.shape())
92 yield crregs
.regs
[i
].reg
.eq(cri
)
94 # set up XER. "direct" write (bypass rd/write ports)
96 print("setup sprs", test
.sprs
)
98 if 'XER' in test
.sprs
:
99 xer
= test
.sprs
['XER']
103 if isinstance(xer
, int):
104 xer
= SelectableInt(xer
, 64)
105 sobit
= xer
[XER_bits
['SO']].value
106 yield xregs
.regs
[xregs
.SO
].reg
.eq(sobit
)
107 cabit
= xer
[XER_bits
['CA']].value
108 ca32bit
= xer
[XER_bits
['CA32']].value
109 yield xregs
.regs
[xregs
.CA
].reg
.eq(Cat(cabit
, ca32bit
))
110 ovbit
= xer
[XER_bits
['OV']].value
111 ov32bit
= xer
[XER_bits
['OV32']].value
112 yield xregs
.regs
[xregs
.OV
].reg
.eq(Cat(ovbit
, ov32bit
))
113 print("setting XER so %d ca %d ca32 %d ov %d ov32 %d" %
114 (sobit
, cabit
, ca32bit
, ovbit
, ov32bit
))
116 yield xregs
.regs
[xregs
.SO
].reg
.eq(0)
117 yield xregs
.regs
[xregs
.OV
].reg
.eq(0)
118 yield xregs
.regs
[xregs
.CA
].reg
.eq(0)
120 # setting both fast and slow SPRs from test data
122 fregs
= core
.regs
.fast
123 sregs
= core
.regs
.spr
124 for sprname
, val
in test
.sprs
.items():
125 if isinstance(val
, SelectableInt
):
127 if isinstance(sprname
, int):
128 sprname
= spr_dict
[sprname
].SPR
131 print ('set spr %s val %x' % (sprname
, val
))
133 fast
= spr_to_fast_reg(sprname
)
136 # match behaviour of SPRMap in power_decoder2.py
137 for i
, x
in enumerate(SPR
):
138 if sprname
== x
.name
:
139 print("setting slow SPR %d (%s) to %x" %
141 if sprname
not in mmu_sprs
:
142 yield sregs
.memory
._array
[i
].eq(val
)
144 yield from set_mmu_spr(sprname
, x
.value
, val
, core
)
146 print("setting fast reg %d (%s) to %x" %
147 (fast
, sprname
, val
))
149 rval
= fregs
.int.regs
[fast
].reg
151 rval
= fregs
.memory
._array
[fast
]
154 # allow changes to settle before reporting on XER
158 so
= yield xregs
.regs
[xregs
.SO
].reg
159 ov
= yield xregs
.regs
[xregs
.OV
].reg
160 ca
= yield xregs
.regs
[xregs
.CA
].reg
161 oe
= yield pdecode2
.e
.do
.oe
.oe
162 oe_ok
= yield pdecode2
.e
.do
.oe
.oe_ok
164 print("before: so/ov-32/ca-32", so
, bin(ov
), bin(ca
))
165 print("oe:", oe
, oe_ok
)
168 def check_regs(dut
, sim
, core
, test
, code
):
169 # create the two states and compare
170 testdic
= {'sim': sim
, 'hdl': core
}
171 yield from teststate_check_regs(dut
, testdic
, test
, code
)
174 def check_mem(dut
, sim
, core
, test
, code
):
175 # create the two states and compare mem
176 testdic
= {'sim': sim
, 'hdl': core
}
177 yield from teststate_check_mem(dut
, testdic
, test
, code
)
180 def wait_for_busy_hi(cu
):
182 busy_o
= yield cu
.busy_o
183 terminate_o
= yield cu
.core_terminate_o
185 print("busy/terminate:", busy_o
, terminate_o
)
187 print("!busy", busy_o
, terminate_o
)
191 def set_issue(core
, dec2
, sim
):
192 yield core
.issue_i
.eq(1)
194 yield core
.issue_i
.eq(0)
195 yield from wait_for_busy_hi(core
)
198 def wait_for_busy_clear(cu
):
200 busy_o
= yield cu
.o
.busy_o
201 terminate_o
= yield cu
.o
.core_terminate_o
203 print("busy/terminate:", busy_o
, terminate_o
)
209 class TestRunner(FHDLTestCase
):
210 def __init__(self
, tst_data
):
211 super().__init
__("run_all")
212 self
.test_data
= tst_data
217 instruction
= Signal(32)
219 units
= {'alu': 3, 'cr': 1, 'branch': 1, 'trap': 1,
223 'div': 1, 'shiftrot': 1}
225 pspec
= TestMemPspec(ldst_ifacetype
='testpi',
233 cur_state
= CoreState("cur") # current state (MSR/PC/SVSTATE)
234 pdecode2
= PowerDecode2(None, state
=cur_state
,
235 #opkls=IssuerDecode2ToOperand,
236 svp64_en
=True, # self.svp64_en,
237 regreduce_en
=False, #self.regreduce_en
240 m
.submodules
.core
= core
= NonProductionCore(pspec
)
241 m
.submodules
.pdecode2
= pdecode2
242 core
.pdecode2
= pdecode2
245 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
246 comb
+= pdecode2
.dec
.bigendian
.eq(bigendian
) # little / big?
247 comb
+= core
.i
.e
.eq(pdecode2
.e
)
248 comb
+= core
.i
.state
.eq(cur_state
)
249 comb
+= core
.i
.raw_insn_i
.eq(instruction
)
250 comb
+= core
.i
.bigendian_i
.eq(bigendian
)
252 # set the PC StateRegs read port to always send back the PC
253 stateregs
= core
.regs
.state
254 pc_regnum
= StateRegs
.PC
255 comb
+= stateregs
.r_ports
['cia'].ren
.eq(1<<pc_regnum
)
257 # temporary hack: says "go" immediately for both address gen and ST
258 ldst
= core
.fus
.fus
['ldst0']
259 m
.d
.comb
+= ldst
.ad
.go_i
.eq(ldst
.ad
.rel_o
) # link addr-go to rel
260 m
.d
.comb
+= ldst
.st
.go_i
.eq(ldst
.st
.rel_o
) # link store-go to rel
269 for test
in self
.test_data
:
271 program
= test
.program
272 with self
.subTest(test
.name
):
273 sim
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
,
277 gen
= program
.generate_instructions()
278 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
280 yield from setup_tst_memory(l0
, test
.mem
)
281 yield from setup_regs(pdecode2
, core
, test
)
283 index
= sim
.pc
.CIA
.value
// 4
284 while index
< len(instructions
):
285 ins
, code
= instructions
[index
]
287 print("instruction: 0x{:X}".format(ins
& 0xffffffff))
290 # ask the decoder to decode this binary data (endian'd)
291 yield instruction
.eq(ins
) # raw binary instr.
295 # call simulated operation
296 opname
= code
.split(' ')[0]
297 yield from sim
.call(opname
)
298 pc
= sim
.pc
.CIA
.value
299 nia
= sim
.pc
.NIA
.value
302 # set the PC to the same simulated value
303 # (core is not able to do this itself, except
305 print ("after call, pc nia", pc
, nia
)
306 yield stateregs
.regs
[pc_regnum
].reg
.eq(pc
)
309 yield core
.p
.i_valid
.eq(1)
311 o_ready
= yield core
.p
.o_ready
316 o_ready
= yield core
.p
.o_ready
317 yield core
.p
.i_valid
.eq(0)
319 # set operand and get inputs
320 yield from wait_for_busy_clear(core
)
322 # synchronised (non-overlap) is fine to check
323 if not core
.allow_overlap
:
325 yield from check_regs(self
, sim
, core
, test
, code
)
328 yield from check_mem(self
, sim
, core
, test
, code
)
330 # non-overlap mode is only fine to check right at the end
331 if core
.allow_overlap
:
332 # wait until all settled
333 # XXX really this should be in DMI, which should in turn
334 # use issuer.any_busy to not send back "stopped" signal
335 while (yield core
.o
.any_busy_o
):
340 yield from check_regs(self
, sim
, core
, test
, code
)
343 yield from check_mem(self
, sim
, core
, test
, code
)
345 # give a couple extra clock cycles for gtkwave display to be happy
349 sim
.add_sync_process(process
)
350 with sim
.write_vcd("core_simulator.vcd", "core_simulator.gtkw",
355 if __name__
== "__main__":
356 unittest
.main(exit
=False)
357 suite
= unittest
.TestSuite()
358 suite
.addTest(TestRunner(HazardTestCase().test_data
))
359 suite
.addTest(TestRunner(RandomHazardTestCase().test_data
))
360 #suite.addTest(TestRunner(LDSTTestCase().test_data))
361 #suite.addTest(TestRunner(CRTestCase().test_data))
362 #suite.addTest(TestRunner(ShiftRotTestCase().test_data))
363 #suite.addTest(TestRunner(LogicalTestCase().test_data))
364 #suite.addTest(TestRunner(ALUTestCase().test_data))
365 #suite.addTest(TestRunner(BranchTestCase().test_data))
367 runner
= unittest
.TextTestRunner()