Merge pull request #3310 from robinsonb5-PRs/master
[yosys.git] / kernel / ffinit.h
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2020 Marcelina Koƛcielnicka <mwk@0x04.net>
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 #ifndef FFINIT_H
21 #define FFINIT_H
22
23 #include "kernel/yosys.h"
24 #include "kernel/sigtools.h"
25
26 YOSYS_NAMESPACE_BEGIN
27
28 struct FfInitVals
29 {
30 const SigMap *sigmap;
31 dict<SigBit, std::pair<State,SigBit>> initbits;
32
33 void set(const SigMap *sigmap_, RTLIL::Module *module)
34 {
35 sigmap = sigmap_;
36 initbits.clear();
37 for (auto wire : module->wires())
38 {
39 if (wire->attributes.count(ID::init) == 0)
40 continue;
41
42 SigSpec wirebits = (*sigmap)(wire);
43 Const initval = wire->attributes.at(ID::init);
44
45 for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++)
46 {
47 SigBit bit = wirebits[i];
48 State val = initval[i];
49
50 if (val != State::S0 && val != State::S1 && bit.wire != nullptr)
51 continue;
52
53 if (initbits.count(bit)) {
54 if (initbits.at(bit).first != val)
55 log_error("Conflicting init values for signal %s (%s = %s != %s).\n",
56 log_signal(bit), log_signal(SigBit(wire, i)),
57 log_signal(val), log_signal(initbits.at(bit).first));
58 continue;
59 }
60
61 initbits[bit] = std::make_pair(val,SigBit(wire,i));
62 }
63 }
64 }
65
66 RTLIL::State operator()(RTLIL::SigBit bit) const
67 {
68 auto it = initbits.find((*sigmap)(bit));
69 if (it != initbits.end())
70 return it->second.first;
71 else
72 return State::Sx;
73 }
74
75 RTLIL::Const operator()(const RTLIL::SigSpec &sig) const
76 {
77 RTLIL::Const res;
78 for (auto bit : sig)
79 res.bits.push_back((*this)(bit));
80 return res;
81 }
82
83 void set_init(RTLIL::SigBit bit, RTLIL::State val)
84 {
85 SigBit mbit = (*sigmap)(bit);
86 SigBit abit = bit;
87 auto it = initbits.find(mbit);
88 if (it != initbits.end())
89 abit = it->second.second;
90 else if (val == State::Sx)
91 return;
92 log_assert(abit.wire);
93 initbits[mbit] = std::make_pair(val,abit);
94 auto it2 = abit.wire->attributes.find(ID::init);
95 if (it2 != abit.wire->attributes.end()) {
96 it2->second[abit.offset] = val;
97 if (it2->second.is_fully_undef())
98 abit.wire->attributes.erase(it2);
99 } else if (val != State::Sx) {
100 Const cval(State::Sx, GetSize(abit.wire));
101 cval[abit.offset] = val;
102 abit.wire->attributes[ID::init] = cval;
103 }
104 }
105
106 void set_init(const RTLIL::SigSpec &sig, RTLIL::Const val)
107 {
108 log_assert(GetSize(sig) == GetSize(val));
109 for (int i = 0; i < GetSize(sig); i++)
110 set_init(sig[i], val[i]);
111 }
112
113 void remove_init(RTLIL::SigBit bit)
114 {
115 set_init(bit, State::Sx);
116 }
117
118 void remove_init(const RTLIL::SigSpec &sig)
119 {
120 for (auto bit : sig)
121 remove_init(bit);
122 }
123
124 void clear()
125 {
126 initbits.clear();
127 }
128
129 FfInitVals (const SigMap *sigmap, RTLIL::Module *module)
130 {
131 set(sigmap, module);
132 }
133
134 FfInitVals () {}
135 };
136
137
138 YOSYS_NAMESPACE_END
139
140 #endif