Zane Shelley | 5a26661 | 2019-08-15 16:23:53 -0500 | [diff] [blame] | 1 | |
Zane Shelley | 7bf1f6d | 2019-10-18 16:03:51 -0500 | [diff] [blame] | 2 | #include <isolator/hei_isolation_node.hpp> |
Zane Shelley | ca9f625 | 2019-10-25 21:17:30 -0500 | [diff] [blame] | 3 | #include <isolator/hei_isolator.hpp> |
Zane Shelley | b0559b9 | 2019-12-05 22:18:20 -0600 | [diff] [blame] | 4 | #include <register/hei_operator_register.hpp> |
Zane Shelley | 75e68e9 | 2019-10-18 16:16:23 -0500 | [diff] [blame] | 5 | #include <register/hei_scom_register.hpp> |
Zane Shelley | dd69c96 | 2020-05-05 22:19:11 -0500 | [diff] [blame] | 6 | #include <util/hei_flyweight.hpp> |
Zane Shelley | d507351 | 2021-01-14 12:51:18 -0600 | [diff] [blame] | 7 | #include <util/hei_includes.hpp> |
Zane Shelley | 75e68e9 | 2019-10-18 16:16:23 -0500 | [diff] [blame] | 8 | |
Zane Shelley | 5a26661 | 2019-08-15 16:23:53 -0500 | [diff] [blame] | 9 | namespace libhei |
| 10 | { |
| 11 | |
Zane Shelley | 3a02e24 | 2020-05-08 16:25:36 -0500 | [diff] [blame] | 12 | //------------------------------------------------------------------------------ |
| 13 | |
| 14 | // Definitions for the interfaces defined in hei_main.hpp. |
| 15 | |
| 16 | void initialize(void* i_buffer, size_t i_bufferSize) |
| 17 | { |
| 18 | Isolator::getSingleton().initialize(i_buffer, i_bufferSize); |
| 19 | } |
| 20 | |
| 21 | void uninitialize() |
| 22 | { |
| 23 | Isolator::getSingleton().uninitialize(); |
| 24 | } |
| 25 | |
| 26 | void isolate(const std::vector<Chip>& i_chipList, IsolationData& o_isoData) |
| 27 | { |
| 28 | Isolator::getSingleton().isolate(i_chipList, o_isoData); |
| 29 | } |
| 30 | |
| 31 | //------------------------------------------------------------------------------ |
| 32 | |
Zane Shelley | 5a26661 | 2019-08-15 16:23:53 -0500 | [diff] [blame] | 33 | void Isolator::uninitialize() |
| 34 | { |
Zane Shelley | d39aa57 | 2020-05-14 10:35:57 -0500 | [diff] [blame] | 35 | // Clear all of the isolation objects. |
Zane Shelley | dd69c96 | 2020-05-05 22:19:11 -0500 | [diff] [blame] | 36 | iv_isoChips.clear(); |
| 37 | |
Zane Shelley | d0af358 | 2019-09-19 10:48:59 -0500 | [diff] [blame] | 38 | // Must flush the hardware register cache before deleting any |
| 39 | // HardwareRegister objects. |
| 40 | HardwareRegister::flushAll(); |
| 41 | |
Zane Shelley | f8c92f9 | 2020-05-16 10:17:16 -0500 | [diff] [blame] | 42 | // 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 Shelley | 7bf1f6d | 2019-10-18 16:03:51 -0500 | [diff] [blame] | 50 | // Remove all of the HardwareRegister objects stored in the flyweights. |
Zane Shelley | 981e56a | 2020-05-11 21:24:20 -0500 | [diff] [blame] | 51 | Flyweight<const ScomRegister>::getSingleton().clear(); |
| 52 | Flyweight<const IdScomRegister>::getSingleton().clear(); |
Zane Shelley | 5a26661 | 2019-08-15 16:23:53 -0500 | [diff] [blame] | 53 | } |
| 54 | |
Zane Shelley | 229c155 | 2020-05-04 22:44:15 -0500 | [diff] [blame] | 55 | void Isolator::isolate(const std::vector<Chip>& i_chipList, |
| 56 | IsolationData& o_isoData) const |
Zane Shelley | 5a26661 | 2019-08-15 16:23:53 -0500 | [diff] [blame] | 57 | { |
Zane Shelley | 5a26661 | 2019-08-15 16:23:53 -0500 | [diff] [blame] | 58 | // Flush the isolation data to ensure a clean slate. |
Zane Shelley | 93b61ad | 2019-10-16 20:41:03 -0500 | [diff] [blame] | 59 | o_isoData.flush(); |
Zane Shelley | 5a26661 | 2019-08-15 16:23:53 -0500 | [diff] [blame] | 60 | |
Zane Shelley | d0af358 | 2019-09-19 10:48:59 -0500 | [diff] [blame] | 61 | // Flush the hardware register cache to avoid using stale data. |
| 62 | HardwareRegister::flushAll(); |
| 63 | |
Zane Shelley | 61565dc | 2019-09-18 21:57:10 -0500 | [diff] [blame] | 64 | // Analyze active error on each chip. |
Zane Shelley | fe27b65 | 2019-10-28 11:33:07 -0500 | [diff] [blame] | 65 | for (const auto& chip : i_chipList) |
Zane Shelley | b406de4 | 2019-09-09 16:10:38 -0500 | [diff] [blame] | 66 | { |
Zane Shelley | dd69c96 | 2020-05-05 22:19:11 -0500 | [diff] [blame] | 67 | // 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 Shelley | b406de4 | 2019-09-09 16:10:38 -0500 | [diff] [blame] | 73 | } |
Zane Shelley | 5a26661 | 2019-08-15 16:23:53 -0500 | [diff] [blame] | 74 | } |
| 75 | |
Caleb Palmer | e4ad4e3 | 2024-08-07 09:48:14 -0500 | [diff] [blame^] | 76 | //------------------------------------------------------------------------------ |
| 77 | |
| 78 | #ifdef __HEI_ENABLE_HW_WRITE |
| 79 | |
| 80 | bool __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 | |
| 90 | bool __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 | |
| 100 | bool __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 | |
| 114 | bool __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 | |
| 128 | bool 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 Shelley | 5a26661 | 2019-08-15 16:23:53 -0500 | [diff] [blame] | 220 | } // end namespace libhei |