Skip to content

Commit 9bf2bac

Browse files
authored
Merge pull request #1065 from diffblue/nexttime-to-ltl
translate `s_always` and ranged `always` into LTL
2 parents 2e7a406 + f6dd221 commit 9bf2bac

File tree

5 files changed

+133
-0
lines changed

5 files changed

+133
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
always_with_range1.sv
3+
--smv-netlist
4+
^LTLSPEC node275 & X node363 & X X node451 .*
5+
^LTLSPEC G node1155$
6+
^LTLSPEC node1243 & X node1331 & X X node1419 .*
7+
^LTLSPEC G \(\!node2066 \| X node2097\)$
8+
^EXIT=0$
9+
^SIGNAL=0$
10+
--
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
module main;
2+
3+
reg [31:0] x;
4+
wire clk;
5+
6+
initial x=0;
7+
8+
always @(posedge clk)
9+
x<=x+1;
10+
11+
// holds owing to the range
12+
initial p0: assert property (always [0:9] x<10);
13+
14+
// unbounded, fails
15+
initial p1: assert property (always [0:$] x<10);
16+
17+
// strong variant
18+
initial p2: assert property (s_always [0:9] x<10);
19+
20+
// nested
21+
p3: assert property (always (x==1 implies always [1:1] x==2));
22+
23+
endmodule
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
nexttime1.sv
3+
--smv-netlist
4+
^CTLSPEC node65$
5+
^LTLSPEC X node72$
6+
^LTLSPEC X X X X X X X X node79$
7+
^EXIT=0$
8+
^SIGNAL=0$
9+
--
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
module main(input clk);
2+
3+
// count up from 0 to 10
4+
reg [7:0] counter;
5+
6+
initial counter = 0;
7+
8+
always @(posedge clk)
9+
if(counter == 10)
10+
counter = 0;
11+
else
12+
counter = counter + 1;
13+
14+
// expected to pass
15+
initial p1: assert property (s_nexttime[0] counter == 0);
16+
17+
// expected to pass
18+
initial p2: assert property (s_nexttime[1] counter == 1);
19+
20+
// expected to pass
21+
initial p3: assert property (nexttime[8] counter == 8);
22+
23+
endmodule

src/temporal-logic/temporal_logic.cpp

+68
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Author: Daniel Kroening, [email protected]
88

99
#include "temporal_logic.h"
1010

11+
#include <util/arith_tools.h>
1112
#include <util/expr_util.h>
1213

1314
#include <verilog/sva_expr.h>
@@ -211,6 +212,15 @@ std::optional<exprt> LTL_to_CTL(exprt expr)
211212
return {};
212213
}
213214

215+
static exprt n_Xes(mp_integer n, exprt op)
216+
{
217+
PRECONDITION(n >= 0);
218+
if(n == 0)
219+
return op;
220+
else
221+
return n_Xes(n - 1, X_exprt{std::move(op)});
222+
}
223+
214224
std::optional<exprt> SVA_to_LTL(exprt expr)
215225
{
216226
// Some SVA is directly mappable to LTL
@@ -222,6 +232,64 @@ std::optional<exprt> SVA_to_LTL(exprt expr)
222232
else
223233
return {};
224234
}
235+
else if(expr.id() == ID_sva_ranged_always)
236+
{
237+
auto &ranged_always = to_sva_ranged_always_expr(expr);
238+
auto rec = SVA_to_LTL(ranged_always.op());
239+
if(rec.has_value())
240+
{
241+
// always [l:u] op ---> X ... X (op ∧ X op ∧ ... ∧ X ... X op)
242+
auto lower_int = numeric_cast_v<mp_integer>(ranged_always.lower());
243+
244+
// Is there an upper end of the range?
245+
if(ranged_always.upper().is_constant())
246+
{
247+
// upper end set
248+
auto upper_int =
249+
numeric_cast_v<mp_integer>(to_constant_expr(ranged_always.upper()));
250+
PRECONDITION(upper_int >= lower_int);
251+
auto diff = upper_int - lower_int;
252+
253+
exprt::operandst conjuncts;
254+
255+
for(auto i = 0; i <= diff; i++)
256+
conjuncts.push_back(n_Xes(i, rec.value()));
257+
258+
return n_Xes(lower_int, conjunction(conjuncts));
259+
}
260+
else if(ranged_always.upper().id() == ID_infinity)
261+
{
262+
// always [l:$] op ---> X ... X G op
263+
return n_Xes(lower_int, G_exprt{rec.value()});
264+
}
265+
else
266+
PRECONDITION(false);
267+
}
268+
else
269+
return {};
270+
}
271+
else if(expr.id() == ID_sva_s_always)
272+
{
273+
auto &ranged_always = to_sva_s_always_expr(expr);
274+
auto rec = SVA_to_LTL(ranged_always.op());
275+
if(rec.has_value())
276+
{
277+
// s_always [l:u] op ---> X ... X (op ∧ X op ∧ ... ∧ X ... X op)
278+
auto lower_int = numeric_cast_v<mp_integer>(ranged_always.lower());
279+
auto upper_int = numeric_cast_v<mp_integer>(ranged_always.upper());
280+
PRECONDITION(upper_int >= lower_int);
281+
auto diff = upper_int - lower_int;
282+
283+
exprt::operandst conjuncts;
284+
285+
for(auto i = 0; i <= diff; i++)
286+
conjuncts.push_back(n_Xes(i, rec.value()));
287+
288+
return n_Xes(lower_int, conjunction(conjuncts));
289+
}
290+
else
291+
return {};
292+
}
225293
else if(expr.id() == ID_sva_s_eventually)
226294
{
227295
auto rec = SVA_to_LTL(to_sva_s_eventually_expr(expr).op());

0 commit comments

Comments
 (0)