Skip to content

Commit fea0d46

Browse files
committed
Verilog: module port declarations with default value
This fixes the grammar to allow ANSI module port declarations that have a default value. This adds support for module ports (ANSI and non-ANSI) that have a default value to the type checker.
1 parent a578ca9 commit fea0d46

File tree

8 files changed

+81
-20
lines changed

8 files changed

+81
-20
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
port_with_value2.sv
3+
4+
^file .* line 2: output ports must not have a default value$
5+
^EXIT=2$
6+
^SIGNAL=0$
7+
--
8+
^warning: ignoring
9+
--
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// output ports must not have a default value
2+
module M(output [31:0] o = 4567);
3+
4+
endmodule
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
port_with_value3.sv
3+
4+
^file .* line 2: expected constant expression, but got `M\.a'$
5+
^EXIT=2$
6+
^SIGNAL=0$
7+
--
8+
^warning: ignoring
9+
--
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// default values for inputs must be constants
2+
module M(input a, input b = a);
3+
4+
endmodule

src/verilog/parser.y

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -899,14 +899,15 @@ ansi_port_declaration_brace:
899899

900900
// append to last one -- required to make
901901
// the grammar LR1
902-
| ansi_port_declaration_brace ',' port_identifier
902+
| ansi_port_declaration_brace ',' port_identifier ansi_port_initializer_opt
903903
{ $$=$1;
904904
exprt decl(ID_decl);
905905
decl.add_to_operands(std::move(stack_expr($3)));
906906
// grab the type and class from previous!
907907
const irept &prev=stack_expr($$).get_sub().back();
908908
decl.set(ID_type, prev.find(ID_type));
909909
decl.set(ID_class, prev.find(ID_class));
910+
decl.set(ID_value, stack_expr($4));
910911
stack_expr($$).move_to_sub(decl);
911912
}
912913
;
@@ -935,6 +936,7 @@ ansi_port_declaration:
935936
// and the unpacked_array_type goes onto the declarator.
936937
stack_expr($$).type() = std::move(stack_expr($1).type());
937938
addswap($2, ID_type, $3);
939+
stack_expr($2).set(ID_value, stack_expr($4));
938940
mto($$, $2); /* declarator */ }
939941
| variable_port_header port_identifier unpacked_dimension_brace ansi_port_initializer_opt
940942
{ init($$, ID_decl);
@@ -946,6 +948,7 @@ ansi_port_declaration:
946948
// and the unpacked_array_type goes onto the declarator.
947949
stack_expr($$).type() = std::move(stack_expr($1).type());
948950
addswap($2, ID_type, $3);
951+
stack_expr($2).set(ID_value, stack_expr($4));
949952
mto($$, $2); /* declarator */ }
950953
;
951954

src/verilog/verilog_elaborate.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,21 @@ void verilog_typecheckt::collect_port_symbols(const verilog_declt &decl)
6262
new_symbol.base_name = base_name;
6363
new_symbol.pretty_name = strip_verilog_prefix(new_symbol.name);
6464

65+
// When using ANSI style, input ports may have an
66+
// elaboration-time constant default value
67+
auto &default_value = declarator.value();
68+
if(default_value.is_not_nil())
69+
{
70+
if(new_symbol.is_output)
71+
throw errort{}.with_location(default_value.source_location())
72+
<< "output ports must not have a default value";
73+
74+
auto value = default_value;
75+
convert_expr(value);
76+
auto elaborated_value = elaborate_constant_expression_check(value);
77+
new_symbol.value = elaborated_value;
78+
}
79+
6580
add_symbol(std::move(new_symbol));
6681
}
6782
}

src/verilog/verilog_synthesis.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1444,6 +1444,35 @@ void verilog_synthesist::instantiate_ports(
14441444
is_output, port, value, replace_map, inst.source_location(), trans);
14451445
}
14461446
}
1447+
1448+
std::set<irep_idt> connected_ports;
1449+
1450+
for(const auto &connection : inst.connections())
1451+
{
1452+
auto &named_connection = to_verilog_named_port_connection(connection);
1453+
connected_ports.insert(
1454+
to_symbol_expr(named_connection.port()).get_identifier());
1455+
}
1456+
1457+
// unconnected inputs may be given a default value
1458+
for(auto &port : ports)
1459+
if(port.get_bool(ID_input))
1460+
{
1461+
auto &port_symbol_expr = to_symbol_expr((const exprt &)(port));
1462+
auto identifier = port_symbol_expr.get_identifier();
1463+
if(connected_ports.find(identifier) == connected_ports.end())
1464+
{
1465+
auto &port_symbol = ns.lookup(port_symbol_expr);
1466+
if(port_symbol.value.is_not_nil())
1467+
instantiate_port(
1468+
false,
1469+
port_symbol_expr,
1470+
symbol.value,
1471+
replace_map,
1472+
inst.source_location(),
1473+
trans);
1474+
}
1475+
}
14471476
}
14481477
else // just a list without names
14491478
{

src/verilog/verilog_typecheck.cpp

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -103,28 +103,16 @@ void verilog_typecheckt::typecheck_port_connections(
103103

104104
const irept::subt &ports=symbol.type.find(ID_ports).get_sub();
105105

106-
// no arguments is one argument that is nil
107-
if(
108-
ports.size() == 0 && inst.connections().size() == 1 &&
109-
inst.connections().front().is_nil())
106+
// no connection is one connection that is nil
107+
if(inst.connections().size() == 1 && inst.connections().front().is_nil())
110108
{
111109
inst.connections().clear();
112110
}
113111

114-
if(inst.connections().empty())
115-
{
116-
if(!ports.empty())
117-
{
118-
throw errort().with_location(inst.source_location())
119-
<< "module does not have ports";
120-
}
121-
122-
return;
123-
}
124-
125112
// named port connection?
126-
127-
if(inst.connections().front().id() == ID_named_port_connection)
113+
if(
114+
inst.connections().empty() ||
115+
inst.connections().front().id() == ID_named_port_connection)
128116
{
129117
// We don't require that all ports are connected.
130118

@@ -184,8 +172,8 @@ void verilog_typecheckt::typecheck_port_connections(
184172
if(inst.connections().size() != ports.size())
185173
{
186174
throw errort().with_location(inst.source_location())
187-
<< "wrong number of arguments: expected " << ports.size() << " but got "
188-
<< inst.connections().size();
175+
<< "wrong number of port connections: expected " << ports.size()
176+
<< " but got " << inst.connections().size();
189177
}
190178

191179
irept::subt::const_iterator p_it=

0 commit comments

Comments
 (0)