abc9_ops: use TimingInfo for -prep_{lut,box} too
[yosys.git] / kernel / timinginfo.h
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 * (C) 2020 Eddie Hung <eddie@fpgeh.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 #ifndef TIMINGARCS_H
22 #define TIMINGARCS_H
23
24 #include "kernel/yosys.h"
25
26 YOSYS_NAMESPACE_BEGIN
27
28 typedef std::pair<RTLIL::SigBit,RTLIL::SigBit> BitBit;
29
30 struct ModuleTiming
31 {
32 RTLIL::IdString type;
33 dict<BitBit, int> comb;
34 dict<RTLIL::SigBit, int> arrival, required;
35 };
36
37 struct TimingInfo
38 {
39 dict<RTLIL::IdString, ModuleTiming> data;
40
41 TimingInfo()
42 {
43 }
44
45 TimingInfo(RTLIL::Design *design)
46 {
47 setup(design);
48 }
49
50 void setup(RTLIL::Design *design)
51 {
52 for (auto module : design->modules()) {
53 if (!module->get_blackbox_attribute())
54 continue;
55 setup_module(module);
56 }
57 }
58
59 void setup_module(RTLIL::Module *module)
60 {
61 auto r = data.insert(module->name);
62 log_assert(r.second);
63 auto &t = r.first->second;
64
65 for (auto cell : module->cells()) {
66 if (cell->type == ID($specify2)) {
67 auto src = cell->getPort(ID(SRC));
68 auto dst = cell->getPort(ID(DST));
69 for (const auto &c : src.chunks())
70 if (!c.wire->port_input)
71 log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(src));
72 for (const auto &c : dst.chunks())
73 if (!c.wire->port_output)
74 log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module output.\n", log_id(module), log_id(cell), log_signal(dst));
75 int rise_max = cell->getParam(ID(T_RISE_MAX)).as_int();
76 int fall_max = cell->getParam(ID(T_FALL_MAX)).as_int();
77 int max = std::max(rise_max,fall_max);
78 if (max < 0)
79 log_error("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0.\n", log_id(module), log_id(cell));
80 if (cell->getParam(ID(FULL)).as_bool()) {
81 for (const auto &s : src)
82 for (const auto &d : dst) {
83 auto r = t.comb.insert(BitBit(s,d));
84 if (!r.second)
85 log_error("Module '%s' contains multiple specify cells for SRC '%s' and DST '%s'.\n", log_id(module), log_signal(s), log_signal(d));
86 r.first->second = max;
87 }
88 }
89 else {
90 log_assert(GetSize(src) == GetSize(dst));
91 for (auto i = 0; i < GetSize(src); i++) {
92 const auto &s = src[i];
93 const auto &d = dst[i];
94 auto r = t.comb.insert(BitBit(s,d));
95 if (!r.second)
96 log_error("Module '%s' contains multiple specify cells for SRC '%s' and DST '%s'.\n", log_id(module), log_signal(s), log_signal(d));
97 r.first->second = max;
98 }
99 }
100 }
101 else if (cell->type == ID($specify3)) {
102 auto src = cell->getPort(ID(SRC));
103 auto dst = cell->getPort(ID(DST));
104 for (const auto &c : src.chunks())
105 if (!c.wire->port_input)
106 log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(src));
107 for (const auto &c : dst.chunks())
108 if (!c.wire->port_output)
109 log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module output.\n", log_id(module), log_id(cell), log_signal(dst));
110 int rise_max = cell->getParam(ID(T_RISE_MAX)).as_int();
111 int fall_max = cell->getParam(ID(T_FALL_MAX)).as_int();
112 int max = std::max(rise_max,fall_max);
113 if (max < 0)
114 log_warning("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell));
115 if (max <= 0) {
116 log_debug("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX <= 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell));
117 continue;
118 }
119 for (const auto &d : dst) {
120 auto &v = t.arrival[d];
121 v = std::max(v, max);
122 }
123 }
124 else if (cell->type == ID($specrule)) {
125 auto type = cell->getParam(ID(TYPE)).decode_string();
126 if (type != "$setup" && type != "$setuphold")
127 continue;
128 auto src = cell->getPort(ID(SRC));
129 auto dst = cell->getPort(ID(DST));
130 for (const auto &c : src.chunks())
131 if (!c.wire->port_input)
132 log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(src));
133 for (const auto &c : dst.chunks())
134 if (!c.wire->port_input)
135 log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(dst));
136 int max = cell->getParam(ID(T_LIMIT_MAX)).as_int();
137 if (max < 0)
138 log_warning("Module '%s' contains specify cell '%s' with T_LIMIT_MAX < 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell));
139 if (max <= 0) {
140 log_debug("Module '%s' contains specify cell '%s' with T_LIMIT_MAX <= 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell));
141 continue;
142 }
143 for (const auto &s : src) {
144 auto &v = t.required[s];
145 v = std::max(v, max);
146 }
147 }
148 }
149 }
150
151 decltype(data)::const_iterator find (RTLIL::IdString module_name) const { return data.find(module_name); }
152 decltype(data)::const_iterator end () const { return data.end(); }
153 };
154
155 YOSYS_NAMESPACE_END
156
157 #endif