Skip to content

Commit aeecd2e

Browse files
authored
Merge pull request #753 from diffblue/parameters10
Verilog: reject non-constant parameters
2 parents 8bbc75e + 995f6b4 commit aeecd2e

File tree

6 files changed

+68
-16
lines changed

6 files changed

+68
-16
lines changed

regression/verilog/enums/enum5.desc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
enum5.sv
3+
--bound 0
4+
^file .* line 6: expected constant expression, but got `main\.some_wire'$
5+
^EXIT=2$
6+
^SIGNAL=0$
7+
--

regression/verilog/enums/enum5.sv

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module main;
2+
3+
wire some_wire;
4+
5+
// some_wire is not a constant
6+
typedef enum bit [7:0] { A = some_wire } enum_t;
7+
8+
endmodule

src/verilog/verilog_elaborate.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,8 @@ void verilog_typecheckt::collect_symbols(const verilog_lett &let)
614614
new_symbol.base_name = base_name;
615615
new_symbol.pretty_name = strip_verilog_prefix(new_symbol.name);
616616

617+
let_symbols.insert(new_symbol.name);
618+
617619
add_symbol(std::move(new_symbol));
618620
}
619621

@@ -929,12 +931,17 @@ void verilog_typecheckt::elaborate_symbol_rec(irep_idt identifier)
929931
// mark as "elaborating" to detect cycles
930932
symbol.type.id(ID_elaborating);
931933

934+
bool is_let = let_symbols.find(symbol.name) != let_symbols.end();
935+
932936
// Is the type derived from the value (e.g., parameters)?
933937
if(to_type_with_subtype(symbol.type).subtype().id() == ID_derive_from_value)
934938
{
935939
// First elaborate the value, possibly recursively.
936940
convert_expr(symbol.value);
937-
symbol.value = elaborate_constant_expression(symbol.value);
941+
942+
if(!is_let)
943+
symbol.value = elaborate_constant_expression_check(symbol.value);
944+
938945
symbol.type = symbol.value.type();
939946
}
940947
else
@@ -948,7 +955,9 @@ void verilog_typecheckt::elaborate_symbol_rec(irep_idt identifier)
948955
if(symbol.value.is_not_nil())
949956
{
950957
convert_expr(symbol.value);
951-
symbol.value = elaborate_constant_expression(symbol.value);
958+
959+
if(!is_let)
960+
symbol.value = elaborate_constant_expression_check(symbol.value);
952961

953962
// Cast to the given type.
954963
propagate_type(symbol.value, symbol.type);

src/verilog/verilog_typecheck.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ class verilog_typecheckt:
9797
collect_symbols(const typet &, const verilog_parameter_declt::declaratort &);
9898
void collect_port_symbols(const verilog_declt &);
9999
std::vector<irep_idt> symbols_added;
100+
std::set<irep_idt> let_symbols;
100101

101102
// instances
102103
irep_idt parameterize_module(

src/verilog/verilog_typecheck_expr.cpp

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -844,13 +844,8 @@ exprt verilog_typecheck_exprt::convert_system_function(
844844

845845
if(arguments.size() >= 2)
846846
{
847-
auto tmp = elaborate_constant_expression(arguments[1]);
848-
if(!tmp.is_constant())
849-
{
850-
throw errort().with_location(arguments[1].source_location())
851-
<< "expected elaboration-time constant, but got `" << to_string(tmp)
852-
<< '\'';
853-
}
847+
auto tmp = elaborate_constant_expression_check(arguments[1]);
848+
arguments[1] = tmp;
854849
}
855850

856851
expr.type() = arguments.front().type();
@@ -1454,12 +1449,12 @@ verilog_typecheck_exprt::convert_integer_constant_expression(exprt expr)
14541449
// this could be large
14551450
propagate_type(expr, integer_typet());
14561451

1457-
exprt tmp = elaborate_constant_expression(expr);
1452+
exprt tmp = elaborate_constant_expression_check(expr);
14581453

1459-
if(!tmp.is_constant())
1454+
if(tmp.id() == ID_infinity)
14601455
{
14611456
throw errort().with_location(source_location)
1462-
<< "expected constant expression, but got `" << to_string(tmp) << '\'';
1457+
<< "expected integer constant, but got $";
14631458
}
14641459

14651460
const auto &tmp_constant = to_constant_expr(tmp);
@@ -1515,6 +1510,9 @@ exprt verilog_typecheck_exprt::elaborate_constant_expression(exprt expr)
15151510

15161511
if(symbol.is_macro)
15171512
{
1513+
// Elaborate recursively
1514+
elaborate_symbol_rec(symbol.name);
1515+
15181516
// A parameter or local parameter. Replace by its value.
15191517
return symbol.value;
15201518
}
@@ -1524,12 +1522,12 @@ exprt verilog_typecheck_exprt::elaborate_constant_expression(exprt expr)
15241522
#if 0
15251523
status() << "READ " << identifier << " = " << to_string(value) << eom;
15261524
#endif
1527-
1525+
15281526
if(value.is_not_nil())
15291527
{
1530-
source_locationt source_location=expr.source_location();
1531-
exprt tmp=value;
1532-
tmp.add_source_location()=source_location;
1528+
source_locationt source_location = expr.source_location();
1529+
exprt tmp = value;
1530+
tmp.add_source_location() = source_location;
15331531
return tmp;
15341532
}
15351533
else
@@ -1671,6 +1669,34 @@ exprt verilog_typecheck_exprt::elaborate_constant_expression(exprt expr)
16711669

16721670
/*******************************************************************\
16731671
1672+
Function: verilog_typecheck_exprt::elaborate_constant_expression_check
1673+
1674+
Inputs:
1675+
1676+
Outputs:
1677+
1678+
Purpose:
1679+
1680+
\*******************************************************************/
1681+
1682+
exprt verilog_typecheck_exprt::elaborate_constant_expression_check(exprt expr)
1683+
{
1684+
source_locationt source_location = expr.find_source_location();
1685+
1686+
exprt tmp = elaborate_constant_expression(std::move(expr));
1687+
1688+
// $ counts as a constant
1689+
if(!tmp.is_constant() && tmp.id() != ID_infinity)
1690+
{
1691+
throw errort().with_location(source_location)
1692+
<< "expected constant expression, but got `" << to_string(tmp) << '\'';
1693+
}
1694+
1695+
return tmp;
1696+
}
1697+
1698+
/*******************************************************************\
1699+
16741700
Function: verilog_typecheck_exprt::elaborate_constant_system_function_call
16751701
16761702
Inputs:

src/verilog/verilog_typecheck_expr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ class verilog_typecheck_exprt:public verilog_typecheck_baset
148148
bool is_constant_expression(const exprt &, mp_integer &value);
149149
std::optional<mp_integer> is_constant_integer_post_convert(const exprt &);
150150
exprt elaborate_constant_expression(exprt);
151+
exprt elaborate_constant_expression_check(exprt);
151152

152153
// To be overridden, requires a Verilog interpreter.
153154
virtual exprt elaborate_constant_function_call(const function_call_exprt &)

0 commit comments

Comments
 (0)