Skip to content

Commit 44a1b82

Browse files
authored
Merge pull request #517 from diffblue/random-initial
random traces: set random initial state
2 parents de8cc6a + 287969f commit 44a1b82

File tree

3 files changed

+166
-19
lines changed

3 files changed

+166
-19
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
initial_state1.v
3+
--random-trace --trace-steps 1 --numbered-trace --random-seed 0
4+
^m\.x@0 = 'hBF9059EA$
5+
^m\.y@0 = 123$
6+
^m\.x@1 = 'hBF9059EB$
7+
^m\.y@1 = 124$
8+
^EXIT=0$
9+
^SIGNAL=0$
10+
--
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
module m(input clk);
2+
3+
// x is unconstrained
4+
reg [31:0] x;
5+
always @(posedge clk) x = x + 1;
6+
7+
// y is constrained
8+
reg [31:0] y;
9+
always @(posedge clk) y = y + 1;
10+
initial y = 123;
11+
12+
endmodule

src/ebmc/random_traces.cpp

Lines changed: 144 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Author: Daniel Kroening, [email protected]
1212
#include <util/bitvector_types.h>
1313
#include <util/console.h>
1414
#include <util/expr_util.h>
15+
#include <util/find_symbols.h>
1516
#include <util/string2int.h>
1617
#include <util/unicode.h>
1718

@@ -59,21 +60,35 @@ class random_tracest
5960
const namespacet ns;
6061
messaget message;
6162

62-
using inputst = std::vector<symbol_exprt>;
63+
using symbolst = std::vector<symbol_exprt>;
6364

6465
std::vector<exprt> random_input_constraints(
6566
decision_proceduret &,
66-
const inputst &,
67+
const symbolst &inputs,
6768
size_t number_of_timeframes);
6869

70+
std::vector<exprt> random_initial_state_constraints(
71+
decision_proceduret &,
72+
const symbolst &state_variables);
73+
74+
static std::vector<exprt>
75+
merge_constraints(const std::vector<exprt> &a, const std::vector<exprt> &b)
76+
{
77+
std::vector<exprt> result;
78+
result.reserve(a.size() + b.size());
79+
result.insert(result.end(), a.begin(), a.end());
80+
result.insert(result.end(), b.begin(), b.end());
81+
return result;
82+
}
83+
6984
constant_exprt random_value(const typet &);
7085

71-
inputst inputs() const;
86+
symbolst inputs() const;
87+
symbolst state_variables() const;
88+
symbolst remove_constrained(const symbolst &) const;
7289

73-
void freeze_inputs(
74-
const inputst &,
75-
std::size_t number_of_timeframes,
76-
boolbvt &) const;
90+
void
91+
freeze(const symbolst &, std::size_t number_of_timeframes, boolbvt &) const;
7792

7893
// Random number generator. These are fully specified in
7994
// the C++ standard, and produce the same values on compliant
@@ -261,10 +276,15 @@ int random_trace(const cmdlinet &cmdline, message_handlert &message_handler)
261276

