support for FFDC-only isolation nodes in chip data

Signed-off-by: Zane Shelley <zshelle@us.ibm.com>
Change-Id: Ib457329d31a9f01eb6992e57b11d84c06a63e6e7
diff --git a/xml/.gitignore b/xml/.gitignore
new file mode 100644
index 0000000..84c048a
--- /dev/null
+++ b/xml/.gitignore
@@ -0,0 +1 @@
+/build/
diff --git a/xml/chip_data_xml.md b/xml/chip_data_xml.md
index d7d839a..5052056 100644
--- a/xml/chip_data_xml.md
+++ b/xml/chip_data_xml.md
@@ -101,11 +101,13 @@
    * Register length:   8 bytes
    * Bit order:         ascending (0-63, left to right)
 
-### 2.4) Element `<register>` (required 1 or more)
+### 2.4) Element `<register>` (conditionally optional)
 
-These provide a list of all registers required for isolation of this node. At
-a minimum, a `<register>` element must exist for each register referenced by
-the `<rule>` elements.
+These provide a list of all registers required for isolation of this node.
+
+At a minimum, a `<register>` element must exist for each register referenced by
+the `<capture_group>` or `<rule>` elements. Also, see the `<local_fir>` element
+for a possible shorthand definition.
 
 #### 2.4.1) Attribute `name` (required)
 
@@ -187,13 +189,18 @@
 number of instances represented by the the `node_inst` attribute of the
 `<capture_group>` element.
 
-### 2.6) Element `<rule>` (required 1 or more)
+### 2.6) Element `<rule>` (conditionally optional)
 
 A rule helps specify if an attention is being raised from a register and what
 type of attention is being raised. A rule is constructed by a series of
 expressions (see `<expr>` below). The result of the expressions will indicate
 all active attentions for a rule.
 
+At least one `<rule>` must exist if any `<bit>` elements are defined. The
+`<rule>` elements are optional for nodes that are intended to only capture FFDC
+for a bit defined in the parent node. Also, see the `<local_fir>` element for a
+possible shorthand definition.
+
 #### 2.6.1) Attribute `attn_type` (required)
 
 The attention type for this rule. See appendix for supported values.
@@ -259,10 +266,13 @@
    The length of the number is defined by the `reg_type` attribute of the root
    `<attn_node>` element.
 
-### 2.7) Element `<bit>` (required 1 or more)
+### 2.7) Element `<bit>` (conditionally optional)
 
-These provide metadata for each bit in this node. There should be a `<bit>`
-element for each bit that could generate an attention.
+These provide metadata for each bit in this node.
+
+The `<bit>` elements should only be defined if there are `<rule>` elements
+defined and there should be a `<bit>` element for each bit in the rules that
+could generate an attention.
 
 #### 2.7.1) Attribute `pos` (required)
 
diff --git a/xml/explorer/node_ocmb_lfir.xml b/xml/explorer/node_ocmb_lfir.xml
index 7cb4543..4c8c1a1 100644
--- a/xml/explorer/node_ocmb_lfir.xml
+++ b/xml/explorer/node_ocmb_lfir.xml
@@ -31,7 +31,14 @@
     <bit pos="36"   >DDR4 PHY fatal</bit>
     <bit pos="37"   >DDR4 PHY non fatal</bit>
     <bit pos="38"   >DDR4 PHY interrupt</bit>
-    <bit pos="39:46">foxhound fatal</bit>
+    <bit pos="39" child_node="OCMB_LFIR_FFDC_FOXHOUND" node_inst="7">foxhound fatal lane 7</bit>
+    <bit pos="40" child_node="OCMB_LFIR_FFDC_FOXHOUND" node_inst="6">foxhound fatal lane 6</bit>
+    <bit pos="41" child_node="OCMB_LFIR_FFDC_FOXHOUND" node_inst="5">foxhound fatal lane 5</bit>
+    <bit pos="42" child_node="OCMB_LFIR_FFDC_FOXHOUND" node_inst="4">foxhound fatal lane 4</bit>
+    <bit pos="43" child_node="OCMB_LFIR_FFDC_FOXHOUND" node_inst="3">foxhound fatal lane 3</bit>
+    <bit pos="44" child_node="OCMB_LFIR_FFDC_FOXHOUND" node_inst="2">foxhound fatal lane 2</bit>
+    <bit pos="45" child_node="OCMB_LFIR_FFDC_FOXHOUND" node_inst="1">foxhound fatal lane 1</bit>
+    <bit pos="46" child_node="OCMB_LFIR_FFDC_FOXHOUND" node_inst="0">foxhound fatal lane 0</bit>
     <bit pos="47:54">foxhound non fatal</bit>
     <bit pos="55:62">foxhound serdes interrupt</bit>
     <bit pos="63"   >GIF2PCB parity error on FSM or Registers</bit>
