Skip to content

Commit

Permalink
macc_v2: Start new cell
Browse files Browse the repository at this point in the history
  • Loading branch information
povik committed Dec 13, 2024
1 parent fdc3e4b commit abdeac3
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 38 deletions.
4 changes: 4 additions & 0 deletions kernel/constids.inc
Original file line number Diff line number Diff line change
Expand Up @@ -276,3 +276,7 @@ X(Y)
X(Y_WIDTH)
X(area)
X(capacitance)
X(NTERMS)
X(TERM_NEGATED)
X(A_WIDTHS)
X(B_WIDTHS)
104 changes: 67 additions & 37 deletions kernel/macc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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<RTLIL::State> 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
Expand Down
29 changes: 29 additions & 0 deletions kernel/rtlil.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down Expand Up @@ -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)) {
Expand Down
2 changes: 1 addition & 1 deletion passes/techmap/maccmap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
19 changes: 19 additions & 0 deletions tests/alumacc/macc_infer_n_unmap.ys
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit abdeac3

Please sign in to comment.