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