Merge pull request #1559 from YosysHQ/efinix_test_fix
[yosys.git] / techlibs / ecp5 / ecp5_gsr.cc
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 * Copyright (C) 2019 David Shah <david@symbioticeda.com>
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 *
19 */
20
21 #include "kernel/yosys.h"
22 #include "kernel/sigtools.h"
23
24 USING_YOSYS_NAMESPACE
25 PRIVATE_NAMESPACE_BEGIN
26
27 struct Ecp5GsrPass : public Pass {
28 Ecp5GsrPass() : Pass("ecp5_gsr", "ECP5: handle GSR") { }
29 void help() YS_OVERRIDE
30 {
31 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
32 log("\n");
33 log(" ecp5_gsr [options] [selection]\n");
34 log("\n");
35 log("Trim active low async resets connected to GSR and resolve GSR parameter,\n");
36 log("if a GSR or SGSR primitive is used in the design.\n");
37 log("\n");
38 log("If any cell has the GSR parameter set to \"AUTO\", this will be resolved\n");
39 log("to \"ENABLED\" if a GSR primitive is present and the (* nogsr *) attribute\n");
40 log("is not set, otherwise it will be resolved to \"DISABLED\".\n");
41 log("\n");
42 }
43 void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
44 {
45 log_header(design, "Executing ECP5_GSR pass (implement FF init values).\n");
46
47 size_t argidx;
48 for (argidx = 1; argidx < args.size(); argidx++)
49 {
50 // if (args[argidx] == "-singleton") {
51 // singleton_mode = true;
52 // continue;
53 // }
54 break;
55 }
56 extra_args(args, argidx, design);
57
58 for (auto module : design->selected_modules())
59 {
60 log("Handling GSR in %s.\n", log_id(module));
61
62 SigMap sigmap(module);
63
64 SigBit gsr;
65 bool found_gsr = false;
66
67 for (auto cell : module->selected_cells())
68 {
69 if (cell->type != ID(GSR) && cell->type != ID(SGSR))
70 continue;
71 if (found_gsr)
72 log_error("Found more than one GSR or SGSR cell in module %s.\n", log_id(module));
73 found_gsr = true;
74 SigSpec sig_gsr = cell->getPort(ID(GSR));
75 if (GetSize(sig_gsr) < 1)
76 log_error("GSR cell %s has disconnected GSR input.\n", log_id(cell));
77 gsr = sigmap(sig_gsr[0]);
78 }
79
80 // Resolve GSR parameter
81
82 for (auto cell : module->selected_cells())
83 {
84 if (!cell->hasParam(ID(GSR)) || cell->getParam(ID(GSR)).decode_string() != "AUTO")
85 continue;
86
87 bool gsren = found_gsr;
88 if (cell->get_bool_attribute("\\nogsr"))
89 gsren = false;
90 cell->setParam(ID(GSR), gsren ? Const("ENABLED") : Const("DISABLED"));
91
92 }
93
94 if (!found_gsr)
95 continue;
96
97 // For finding active low FF inputs
98 pool<SigBit> inverted_gsr;
99
100 log_debug("GSR net in module %s is %s.\n", log_id(module), log_signal(gsr));
101 for (auto cell : module->selected_cells())
102 {
103 if (cell->type != ID($_NOT_))
104 continue;
105 SigSpec sig_a = cell->getPort(ID(A)), sig_y = cell->getPort(ID(Y));
106 if (GetSize(sig_a) < 1 || GetSize(sig_y) < 1)
107 continue;
108 SigBit a = sigmap(sig_a[0]);
109 if (a == gsr)
110 inverted_gsr.insert(sigmap(sig_y[0]));
111 }
112
113 for (auto cell : module->selected_cells())
114 {
115 if (cell->type != ID(TRELLIS_FF))
116 continue;
117 if (!cell->hasParam(ID(GSR)) || cell->getParam(ID(GSR)).decode_string() != "ENABLED")
118 continue;
119 if (!cell->hasParam(ID(SRMODE)) || cell->getParam(ID(SRMODE)).decode_string() != "ASYNC")
120 continue;
121 SigSpec sig_lsr = cell->getPort(ID(LSR));
122 if (GetSize(sig_lsr) < 1)
123 continue;
124 SigBit lsr = sigmap(sig_lsr[0]);
125 if (!inverted_gsr.count(lsr))
126 continue;
127 cell->setParam(ID(SRMODE), Const("LSR_OVER_CE"));
128 cell->unsetPort(ID(LSR));
129 }
130
131 }
132 }
133 } Ecp5GsrPass;
134
135 PRIVATE_NAMESPACE_END