From 5882055899a4b44a8d3ded4f0fee8f25fd510321 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Fri, 10 Jan 2025 11:44:54 +0100 Subject: [PATCH] macc_v2: Add C port --- kernel/constids.inc | 8 +++-- kernel/macc.h | 79 +++++++++++++++++++++++++++++++-------------- kernel/rtlil.cc | 26 ++++++++++----- 3 files changed, 78 insertions(+), 35 deletions(-) diff --git a/kernel/constids.inc b/kernel/constids.inc index 15d3cc83b..4fdbb3dc8 100644 --- a/kernel/constids.inc +++ b/kernel/constids.inc @@ -276,7 +276,11 @@ X(Y) X(Y_WIDTH) X(area) X(capacitance) -X(NTERMS) -X(TERM_NEGATED) +X(NPRODUCTS) +X(NADDENDS) +X(PRODUCT_NEGATED) +X(ADDEND_NEGATED) X(A_WIDTHS) X(B_WIDTHS) +X(C_WIDTHS) +X(C_SIGNED) diff --git a/kernel/macc.h b/kernel/macc.h index e969dd86d..fdd738d45 100644 --- a/kernel/macc.h +++ b/kernel/macc.h @@ -146,18 +146,18 @@ struct Macc RTLIL::SigSpec port_a = cell->getPort(ID::A); RTLIL::SigSpec port_b = cell->getPort(ID::B); + RTLIL::SigSpec port_c = cell->getPort(ID::C); ports.clear(); - int nterms = cell->getParam(ID::NTERMS).as_int(); - const Const &neg = cell->getParam(ID::TERM_NEGATED); + int nproducts = cell->getParam(ID::NPRODUCTS).as_int(); + const Const &product_neg = cell->getParam(ID::PRODUCT_NEGATED); const Const &a_widths = cell->getParam(ID::A_WIDTHS); const Const &b_widths = cell->getParam(ID::B_WIDTHS); const Const &a_signed = cell->getParam(ID::A_SIGNED); const Const &b_signed = cell->getParam(ID::B_SIGNED); - int ai = 0, bi = 0; - for (int i = 0; i < nterms; i++) { + for (int i = 0; i < nproducts; i++) { port_t term; log_assert(a_signed[i] == b_signed[i]); @@ -169,49 +169,78 @@ struct Macc ai += a_width; term.in_b = port_b.extract(bi, b_width); bi += b_width; - term.do_subtract = (neg[i] == State::S1); + term.do_subtract = (product_neg[i] == State::S1); ports.push_back(term); } log_assert(port_a.size() == ai); log_assert(port_b.size() == bi); + + int naddends = cell->getParam(ID::NADDENDS).as_int(); + const Const &addend_neg = cell->getParam(ID::ADDEND_NEGATED); + const Const &c_widths = cell->getParam(ID::C_WIDTHS); + const Const &c_signed = cell->getParam(ID::C_SIGNED); + int ci = 0; + for (int i = 0; i < naddends; i++) { + port_t term; + + term.is_signed = (c_signed[i] == State::S1); + int c_width = c_widths.extract(16 * i, 16).as_int(false); + + term.in_a = port_c.extract(ci, c_width); + ci += c_width; + term.do_subtract = (addend_neg[i] == State::S1); + + ports.push_back(term); + } + log_assert(port_c.size() == ci); } void to_cell(RTLIL::Cell *cell) { cell->type = ID($macc_v2); - int nterms = ports.size(); - const auto Sx = State::Sx; - Const a_signed(Sx, nterms), b_signed(Sx, nterms), negated(Sx, nterms); - Const a_widths, b_widths; - SigSpec a, b; + int nproducts = 0, naddends = 0; + Const a_signed, b_signed, a_widths, b_widths, product_negated; + Const c_signed, c_widths, addend_negated; + SigSpec a, b, c; - for (int i = 0; i < nterms; i++) { + for (int i = 0; i < (int) ports.size(); i++) { SigSpec term_a = ports[i].in_a, term_b = ports[i].in_b; - a_widths.append(Const(term_a.size(), 16)); - b_widths.append(Const(term_b.size(), 16)); - - a_signed.bits()[i] = b_signed.bits()[i] = - (ports[i].is_signed ? RTLIL::S1 : RTLIL::S0); - negated.bits()[i] = (ports[i].do_subtract ? RTLIL::S1 : RTLIL::S0); - - a.append(term_a); - b.append(term_b); + if (term_b.empty()) { + // addend + c_widths.append(Const(term_a.size(), 16)); + c_signed.append(ports[i].is_signed ? RTLIL::S1 : RTLIL::S0); + addend_negated.append(ports[i].do_subtract ? RTLIL::S1 : RTLIL::S0); + c.append(term_a); + naddends++; + } else { + // product + a_widths.append(Const(term_a.size(), 16)); + b_widths.append(Const(term_b.size(), 16)); + a_signed.append(ports[i].is_signed ? RTLIL::S1 : RTLIL::S0); + b_signed.append(ports[i].is_signed ? RTLIL::S1 : RTLIL::S0); + product_negated.append(ports[i].do_subtract ? RTLIL::S1 : RTLIL::S0); + a.append(term_a); + b.append(term_b); + nproducts++; + } } - negated.is_fully_def(); - a_signed.is_fully_def(); - b_signed.is_fully_def(); - cell->setParam(ID::NTERMS, nterms); - cell->setParam(ID::TERM_NEGATED, negated); + cell->setParam(ID::NPRODUCTS, nproducts); + cell->setParam(ID::PRODUCT_NEGATED, product_negated); + cell->setParam(ID::NADDENDS, naddends); + cell->setParam(ID::ADDEND_NEGATED, addend_negated); cell->setParam(ID::A_SIGNED, a_signed); cell->setParam(ID::B_SIGNED, b_signed); + cell->setParam(ID::C_SIGNED, c_signed); cell->setParam(ID::A_WIDTHS, a_widths); cell->setParam(ID::B_WIDTHS, b_widths); + cell->setParam(ID::C_WIDTHS, c_widths); cell->setPort(ID::A, a); cell->setPort(ID::B, b); + cell->setPort(ID::C, c); } bool eval(RTLIL::Const &result) const diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index ac491f4cd..f2f36ba30 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -1468,24 +1468,34 @@ namespace { } if (cell->type == ID($macc_v2)) { - if (param(ID::NTERMS) <= 0) + if (param(ID::NPRODUCTS) <= 0) error(__LINE__); - param_bits(ID::TERM_NEGATED, param(ID::NTERMS)); - param_bits(ID::A_SIGNED, param(ID::NTERMS)); - param_bits(ID::B_SIGNED, param(ID::NTERMS)); + if (param(ID::NADDENDS) <= 0) + error(__LINE__); + param_bits(ID::PRODUCT_NEGATED, param(ID::NPRODUCTS)); + param_bits(ID::ADDEND_NEGATED, param(ID::NADDENDS)); + param_bits(ID::A_SIGNED, param(ID::NPRODUCTS)); + param_bits(ID::B_SIGNED, param(ID::NPRODUCTS)); + param_bits(ID::C_SIGNED, param(ID::NADDENDS)); if (cell->getParam(ID::A_SIGNED) != cell->getParam(ID::B_SIGNED)) error(__LINE__); - param_bits(ID::A_WIDTHS, param(ID::NTERMS) * 16); - param_bits(ID::B_WIDTHS, param(ID::NTERMS) * 16); + param_bits(ID::A_WIDTHS, param(ID::NPRODUCTS) * 16); + param_bits(ID::B_WIDTHS, param(ID::NPRODUCTS) * 16); + param_bits(ID::C_WIDTHS, param(ID::NADDENDS) * 16); const Const &a_width = cell->getParam(ID::A_WIDTHS); const Const &b_width = cell->getParam(ID::B_WIDTHS); - int a_width_sum = 0, b_width_sum = 0; - for (int i = 0; i < param(ID::NTERMS); i++) { + const Const &c_width = cell->getParam(ID::C_WIDTHS); + int a_width_sum = 0, b_width_sum = 0, c_width_sum = 0; + for (int i = 0; i < param(ID::NPRODUCTS); i++) { a_width_sum += a_width.extract(16 * i, 16).as_int(false); b_width_sum += b_width.extract(16 * i, 16).as_int(false); } + for (int i = 0; i < param(ID::NADDENDS); i++) { + c_width_sum += c_width.extract(16 * i, 16).as_int(false); + } port(ID::A, a_width_sum); port(ID::B, b_width_sum); + port(ID::C, c_width_sum); port(ID::Y, param(ID::Y_WIDTH)); check_expected(); return;