blob: 1820d09235768aeb57e979f41b0f4eb31d43ff44 [file] [log] [blame]
Zane Shelley65fefb22021-10-18 15:35:26 -05001#include <assert.h>
2
3#include <hei_main.hpp>
4
5#include <algorithm>
6#include <limits>
7#include <string>
8
9namespace analyzer
10{
11
12//------------------------------------------------------------------------------
13
Zane Shelleya7369f82021-10-18 16:52:21 -050014uint64_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
52bool __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
72bool __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 Shelley65fefb22021-10-18 15:35:26 -050092bool 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 Shelleya7369f82021-10-18 16:52:21 -0500110 // 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 Shelley65fefb22021-10-18 15:35:26 -0500119 // 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