11#include "llvm/ADT/STLExtras.h"
12#include "llvm/ADT/SmallString.h"
20 signals.push_back({name.str(), width});
32 assert(signal <
signals.size() &&
"signal index out of range");
38 unsigned width,
Handle handle) {
45 assert(
signals[signal].width == width &&
"trace signal width changed");
47 record(step, signal, handle);
50std::optional<circt::bmc::BMCTrace::Handle>
59 os <<
"counterexample for " <<
topName <<
":\n";
60 for (
size_t step = 0, e =
recorded.size(); step != e; ++step) {
61 os <<
"cycle " << step <<
":\n";
62 for (
size_t signal = 0, numSignals =
signals.size(); signal != numSignals;
64 auto handle =
recorded[step][signal];
67 auto value = evaluate(*handle,
signals[signal].width);
68 if (!value || value->getBitWidth() !=
signals[signal].width)
70 llvm::SmallString<40> str;
71 value->toString(str, 16,
false,
73 os <<
" " <<
signals[signal].name <<
" = 0x" << str <<
"\n";
82 if (!
context || !model || !modelEval || !getNumeralBinaryString)
86 os, [&](
Handle expression,
unsigned width) -> std::optional<llvm::APInt> {
90 return llvm::APInt(0, uint64_t{0});
93 if (!modelEval(
context, model, expression,
true,
98 const char *binaryString = getNumeralBinaryString(
context, value);
101 llvm::StringRef digits(binaryString);
102 digits.consume_front(
"#b");
103 if (digits.empty() || digits.size() > width ||
104 llvm::any_of(digits, [](
char digit) {
105 return digit !=
'0' && digit !=
'1';
108 return llvm::APInt(width, digits, 2);
119 trace->
record(step, name, width, handle);
129 getNumeralBinaryString)) {
130 llvm::errs() <<
"failed to evaluate BMC counterexample trace\n";
assert(baseType &&"element must be base type")
static std::unique_ptr< Context > context
std::vector< std::optional< Handle > > Step
Per-cycle storage for all tracked signals.
bool printTextTrace(llvm::raw_ostream &os, Evaluator evaluate) const
Render the trace as cycle-by-cycle text using the provided evaluator to materialize values from recor...
const char *(*)(Handle context, Handle value) GetNumeralBinaryString
void ensureStep(size_t step)
std::vector< Step > recorded
BMCTrace(llvm::StringRef topName="bmc")
Create an empty trace for the given top-level design/module name.
const void * Handle
Opaque per-signal value reference recorded for a specific cycle.
size_t addSignal(llvm::StringRef name, unsigned width)
Register a signal to be tracked and return its stable index.
llvm::StringMap< size_t > signalIndices
bool(*)(Handle context, Handle model, Handle expression, bool modelCompletion, Handle *value) ModelEval
Z3 API callbacks passed in by JIT-compiled code.
llvm::function_ref< std::optional< llvm::APInt >(Handle, unsigned width)> Evaluator
Callback used to materialize a recorded handle into a concrete value when formatting a trace.
std::vector< Signal > signals
void record(size_t step, size_t signal, Handle handle)
Record the value handle for a tracked signal at the given cycle.
std::optional< Handle > lookup(size_t step, size_t signal) const
Return the recorded handle for a signal at a given cycle, if present.
bool circt_bmc_print_trace(BMCTrace *trace, BMCTrace::Handle context, BMCTrace::Handle model, BMCTrace::ModelEval modelEval, BMCTrace::GetNumeralBinaryString getNumeralBinaryString)
Runtime entry point called on the SAT path while the Z3 context and model are still alive.
void circt_bmc_record_trace(BMCTrace *trace, uint32_t step, const char *name, uint32_t width, BMCTrace::Handle handle)
Runtime entry point called by JIT-compiled BMC code.