mirror of
https://github.com/YosysHQ/yosys
synced 2026-07-25 00:22:34 +00:00
75 lines
2 KiB
Text
75 lines
2 KiB
Text
pattern negmux
|
|
//
|
|
// Authored by Abhinav Tondapu of Silimate, Inc. under ISC license.
|
|
//
|
|
// Distribute negation over mux
|
|
//
|
|
// -(s ? a : b) ===> s ? (-a) : (-b)
|
|
//
|
|
|
|
state <SigSpec> neg_a neg_y neg_a_norm mux_a mux_b mux_s mux_y
|
|
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()
|
|
set neg_a_norm strip_ext_for_match(neg_a)
|
|
endmatch
|
|
|
|
match mux
|
|
select mux->type == $mux
|
|
index <SigSpec> strip_ext_for_match(port(mux, \Y)) === neg_a_norm
|
|
filter nusers(port(mux, \Y)) == 2
|
|
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
|
|
|
|
code neg_a neg_y mux_a mux_b mux_s mux_y a_signed
|
|
// Require neg input to be exactly mux_y or a sign/zero extension of it
|
|
if (GetSize(neg_a) < GetSize(mux_y))
|
|
reject;
|
|
for (int i = 0; i < GetSize(mux_y); i++) {
|
|
if (neg_a[i] != mux_y[i])
|
|
reject;
|
|
}
|
|
if (GetSize(neg_a) > GetSize(mux_y)) {
|
|
RTLIL::SigBit ext = a_signed ? mux_y[GetSize(mux_y)-1] : RTLIL::SigBit(RTLIL::State::S0);
|
|
for (int i = GetSize(mux_y); i < GetSize(neg_a); i++) {
|
|
if (neg_a[i] != ext)
|
|
reject;
|
|
}
|
|
}
|
|
|
|
{
|
|
// Anchor negations to the original neg output width
|
|
int width = GetSize(neg_y);
|
|
|
|
Cell *cell = neg;
|
|
SigSpec mux_a_rs = mux_a;
|
|
SigSpec mux_b_rs = mux_b;
|
|
mux_a_rs.extend_u0(width, a_signed);
|
|
mux_b_rs.extend_u0(width, a_signed);
|
|
|
|
SigSpec neg_mux_a = module->addWire(NEW_ID2_SUFFIX("na"), width);
|
|
Cell *neg_a_cell = module->addNeg(NEW_ID2_SUFFIX("nega"), mux_a_rs, neg_mux_a, a_signed);
|
|
|
|
SigSpec neg_mux_b = module->addWire(NEW_ID2_SUFFIX("nb"), width);
|
|
Cell *neg_b_cell = module->addNeg(NEW_ID2_SUFFIX("negb"), mux_b_rs, neg_mux_b, a_signed);
|
|
|
|
Cell *new_mux = module->addMux(NEW_ID2_SUFFIX("mux"), neg_mux_a, neg_mux_b, mux_s, neg_y);
|
|
|
|
log(" neg=%s, mux=%s\n", log_id(neg), log_id(mux));
|
|
|
|
neg_a_cell->fixup_parameters();
|
|
neg_b_cell->fixup_parameters();
|
|
new_mux->fixup_parameters();
|
|
autoremove(neg);
|
|
autoremove(mux);
|
|
did_something = true;
|
|
}
|
|
accept;
|
|
endcode
|