macc_v2: Start new cell

This commit is contained in:
Martin Povišer 2024-12-13 19:01:41 +01:00
parent 08394c51a2
commit c5fd96ebb0
5 changed files with 119 additions and 37 deletions

View File

@ -276,3 +276,7 @@ X(Y)
X(Y_WIDTH) X(Y_WIDTH)
X(area) X(area)
X(capacitance) X(capacitance)
X(NTERMS)
X(TERM_NEGATED)
X(A_WIDTHS)
X(B_WIDTHS)

View File

@ -82,7 +82,7 @@ struct Macc
new_ports.swap(ports); 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); RTLIL::SigSpec port_a = cell->getPort(ID::A);
@ -136,52 +136,82 @@ struct Macc
log_assert(port_a_cursor == GetSize(port_a)); 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; if (cell->type == ID($macc)) {
std::vector<RTLIL::State> config_bits; from_cell_v1(cell);
int max_size = 0, num_bits = 0; return;
for (auto &port : ports) {
max_size = max(max_size, GetSize(port.in_a));
max_size = max(max_size, GetSize(port.in_b));
} }
log_assert(cell->type == ID($macc_v2));
while (max_size) RTLIL::SigSpec port_a = cell->getPort(ID::A);
num_bits++, max_size /= 2; RTLIL::SigSpec port_b = cell->getPort(ID::B);
log_assert(num_bits < 16); ports.clear();
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);
for (auto &port : ports) int nterms = cell->getParam(ID::NTERMS).as_int();
{ const Const &neg = cell->getParam(ID::TERM_NEGATED);
if (GetSize(port.in_a) == 0) const Const &a_widths = cell->getParam(ID::A_WIDTHS);
continue; 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);
config_bits.push_back(port.is_signed ? State::S1 : State::S0); int ai = 0, bi = 0;
config_bits.push_back(port.do_subtract ? State::S1 : State::S0); for (int i = 0; i < nterms; i++) {
port_t term;
int size_a = GetSize(port.in_a); log_assert(a_signed[i] == b_signed[i]);
for (int i = 0; i < num_bits; i++) term.is_signed = (a_signed[i] == State::S1);
config_bits.push_back(size_a & (1 << i) ? State::S1 : State::S0); int a_width = a_widths.extract(16 * i, 16).as_int(false);
int b_width = b_widths.extract(16 * i, 16).as_int(false);
int size_b = GetSize(port.in_b); term.in_a = port_a.extract(ai, a_width);
for (int i = 0; i < num_bits; i++) ai += a_width;
config_bits.push_back(size_b & (1 << i) ? State::S1 : State::S0); term.in_b = port_b.extract(bi, b_width);
bi += b_width;
term.do_subtract = (neg[i] == State::S1);
port_a.append(port.in_a); ports.push_back(term);
port_a.append(port.in_b);
} }
log_assert(port_a.size() == ai);
log_assert(port_b.size() == bi);
}
cell->setPort(ID::A, port_a); void to_cell(RTLIL::Cell *cell)
cell->setPort(ID::B, {}); {
cell->setParam(ID::CONFIG, config_bits); cell->type = ID($macc_v2);
cell->setParam(ID::CONFIG_WIDTH, GetSize(config_bits));
cell->setParam(ID::A_WIDTH, GetSize(port_a)); int nterms = ports.size();
cell->setParam(ID::B_WIDTH, 0); 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;
for (int i = 0; i < nterms; 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);
}
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 bool eval(RTLIL::Const &result) const

View File

@ -1467,6 +1467,30 @@ namespace {
return; 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)) { if (cell->type == ID($logic_not)) {
param_bool(ID::A_SIGNED); param_bool(ID::A_SIGNED);
port(ID::A, param(ID::A_WIDTH)); 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; 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)); bool signedness_ab = !type.in(ID($slice), ID($concat), ID($macc));
if (connections_.count(ID::A)) { if (connections_.count(ID::A)) {

View File

@ -403,7 +403,7 @@ struct MaccmapPass : public Pass {
for (auto mod : design->selected_modules()) for (auto mod : design->selected_modules())
for (auto cell : mod->selected_cells()) 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)); log("Mapping %s.%s (%s).\n", log_id(mod), log_id(cell), log_id(cell->type));
maccmap(mod, cell, unmap_mode); maccmap(mod, cell, unmap_mode);
mod->remove(cell); mod->remove(cell);

View File

@ -0,0 +1,19 @@
read_verilog <<EOF
module gate(input signed [2:0] a1, input signed [2:0] b1,
input [1:0] a2, input [3:0] b2, input c, input d, output signed [3:0] y);
wire signed [3:0] ab1;
assign ab1 = a1 * b1;
assign y = ab1 + a2*b2 + c + d + 1;
endmodule
EOF
prep
design -save gold
alumacc
opt_clean
select -assert-count 1 t:$macc_v2
maccmap -unmap
design -copy-from gold -as gold gate
equiv_make gold gate equiv
equiv_induct equiv
equiv_status -assert equiv