Merge pull request #2006 from jersey99/signed-in-rtlil-wire
[yosys.git] / techlibs / coolrunner2 / coolrunner2_fixup.cc
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2020 R. Ou <rqou@robertou.com>
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
23 USING_YOSYS_NAMESPACE
24 PRIVATE_NAMESPACE_BEGIN
25
26 RTLIL::Wire *makexorbuffer(RTLIL::Module *module, SigBit inwire, const char *cellname)
27 {
28 RTLIL::Wire *outwire = nullptr;
29
30 if (inwire == SigBit(true))
31 {
32 // Constant 1
33 outwire = module->addWire(
34 module->uniquify(stringf("$xc2fix$%s_BUF1_XOR_OUT", cellname)));
35 auto xor_cell = module->addCell(
36 module->uniquify(stringf("$xc2fix$%s_BUF1_XOR", cellname)),
37 ID(MACROCELL_XOR));
38 xor_cell->setParam(ID(INVERT_OUT), true);
39 xor_cell->setPort(ID(OUT), outwire);
40 }
41 else if (inwire == SigBit(false))
42 {
43 // Constant 0
44 outwire = module->addWire(
45 module->uniquify(stringf("$xc2fix$%s_BUF0_XOR_OUT", cellname)));
46 auto xor_cell = module->addCell(
47 module->uniquify(stringf("$xc2fix$%s_BUF0_XOR", cellname)),
48 ID(MACROCELL_XOR));
49 xor_cell->setParam(ID(INVERT_OUT), false);
50 xor_cell->setPort(ID(OUT), outwire);
51 }
52 else if (inwire == SigBit(RTLIL::State::Sx))
53 {
54 // x; treat as 0
55 log_warning("While buffering, changing x to 0 into cell %s\n", cellname);
56 outwire = module->addWire(
57 module->uniquify(stringf("$xc2fix$%s_BUF0_XOR_OUT", cellname)));
58 auto xor_cell = module->addCell(
59 module->uniquify(stringf("$xc2fix$%s_BUF0_XOR", cellname)),
60 ID(MACROCELL_XOR));
61 xor_cell->setParam(ID(INVERT_OUT), false);
62 xor_cell->setPort(ID(OUT), outwire);
63 }
64 else
65 {
66 auto inwire_name = inwire.wire->name.c_str();
67
68 outwire = module->addWire(
69 module->uniquify(stringf("$xc2fix$%s_BUF_XOR_OUT", inwire_name)));
70
71 auto and_to_xor_wire = module->addWire(
72 module->uniquify(stringf("$xc2fix$%s_BUF_AND_OUT", inwire_name)));
73
74 auto and_cell = module->addCell(
75 module->uniquify(stringf("$xc2fix$%s_BUF_AND", inwire_name)),
76 ID(ANDTERM));
77 and_cell->setParam(ID(TRUE_INP), 1);
78 and_cell->setParam(ID(COMP_INP), 0);
79 and_cell->setPort(ID(OUT), and_to_xor_wire);
80 and_cell->setPort(ID(IN), inwire);
81 and_cell->setPort(ID(IN_B), SigSpec());
82
83 auto xor_cell = module->addCell(
84 module->uniquify(stringf("$xc2fix$%s_BUF_XOR", inwire_name)),
85 ID(MACROCELL_XOR));
86 xor_cell->setParam(ID(INVERT_OUT), false);
87 xor_cell->setPort(ID(IN_PTC), and_to_xor_wire);
88 xor_cell->setPort(ID(OUT), outwire);
89 }
90
91 return outwire;
92 }
93
94 RTLIL::Wire *makeptermbuffer(RTLIL::Module *module, SigBit inwire)
95 {
96 auto inwire_name = inwire.wire->name.c_str();
97
98 auto outwire = module->addWire(
99 module->uniquify(stringf("$xc2fix$%s_BUF_AND_OUT", inwire_name)));
100
101 auto and_cell = module->addCell(
102 module->uniquify(stringf("$xc2fix$%s_BUF_AND", inwire_name)),
103 ID(ANDTERM));
104 and_cell->setParam(ID(TRUE_INP), 1);
105 and_cell->setParam(ID(COMP_INP), 0);
106 and_cell->setPort(ID(OUT), outwire);
107 and_cell->setPort(ID(IN), inwire);
108 and_cell->setPort(ID(IN_B), SigSpec());
109
110 return outwire;
111 }
112
113 struct Coolrunner2FixupPass : public Pass {
114 Coolrunner2FixupPass() : Pass("coolrunner2_fixup", "insert necessary buffer cells for CoolRunner-II architecture") { }
115 void help() YS_OVERRIDE
116 {
117 log("\n");
118 log(" coolrunner2_fixup [options] [selection]\n");
119 log("\n");
120 log("Insert necessary buffer cells for CoolRunner-II architecture.\n");
121 log("\n");
122 }
123 void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
124 {
125 log_header(design, "Executing COOLRUNNER2_FIXUP pass (insert necessary buffer cells for CoolRunner-II architecture).\n");
126 extra_args(args, 1, design);
127
128 for (auto module : design->selected_modules())
129 {
130 SigMap sigmap(module);
131
132 // Find all the FF outputs
133 pool<SigBit> sig_fed_by_ff;
134 for (auto cell : module->selected_cells())
135 {
136 if (cell->type.in(ID(FDCP), ID(FDCP_N), ID(FDDCP), ID(LDCP), ID(LDCP_N),
137 ID(FTCP), ID(FTCP_N), ID(FTDCP), ID(FDCPE), ID(FDCPE_N), ID(FDDCPE)))
138 {
139 auto output = sigmap(cell->getPort(ID::Q)[0]);
140 sig_fed_by_ff.insert(output);
141 }
142 }
143
144 // Find all the XOR outputs
145 pool<SigBit> sig_fed_by_xor;
146 for (auto cell : module->selected_cells())
147 {
148 if (cell->type == ID(MACROCELL_XOR))
149 {
150 auto output = sigmap(cell->getPort(ID(OUT))[0]);
151 sig_fed_by_xor.insert(output);
152 }
153 }
154
155 // Find all the input/inout outputs
156 pool<SigBit> sig_fed_by_io;
157 for (auto cell : module->selected_cells())
158 {
159 if (cell->type.in(ID(IBUF), ID(IOBUFE)))
160 {
161 if (cell->hasPort(ID::O)) {
162 auto output = sigmap(cell->getPort(ID::O)[0]);
163 sig_fed_by_io.insert(output);
164 }
165 }
166 }
167
168 // Find all the pterm outputs
169 pool<SigBit> sig_fed_by_pterm;
170 for (auto cell : module->selected_cells())
171 {
172 if (cell->type == ID(ANDTERM))
173 {
174 auto output = sigmap(cell->getPort(ID(OUT))[0]);
175 sig_fed_by_pterm.insert(output);
176 }
177 }
178
179 // Find all the bufg outputs
180 pool<SigBit> sig_fed_by_bufg;
181 for (auto cell : module->selected_cells())
182 {
183 if (cell->type == ID(BUFG))
184 {
185 auto output = sigmap(cell->getPort(ID::O)[0]);
186 sig_fed_by_bufg.insert(output);
187 }
188 }
189
190 // Find all the bufgsr outputs
191 pool<SigBit> sig_fed_by_bufgsr;
192 for (auto cell : module->selected_cells())
193 {
194 if (cell->type == ID(BUFGSR))
195 {
196 auto output = sigmap(cell->getPort(ID::O)[0]);
197 sig_fed_by_bufgsr.insert(output);
198 }
199 }
200
201 // Find all the bufgts outputs
202 pool<SigBit> sig_fed_by_bufgts;
203 for (auto cell : module->selected_cells())
204 {
205 if (cell->type == ID(BUFGTS))
206 {
207 auto output = sigmap(cell->getPort(ID::O)[0]);
208 sig_fed_by_bufgts.insert(output);
209 }
210 }
211
212 // This is used to fix the input -> FF -> output scenario
213 pool<SigBit> sig_fed_by_ibuf;
214 for (auto cell : module->selected_cells())
215 {
216 if (cell->type == ID(IBUF))
217 {
218 auto output = sigmap(cell->getPort(ID::O)[0]);
219 sig_fed_by_ibuf.insert(output);
220 }
221 }
222
223 // Find all of the sinks for each output from an IBUF
224 dict<SigBit, std::pair<int, RTLIL::Cell *>> ibuf_fanouts;
225 for (auto cell : module->selected_cells())
226 {
227 for (auto &conn : cell->connections())
228 {
229 if (cell->input(conn.first))
230 {
231 for (auto wire_in : sigmap(conn.second))
232 {
233 if (sig_fed_by_ibuf[wire_in])
234 {
235 auto existing_count = ibuf_fanouts[wire_in].first;
236 ibuf_fanouts[wire_in] =
237 std::pair<int, RTLIL::Cell *>(existing_count + 1, cell);
238 }
239 }
240 }
241 }
242 }
243
244 dict<SigBit, RTLIL::Cell *> ibuf_out_to_packed_reg_cell;
245 pool<SigBit> packed_reg_out;
246 for (auto x : ibuf_fanouts)
247 {
248 auto ibuf_out_wire = x.first;
249 auto fanout_count = x.second.first;
250 auto maybe_ff_cell = x.second.second;
251
252 // The register can be packed with the IBUF only if it's
253 // actually a register and it's the only fanout. Otherwise,
254 // the pad-to-zia path has to be used up and the register
255 // can't be packed with the ibuf.
256 if (fanout_count == 1 && maybe_ff_cell->type.in(
257 ID(FDCP), ID(FDCP_N), ID(FDDCP), ID(LDCP), ID(LDCP_N),
258 ID(FTCP), ID(FTCP_N), ID(FTDCP), ID(FDCPE), ID(FDCPE_N), ID(FDDCPE)))
259 {
260 SigBit input;
261 if (maybe_ff_cell->type.in(ID(FTCP), ID(FTCP_N), ID(FTDCP)))
262 input = sigmap(maybe_ff_cell->getPort(ID::T)[0]);
263 else
264 input = sigmap(maybe_ff_cell->getPort(ID::D)[0]);
265 SigBit output = sigmap(maybe_ff_cell->getPort(ID::Q)[0]);
266
267 if (input == ibuf_out_wire)
268 {
269 log("Found IBUF %s that can be packed with FF %s (type %s)\n",
270 ibuf_out_wire.wire->name.c_str(),
271 maybe_ff_cell->name.c_str(),
272 maybe_ff_cell->type.c_str());
273
274 ibuf_out_to_packed_reg_cell[ibuf_out_wire] = maybe_ff_cell;
275 packed_reg_out.insert(output);
276 }
277 }
278 }
279
280 for (auto cell : module->selected_cells())
281 {
282 if (cell->type.in(ID(FDCP), ID(FDCP_N), ID(FDDCP), ID(LDCP), ID(LDCP_N),
283 ID(FTCP), ID(FTCP_N), ID(FTDCP), ID(FDCPE), ID(FDCPE_N), ID(FDDCPE)))
284 {
285 // Buffering FF inputs. FF inputs can only come from either
286 // an IO pin or from an XOR. Otherwise AND/XOR cells need
287 // to be inserted.
288 SigBit input;
289 if (cell->type.in(ID(FTCP), ID(FTCP_N), ID(FTDCP)))
290 input = sigmap(cell->getPort(ID::T)[0]);
291 else
292 input = sigmap(cell->getPort(ID::D)[0]);
293
294 // If the input wasn't an XOR nor an IO, then a buffer
295 // definitely needs to be added.
296 // Otherwise, if it is an IO, only leave unbuffered
297 // if we're being packed with the IO.
298 if ((!sig_fed_by_xor[input] && !sig_fed_by_io[input]) ||
299 (sig_fed_by_io[input] && ibuf_out_to_packed_reg_cell[input] != cell))
300 {
301 log("Buffering input to \"%s\"\n", cell->name.c_str());
302
303 auto xor_to_ff_wire = makexorbuffer(module, input, cell->name.c_str());
304
305 if (cell->type.in(ID(FTCP), ID(FTCP_N), ID(FTDCP)))
306 cell->setPort(ID::T, xor_to_ff_wire);
307 else
308 cell->setPort(ID::D, xor_to_ff_wire);
309 }
310
311 // Buffering FF clocks. FF clocks can only come from either
312 // a pterm or a bufg. In some cases this will be handled
313 // in coolrunner2_sop (e.g. if clock is generated from
314 // AND-ing two signals) but not in all cases.
315 SigBit clock;
316 if (cell->type.in(ID(LDCP), ID(LDCP_N)))
317 clock = sigmap(cell->getPort(ID::G)[0]);
318 else
319 clock = sigmap(cell->getPort(ID::C)[0]);
320
321 if (!sig_fed_by_pterm[clock] && !sig_fed_by_bufg[clock])
322 {
323 log("Buffering clock to \"%s\"\n", cell->name.c_str());
324
325 auto pterm_to_ff_wire = makeptermbuffer(module, clock);
326
327 if (cell->type.in(ID(LDCP), ID(LDCP_N)))
328 cell->setPort(ID::G, pterm_to_ff_wire);
329 else
330 cell->setPort(ID::C, pterm_to_ff_wire);
331 }
332
333 // Buffering FF set/reset. This can only come from either
334 // a pterm or a bufgsr.
335 SigBit set;
336 set = sigmap(cell->getPort(ID(PRE))[0]);
337 if (set != SigBit(false))
338 {
339 if (!sig_fed_by_pterm[set] && !sig_fed_by_bufgsr[set])
340 {
341 log("Buffering set to \"%s\"\n", cell->name.c_str());
342
343 auto pterm_to_ff_wire = makeptermbuffer(module, set);
344
345 cell->setPort(ID(PRE), pterm_to_ff_wire);
346 }
347 }
348
349 SigBit reset;
350 reset = sigmap(cell->getPort(ID::CLR)[0]);
351 if (reset != SigBit(false))
352 {
353 if (!sig_fed_by_pterm[reset] && !sig_fed_by_bufgsr[reset])
354 {
355 log("Buffering reset to \"%s\"\n", cell->name.c_str());
356
357 auto pterm_to_ff_wire = makeptermbuffer(module, reset);
358
359 cell->setPort(ID::CLR, pterm_to_ff_wire);
360 }
361 }
362
363 // Buffering FF clock enable
364 // FIXME: This doesn't fully fix PTC conflicts
365 // FIXME: Need to ensure constant enables are optimized out
366 if (cell->type.in(ID(FDCPE), ID(FDCPE_N), ID(FDDCPE)))
367 {
368 SigBit ce;
369 ce = sigmap(cell->getPort(ID(CE))[0]);
370 if (!sig_fed_by_pterm[ce])
371 {
372 log("Buffering clock enable to \"%s\"\n", cell->name.c_str());
373
374 auto pterm_to_ff_wire = makeptermbuffer(module, ce);
375
376 cell->setPort(ID(CE), pterm_to_ff_wire);
377 }
378 }
379 }
380 }
381
382 for (auto cell : module->selected_cells())
383 {
384 if (cell->type == ID(IOBUFE))
385 {
386 // Buffer IOBUFE inputs. This can only be fed from an XOR or FF.
387 SigBit input = sigmap(cell->getPort(ID::I)[0]);
388
389 if ((!sig_fed_by_xor[input] && !sig_fed_by_ff[input]) ||
390 packed_reg_out[input])
391 {
392 log("Buffering input to \"%s\"\n", cell->name.c_str());
393
394 auto xor_to_io_wire = makexorbuffer(module, input, cell->name.c_str());
395
396 cell->setPort(ID::I, xor_to_io_wire);
397 }
398
399 // Buffer IOBUFE enables. This can only be fed from a pterm
400 // or a bufgts.
401 if (cell->hasPort(ID::E))
402 {
403 SigBit oe;
404 oe = sigmap(cell->getPort(ID::E)[0]);
405 if (!sig_fed_by_pterm[oe] && !sig_fed_by_bufgts[oe])
406 {
407 log("Buffering output enable to \"%s\"\n", cell->name.c_str());
408
409 auto pterm_to_oe_wire = makeptermbuffer(module, oe);
410
411 cell->setPort(ID::E, pterm_to_oe_wire);
412 }
413 }
414 }
415 }
416
417 // Now we have to fix up some cases where shared logic can
418 // cause XORs to have multiple fanouts to something other than
419 // pterms (which is not ok)
420
421 // Find all the XOR outputs
422 dict<SigBit, RTLIL::Cell *> xor_out_to_xor_cell;
423 for (auto cell : module->selected_cells())
424 {
425 if (cell->type == ID(MACROCELL_XOR))
426 {
427 auto output = sigmap(cell->getPort(ID(OUT))[0]);
428 xor_out_to_xor_cell[output] = cell;
429 }
430 }
431
432 // Find all of the sinks for each output from an XOR
433 pool<SigBit> xor_fanout_once;
434 for (auto cell : module->selected_cells())
435 {
436 if (cell->type == ID(ANDTERM))
437 continue;
438
439 for (auto &conn : cell->connections())
440 {
441 if (cell->input(conn.first))
442 {
443 for (auto wire_in : sigmap(conn.second))
444 {
445 auto xor_cell = xor_out_to_xor_cell[wire_in];
446 if (xor_cell)
447 {
448 if (xor_fanout_once[wire_in])
449 {
450 log("Additional fanout found for %s into %s (type %s), duplicating\n",
451 xor_cell->name.c_str(),
452 cell->name.c_str(),
453 cell->type.c_str());
454
455 auto new_xor_cell = module->addCell(
456 module->uniquify(xor_cell->name), xor_cell);
457 auto new_wire = module->addWire(
458 module->uniquify(wire_in.wire->name));
459 new_xor_cell->setPort(ID(OUT), new_wire);
460 cell->setPort(conn.first, new_wire);
461 }
462 xor_fanout_once.insert(wire_in);
463 }
464 }
465 }
466 }
467 }
468
469 // Do the same fanout fixing for OR terms. By doing this
470 // after doing XORs, both pieces will be duplicated when necessary.
471
472 // Find all the OR outputs
473 dict<SigBit, RTLIL::Cell *> or_out_to_or_cell;
474 for (auto cell : module->selected_cells())
475 {
476 if (cell->type == ID(ORTERM))
477 {
478 auto output = sigmap(cell->getPort(ID(OUT))[0]);
479 or_out_to_or_cell[output] = cell;
480 }
481 }
482
483 // Find all of the sinks for each output from an OR
484 pool<SigBit> or_fanout_once;
485 for (auto cell : module->selected_cells())
486 {
487 for (auto &conn : cell->connections())
488 {
489 if (cell->input(conn.first))
490 {
491 for (auto wire_in : sigmap(conn.second))
492 {
493 auto or_cell = or_out_to_or_cell[wire_in];
494 if (or_cell)
495 {
496 if (or_fanout_once[wire_in])
497 {
498 log("Additional fanout found for %s into %s (type %s), duplicating\n",
499 or_cell->name.c_str(),
500 cell->name.c_str(),
501 cell->type.c_str());
502
503 auto new_or_cell = module->addCell(
504 module->uniquify(or_cell->name), or_cell);
505 auto new_wire = module->addWire(
506 module->uniquify(wire_in.wire->name));
507 new_or_cell->setPort(ID(OUT), new_wire);
508 cell->setPort(conn.first, new_wire);
509 }
510 or_fanout_once.insert(wire_in);
511 }
512 }
513 }
514 }
515 }
516 }
517 }
518 } Coolrunner2FixupPass;
519
520 PRIVATE_NAMESPACE_END