@@ -222,6 +222,39 @@ void verilog_typecheck_exprt::propagate_type(
222
222
223
223
/* ******************************************************************\
224
224
225
+ Function: zero_extend
226
+
227
+ Inputs:
228
+
229
+ Outputs:
230
+
231
+ Purpose:
232
+
233
+ \*******************************************************************/
234
+
235
+ static exprt zero_extend (const exprt &expr, const typet &type)
236
+ {
237
+ auto old_width = expr.type ().id () == ID_bool ? 1
238
+ : expr.type ().id () == ID_integer
239
+ ? 32
240
+ : to_bitvector_type (expr.type ()).get_width ();
241
+
242
+ // first make unsigned
243
+ typet tmp_type;
244
+
245
+ if (type.id () == ID_unsignedbv)
246
+ tmp_type = unsignedbv_typet{old_width};
247
+ else if (type.id () == ID_verilog_unsignedbv)
248
+ tmp_type = verilog_unsignedbv_typet{old_width};
249
+ else
250
+ PRECONDITION (false );
251
+
252
+ return typecast_exprt::conditional_cast (
253
+ typecast_exprt::conditional_cast (expr, tmp_type), type);
254
+ }
255
+
256
+ /* ******************************************************************\
257
+
225
258
Function: verilog_typecheck_exprt::downwards_type_progatation
226
259
227
260
Inputs:
@@ -241,95 +274,70 @@ void verilog_typecheck_exprt::downwards_type_propagation(
241
274
242
275
// Any context-determined operand of an operator shall be the
243
276
// same type and size as the result of the operator.
244
- // Exceptions:
245
- // * result type real -- just cast
246
- // * relational operators are always 1 bit unsigned
277
+ // As an exception, if the result type is real, the operands
278
+ // are just casted.
247
279
248
280
if (expr.type () == type)
249
281
return ;
250
282
251
- vtypet vt_from = vtypet (expr.type ());
252
- vtypet vt_to = vtypet (type);
253
-
254
- if (!vt_from.is_other () && !vt_to.is_other () && expr.has_operands ())
283
+ if (type.id () == ID_verilog_real || type.id () == ID_verilog_shortreal)
255
284
{
256
- // arithmetic
257
-
258
- if (
259
- expr.id () == ID_plus || expr.id () == ID_minus || expr.id () == ID_mult ||
260
- expr.id () == ID_div || expr.id () == ID_unary_minus ||
261
- expr.id () == ID_unary_plus)
262
- {
263
- if (type.id () != ID_bool)
264
- {
265
- Forall_operands (it, expr)
266
- propagate_type (*it, type);
267
-
268
- expr.type () = type;
269
-
270
- return ;
271
- }
272
- }
273
- else if (
274
- expr.id () == ID_bitand || expr.id () == ID_bitor ||
275
- expr.id () == ID_bitnand || expr.id () == ID_bitnor ||
276
- expr.id () == ID_bitxor || expr.id () == ID_bitxnor ||
277
- expr.id () == ID_bitnot)
278
- {
279
- Forall_operands (it, expr)
280
- propagate_type (*it, type);
281
-
282
- expr.type () = type;
283
-
284
- if (type.id () == ID_bool)
285
- {
286
- if (expr.id () == ID_bitand)
287
- expr.id (ID_and);
288
- else if (expr.id () == ID_bitor)
289
- expr.id (ID_or);
290
- else if (expr.id () == ID_bitnand)
291
- expr.id (ID_nand);
292
- else if (expr.id () == ID_bitnor)
293
- expr.id (ID_nor);
294
- else if (expr.id () == ID_bitxor)
295
- expr.id (ID_xor);
296
- else if (expr.id () == ID_bitxnor)
297
- expr.id (ID_xnor);
298
- else if (expr.id () == ID_bitnot)
299
- expr.id (ID_not);
300
- }
285
+ expr = typecast_exprt{expr, type};
286
+ return ;
287
+ }
301
288
302
- return ;
303
- }
304
- else if (expr.id () == ID_if)
305
- {
306
- if (expr.operands ().size () == 3 )
307
- {
308
- propagate_type (to_if_expr (expr).true_case (), type);
309
- propagate_type (to_if_expr (expr).false_case (), type);
289
+ // expressions with context-determined width, following
290
+ // 1800-2017 Table 11-21
291
+ if (
292
+ expr.id () == ID_plus || expr.id () == ID_minus || expr.id () == ID_mult ||
293
+ expr.id () == ID_div || expr.id () == ID_mod || expr.id () == ID_bitand ||
294
+ expr.id () == ID_bitor || expr.id () == ID_bitxor ||
295
+ expr.id () == ID_bitxnor || expr.id () == ID_unary_plus ||
296
+ expr.id () == ID_unary_minus || expr.id () == ID_bitnot)
297
+ {
298
+ // All operands are context-determined.
299
+ for (auto &op : expr.operands ())
300
+ downwards_type_propagation (op, type);
301
+ expr.type () = type;
302
+ return ;
303
+ }
304
+ else if (
305
+ expr.id () == ID_shl || expr.id () == ID_ashr || expr.id () == ID_lshr ||
306
+ expr.id () == ID_power)
307
+ {
308
+ // The LHS is context-determined, the RHS is self-determined
309
+ auto &binary_expr = to_binary_expr (expr);
310
+ downwards_type_propagation (binary_expr.lhs (), type);
311
+ expr.type () = type;
312
+ return ;
313
+ }
314
+ else if (expr.id () == ID_if)
315
+ {
316
+ // The first operand is self-determined, the others are context-determined
317
+ auto &if_expr = to_if_expr (expr);
318
+ downwards_type_propagation (if_expr.op1 (), type);
319
+ downwards_type_propagation (if_expr.op2 (), type);
320
+ expr.type () = type;
321
+ return ;
322
+ }
310
323
311
- expr.type () = type;
312
- return ;
313
- }
314
- }
315
- else if (expr.id () == ID_shl) // does not work with shr
316
- {
317
- // does not work with boolean
318
- if (type.id () != ID_bool)
319
- {
320
- if (expr.operands ().size () == 2 )
321
- {
322
- propagate_type (to_binary_expr (expr).op0 (), type);
323
- // not applicable to second operand
324
+ // Just cast the expression, leave any operands as they are.
324
325
325
- expr.type () = type;
326
- return ;
327
- }
328
- }
329
- }
326
+ if (
327
+ (expr.type ().id () == ID_signedbv ||
328
+ expr.type ().id () == ID_verilog_signedbv) &&
329
+ (type.id () == ID_unsignedbv || type.id () == ID_verilog_unsignedbv) &&
330
+ get_width (expr.type ()) < get_width (type))
331
+ {
332
+ // "If the operand shall be extended, then it shall be sign-extended only
333
+ // if the propagated type is signed."
334
+ // A typecast from signed to a larger unsigned would sign extend.
335
+ expr = zero_extend (expr, type);
336
+ }
337
+ else
338
+ {
339
+ expr = typecast_exprt{expr, type};
330
340
}
331
-
332
- implicit_typecast (expr, type);
333
341
}
334
342
335
343
/* ******************************************************************\
@@ -2538,39 +2546,6 @@ void verilog_typecheck_exprt::tc_binary_expr(
2538
2546
2539
2547
/* ******************************************************************\
2540
2548
2541
- Function: zero_extend
2542
-
2543
- Inputs:
2544
-
2545
- Outputs:
2546
-
2547
- Purpose:
2548
-
2549
- \*******************************************************************/
2550
-
2551
- static exprt zero_extend (const exprt &expr, const typet &type)
2552
- {
2553
- auto old_width = expr.type ().id () == ID_bool ? 1
2554
- : expr.type ().id () == ID_integer
2555
- ? 32
2556
- : to_bitvector_type (expr.type ()).get_width ();
2557
-
2558
- // first make unsigned
2559
- typet tmp_type;
2560
-
2561
- if (type.id () == ID_unsignedbv)
2562
- tmp_type = unsignedbv_typet{old_width};
2563
- else if (type.id () == ID_verilog_unsignedbv)
2564
- tmp_type = verilog_unsignedbv_typet{old_width};
2565
- else
2566
- PRECONDITION (false );
2567
-
2568
- return typecast_exprt::conditional_cast (
2569
- typecast_exprt::conditional_cast (expr, tmp_type), type);
2570
- }
2571
-
2572
- /* ******************************************************************\
2573
-
2574
2549
Function: verilog_typecheck_exprt::convert_relation
2575
2550
2576
2551
Inputs:
0 commit comments