From afabf72e2314b3114e6c8df4ec81affd2910cdd3 Mon Sep 17 00:00:00 2001 From: nella Date: Wed, 3 Jun 2026 15:35:17 +0200 Subject: [PATCH] Depth-schedule finar adder. --- kernel/compressor_tree.cc | 27 ++++++++++++------ kernel/compressor_tree.h | 10 ++++--- passes/techmap/arith_tree.cc | 32 ++++++++++++---------- tests/arith_tree/arith_tree_final_adder.ys | 6 ++-- 4 files changed, 45 insertions(+), 30 deletions(-) diff --git a/kernel/compressor_tree.cc b/kernel/compressor_tree.cc index 90b632126..dad777114 100644 --- a/kernel/compressor_tree.cc +++ b/kernel/compressor_tree.cc @@ -133,7 +133,7 @@ std::vector generate_partial_products(Module *module, SigSpec a, SigSp return products; } -std::pair reduce_scheduled(Module *module, std::vector operands, int width, Strategy strategy, int *compressor_count) { +std::pair reduce_scheduled(Module *module, std::vector operands, int width, Strategy strategy, int *out_compressor_count, int *out_final_depth) { int levels = 0; int fa_count = 0; int c42_count = 0; @@ -217,15 +217,22 @@ std::pair reduce_scheduled(Module *module, std::vector= RIPPLE_PREFIX_THRESHOLD; + bool deep = final_depth >= PREFIX_DEPTH_THRESHOLD; + return (wide && deep) ? FinalAdder::PARALLEL_PREFIX : FinalAdder::DEFAULT; + } } } diff --git a/kernel/compressor_tree.h b/kernel/compressor_tree.h index 54a4d421d..814f7fdca 100644 --- a/kernel/compressor_tree.h +++ b/kernel/compressor_tree.h @@ -29,8 +29,9 @@ YOSYS_NAMESPACE_BEGIN namespace CompressorTree { -// Width threshold below which a ripple is preferred over parallel-prefix +// Width and depth thresholds below which a ripple is preferred over parallel-prefix constexpr int RIPPLE_PREFIX_THRESHOLD = 16; +constexpr int PREFIX_DEPTH_THRESHOLD = 5; enum class Strategy { FA_ONLY, // 3:2 compressors @@ -80,11 +81,12 @@ std::vector generate_partial_products(Module *module, SigSpec a, SigSp * @sigs: Vector of input signals (operands) to be reduced * @width: Target bit-width to which all operands will be zero-extended * @strategy: Compression strategy to use - * @compressor_count: Optional pointer to return the number of $fa cells emitted + * @out_compressor_count: Optional pointer to return the number of $fa cells emitted + * @out_final_depth: Optional pointer to return the final depth of the scheduled tree * * Return: The final two reduced operands, that are to be fed into an adder */ -std::pair reduce_scheduled(Module *module, std::vector operands, int width, Strategy strategy, int *compressor_count = nullptr); +std::pair reduce_scheduled(Module *module, std::vector operands, int width, Strategy strategy, int *out_compressor_count = nullptr, int *out_final_depth = nullptr); /** * emit_kogge_stone() - Emit a Kogge-Stone parallel-prefix adder @@ -107,7 +109,7 @@ void emit_kogge_stone(Module *module, SigSpec a, SigSpec b, SigSpec y); */ Cell *emit_final_adder(Module *module, SigSpec a, SigSpec b, SigSpec y, FinalAdder choice); -FinalAdder pick_final_adder(int width, FinalMode mode); +FinalAdder pick_final_adder(int width, int final_depth, FinalMode mode); } // namespace CompressorTree diff --git a/passes/techmap/arith_tree.cc b/passes/techmap/arith_tree.cc index 40544151e..bde3decc0 100644 --- a/passes/techmap/arith_tree.cc +++ b/passes/techmap/arith_tree.cc @@ -309,21 +309,22 @@ struct ArithTreeWorker { s = module->Not(NEW_ID, s); pool.push_back({s, 0}); } else { - // Multiplicative operand - auto pps = CompressorTree::generate_partial_products(module, op.sig, op.factor_b, op.is_signed, op.factor_b_signed, width); + // Multiplicative operand + auto pps = CompressorTree::generate_partial_products(module, op.sig, op.factor_b, op.is_signed, op.factor_b_signed, width); - if (!op.negate) { - for (auto &pp : pps) - pool.push_back(pp); - continue; - } - - SigSpec neg_a = module->Not(NEW_ID, op.sig); - auto neg_pps = CompressorTree::generate_partial_products(module, neg_a, op.factor_b, op.is_signed, op.factor_b_signed, width); - for (auto &pp : neg_pps) + if (!op.negate) { + for (auto &pp : pps) pool.push_back(pp); - SigSpec b_ext = CompressorTree::normalize_to_width(op.factor_b, op.factor_b_signed, width); - pool.push_back({b_ext, 0}); + continue; + } + + auto [pa, pb] = CompressorTree::reduce_scheduled(module, pps, width, opt.strategy); + SigSpec p = module->addWire(NEW_ID, width); + module->addAdd(NEW_ID, pa, pb, p, false); + SigSpec np = module->addWire(NEW_ID, width); + module->addNot(NEW_ID, p, np); + pool.push_back({np, 0}); + neg_compensation++; } } @@ -337,8 +338,9 @@ struct ArithTreeWorker { { int width = GetSize(result_y); auto pool = build_operand_pool(operands, width, neg_compensation); - auto [a, b] = CompressorTree::reduce_scheduled(module, std::move(pool), width, opt.strategy); - auto final_choice = CompressorTree::pick_final_adder(width, opt.final_mode); + int final_depth = 0; + auto [a, b] = CompressorTree::reduce_scheduled(module, std::move(pool), width, opt.strategy, nullptr, &final_depth); + auto final_choice = CompressorTree::pick_final_adder(width, final_depth, opt.final_mode); CompressorTree::emit_final_adder(module, a, b, result_y, final_choice); } diff --git a/tests/arith_tree/arith_tree_final_adder.ys b/tests/arith_tree/arith_tree_final_adder.ys index df995f531..b8184128a 100644 --- a/tests/arith_tree/arith_tree_final_adder.ys +++ b/tests/arith_tree/arith_tree_final_adder.ys @@ -10,10 +10,10 @@ hierarchy -auto-top proc equiv_opt arith_tree -final auto design -load postopt -select -assert-none t:$add +select -assert-count 1 t:$add select -assert-count 2 t:$fa -select -assert-min 1 t:$_AND_ -select -assert-min 1 t:$_XOR_ +select -assert-none t:$_AND_ +select -assert-none 1 t:$_XOR_ design -reset read_verilog <