Skip to content

Commit efc46fe

Browse files
committed
Verilog: cleanup downwards type propagation
This cleans up verilog_typecheck_exprt::downwards_type_progatation to handle all the cases in 1800-2017 11.8.2.
1 parent fb1f9f4 commit efc46fe

File tree

1 file changed

+88
-113
lines changed

1 file changed

+88
-113
lines changed

src/verilog/verilog_typecheck_expr.cpp

Lines changed: 88 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,39 @@ void verilog_typecheck_exprt::propagate_type(
222222

223223
/*******************************************************************\
224224
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+
225258
Function: verilog_typecheck_exprt::downwards_type_progatation
226259
227260
Inputs:
@@ -241,95 +274,70 @@ void verilog_typecheck_exprt::downwards_type_propagation(
241274

242275
// Any context-determined operand of an operator shall be the
243276
// 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.
247279

248280
if(expr.type() == type)
249281
return;
250282

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)
255284
{
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+
}
301288

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+
}
310323

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.
324325

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};
330340
}
331-
332-
implicit_typecast(expr, type);
333341
}
334342

335343
/*******************************************************************\
@@ -2538,39 +2546,6 @@ void verilog_typecheck_exprt::tc_binary_expr(
25382546

25392547
/*******************************************************************\
25402548
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-
25742549
Function: verilog_typecheck_exprt::convert_relation
25752550
25762551
Inputs:

0 commit comments

Comments
 (0)