start implementing fp fused-mul-add pipeline
[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 (bv48_lshr_merging
263 norm_product
264 (f32_sexp_to_bv48 subnormal_shift)
265 )
266 f32_subnormal_exponent
267 #x00
268 )
269 ; normals:
270 (f32_round_product_rne
271 sign
272 norm_product
273 norm_exponent
274 (f32_sexp_to_bv8 (bvadd norm_exponent
275 f32_exponent_bias))
276 )
277 )
278 )
279 )
280 )
281 )
282
283 (define-fun f32_mul_rne ((a bv32) (b bv32)) bv32
284 (ite (f32_is_nan a)
285 (f32_into_qnan a)
286 (ite (f32_is_nan b)
287 (f32_into_qnan b)
288 (ite
289 (or
290 (and (f32_is_zero a) (f32_is_infinite b))
291 (and (f32_is_infinite a) (f32_is_zero b))
292 )
293 #x7FC00000
294 (ite (or (f32_is_infinite a) (f32_is_infinite b))
295 (f32_infinity (bvxor (f32_sign_field a) (f32_sign_field b)))
296 (ite (or (f32_is_zero a) (f32_is_zero b))
297 (f32_zero (bvxor (f32_sign_field a) (f32_sign_field b)))
298 (f32_mul_nonzero_finite_rne a b)
299 )
300 )
301 )
302 )
303 )
304 )
305
306 ; input values in ieee754 f32 format as bit-vectors
307 (declare-const a bv32)
308 (declare-const b bv32)
309 ; product for debugging
310 (declare-const p bv32)
311 (assert (= (f32_to_fp p) (fp.mul RNE (f32_to_fp a) (f32_to_fp b))))
312 ; intermediate values from f32_mul_nonzero_finite_rne for debugging
313 (define-const product bv48 (bvmul (bv24_to_bv48 (f32_mantissa_value a))
314 (bv24_to_bv48 (f32_mantissa_value b))))
315 (define-const sign bv1 (bvxor (f32_sign_field a) (f32_sign_field b)))
316 (define-const exponent f32_sexp_t (bvadd (f32_exponent_value a) (f32_exponent_value b)))
317 (define-const norm_product bv48 (bvshl product (bv48_clz product)))
318 (define-const norm_exponent f32_sexp_t
319 (bvadd
320 exponent
321
322 ; compensation for product changing from having two
323 ; integer-part bits to one by normalization
324 #x001
325
326 (bvneg (bv48_to_f32_sexp (bv48_clz product)))
327 )
328 )
329 (define-const subnormal_shift f32_sexp_t
330 (f32_sexp_sub f32_subnormal_exponent norm_exponent)
331 )
332 ; intermediate values from f32_round_product_rne when the result is subnormal:
333 (define-const product_subnormal bv48
334 (bv48_lshr_merging
335 norm_product
336 (f32_sexp_to_bv48 subnormal_shift)
337 )
338 )
339 (define-const half_way_subnormal Bool
340 (= (bv48_to_bv24 product_subnormal) #x800000))
341 (define-const is_even_subnormal Bool
342 (= ((_ extract 24 24) product_subnormal) #b0))
343 (define-const rounded_up_subnormal bv48
344 (bvadd product_subnormal (bv24_to_bv48 #x800000)))
345 (define-const round_up_overflows_subnormal Bool
346 (bvult rounded_up_subnormal product_subnormal))
347 (define-const do_round_up_subnormal Bool
348 (ite half_way_subnormal
349 (not is_even_subnormal)
350 (bvult #x800000 (bv48_to_bv24 product_subnormal))
351 )
352 )
353 ; intermediate values from f32_round_product_rne when the result is normal:
354 (define-const exponent_field_normal bv8
355 (f32_sexp_to_bv8 (bvadd norm_exponent f32_exponent_bias))
356 )
357 (define-const half_way_normal Bool (= (bv48_to_bv24 norm_product) #x800000))
358 (define-const is_even_normal Bool (= ((_ extract 24 24) norm_product) #b0))
359 (define-const rounded_up_normal bv48
360 (bvadd norm_product (bv24_to_bv48 #x800000))
361 )
362 (define-const round_up_overflows_normal Bool (bvult rounded_up_normal norm_product))
363 (define-const do_round_up_normal Bool
364 (ite half_way_normal
365 (not is_even_normal)
366 (bvult #x800000 (bv48_to_bv24 norm_product))
367 )
368 )
369
370
371
372 ; now look for a case where f32_mul_rne is broke:
373 (assert (not (=
374 (f32_to_fp (f32_mul_rne a b))
375 (fp.mul RNE (f32_to_fp a) (f32_to_fp b))
376 )))
377 ; should return unsat, meaning there aren't any broken cases
378 (echo "should return unsat:")
379 (check-sat)
380 (echo "dumping values in case it returned sat:")
381 (get-value (
382 a
383 b
384 p
385 (f32_to_fp a)
386 (f32_to_fp b)
387 (fp.mul RNE (f32_to_fp a) (f32_to_fp b))
388 (f32_to_fp (f32_mul_rne a b))
389 (f32_mul_nonzero_finite_rne a b)
390 (f32_mantissa_field a)
391 (f32_mantissa_value a)
392 (f32_mantissa_field b)
393 (f32_mantissa_value b)
394 product
395 sign
396 exponent
397 (bv48_clz product)
398 (ite (bvult #x00000000FFFF product) #x000000000000 #x000000000010)
399 norm_product
400 norm_exponent
401 subnormal_shift
402 product_subnormal
403 half_way_subnormal
404 is_even_subnormal
405 rounded_up_subnormal
406 round_up_overflows_subnormal
407 do_round_up_subnormal
408 exponent_field_normal
409 half_way_normal
410 is_even_normal
411 rounded_up_normal
412 round_up_overflows_normal
413 do_round_up_normal
414 ))