Skip to content

Commit 91db9b4

Browse files
committed
SystemVerilog: --initial-zero
The SystemVerilog standard specifies that variables are to be zero initialized before simulation begins. Some synthesis tools generate logic to achieve this, whereas others do not. This adds the option --initial-zero to match the synthesis semantics when appropriate.
1 parent aac75f1 commit 91db9b4

14 files changed

+148
-5
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
initial-zero1.sv
3+
--top main --initial-zero --bound 3
4+
^\[main\.p1\] main\.t == 0: PROVED up to bound 3$
5+
^\[main\.p2\] ##1 main\.t == 5: PROVED up to bound 3$
6+
^EXIT=0$
7+
^SIGNAL=0$
8+
--
9+
^warning: ignoring
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
module main(input clk);
2+
3+
reg [7:0] t;
4+
5+
always_ff @(posedge clk) t = 5;
6+
7+
initial p1: assert property (t == 0);
8+
initial p2: assert property (##1 t == 5);
9+
10+
chandle ch;
11+
initial p3: assert property (ch == null);
12+
13+
endmodule

src/ebmc/ebmc_parse_options.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,7 @@ void ebmc_parse_optionst::help()
417417
" {y--systemverilog} \t force SystemVerilog instead of Verilog\n"
418418
" {y--reset} {uexpr} \t set up module reset\n"
419419
" {y--ignore-initial} \t disregard initial blocks\n"
420+
" {y--initial-zero} \t initialize variables with zero\n"
420421
"\n"
421422
"Debugging options:\n"
422423
" {y--preprocess} \t output the preprocessed source file\n"

src/ebmc/ebmc_parse_options.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class ebmc_parse_optionst:public parse_options_baset
3535
"(outfile):(xml-ui)(verbosity):(gui)"
3636
"(json-modules):(json-properties):(json-result):"
3737
"(neural-liveness)(neural-engine):"
38-
"(reset):(ignore-initial)"
38+
"(reset):(ignore-initial)(initial-zero)"
3939
"(version)(verilog-rtl)(verilog-netlist)"
4040
"(compute-interpolant)(interpolation)(interpolation-vmcai)"
4141
"(ic3)(property):(constr)(h)(new-mode)(aiger)"

src/ebmc/transition_system.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,10 @@ static bool parse(
178178
if(cmdline.isset("ignore-initial"))
179179
options.set_option("ignore-initial", true);
180180

181+
// do --initial-zero
182+
if(cmdline.isset("initial-zero"))
183+
options.set_option("initial-zero", true);
184+
181185
language.set_language_options(options, message_handler);
182186

183187
message.status() << "Parsing " << filename << messaget::eom;

src/verilog/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ SRC = aval_bval_encoding.cpp \
77
verilog_elaborate_type.cpp \
88
verilog_expr.cpp \
99
verilog_generate.cpp \
10+
verilog_initializer.cpp \
1011
verilog_interfaces.cpp \
1112
verilog_interpreter.cpp \
1213
verilog_language.cpp \

src/verilog/verilog_expr.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,6 +1073,12 @@ class verilog_initialt:public verilog_statementt
10731073
operands().resize(1);
10741074
}
10751075

1076+
explicit verilog_initialt(verilog_statementt _statement)
1077+
: verilog_statementt(ID_initial)
1078+
{
1079+
add_to_operands(std::move(_statement));
1080+
}
1081+
10761082
verilog_statementt &statement()
10771083
{
10781084
return static_cast<verilog_statementt &>(op0());

src/verilog/verilog_initializer.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*******************************************************************\
2+
3+
Module: Verilog Initializer
4+
5+
Author: Daniel Kroening, [email protected]
6+
7+
\*******************************************************************/
8+
9+
#include "verilog_initializer.h"
10+
11+
#include <util/arith_tools.h>
12+
#include <util/std_expr.h>
13+
14+
std::optional<exprt> verilog_zero_initializer(const typet &type)
15+
{
16+
if(type.id() == ID_signedbv || type.id() == ID_unsignedbv)
17+
return from_integer(0, type);
18+
else if(type.id() == ID_bool)
19+
return false_exprt{};
20+
else if(type.id() == ID_array)
21+
{
22+
auto &array_type = to_array_type(type);
23+
auto zero_element_opt = verilog_zero_initializer(array_type.element_type());
24+
if(!zero_element_opt.has_value())
25+
return {};
26+
else
27+
return array_of_exprt{*zero_element_opt, array_type};
28+
}
29+
else if(type.id() == ID_struct)
30+
{
31+
auto &struct_type = to_struct_type(type);
32+
exprt::operandst member_values;
33+
for(auto &component : struct_type.components())
34+
{
35+
auto member_value_opt = verilog_zero_initializer(component.type());
36+
if(!member_value_opt.has_value())
37+
return {};
38+
member_values.push_back(*member_value_opt);
39+
}
40+
return struct_exprt{std::move(member_values), struct_type};
41+
}
42+
else if(type.id() == ID_verilog_chandle)
43+
{
44+
return constant_exprt{ID_NULL, type};
45+
}
46+
else
47+
return {};
48+
}

src/verilog/verilog_initializer.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*******************************************************************\
2+
3+
Module: Verilog Initializer
4+
5+
Author: Daniel Kroening, [email protected]
6+
7+
\*******************************************************************/
8+
9+
#ifndef CPROVER_VERILOG_INITIALIZER_H
10+
#define CPROVER_VERILOG_INITIALIZER_H
11+
12+
#include <optional>
13+
14+
class exprt;
15+
class typet;
16+
17+
std::optional<exprt> verilog_zero_initializer(const typet &);
18+
19+
#endif

src/verilog/verilog_language.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ void verilog_languaget::set_language_options(
4040
initial_defines = options.get_list_option("defines");
4141
warn_implicit_nets = options.get_bool_option("warn-implicit-nets");
4242
ignore_initial = options.get_bool_option("ignore-initial");
43+
initial_zero = options.get_bool_option("initial-zero");
4344
}
4445

4546
/*******************************************************************\
@@ -196,6 +197,7 @@ bool verilog_languaget::typecheck(
196197
module,
197198
parse_tree.standard,
198199
ignore_initial,
200+
initial_zero,
199201
message_handler))
200202
{
201203
return true;

src/verilog/verilog_language.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ class verilog_languaget:public languaget
9595
bool vl2smv_extensions = false;
9696
bool warn_implicit_nets = false;
9797
bool ignore_initial = false;
98+
bool initial_zero = false;
9899
std::list<std::string> include_paths;
99100
std::list<std::string> initial_defines;
100101
verilog_parse_treet parse_tree;

src/verilog/verilog_synthesis.cpp

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Author: Daniel Kroening, [email protected]
2323
#include "expr2verilog.h"
2424
#include "sva_expr.h"
2525
#include "verilog_expr.h"
26+
#include "verilog_initializer.h"
2627
#include "verilog_lowering.h"
2728
#include "verilog_typecheck_expr.h"
2829

@@ -1463,6 +1464,7 @@ void verilog_synthesist::synth_module_instance(
14631464
module_identifier,
14641465
standard,
14651466
ignore_initial,
1467+
initial_zero,
14661468
get_message_handler());
14671469

14681470
for(auto &instance : statement.instances())
@@ -1933,6 +1935,8 @@ void verilog_synthesist::synth_decl(const verilog_declt &statement) {
19331935
{
19341936
DATA_INVARIANT(declarator.id() == ID_declarator, "must have declarator");
19351937

1938+
auto lhs = declarator.symbol_expr();
1939+
19361940
// This is reg x = ... or wire x = ...
19371941
if(declarator.has_value())
19381942
{
@@ -1941,9 +1945,7 @@ void verilog_synthesist::synth_decl(const verilog_declt &statement) {
19411945
construct=constructt::INITIAL;
19421946
event_guard=event_guardt::NONE;
19431947

1944-
auto lhs = declarator.symbol_expr();
19451948
auto rhs = declarator.value();
1946-
19471949
const symbolt &symbol = ns.lookup(lhs);
19481950

19491951
if(symbol.is_state_var)
@@ -1964,6 +1966,26 @@ void verilog_synthesist::synth_decl(const verilog_declt &statement) {
19641966
synth_continuous_assign(assign);
19651967
}
19661968
}
1969+
else if(initial_zero)
1970+
{
1971+
const symbolt &symbol = ns.lookup(lhs);
1972+
1973+
if(symbol.is_state_var)
1974+
{
1975+
// much like: initial LHS=0;
1976+
auto rhs_opt = verilog_zero_initializer(lhs.type());
1977+
if(!rhs_opt.has_value())
1978+
{
1979+
throw errort().with_location(declarator.source_location())
1980+
<< "cannot zero-initialize `" << to_string(lhs) << "'";
1981+
}
1982+
verilog_initialt initial{verilog_blocking_assignt{lhs, *rhs_opt}};
1983+
initial.statement().add_source_location() =
1984+
declarator.source_location();
1985+
initial.add_source_location() = declarator.source_location();
1986+
synth_initial(initial);
1987+
}
1988+
}
19671989
}
19681990
}
19691991

@@ -3724,11 +3746,18 @@ bool verilog_synthesis(
37243746
const irep_idt &module,
37253747
verilog_standardt standard,
37263748
bool ignore_initial,
3749+
bool initial_zero,
37273750
message_handlert &message_handler)
37283751
{
37293752
const namespacet ns(symbol_table);
37303753
verilog_synthesist verilog_synthesis(
3731-
standard, ignore_initial, ns, symbol_table, module, message_handler);
3754+
standard,
3755+
ignore_initial,
3756+
initial_zero,
3757+
ns,
3758+
symbol_table,
3759+
module,
3760+
message_handler);
37323761
return verilog_synthesis.typecheck_main();
37333762
}
37343763

@@ -3757,7 +3786,13 @@ bool verilog_synthesis(
37573786
message_handler.get_message_count(messaget::M_ERROR);
37583787

37593788
verilog_synthesist verilog_synthesis(
3760-
standard, false, ns, symbol_table, module_identifier, message_handler);
3789+
standard,
3790+
false,
3791+
false,
3792+
ns,
3793+
symbol_table,
3794+
module_identifier,
3795+
message_handler);
37613796

37623797
try
37633798
{

src/verilog/verilog_synthesis.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ bool verilog_synthesis(
2020
const irep_idt &module,
2121
verilog_standardt,
2222
bool ignore_initial,
23+
bool initial_zero,
2324
message_handlert &);
2425

2526
bool verilog_synthesis(

src/verilog/verilog_synthesis_class.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,15 @@ class verilog_synthesist:
4343
verilog_synthesist(
4444
verilog_standardt _standard,
4545
bool _ignore_initial,
46+
bool _initial_zero,
4647
const namespacet &_ns,
4748
symbol_table_baset &_symbol_table,
4849
const irep_idt &_module,
4950
message_handlert &_message_handler)
5051
: verilog_typecheck_baset(_standard, _ns, _message_handler),
5152
verilog_symbol_tablet(_symbol_table),
5253
ignore_initial(_ignore_initial),
54+
initial_zero(_initial_zero),
5355
value_map(NULL),
5456
module(_module),
5557
temporary_counter(0)
@@ -70,6 +72,7 @@ class verilog_synthesist:
7072

7173
protected:
7274
bool ignore_initial;
75+
bool initial_zero;
7376

7477
[[nodiscard]] exprt synth_expr_rec(exprt expr, symbol_statet symbol_state);
7578

0 commit comments

Comments
 (0)