diff --git a/xml/explorer/node_ocmb_lfir_ffdc_foxhound.xml b/xml/explorer/node_ocmb_lfir_ffdc_foxhound.xml
new file mode 100644
index 0000000..531c9ff
--- /dev/null
+++ b/xml/explorer/node_ocmb_lfir_ffdc_foxhound.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<attn_node name="OCMB_LFIR_FFDC_FOXHOUND" model_ec="EXPLORER_11,EXPLORER_20" reg_type="SCOM">
+
+    <!--
+        These registers are on the MicroChip side of Explorer and are not in
+        the SCOM def.
+    -->
+
+    <register name="ADSP_PCBI">
+        <instance reg_inst="0" addr="0x00200860" />
+        <instance reg_inst="1" addr="0x00201860" />
+        <instance reg_inst="2" addr="0x00202860" />
+        <instance reg_inst="3" addr="0x00203860" />
+        <instance reg_inst="4" addr="0x00204860" />
+        <instance reg_inst="5" addr="0x00205860" />
+        <instance reg_inst="6" addr="0x00206860" />
+        <instance reg_inst="7" addr="0x00207860" />
+    </register>
+
+    <register name="CSU_PCBI">
+        <instance reg_inst="0" addr="0x002000B0" />
+        <instance reg_inst="1" addr="0x002010B0" />
+        <instance reg_inst="2" addr="0x002020B0" />
+        <instance reg_inst="3" addr="0x002030B0" />
+        <instance reg_inst="4" addr="0x002040B0" />
+        <instance reg_inst="5" addr="0x002050B0" />
+        <instance reg_inst="6" addr="0x002060B0" />
+        <instance reg_inst="7" addr="0x002070B0" />
+    </register>
+
+    <capture_group node_inst="0:7">
+        <capture_register reg_name="ADSP_PCBI" reg_inst="0:7" />
+        <capture_register reg_name="CSU_PCBI"  reg_inst="0:7" />
+    </capture_group>
+
+</attn_node>
+
diff --git a/xml/node.xsd b/xml/node.xsd
index 5edcb32..2bbe4ec 100644
--- a/xml/node.xsd
+++ b/xml/node.xsd
@@ -17,7 +17,7 @@
             <xsd:element name="capture_group" type="capture_group" minOccurs="0"
                          maxOccurs="255"/>
             <xsd:element name="rule" type="rule" minOccurs="0" maxOccurs="255"/>
-            <xsd:element name="bit"  type="bit"  minOccurs="1" maxOccurs="255"/>
+            <xsd:element name="bit"  type="bit"  minOccurs="0" maxOccurs="255"/>
         </xsd:sequence>
 
         <xsd:attribute name="name"     type="name_type"     use="required"/>
diff --git a/xml/parse_chip_data_xml b/xml/parse_chip_data_xml
index 131ff56..b91de9d 100755
--- a/xml/parse_chip_data_xml
+++ b/xml/parse_chip_data_xml
@@ -552,12 +552,6 @@
 {
     my ( $node, $insts_data ) = @_;
 
-    # There must be at least one rule entry.
-    unless ( defined $node->{rule} and 0 < scalar @{$node->{rule}} )
-    {
-        FAIL( "Node $node->{name} does not contain at least one rule" );
-    }
-
     # There should be only one rule per attention type and node instance for
     # this node.
     my $rule_dups = {};
@@ -607,12 +601,6 @@
 {
     my ( $node, $sigs, $insts_data ) = @_;
 
-    # There must be at least one bit entry.
-    unless ( defined $node->{bit} and 0 < scalar @{$node->{bit}} )
-    {
-        FAIL( "Node $node->{name} does not contain at least one bit" );
-    }
-
     my @node_insts = sort keys %{$insts_data};
     my $sz_insts = scalar @node_insts;
 
@@ -720,13 +708,27 @@
     # Split the capture group information per node instance.
     __normalizeCaptureGroup($node, $insts_data);
 
-    # Split the rule information per node instance. The sorted instance list
-    # will be used as indexes for the node_inst attribute of the <bit> elements.
-    __normalizeRule($node, $insts_data);
+    my $is_rule = (defined $node->{rule} and 0 < scalar @{$node->{rule}}) ? 1 : 0;
+    my $is_bit  = (defined $node->{bit}  and 0 < scalar @{$node->{bit}})  ? 1 : 0;
 
-    # Finally, collect the signature details and split the bit information per
-    # node instance.
-    __normalizeBit($node, $sigs, $insts_data);
+    # If a rule is defined, a bit must be defined as well. It is possible for
+    # neither to be defined (FFDC-only node).
+    if ( $is_rule and $is_bit )
+    {
+        # Split the rule information per node instance. The sorted instance list
+        # will be used as indexes for the node_inst attribute of the <bit>
+        # elements.
+        __normalizeRule($node, $insts_data);
+
+        # Finally, collect the signature details and split the bit information
+        # per node instance.
+        __normalizeBit($node, $sigs, $insts_data);
+    }
+    elsif ( $is_rule or $is_bit )
+    {
+        # One is defined and the other is not. This is an error.
+        FAIL("Node $node->{name} has a bit or rule defined and the other is not.");
+    }
 
     # Now that we have all of the node data, collapse the instance data into
     # a list.
@@ -1068,12 +1070,8 @@
             my $num_cap_regs = (defined $i->{capture_group})
                                     ? scalar @{$i->{capture_group}} : 0;
 
-            # At least one rule is required.
-            my $num_rules = scalar @{$i->{rule}};
-            unless ( 0 < $num_rules )
-            {
-                FAIL("No rule for $n->{name} $i->{node_inst}");
-            }
+            # Rules may not exist for this node.
+            my $num_rules = (defined $i->{rule}) ? scalar @{$i->{rule}} : 0;
 
             # Child nodes may not exist for this node.
             my $num_bit = (defined $i->{bit}) ? scalar @{$i->{bit}} : 0;
@@ -1094,11 +1092,14 @@
                 }
             }
 
-            for my $r ( @{$i->{rule}} )
+            if ( 0 < $num_rules )
             {
-                # Register rule metadata
-                __bin($fh, 1, $ATTN_TYPE->{$r->{attn_type}}->[0]);
-                __printExpr($fh, $reg_size, $r->{expr});
+                for my $r ( @{$i->{rule}} )
+                {
+                    # Register rule metadata
+                    __bin($fh, 1, $ATTN_TYPE->{$r->{attn_type}}->[0]);
+                    __printExpr($fh, $reg_size, $r->{expr});
+                }
             }
 
             if ( 0 < $num_bit )