262277
auto consumer = [&](trans_tracet trace) -> void {
263278
namespacet ns(transition_system.symbol_table);
264-
if(cmdline.isset("random-waveform"))
279+
if(cmdline.isset("random-waveform") || cmdline.isset("waveform"))
265280
{
266281
show_waveform(trace, ns);
267282
}
283+
else if(cmdline.isset("numbered-trace"))
284+
{
285+
messaget message(message_handler);
286+
show_trans_trace_numbered(trace, message, ns, consolet::out());
287+
}
268288
else // default
269289
{
270290
messaget message(message_handler);
@@ -406,9 +426,9 @@ Function: random_tracest::inputs
406426
407427
\*******************************************************************/
408428

409-
random_tracest::inputst random_tracest::inputs() const
429+
random_tracest::symbolst random_tracest::inputs() const
410430
{
411-
inputst inputs;
431+
symbolst inputs;
412432

413433
const auto &module_symbol = *transition_system.main_symbol;
414434

@@ -435,7 +455,7 @@ random_tracest::inputst random_tracest::inputs() const
435455

436456
/*******************************************************************\
437457
438-
Function: random_tracest::freeze_inputs
458+
Function: random_tracest::state_variables
439459
440460
Inputs:
441461
@@ -445,17 +465,81 @@ Function: random_tracest::freeze_inputs
445465
446466
\*******************************************************************/
447467

448-
void random_tracest::freeze_inputs(
449-
const inputst &inputs,
468+
random_tracest::symbolst random_tracest::state_variables() const
469+
{
470+
symbolst state_variables;
471+
472+
const auto &module_symbol = *transition_system.main_symbol;
473+
const namespacet ns(transition_system.symbol_table);
474+
475+
const auto &symbol_module_map =
476+
transition_system.symbol_table.symbol_module_map;
477+
auto lower = symbol_module_map.lower_bound(module_symbol.name);
478+
auto upper = symbol_module_map.upper_bound(module_symbol.name);
479+
480+
for(auto it = lower; it != upper; it++)
481+
{
482+
const symbolt &symbol = ns.lookup(it->second);
483+
484+
if(symbol.is_state_var)
485+
state_variables.push_back(symbol.symbol_expr());
486+
}
487+
488+
return state_variables;
489+
}
490+
491+
/*******************************************************************\
492+
493+
Function: random_tracest::remove_constrained
494+
495+
Inputs:
496+
497+
Outputs:
498+
499+
Purpose:
500+
501+
\*******************************************************************/
502+
503+
random_tracest::symbolst
504+
random_tracest::remove_constrained(const symbolst &symbols) const
505+
{
506+
auto constrained_symbols = find_symbols(transition_system.trans_expr.init());
507+
508+
symbolst result;
509+
result.reserve(symbols.size());
510+
511+
// this is symbols setminus constrained_symbols
512+
for(auto &symbol : symbols)
513+
if(constrained_symbols.find(symbol) == constrained_symbols.end())
514+
result.push_back(symbol);
515+
516+
return result;
517+
}
518+
519+
/*******************************************************************\
520+
521+
Function: random_tracest::freeze
522+
523+
Inputs:
524+
525+
Outputs:
526+
527+
Purpose:
528+
529+
\*******************************************************************/
530+
531+
void random_tracest::freeze(
532+
const symbolst &symbols,
450533
std::size_t number_of_timeframes,
451534
boolbvt &boolbv) const
452535
{
453536
for(std::size_t i = 0; i < number_of_timeframes; i++)
454537
{
455-
for(auto &input : inputs)
538+
for(auto &symbol : symbols)
456539
{
457-
auto input_in_timeframe = instantiate(input, i, number_of_timeframes, ns);
458-
boolbv.set_frozen(boolbv.convert_bv(input_in_timeframe));
540+
auto symbol_in_timeframe =
541+
instantiate(symbol, i, number_of_timeframes, ns);
542+
boolbv.set_frozen(boolbv.convert_bv(symbol_in_timeframe));
459543
}
460544
}
461545
}
@@ -495,6 +579,35 @@ std::vector<exprt> random_tracest::random_input_constraints(
495579

496580
/*******************************************************************\
497581
582+
Function: random_tracest::random_initial_state_constraints
583+
584+
Inputs:
585+
586+
Outputs:
587+
588+
Purpose:
589+
590+
\*******************************************************************/
591+
592+
std::vector<exprt> random_tracest::random_initial_state_constraints(
593+
decision_proceduret &solver,
594+
const symbolst &state_variables)
595+
{
596+
std::vector<exprt> result;
597+
598+
for(auto &symbol : state_variables)
599+
{
600+
auto symbol_in_timeframe = instantiate(symbol, 0, 1, ns);
601+
auto constraint =
602+
equal_exprt(symbol_in_timeframe, random_value(symbol.type()));
603+
result.push_back(std::move(constraint));
604+
}
605+
606+
return result;
607+
}
608+
609+
/*******************************************************************\
610+
498611
Function: random_tracest::operator()()
499612
500613
Inputs:
@@ -533,10 +646,16 @@ void random_tracest::operator()(
533646
if(inputs.empty())
534647
throw ebmc_errort() << "module does not have inputs";
535648

536-
message.statistics() << "Found " << inputs.size() << " input(s)"
649+
auto state_variables = this->state_variables();
650+
651+
message.statistics() << "Found " << inputs.size() << " input(s) and "
652+
<< state_variables.size() << " state variable(s)"
537653
<< messaget::eom;
538654

539-
freeze_inputs(inputs, number_of_timeframes, solver);
655+
auto unconstrained_state_variables = remove_constrained(state_variables);
656+
657+
freeze(inputs, number_of_timeframes, solver);
658+
freeze(unconstrained_state_variables, 1, solver);
540659

541660
message.status() << "Solving with " << solver.decision_procedure_text()
542661
<< messaget::eom;
@@ -546,7 +665,13 @@ void random_tracest::operator()(
546665
auto input_constraints =
547666
random_input_constraints(solver, inputs, number_of_timeframes);
548667

549-
solver.push(input_constraints);
668+
auto initial_state_constraints =
669+
random_initial_state_constraints(solver, unconstrained_state_variables);
670+
671+
auto merged =
672+
merge_constraints(input_constraints, initial_state_constraints);
673+
674+
solver.push(merged);
550675
auto dec_result = solver();
551676
solver.pop();
552677

0 commit comments

Comments
 (0)