Skip to content

Commit da710d1

Browse files
authored
Merge pull request #493 from diffblue/verilog_past
SystemVerilog: $past
2 parents 55379a4 + c18a712 commit da710d1

File tree

8 files changed

+146
-1
lines changed

8 files changed

+146
-1
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
past1.sv
3+
--bound 10
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
7+
^warning: ignoring
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
module main(input clk);
2+
3+
reg [31:0] counter = 0;
4+
5+
always @(posedge clk)
6+
counter++;
7+
8+
initial p0: assert property (##0 $past(counter, 0) == 0);
9+
initial p1: assert property (##1 $past(counter, 1) == 0);
10+
initial p2: assert property (##2 $past(counter, 2) == 0);
11+
initial p3: assert property (##3 $past(counter, 3) == 0);
12+
initial p4: assert property (##4 $past(counter, 4) == 0);
13+
14+
initial q0: assert property (##0 $past(counter, 1) == 0);
15+
initial q1: assert property (##1 $past(counter, 1) == 0);
16+
initial q2: assert property (##2 $past(counter, 1) == 1);
17+
initial q3: assert property (##3 $past(counter, 1) == 2);
18+
initial q4: assert property (##4 $past(counter, 1) == 3);
19+
20+
endmodule

src/hw_cbmc_irep_ids.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ IREP_ID_ONE(verilog_priority)
4949
IREP_ID_ONE(verilog_non_indexed_part_select)
5050
IREP_ID_ONE(verilog_indexed_part_select_plus)
5151
IREP_ID_ONE(verilog_indexed_part_select_minus)
52+
IREP_ID_ONE(verilog_past)
5253
IREP_ID_ONE(chandle)
5354
IREP_ID_ONE(event)
5455
IREP_ID_ONE(reg)

src/trans-word-level/instantiate_word_level.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Author: Daniel Kroening, [email protected]
1212

1313
#include <temporal-logic/temporal_expr.h>
1414
#include <verilog/sva_expr.h>
15+
#include <verilog/verilog_expr.h>
1516

1617
#include "property.h"
1718

@@ -91,6 +92,27 @@ class wl_instantiatet
9192

9293
/*******************************************************************\
9394
95+
Function: default_value
96+
97+
Inputs:
98+
99+
Outputs:
100+
101+
Purpose:
102+
103+
\*******************************************************************/
104+
105+
static exprt default_value(const typet &type)
106+
{
107+
auto zero = from_integer(0, type);
108+
if(zero.is_nil())
109+
throw "failed to create $past default value";
110+
else
111+
return std::move(zero);
112+
}
113+
114+
/*******************************************************************\
115+
94116
Function: wl_instantiatet::instantiate_rec
95117
96118
Inputs:
@@ -303,6 +325,24 @@ exprt wl_instantiatet::instantiate_rec(exprt expr, const mp_integer &t) const
303325

304326
return instantiate_rec(tmp, t);
305327
}
328+
else if(expr.id() == ID_verilog_past)
329+
{
330+
auto &verilog_past = to_verilog_past_expr(expr);
331+
332+
mp_integer ticks;
333+
if(to_integer_non_constant(verilog_past.ticks(), ticks))
334+
throw "failed to convert $past number of ticks";
335+
336+
if(ticks > t)
337+
{
338+
// return the 'default value' for the type
339+
return default_value(verilog_past.type());
340+
}
341+
else
342+
{
343+
return instantiate_rec(verilog_past.what(), t - ticks);
344+
}
345+
}
306346
else
307347
{
308348
for(auto &op : expr.operands())

src/verilog/expr2verilog.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1061,7 +1061,10 @@ std::string expr2verilogt::convert(
10611061

10621062
else if(src.id()==ID_constraint_select_one)
10631063
return convert_function("$ND", src);
1064-
1064+
1065+
else if(src.id() == ID_verilog_past)
1066+
return convert_function("$past", src);
1067+
10651068
else if(src.id()==ID_onehot)
10661069
return convert_function("$onehot", src);
10671070

src/verilog/verilog_expr.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1946,4 +1946,47 @@ to_verilog_implicit_typecast_expr(exprt &expr)
19461946
return static_cast<verilog_implicit_typecast_exprt &>(expr);
19471947
}
19481948

1949+
class verilog_past_exprt : public binary_exprt
1950+
{
1951+
public:
1952+
verilog_past_exprt(exprt __what, exprt __ticks)
1953+
: binary_exprt(__what, ID_verilog_past, std::move(__ticks), __what.type())
1954+
{
1955+
}
1956+
1957+
const exprt &what() const
1958+
{
1959+
return op0();
1960+
}
1961+
1962+
exprt &what()
1963+
{
1964+
return op0();
1965+
}
1966+
1967+
const exprt &ticks() const
1968+
{
1969+
return op1();
1970+
}
1971+
1972+
exprt &ticks()
1973+
{
1974+
return op1();
1975+
}
1976+
};
1977+
1978+
inline const verilog_past_exprt &to_verilog_past_expr(const exprt &expr)
1979+
{
1980+
PRECONDITION(expr.id() == ID_verilog_past);
1981+
verilog_past_exprt::check(expr);
1982+
return static_cast<const verilog_past_exprt &>(expr);
1983+
}
1984+
1985+
inline verilog_past_exprt &to_verilog_past_expr(exprt &expr)
1986+
{
1987+
PRECONDITION(expr.id() == ID_verilog_past);
1988+
verilog_past_exprt::check(expr);
1989+
return static_cast<verilog_past_exprt &>(expr);
1990+
}
1991+
19491992
#endif

src/verilog/verilog_synthesis.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,14 @@ exprt verilog_synthesist::expand_function_call(const function_call_exprt &call)
184184
select_one.set(ID_identifier, identifier);
185185
return select_one.with_source_location(call);
186186
}
187+
else if(identifier == "$past")
188+
{
189+
auto what = call.arguments()[0];
190+
auto ticks = call.arguments().size() < 2
191+
? from_integer(1, integer_typet())
192+
: call.arguments()[1];
193+
return verilog_past_exprt{what, ticks}.with_source_location(call);
194+
}
187195
else
188196
{
189197
// Attempt to constant fold.

src/verilog/verilog_typecheck_expr.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,29 @@ exprt verilog_typecheck_exprt::convert_system_function(
653653

654654
return std::move(expr);
655655
}
656+
else if(identifier == "$past")
657+
{
658+
if(arguments.size() == 0 || arguments.size() >= 4)
659+
{
660+
throw errort().with_location(expr.source_location())
661+
<< "$past takes one to four arguments";
662+
}
663+
664+
if(arguments.size() >= 2)
665+
{
666+
auto tmp = elaborate_constant_expression(arguments[1]);
667+
if(!tmp.is_constant())
668+
{
669+
throw errort().with_location(arguments[1].source_location())
670+
<< "expected elaboration-time constant, but got `" << to_string(tmp)
671+
<< '\'';
672+
}
673+
}
674+
675+
expr.type() = arguments.front().type();
676+
677+
return std::move(expr);
678+
}
656679
else
657680
{
658681
throw errort().with_location(expr.function().source_location())

0 commit comments

Comments
 (0)