Skip to content

Commit 28be476

Browse files
authored
Merge pull request #315 from diffblue/fix-functioncall5
do not add constraints for assignments to function-local variables
2 parents b175768 + 9628033 commit 28be476

File tree

6 files changed

+97
-28
lines changed

6 files changed

+97
-28
lines changed

regression/verilog/functioncall/functioncall5.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
KNOWNBUG
1+
CORE
22
functioncall5.v
33
--module main --bound 0
44
^EXIT=0$

regression/verilog/functioncall/functioncall5.v

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ module main(input clk);
1717

1818
reg my_reg;
1919

20-
always @(posedge clk)
20+
always @(posedge clk) begin
2121
my_reg = isUpper(my_wire1);
22+
assert (my_reg == my_wire2);
23+
end
2224

2325
endmodule
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
functioncall7.v
3+
--module main --bound 0
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
7+
^warning: ignoring
8+
--
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
module main(input clk);
2+
3+
function negate;
4+
input in;
5+
begin
6+
negate = ~in;
7+
end
8+
endfunction
9+
10+
// same function used twice
11+
12+
wire my_wire0 = negate(0);
13+
wire my_wire1 = negate(1);
14+
15+
always assert p0: (my_wire0 == 1);
16+
always assert p1: (my_wire1 == 0);
17+
18+
endmodule

src/verilog/verilog_synthesis.cpp

Lines changed: 59 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,7 @@ exprt verilog_synthesist::synth_expr(exprt expr, symbol_statet symbol_state)
7676
}
7777
else if(expr.id()==ID_function_call)
7878
{
79-
expand_function_call(to_function_call_expr(expr));
80-
return expr;
79+
return expand_function_call(to_function_call_expr(expr));
8180
}
8281
else if(expr.id()==ID_hierarchical_identifier)
8382
{
@@ -112,6 +111,32 @@ exprt verilog_synthesist::synth_expr(exprt expr, symbol_statet symbol_state)
112111

113112
/*******************************************************************\
114113
114+
Function: verilog_synthesist::function_locality
115+
116+
Inputs:
117+
118+
Outputs:
119+
120+
Purpose:
121+
122+
\*******************************************************************/
123+
124+
void verilog_synthesist::function_locality(const symbolt &function_symbol)
125+
{
126+
// Find all local symbols of the function, mark their
127+
// assignments as local.
128+
auto prefix = id2string(function_symbol.name) + '.';
129+
for(auto &symbol : symbol_table.symbols)
130+
{
131+
if(irep_idt(symbol.first).starts_with(prefix))
132+
{
133+
assignments[symbol.first].is_cycle_local = true;
134+
}
135+
}
136+
}
137+
138+
/*******************************************************************\
139+
115140
Function: verilog_synthesist::expand_function_call
116141
117142
Inputs:
@@ -122,7 +147,7 @@ Function: verilog_synthesist::expand_function_call
122147
123148
\*******************************************************************/
124149

125-
void verilog_synthesist::expand_function_call(function_call_exprt &call)
150+
exprt verilog_synthesist::expand_function_call(const function_call_exprt &call)
126151
{
127152
// Is it a 'system function call'?
128153
if(call.is_system_function_call())
@@ -138,8 +163,7 @@ void verilog_synthesist::expand_function_call(function_call_exprt &call)
138163
throw 0;
139164
}
140165

141-
call.swap(result);
142-
return;
166+
return result;
143167
}
144168

145169
// check some restrictions
@@ -184,7 +208,10 @@ void verilog_synthesist::expand_function_call(function_call_exprt &call)
184208
error() << "wrong number of arguments" << eom;
185209
throw 0;
186210
}
187-
211+
212+
// preserve locality of function-local variables
213+
function_locality(symbol);
214+
188215
// do assignments to function parameters
189216
for(unsigned i=0; i<parameters.size(); i++)
190217
{
@@ -197,15 +224,16 @@ void verilog_synthesist::expand_function_call(function_call_exprt &call)
197224
}
198225

199226
synth_statement(to_verilog_statement(symbol.value));
200-
227+
201228
// replace function call by return value symbol
202229
const symbolt &return_symbol=
203230
ns.lookup(id2string(symbol.name)+"."+
204231
id2string(symbol.base_name));
205232

206-
exprt return_value=return_symbol.symbol_expr();
233+
// get the current value
234+
auto result = synth_expr(return_symbol.symbol_expr(), symbol_statet::CURRENT);
207235

208-
call.swap(return_value);
236+
return result;
209237
}
210238

211239
/*******************************************************************\
@@ -362,22 +390,27 @@ void verilog_synthesist::assignment_rec(
362390

363391
assignmentt &assignment=assignments[symbol.name];
364392

365-
if(assignment.type==event_guardt::NONE)
366-
assignment.type=new_type;
367-
else if(assignment.type!=new_type)
393+
if(assignment.is_cycle_local)
368394
{
369-
error().source_location=lhs.source_location();
370-
error() << "conflicting assignment types for `"
371-
<< symbol.base_name
372-
<< "' (new: "
373-
<< as_string(new_type) << ", old: "
374-
<< as_string(assignment.type) << ")" << eom;
375-
throw 0;
376395
}
377-
378-
membert member;
379-
assignment_member_rec(lhs, member,
380-
(construct==constructt::INITIAL)?assignment.init:assignment.next);
396+
else
397+
{
398+
if(assignment.type == event_guardt::NONE)
399+
assignment.type = new_type;
400+
else if(assignment.type != new_type)
401+
{
402+
throw errort().with_location(lhs.source_location())
403+
<< "conflicting assignment types for `" << symbol.base_name
404+
<< "' (new: " << as_string(new_type)
405+
<< ", old: " << as_string(assignment.type) << ")";
406+
}
407+
408+
membert member;
409+
assignment_member_rec(
410+
lhs,
411+
member,
412+
(construct == constructt::INITIAL) ? assignment.init : assignment.next);
413+
}
381414
}
382415

383416
{
@@ -2764,6 +2797,9 @@ void verilog_synthesist::synth_assignments(transt &trans)
27642797
{
27652798
assignmentt &assignment=assignments[symbol.name];
27662799

2800+
if(assignment.is_cycle_local)
2801+
continue; // ignore
2802+
27672803
if(assignment.type==event_guardt::COMBINATIONAL)
27682804
{
27692805
warning().source_location = symbol.location;

src/verilog/verilog_synthesis_class.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ class verilog_synthesist:
111111

112112
// only relevant for 'next'
113113
event_guardt type;
114+
bool is_cycle_local = false;
114115

115116
assignmentt():type(event_guardt::NONE)
116117
{
@@ -277,8 +278,8 @@ class verilog_synthesist:
277278
class hierarchical_identifier_exprt &expr,
278279
symbol_statet symbol_state);
279280

280-
void expand_function_call(class function_call_exprt &call);
281-
281+
exprt expand_function_call(const class function_call_exprt &call);
282+
282283
typedef std::map<irep_idt, exprt> replace_mapt;
283284

284285
void instantiate_ports(
@@ -299,7 +300,11 @@ class verilog_synthesist:
299300
transt &);
300301

301302
void replace_by_wire(exprt &expr, const symbolt &base);
302-
303+
304+
// Mark the local variables of a function or task
305+
// as cycle local.
306+
void function_locality(const symbolt &);
307+
303308
unsigned temporary_counter;
304309
};
305310

0 commit comments

Comments
 (0)