1

I'm trying to write a plugin that requires evaluating combinatorial circuits. From what I can gather ConstEval is the tool which does this. However, the API is not so clear to me. Is there somewhere a rundown of the members of ConstEval and what they do?

(Asked by jeremysalwen on github).

CliffordVienna
  • 7,995
  • 1
  • 37
  • 57

1 Answers1

1

Using the ConstEval class is actually quite easy. You create a ConstEval object for a given module and set the known values using the void ConstEval::set(SigSpec, Const) method. After all the known signals have been set, the bool ConstEval::eval(SigSpec&, SigSpec&) method can be used to evaluate nets. The eval() method returns true when the evaluation was successful and replaces the net(s) in the first argument with the constant values the net evaluates to. Otherwise it returns false and sets the 2nd argument to the list of nets that need to be set in order to continue evaluation.

The methods push() and pop() can be used for creating local contexts for set(). The method stop() can be used to declare signals at which the evaluation should stop, even when there are combinatoric cells driving the net.

The following simple Yosys plugin demonstrates how to use the ConstEval API (evaldemo.cc):

#include "kernel/yosys.h"
#include "kernel/consteval.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

struct EvalDemoPass : public Pass
{
    EvalDemoPass() : Pass("evaldemo") { }

    virtual void execute(vector<string>, Design *design)
    {
        Module *module = design->top_module();

        if (module == nullptr)
            log_error("No top module found!\n");

        Wire *wire_a = module->wire("\\A");
        Wire *wire_y = module->wire("\\Y");

        if (wire_a == nullptr)
            log_error("No wire A found!\n");

        if (wire_y == nullptr)
            log_error("No wire Y found!\n");

        ConstEval ce(module);
        for (int v = 0; v < 4; v++) {
            ce.push();
            ce.set(wire_a, Const(v, GetSize(wire_a)));
            SigSpec sig_y = wire_y, sig_undef;
            if (ce.eval(sig_y, sig_undef))
                log("Eval results for A=%d: Y=%s\n", v, log_signal(sig_y));
            else
                log("Eval failed for A=%d: Missing value for %s\n", v, log_signal(sig_undef));
            ce.pop();
        }
    }
} EvalDemoPass;

PRIVATE_NAMESPACE_END

Example usage:

$ cat > evaldemo.v <<EOT
module main(input [1:0] A, input [7:0] B, C, D, output [7:0] Y);
  assign Y = A == 0 ? B : A == 1 ? C : A == 2 ? D : 42;
endmodule
EOT

$ yosys-config --build evaldemo.so evaldemo.cc
$ yosys -m evaldemo.so -p evaldemo evaldemo.v
...
-- Running command `evaldemo' --
Eval failed for A=0: Missing value for \B
Eval failed for A=1: Missing value for \C
Eval failed for A=2: Missing value for \D
Eval results for A=3: Y=8'00101010
CliffordVienna
  • 7,995
  • 1
  • 37
  • 57