mirror of
https://github.com/YosysHQ/yosys
synced 2026-07-25 00:22:34 +00:00
This commit introduces the negopt pass with pre/post optimization modes for handling negation patterns in arithmetic circuits. Pre-optimization patterns (expose for tree balancing): - manual2sub: (a + ~b) + 1 → a - b - sub2neg: a - b → a + (-b) - negexpand: -(a + b) → (-a) + (-b) [with output width fix] - negneg: -(-a) → a - negmux: -(s ? a : b) → s ? (-a) : (-b) Post-optimization patterns (cleanup/rebuild): - negrebuild: (-a) + (-b) → -(a + b) - muxneg: s ? (-a) : (-b) → -(s ? a : b) - neg2sub: a + (-b) → a - b All patterns use nusers() for fanout checking (standard Yosys style). Comprehensive test coverage with positive/negative cases and formal verification via equiv_opt.
56 lines
1.4 KiB
Text
56 lines
1.4 KiB
Text
pattern negexpand
|
|
//
|
|
// Authored by Abhinav Tondapu of Silimate, Inc. under ISC license.
|
|
//
|
|
// Expand negation over addition
|
|
//
|
|
// -(a + b) ===> (-a) + (-b)
|
|
//
|
|
|
|
state <SigSpec> neg_a neg_y add_a add_b
|
|
state <bool> a_signed
|
|
|
|
match neg
|
|
select neg->type == $neg
|
|
set neg_a port(neg, \A)
|
|
set neg_y port(neg, \Y)
|
|
set a_signed neg->getParam(\A_SIGNED).as_bool()
|
|
endmatch
|
|
|
|
match add
|
|
select add->type == $add
|
|
index <SigSpec> port(add, \Y) === neg_a
|
|
select nusers(port(add, \Y)) == 2
|
|
set add_a port(add, \A)
|
|
set add_b port(add, \B)
|
|
endmatch
|
|
|
|
code neg_a neg_y add_a add_b a_signed
|
|
if (add->getParam(\A_SIGNED).as_bool() != a_signed)
|
|
reject;
|
|
if (add->getParam(\B_SIGNED).as_bool() != a_signed)
|
|
reject;
|
|
|
|
{
|
|
// Use output width for negations to handle overflow correctly
|
|
int width = GetSize(neg_y);
|
|
SigSpec neg_add_a = module->addWire(NEW_ID, width);
|
|
Cell *neg_a_cell = module->addNeg(NEW_ID, add_a, neg_add_a, a_signed);
|
|
|
|
SigSpec neg_add_b = module->addWire(NEW_ID, width);
|
|
Cell *neg_b_cell = module->addNeg(NEW_ID, add_b, neg_add_b, a_signed);
|
|
|
|
Cell *new_add = module->addAdd(NEW_ID, neg_add_a, neg_add_b, neg_y, a_signed);
|
|
|
|
log("negexpand pattern in %s: neg=%s, add=%s\n",
|
|
log_id(module), log_id(neg), log_id(add));
|
|
|
|
neg_a_cell->fixup_parameters();
|
|
neg_b_cell->fixup_parameters();
|
|
new_add->fixup_parameters();
|
|
autoremove(neg);
|
|
autoremove(add);
|
|
did_something = true;
|
|
}
|
|
accept;
|
|
endcode
|