blob: a0bbf374835fe4c655f1eb812a2922954f2dfffc [file] [log] [blame]
Zane Shelley7bf1f6d2019-10-18 16:03:51 -05001#include <isolator/hei_isolation_node.hpp>
2
3namespace libhei
4{
5
6//------------------------------------------------------------------------------
7
8bool IsolationNode::analyze( const Chip & i_chip, AttentionType_t i_attnType,
9 IsolationData & io_isoData ) const
10{
11 bool o_activeAttn = false; // Initially, assume no active attentions.
12
13 // Keep track of nodes that have been analyzed to avoid cyclic isolation.
14 pushIsolationStack();
15
16 // A rule for i_attnType must exist.
17 auto rule_itr = iv_rules.find( i_attnType );
18 HEI_ASSERT( iv_rules.end() != rule_itr );
19
20 // Get the returned BitString for this rule.
21 const BitString * bs = rule_itr->second->getBitString( i_chip );
22
23 // Ensure this BitString is not longer than the maximum bit field.
24 HEI_ASSERT( bs->getBitLen() <= sizeof(RegisterBit_t) * 8 );
25
26 // Find all active bits for this rule.
27 for ( RegisterBit_t bit = 0; bit < bs->getBitLen(); bit++ )
28 {
29 // Continue to the next bit if not active.
30 if ( !bs->isBitSet(bit) ) continue;
31
32 // At least one active bit was found.
33 o_activeAttn = true;
34
35 // Determine if this attention originated from another register or if it
36 // is a leaf in the isolation tree.
37 auto child_itr = iv_children.find( bit );
38 if ( iv_children.end() != child_itr )
39 {
40 // This bit was driven from an attention from another register.
41 // Continue down the isolation tree to look for more attentions.
42 bool attnFound = child_itr->second->analyze( i_chip, i_attnType,
43 io_isoData );
44 if ( !attnFound )
45 {
46 // Something went wrong. There should have been an active
47 // attention. It's possible there is a bug in the Chip Data
48 // File. Or, it is also possible some other piece of code is
49 // clearing the attention before this code is able to analyze
50 // it. Another possibility is that the hardware it not behaving
51 // as expected. Since we really don't know what happened, we
52 // should not assert. Instead, add this bit's signature to
53 // io_isoData. If there are no other active attentions, the user
54 // application could use this signature to help determine, and
55 // circumvent, the isolation problem.
56 io_isoData.addSignature( Signature { i_chip, iv_hwReg.getId(),
57 iv_hwReg.getInstance(),
58 bit, i_attnType } );
59 }
60 }
61 else
62 {
63 // We have reached a leaf in the isolation tree. Add this bit's
64 // signature to io_isoData.
65 io_isoData.addSignature( Signature { i_chip, iv_hwReg.getId(),
66 iv_hwReg.getInstance(),
67 bit, i_attnType } );
68 }
69 }
70
71 // Analysis is complete on this node. So remove it from cv_isolationStack.
72 popIsolationStack();
73
74 return o_activeAttn;
75}
76
77//------------------------------------------------------------------------------
78
79void IsolationNode::addRule( AttentionType_t i_attnType,
80 const Register * i_rule )
81{
82 // A rule for this attention type should not already exist.
83 HEI_ASSERT( iv_rules.end() == iv_rules.find(i_attnType) );
84
85 // The rule should not be null.
86 HEI_ASSERT( nullptr != i_rule );
87
88 // Add the new rule.
89 iv_rules[i_attnType] = i_rule;
90}
91
92//------------------------------------------------------------------------------
93
94void IsolationNode::addChild( uint8_t i_bit, const IsolationNode * i_child )
95{
96 // An entry for this bit should not already exist.
97 HEI_ASSERT( iv_children.end() == iv_children.find(i_bit) );
98
99 // The child register should not be null.
100 HEI_ASSERT( nullptr != i_child );
101
102 // Add the new rule.
103 iv_children[i_bit] = i_child;
104}
105
106//------------------------------------------------------------------------------
107
108std::vector<const IsolationNode *> IsolationNode::cv_isolationStack {};
109
110//------------------------------------------------------------------------------
111
112void IsolationNode::pushIsolationStack() const
113{
114 // Ensure this node does not already exist in cv_isolationStack.
115 auto itr = std::find( cv_isolationStack.begin(),
116 cv_isolationStack.end(), this );
117 HEI_ASSERT( cv_isolationStack.end() == itr );
118
119 // Push to node to the stack.
120 cv_isolationStack.push_back( this );
121}
122
123//------------------------------------------------------------------------------
124
125} // end namespace libhei
126