Zane Shelley | 7bf1f6d | 2019-10-18 16:03:51 -0500 | [diff] [blame] | 1 | #include <isolator/hei_isolation_node.hpp> |
Zane Shelley | 6722b5b | 2020-05-12 22:09:04 -0500 | [diff] [blame] | 2 | #include <util/hei_bit_string.hpp> |
Zane Shelley | 7bf1f6d | 2019-10-18 16:03:51 -0500 | [diff] [blame] | 3 | |
| 4 | namespace libhei |
| 5 | { |
| 6 | |
| 7 | //------------------------------------------------------------------------------ |
| 8 | |
Zane Shelley | fe27b65 | 2019-10-28 11:33:07 -0500 | [diff] [blame] | 9 | bool IsolationNode::analyze(const Chip& i_chip, AttentionType_t i_attnType, |
| 10 | IsolationData& io_isoData) const |
Zane Shelley | 7bf1f6d | 2019-10-18 16:03:51 -0500 | [diff] [blame] | 11 | { |
| 12 | bool o_activeAttn = false; // Initially, assume no active attentions. |
| 13 | |
| 14 | // Keep track of nodes that have been analyzed to avoid cyclic isolation. |
| 15 | pushIsolationStack(); |
| 16 | |
Zane Shelley | e8dc72c | 2020-05-14 16:40:52 -0500 | [diff] [blame] | 17 | // Capture all registers for this node. |
| 18 | for (const auto& hwReg : iv_capRegs) |
| 19 | { |
| 20 | // Read the register (adds BitString to register cache). |
| 21 | if (hwReg->read(i_chip)) |
| 22 | { |
| 23 | // TODO: Would be nice to add SCOM errors to the log just in case |
| 24 | // traces are not available. |
| 25 | HEI_ERR("register read failed on chip type=0x%0" PRIx32 |
| 26 | "address=0x%0" PRIx64, |
| 27 | i_chip.getType(), hwReg->getAddress()); |
| 28 | } |
| 29 | |
| 30 | // TODO: Add this register to io_isoData. |
| 31 | // TODO: getBitString() does read hardware if read() has not been called |
| 32 | // and there is nothing in the register cache. However, it does |
| 33 | // not does not indicate if the read was successful. Not sure if |
| 34 | // this is intentional. Will need to investigate. |
| 35 | // auto bs = hwReg->getBitString(); |
| 36 | } |
| 37 | |
Zane Shelley | 7bf1f6d | 2019-10-18 16:03:51 -0500 | [diff] [blame] | 38 | // A rule for i_attnType must exist. |
Zane Shelley | 83da245 | 2019-10-25 15:45:34 -0500 | [diff] [blame] | 39 | auto rule_itr = iv_rules.find(i_attnType); |
| 40 | HEI_ASSERT(iv_rules.end() != rule_itr); |
Zane Shelley | 7bf1f6d | 2019-10-18 16:03:51 -0500 | [diff] [blame] | 41 | |
| 42 | // Get the returned BitString for this rule. |
Zane Shelley | fe27b65 | 2019-10-28 11:33:07 -0500 | [diff] [blame] | 43 | const BitString* bs = rule_itr->second->getBitString(i_chip); |
Zane Shelley | 7bf1f6d | 2019-10-18 16:03:51 -0500 | [diff] [blame] | 44 | |
| 45 | // Ensure this BitString is not longer than the maximum bit field. |
Zane Shelley | 13b182b | 2020-05-07 20:23:45 -0500 | [diff] [blame] | 46 | HEI_ASSERT(bs->getBitLen() <= (1 << (sizeof(BitPosition_t) * 8))); |
Zane Shelley | 7bf1f6d | 2019-10-18 16:03:51 -0500 | [diff] [blame] | 47 | |
| 48 | // Find all active bits for this rule. |
Zane Shelley | 13b182b | 2020-05-07 20:23:45 -0500 | [diff] [blame] | 49 | for (BitPosition_t bit = 0; bit < bs->getBitLen(); bit++) |
Zane Shelley | 7bf1f6d | 2019-10-18 16:03:51 -0500 | [diff] [blame] | 50 | { |
| 51 | // Continue to the next bit if not active. |
Zane Shelley | 7f7a42d | 2019-10-28 13:28:31 -0500 | [diff] [blame] | 52 | if (!bs->isBitSet(bit)) |
| 53 | continue; |
Zane Shelley | 7bf1f6d | 2019-10-18 16:03:51 -0500 | [diff] [blame] | 54 | |
| 55 | // At least one active bit was found. |
| 56 | o_activeAttn = true; |
| 57 | |
| 58 | // Determine if this attention originated from another register or if it |
| 59 | // is a leaf in the isolation tree. |
Zane Shelley | 83da245 | 2019-10-25 15:45:34 -0500 | [diff] [blame] | 60 | auto child_itr = iv_children.find(bit); |
| 61 | if (iv_children.end() != child_itr) |
Zane Shelley | 7bf1f6d | 2019-10-18 16:03:51 -0500 | [diff] [blame] | 62 | { |
| 63 | // This bit was driven from an attention from another register. |
| 64 | // Continue down the isolation tree to look for more attentions. |
Zane Shelley | 7f7a42d | 2019-10-28 13:28:31 -0500 | [diff] [blame] | 65 | bool attnFound = |
| 66 | child_itr->second->analyze(i_chip, i_attnType, io_isoData); |
Zane Shelley | 83da245 | 2019-10-25 15:45:34 -0500 | [diff] [blame] | 67 | if (!attnFound) |
Zane Shelley | 7bf1f6d | 2019-10-18 16:03:51 -0500 | [diff] [blame] | 68 | { |
| 69 | // Something went wrong. There should have been an active |
| 70 | // attention. It's possible there is a bug in the Chip Data |
| 71 | // File. Or, it is also possible some other piece of code is |
| 72 | // clearing the attention before this code is able to analyze |
| 73 | // it. Another possibility is that the hardware it not behaving |
| 74 | // as expected. Since we really don't know what happened, we |
| 75 | // should not assert. Instead, add this bit's signature to |
| 76 | // io_isoData. If there are no other active attentions, the user |
| 77 | // application could use this signature to help determine, and |
| 78 | // circumvent, the isolation problem. |
Zane Shelley | 6722b5b | 2020-05-12 22:09:04 -0500 | [diff] [blame] | 79 | io_isoData.addSignature( |
| 80 | Signature{i_chip, iv_id, iv_instance, bit, i_attnType}); |
Zane Shelley | 7bf1f6d | 2019-10-18 16:03:51 -0500 | [diff] [blame] | 81 | } |
| 82 | } |
| 83 | else |
| 84 | { |
| 85 | // We have reached a leaf in the isolation tree. Add this bit's |
| 86 | // signature to io_isoData. |
Zane Shelley | 6722b5b | 2020-05-12 22:09:04 -0500 | [diff] [blame] | 87 | io_isoData.addSignature( |
| 88 | Signature{i_chip, iv_id, iv_instance, bit, i_attnType}); |
Zane Shelley | 7bf1f6d | 2019-10-18 16:03:51 -0500 | [diff] [blame] | 89 | } |
| 90 | } |
| 91 | |
| 92 | // Analysis is complete on this node. So remove it from cv_isolationStack. |
| 93 | popIsolationStack(); |
| 94 | |
| 95 | return o_activeAttn; |
| 96 | } |
| 97 | |
| 98 | //------------------------------------------------------------------------------ |
| 99 | |
Zane Shelley | e8dc72c | 2020-05-14 16:40:52 -0500 | [diff] [blame] | 100 | void IsolationNode::addCaptureRegister(HardwareRegister::ConstPtr i_hwReg) |
| 101 | { |
| 102 | HEI_ASSERT(i_hwReg); // should not be null |
| 103 | |
| 104 | // If the register already exists, ignore it. Otherwise, add it to the list. |
| 105 | auto itr = std::find(iv_capRegs.begin(), iv_capRegs.end(), i_hwReg); |
| 106 | if (iv_capRegs.end() == itr) |
| 107 | { |
| 108 | iv_capRegs.push_back(i_hwReg); |
| 109 | } |
| 110 | } |
| 111 | |
| 112 | //------------------------------------------------------------------------------ |
| 113 | |
Zane Shelley | 4de8ff8 | 2020-05-14 15:39:01 -0500 | [diff] [blame] | 114 | void IsolationNode::addRule(AttentionType_t i_attnType, |
| 115 | Register::ConstPtr i_rule) |
Zane Shelley | 7bf1f6d | 2019-10-18 16:03:51 -0500 | [diff] [blame] | 116 | { |
Zane Shelley | 6722b5b | 2020-05-12 22:09:04 -0500 | [diff] [blame] | 117 | HEI_ASSERT(i_rule); // should not be null |
Zane Shelley | 7bf1f6d | 2019-10-18 16:03:51 -0500 | [diff] [blame] | 118 | |
Zane Shelley | 6722b5b | 2020-05-12 22:09:04 -0500 | [diff] [blame] | 119 | auto ret = iv_rules.emplace(i_attnType, i_rule); |
Zane Shelley | 7bf1f6d | 2019-10-18 16:03:51 -0500 | [diff] [blame] | 120 | |
Zane Shelley | 6722b5b | 2020-05-12 22:09:04 -0500 | [diff] [blame] | 121 | // If an entry already existed, it must point to the same object. |
| 122 | HEI_ASSERT(ret.second || (ret.first->second == i_rule)); |
Zane Shelley | 7bf1f6d | 2019-10-18 16:03:51 -0500 | [diff] [blame] | 123 | } |
| 124 | |
| 125 | //------------------------------------------------------------------------------ |
| 126 | |
Zane Shelley | 4de8ff8 | 2020-05-14 15:39:01 -0500 | [diff] [blame] | 127 | void IsolationNode::addChild(uint8_t i_bit, ConstPtr i_child) |
Zane Shelley | 7bf1f6d | 2019-10-18 16:03:51 -0500 | [diff] [blame] | 128 | { |
Zane Shelley | 6722b5b | 2020-05-12 22:09:04 -0500 | [diff] [blame] | 129 | HEI_ASSERT(i_child); // should not be null |
Zane Shelley | 7bf1f6d | 2019-10-18 16:03:51 -0500 | [diff] [blame] | 130 | |
Zane Shelley | 6722b5b | 2020-05-12 22:09:04 -0500 | [diff] [blame] | 131 | auto ret = iv_children.emplace(i_bit, i_child); |
Zane Shelley | 7bf1f6d | 2019-10-18 16:03:51 -0500 | [diff] [blame] | 132 | |
Zane Shelley | 6722b5b | 2020-05-12 22:09:04 -0500 | [diff] [blame] | 133 | // If an entry already existed, it must point to the same object. |
| 134 | HEI_ASSERT(ret.second || (ret.first->second == i_child)); |
Zane Shelley | 7bf1f6d | 2019-10-18 16:03:51 -0500 | [diff] [blame] | 135 | } |
| 136 | |
| 137 | //------------------------------------------------------------------------------ |
| 138 | |
Zane Shelley | 4de8ff8 | 2020-05-14 15:39:01 -0500 | [diff] [blame] | 139 | std::vector<IsolationNode::ConstPtr> IsolationNode::cv_isolationStack{}; |
Zane Shelley | 7bf1f6d | 2019-10-18 16:03:51 -0500 | [diff] [blame] | 140 | |
| 141 | //------------------------------------------------------------------------------ |
| 142 | |
| 143 | void IsolationNode::pushIsolationStack() const |
| 144 | { |
| 145 | // Ensure this node does not already exist in cv_isolationStack. |
Zane Shelley | 6722b5b | 2020-05-12 22:09:04 -0500 | [diff] [blame] | 146 | auto itr = std::find(cv_isolationStack.begin(), cv_isolationStack.end(), |
Zane Shelley | 4de8ff8 | 2020-05-14 15:39:01 -0500 | [diff] [blame] | 147 | ConstPtr(this)); |
Zane Shelley | 83da245 | 2019-10-25 15:45:34 -0500 | [diff] [blame] | 148 | HEI_ASSERT(cv_isolationStack.end() == itr); |
Zane Shelley | 7bf1f6d | 2019-10-18 16:03:51 -0500 | [diff] [blame] | 149 | |
| 150 | // Push to node to the stack. |
Zane Shelley | 4de8ff8 | 2020-05-14 15:39:01 -0500 | [diff] [blame] | 151 | cv_isolationStack.push_back(ConstPtr(this)); |
Zane Shelley | 7bf1f6d | 2019-10-18 16:03:51 -0500 | [diff] [blame] | 152 | } |
| 153 | |
| 154 | //------------------------------------------------------------------------------ |
| 155 | |
| 156 | } // end namespace libhei |