mirror of
https://github.com/YosysHQ/yosys
synced 2026-06-04 16:10:51 +00:00
Remove black boxes for now.
This commit is contained in:
parent
b17792c451
commit
932be8c611
3 changed files with 6 additions and 86 deletions
|
|
@ -47,14 +47,12 @@ enum class FinalAdder {
|
||||||
DEFAULT, // emit $add and let downstream techmap pick
|
DEFAULT, // emit $add and let downstream techmap pick
|
||||||
RIPPLE, // emit $add with explicit narrow hint
|
RIPPLE, // emit $add with explicit narrow hint
|
||||||
PARALLEL_PREFIX, // emit $add with PARALLEL_PREFIX
|
PARALLEL_PREFIX, // emit $add with PARALLEL_PREFIX
|
||||||
ELARITH_MOP_CSV, // black-box instance of \AddMopCsv
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class FinalMode {
|
enum class FinalMode {
|
||||||
AUTO,
|
AUTO,
|
||||||
RIPPLE,
|
RIPPLE,
|
||||||
PREFIX,
|
PREFIX,
|
||||||
ELARITH
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::pair<SigSpec, SigSpec> emit_compressor_32(Module *module, SigSpec a, SigSpec b, SigSpec c, int width)
|
inline std::pair<SigSpec, SigSpec> emit_compressor_32(Module *module, SigSpec a, SigSpec b, SigSpec c, int width)
|
||||||
|
|
@ -393,11 +391,10 @@ inline void emit_kogge_stone(Module *module, SigSpec a, SigSpec b, SigSpec y)
|
||||||
* @b: Signal B
|
* @b: Signal B
|
||||||
* @y: Signal Y
|
* @y: Signal Y
|
||||||
* @choice: Adder type to instantiate
|
* @choice: Adder type to instantiate
|
||||||
* @any_signed: Signed info for library macros
|
|
||||||
*
|
*
|
||||||
* Return: Cell* of the emitted instance
|
* Return: Cell* of the emitted instance
|
||||||
*/
|
*/
|
||||||
inline Cell *emit_final_adder(Module *module, SigSpec a, SigSpec b, SigSpec y, FinalAdder choice, bool any_signed) {
|
inline Cell *emit_final_adder(Module *module, SigSpec a, SigSpec b, SigSpec y, FinalAdder choice) {
|
||||||
switch (choice) {
|
switch (choice) {
|
||||||
case FinalAdder::DEFAULT:
|
case FinalAdder::DEFAULT:
|
||||||
case FinalAdder::RIPPLE: {
|
case FinalAdder::RIPPLE: {
|
||||||
|
|
@ -407,17 +404,6 @@ inline Cell *emit_final_adder(Module *module, SigSpec a, SigSpec b, SigSpec y, F
|
||||||
emit_kogge_stone(module, a, b, y);
|
emit_kogge_stone(module, a, b, y);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
case FinalAdder::ELARITH_MOP_CSV: {
|
|
||||||
Cell *c = module->addCell(NEW_ID, IdString("\\AddMopCsv"));
|
|
||||||
int w = GetSize(y);
|
|
||||||
c->setParam(IdString("\\WIDTH"), w);
|
|
||||||
c->setParam(IdString("\\NUM_OPERANDS"), 2);
|
|
||||||
c->setParam(IdString("\\SIGNED"), any_signed ? 1 : 0);
|
|
||||||
c->setParam(IdString("\\SPEED"), Const("fast"));
|
|
||||||
c->setPort(IdString("\\Operands"), {a, b});
|
|
||||||
c->setPort(IdString("\\Sum"), y);
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
log_assert(false && "CompressorTree::emit_final_adder: invalid choice");
|
log_assert(false && "CompressorTree::emit_final_adder: invalid choice");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
@ -427,7 +413,6 @@ inline FinalAdder pick_final_adder(int width, FinalMode mode) {
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case FinalMode::RIPPLE: return FinalAdder::RIPPLE;
|
case FinalMode::RIPPLE: return FinalAdder::RIPPLE;
|
||||||
case FinalMode::PREFIX: return FinalAdder::PARALLEL_PREFIX;
|
case FinalMode::PREFIX: return FinalAdder::PARALLEL_PREFIX;
|
||||||
case FinalMode::ELARITH: return FinalAdder::ELARITH_MOP_CSV;
|
|
||||||
case FinalMode::AUTO:
|
case FinalMode::AUTO:
|
||||||
default: return (width < RIPPLE_PREFIX_THRESHOLD) ? FinalAdder::DEFAULT : FinalAdder::PARALLEL_PREFIX;
|
default: return (width < RIPPLE_PREFIX_THRESHOLD) ? FinalAdder::DEFAULT : FinalAdder::PARALLEL_PREFIX;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ struct ArithTreeOptions {
|
||||||
CompressorTree::Strategy strategy = CompressorTree::Strategy::PREFER_42;
|
CompressorTree::Strategy strategy = CompressorTree::Strategy::PREFER_42;
|
||||||
CompressorTree::FinalMode final_mode = CompressorTree::FinalMode::AUTO;
|
CompressorTree::FinalMode final_mode = CompressorTree::FinalMode::AUTO;
|
||||||
bool fma_fusion = true;
|
bool fma_fusion = true;
|
||||||
bool elarith_macro = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ArithTreeWorker {
|
struct ArithTreeWorker {
|
||||||
|
|
@ -335,52 +334,13 @@ struct ArithTreeWorker {
|
||||||
return pool;
|
return pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit_tree(std::vector<Operand> &operands, SigSpec result_y, int neg_compensation, bool any_signed, const char *desc)
|
void emit_tree(std::vector<Operand> &operands, SigSpec result_y, int neg_compensation)
|
||||||
{
|
{
|
||||||
int width = GetSize(result_y);
|
int width = GetSize(result_y);
|
||||||
|
|
||||||
if (opt.elarith_macro) {
|
|
||||||
// Bypass the compressor
|
|
||||||
emit_elarith_macro(operands, result_y, neg_compensation, any_signed, desc);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto pool = build_operand_pool(operands, width, neg_compensation);
|
auto pool = build_operand_pool(operands, width, neg_compensation);
|
||||||
auto [a, b] = CompressorTree::reduce_scheduled(module, std::move(pool), width, opt.strategy);
|
auto [a, b] = CompressorTree::reduce_scheduled(module, std::move(pool), width, opt.strategy);
|
||||||
auto final_choice = CompressorTree::pick_final_adder(width, opt.final_mode);
|
auto final_choice = CompressorTree::pick_final_adder(width, opt.final_mode);
|
||||||
CompressorTree::emit_final_adder(module, a, b, result_y, final_choice, any_signed);
|
CompressorTree::emit_final_adder(module, a, b, result_y, final_choice);
|
||||||
}
|
|
||||||
|
|
||||||
void emit_elarith_macro(std::vector<Operand> &operands, SigSpec result_y, int neg_compensation, bool any_signed, const char *desc)
|
|
||||||
{
|
|
||||||
// Multi operand
|
|
||||||
int width = GetSize(result_y);
|
|
||||||
auto pool = build_operand_pool(operands, width, neg_compensation);
|
|
||||||
|
|
||||||
log(" arith_tree::elarith: %s -> \\AddMopCsv macro, %d operands, width %d (module %s)\n", desc, (int)pool.size(), width, log_id(module));
|
|
||||||
|
|
||||||
// Pack all operands
|
|
||||||
SigSpec flat;
|
|
||||||
for (auto &dp : pool) {
|
|
||||||
SigSpec ext = CompressorTree::normalize_to_width(dp.sig, false, width);
|
|
||||||
flat.append(ext);
|
|
||||||
}
|
|
||||||
|
|
||||||
Cell *c = module->addCell(NEW_ID, IdString("\\AddMopCsv"));
|
|
||||||
c->setParam(IdString("\\WIDTH"), width);
|
|
||||||
c->setParam(IdString("\\NUM_OPERANDS"), (int)pool.size());
|
|
||||||
c->setParam(IdString("\\SIGNED"), any_signed ? 1 : 0);
|
|
||||||
c->setParam(IdString("\\SPEED"), Const("fast"));
|
|
||||||
c->setPort(IdString("\\Operands"), flat);
|
|
||||||
c->setPort(IdString("\\Sum"), result_y);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool any_operand_signed(const std::vector<Operand> &operands)
|
|
||||||
{
|
|
||||||
for (auto &op : operands)
|
|
||||||
if (op.is_signed || op.factor_b_signed)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void process_chains()
|
void process_chains()
|
||||||
|
|
@ -415,7 +375,7 @@ struct ArithTreeWorker {
|
||||||
for (auto c : chain)
|
for (auto c : chain)
|
||||||
to_remove.insert(c);
|
to_remove.insert(c);
|
||||||
|
|
||||||
emit_tree(operands, root->getPort(ID::Y), neg_compensation, any_operand_signed(operands), "Replaced $add/$sub chain");
|
emit_tree(operands, root->getPort(ID::Y), neg_compensation);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto cell : to_remove)
|
for (auto cell : to_remove)
|
||||||
|
|
@ -442,7 +402,7 @@ struct ArithTreeWorker {
|
||||||
if (!has_mul && operands.size() < 3)
|
if (!has_mul && operands.size() < 3)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
emit_tree(operands, cell->getPort(ID::Y), neg_compensation, any_operand_signed(operands), has_mul ? "Replaced $macc (FMA)" : "Replaced $macc");
|
emit_tree(operands, cell->getPort(ID::Y), neg_compensation);
|
||||||
to_remove.insert(cell);
|
to_remove.insert(cell);
|
||||||
}
|
}
|
||||||
for (auto cell : to_remove)
|
for (auto cell : to_remove)
|
||||||
|
|
@ -477,17 +437,12 @@ struct ArithTreePass : public Pass {
|
||||||
log(" '42' (the default) prefers 4:2 compressor groupings, with\n");
|
log(" '42' (the default) prefers 4:2 compressor groupings, with\n");
|
||||||
log(" fallback to 3:2 compressors for residuals\n");
|
log(" fallback to 3:2 compressors for residuals\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -final <auto|ripple|prefix|elarith>\n");
|
log(" -final <auto|ripple|prefix>\n");
|
||||||
log(" Selects the architecture used for the final two-vector add.\n");
|
log(" Selects the architecture used for the final two-vector add.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -no-fma\n");
|
log(" -no-fma\n");
|
||||||
log(" Disable fused multiply-add expansion in $macc cells\n");
|
log(" Disable fused multiply-add expansion in $macc cells\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -elarith-macro\n");
|
|
||||||
log(" Replace each detected chain with a single \\AddMopCsv black-box\n");
|
|
||||||
log(" instance instead of expanding it into $fa cells. The downstream\n");
|
|
||||||
log(" flow must provide an \\AddMopCsv implementation\n");
|
|
||||||
log("\n");
|
|
||||||
log("The default behaviour delivers 4:2 compression, FMA fusion, and a\n");
|
log("The default behaviour delivers 4:2 compression, FMA fusion, and a\n");
|
||||||
log("width-adaptive final adder\n");
|
log("width-adaptive final adder\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
|
@ -514,7 +469,6 @@ struct ArithTreePass : public Pass {
|
||||||
if (v == "auto") { opt.final_mode = CompressorTree::FinalMode::AUTO; }
|
if (v == "auto") { opt.final_mode = CompressorTree::FinalMode::AUTO; }
|
||||||
else if (v == "ripple") { opt.final_mode = CompressorTree::FinalMode::RIPPLE; }
|
else if (v == "ripple") { opt.final_mode = CompressorTree::FinalMode::RIPPLE; }
|
||||||
else if (v == "prefix") { opt.final_mode = CompressorTree::FinalMode::PREFIX; }
|
else if (v == "prefix") { opt.final_mode = CompressorTree::FinalMode::PREFIX; }
|
||||||
else if (v == "elarith") { opt.final_mode = CompressorTree::FinalMode::ELARITH; }
|
|
||||||
else { log_cmd_error("arith_tree: unknown -final '%s'\n", v.c_str()); }
|
else { log_cmd_error("arith_tree: unknown -final '%s'\n", v.c_str()); }
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -522,10 +476,6 @@ struct ArithTreePass : public Pass {
|
||||||
opt.fma_fusion = false;
|
opt.fma_fusion = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (arg == "-elarith-macro") {
|
|
||||||
opt.elarith_macro = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
extra_args(args, argidx, design);
|
extra_args(args, argidx, design);
|
||||||
|
|
|
||||||
|
|
@ -68,18 +68,3 @@ select -assert-min 1 t:$_AND_
|
||||||
select -assert-min 1 t:$_XOR_
|
select -assert-min 1 t:$_XOR_
|
||||||
design -reset
|
design -reset
|
||||||
|
|
||||||
read_verilog <<EOT
|
|
||||||
module elarith_macro(
|
|
||||||
input [15:0] a, b, c, d,
|
|
||||||
output [15:0] y
|
|
||||||
);
|
|
||||||
assign y = a + b + c + d;
|
|
||||||
endmodule
|
|
||||||
EOT
|
|
||||||
hierarchy -auto-top
|
|
||||||
proc
|
|
||||||
arith_tree -elarith-macro
|
|
||||||
select -assert-count 0 t:$fa
|
|
||||||
select -assert-count 0 t:$add
|
|
||||||
select -assert-count 1 t:\AddMopCsv
|
|
||||||
design -reset
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue