blob: 98f9ca4c9d8f38a1e90e8c3628a6b4e6cd087b3d [file] [log] [blame]
Zane Shelley7bf1f6d2019-10-18 16:03:51 -05001#include <isolator/hei_isolation_node.hpp>
Zane Shelley6722b5b2020-05-12 22:09:04 -05002#include <util/hei_bit_string.hpp>
Zane Shelley7bf1f6d2019-10-18 16:03:51 -05003
4namespace libhei
5{
6
7//------------------------------------------------------------------------------
8
Zane Shelleyfe27b652019-10-28 11:33:07 -05009bool IsolationNode::analyze(const Chip& i_chip, AttentionType_t i_attnType,
10 IsolationData& io_isoData) const
Zane Shelley7bf1f6d2019-10-18 16:03:51 -050011{
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 Shelleye8dc72c2020-05-14 16:40:52 -050017 // 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.
Zane Shelley734cfe92020-08-10 19:57:27 -050025 // TODO: This trace could be redundant with the user application,
26 // which will have more information on the actual chip that
27 // failed anyway. Leaving it commented out for now until the
28 // SCOM errors are added to the log.
29 // HEI_ERR("register read failed on chip type=0x%0" PRIx32
30 // "address=0x%0" PRIx64,
31 // i_chip.getType(), hwReg->getAddress());
Zane Shelleye8dc72c2020-05-14 16:40:52 -050032 }
33
34 // TODO: Add this register to io_isoData.
35 // TODO: getBitString() does read hardware if read() has not been called
36 // and there is nothing in the register cache. However, it does
37 // not does not indicate if the read was successful. Not sure if
38 // this is intentional. Will need to investigate.
39 // auto bs = hwReg->getBitString();
40 }
41
Zane Shelley7bf1f6d2019-10-18 16:03:51 -050042 // A rule for i_attnType must exist.
Zane Shelley83da2452019-10-25 15:45:34 -050043 auto rule_itr = iv_rules.find(i_attnType);
44 HEI_ASSERT(iv_rules.end() != rule_itr);
Zane Shelley7bf1f6d2019-10-18 16:03:51 -050045
46 // Get the returned BitString for this rule.
Zane Shelleyfe27b652019-10-28 11:33:07 -050047 const BitString* bs = rule_itr->second->getBitString(i_chip);
Zane Shelley7bf1f6d2019-10-18 16:03:51 -050048
49 // Ensure this BitString is not longer than the maximum bit field.
Zane Shelley13b182b2020-05-07 20:23:45 -050050 HEI_ASSERT(bs->getBitLen() <= (1 << (sizeof(BitPosition_t) * 8)));
Zane Shelley7bf1f6d2019-10-18 16:03:51 -050051
52 // Find all active bits for this rule.
Zane Shelley13b182b2020-05-07 20:23:45 -050053 for (BitPosition_t bit = 0; bit < bs->getBitLen(); bit++)
Zane Shelley7bf1f6d2019-10-18 16:03:51 -050054 {
55 // Continue to the next bit if not active.
Zane Shelley7f7a42d2019-10-28 13:28:31 -050056 if (!bs->isBitSet(bit))
57 continue;
Zane Shelley7bf1f6d2019-10-18 16:03:51 -050058
59 // At least one active bit was found.
60 o_activeAttn = true;
61
62 // Determine if this attention originated from another register or if it
63 // is a leaf in the isolation tree.
Zane Shelley83da2452019-10-25 15:45:34 -050064 auto child_itr = iv_children.find(bit);
65 if (iv_children.end() != child_itr)
Zane Shelley7bf1f6d2019-10-18 16:03:51 -050066 {
67 // This bit was driven from an attention from another register.
68 // Continue down the isolation tree to look for more attentions.
Zane Shelley7f7a42d2019-10-28 13:28:31 -050069 bool attnFound =
70 child_itr->second->analyze(i_chip, i_attnType, io_isoData);
Zane Shelley83da2452019-10-25 15:45:34 -050071 if (!attnFound)
Zane Shelley7bf1f6d2019-10-18 16:03:51 -050072 {
73 // Something went wrong. There should have been an active
74 // attention. It's possible there is a bug in the Chip Data
75 // File. Or, it is also possible some other piece of code is
76 // clearing the attention before this code is able to analyze
77 // it. Another possibility is that the hardware it not behaving
78 // as expected. Since we really don't know what happened, we
79 // should not assert. Instead, add this bit's signature to
80 // io_isoData. If there are no other active attentions, the user
81 // application could use this signature to help determine, and
82 // circumvent, the isolation problem.
Zane Shelley6722b5b2020-05-12 22:09:04 -050083 io_isoData.addSignature(
84 Signature{i_chip, iv_id, iv_instance, bit, i_attnType});
Zane Shelley7bf1f6d2019-10-18 16:03:51 -050085 }
86 }
87 else
88 {
89 // We have reached a leaf in the isolation tree. Add this bit's
90 // signature to io_isoData.
Zane Shelley6722b5b2020-05-12 22:09:04 -050091 io_isoData.addSignature(
92 Signature{i_chip, iv_id, iv_instance, bit, i_attnType});
Zane Shelley7bf1f6d2019-10-18 16:03:51 -050093 }
94 }
95
96 // Analysis is complete on this node. So remove it from cv_isolationStack.
97 popIsolationStack();
98
99 return o_activeAttn;
100}
101
102//------------------------------------------------------------------------------
103
Zane Shelleye8dc72c2020-05-14 16:40:52 -0500104void IsolationNode::addCaptureRegister(HardwareRegister::ConstPtr i_hwReg)
105{
106 HEI_ASSERT(i_hwReg); // should not be null
107
108 // If the register already exists, ignore it. Otherwise, add it to the list.
109 auto itr = std::find(iv_capRegs.begin(), iv_capRegs.end(), i_hwReg);
110 if (iv_capRegs.end() == itr)
111 {
112 iv_capRegs.push_back(i_hwReg);
113 }
114}
115
116//------------------------------------------------------------------------------
117
Zane Shelley4de8ff82020-05-14 15:39:01 -0500118void IsolationNode::addRule(AttentionType_t i_attnType,
119 Register::ConstPtr i_rule)
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500120{
Zane Shelley6722b5b2020-05-12 22:09:04 -0500121 HEI_ASSERT(i_rule); // should not be null
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500122
Zane Shelley6722b5b2020-05-12 22:09:04 -0500123 auto ret = iv_rules.emplace(i_attnType, i_rule);
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500124
Zane Shelley6722b5b2020-05-12 22:09:04 -0500125 // If an entry already existed, it must point to the same object.
126 HEI_ASSERT(ret.second || (ret.first->second == i_rule));
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500127}
128
129//------------------------------------------------------------------------------
130
Zane Shelley4de8ff82020-05-14 15:39:01 -0500131void IsolationNode::addChild(uint8_t i_bit, ConstPtr i_child)
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500132{
Zane Shelley6722b5b2020-05-12 22:09:04 -0500133 HEI_ASSERT(i_child); // should not be null
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500134
Zane Shelley6722b5b2020-05-12 22:09:04 -0500135 auto ret = iv_children.emplace(i_bit, i_child);
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500136
Zane Shelley6722b5b2020-05-12 22:09:04 -0500137 // If an entry already existed, it must point to the same object.
138 HEI_ASSERT(ret.second || (ret.first->second == i_child));
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500139}
140
141//------------------------------------------------------------------------------
142
Zane Shelley2467db82020-05-18 19:56:30 -0500143std::vector<const IsolationNode*> IsolationNode::cv_isolationStack{};
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500144
145//------------------------------------------------------------------------------
146
147void IsolationNode::pushIsolationStack() const
148{
149 // Ensure this node does not already exist in cv_isolationStack.
Zane Shelley2467db82020-05-18 19:56:30 -0500150 auto itr =
151 std::find(cv_isolationStack.begin(), cv_isolationStack.end(), this);
Zane Shelley83da2452019-10-25 15:45:34 -0500152 HEI_ASSERT(cv_isolationStack.end() == itr);
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500153
154 // Push to node to the stack.
Zane Shelley2467db82020-05-18 19:56:30 -0500155 cv_isolationStack.push_back(this);
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500156}
157
158//------------------------------------------------------------------------------
159
160} // end namespace libhei