yosys/passes/silimate/peepopt_sub2neg.pmg

55 lines
1.3 KiB
Plaintext

pattern sub2neg
//
// Authored by Abhinav Tondapu of Silimate, Inc. under ISC license.
//
// Convert subtraction to addition with negation
//
// a - b ===> a + (-b)
//
state <SigSpec> sub_a sub_b sub_y
state <bool> a_signed b_signed
match sub
select sub->type == $sub
filter !sub->getPort(\B).is_fully_const()
set sub_a port(sub, \A)
set sub_b port(sub, \B)
set sub_y port(sub, \Y)
set a_signed sub->getParam(\A_SIGNED).as_bool()
set b_signed sub->getParam(\B_SIGNED).as_bool()
endmatch
code sub_a sub_b sub_y a_signed b_signed
if (a_signed != b_signed)
reject;
{
int width = GetSize(sub_y);
Cell *cell = sub;
SigSpec sub_a_rs = sub_a;
SigSpec sub_b_rs = sub_b;
// Anchor operands to the original subtract width to preserve wrap behavior
sub_a_rs.extend_u0(width, a_signed);
sub_b_rs.extend_u0(width, b_signed);
// Negate within the anchored width, then reuse the original cell as $add
SigSpec neg_y = module->addWire(NEW_ID2_SUFFIX("neg_y"), width);
Cell *neg = module->addNeg(NEW_ID2_SUFFIX("neg"), sub_b_rs, neg_y, b_signed);
sub->setPort(\A, sub_a_rs);
sub->setPort(\B, neg_y);
sub->setPort(\Y, sub_y);
sub->type = $add;
log(" sub=%s -> neg=%s, add=%s\n",
log_id(sub), log_id(neg), log_id(sub));
sub->fixup_parameters();
neg->fixup_parameters();
did_something = true;
}
accept;
endcode