abc9: generate $abc9_holes design instead of <name>$holes
[yosys.git] / techlibs / anlogic / anlogic_fixcarry.cc
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2019 Miodrag Milanovic <miodrag@symbioticeda.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 static SigBit get_bit_or_zero(const SigSpec &sig)
27 {
28 if (GetSize(sig) == 0)
29 return State::S0;
30 return sig[0];
31 }
32
33 static void fix_carry_chain(Module *module)
34 {
35 SigMap sigmap(module);
36
37 pool<SigBit> ci_bits;
38 dict<SigBit, SigBit> mapping_bits;
39
40 for (auto cell : module->cells())
41 {
42 if (cell->type == ID(AL_MAP_ADDER)) {
43 if (cell->getParam(ID(ALUTYPE)) != Const("ADD")) continue;
44 SigBit bit_i0 = get_bit_or_zero(cell->getPort(ID(a)));
45 SigBit bit_i1 = get_bit_or_zero(cell->getPort(ID(b)));
46 if (bit_i0 == State::S0 && bit_i1== State::S0) {
47 SigBit bit_ci = get_bit_or_zero(cell->getPort(ID(c)));
48 SigSpec o = cell->getPort(ID(o));
49 if (GetSize(o) == 2) {
50 SigBit bit_o = o[0];
51 ci_bits.insert(bit_ci);
52 mapping_bits[bit_ci] = bit_o;
53 }
54 }
55 }
56 }
57 vector<Cell*> adders_to_fix_cells;
58 for (auto cell : module->cells())
59 {
60 if (cell->type == ID(AL_MAP_ADDER)) {
61 if (cell->getParam(ID(ALUTYPE)) != Const("ADD")) continue;
62 SigBit bit_ci = get_bit_or_zero(cell->getPort(ID(c)));
63 SigBit bit_i0 = get_bit_or_zero(cell->getPort(ID(a)));
64 SigBit bit_i1 = get_bit_or_zero(cell->getPort(ID(b)));
65 SigBit canonical_bit = sigmap(bit_ci);
66 if (!ci_bits.count(canonical_bit))
67 continue;
68 if (bit_i0 == State::S0 && bit_i1== State::S0)
69 continue;
70
71 adders_to_fix_cells.push_back(cell);
72 log("Found %s cell named %s with invalid 'c' signal.\n", log_id(cell->type), log_id(cell));
73 }
74 }
75
76 for (auto cell : adders_to_fix_cells)
77 {
78 SigBit bit_ci = get_bit_or_zero(cell->getPort(ID(c)));
79 SigBit canonical_bit = sigmap(bit_ci);
80 auto bit = mapping_bits.at(canonical_bit);
81 log("Fixing %s cell named %s breaking carry chain.\n", log_id(cell->type), log_id(cell));
82 Cell *c = module->addCell(NEW_ID, ID(AL_MAP_ADDER));
83 SigBit new_bit = module->addWire(NEW_ID);
84 SigBit dummy_bit = module->addWire(NEW_ID);
85 SigSpec bits;
86 bits.append(dummy_bit);
87 bits.append(new_bit);
88 c->setParam(ID(ALUTYPE), Const("ADD_CARRY"));
89 c->setPort(ID(a), bit);
90 c->setPort(ID(b), State::S0);
91 c->setPort(ID(c), State::S0);
92 c->setPort(ID(o), bits);
93
94 cell->setPort(ID(c), new_bit);
95 }
96
97 }
98
99 struct AnlogicCarryFixPass : public Pass {
100 AnlogicCarryFixPass() : Pass("anlogic_fixcarry", "Anlogic: fix carry chain") { }
101 void help() YS_OVERRIDE
102 {
103 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
104 log("\n");
105 log(" anlogic_fixcarry [options] [selection]\n");
106 log("\n");
107 log("Add Anlogic adders to fix carry chain if needed.\n");
108 log("\n");
109 }
110 void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
111 {
112 log_header(design, "Executing anlogic_fixcarry pass (fix invalid carry chain).\n");
113
114 size_t argidx;
115 for (argidx = 1; argidx < args.size(); argidx++)
116 {
117 break;
118 }
119 extra_args(args, argidx, design);
120
121 Module *module = design->top_module();
122
123 if (module == nullptr)
124 log_cmd_error("No top module found.\n");
125
126 fix_carry_chain(module);
127 }
128 } AnlogicCarryFixPass;
129
130 PRIVATE_NAMESPACE_END