Skip to content

Commit 820b050

Browse files
committed
Verilog: add checks for operators that require integral types
This adds checks to the typechecker to enforce that the operands have an integral type.
1 parent 51fa81e commit 820b050

13 files changed

+128
-41
lines changed
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
KNOWNBUG
1+
CORE
22
concatenation5.v
33
--bound 0
4-
^EXIT=0$
4+
^file .* line 4: operand 1.1 must be integral$
5+
^EXIT=2$
56
^SIGNAL=0$
67
--
78
^warning: ignoring
89
--
9-
This should be errored.
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
KNOWNBUG
1+
CORE
22
equality3.v
33
--bound 0
4-
^EXIT=0$
4+
^EXIT=2$
55
^SIGNAL=0$
66
--
77
^warning: ignoring
88
--
9-
This should be errored.
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
KNOWNBUG
1+
CORE
22
mod2.v
33
--bound 0
4-
^EXIT=0$
4+
^file .* line 4: operand 1\.1 must be integral$
5+
^EXIT=2$
56
^SIGNAL=0$
67
--
78
^warning: ignoring
89
--
9-
This should be errored.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
reduction2.v
3+
--bound 0
4+
^file .* line 4: operand 1\.1 must be integral$
5+
^EXIT=2$
6+
^SIGNAL=0$
7+
--
8+
^warning: ignoring
9+
--
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module main;
2+
3+
// reduction operators only take integral types
4+
wire x = &1.1;
5+
6+
endmodule
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
replication3.v
3+
--bound 0
4+
^file .* line 3: operand 1\.1 must be integral$
5+
^EXIT=2$
6+
^SIGNAL=0$
7+
--
8+
^warning: ignoring
9+
--
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module main;
2+
3+
wire [31:0] x = {4{1.1}};
4+
5+
endmodule
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
KNOWNBUG
1+
CORE
22
shr2.v
33
--bound 0
4-
^EXIT=0$
4+
^file .* line 4: operand 1\.1 must be integral$
5+
^EXIT=2$
56
^SIGNAL=0$
67
--
78
^warning: ignoring
89
--
9-
This should be errored.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
streaming_concatenation2.sv
3+
--bound 0
4+
^file .* line 4: operand 1\.1 must be integral$
5+
^EXIT=2$
6+
^SIGNAL=0$
7+
--
8+
^warning: ignoring
9+
--
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module main;
2+
3+
// operand must be integral
4+
wire x = {<<{1.1}};
5+
6+
endmodule
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
KNOWNBUG
1+
CORE
22
wildcard_equality2.v
33
--bound 0
4-
^EXIT=0$
4+
^file .* line 4: operand 1\.1 must be integral$
5+
^EXIT=2$
56
^SIGNAL=0$
67
--
78
^warning: ignoring
89
--
9-
This should be errored.

src/verilog/verilog_typecheck_expr.cpp

Lines changed: 69 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,37 @@ void verilog_typecheck_exprt::no_bool_ops(exprt &expr)
226226

