Add operand producers to the parallel LDST Compunit test case
[soc.git] / src / soc / experiment / test / test_compldst_multi.py
1 """Self-contained unit test for the Load/Store CompUnit
2 """
3
4 import unittest
5 from nmigen import Module
6 from nmigen.sim import Simulator
7 from nmutil.gtkw import write_gtkw
8
9 from openpower.consts import MSR
10 from openpower.decoder.power_enums import MicrOp, LDSTMode
11
12 from soc.experiment.compldst_multi import LDSTCompUnit
13 from soc.experiment.pimem import PortInterface
14 from soc.experiment.test.test_compalu_multi import OperandProducer
15 from soc.fu.ldst.pipe_data import LDSTPipeSpec
16
17
18 class OpSim:
19 def __init__(self, dut, sim):
20 self.dut = dut
21 # create one operand producer for each input port
22 self.producers = list()
23 for i in range(len(dut.src_i)):
24 self.producers.append(OperandProducer(sim, dut, i))
25
26 def issue(self, op, ra=None, rb=None, rc=None,
27 zero_a=False, imm=None, update=False,
28 byterev=True, signext=False,
29 data_len=2, msr_pr=0,
30 delays=None):
31 assert zero_a == (ra is None), \
32 "ra and zero_a are mutually exclusive"
33 assert (rb is None) != (imm is None), \
34 "rb and imm are mutually exclusive"
35 if op == MicrOp.OP_STORE:
36 assert rc, "need source operand for store"
37 dut = self.dut
38 pi = dut.pi
39 producers = self.producers
40 if ra:
41 yield from producers[0].send(ra, delays['ra'])
42 if rb:
43 yield from producers[1].send(rb, delays['rb'])
44 if rc:
45 yield from producers[2].send(rc, delays['rc'])
46 yield dut.oper_i.insn_type.eq(op)
47 yield dut.oper_i.data_len.eq(data_len)
48 yield dut.oper_i.zero_a.eq(zero_a)
49 yield dut.oper_i.byte_reverse.eq(byterev)
50 yield dut.oper_i.sign_extend.eq(signext)
51 if imm is not None:
52 yield dut.oper_i.imm_data.data.eq(imm)
53 yield dut.oper_i.imm_data.ok.eq(1)
54 if update:
55 yield dut.oper_i.ldst_mode.eq(LDSTMode.update)
56 yield dut.oper_i.msr[MSR.PR].eq(msr_pr)
57 yield dut.issue_i.eq(1)
58 yield
59 yield dut.issue_i.eq(0)
60 # deactivate decoder inputs along with issue_i, so we can be sure they
61 # were latched at the correct cycle
62 yield dut.oper_i.insn_type.eq(0)
63 yield dut.oper_i.data_len.eq(0)
64 yield dut.oper_i.zero_a.eq(0)
65 yield dut.oper_i.byte_reverse.eq(0)
66 yield dut.oper_i.sign_extend.eq(0)
67 yield dut.oper_i.imm_data.data.eq(0)
68 yield dut.oper_i.imm_data.ok.eq(0)
69 yield dut.oper_i.ldst_mode.eq(LDSTMode.NONE)
70 yield dut.oper_i.msr[MSR.PR].eq(0)
71 while not (yield pi.addr.ok):
72 yield
73
74
75 class TestLDSTCompUnit(unittest.TestCase):
76
77 def test_ldst_compunit(self):
78 m = Module()
79 pi = PortInterface(name="pi")
80 regspec = LDSTPipeSpec.regspec
81 dut = LDSTCompUnit(pi, regspec, name="ldst")
82 m.submodules.dut = dut
83 sim = Simulator(m)
84 sim.add_clock(1e-6)
85 op = OpSim(dut, sim)
86 self.write_gtkw()
87
88 def process():
89 yield from op.issue(MicrOp.OP_STORE, ra=1, rb=2, rc=3,
90 delays={'ra': 1, 'rb': 2, 'rc': 5})
91
92 sim.add_sync_process(process)
93 sim_writer = sim.write_vcd("test_ldst_compunit.vcd")
94 with sim_writer:
95 sim.run()
96
97 @classmethod
98 def write_gtkw(cls):
99 traces = [
100 'clk',
101 ('operation', [
102 ('oper_i_ldst__insn_type', {'display': 'insn_type'}),
103 ('oper_i_ldst__ldst_mode', {'display': 'ldst_mode'}),
104 ('oper_i_ldst__zero_a', {'display': 'zero_a'}),
105 ('oper_i_ldst__imm_data__ok', {'display': 'imm_data_ok'}),
106 ('oper_i_ldst__imm_data__data[63:0]',
107 {'display': 'imm_data_data', 'base': 'dec'})
108 ]),
109 ('cu_issue_i', {'display': 'issue_i'}),
110 ('cu_busy_o', {'display': 'busy_o'})
111 ]
112 write_gtkw("test_ldst_compunit.gtkw",
113 "test_ldst_compunit.vcd",
114 traces, module="top.dut")
115
116
117 if __name__ == '__main__':
118 unittest.main()