Revert "Merge pull request #1917 from YosysHQ/eddie/abc9_delay_check"
[yosys.git] / passes / pmgen / ice40_wrapcarry.cc
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 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
23 USING_YOSYS_NAMESPACE
24 PRIVATE_NAMESPACE_BEGIN
25
26 #include "passes/pmgen/ice40_wrapcarry_pm.h"
27
28 void create_ice40_wrapcarry(ice40_wrapcarry_pm &pm)
29 {
30 auto &st = pm.st_ice40_wrapcarry;
31
32 #if 0
33 log("\n");
34 log("carry: %s\n", log_id(st.carry, "--"));
35 log("lut: %s\n", log_id(st.lut, "--"));
36 #endif
37
38 log(" replacing SB_LUT + SB_CARRY with $__ICE40_CARRY_WRAPPER cell.\n");
39
40 Cell *cell = pm.module->addCell(NEW_ID, ID($__ICE40_CARRY_WRAPPER));
41 pm.module->swap_names(cell, st.carry);
42
43 cell->setPort(ID::A, st.carry->getPort(ID(I0)));
44 cell->setPort(ID::B, st.carry->getPort(ID(I1)));
45 auto CI = st.carry->getPort(ID::CI);
46 cell->setPort(ID::CI, CI);
47 cell->setPort(ID::CO, st.carry->getPort(ID::CO));
48
49 cell->setPort(ID(I0), st.lut->getPort(ID(I0)));
50 auto I3 = st.lut->getPort(ID(I3));
51 if (pm.sigmap(CI) == pm.sigmap(I3)) {
52 cell->setParam(ID(I3_IS_CI), State::S1);
53 I3 = State::Sx;
54 }
55 else
56 cell->setParam(ID(I3_IS_CI), State::S0);
57 cell->setPort(ID(I3), I3);
58 cell->setPort(ID::O, st.lut->getPort(ID::O));
59 cell->setParam(ID::LUT, st.lut->getParam(ID(LUT_INIT)));
60
61 for (const auto &a : st.carry->attributes)
62 cell->attributes[stringf("\\SB_CARRY.%s", a.first.c_str())] = a.second;
63 for (const auto &a : st.lut->attributes)
64 cell->attributes[stringf("\\SB_LUT4.%s", a.first.c_str())] = a.second;
65 cell->attributes[ID(SB_LUT4.name)] = Const(st.lut->name.str());
66 if (st.carry->get_bool_attribute(ID::keep) || st.lut->get_bool_attribute(ID::keep))
67 cell->attributes[ID::keep] = true;
68
69 pm.autoremove(st.carry);
70 pm.autoremove(st.lut);
71 }
72
73 struct Ice40WrapCarryPass : public Pass {
74 Ice40WrapCarryPass() : Pass("ice40_wrapcarry", "iCE40: wrap carries") { }
75 void help() YS_OVERRIDE
76 {
77 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
78 log("\n");
79 log(" ice40_wrapcarry [selection]\n");
80 log("\n");
81 log("Wrap manually instantiated SB_CARRY cells, along with their associated SB_LUT4s,\n");
82 log("into an internal $__ICE40_CARRY_WRAPPER cell for preservation across technology\n");
83 log("mapping.\n");
84 log("\n");
85 log("Attributes on both cells will have their names prefixed with 'SB_CARRY.' or\n");
86 log("'SB_LUT4.' and attached to the wrapping cell.\n");
87 log("A (* keep *) attribute on either cell will be logically OR-ed together.\n");
88 log("\n");
89 log(" -unwrap\n");
90 log(" unwrap $__ICE40_CARRY_WRAPPER cells back into SB_CARRYs and SB_LUT4s,\n");
91 log(" including restoring their attributes.\n");
92 log("\n");
93 }
94 void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
95 {
96 bool unwrap = false;
97
98 log_header(design, "Executing ICE40_WRAPCARRY pass (wrap carries).\n");
99
100 size_t argidx;
101 for (argidx = 1; argidx < args.size(); argidx++)
102 {
103 if (args[argidx] == "-unwrap") {
104 unwrap = true;
105 continue;
106 }
107 break;
108 }
109 extra_args(args, argidx, design);
110
111 for (auto module : design->selected_modules()) {
112 if (!unwrap)
113 ice40_wrapcarry_pm(module, module->selected_cells()).run_ice40_wrapcarry(create_ice40_wrapcarry);
114 else {
115 for (auto cell : module->selected_cells()) {
116 if (cell->type != ID($__ICE40_CARRY_WRAPPER))
117 continue;
118
119 auto carry = module->addCell(NEW_ID, ID(SB_CARRY));
120 carry->setPort(ID(I0), cell->getPort(ID::A));
121 carry->setPort(ID(I1), cell->getPort(ID::B));
122 carry->setPort(ID::CI, cell->getPort(ID::CI));
123 carry->setPort(ID::CO, cell->getPort(ID::CO));
124 module->swap_names(carry, cell);
125 auto lut_name = cell->attributes.at(ID(SB_LUT4.name), Const(NEW_ID.str())).decode_string();
126 auto lut = module->addCell(lut_name, ID($lut));
127 lut->setParam(ID::WIDTH, 4);
128 lut->setParam(ID::LUT, cell->getParam(ID::LUT));
129 auto I3 = cell->getPort(cell->getParam(ID(I3_IS_CI)).as_bool() ? ID::CI : ID(I3));
130 lut->setPort(ID::A, { I3, cell->getPort(ID::B), cell->getPort(ID::A), cell->getPort(ID(I0)) });
131 lut->setPort(ID::Y, cell->getPort(ID::O));
132
133 Const src;
134 for (const auto &a : cell->attributes)
135 if (a.first.begins_with("\\SB_CARRY.\\"))
136 carry->attributes[a.first.c_str() + strlen("\\SB_CARRY.")] = a.second;
137 else if (a.first.begins_with("\\SB_LUT4.\\"))
138 lut->attributes[a.first.c_str() + strlen("\\SB_LUT4.")] = a.second;
139 else if (a.first == ID::src)
140 src = a.second;
141 else if (a.first.in(ID(SB_LUT4.name), ID::keep, ID::module_not_derived))
142 continue;
143 else
144 log_abort();
145
146 if (!src.empty()) {
147 carry->attributes.insert(std::make_pair(ID::src, src));
148 lut->attributes.insert(std::make_pair(ID::src, src));
149 }
150
151 module->remove(cell);
152 }
153 }
154 }
155 }
156 } Ice40WrapCarryPass;
157
158 PRIVATE_NAMESPACE_END