Skip to content

Commit ad4dc2d

Browse files
committed
SystemVerilog .*
SystemVerilog 1800-2005 has introduced the .* operator, used for a) wildcard port connections (23.3.2.4), and b) wildcard patterns (12.6). This adds support to the scanner, parser, and type checker.
1 parent e281a3d commit ad4dc2d

File tree

10 files changed

+88
-17
lines changed

10 files changed

+88
-17
lines changed

CHANGELOG

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* Verilog: $onehot and $onehot0 are now elaboration-time constant
66
* SystemVerilog: fix for #-# and #=# for empty matches
77
* SystemVerilog: fix for |-> and |=> for empty matches
8+
* SystemVerilog: support 1800-2005 .*
89
* LTL/SVA to Buechi with --buechi
910
* SMV: abs, bool, count, max, min, toint, word1
1011
* BMC: new encoding for F, avoiding spurious traces
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
wildcard_port_connection1.sv
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
7+
^warning: ignoring
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module M(input a, b);
2+
assert final (a);
3+
assert final (!b);
4+
endmodule
5+
6+
module main;
7+
wire a = 0, b = 1;
8+
M m(.*);
9+
endmodule

src/hw_cbmc_irep_ids.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,8 @@ IREP_ID_ONE(verilog_always)
212212
IREP_ID_ONE(verilog_always_comb)
213213
IREP_ID_ONE(verilog_always_ff)
214214
IREP_ID_ONE(verilog_always_latch)
215-
IREP_ID_ONE(named_port_connection)
215+
IREP_ID_ONE(verilog_named_port_connection)
216+
IREP_ID_ONE(verilog_wildcard_port_connection)
216217
IREP_ID_ONE(verilog_final)
217218
IREP_ID_ONE(initial)
218219
IREP_ID_ONE(verilog_label_statement)

src/verilog/parser.y

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,7 @@ int yyverilogerror(const char *error)
405405
%token TOK_LSQPLUS "[+"
406406
%token TOK_LSQEQUAL "[="
407407
%token TOK_LSQMINUSGREATER "[->"
408+
%token TOK_DOTASTERIC ".*"
408409

409410
/* System Verilog Keywords */
410411
%token TOK_ACCEPT_ON "accept_on"
@@ -3101,9 +3102,10 @@ named_port_connection_brace:
31013102

31023103
named_port_connection:
31033104
'.' port_identifier '(' expression_opt ')'
3104-
{ init($$, ID_named_port_connection);
3105+
{ init($$, ID_verilog_named_port_connection);
31053106
mto($$, $2);
31063107
mto($$, $4); }
3108+
| ".*" { init($$, ID_verilog_wildcard_port_connection); }
31073109
;
31083110

31093111
// System Verilog standard 1800-2017
@@ -3737,6 +3739,26 @@ open_value_range: value_range;
37373739
// System Verilog standard 1800-2017
37383740
// A.6.7.1 Patterns
37393741

3742+
pattern:
3743+
"." variable_identifier
3744+
| ".*"
3745+
| constant_expression
3746+
| "tagged" member_identifier
3747+
| "tagged" member_identifier pattern
3748+
| "'{" pattern_list "}"
3749+
| "'{" member_pattern_list "}"
3750+
;
3751+
3752+
pattern_list:
3753+
pattern
3754+
| pattern_list "," pattern
3755+
;
3756+
3757+
member_pattern_list:
3758+
member_identifier ":" pattern
3759+
| member_pattern_list "," member_identifier ":" pattern
3760+
;
3761+
37403762
assignment_pattern:
37413763
'\'' '{' expression_brace '}'
37423764
{ init($$, ID_verilog_assignment_pattern); swapop($$, $3); }

src/verilog/scanner.l

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,8 @@ void verilog_scanner_init()
273273
"[+" { SYSTEM_VERILOG_OPERATOR(TOK_LSQPLUS, "[+"); }
274274
"[=" { SYSTEM_VERILOG_OPERATOR(TOK_LSQEQUAL, "[="); }
275275
"[->" { SYSTEM_VERILOG_OPERATOR(TOK_LSQMINUSGREATER, "[->"); }
276+
/* port connections, patterns */
277+
".*" { SYSTEM_VERILOG_OPERATOR(TOK_DOTASTERIC, ".*"); }
276278

277279
/* Verilog 1364-1995 keywords */
278280

src/verilog/verilog_expr.h

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -799,7 +799,7 @@ class verilog_inst_baset : public verilog_module_itemt
799799
named_port_connectiont(exprt _port, exprt _value)
800800
: binary_exprt(
801801
std::move(_port),
802-
ID_named_port_connection,
802+
ID_verilog_named_port_connection,
803803
std::move(_value),
804804
typet{})
805805
{
@@ -854,6 +854,19 @@ class verilog_inst_baset : public verilog_module_itemt
854854
return operands();
855855
}
856856

857+
bool positional_connections() const
858+
{
859+
return !named_connections();
860+
}
861+
862+
bool named_connections() const
863+
{
864+
auto &connections = this->connections();
865+
return !connections.empty() &&
866+
(connections.front().id() == ID_verilog_named_port_connection ||
867+
connections.front().id() == ID_verilog_wildcard_port_connection);
868+
}
869+
857870
protected:
858871
using exprt::operands;
859872
};
@@ -877,15 +890,15 @@ class verilog_inst_baset : public verilog_module_itemt
877890
inline const verilog_inst_baset::named_port_connectiont &
878891
to_verilog_named_port_connection(const exprt &expr)
879892
{
880-
PRECONDITION(expr.id() == ID_named_port_connection);
893+
PRECONDITION(expr.id() == ID_verilog_named_port_connection);
881894
verilog_inst_baset::named_port_connectiont::check(expr);
882895
return static_cast<const verilog_inst_baset::named_port_connectiont &>(expr);
883896
}
884897

