Zane Shelley | 65fefb2 | 2021-10-18 15:35:26 -0500 | [diff] [blame] | 1 | #include <assert.h> |
| 2 | |
| 3 | #include <hei_main.hpp> |
| 4 | |
| 5 | #include <algorithm> |
| 6 | #include <limits> |
| 7 | #include <string> |
| 8 | |
| 9 | namespace analyzer |
| 10 | { |
| 11 | |
| 12 | //------------------------------------------------------------------------------ |
| 13 | |
Zane Shelley | a7369f8 | 2021-10-18 16:52:21 -0500 | [diff] [blame^] | 14 | uint64_t __hash(unsigned int i_bytes, const std::string& i_str) |
| 15 | { |
| 16 | // This hash is a simple "n*s[0] + (n-1)*s[1] + ... + s[n-1]" algorithm, |
| 17 | // where s[i] is a chunk from the input string the length of i_bytes. |
| 18 | |
| 19 | // Currently only supporting 1-8 byte hashes. |
| 20 | assert(1 <= i_bytes && i_bytes <= sizeof(uint64_t)); |
| 21 | |
| 22 | // Start hashing each chunk. |
| 23 | uint64_t sumA = 0; |
| 24 | uint64_t sumB = 0; |
| 25 | |
| 26 | // Iterate one chunk at a time. |
| 27 | for (unsigned int i = 0; i < i_str.size(); i += i_bytes) |
| 28 | { |
| 29 | // Combine each chunk into a single integer value. If we reach the end |
| 30 | // of the string, pad with null characters. |
| 31 | uint64_t chunk = 0; |
| 32 | for (unsigned int j = 0; j < i_bytes; j++) |
| 33 | { |
| 34 | chunk <<= 8; |
| 35 | chunk |= (i + j < i_str.size()) ? i_str[i + j] : '\0'; |
| 36 | } |
| 37 | |
| 38 | // Apply the simple hash. |
| 39 | sumA += chunk; |
| 40 | sumB += sumA; |
| 41 | } |
| 42 | |
| 43 | // Mask off everything except the target number of bytes. |
| 44 | auto mask = std::numeric_limits<uint64_t>::max(); |
| 45 | sumB &= mask >> ((sizeof(uint64_t) - i_bytes) * 8); |
| 46 | |
| 47 | return sumB; |
| 48 | } |
| 49 | |
| 50 | //------------------------------------------------------------------------------ |
| 51 | |
| 52 | bool __findRcsOscError(const std::vector<libhei::Signature>& i_list, |
| 53 | libhei::Signature& o_rootCause) |
| 54 | { |
| 55 | // TODO: Consider returning all of them instead of one as root cause. |
| 56 | auto itr = std::find_if(i_list.begin(), i_list.end(), [&](const auto& t) { |
| 57 | return (__hash(2, "TP_LOCAL_FIR") == t.getId() && |
| 58 | (42 == t.getBit() || 43 == t.getBit())); |
| 59 | }); |
| 60 | |
| 61 | if (i_list.end() != itr) |
| 62 | { |
| 63 | o_rootCause = *itr; |
| 64 | return true; |
| 65 | } |
| 66 | |
| 67 | return false; |
| 68 | } |
| 69 | |
| 70 | //------------------------------------------------------------------------------ |
| 71 | |
| 72 | bool __findPllUnlock(const std::vector<libhei::Signature>& i_list, |
| 73 | libhei::Signature& o_rootCause) |
| 74 | { |
| 75 | // TODO: Consider returning all of them instead of one as root cause. |
| 76 | auto itr = std::find_if(i_list.begin(), i_list.end(), [&](const auto& t) { |
| 77 | return (__hash(2, "PLL_UNLOCK") == t.getId() && |
| 78 | (0 == t.getBit() || 1 == t.getBit())); |
| 79 | }); |
| 80 | |
| 81 | if (i_list.end() != itr) |
| 82 | { |
| 83 | o_rootCause = *itr; |
| 84 | return true; |
| 85 | } |
| 86 | |
| 87 | return false; |
| 88 | } |
| 89 | |
| 90 | //------------------------------------------------------------------------------ |
| 91 | |
Zane Shelley | 65fefb2 | 2021-10-18 15:35:26 -0500 | [diff] [blame] | 92 | bool filterRootCause(const libhei::IsolationData& i_isoData, |
| 93 | libhei::Signature& o_rootCause) |
| 94 | { |
| 95 | // We'll need to make a copy of the list so that the original list is |
| 96 | // maintained for the log. |
| 97 | std::vector<libhei::Signature> list{i_isoData.getSignatureList()}; |
| 98 | |
| 99 | // START WORKAROUND |
| 100 | // TODO: Filtering should be data driven. Until that support is available, |
| 101 | // use the following isolation rules. |
| 102 | |
| 103 | // Special and host attentions are not supported by this user application. |
| 104 | auto itr = std::remove_if(list.begin(), list.end(), [&](const auto& t) { |
| 105 | return (libhei::ATTN_TYPE_SP_ATTN == t.getAttnType() || |
| 106 | libhei::ATTN_TYPE_HOST_ATTN == t.getAttnType()); |
| 107 | }); |
| 108 | list.resize(std::distance(list.begin(), itr)); |
| 109 | |
Zane Shelley | a7369f8 | 2021-10-18 16:52:21 -0500 | [diff] [blame^] | 110 | // Look for: |
| 111 | // - any RCS OSC errors (always first) |
| 112 | // - any PLL unlock attentions (always second) |
| 113 | if (__findRcsOscError(list, o_rootCause) || |
| 114 | __findPllUnlock(list, o_rootCause)) |
| 115 | { |
| 116 | return true; |
| 117 | } |
| 118 | |
Zane Shelley | 65fefb2 | 2021-10-18 15:35:26 -0500 | [diff] [blame] | 119 | // TODO: This is a rudimentary filter that first looks for any recoverable |
| 120 | // attention, then any unit checkstop, and then any system checkstop. |
| 121 | // This is built on the premise that recoverable errors could be the |
| 122 | // root cause of an system checkstop attentions. Fortunately, we |
| 123 | // just need to sort the list by the greater attention type value. |
| 124 | std::sort(list.begin(), list.end(), [&](const auto& a, const auto& b) { |
| 125 | return a.getAttnType() > b.getAttnType(); |
| 126 | }); |
| 127 | if (!list.empty()) |
| 128 | { |
| 129 | // The entry at the front of the list will be the root cause. |
| 130 | o_rootCause = list.front(); |
| 131 | return true; |
| 132 | } |
| 133 | |
| 134 | // END WORKAROUND |
| 135 | |
| 136 | return false; // default, no active attentions found. |
| 137 | } |
| 138 | |
| 139 | //------------------------------------------------------------------------------ |
| 140 | |
| 141 | } // namespace analyzer |