28 std::vector<std::set<RTLIL::SigBit>>
bits;
42 if (
bits.at(position).count(bit)) {
43 bits.at(position).erase(bit);
46 bits.at(position).insert(bit);
59 for (
int i = 0; i <
width; i++)
73 for (
int i = 0; i <
GetSize(b); i++)
74 if (is_signed && i+1 ==
GetSize(b))
89 int start_index = 0, stop_index =
GetSize(in1);
94 while (start_index < stop_index && in1[stop_index-1] ==
RTLIL::S0 && in2[stop_index-1] ==
RTLIL::S0 && in3[stop_index-1] ==
RTLIL::S0)
97 if (start_index == stop_index)
106 in1 = in1.
extract(start_index, stop_index-start_index);
107 in2 = in2.
extract(start_index, stop_index-start_index);
108 in3 = in3.
extract(start_index, stop_index-start_index);
122 out1 = {out_zeros_msb, w1, out_zeros_lsb};
123 out2 = {out_zeros_msb, w2, out_zeros_lsb};
133 n = 2*(n / 3) + (n % 3);
137 return std::max(n - 1, 0);
143 std::vector<RTLIL::SigSpec> summands;
144 std::vector<RTLIL::SigBit> tree_sum_bits;
145 int unique_tree_bits = 0;
146 int count_tree_words = 0;
151 bool got_data_bits =
false;
153 for (
int i = 0; i <
width; i++)
154 if (!
bits.at(i).empty()) {
155 auto it =
bits.at(i).begin();
157 bits.at(i).erase(it);
158 got_data_bits =
true;
164 summands.push_back(summand);
170 int max_depth = 0, max_position = 0;
171 for (
int i = 0; i <
width; i++)
177 if (max_depth == 0 || max_position > 4)
180 int required_bits = 0;
181 for (
int i = 0; i <= max_position; i++)
183 required_bits += 1 << i;
185 if (required_bits > free_bit_slots)
188 for (
int i = 0; i <= max_position; i++)
190 auto it =
bits.at(i).begin();
192 for (
int k = 0; k < (1 << i); k++, free_bit_slots--)
193 tree_sum_bits.push_back(bit);
194 bits.at(i).erase(it);
202 if (!tree_sum_bits.empty())
203 log(
" packed %d (%d) bits / %d words into adder tree\n",
GetSize(tree_sum_bits), unique_tree_bits, count_tree_words);
212 return summands.front();
217 std::vector<RTLIL::SigSpec> new_summands;
218 for (
int i = 0; i <
GetSize(summands); i += 3)
224 fulladd(in1, in2, in3, out1, out2);
226 if (!tree_sum_bits.empty()) {
227 extra_bit = tree_sum_bits.back();
228 tree_sum_bits.pop_back();
230 new_summands.push_back(out1);
231 new_summands.push_back({out2.
extract(0,
width-1), extra_bit});
233 new_summands.push_back(summands[i]);
236 summands.swap(new_summands);
241 c->
setPort(
"\\A", summands.front());
242 c->
setPort(
"\\B", summands.back());
250 if (!tree_sum_bits.empty()) {
251 c->
setPort(
"\\CI", tree_sum_bits.back());
252 tree_sum_bits.pop_back();
281 for (
auto &port : macc.ports)
283 log(
" %s %s (%d bits, %s)\n", port.do_subtract ?
"sub" :
"add",
log_signal(port.in_a),
284 GetSize(port.in_a), port.is_signed ?
"signed" :
"unsigned");
286 log(
" %s %s * %s (%dx%d bits, %s)\n", port.do_subtract ?
"sub" :
"add",
log_signal(port.in_a),
log_signal(port.in_b),
287 GetSize(port.in_a),
GetSize(port.in_b), port.is_signed ?
"signed" :
"unsigned");
289 if (
GetSize(macc.bit_ports) != 0)
294 typedef std::pair<RTLIL::SigSpec, bool> summand_t;
295 std::vector<summand_t> summands;
297 for (
auto &port : macc.ports) {
298 summand_t this_summand;
301 module->
addMul(
NEW_ID, port.in_a, port.in_b, this_summand.first, port.is_signed);
302 }
else if (
GetSize(port.in_a) != width) {
304 module->
addPos(
NEW_ID, port.in_a, this_summand.first, port.is_signed);
306 this_summand.first = port.in_a;
308 this_summand.second = port.do_subtract;
309 summands.push_back(this_summand);
312 for (
auto &bit : macc.bit_ports)
313 summands.push_back(summand_t(bit,
false));
320 std::vector<summand_t> new_summands;
321 for (
int i = 0; i <
GetSize(summands); i += 2) {
323 summand_t this_summand;
325 this_summand.second = summands[i].second && summands[i+1].second;
326 if (summands[i].second == summands[i+1].second)
327 module->
addAdd(
NEW_ID, summands[i].first, summands[i+1].first, this_summand.first);
328 else if (summands[i].second)
329 module->
addSub(
NEW_ID, summands[i+1].first, summands[i].first, this_summand.first);
330 else if (summands[i+1].second)
331 module->
addSub(
NEW_ID, summands[i].first, summands[i+1].first, this_summand.first);
334 new_summands.push_back(this_summand);
336 new_summands.push_back(summands[i]);
338 summands.swap(new_summands);
341 if (summands.front().second)
350 for (
auto &port : macc.ports)
352 worker.
add(port.in_a, port.is_signed, port.do_subtract);
354 worker.
add(port.in_a, port.in_b, port.is_signed, port.do_subtract);
356 for (
auto &bit : macc.bit_ports)
372 log(
" maccmap [-unmap] [selection]\n");
374 log(
"This pass maps $macc cells to yosys gate primitives. When the -unmap option is\n");
375 log(
"used then the $macc cell is mapped to $and, $sub, etc. cells instead.\n");
380 bool unmap_mode =
false;
382 log_header(
"Executing MACCMAP pass (map $macc cells).\n");
385 for (argidx = 1; argidx < args.size(); argidx++) {
386 if (args[argidx] ==
"-unmap") {
395 for (
auto cell : mod->selected_cells())
396 if (cell->type ==
"$macc") {
398 maccmap(mod, cell, unmap_mode);
void fixup_parameters(bool set_a_signed=false, bool set_b_signed=false)
void add(RTLIL::SigSpec a, RTLIL::SigSpec b, bool is_signed, bool do_subtract)
int tree_bit_slots(int n)
void add(RTLIL::SigSpec a, bool is_signed, bool do_subtract)
RTLIL::Cell * addCell(RTLIL::IdString name, RTLIL::IdString type)
void log_header(const char *format,...)
void setParam(RTLIL::IdString paramname, RTLIL::Const value)
#define YOSYS_NAMESPACE_END
std::set< RTLIL::SigBit > to_sigbit_set() const
const char * log_signal(const RTLIL::SigSpec &sig, bool autoint)
void setPort(RTLIL::IdString portname, RTLIL::SigSpec signal)
PRIVATE_NAMESPACE_END YOSYS_NAMESPACE_BEGIN void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap=false)
RTLIL::Cell * addAdd(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed=false)
virtual void execute(std::vector< std::string > args, RTLIL::Design *design)
RTLIL::Cell * addNeg(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, bool is_signed=false)
void fulladd(RTLIL::SigSpec &in1, RTLIL::SigSpec &in2, RTLIL::SigSpec &in3, RTLIL::SigSpec &out1, RTLIL::SigSpec &out2)
MaccmapWorker(RTLIL::Module *module, int width)
void connect(const RTLIL::SigSig &conn)
#define PRIVATE_NAMESPACE_BEGIN
const RTLIL::SigSpec & getPort(RTLIL::IdString portname) const
int GetSize(RTLIL::Wire *wire)
#define log_assert(_assert_expr_)
RTLIL::Wire * addWire(RTLIL::IdString name, int width=1)
RTLIL::Cell * addMul(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed=false)
void from_cell(RTLIL::Cell *cell)
RTLIL::Cell * addSub(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed=false)
#define PRIVATE_NAMESPACE_END
#define USING_YOSYS_NAMESPACE
#define YOSYS_NAMESPACE_BEGIN
void log(const char *format,...)
RTLIL::SigSpec extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other=NULL) const
RTLIL::SigSpec And(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed=false)
void append(const RTLIL::SigSpec &signal)
std::vector< RTLIL::Module * > selected_modules() const
void extend(int width, bool is_signed=false)
std::vector< std::set< RTLIL::SigBit > > bits
void add(RTLIL::SigBit bit, int position)
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)
RTLIL::SigSpec Not(RTLIL::IdString name, RTLIL::SigSpec sig_a, bool is_signed=false)
const char * log_id(RTLIL::IdString str)