885898
inline verilog_inst_baset::named_port_connectiont &
886899
to_verilog_named_port_connection(exprt &expr)
887900
{
888-
PRECONDITION(expr.id() == ID_named_port_connection);
901+
PRECONDITION(expr.id() == ID_verilog_named_port_connection);
889902
verilog_inst_baset::named_port_connectiont::check(expr);
890903
return static_cast<verilog_inst_baset::named_port_connectiont &>(expr);
891904
}

src/verilog/verilog_synthesis.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,17 +1376,17 @@ Function: verilog_synthesist::instantiate_ports
13761376

13771377
void verilog_synthesist::instantiate_ports(
13781378
const irep_idt &instance,
1379-
const exprt &inst,
1379+
const verilog_instt::instancet &inst,
13801380
const symbolt &symbol,
13811381
const replace_mapt &replace_map,
13821382
transt &trans)
13831383
{
1384-
if(inst.operands().size()==0)
1384+
if(inst.connections().size() == 0)
13851385
return;
13861386

13871387
// named port connection?
13881388

1389-
if(to_multi_ary_expr(inst).op0().id() == ID_named_port_connection)
1389+
if(inst.named_connections())
13901390
{
13911391
const irept::subt &ports = symbol.type.find(ID_ports).get_sub();
13921392

@@ -1397,7 +1397,7 @@ void verilog_synthesist::instantiate_ports(
13971397
to_symbol_expr((const exprt &)(port)).get_identifier());
13981398

13991399
// no requirement that all ports are connected
1400-
for(const auto &o_it : inst.operands())
1400+
for(const auto &o_it : inst.connections())
14011401
{
14021402
if(o_it.operands().size()==2)
14031403
{
@@ -1418,17 +1418,17 @@ void verilog_synthesist::instantiate_ports(
14181418
{
14191419
const irept::subt &ports = symbol.type.find(ID_ports).get_sub();
14201420

1421-
if(inst.operands().size()!=ports.size())
1421+
if(inst.connections().size() != ports.size())
14221422
{
14231423
throw errort().with_location(inst.source_location())
14241424
<< "wrong number of ports: expected " << ports.size() << " but got "
1425-
<< inst.operands().size();
1425+
<< inst.connections().size();
14261426
}
14271427

14281428
irept::subt::const_iterator p_it=
14291429
ports.begin();
14301430

1431-
for(const auto &o_it : inst.operands())
1431+
for(const auto &o_it : inst.connections())
14321432
{
14331433
DATA_INVARIANT(o_it.is_not_nil(), "all ports must be connected");
14341434

src/verilog/verilog_synthesis_class.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ class verilog_synthesist:
310310

311311
void instantiate_ports(
312312
const irep_idt &instance,
313-
const exprt &inst,
313+
const verilog_instt::instancet &inst,
314314
const symbolt &,
315315
const replace_mapt &,
316316
transt &);

src/verilog/verilog_typecheck.cpp

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,16 +123,32 @@ void verilog_typecheckt::typecheck_port_connections(
123123
}
124124

125125
// named port connection?
126-
127-
if(inst.connections().front().id() == ID_named_port_connection)
126+
if(inst.named_connections())
128127
{
129128
// We don't require that all ports are connected.
130129

131130
std::set<irep_idt> assigned_ports;
131+
bool wildcard = false;
132132

133133
for(auto &connection : inst.connections())
134134
{
135-
if(connection.id() != ID_named_port_connection)
135+
if(connection.id() == ID_verilog_wildcard_port_connection)
136+
{
137+
// .*
138+
if(wildcard)
139+
{
140+
// .* can only be given once
141+
throw errort{}.with_location(connection.source_location())
142+
<< "wildcard connection given more than once";
143+
}
144+
else
145+
{
146+
wildcard = true;
147+
continue;
148+
}
149+
}
150+
151+
if(connection.id() != ID_verilog_named_port_connection)
136152
{
137153
throw errort().with_location(inst.source_location())
138154
<< "expected a named port connection";
@@ -179,7 +195,7 @@ void verilog_typecheckt::typecheck_port_connections(
179195
assigned_ports.insert(identifier);
180196
}
181197
}
182-
else // just a list without names
198+
else // Positional connections, i.e., just a list without port names
183199
{
184200
if(inst.connections().size() != ports.size())
185201
{

0 commit comments

Comments
 (0)