Как работает API Yosys ConstEval?

Я пытаюсь написать плагин, который требует оценки комбинаторных схем. Из того, что я могу собрать, ConstEval - инструмент, который делает это. Однако API мне не так понятен. Есть ли где-нибудь краткое изложение членов ConstEval и что они делают?

( Спросил Джеремисальвен на github).

1 ответ

Решение

Использование класса ConstEval на самом деле довольно просто. Вы создаете объект ConstEval для данного модуля и устанавливаете известные значения, используя void ConstEval::set(SigSpec, Const) метод. После того, как все известные сигналы были установлены, bool ConstEval::eval(SigSpec&, SigSpec&) Метод может быть использован для оценки сетей. eval() метод возвращает true когда оценка была успешной и заменяет сеть (ы) в первом аргументе постоянными значениями, к которым оценивает сеть. В противном случае возвращается false и устанавливает второй аргумент в список сетей, которые должны быть установлены для продолжения оценки.

Методы push() а также pop() может быть использован для создания локальных контекстов для set(), Метод stop() может использоваться для объявления сигналов, при которых оценка должна прекратиться, даже когда в сети находятся комбинаторные ячейки.

Следующий простой плагин Yosys демонстрирует, как использовать API ConstEval (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

Пример использования:

$ 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
Другие вопросы по тегам