Yosys ConstEval API 是如何工作的?
How does the Yosys ConstEval API work?
我正在尝试编写一个需要评估组合电路的插件。据我所知,ConstEval 是执行此操作的工具。但是,API 对我来说不是很清楚。是否有关于 ConstEval 成员及其所做工作的概要?
使用 ConstEval class 其实很简单。您为给定模块创建一个 ConstEval 对象,并使用 void ConstEval::set(SigSpec, Const)
方法设置已知值。设置完所有已知信号后,可以使用 bool ConstEval::eval(SigSpec&, SigSpec&)
方法评估网络。 eval()
方法 returns true
当评估成功时,将第一个参数中的网络替换为网络评估的常量值。否则它 returns false
并将第二个参数设置为需要设置以继续评估的网络列表。
方法 push()
和 pop()
可用于为 set()
创建本地上下文。方法 stop()
可用于声明评估应停止的信号,即使有组合单元驱动网络。
以下简单的 Yosys 插件演示了如何使用 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
用法示例:
$ 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
我正在尝试编写一个需要评估组合电路的插件。据我所知,ConstEval 是执行此操作的工具。但是,API 对我来说不是很清楚。是否有关于 ConstEval 成员及其所做工作的概要?
使用 ConstEval class 其实很简单。您为给定模块创建一个 ConstEval 对象,并使用 void ConstEval::set(SigSpec, Const)
方法设置已知值。设置完所有已知信号后,可以使用 bool ConstEval::eval(SigSpec&, SigSpec&)
方法评估网络。 eval()
方法 returns true
当评估成功时,将第一个参数中的网络替换为网络评估的常量值。否则它 returns false
并将第二个参数设置为需要设置以继续评估的网络列表。
方法 push()
和 pop()
可用于为 set()
创建本地上下文。方法 stop()
可用于声明评估应停止的信号,即使有组合单元驱动网络。
以下简单的 Yosys 插件演示了如何使用 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
用法示例:
$ 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