add missing inf * 0 -> NaN cases
[ieee754fpu.git] / fpmul_test.smt2
1 ; SPDX-License-Identifier: LGPL-2.1-or-later
2
3 ; Test to see if using smt-lib2's floating-point support for checking fpu hw
4 ; is feasible by implementing fp multiplication with bit-vectors and seeing if
5 ; the smt checkers work. The idea is we can run this test before putting in
6 ; all the effort to add support in yosys and nmigen for smtlib2 reals and
7 ; floating-point numbers.
8
9 ; run with: z3 -smt2 fpmul_test.smt2
10
11 ; create some handy type aliases
12 (define-sort bv1 () (_ BitVec 1))
13 (define-sort bv2 () (_ BitVec 2))
14 (define-sort bv4 () (_ BitVec 4))
15 (define-sort bv8 () (_ BitVec 8))
16 (define-sort bv16 () (_ BitVec 16))
17 (define-sort bv23 () (_ BitVec 23))
18 (define-sort bv24 () (_ BitVec 24))
19 (define-sort bv32 () (_ BitVec 32))
20 (define-sort bv48 () (_ BitVec 48))
21
22 ; type for signed f32 exponents
23 (define-sort f32_sexp_t () (_ BitVec 12))
24 ; signed less-than comparison
25 (define-fun f32_sexp_lt ((a f32_sexp_t) (b f32_sexp_t)) Bool
26 (bvult (bvxor #x800 a) (bvxor #x800 b))
27 )
28 ; subtraction
29 (define-fun f32_sexp_sub ((a f32_sexp_t) (b f32_sexp_t)) f32_sexp_t
30 (bvadd a (bvneg b))
31 )
32 ; conversion
33 (define-fun f32_sexp_to_bv8 ((v f32_sexp_t)) bv8 ((_ extract 7 0) v))
34 (define-fun bv8_to_f32_sexp ((v bv8)) f32_sexp_t (concat #x0 v))
35 (define-fun f32_sexp_to_bv48 ((v f32_sexp_t)) bv48 (concat #x000000000 v))
36 (define-fun bv48_to_f32_sexp ((v bv48)) f32_sexp_t ((_ extract 11 0) v))
37 (define-fun bv24_to_bv48 ((v bv24)) bv48 (concat #x000000 v))
38 (define-fun bv48_to_bv24 ((v bv48)) bv24 ((_ extract 23 0) v))
39 (define-fun bv32_to_bv48 ((v bv32)) bv48 (concat #x0000 v))
40 (define-fun bv48_to_bv32 ((v bv48)) bv32 ((_ extract 31 0) v))
41 (define-fun bv16_to_bv32 ((v bv16)) bv32 (concat #x0000 v))
42 (define-fun bv32_to_bv16 ((v bv32)) bv16 ((_ extract 15 0) v))
43 (define-fun bv8_to_bv16 ((v bv8)) bv16 (concat #x00 v))
44 (define-fun bv16_to_bv8 ((v bv16)) bv8 ((_ extract 7 0) v))
45 (define-fun bv4_to_bv8 ((v bv4)) bv8 (concat #x0 v))
46 (define-fun bv8_to_bv4 ((v bv8)) bv4 ((_ extract 3 0) v))
47 (define-fun bv2_to_bv4 ((v bv2)) bv4 (concat #b00 v))
48 (define-fun bv4_to_bv2 ((v bv4)) bv2 ((_ extract 1 0) v))
49 (define-fun bv1_to_bv2 ((v bv1)) bv2 (concat #b0 v))
50 (define-fun bv2_to_bv1 ((v bv2)) bv1 ((_ extract 0 0) v))
51 ; count-leading-zeros
52 (define-fun bv1_clz ((v bv1)) bv1
53 (bvxor #b1 v)
54 )
55 (define-fun bv2_clz ((v bv2)) bv2
56 (let
57 ((shift (ite (bvult #b01 v) #b00 #b01)))
58 (bvadd shift (bv1_to_bv2 (bv1_clz ((_ extract 1 1) (bvshl v shift)))))
59 )
60 )
61 (define-fun bv4_clz ((v bv4)) bv4
62 (let
63 ((shift (ite (bvult #x3 v) #x0 #x2)))
64 (bvadd shift (bv2_to_bv4 (bv2_clz ((_ extract 3 2) (bvshl v shift)))))
65 )
66 )
67 (define-fun bv8_clz ((v bv8)) bv8
68 (let
69 ((shift (ite (bvult #x0F v) #x00 #x04)))
70 (bvadd shift (bv4_to_bv8 (bv4_clz ((_ extract 7 4) (bvshl v shift)))))
71 )
72 )
73 (define-fun bv16_clz ((v bv16)) bv16
74 (let
75 ((shift (ite (bvult #x00FF v) #x0000 #x0008)))
76 (bvadd shift (bv8_to_bv16 (bv8_clz
77 ((_ extract 15 8) (bvshl v shift)))))
78 )
79 )
80 (define-fun bv32_clz ((v bv32)) bv32
81 (let
82 ((shift (ite (bvult #x0000FFFF v) #x00000000 #x00000010)))
83 (bvadd shift (bv16_to_bv32 (bv16_clz
84 ((_ extract 31 16) (bvshl v shift)))))
85 )
86 )
87 (define-fun bv48_clz ((v bv48)) bv48
88 (let
89 ((shift (ite (bvult #x00000000FFFF v) #x000000000000 #x000000000010)))
90 (bvadd shift (bv32_to_bv48 (bv32_clz
91 ((_ extract 47 16) (bvshl v shift)))))
92 )
93 )
94 ; shift right merging shifted out bits into the result's lsb
95 (define-fun bv48_lshr_merging ((v bv48) (shift bv48)) bv48
96 ; did we shift out only zeros?
97 (ite (= v (bvshl (bvlshr v shift) shift))
98 ; yes. no adjustment needed
99 (bvlshr v shift)
100 ; no. set lsb
101 (bvor (bvlshr v shift) #x000000000001)
102 )
103 )
104
105 ; field extraction functions
106 (define-fun f32_sign_field ((v bv32)) bv1 ((_ extract 31 31) v))
107 (define-fun f32_exponent_field ((v bv32)) bv8 ((_ extract 30 23) v))
108 (define-fun f32_mantissa_field ((v bv32)) bv23 ((_ extract 22 0) v))
109 (define-fun f32_mantissa_field_msb ((v bv32)) bv1 ((_ extract 22 22) v))
110 ; construction from fields
111 (define-fun f32_from_fields ((sign_field bv1)
112 (exponent_field bv8)
113 (mantissa_field bv23)) bv32
114 (concat sign_field exponent_field mantissa_field)
115 )
116 ; handy constants
117 (define-fun f32_infinity ((sign_field bv1)) bv32
118 (f32_from_fields sign_field #xFF #b00000000000000000000000)
119 )
120 (define-fun f32_zero ((sign_field bv1)) bv32
121 (f32_from_fields sign_field #x00 #b00000000000000000000000)
122 )
123 ; conversion to quiet NaN
124 (define-fun f32_into_qnan ((v bv32)) bv32
125 (f32_from_fields
126 (f32_sign_field v)
127 #xFF
128 (bvor #b10000000000000000000000 (f32_mantissa_field v))
129 )
130 )
131 ; conversion
132 (define-fun f32_to_fp ((v bv32)) Float32 ((_ to_fp 8 24) v))
133 ; classification
134 (define-fun f32_is_nan ((v bv32)) Bool (fp.isNaN (f32_to_fp v)))
135 (define-fun f32_is_infinite ((v bv32)) Bool (fp.isInfinite (f32_to_fp v)))
136 (define-fun f32_is_normal ((v bv32)) Bool (fp.isNormal (f32_to_fp v)))
137 (define-fun f32_is_subnormal ((v bv32)) Bool (fp.isSubnormal (f32_to_fp v)))
138 (define-fun f32_is_zero ((v bv32)) Bool (fp.isZero (f32_to_fp v)))
139 (define-fun f32_is_qnan ((v bv32)) Bool
140 (and (f32_is_nan v) (= (f32_mantissa_field_msb v) #b1))
141 )
142 ; get mantissa value -- only correct for finite values
143 (define-fun f32_mantissa_value ((v bv32)) bv24
144 (ite (f32_is_subnormal v)
145 (concat #b0 (f32_mantissa_field v))
146 (concat #b1 (f32_mantissa_field v))
147 )
148 )
149 ; f32 field values
150 (define-const f32_exponent_bias f32_sexp_t #x07F)
151 (define-const f32_max_exponent f32_sexp_t #x080)
152 (define-const f32_subnormal_exponent f32_sexp_t #xF82) ; -126
153 (define-fun f32_exponent_value ((v bv32)) f32_sexp_t
154 (ite (= (f32_exponent_field v) #x00)
155 f32_subnormal_exponent
156 (f32_sexp_sub
157 (bv8_to_f32_sexp (f32_exponent_field v))
158 f32_exponent_bias
159 )
160 )
161 )
162 ; f32 mul
163 (define-fun f32_round_product_final_step_rne ((sign bv1)
164 (product bv48)
165 (exponent f32_sexp_t)
166 (exponent_field bv8)) bv32
167 ; if the exponent doesn't overflow
168 (ite (f32_sexp_lt exponent f32_max_exponent)
169 ; if we rounded a subnormal up to a normal
170 (ite (and (= exponent_field #x00) (not (bvult product #x800000000000)))
171 (f32_from_fields
172 sign
173 #x01
174 ((_ extract 46 24) product)
175 )
176 (f32_from_fields
177 sign
178 exponent_field
179 ((_ extract 46 24) product)
180 )
181 )
182 (f32_infinity sign)
183 )
184 )
185 (define-fun f32_round_product_rne ((sign bv1)
186 (product bv48)
187 (exponent f32_sexp_t)
188 (exponent_field bv8)) bv32
189 (let
190 (
191 (half_way (= (bv48_to_bv24 product) #x800000))
192 (is_even (= ((_ extract 24 24) product) #b0))
193 (rounded_up (bvadd product (bv24_to_bv48 #x800000)))
194 )
195 (let
196 (
197 (round_up_overflows (bvult rounded_up product))
198 (do_round_up
199 (ite half_way
200 (not is_even)
201 (bvult #x800000 (bv48_to_bv24 product))
202 )
203 )
204 )
205 (ite do_round_up
206 (ite round_up_overflows
207 (f32_round_product_final_step_rne
208 sign
209 (bvor
210 (bvlshr rounded_up #x000000000001)
211 #x800000000000
212 )
213 (bvadd exponent #x001)
214 (bvadd exponent_field #x01)
215 )
216 (f32_round_product_final_step_rne
217 sign rounded_up exponent exponent_field)
218 )
219 (f32_round_product_final_step_rne
220 sign product exponent exponent_field)
221 )
222 )
223 )
224 )
225 (define-fun f32_mul_nonzero_finite_rne ((a bv32) (b bv32)) bv32
226 (let
227 (
228 (product (bvmul (bv24_to_bv48 (f32_mantissa_value a))
229 (bv24_to_bv48 (f32_mantissa_value b))))
230 (sign (bvxor (f32_sign_field a) (f32_sign_field b)))
231 (exponent (bvadd (f32_exponent_value a) (f32_exponent_value b)))
232 )
233 ; normalize product
234 (let
235 (
236 (norm_product (bvshl product (bv48_clz product)))
237 (norm_exponent
238 (bvadd
239 exponent
240
241 ; compensation for product changing from having two
242 ; integer-part bits to one by normalization
243 #x001
244
245 (bvneg (bv48_to_f32_sexp (bv48_clz product)))
246 )
247 )
248 )
249 (let
250 (
251 ; amount to shift norm_product right to de-normalize again
252 ; for subnormals
253 (subnormal_shift
254 (f32_sexp_sub f32_subnormal_exponent norm_exponent)
255 )
256 )
257 ; if subnormal_shift would not cause the mantissa to overflow
258 (ite (f32_sexp_lt #x000 subnormal_shift)
259 ; subnormals:
260 (f32_round_product_rne
261 sign
262 (bvadd
263 (bv48_lshr_merging
264 norm_product
265 (f32_sexp_to_bv48 subnormal_shift)
266 )
267 )
268 f32_subnormal_exponent
269 #x00
270 )
271 ; normals:
272 (f32_round_product_rne
273 sign
274 norm_product
275 norm_exponent
276 (f32_sexp_to_bv8 (bvadd norm_exponent
277 f32_exponent_bias))
278 )
279 )
280 )
281 )
282 )
283 )
284
285 (define-fun f32_mul_rne ((a bv32) (b bv32)) bv32
286 (ite (f32_is_nan a)
287 (f32_into_qnan a)
288 (ite (f32_is_nan b)
289 (f32_into_qnan b)
290 (ite
291 (or
292 (and (f32_is_zero a) (f32_is_infinite b))
293 (and (f32_is_infinite a) (f32_is_zero b))
294 )
295 #x7FC00000
296 (ite (or (f32_is_infinite a) (f32_is_infinite b))
297 (f32_infinity (bvxor (f32_sign_field a) (f32_sign_field b)))
298 (ite (or (f32_is_zero a) (f32_is_zero b))
299 (f32_zero (bvxor (f32_sign_field a) (f32_sign_field b)))
300 (f32_mul_nonzero_finite_rne a b)
301 )
302 )
303 )
304 )
305 )
306 )
307
308 ; input values in ieee754 f32 format as bit-vectors
309 (declare-const a bv32)
310 (declare-const b bv32)
311 ; product for debugging
312 (declare-const p bv32)
313 (assert (= (f32_to_fp p) (fp.mul RNE (f32_to_fp a) (f32_to_fp b))))
314 ; intermediate values from f32_mul_nonzero_finite_rne for debugging
315 (define-const product bv48 (bvmul (bv24_to_bv48 (f32_mantissa_value a))
316 (bv24_to_bv48 (f32_mantissa_value b))))
317 (define-const sign bv1 (bvxor (f32_sign_field a) (f32_sign_field b)))
318 (define-const exponent f32_sexp_t (bvadd (f32_exponent_value a) (f32_exponent_value b)))
319 (define-const norm_product bv48 (bvshl product (bv48_clz product)))
320 (define-const norm_exponent f32_sexp_t
321 (bvadd
322 exponent
323
324 ; compensation for product changing from having two
325 ; integer-part bits to one by normalization
326 #x001
327
328 (bvneg (bv48_to_f32_sexp (bv48_clz product)))
329 )
330 )
331 (define-const subnormal_shift f32_sexp_t
332 (f32_sexp_sub f32_subnormal_exponent norm_exponent)
333 )
334 ; intermediate values from f32_round_product_rne when the result is subnormal:
335 (define-const product_subnormal bv48
336 (bv48_lshr_merging
337 norm_product
338 (f32_sexp_to_bv48 subnormal_shift)
339 )
340 )
341 (define-const half_way_subnormal Bool
342 (= (bv48_to_bv24 product_subnormal) #x800000))
343 (define-const is_even_subnormal Bool
344 (= ((_ extract 24 24) product_subnormal) #b0))
345 (define-const rounded_up_subnormal bv48
346 (bvadd product_subnormal (bv24_to_bv48 #x800000)))
347 (define-const round_up_overflows_subnormal Bool
348 (bvult rounded_up_subnormal product_subnormal))
349 (define-const do_round_up_subnormal Bool
350 (ite half_way_subnormal
351 (not is_even_subnormal)
352 (bvult #x800000 (bv48_to_bv24 product_subnormal))
353 )
354 )
355 ; intermediate values from f32_round_product_rne when the result is normal:
356 (define-const exponent_field_normal bv8
357 (f32_sexp_to_bv8 (bvadd norm_exponent f32_exponent_bias))
358 )
359 (define-const half_way_normal Bool (= (bv48_to_bv24 norm_product) #x800000))
360 (define-const is_even_normal Bool (= ((_ extract 24 24) norm_product) #b0))
361 (define-const rounded_up_normal bv48
362 (bvadd norm_product (bv24_to_bv48 #x800000))
363 )
364 (define-const round_up_overflows_normal Bool (bvult rounded_up_normal norm_product))
365 (define-const do_round_up_normal Bool
366 (ite half_way_normal
367 (not is_even_normal)
368 (bvult #x800000 (bv48_to_bv24 norm_product))
369 )
370 )
371
372
373
374 ; now look for a case where f32_mul_rne is broke:
375 (assert (not (=
376 (f32_to_fp (f32_mul_rne a b))
377 (fp.mul RNE (f32_to_fp a) (f32_to_fp b))
378 )))
379 ; should return unsat, meaning there aren't any broken cases
380 (echo "should return unsat:")
381 (check-sat)
382 (echo "dumping values in case it returned sat:")
383 (get-value (
384 a
385 b
386 p
387 (f32_to_fp a)
388 (f32_to_fp b)
389 (fp.mul RNE (f32_to_fp a) (f32_to_fp b))
390 (f32_to_fp (f32_mul_rne a b))
391 (f32_mul_nonzero_finite_rne a b)
392 (f32_mantissa_field a)
393 (f32_mantissa_value a)
394 (f32_mantissa_field b)
395 (f32_mantissa_value b)
396 product
397 sign
398 exponent
399 (bv48_clz product)
400 (ite (bvult #x00000000FFFF product) #x000000000000 #x000000000010)
401 norm_product
402 norm_exponent
403 subnormal_shift
404 product_subnormal
405 half_way_subnormal
406 is_even_subnormal
407 rounded_up_subnormal
408 round_up_overflows_subnormal
409 do_round_up_subnormal
410 exponent_field_normal
411 half_way_normal
412 is_even_normal
413 rounded_up_normal
414 round_up_overflows_normal
415 do_round_up_normal
416 ))