From abdeac3069c1626c307ed05e5ba6ae741073d778 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Fri, 13 Dec 2024 19:01:41 +0100 Subject: [PATCH] macc_v2: Start new cell --- kernel/constids.inc | 4 ++ kernel/macc.h | 104 ++++++++++++++++++---------- kernel/rtlil.cc | 29 ++++++++ passes/techmap/maccmap.cc | 2 +- tests/alumacc/macc_infer_n_unmap.ys | 19 +++++ 5 files changed, 120 insertions(+), 38 deletions(-) create mode 100644 tests/alumacc/macc_infer_n_unmap.ys diff --git a/kernel/constids.inc b/kernel/constids.inc index d68e2dfe646..15d3cc83b29 100644 --- a/kernel/constids.inc +++ b/kernel/constids.inc @@ -276,3 +276,7 @@ X(Y) X(Y_WIDTH) X(area) X(capacitance) +X(NTERMS) +X(TERM_NEGATED) +X(A_WIDTHS) +X(B_WIDTHS) diff --git a/kernel/macc.h b/kernel/macc.h index 55940769de2..e969dd86d0a 100644 --- a/kernel/macc.h +++ b/kernel/macc.h @@ -82,7 +82,7 @@ struct Macc new_ports.swap(ports); } - void from_cell(RTLIL::Cell *cell) + void from_cell_v1(RTLIL::Cell *cell) { RTLIL::SigSpec port_a = cell->getPort(ID::A); @@ -136,52 +136,82 @@ struct Macc log_assert(port_a_cursor == GetSize(port_a)); } - void to_cell(RTLIL::Cell *cell) const + void from_cell(RTLIL::Cell *cell) { - RTLIL::SigSpec port_a; - std::vector config_bits; - int max_size = 0, num_bits = 0; - - for (auto &port : ports) { - max_size = max(max_size, GetSize(port.in_a)); - max_size = max(max_size, GetSize(port.in_b)); + if (cell->type == ID($macc)) { + from_cell_v1(cell); + return; } + log_assert(cell->type == ID($macc_v2)); - while (max_size) - num_bits++, max_size /= 2; + RTLIL::SigSpec port_a = cell->getPort(ID::A); + RTLIL::SigSpec port_b = cell->getPort(ID::B); - log_assert(num_bits < 16); - config_bits.push_back(num_bits & 1 ? State::S1 : State::S0); - config_bits.push_back(num_bits & 2 ? State::S1 : State::S0); - config_bits.push_back(num_bits & 4 ? State::S1 : State::S0); - config_bits.push_back(num_bits & 8 ? State::S1 : State::S0); + ports.clear(); - for (auto &port : ports) - { - if (GetSize(port.in_a) == 0) - continue; + int nterms = cell->getParam(ID::NTERMS).as_int(); + const Const &neg = cell->getParam(ID::TERM_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++) { + port_t term; + + log_assert(a_signed[i] == b_signed[i]); + term.is_signed = (a_signed[i] == State::S1); + int a_width = a_widths.extract(16 * i, 16).as_int(false); + int b_width = b_widths.extract(16 * i, 16).as_int(false); + + term.in_a = port_a.extract(ai, a_width); + ai += a_width; + term.in_b = port_b.extract(bi, b_width); + bi += b_width; + term.do_subtract = (neg[i] == State::S1); + + ports.push_back(term); + } + log_assert(port_a.size() == ai); + log_assert(port_b.size() == bi); + } - config_bits.push_back(port.is_signed ? State::S1 : State::S0); - config_bits.push_back(port.do_subtract ? State::S1 : State::S0); + void to_cell(RTLIL::Cell *cell) + { + cell->type = ID($macc_v2); - int size_a = GetSize(port.in_a); - for (int i = 0; i < num_bits; i++) - config_bits.push_back(size_a & (1 << i) ? State::S1 : State::S0); + 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 size_b = GetSize(port.in_b); - for (int i = 0; i < num_bits; i++) - config_bits.push_back(size_b & (1 << i) ? State::S1 : State::S0); + for (int i = 0; i < nterms; i++) { + SigSpec term_a = ports[i].in_a, term_b = ports[i].in_b; - port_a.append(port.in_a); - port_a.append(port.in_b); - } + a_widths.append(Const(term_a.size(), 16)); + b_widths.append(Const(term_b.size(), 16)); - cell->setPort(ID::A, port_a); - cell->setPort(ID::B, {}); - cell->setParam(ID::CONFIG, config_bits); - cell->setParam(ID::CONFIG_WIDTH, GetSize(config_bits)); - cell->setParam(ID::A_WIDTH, GetSize(port_a)); - cell->setParam(ID::B_WIDTH, 0); + 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); + } + 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::A_SIGNED, a_signed); + cell->setParam(ID::B_SIGNED, b_signed); + cell->setParam(ID::A_WIDTHS, a_widths); + cell->setParam(ID::B_WIDTHS, b_widths); + cell->setPort(ID::A, a); + cell->setPort(ID::B, b); } bool eval(RTLIL::Const &result) const diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 63258079591..ca6c24a6fa8 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -1467,6 +1467,30 @@ namespace { return; } + if (cell->type == ID($macc_v2)) { + if (param(ID::NTERMS) <= 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 (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); + 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++) { + a_width_sum += a_width.extract(16 * i, 16).as_int(false); + b_width_sum += b_width.extract(16 * i, 16).as_int(false); + } + port(ID::A, a_width_sum); + port(ID::B, b_width_sum); + port(ID::Y, param(ID::Y_WIDTH)); + check_expected(); + return; + } + if (cell->type == ID($logic_not)) { param_bool(ID::A_SIGNED); port(ID::A, param(ID::A_WIDTH)); @@ -4099,6 +4123,11 @@ void RTLIL::Cell::fixup_parameters(bool set_a_signed, bool set_b_signed) return; } + if (type == ID($macc_v2)) { + parameters[ID::Y_WIDTH] = GetSize(connections_[ID::Y]); + return; + } + bool signedness_ab = !type.in(ID($slice), ID($concat), ID($macc)); if (connections_.count(ID::A)) { diff --git a/passes/techmap/maccmap.cc b/passes/techmap/maccmap.cc index 911d66cfa1b..3dde9243803 100644 --- a/passes/techmap/maccmap.cc +++ b/passes/techmap/maccmap.cc @@ -403,7 +403,7 @@ struct MaccmapPass : public Pass { for (auto mod : design->selected_modules()) for (auto cell : mod->selected_cells()) - if (cell->type == ID($macc)) { + if (cell->type.in(ID($macc), ID($macc_v2))) { log("Mapping %s.%s (%s).\n", log_id(mod), log_id(cell), log_id(cell->type)); maccmap(mod, cell, unmap_mode); mod->remove(cell); diff --git a/tests/alumacc/macc_infer_n_unmap.ys b/tests/alumacc/macc_infer_n_unmap.ys new file mode 100644 index 00000000000..569511b64d0 --- /dev/null +++ b/tests/alumacc/macc_infer_n_unmap.ys @@ -0,0 +1,19 @@ +read_verilog <