Adding new pass to fix carry chain
[yosys.git] / techlibs / efinix / efinix_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 == "\\EFX_ADD") {
43 SigBit bit_i0 = get_bit_or_zero(cell->getPort("\\I0"));
44 SigBit bit_i1 = get_bit_or_zero(cell->getPort("\\I1"));
45 if (bit_i0 == State::S0 && bit_i1== State::S0) {
46 SigBit bit_ci = get_bit_or_zero(cell->getPort("\\CI"));
47 SigBit bit_o = sigmap(cell->getPort("\\O"));
48 ci_bits.insert(bit_ci);
49 mapping_bits[bit_ci] = bit_o;
50 }
51 }
52 }
53
54 vector<Cell*> adders_to_fix_cells;
55 for (auto cell : module->cells())
56 {
57 if (cell->type == "\\EFX_ADD") {
58 SigBit bit_ci = get_bit_or_zero(cell->getPort("\\CI"));
59 SigBit bit_i0 = get_bit_or_zero(cell->getPort("\\I0"));
60 SigBit bit_i1 = get_bit_or_zero(cell->getPort("\\I1"));
61 SigBit canonical_bit = sigmap(bit_ci);
62 if (!ci_bits.count(canonical_bit))
63 continue;
64 if (bit_i0 == State::S0 && bit_i1== State::S0)
65 continue;
66
67 adders_to_fix_cells.push_back(cell);
68 log("Found %s cell named %s with invalid CI signal.\n", log_id(cell->type), log_id(cell));
69 }
70 }
71
72 for (auto cell : adders_to_fix_cells)
73 {
74 SigBit bit_ci = get_bit_or_zero(cell->getPort("\\CI"));
75 SigBit canonical_bit = sigmap(bit_ci);
76 auto bit = mapping_bits.at(canonical_bit);
77 log("Fixing %s cell named %s breaking carry chain.\n", log_id(cell->type), log_id(cell));
78 Cell *c = module->addCell(NEW_ID, "\\EFX_ADD");
79 SigBit new_bit = module->addWire(NEW_ID);
80 c->setParam("\\I0_POLARITY", State::S1);
81 c->setParam("\\I1_POLARITY", State::S1);
82 c->setPort("\\I0", bit);
83 c->setPort("\\I1", State::S1);
84 c->setPort("\\CI", State::S0);
85 c->setPort("\\CO", new_bit);
86
87 cell->setPort("\\CI", new_bit);
88 }
89 }
90
91 struct EfinixCarryFixPass : public Pass {
92 EfinixCarryFixPass() : Pass("efinix_fixcarry", "Efinix: fix carry chain") { }
93 void help() YS_OVERRIDE
94 {
95 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
96 log("\n");
97 log(" efinix_fixcarry [options] [selection]\n");
98 log("\n");
99 log("Add Efinix adders to fix carry chain if needed.\n");
100 log("\n");
101 }
102 void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
103 {
104 log_header(design, "Executing efinix_fixcarry pass (fix invalid carry chain).\n");
105
106 size_t argidx;
107 for (argidx = 1; argidx < args.size(); argidx++)
108 {
109 break;
110 }
111 extra_args(args, argidx, design);
112
113 Module *module = design->top_module();
114
115 if (module == nullptr)
116 log_cmd_error("No top module found.\n");
117
118 fix_carry_chain(module);
119 }
120 } EfinixCarryFixPass;
121
122 PRIVATE_NAMESPACE_END