mirror of https://github.com/YosysHQ/yosys.git
74 lines
1.7 KiB
Plaintext
74 lines
1.7 KiB
Plaintext
pattern neg2sub
|
|
//
|
|
// Authored by Abhinav Tondapu of Silimate, Inc. under ISC license.
|
|
//
|
|
// Convert addition with negation back to subtraction
|
|
//
|
|
// a + (-b) ===> a - b
|
|
//
|
|
|
|
state <SigSpec> add_a add_b add_y neg_a neg_y
|
|
state <bool> add_a_signed add_b_signed neg_signed
|
|
state <bool> neg_on_a
|
|
|
|
match add
|
|
select add->type == $add
|
|
set add_a port(add, \A)
|
|
set add_b port(add, \B)
|
|
set add_y port(add, \Y)
|
|
set add_a_signed add->getParam(\A_SIGNED).as_bool()
|
|
set add_b_signed add->getParam(\B_SIGNED).as_bool()
|
|
endmatch
|
|
|
|
code neg_on_a
|
|
neg_on_a = true;
|
|
branch;
|
|
neg_on_a = false;
|
|
endcode
|
|
|
|
match neg
|
|
select neg->type == $neg
|
|
filter nusers(port(neg, \Y)) == 2
|
|
index <SigSpec> port(neg, \Y) === (neg_on_a ? add_a : add_b)
|
|
set neg_a port(neg, \A)
|
|
set neg_y port(neg, \Y)
|
|
set neg_signed neg->getParam(\A_SIGNED).as_bool()
|
|
endmatch
|
|
|
|
code add_a add_b add_y neg_a neg_y neg_on_a add_a_signed add_b_signed neg_signed
|
|
if (add_a_signed != add_b_signed)
|
|
reject;
|
|
|
|
if (neg_signed != (neg_on_a ? add_a_signed : add_b_signed))
|
|
reject;
|
|
|
|
{
|
|
int neg_y_width = GetSize(neg_y);
|
|
int add_y_width = GetSize(add_y);
|
|
|
|
// Reject if the negation truncates its input
|
|
if (GetSize(neg_a) > neg_y_width)
|
|
reject;
|
|
|
|
// Reject if the add result is wider than the negation boundary
|
|
if (add_y_width > neg_y_width)
|
|
reject;
|
|
|
|
SigSpec pos_op = neg_on_a ? add_b : add_a;
|
|
|
|
// Reuse the original add cell for stable naming
|
|
add->setPort(\A, pos_op);
|
|
add->setPort(\B, neg_a);
|
|
add->setPort(\Y, add_y);
|
|
add->type = $sub;
|
|
|
|
log(" add=%s, neg=%s (safe sub replacement)\n",
|
|
log_id(add), log_id(neg));
|
|
|
|
add->fixup_parameters();
|
|
autoremove(neg);
|
|
did_something = true;
|
|
}
|
|
accept;
|
|
endcode
|