227227
/*******************************************************************\
228228
229+
Function: verilog_typecheck_exprt::must_be_integral
230+
231+
Inputs:
232+
233+
Outputs:
234+
235+
Purpose:
236+
237+
\*******************************************************************/
238+
239+
void verilog_typecheck_exprt::must_be_integral(const exprt &expr)
240+
{
241+
// Throw an error if the given expression doesn't have an integral type.
242+
const auto &type = expr.type();
243+
if(type.id() == ID_bool)
244+
{
245+
// ok as is
246+
}
247+
else if(
248+
type.id() == ID_unsignedbv || type.id() == ID_signedbv ||
249+
type.id() == ID_verilog_unsignedbv || type.id() == ID_verilog_signedbv)
250+
{
251+
// ok as is
252+
}
253+
else
254+
throw errort().with_location(expr.source_location())
255+
<< "operand " << to_string(expr) << " must be integral";
256+
}
257+
258+
/*******************************************************************\
259+
229260
Function: verilog_typecheck_exprt::convert_expr_rec
230261
231262
Inputs:
@@ -263,22 +294,14 @@ exprt verilog_typecheck_exprt::convert_expr_rec(exprt expr)
263294
Forall_operands(it, expr)
264295
{
265296
convert_expr(*it);
266-
297+
must_be_integral(*it);
298+
267299
const typet &type=it->type();
268300

269-
if(type.id()==ID_array)
270-
{
271-
throw errort().with_location(it->source_location())
272-
<< "array type not allowed in concatenation";
273-
}
274-
else if(type.id() == ID_integer)
301+
if(type.id() == ID_verilog_signedbv || type.id() == ID_verilog_unsignedbv)
275302
{
276-
throw errort().with_location(it->source_location())
277-
<< "integer type not allowed in concatenation";
278-
}
279-
else if(type.id()==ID_verilog_signedbv ||
280-
type.id()==ID_verilog_unsignedbv)
281303
has_verilogbv=true;
304+
}
282305

283306
width+=get_width(*it);
284307
}
@@ -2640,10 +2663,13 @@ exprt verilog_typecheck_exprt::convert_unary_expr(unary_exprt expr)
26402663
{
26412664
// these may produce an 'x' if the operand is a verilog_bv
26422665
convert_expr(expr.op());
2666+
must_be_integral(expr.op());
26432667

26442668
if (expr.op().type().id() == ID_verilog_signedbv ||
26452669
expr.op().type().id() == ID_verilog_unsignedbv)
2670+
{
26462671
expr.type()=verilog_unsignedbv_typet(1);
2672+
}
26472673
else
26482674
expr.type()=bool_typet();
26492675
}
@@ -2676,6 +2702,7 @@ exprt verilog_typecheck_exprt::convert_unary_expr(unary_exprt expr)
26762702
// slice_size is defaulted to 1
26772703
PRECONDITION(expr.op().operands().size() == 1);
26782704
convert_expr(expr.op().operands()[0]);
2705+
must_be_integral(expr.op().operands()[0]);
26792706
expr.type() = expr.op().operands()[0].type();
26802707
return std::move(expr);
26812708
}
@@ -2817,12 +2844,7 @@ exprt verilog_typecheck_exprt::convert_replication_expr(replication_exprt expr)
28172844
exprt &op1=expr.op1();
28182845

28192846
convert_expr(op1);
2820-
2821-
if(op1.type().id()==ID_array)
2822-
{
2823-
throw errort().with_location(op1.source_location())
2824-
<< "array type not allowed in replication";
2825-
}
2847+
must_be_integral(op1);
28262848

28272849
if(op1.type().id()==ID_bool)
28282850
op1 = typecast_exprt{op1, unsignedbv_typet{1}};
@@ -3020,11 +3042,14 @@ exprt verilog_typecheck_exprt::convert_binary_expr(binary_exprt expr)
30203042
// a proper equality is performed.
30213043
expr.type()=bool_typet();
30223044

3023-
Forall_operands(it, expr)
3024-
convert_expr(*it);
3025-
3045+
convert_expr(expr.lhs());
3046+
convert_expr(expr.rhs());
30263047
typecheck_relation(expr);
30273048

3049+
// integral operands only
3050+
must_be_integral(expr.lhs());
3051+
must_be_integral(expr.rhs());
3052+
30283053
return std::move(expr);
30293054
}
30303055
else if(expr.id()==ID_lt || expr.id()==ID_gt ||
@@ -3049,8 +3074,10 @@ exprt verilog_typecheck_exprt::convert_binary_expr(binary_exprt expr)
30493074
// This is the >>> expression, which turns into ID_lshr or ID_ashr
30503075
// depending on type of first operand.
30513076

3052-
convert_expr(expr.op0());
3053-
convert_expr(expr.op1());
3077+
convert_expr(expr.lhs());
3078+
convert_expr(expr.rhs());
3079+
must_be_integral(expr.lhs());
3080+
must_be_integral(expr.rhs());
30543081
no_bool_ops(expr);
30553082

30563083
const typet &op0_type = expr.op0().type();
@@ -3074,14 +3101,16 @@ exprt verilog_typecheck_exprt::convert_binary_expr(binary_exprt expr)
30743101
else if(expr.id()==ID_lshr)
30753102
{
30763103
// logical right shift >>
3077-
convert_expr(expr.op0());
3078-
convert_expr(expr.op1());
3104+
convert_expr(expr.lhs());
3105+
convert_expr(expr.rhs());
3106+
must_be_integral(expr.lhs());
3107+
must_be_integral(expr.rhs());
30793108
no_bool_ops(expr);
30803109
expr.type()=expr.op0().type();
30813110

30823111
return std::move(expr);
30833112
}
3084-
else if(expr.id()==ID_div || expr.id()==ID_mod)
3113+
else if(expr.id() == ID_div)
30853114
{
30863115
Forall_operands(it, expr)
30873116
convert_expr(*it);
@@ -3093,6 +3122,20 @@ exprt verilog_typecheck_exprt::convert_binary_expr(binary_exprt expr)
30933122

30943123
return std::move(expr);
30953124
}
3125+
else if(expr.id() == ID_mod)
3126+
{
3127+
convert_expr(expr.lhs());
3128+
convert_expr(expr.rhs());
3129+
must_be_integral(expr.lhs());
3130+
must_be_integral(expr.rhs());
3131+
3132+
tc_binary_expr(expr);
3133+
no_bool_ops(expr);
3134+
3135+
expr.type() = expr.lhs().type();
3136+
3137+
return std::move(expr);
3138+
}
30963139
else if(expr.id()==ID_hierarchical_identifier)
30973140
{
30983141
return convert_hierarchical_identifier(

src/verilog/verilog_typecheck_expr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ class verilog_typecheck_exprt:public verilog_typecheck_baset
187187
void tc_binary_expr(const exprt &expr, exprt &op0, exprt &op1);
188188
void typecheck_relation(binary_exprt &);
189189
void no_bool_ops(exprt &);
190+
void must_be_integral(const exprt &);
190191

191192
// SVA
192193
void convert_sva(exprt &expr)

0 commit comments

Comments
 (0)