Skip to content

Commit a8a7e0b

Browse files
committed
Verilog: separate path for downwards type progatation
This splits up the logic for downwards type progatation used for expression evaluation and for the RHS of assignments, given that they differ in behavior.
1 parent 342a2c7 commit a8a7e0b

File tree

2 files changed

+127
-5
lines changed

2 files changed

+127
-5
lines changed

src/verilog/verilog_typecheck_expr.cpp

Lines changed: 126 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,118 @@ void verilog_typecheck_exprt::propagate_type(
222222

223223
/*******************************************************************\
224224
225+
Function: verilog_typecheck_exprt::downwards_type_progatation
226+
227+
Inputs:
228+
229+
Outputs:
230+
231+
Purpose:
232+
233+
\*******************************************************************/
234+
235+
void verilog_typecheck_exprt::downwards_type_propagation(
236+
exprt &expr,
237+
const typet &type)
238+
{
239+
// This implements the step "propagate the type and size down to
240+
// the context-determined operands" in 1800-2017 11.8.2
241+
242+
// Any context-determined operand of an operator shall be the
243+
// 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
247+
248+
if(expr.type() == type)
249+
return;
250+
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())
255+
{
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+
}
301+
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);
310+
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+
325+
expr.type() = type;
326+
return;
327+
}
328+
}
329+
}
330+
}
331+
332+
implicit_typecast(expr, type);
333+
}
334+
335+
/*******************************************************************\
336+
225337
Function: verilog_typecheck_exprt::no_bool_ops
226338
227339
Inputs:
@@ -2396,12 +2508,20 @@ void verilog_typecheck_exprt::tc_binary_expr(
23962508
const exprt &expr,
23972509
exprt &op0, exprt &op1)
23982510
{
2511+
// Follows 1800-2017 11.8.2.
2512+
2513+
// First get the self-determined type and size of both operands
23992514
union_decay(op0);
24002515
union_decay(op1);
24012516

2402-
// follows 1800-2017 11.8.2
2403-
const typet new_type =
2404-
max_type(enum_decay(op0.type()), enum_decay(op1.type()));
2517+
enum_decay(op0);
2518+
enum_decay(op1);
2519+
2520+
struct_decay(op0);
2521+
struct_decay(op1);
2522+
2523+
// Now get the max
2524+
const typet new_type = max_type(op0.type(), op1.type());
24052525

24062526
if(new_type.is_nil())
24072527
{
@@ -2411,8 +2531,9 @@ void verilog_typecheck_exprt::tc_binary_expr(
24112531
<< " " << to_string(op1.type());
24122532
}
24132533

2414-
propagate_type(op0, new_type);
2415-
propagate_type(op1, new_type);
2534+
// Now do downwards propagation
2535+
downwards_type_propagation(op0, new_type);
2536+
downwards_type_propagation(op1, new_type);
24162537
}
24172538

24182539
/*******************************************************************\

src/verilog/verilog_typecheck_expr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ class verilog_typecheck_exprt:public verilog_typecheck_baset
6666
void make_boolean(exprt &expr);
6767

6868
void propagate_type(exprt &expr, const typet &type);
69+
void downwards_type_propagation(exprt &, const typet &);
6970

7071
[[nodiscard]] typet elaborate_type(const typet &);
7172
typet elaborate_package_scope_typedef(const verilog_package_scope_typet &);

0 commit comments

Comments
 (0)