41 std::vector<RTLIL::Cell*>
cells;
43 std::vector<std::tuple<bool, bool, bool, bool, RTLIL::SigSpec>>
cmp;
103 std::map<RTLIL::SigSig, std::set<alunode_t*>>
sig_alu;
119 for (
auto &conn : cell->connections())
120 for (
auto bit :
sigmap(conn.second))
128 if (!cell->type.in(
"$pos",
"$neg",
"$add",
"$sub",
"$mul"))
131 log(
" creating $macc model for %s (%s).\n",
log_id(cell),
log_id(cell->type));
137 n->
y =
sigmap(cell->getPort(
"\\Y"));
140 for (
auto bit : n->
y)
143 if (cell->type.in(
"$pos",
"$neg"))
146 new_port.
is_signed = cell->getParam(
"\\A_SIGNED").as_bool();
151 if (cell->type.in(
"$add",
"$sub"))
154 new_port.
is_signed = cell->getParam(
"\\A_SIGNED").as_bool();
159 new_port.
is_signed = cell->getParam(
"\\B_SIGNED").as_bool();
164 if (cell->type.in(
"$mul"))
168 new_port.
is_signed = cell->getParam(
"\\A_SIGNED").as_bool();
180 std::vector<int> port_sizes;
182 for (
auto &port : macc.
ports) {
183 if (port.is_signed != is_signed)
185 if (!port.is_signed && port.do_subtract)
190 port_sizes.push_back(
GetSize(port.in_a));
193 std::sort(port_sizes.begin(), port_sizes.end());
195 int acc_sum = 0, acc_shift = 0;
196 for (
int sz : port_sizes) {
197 while ((sz - acc_shift) > 20) {
200 acc_sum = acc_sum >> 1;
203 acc_sum += (1 << (sz - acc_shift)) - 1;
207 acc_sum = acc_sum >> 1;
211 return acc_shift > width;
218 std::set<maccnode_t*> delete_nodes;
224 if (delete_nodes.count(
n))
227 for (
int i = 0; i <
GetSize(
n->macc.ports); i++)
229 auto &port =
n->macc.ports[i];
231 if (
GetSize(port.in_b) > 0 || sig_macc.count(port.in_a) == 0)
234 auto other_n = sig_macc.at(port.in_a);
236 if (other_n->users > 1)
242 log(
" merging $macc model for %s into %s.\n",
log_id(other_n->cell),
log_id(
n->cell));
244 bool do_subtract = port.do_subtract;
245 for (
int j = 0; j <
GetSize(other_n->macc.ports); j++) {
247 other_n->macc.ports[j].do_subtract = !other_n->macc.ports[j].do_subtract;
249 n->macc.ports[i--] = other_n->macc.ports[j];
251 n->macc.ports.push_back(other_n->macc.ports[j]);
254 delete_nodes.insert(other_n);
258 if (delete_nodes.empty())
261 for (
auto n : delete_nodes) {
262 sig_macc.erase(
n->y);
270 std::set<maccnode_t*> delete_nodes;
276 bool a_signed =
false, b_signed =
false;
277 bool subtract_b =
false;
280 for (
auto &port :
n->macc.ports)
283 }
else if (
GetSize(port.in_a) == 1 && !port.is_signed && !port.do_subtract) {
285 }
else if (
GetSize(A) || port.do_subtract) {
289 b_signed = port.is_signed;
290 subtract_b = port.do_subtract;
295 a_signed = port.is_signed;
298 if (!a_signed || !b_signed) {
303 if (a_signed != b_signed)
323 if (!subtract_b && B < A &&
GetSize(B))
326 log(
" creating $alu model for $macc %s.\n",
log_id(
n->cell));
329 alunode->
cells.push_back(
n->cell);
339 delete_nodes.insert(
n);
343 for (
auto n : delete_nodes) {
344 sig_macc.erase(
n->y);
360 n->macc.to_cell(cell);
361 cell->setPort(
"\\Y",
n->y);
362 cell->fixup_parameters();
372 std::vector<RTLIL::Cell*> lge_cells, eq_cells;
376 if (cell->type.in(
"$lt",
"$le",
"$ge",
"$gt"))
377 lge_cells.push_back(cell);
378 if (cell->type.in(
"$eq",
"$eqx",
"$ne",
"$nex"))
379 eq_cells.push_back(cell);
382 for (
auto cell : lge_cells)
384 log(
" creating $alu model for %s (%s):",
log_id(cell),
log_id(cell->type));
386 bool cmp_less = cell->type.in(
"$lt",
"$le");
387 bool cmp_equal = cell->type.in(
"$le",
"$ge");
388 bool is_signed = cell->getParam(
"\\A_SIGNED").as_bool();
395 cmp_less = !cmp_less;
402 if (node->is_signed == is_signed && node->invert_b && node->c ==
RTLIL::S1) {
421 n->
cells.push_back(cell);
422 n->
cmp.push_back(std::make_tuple(cmp_less, !cmp_less, cmp_equal,
false, Y));
425 for (
auto cell : eq_cells)
427 bool cmp_equal = cell->type.in(
"$eq",
"$eqx");
428 bool is_signed = cell->getParam(
"\\A_SIGNED").as_bool();
440 if (node->is_signed == is_signed && node->invert_b && node->c ==
RTLIL::S1) {
447 n->
cells.push_back(cell);
448 n->
cmp.push_back(std::make_tuple(
false,
false, cmp_equal, !cmp_equal, Y));
456 for (
auto n : it1.second)
462 log(
" creating $pos cell for ");
463 for (
int i = 0; i <
GetSize(
n->cells); i++)
464 log(
"%s%s", i ?
", ":
"",
log_id(
n->cells[i]));
473 log(
" creating $alu cell for ");
474 for (
int i = 0; i <
GetSize(
n->cells); i++)
475 log(
"%s%s", i ?
", ":
"",
log_id(
n->cells[i]));
478 n->alu_cell->setPort(
"\\A",
n->a);
479 n->alu_cell->setPort(
"\\B",
n->b);
482 n->alu_cell->setPort(
"\\Y",
n->y);
485 n->alu_cell->fixup_parameters(
n->is_signed,
n->is_signed);
487 for (
auto &it :
n->cmp)
489 bool cmp_lt = std::get<0>(it);
490 bool cmp_gt = std::get<1>(it);
491 bool cmp_eq = std::get<2>(it);
492 bool cmp_ne = std::get<3>(it);
496 if (cmp_lt) sig.
append(
n->get_lt());
497 if (cmp_gt) sig.append(
n->get_gt());
498 if (cmp_eq) sig.append(
n->get_eq());
499 if (cmp_ne) sig.append(
n->get_ne());
509 for (
auto c :
n->cells)
519 log(
"Extracting $alu and $macc cells in module %s:\n",
log_id(
module));
539 log(
" alumacc [selection]\n");
541 log(
"This pass translates arithmetic operations like $add, $mul, $lt, etc. to $alu\n");
542 log(
"and $macc cells.\n");
547 log_header(
"Executing ALUMACC pass (create $alu and $macc cells).\n");
550 for (argidx = 1; argidx < args.size(); argidx++) {
560 if (!mod->has_processes_warn()) {
RTLIL::Wire * wire(RTLIL::IdString id)
void sort(T *array, int size, LessThan lt)
RTLIL::Cell * addCell(RTLIL::IdString name, RTLIL::IdString type)
void log_header(const char *format,...)
AlumaccWorker(RTLIL::Module *module)
std::vector< port_t > ports
void remove(const RTLIL::SigSpec &pattern)
static bool macc_may_overflow(Macc &macc, int width, bool is_signed)
RTLIL::SigSpec Or(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed=false)
std::map< RTLIL::SigSpec, maccnode_t * > sig_macc
void connect(const RTLIL::SigSig &conn)
std::vector< RTLIL::IdString > ports
std::map< RTLIL::SigBit, int > bit_users
#define PRIVATE_NAMESPACE_BEGIN
const RTLIL::SigSpec & getPort(RTLIL::IdString portname) const
int GetSize(RTLIL::Wire *wire)
RTLIL::SigSpec Xor(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed=false)
#define log_assert(_assert_expr_)
RTLIL::Wire * addWire(RTLIL::IdString name, int width=1)
std::vector< RTLIL::Cell * > selected_cells() const
std::map< RTLIL::SigSig, std::set< alunode_t * > > sig_alu
#define PRIVATE_NAMESPACE_END
#define USING_YOSYS_NAMESPACE
RTLIL::ObjRange< RTLIL::Cell * > cells()
void remove(const std::set< RTLIL::Wire * > &wires)
RTLIL::SigSpec ReduceOr(RTLIL::IdString name, RTLIL::SigSpec sig_a, bool is_signed=false)
void log(const char *format,...)
std::vector< RTLIL::Cell * > cells
void append(const RTLIL::SigSpec &signal)
std::vector< RTLIL::Module * > selected_modules() const
void extend(int width, bool is_signed=false)
std::vector< std::tuple< bool, bool, bool, bool, RTLIL::SigSpec > > cmp
RTLIL::Cell * addPos(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, bool is_signed=false)
void extra_args(std::vector< std::string > args, size_t argidx, RTLIL::Design *design, bool select=true)
std::pair< SigSpec, SigSpec > SigSig
RTLIL::SigSpec Not(RTLIL::IdString name, RTLIL::SigSpec sig_a, bool is_signed=false)
const char * log_id(RTLIL::IdString str)
RTLIL::SigSpec ReduceAnd(RTLIL::IdString name, RTLIL::SigSpec sig_a, bool is_signed=false)
virtual void execute(std::vector< std::string > args, RTLIL::Design *design)