Merge pull request #1105 from YosysHQ/clifford/fixlogicinit
[yosys.git] / passes / techmap / extract_counter.cc
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2017 Clifford Wolf <clifford@clifford.at>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 */
19
20 #include "kernel/yosys.h"
21 #include "kernel/sigtools.h"
22 #include "kernel/modtools.h"
23
24 USING_YOSYS_NAMESPACE
25 PRIVATE_NAMESPACE_BEGIN
26
27 //get the list of cells hooked up to at least one bit of a given net
28 pool<Cell*> get_other_cells(const RTLIL::SigSpec& port, ModIndex& index, Cell* src)
29 {
30 pool<Cell*> rval;
31 for(auto b : port)
32 {
33 pool<ModIndex::PortInfo> ports = index.query_ports(b);
34 for(auto x : ports)
35 {
36 if(x.cell == src)
37 continue;
38 rval.insert(x.cell);
39 }
40 }
41 return rval;
42 }
43
44 //return true if there is a full-width bus connection from cell a port ap to cell b port bp
45 //if other_conns_allowed is false, then we require a strict point to point connection (no other links)
46 bool is_full_bus(
47 const RTLIL::SigSpec& sig,
48 ModIndex& index,
49 Cell* a,
50 RTLIL::IdString ap,
51 Cell* b,
52 RTLIL::IdString bp,
53 bool other_conns_allowed = false)
54 {
55 for(auto s : sig)
56 {
57 pool<ModIndex::PortInfo> ports = index.query_ports(s);
58 bool found_a = false;
59 bool found_b = false;
60 for(auto x : ports)
61 {
62 if( (x.cell == a) && (x.port == ap) )
63 found_a = true;
64 else if( (x.cell == b) && (x.port == bp) )
65 found_b = true;
66 else if(!other_conns_allowed)
67 return false;
68 }
69
70 if( (!found_a) || (!found_b) )
71 return false;
72 }
73
74 return true;
75 }
76
77 //return true if the signal connects to one port only (nothing on the other end)
78 bool is_unconnected(const RTLIL::SigSpec& port, ModIndex& index)
79 {
80 for(auto b : port)
81 {
82 pool<ModIndex::PortInfo> ports = index.query_ports(b);
83 if(ports.size() > 1)
84 return false;
85 }
86
87 return true;
88 }
89
90 struct CounterExtraction
91 {
92 int width; //counter width
93 RTLIL::Wire* rwire; //the register output
94 bool has_reset; //true if we have a reset
95 bool has_ce; //true if we have a clock enable
96 RTLIL::SigSpec rst; //reset pin
97 bool rst_inverted; //true if reset is active low
98 bool rst_to_max; //true if we reset to max instead of 0
99 int count_value; //value we count from
100 RTLIL::SigSpec ce; //clock signal
101 RTLIL::SigSpec clk; //clock enable, if any
102 RTLIL::SigSpec outsig; //counter output signal
103 RTLIL::Cell* count_mux; //counter mux
104 RTLIL::Cell* count_reg; //counter register
105 RTLIL::Cell* underflow_inv; //inverter reduction for output-underflow detect
106 pool<ModIndex::PortInfo> pouts; //Ports that take a parallel output from us
107 };
108
109 //attempt to extract a counter centered on the given adder cell
110 //For now we only support DOWN counters.
111 //TODO: up/down support
112 int counter_tryextract(
113 ModIndex& index,
114 Cell *cell,
115 CounterExtraction& extract,
116 pool<RTLIL::IdString>& parallel_cells,
117 int maxwidth)
118 {
119 SigMap& sigmap = index.sigmap;
120
121 //A counter with less than 2 bits makes no sense
122 //TODO: configurable min threshold
123 int a_width = cell->getParam("\\A_WIDTH").as_int();
124 extract.width = a_width;
125 if( (a_width < 2) || (a_width > maxwidth) )
126 return 1;
127
128 //Second input must be a single bit
129 int b_width = cell->getParam("\\B_WIDTH").as_int();
130 if(b_width != 1)
131 return 2;
132
133 //Both inputs must be unsigned, so don't extract anything with a signed input
134 bool a_sign = cell->getParam("\\A_SIGNED").as_bool();
135 bool b_sign = cell->getParam("\\B_SIGNED").as_bool();
136 if(a_sign || b_sign)
137 return 3;
138
139 //To be a counter, one input of the ALU must be a constant 1
140 //TODO: can A or B be swapped in synthesized RTL or is B always the 1?
141 const RTLIL::SigSpec b_port = sigmap(cell->getPort("\\B"));
142 if(!b_port.is_fully_const() || (b_port.as_int() != 1) )
143 return 4;
144
145 //BI and CI must be constant 1 as well
146 const RTLIL::SigSpec bi_port = sigmap(cell->getPort("\\BI"));
147 if(!bi_port.is_fully_const() || (bi_port.as_int() != 1) )
148 return 5;
149 const RTLIL::SigSpec ci_port = sigmap(cell->getPort("\\CI"));
150 if(!ci_port.is_fully_const() || (ci_port.as_int() != 1) )
151 return 6;
152
153 //CO and X must be unconnected (exactly one connection to each port)
154 if(!is_unconnected(sigmap(cell->getPort("\\CO")), index))
155 return 7;
156 if(!is_unconnected(sigmap(cell->getPort("\\X")), index))
157 return 8;
158
159 //Y must have exactly one connection, and it has to be a $mux cell.
160 //We must have a direct bus connection from our Y to their A.
161 const RTLIL::SigSpec aluy = sigmap(cell->getPort("\\Y"));
162 pool<Cell*> y_loads = get_other_cells(aluy, index, cell);
163 if(y_loads.size() != 1)
164 return 9;
165 Cell* count_mux = *y_loads.begin();
166 extract.count_mux = count_mux;
167 if(count_mux->type != "$mux")
168 return 10;
169 if(!is_full_bus(aluy, index, cell, "\\Y", count_mux, "\\A"))
170 return 11;
171
172 //B connection of the mux is our underflow value
173 const RTLIL::SigSpec underflow = sigmap(count_mux->getPort("\\B"));
174 if(!underflow.is_fully_const())
175 return 12;
176 extract.count_value = underflow.as_int();
177
178 //S connection of the mux must come from an inverter (need not be the only load)
179 const RTLIL::SigSpec muxsel = sigmap(count_mux->getPort("\\S"));
180 extract.outsig = muxsel;
181 pool<Cell*> muxsel_conns = get_other_cells(muxsel, index, count_mux);
182 Cell* underflow_inv = NULL;
183 for(auto c : muxsel_conns)
184 {
185 if(c->type != "$logic_not")
186 continue;
187 if(!is_full_bus(muxsel, index, c, "\\Y", count_mux, "\\S", true))
188 continue;
189
190 underflow_inv = c;
191 break;
192 }
193 if(underflow_inv == NULL)
194 return 13;
195 extract.underflow_inv = underflow_inv;
196
197 //Y connection of the mux must have exactly one load, the counter's internal register, if there's no clock enable
198 //If we have a clock enable, Y drives the B input of a mux. A of that mux must come from our register
199 const RTLIL::SigSpec muxy = sigmap(count_mux->getPort("\\Y"));
200 pool<Cell*> muxy_loads = get_other_cells(muxy, index, count_mux);
201 if(muxy_loads.size() != 1)
202 return 14;
203 Cell* muxload = *muxy_loads.begin();
204 Cell* count_reg = muxload;
205 Cell* cemux = NULL;
206 RTLIL::SigSpec cey;
207 if(muxload->type == "$mux")
208 {
209 //This mux is probably a clock enable mux.
210 //Find our count register (should be our only load)
211 cemux = muxload;
212 cey = sigmap(cemux->getPort("\\Y"));
213 pool<Cell*> cey_loads = get_other_cells(cey, index, cemux);
214 if(cey_loads.size() != 1)
215 return 24;
216 count_reg = *cey_loads.begin();
217
218 //Mux should have A driven by count Q, and B by muxy
219 //TODO: if A and B are swapped, CE polarity is inverted
220 if(sigmap(cemux->getPort("\\B")) != muxy)
221 return 24;
222 if(sigmap(cemux->getPort("\\A")) != sigmap(count_reg->getPort("\\Q")))
223 return 24;
224 if(sigmap(cemux->getPort("\\Y")) != sigmap(count_reg->getPort("\\D")))
225 return 24;
226
227 //Select of the mux is our clock enable
228 extract.has_ce = true;
229 extract.ce = sigmap(cemux->getPort("\\S"));
230 }
231 else
232 extract.has_ce = false;
233
234 extract.count_reg = count_reg;
235 if(count_reg->type == "$dff")
236 extract.has_reset = false;
237 else if(count_reg->type == "$adff")
238 {
239 extract.has_reset = true;
240
241 //Check polarity of reset - we may have to add an inverter later on!
242 extract.rst_inverted = (count_reg->getParam("\\ARST_POLARITY").as_int() != 1);
243
244 //Verify ARST_VALUE is zero or full scale
245 int rst_value = count_reg->getParam("\\ARST_VALUE").as_int();
246 if(rst_value == 0)
247 extract.rst_to_max = false;
248 else if(rst_value == extract.count_value)
249 extract.rst_to_max = true;
250 else
251 return 23;
252
253 //Save the reset
254 extract.rst = sigmap(count_reg->getPort("\\ARST"));
255 }
256 //TODO: support synchronous reset
257 else
258 return 15;
259
260 //Sanity check that we use the ALU output properly
261 if(extract.has_ce)
262 {
263 if(!is_full_bus(muxy, index, count_mux, "\\Y", cemux, "\\B"))
264 return 16;
265 if(!is_full_bus(cey, index, cemux, "\\Y", count_reg, "\\D"))
266 return 16;
267 }
268 else if(!is_full_bus(muxy, index, count_mux, "\\Y", count_reg, "\\D"))
269 return 16;
270
271 //TODO: Verify count_reg CLK_POLARITY is 1
272
273 //Register output must have exactly two loads, the inverter and ALU
274 //(unless we have a parallel output!)
275 //If we have a clock enable, 3 is OK
276 const RTLIL::SigSpec qport = count_reg->getPort("\\Q");
277 const RTLIL::SigSpec cnout = sigmap(qport);
278 pool<Cell*> cnout_loads = get_other_cells(cnout, index, count_reg);
279 unsigned int max_loads = 2;
280 if(extract.has_ce)
281 max_loads = 3;
282 if(cnout_loads.size() > max_loads)
283 {
284 for(auto c : cnout_loads)
285 {
286 if(c == underflow_inv)
287 continue;
288 if(c == cell)
289 continue;
290 if(c == muxload)
291 continue;
292
293 //If we specified a limited set of cells for parallel output, check that we only drive them
294 if(!parallel_cells.empty())
295 {
296 //Make sure we're in the whitelist
297 if( parallel_cells.find(c->type) == parallel_cells.end())
298 return 17;
299 }
300
301 //Figure out what port(s) are driven by it
302 //TODO: this can probably be done more efficiently w/o multiple iterations over our whole net?
303 for(auto b : qport)
304 {
305 pool<ModIndex::PortInfo> ports = index.query_ports(b);
306 for(auto x : ports)
307 {
308 if(x.cell != c)
309 continue;
310 extract.pouts.insert(ModIndex::PortInfo(c, x.port, 0));
311 }
312 }
313 }
314 }
315 if(!is_full_bus(cnout, index, count_reg, "\\Q", underflow_inv, "\\A", true))
316 return 18;
317 if(!is_full_bus(cnout, index, count_reg, "\\Q", cell, "\\A", true))
318 return 19;
319
320 //Look up the clock from the register
321 extract.clk = sigmap(count_reg->getPort("\\CLK"));
322
323 //Register output net must have an INIT attribute equal to the count value
324 extract.rwire = cnout.as_wire();
325 if(extract.rwire->attributes.find("\\init") == extract.rwire->attributes.end())
326 return 20;
327 int rinit = extract.rwire->attributes["\\init"].as_int();
328 if(rinit != extract.count_value)
329 return 21;
330
331 return 0;
332 }
333
334 void counter_worker(
335 ModIndex& index,
336 Cell *cell,
337 unsigned int& total_counters,
338 pool<Cell*>& cells_to_remove,
339 pool<pair<Cell*, string>>& cells_to_rename,
340 pool<RTLIL::IdString>& parallel_cells,
341 int maxwidth)
342 {
343 SigMap& sigmap = index.sigmap;
344
345 //Core of the counter must be an ALU
346 if (cell->type != "$alu")
347 return;
348
349 //A input is the count value. Check if it has COUNT_EXTRACT set.
350 //If it's not a wire, don't even try
351 auto port = sigmap(cell->getPort("\\A"));
352 if(!port.is_wire())
353 return;
354 RTLIL::Wire* a_wire = port.as_wire();
355 bool force_extract = false;
356 bool never_extract = false;
357 string count_reg_src = a_wire->attributes["\\src"].decode_string().c_str();
358 if(a_wire->attributes.find("\\COUNT_EXTRACT") != a_wire->attributes.end())
359 {
360 pool<string> sa = a_wire->get_strpool_attribute("\\COUNT_EXTRACT");
361 string extract_value;
362 if(sa.size() >= 1)
363 {
364 extract_value = *sa.begin();
365 log(" Signal %s declared at %s has COUNT_EXTRACT = %s\n",
366 log_id(a_wire),
367 count_reg_src.c_str(),
368 extract_value.c_str());
369
370 if(extract_value == "FORCE")
371 force_extract = true;
372 else if(extract_value == "NO")
373 never_extract = true;
374 else if(extract_value == "AUTO")
375 {} //default
376 else
377 log_error(" Illegal COUNT_EXTRACT value %s (must be one of FORCE, NO, AUTO)\n",
378 extract_value.c_str());
379 }
380 }
381
382 //If we're explicitly told not to extract, don't infer a counter
383 if(never_extract)
384 return;
385
386 //Attempt to extract a counter
387 CounterExtraction extract;
388 int reason = counter_tryextract(index, cell, extract, parallel_cells, maxwidth);
389
390 //Nonzero code - we could not find a matchable counter.
391 //Do nothing, unless extraction was forced in which case give an error
392 if(reason != 0)
393 {
394 static const char* reasons[25]=
395 {
396 "no problem", //0
397 "counter is too large/small", //1
398 "counter does not count by one", //2
399 "counter uses signed math", //3
400 "counter does not count by one", //4
401 "ALU is not a subtractor", //5
402 "ALU is not a subtractor", //6
403 "ALU ports used outside counter", //7
404 "ALU ports used outside counter", //8
405 "ALU output used outside counter", //9
406 "ALU output is not a mux", //10
407 "ALU output is not full bus", //11
408 "Underflow value is not constant", //12
409 "No underflow detector found", //13
410 "Mux output is used outside counter", //14
411 "Counter reg is not DFF/ADFF", //15
412 "Counter input is not full bus", //16
413 "Count register is used outside counter, but not by an allowed cell", //17
414 "Register output is not full bus", //18
415 "Register output is not full bus", //19
416 "No init value found", //20
417 "Underflow value is not equal to init value", //21
418 "RESERVED, not implemented", //22, kept for compatibility but not used anymore
419 "Reset is not to zero or COUNT_TO", //23
420 "Clock enable configuration is unsupported" //24
421 };
422
423 if(force_extract)
424 {
425 log_error(
426 "Counter extraction is set to FORCE on register %s, but a counter could not be inferred (%s)\n",
427 log_id(a_wire),
428 reasons[reason]);
429 }
430 return;
431 }
432
433 //Get new cell name
434 string countname = string("$COUNTx$") + log_id(extract.rwire->name.str());
435
436 //Wipe all of the old connections to the ALU
437 cell->unsetPort("\\A");
438 cell->unsetPort("\\B");
439 cell->unsetPort("\\BI");
440 cell->unsetPort("\\CI");
441 cell->unsetPort("\\CO");
442 cell->unsetPort("\\X");
443 cell->unsetPort("\\Y");
444 cell->unsetParam("\\A_SIGNED");
445 cell->unsetParam("\\A_WIDTH");
446 cell->unsetParam("\\B_SIGNED");
447 cell->unsetParam("\\B_WIDTH");
448 cell->unsetParam("\\Y_WIDTH");
449
450 //Change the cell type
451 cell->type = "$__COUNT_";
452
453 //Hook up resets
454 if(extract.has_reset)
455 {
456 //TODO: support other kinds of reset
457 cell->setParam("\\RESET_MODE", RTLIL::Const("LEVEL"));
458
459 //If the reset is active low, infer an inverter ($__COUNT_ cells always have active high reset)
460 if(extract.rst_inverted)
461 {
462 auto realreset = cell->module->addWire(NEW_ID);
463 cell->module->addNot(NEW_ID, extract.rst, RTLIL::SigSpec(realreset));
464 cell->setPort("\\RST", realreset);
465 }
466 else
467 cell->setPort("\\RST", extract.rst);
468 }
469 else
470 {
471 cell->setParam("\\RESET_MODE", RTLIL::Const("RISING"));
472 cell->setPort("\\RST", RTLIL::SigSpec(false));
473 }
474
475 //Hook up other stuff
476 //cell->setParam("\\CLKIN_DIVIDE", RTLIL::Const(1));
477 cell->setParam("\\COUNT_TO", RTLIL::Const(extract.count_value));
478 cell->setParam("\\WIDTH", RTLIL::Const(extract.width));
479 cell->setPort("\\CLK", extract.clk);
480 cell->setPort("\\OUT", extract.outsig);
481
482 //Hook up clock enable
483 if(extract.has_ce)
484 {
485 cell->setParam("\\HAS_CE", RTLIL::Const(1));
486 cell->setPort("\\CE", extract.ce);
487 }
488 else
489 cell->setParam("\\HAS_CE", RTLIL::Const(0));
490
491 //Hook up hard-wired ports (for now up/down are not supported), default to no parallel output
492 cell->setParam("\\HAS_POUT", RTLIL::Const(0));
493 cell->setParam("\\RESET_TO_MAX", RTLIL::Const(0));
494 cell->setParam("\\DIRECTION", RTLIL::Const("DOWN"));
495 cell->setPort("\\CE", RTLIL::Const(1));
496 cell->setPort("\\UP", RTLIL::Const(0));
497
498 //Hook up any parallel outputs
499 for(auto load : extract.pouts)
500 {
501 log(" Counter has parallel output to cell %s port %s\n", log_id(load.cell->name), log_id(load.port));
502
503 //Find the wire hooked to the old port
504 auto sig = load.cell->getPort(load.port);
505
506 //Connect it to our parallel output
507 //(this is OK to do more than once b/c they all go to the same place)
508 cell->setPort("\\POUT", sig);
509 cell->setParam("\\HAS_POUT", RTLIL::Const(1));
510 }
511
512 //Delete the cells we've replaced (let opt_clean handle deleting the now-redundant wires)
513 cells_to_remove.insert(extract.count_mux);
514 cells_to_remove.insert(extract.count_reg);
515 cells_to_remove.insert(extract.underflow_inv);
516
517 //Log it
518 total_counters ++;
519 string reset_type = "non-resettable";
520 if(extract.has_reset)
521 {
522 if(extract.rst_inverted)
523 reset_type = "negative";
524 else
525 reset_type = "positive";
526
527 //TODO: support other kind of reset
528 reset_type += " async resettable";
529 }
530 log(" Found %d-bit (%s) down counter %s (counting from %d) for register %s, declared at %s\n",
531 extract.width,
532 reset_type.c_str(),
533 countname.c_str(),
534 extract.count_value,
535 log_id(extract.rwire->name),
536 count_reg_src.c_str());
537
538 //Optimize the counter
539 //If we have no parallel output, and we have redundant bits, shrink us
540 if(extract.pouts.empty())
541 {
542 //TODO: Need to update this when we add support for counters with nonzero reset values
543 //to make sure the reset value fits in our bit space too
544
545 //Optimize it
546 int newbits = ceil(log2(extract.count_value));
547 if(extract.width != newbits)
548 {
549 cell->setParam("\\WIDTH", RTLIL::Const(newbits));
550 log(" Optimizing out %d unused high-order bits (new width is %d)\n",
551 extract.width - newbits,
552 newbits);
553 }
554 }
555
556 //Finally, rename the cell
557 cells_to_rename.insert(pair<Cell*, string>(cell, countname));
558 }
559
560 struct ExtractCounterPass : public Pass {
561 ExtractCounterPass() : Pass("extract_counter", "Extract GreenPak4 counter cells") { }
562 void help() YS_OVERRIDE
563 {
564 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
565 log("\n");
566 log(" extract_counter [options] [selection]\n");
567 log("\n");
568 log("This pass converts non-resettable or async resettable down counters to\n");
569 log("counter cells. Use a target-specific 'techmap' map file to convert those cells\n");
570 log("to the actual target cells.\n");
571 log("\n");
572 log(" -maxwidth N\n");
573 log(" Only extract counters up to N bits wide\n");
574 log("\n");
575 log(" -pout X,Y,...\n");
576 log(" Only allow parallel output from the counter to the listed cell types\n");
577 log(" (if not specified, parallel outputs are not restricted)\n");
578 log("\n");
579 log("\n");
580 }
581 void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
582 {
583 log_header(design, "Executing EXTRACT_COUNTER pass (find counters in netlist).\n");
584
585 int maxwidth = 64;
586 size_t argidx;
587 pool<RTLIL::IdString> parallel_cells;
588 for (argidx = 1; argidx < args.size(); argidx++)
589 {
590 if (args[argidx] == "-pout")
591 {
592 if(argidx + 1 >= args.size())
593 {
594 log_error("extract_counter -pout requires an argument\n");
595 return;
596 }
597
598 std::string pouts = args[++argidx];
599 std::string tmp;
600 for(size_t i=0; i<pouts.length(); i++)
601 {
602 if(pouts[i] == ',')
603 {
604 parallel_cells.insert(RTLIL::escape_id(tmp));
605 tmp = "";
606 }
607 else
608 tmp += pouts[i];
609 }
610 parallel_cells.insert(RTLIL::escape_id(tmp));
611 continue;
612 }
613
614 if (args[argidx] == "-maxwidth" && argidx+1 < args.size())
615 {
616 maxwidth = atoi(args[++argidx].c_str());
617 continue;
618 }
619 }
620 extra_args(args, argidx, design);
621
622 //Extract all of the counters we could find
623 unsigned int total_counters = 0;
624 for (auto module : design->selected_modules())
625 {
626 pool<Cell*> cells_to_remove;
627 pool<pair<Cell*, string>> cells_to_rename;
628
629 ModIndex index(module);
630 for (auto cell : module->selected_cells())
631 counter_worker(index, cell, total_counters, cells_to_remove, cells_to_rename, parallel_cells, maxwidth);
632
633 for(auto cell : cells_to_remove)
634 {
635 //log("Removing cell %s\n", log_id(cell->name));
636 module->remove(cell);
637 }
638
639 for(auto cpair : cells_to_rename)
640 {
641 //log("Renaming cell %s to %s\n", log_id(cpair.first->name), cpair.second.c_str());
642 module->rename(cpair.first, cpair.second);
643 }
644 }
645
646 if(total_counters)
647 log("Extracted %u counters\n", total_counters);
648 }
649 } ExtractCounterPass;
650
651 PRIVATE_NAMESPACE_END