3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2026-06-21 16:20:26 +00:00
yosys/passes/tests/test_kogge_stone.cc
2026-06-12 14:55:47 +02:00

101 lines
3 KiB
C++

#include "kernel/compressor_tree.h"
#include "kernel/yosys.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
static void build_lcu_adder(Module *module, SigSpec a, SigSpec b, SigSpec y)
{
int width = GetSize(y);
SigSpec p = module->Xor(NEW_ID, a, b);
SigSpec g = module->And(NEW_ID, a, b);
SigSpec co = module->addWire(NEW_ID, width);
Cell *lcu = module->addCell(NEW_ID, ID($lcu));
lcu->setParam(ID::WIDTH, width);
lcu->setPort(ID::P, p);
lcu->setPort(ID::G, g);
lcu->setPort(ID::CI, State::S0);
lcu->setPort(ID::CO, co);
SigSpec carry_in;
carry_in.append(State::S0);
carry_in.append(co.extract(0, width - 1));
module->addXor(NEW_ID, p, carry_in, y);
}
static Module *make_module(Design *design, IdString name, int width)
{
Module *module = design->addModule(name);
Wire *a = module->addWire(ID(a), width);
a->port_input = true;
Wire *b = module->addWire(ID(b), width);
b->port_input = true;
Wire *y = module->addWire(ID(y), width);
y->port_output = true;
module->fixup_ports();
return module;
}
struct TestKoggeStonePass : public Pass {
TestKoggeStonePass() : Pass("test_kogge_stone", "build adders for Kogge-Stone equivalence testing") {}
void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" test_kogge_stone [options]\n");
log("\n");
log("Build two modules implementing an unsigned 'y = a + b' adder of a given width,\n");
log("and compare various internal Kogge-Stone adders.\n");
log("\n");
log(" -width N\n");
log(" width of the operands and result (default = 16)\n");
log("\n");
log(" -gold name\n");
log(" name of the $lcu-based reference module (default = gold)\n");
log("\n");
log(" -gate name\n");
log(" name of the emit_kogge_stone() module (default = gate)\n");
log("\n");
}
void execute(std::vector<std::string> args, Design *design) override
{
int width = 16;
IdString gold_name = ID(gold);
IdString gate_name = ID(gate);
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
if (args[argidx] == "-width" && argidx + 1 < args.size()) {
width = atoi(args[++argidx].c_str());
continue;
}
if (args[argidx] == "-gold" && argidx + 1 < args.size()) {
gold_name = RTLIL::escape_id(args[++argidx]);
continue;
}
if (args[argidx] == "-gate" && argidx + 1 < args.size()) {
gate_name = RTLIL::escape_id(args[++argidx]);
continue;
}
break;
}
extra_args(args, argidx, design, false);
if (width < 1)
log_cmd_error("Width must be at least 1.\n");
log_header(design, "Executing TEST_KOGGE_STONE pass (width=%d).\n", width);
Module *gold = make_module(design, gold_name, width);
build_lcu_adder(gold, gold->wire(ID(a)), gold->wire(ID(b)), gold->wire(ID(y)));
Module *gate = make_module(design, gate_name, width);
CompressorTree::emit_kogge_stone(gate, gate->wire(ID(a)), gate->wire(ID(b)), gate->wire(ID(y)));
}
} TestKoggeStonePass;
PRIVATE_NAMESPACE_END