mirror of
https://github.com/YosysHQ/yosys
synced 2026-07-25 16:42:35 +00:00
74 lines
2.1 KiB
Text
74 lines
2.1 KiB
Text
pattern muxneg
|
|
//
|
|
// Authored by Abhinav Tondapu of Silimate, Inc. under ISC license.
|
|
//
|
|
// Factor negation out of mux
|
|
//
|
|
// s ? (-a) : (-b) ===> -(s ? a : b)
|
|
//
|
|
|
|
state <SigSpec> mux_a mux_b mux_s mux_y neg_a_in neg_a_y neg_b_in neg_b_y
|
|
state <bool> neg_a_signed neg_b_signed
|
|
|
|
match mux
|
|
select mux->type == $mux
|
|
set mux_a port(mux, \A)
|
|
set mux_b port(mux, \B)
|
|
set mux_s port(mux, \S)
|
|
set mux_y port(mux, \Y)
|
|
endmatch
|
|
|
|
match neg_a
|
|
select neg_a->type == $neg
|
|
filter nusers(port(neg_a, \Y)) == 2
|
|
index <SigSpec> port(neg_a, \Y) === mux_a
|
|
set neg_a_in port(neg_a, \A)
|
|
set neg_a_y port(neg_a, \Y)
|
|
set neg_a_signed neg_a->getParam(\A_SIGNED).as_bool()
|
|
endmatch
|
|
|
|
match neg_b
|
|
select neg_b->type == $neg
|
|
filter nusers(port(neg_b, \Y)) == 2
|
|
index <SigSpec> port(neg_b, \Y) === mux_b
|
|
set neg_b_in port(neg_b, \A)
|
|
set neg_b_y port(neg_b, \Y)
|
|
set neg_b_signed neg_b->getParam(\A_SIGNED).as_bool()
|
|
endmatch
|
|
|
|
code mux_a mux_b mux_s mux_y neg_a_in neg_a_y neg_b_in neg_b_y neg_a_signed neg_b_signed
|
|
if (neg_a_signed != neg_b_signed)
|
|
reject;
|
|
|
|
{
|
|
// Anchor to the narrower negation width to preserve wrap behavior
|
|
int width = std::min(GetSize(neg_a_y), GetSize(neg_b_y));
|
|
|
|
Cell *cell = mux;
|
|
SigSpec neg_a_rs = neg_a_in;
|
|
SigSpec neg_b_rs = neg_b_in;
|
|
neg_a_rs.extend_u0(width, neg_a_signed);
|
|
neg_b_rs.extend_u0(width, neg_b_signed);
|
|
|
|
SigSpec mux_out = module->addWire(NEW_ID2_SUFFIX("y"), width);
|
|
Cell *new_mux = module->addMux(NEW_ID2_SUFFIX("mux"), neg_a_rs, neg_b_rs, mux_s, mux_out);
|
|
SigSpec neg_out = module->addWire(NEW_ID2_SUFFIX("neg_y"), width);
|
|
Cell *new_neg = module->addNeg(NEW_ID2_SUFFIX("neg"), mux_out, neg_out, neg_a_signed);
|
|
|
|
// Extend back to mux output width when needed
|
|
SigSpec neg_out_rs = neg_out;
|
|
neg_out_rs.extend_u0(GetSize(mux_y), neg_a_signed);
|
|
module->connect(mux_y, neg_out_rs);
|
|
|
|
log(" mux=%s, neg_a=%s, neg_b=%s\n",
|
|
log_id(mux), log_id(neg_a), log_id(neg_b));
|
|
|
|
new_mux->fixup_parameters();
|
|
new_neg->fixup_parameters();
|
|
autoremove(mux);
|
|
autoremove(neg_a);
|
|
autoremove(neg_b);
|
|
did_something = true;
|
|
}
|
|
accept;
|
|
endcode
|