1 """FP Unit Test Infrastructure
5 * random range against random range
6 * +/- 0, +/- inf, +/- NaN permutations, all tested against all permutations
7 * all of those permutations (+/- 0/inf/NaN) against the following:
8 - nearly zero (random variations)
9 - minimum non-zero exponent (random variations)
10 - nearly infinite (random variations)
11 - random versions of NaN (noncanonical NaN)
12 - random numbers (at the full range)
14 inversion of permutations also done, where appropriate (A,B and B,A)
16 single-operand version also supported
20 from ieee754
.fpcommon
.test
.fpmux
import runfp
, repeat
, pipe_cornercases_repeat
22 from random
import randint
23 from random
import seed
27 def corner_cases(mod
):
28 return [mod
.zero(1), mod
.zero(0),
29 mod
.inf(1), mod
.inf(0),
30 mod
.nan(1), mod
.nan(0)]
32 def get_corner_cases(mod
, single_op
=False):
34 from itertools
import permutations
35 cc
= corner_cases(mod
)
36 stimulus_a
= [i
[0] for i
in permutations(cc
, 2)]
39 stimulus_b
= [i
[1] for i
in permutations(cc
, 2)]
40 return zip(stimulus_a
, stimulus_b
)
43 def replicate(fixed_num
, maxcount
):
44 if isinstance(fixed_num
, int):
45 return [fixed_num
for i
in range(maxcount
)]
51 return randint(0, mval
)
53 def get_rand1(mod
, fixed_num
, maxcount
, width
, single_op
=False):
54 stimulus_b
= [get_rval(width
) for i
in range(maxcount
)]
58 stimulus_a
= replicate(fixed_num
, maxcount
)
59 yield from zip(stimulus_a
, stimulus_b
)
60 yield from zip(stimulus_b
, stimulus_a
)
63 def get_nan_noncan(mod
, fixed_num
, maxcount
, width
, single_op
=False):
65 stimulus_b
= [mod
.set_exponent(get_rval(width
), mod
.max_e
) \
66 for i
in range(maxcount
)]
70 stimulus_a
= replicate(fixed_num
, maxcount
)
71 yield from zip(stimulus_a
, stimulus_b
)
72 yield from zip(stimulus_b
, stimulus_a
)
75 def get_n127(mod
, fixed_num
, maxcount
, width
, single_op
=False):
77 stimulus_b
= [mod
.set_exponent(get_rval(width
), -mod
.max_e
+1
) \
78 for i
in range(maxcount
)]
82 stimulus_a
= replicate(fixed_num
, maxcount
)
83 yield from zip(stimulus_a
, stimulus_b
)
84 yield from zip(stimulus_b
, stimulus_a
)
87 def get_nearly_zero(mod
, fixed_num
, maxcount
, width
, single_op
=False):
89 stimulus_b
= [mod
.set_exponent(get_rval(width
), -mod
.max_e
+2
) \
90 for i
in range(maxcount
)]
94 stimulus_a
= replicate(fixed_num
, maxcount
)
95 yield from zip(stimulus_a
, stimulus_b
)
96 yield from zip(stimulus_b
, stimulus_a
)
99 def get_nearly_inf(mod
, fixed_num
, maxcount
, width
, single_op
=False):
101 stimulus_b
= [mod
.set_exponent(get_rval(width
), mod
.max_e
-1
) \
102 for i
in range(maxcount
)]
104 yield from stimulus_b
106 stimulus_a
= replicate(fixed_num
, maxcount
)
107 yield from zip(stimulus_a
, stimulus_b
)
108 yield from zip(stimulus_b
, stimulus_a
)
111 def get_corner_rand(mod
, fixed_num
, maxcount
, width
, single_op
=False):
113 stimulus_b
= [get_rval(width
) for i
in range(maxcount
)]
115 yield from stimulus_b
117 stimulus_a
= replicate(fixed_num
, maxcount
)
118 yield from zip(stimulus_a
, stimulus_b
)
119 yield from zip(stimulus_b
, stimulus_a
)
123 def __init__(self
, dut
, name
, mod
, fmod
, width
, fpfn
, count
,
132 self
.single_op
= single_op
135 def run(self
, name
, fn
):
136 name
= "%s_%s" % (self
.name
, name
)
137 pipe_cornercases_repeat(self
.dut
, name
, self
.mod
, self
.fmod
,
138 self
.width
, fn
, corner_cases
, self
.fpfn
,
139 self
.count
, self
.single_op
,
142 def run_cornercases(self
):
143 ccs
= get_corner_cases(self
.mod
, self
.single_op
)
144 vals
= repeat(self
.dut
.num_rows
, ccs
)
145 tname
= "test_fp%s_pipe_fp%d_cornercases" % (self
.name
, self
.width
)
146 runfp(self
.dut
, self
.width
, tname
, self
.fmod
, self
.fpfn
, vals
=vals
,
147 single_op
=self
.single_op
,
150 def run_regressions(self
, regressions_fn
):
151 vals
= repeat(self
.dut
.num_rows
, regressions_fn())
152 #print ("regressions", self.single_op, vals)
153 tname
= "test_fp%s_pipe_fp%d_regressions" % (self
.name
, self
.width
)
154 runfp(self
.dut
, self
.width
, tname
, self
.fmod
, self
.fpfn
, vals
=vals
,
155 single_op
=self
.single_op
,
158 def run_random(self
):
159 tname
= "test_fp%s_pipe_fp%d_rand" % (self
.name
, self
.width
)
160 runfp(self
.dut
, self
.width
, tname
, self
.fmod
, self
.fpfn
,
161 single_op
=self
.single_op
,
165 def run_pipe_fp(dut
, width
, name
, mod
, fmod
, regressions
, fpfn
, count
,
168 pc
= PipeFPCase(dut
, name
, mod
, fmod
, width
, fpfn
, count
, single_op
, opcode
)
170 pc
.run_regressions(regressions
)
172 pc
.run("rand1", get_rand1
)
173 pc
.run("n127", get_n127
)
174 pc
.run("noncan", get_nan_noncan
)
175 pc
.run("nearlyzero", get_nearly_zero
)
176 pc
.run("nearlyinf", get_nearly_inf
)
177 pc
.run("corner_rand", get_corner_rand
)