From 0c7afe8e3187b08008242d73100deb61aa2e6447 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Mon, 12 Jan 2026 13:21:13 +0100 Subject: [PATCH] Widen $polarity cell to multiple ports --- kernel/calc.cc | 29 ++++++++++++----------- kernel/celltypes.h | 2 +- kernel/constids.inc | 1 + kernel/rtlil.cc | 10 ++++---- kernel/rtlil.h | 2 +- kernel/satgen.cc | 49 +++++++++++++++++++++------------------ passes/tests/test_cell.cc | 10 +++++--- techlibs/common/techmap.v | 29 ++++++++++++----------- 8 files changed, 74 insertions(+), 58 deletions(-) diff --git a/kernel/calc.cc b/kernel/calc.cc index a1ba5f7c8..589fd4aa7 100644 --- a/kernel/calc.cc +++ b/kernel/calc.cc @@ -658,22 +658,25 @@ RTLIL::Const RTLIL::const_bmux(const RTLIL::Const &arg1, const RTLIL::Const &arg return t; } -RTLIL::Const RTLIL::const_priority(const RTLIL::Const &arg, const RTLIL::Const &polarity) +RTLIL::Const RTLIL::const_priority(const RTLIL::Const &arg, int p_width, const RTLIL::Const &polarity) { std::vector t; - std::optional first_non_zero = std::nullopt; - for (int i = 0; i < GetSize(arg); i++) + for (int offset = 0; offset < GetSize(arg); offset += p_width) { - RTLIL::State s = arg.at(i); - if (first_non_zero && s != State::Sx) { - auto inactive = polarity[i] == State::S0 ? State::S1 : State::S0; - auto val = *first_non_zero == State::Sx ? State::Sx : inactive; - t.push_back(val); - } else { - t.push_back(s); - } - if ((!first_non_zero && s == polarity[i]) || s == State::Sx) { - first_non_zero = s; + std::optional first_non_zero = std::nullopt; + for (int i = offset; i < offset + p_width; i++) + { + RTLIL::State s = arg.at(i); + if (first_non_zero && s != State::Sx) { + auto inactive = polarity[i] == State::S0 ? State::S1 : State::S0; + auto val = *first_non_zero == State::Sx ? State::Sx : inactive; + t.push_back(val); + } else { + t.push_back(s); + } + if ((!first_non_zero && s == polarity[i]) || s == State::Sx) { + first_non_zero = s; + } } } return t; diff --git a/kernel/celltypes.h b/kernel/celltypes.h index 8423deadc..0f15ca61d 100644 --- a/kernel/celltypes.h +++ b/kernel/celltypes.h @@ -511,7 +511,7 @@ struct CellTypes if (cell->type == ID($priority)) { - return const_priority(arg1, cell->getParam(ID::POLARITY)); + return const_priority(arg1, cell->getParam(ID::P_WIDTH).as_int(), cell->getParam(ID::POLARITY)); } bool signed_a = cell->parameters.count(ID::A_SIGNED) > 0 && cell->parameters[ID::A_SIGNED].as_bool(); diff --git a/kernel/constids.inc b/kernel/constids.inc index 250c8688c..e189d804d 100644 --- a/kernel/constids.inc +++ b/kernel/constids.inc @@ -680,6 +680,7 @@ X(PRODUCT_NEGATED) X(P_BYPASS) X(P_EN) X(P_SRST_N) +X(P_WIDTH) X(Q) X(QL_DSP2) X(R) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 65d11cdb2..4eef695a3 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -2648,9 +2648,10 @@ namespace { } if (cell->type.in(ID($priority))) { param(ID::WIDTH); + param(ID::P_WIDTH); param(ID::POLARITY); - port(ID::A, param(ID::WIDTH)); - port(ID::Y, param(ID::WIDTH)); + port(ID::A, param(ID::P_WIDTH)*param(ID::WIDTH)); + port(ID::Y, param(ID::P_WIDTH)*param(ID::WIDTH)); check_expected(); return; } @@ -4501,7 +4502,8 @@ void RTLIL::Cell::check() void RTLIL::Cell::fixup_parameters(bool set_a_signed, bool set_b_signed) { if (!type.begins_with("$") || type.begins_with("$_") || type.begins_with("$paramod") || type.begins_with("$fmcombine") || - type.begins_with("$verific$") || type.begins_with("$array:") || type.begins_with("$extern:")) + type.begins_with("$verific$") || type.begins_with("$array:") || type.begins_with("$extern:")|| + type.begins_with("$priority")) return; if (type == ID($buf) || type == ID($mux) || type == ID($pmux) || type == ID($bmux) || type == ID($bwmux) || type == ID($bweqx)) { @@ -4519,7 +4521,7 @@ void RTLIL::Cell::fixup_parameters(bool set_a_signed, bool set_b_signed) return; } - if (type == ID($lut) || type == ID($sop) || type == ID($priority)) { + if (type == ID($lut) || type == ID($sop)) { parameters[ID::WIDTH] = GetSize(connections_[ID::A]); return; } diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 747ffa811..f65229ee0 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -848,7 +848,7 @@ namespace RTLIL { RTLIL::Const const_pmux (const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3); RTLIL::Const const_bmux (const RTLIL::Const &arg1, const RTLIL::Const &arg2); RTLIL::Const const_demux (const RTLIL::Const &arg1, const RTLIL::Const &arg2); - RTLIL::Const const_priority (const RTLIL::Const &arg, const RTLIL::Const &polarity); + RTLIL::Const const_priority (const RTLIL::Const &arg, int p_width, const RTLIL::Const &polarity); RTLIL::Const const_bweqx (const RTLIL::Const &arg1, const RTLIL::Const &arg2); RTLIL::Const const_bwmux (const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3); diff --git a/kernel/satgen.cc b/kernel/satgen.cc index c608a0c19..c9c0fed4f 100644 --- a/kernel/satgen.cc +++ b/kernel/satgen.cc @@ -437,32 +437,35 @@ bool SatGen::importCell(RTLIL::Cell *cell, int timestep) std::vector yy = model_undef ? ez->vec_var(y.size()) : y; const Const& polarity = cell->getParam(ID::POLARITY); + int p_width = cell->getParam(ID::P_WIDTH).as_int(); - int any_previous_active; - if (a.size()) { - any_previous_active = polarity[0] ? a[0] : ez->NOT(a[0]); - ez->assume(ez->IFF(yy[0], a[0])); - } - for (size_t i = 1; i < a.size(); i++) { - int inactive_val = !polarity[i] ? ez->CONST_TRUE : ez->CONST_FALSE; - int active_val = polarity[i] ? ez->CONST_TRUE : ez->CONST_FALSE; - ez->assume(ez->IFF(yy[i], ez->ITE(any_previous_active, inactive_val, a[i]))); - any_previous_active = ez->OR(any_previous_active, ez->IFF(a[i], active_val)); - } - if (model_undef) { - std::vector undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep); - std::vector undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep); + for (size_t offset = 0; offset < a.size(); offset += p_width) { + int any_previous_active; + if (p_width) { + any_previous_active = polarity[offset] ? a[offset] : ez->NOT(a[offset]); + ez->assume(ez->IFF(yy[offset], a[offset])); + } + for (size_t i = offset + 1; i < offset + p_width; i++) { + int inactive_val = !polarity[i] ? ez->CONST_TRUE : ez->CONST_FALSE; + int active_val = polarity[i] ? ez->CONST_TRUE : ez->CONST_FALSE; + ez->assume(ez->IFF(yy[i], ez->ITE(any_previous_active, inactive_val, a[i]))); + any_previous_active = ez->OR(any_previous_active, ez->IFF(a[i], active_val)); + } + if (model_undef) { + std::vector undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep); + std::vector undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep); - int any_previous_undef; - if (a.size()) { - any_previous_undef = undef_a[0]; - ez->assume(ez->IFF(undef_y[0], undef_a[0])); + int any_previous_undef; + if (p_width) { + any_previous_undef = undef_a[offset]; + ez->assume(ez->IFF(undef_y[offset], undef_a[offset])); + } + for (size_t i = offset + 1; i < offset + p_width; i++) { + any_previous_undef = ez->OR(any_previous_undef, undef_a[i]); + ez->assume(ez->IFF(undef_y[i], any_previous_undef)); + } + undefGating(y, yy, undef_y); } - for (size_t i = 1; i < a.size(); i++) { - any_previous_undef = ez->OR(any_previous_undef, undef_a[i]); - ez->assume(ez->IFF(undef_y[i], any_previous_undef)); - } - undefGating(y, yy, undef_y); } return true; diff --git a/passes/tests/test_cell.cc b/passes/tests/test_cell.cc index b8a4f8d93..a3faf3945 100644 --- a/passes/tests/test_cell.cc +++ b/passes/tests/test_cell.cc @@ -138,24 +138,28 @@ static RTLIL::Cell* create_gold_module(RTLIL::Design *design, RTLIL::IdString ce if (cell_type == ID($priority)) { + int priority_width = 1 + xorshift32(8 * bloat_factor); int width = 1 + xorshift32(8 * bloat_factor); + int port_width = width * priority_width; wire = module->addWire(ID::A); - wire->width = width; + wire->width = port_width; wire->port_input = true; cell->setPort(ID::A, wire); wire = module->addWire(ID::Y); - wire->width = width; + wire->width = port_width; wire->port_output = true; cell->setPort(ID::Y, wire); RTLIL::SigSpec polarity; - for (int i = 0; i < width; i++) + for (int i = 0; i < port_width; i++) polarity.append(xorshift32(2) ? State::S1 : State::S0); cell->setParam(ID::POLARITY, polarity.as_const()); log("polarity: %s\n", log_signal(polarity)); + cell->setParam(ID::P_WIDTH, priority_width); + cell->setParam(ID::WIDTH, width); } if (cell_type == ID($fa)) diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index c8f4ec420..5b6665c92 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -683,30 +683,33 @@ endmodule (* techmap_celltype = "$priority" *) module \$priority (A, Y); parameter WIDTH = 0; + parameter P_WIDTH = 0; parameter POLARITY = 0; (* force_downto *) - input [WIDTH-1:0] A; + input [P_WIDTH*WIDTH-1:0] A; (* force_downto *) - output [WIDTH-1:0] Y; + output [P_WIDTH*WIDTH-1:0] Y; (* force_downto *) - wire [WIDTH-1:0] tmp; + wire [P_WIDTH*WIDTH-1:0] tmp; (* force_downto *) - wire [WIDTH-1:0] A_active; - wire [WIDTH-1:0] Y_active; + wire [P_WIDTH*WIDTH-1:0] A_active; + wire [P_WIDTH*WIDTH-1:0] Y_active; assign A_active = A ^ ~POLARITY; assign Y = Y_active ^ ~POLARITY; - genvar i; + genvar i, offset; generate - if (WIDTH > 0) begin - assign tmp[0] = A_active[0]; - assign Y_active[0] = A_active[0]; - end - for (i = 1; i < WIDTH; i = i + 1) begin - assign Y_active[i] = tmp[i-1] ? 1'b0 : A_active[i]; - assign tmp[i] = tmp[i-1] | A_active[i]; + for (offset = 0; offset < P_WIDTH*WIDTH; offset = offset + P_WIDTH) begin + if (P_WIDTH > 0) begin + assign tmp[offset] = A_active[offset]; + assign Y_active[offset] = A_active[offset]; + end + for (i = offset + 1; i < offset + P_WIDTH; i = i + 1) begin + assign Y_active[i] = tmp[i - 1] ? 1'b0 : A_active[i]; + assign tmp[i] = tmp[i - 1] | A_active[i]; + end end endgenerate