pattern negexpand // // Authored by Abhinav Tondapu of Silimate, Inc. under ISC license. // // Expand negation over addition // // -(a + b) ===> (-a) + (-b) // state neg_a neg_y add_a add_b state 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 port(add, \Y) === neg_a filter 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; { // Anchor negations to the original negation width to preserve wrap behavior int width = GetSize(neg_y); Cell *cell = neg; SigSpec add_a_rs = add_a; SigSpec add_b_rs = add_b; // Signedness is consistent for A and B here add_a_rs.extend_u0(width, a_signed); add_b_rs.extend_u0(width, a_signed); SigSpec neg_add_a = module->addWire(NEW_ID2_SUFFIX("na"), width); Cell *neg_a_cell = module->addNeg(NEW_ID2_SUFFIX("nega"), add_a_rs, neg_add_a, a_signed); SigSpec neg_add_b = module->addWire(NEW_ID2_SUFFIX("nb"), width); Cell *neg_b_cell = module->addNeg(NEW_ID2_SUFFIX("negb"), add_b_rs, neg_add_b, a_signed); Cell *new_add = module->addAdd(NEW_ID2_SUFFIX("add"), neg_add_a, neg_add_b, neg_y, a_signed); log(" neg=%s, add=%s\n", 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