blob: 85995a6b75f576e6daa478d786dc45b62106588a [file] [log] [blame]
Zane Shelley5a266612019-08-15 16:23:53 -05001
Zane Shelley7bf1f6d2019-10-18 16:03:51 -05002#include <isolator/hei_isolation_node.hpp>
Zane Shelleyca9f6252019-10-25 21:17:30 -05003#include <isolator/hei_isolator.hpp>
Zane Shelleyb0559b92019-12-05 22:18:20 -06004#include <register/hei_operator_register.hpp>
Zane Shelley75e68e92019-10-18 16:16:23 -05005#include <register/hei_scom_register.hpp>
Zane Shelleydd69c962020-05-05 22:19:11 -05006#include <util/hei_flyweight.hpp>
Zane Shelleyd5073512021-01-14 12:51:18 -06007#include <util/hei_includes.hpp>
Zane Shelley75e68e92019-10-18 16:16:23 -05008
Zane Shelley5a266612019-08-15 16:23:53 -05009namespace libhei
10{
11
Zane Shelley3a02e242020-05-08 16:25:36 -050012//------------------------------------------------------------------------------
13
14// Definitions for the interfaces defined in hei_main.hpp.
15
16void initialize(void* i_buffer, size_t i_bufferSize)
17{
18 Isolator::getSingleton().initialize(i_buffer, i_bufferSize);
19}
20
21void uninitialize()
22{
23 Isolator::getSingleton().uninitialize();
24}
25
26void isolate(const std::vector<Chip>& i_chipList, IsolationData& o_isoData)
27{
28 Isolator::getSingleton().isolate(i_chipList, o_isoData);
29}
30
31//------------------------------------------------------------------------------
32
Zane Shelley5a266612019-08-15 16:23:53 -050033void Isolator::uninitialize()
34{
Zane Shelleyd39aa572020-05-14 10:35:57 -050035 // Clear all of the isolation objects.
Zane Shelleydd69c962020-05-05 22:19:11 -050036 iv_isoChips.clear();
37
Zane Shelleyd0af3582019-09-19 10:48:59 -050038 // Must flush the hardware register cache before deleting any
39 // HardwareRegister objects.
40 HardwareRegister::flushAll();
41
Zane Shelleyf8c92f92020-05-16 10:17:16 -050042 // Clear the operator register flyweights.
43 Flyweight<const ConstantRegister>::getSingleton().clear();
44 Flyweight<const AndRegister>::getSingleton().clear();
45 Flyweight<const OrRegister>::getSingleton().clear();
46 Flyweight<const NotRegister>::getSingleton().clear();
47 Flyweight<const LeftShiftRegister>::getSingleton().clear();
48 Flyweight<const RightShiftRegister>::getSingleton().clear();
49
Zane Shelley7bf1f6d2019-10-18 16:03:51 -050050 // Remove all of the HardwareRegister objects stored in the flyweights.
Zane Shelley981e56a2020-05-11 21:24:20 -050051 Flyweight<const ScomRegister>::getSingleton().clear();
52 Flyweight<const IdScomRegister>::getSingleton().clear();
Zane Shelley5a266612019-08-15 16:23:53 -050053}
54
Zane Shelley229c1552020-05-04 22:44:15 -050055void Isolator::isolate(const std::vector<Chip>& i_chipList,
56 IsolationData& o_isoData) const
Zane Shelley5a266612019-08-15 16:23:53 -050057{
Zane Shelley5a266612019-08-15 16:23:53 -050058 // Flush the isolation data to ensure a clean slate.
Zane Shelley93b61ad2019-10-16 20:41:03 -050059 o_isoData.flush();
Zane Shelley5a266612019-08-15 16:23:53 -050060
Zane Shelleyd0af3582019-09-19 10:48:59 -050061 // Flush the hardware register cache to avoid using stale data.
62 HardwareRegister::flushAll();
63
Zane Shelley61565dc2019-09-18 21:57:10 -050064 // Analyze active error on each chip.
Zane Shelleyfe27b652019-10-28 11:33:07 -050065 for (const auto& chip : i_chipList)
Zane Shelleyb406de42019-09-09 16:10:38 -050066 {
Zane Shelleydd69c962020-05-05 22:19:11 -050067 // Isolation objects for this chip's type must exist.
68 const auto& itr = iv_isoChips.find(chip.getType());
69 HEI_ASSERT(iv_isoChips.end() != itr);
70
71 // Analyze this chip.
72 itr->second->analyze(chip, o_isoData);
Zane Shelleyb406de42019-09-09 16:10:38 -050073 }
Zane Shelley5a266612019-08-15 16:23:53 -050074}
75
Caleb Palmere4ad4e32024-08-07 09:48:14 -050076//------------------------------------------------------------------------------
77
78#ifdef __HEI_ENABLE_HW_WRITE
79
80bool __atomicOr(Signature i_sig, HardwareRegister::ConstPtr i_hwReg)
81{
82 // Input register is for an atomic OR register used for setting a bit. Get
83 // the bit in the input signature and write that bit to the register.
84 i_hwReg->clearAllBits(i_sig.getChip());
85 i_hwReg->setBit(i_sig.getChip(), i_sig.getBit());
86
87 return i_hwReg->write(i_sig.getChip());
88}
89
90bool __atomicAnd(Signature i_sig, HardwareRegister::ConstPtr i_hwReg)
91{
92 // Input register is for an atomic AND register used for clearing a bit. Get
93 // the bit in the input signature and write that bit to the register.
94 i_hwReg->setAllBits(i_sig.getChip());
95 i_hwReg->clearBit(i_sig.getChip(), i_sig.getBit());
96
97 return i_hwReg->write(i_sig.getChip());
98}
99
100bool __readSetWrite(Signature i_sig, HardwareRegister::ConstPtr i_hwReg)
101{
102 // Perform a read, modify, write to set a bit. Get the bit from the input
103 // signature.
104 if (i_hwReg->read(i_sig.getChip(), true))
105 {
106 HEI_ERR("Failed to read reg ID 0x%04x", i_hwReg->getId());
107 return true;
108 }
109 i_hwReg->setBit(i_sig.getChip(), i_sig.getBit());
110
111 return i_hwReg->write(i_sig.getChip());
112}
113
114bool __readClearWrite(Signature i_sig, HardwareRegister::ConstPtr i_hwReg)
115{
116 // Perform a read, modify, write to clear a bit. Get the bit from the input
117 // signature.
118 if (i_hwReg->read(i_sig.getChip(), true))
119 {
120 HEI_ERR("Failed to read reg ID 0x%04x", i_hwReg->getId());
121 return true;
122 }
123 i_hwReg->clearBit(i_sig.getChip(), i_sig.getBit());
124
125 return i_hwReg->write(i_sig.getChip());
126}
127
128bool Isolator::performWriteOp(OpRuleName_t i_op, Signature i_sig)
129{
130 // Return true on a failure.
131 bool writefail = false;
132
133 // Use the signature to determine the relevant isolation node.
134 IsolationNode::Key nodeKey = {i_sig.getId(), i_sig.getInstance()};
135 IsolationChip::ConstPtr isoChip = iv_isoChips.at(i_sig.getChip().getType());
136 IsolationNode::ConstPtr node = isoChip->getIsolationNode(nodeKey);
137
138 // If the operation name does not exist for the node, print an error
139 // message and return.
140 if (!node->doesOpExist(i_op))
141 {
142 HEI_ERR("Operation rule %d does not exist for node 0x%04x", i_op,
143 node->getId());
144 writeFail = true;
145 return writeFail;
146 }
147
148 // Get the write operation defined in the node.
149 std::pair<OpRuleType_t, RegisterId_t> op = node->getOpRule(i_op);
150
151 // Get the relevant hardware register from the isolation chip. The instance
152 // of the register should match the instance of the signature.
153 HardwareRegister::Key regKey = {op.second, i_sig.getInstance()};
154 HardwareRegister::ConstPtr hwReg = isoChip->getHardwareRegister(regKey);
155
156 // Perform write operation dependent on the operation type.
157 switch (op.first)
158 {
159 case ATOMIC_OR:
160 {
161 if (__atomicOr(i_sig, hwReg))
162 {
163 HEI_ERR("Failed performing ATOMIC_OR write operation %d on "
164 "node 0x%04x",
165 i_op, node->getId());
166 writeFail = true;
167 }
168 break;
169 }
170 case ATOMIC_AND:
171 {
172 if (__atomicAnd(i_sig, hwReg))
173 {
174 HEI_ERR("Failed performing ATOMIC_AND write operation %d on "
175 "node 0x%04x",
176 i_op, node->getId());
177 writeFail = true;
178 }
179 break;
180 }
181 case READ_SET_WRITE:
182 {
183 if (__readSetWrite(i_sig, hwReg))
184 {
185 HEI_ERR("Failed performing READ_SET_WRITE write operation %d "
186 "on node 0x%04x",
187 i_op, node->getId());
188 writeFail = true;
189 }
190 break;
191 }
192 case READ_CLEAR_WRITE:
193 {
194 if (__readClearWrite(i_sig, hwReg))
195 {
196 HEI_ERR("Failed performing READ_CLEAR_WRITE write operation %d "
197 "on node 0x%04x",
198 i_op, node->getId());
199 writeFail = true;
200 }
201 break;
202 }
203 default:
204 {
205 HEI_ERR("Invalid operation type %d for op %d on node 0x%04x",
206 op.first, i_op, node->getId());
207 writeFail = true;
208 }
209 }
210
211 // Flush the affected register from the cache so it is re-read from hardware
212 // next time it is read.
213 hwReg->flush(i_sig.getChip());
214
215 return writeFail;
216}
217
218#endif
219
Zane Shelley5a266612019-08-15 16:23:53 -0500220} // end namespace libhei