mirror of https://github.com/YosysHQ/yosys.git
macc_v2: Start new cell
This commit is contained in:
parent
08394c51a2
commit
c5fd96ebb0
|
@ -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)
|
||||||
|
|
102
kernel/macc.h
102
kernel/macc.h
|
@ -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
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
Loading…
Reference in New Issue