Build chip data from new JSON format

The chip data XML format has been deprecated and the new JSON format
will be used going forward.

Signed-off-by: Zane Shelley <zshelle@us.ibm.com>
Change-Id: I2f44ae7bb921c9ab38c2664ab5cc2a9d6e2fd66a
diff --git a/.gitignore b/.gitignore
index 82d41a6..d3304ad 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@
 /build
 /subprojects/googletest
 /cppcheck-temp
+/.cache
diff --git a/chip_data/.gitignore b/chip_data/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/chip_data/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/chip_data/json_list.sh b/chip_data/json_list.sh
new file mode 100755
index 0000000..e59b127
--- /dev/null
+++ b/chip_data/json_list.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+# Verify input.
+if [ ! -d "$1" ]; then
+    echo "Invalid directory: $1" 1>&2
+    exit 1
+fi
+
+# Simply list out all of the JSON files in the given directory.
+for i in "$1"/*.json; do
+    if [ -f "$i" ]; then
+        echo "$i"
+    fi
+done
diff --git a/chip_data/meson.build b/chip_data/meson.build
new file mode 100644
index 0000000..1741447
--- /dev/null
+++ b/chip_data/meson.build
@@ -0,0 +1,51 @@
+#-------------------------------------------------------------------------------
+# Chip Data Files
+#-------------------------------------------------------------------------------
+
+build_cdb = find_program('parse_chip_data.py')
+
+# The key for each entry in this dictionary is a subdirectory containing XML for
+# a chip model. The value for each entry contains the expected output files that
+# will be produced for each chip model. It is important to note that the script
+# will generate all output files, regardless of what is listed, when the script
+# is run. However, this list must be kept in sync with the expected output so
+# that meson will know to run the script when an output file has changed or is
+# missing.
+cdb_files = {}
+
+chip_config = get_option('chip_config')
+
+if 'p10' in chip_config
+    cdb_files += {'p10_10' : ['chip_data_p10_10.cdb']}
+    cdb_files += {'p10_20' : ['chip_data_p10_20.cdb']}
+endif
+
+if 'explorer' in chip_config
+    cdb_files += {'explorer' : ['chip_data_explorer_11.cdb',
+                                'chip_data_explorer_20.cdb']}
+endif
+
+if 'odyssey' in chip_config
+    cdb_files += {'odyssey' : ['chip_data_odyssey_10.cdb']}
+endif
+
+foreach chip_dir, out_files : cdb_files
+
+    source_dir = meson.current_source_dir() + '/' + chip_dir
+    build_dir  = meson.current_build_dir()
+
+    # Get all JSON files in the chip directory. This is a bit of a workaround
+    # because meson does not allow wildcards.
+    json_list = run_command('json_list.sh', source_dir)
+    in_files = json_list.stdout().strip().split('\n')
+
+    custom_target('build_cdb_' + chip_dir, build_by_default : true,
+                  input : in_files, output : out_files,
+                  command : [ build_cdb, 'bin', source_dir, build_dir ],
+                  install : true,
+                  install_dir : join_paths(get_option('prefix'),
+                                           get_option('datadir'),
+                                           meson.project_name()))
+
+endforeach
+
diff --git a/chip_data/pyprd/chip_data/peltool.py b/chip_data/pyprd/chip_data/peltool.py
index 89724d7..814d17c 100644
--- a/chip_data/pyprd/chip_data/peltool.py
+++ b/chip_data/pyprd/chip_data/peltool.py
@@ -8,10 +8,11 @@
 AttnType = namedtuple("AttnType", "id desc")
 
 _attn_types = {
-    "CS": AttnType(1, "checkstop"),
+    "CS": AttnType(1, "chip checkstop"),
     "UCS": AttnType(2, "unit checkstop"),
     "RE": AttnType(3, "recoverable"),
     "SPA": AttnType(4, "special attention"),
+    "HA": AttnType(5, "host attention"),
 }
 
 
diff --git a/chip_data/pyprd/util/model_ec.py b/chip_data/pyprd/util/model_ec.py
index 20b3954..e7ee5f7 100644
--- a/chip_data/pyprd/util/model_ec.py
+++ b/chip_data/pyprd/util/model_ec.py
@@ -3,9 +3,9 @@
 ModelEc = namedtuple("ModelEc", "id type desc")
 
 supported = {
-    "EXPLORER_11": ModelEc(0x60D20011, "ocmb", "Explorer DD1.1"),
-    "EXPLORER_20": ModelEc(0x60D20020, "ocmb", "Explorer DD2.0"),
-    "ODYSSEY_10": ModelEc(0x60C00010, "ocmb", "Odyssey DD1.0"),
+    "EXPLORER_11": ModelEc(0x60D20011, "ocmb", "Explorer 1.1"),
+    "EXPLORER_20": ModelEc(0x60D20020, "ocmb", "Explorer 2.0"),
+    "ODYSSEY_10": ModelEc(0x60C00010, "ocmb", "Odyssey 1.0"),
     "P10_10": ModelEc(0x20DA0010, "proc", "P10 1.0"),
     "P10_20": ModelEc(0x20DA0020, "proc", "P10 2.0"),
 }
diff --git a/chip_data/setup.py b/chip_data/setup.py
new file mode 100644
index 0000000..408c88a
--- /dev/null
+++ b/chip_data/setup.py
@@ -0,0 +1,56 @@
+import os
+
+from parse_chip_data import gen_peltool_json
+from setuptools import setup
+from setuptools.command.build_py import build_py
+
+# Typically in files like this we'd use find_packages() to traverse directories
+# for any static packages. However, we are trying to add data to a package that
+# will actually exist in another repository. Therefore, we have to explicitly
+# list out the package name, directory, and data information.
+
+# We are building data for the following module:
+package_name = "pel.hwdiags"
+
+# Since we are not using find_packages() we have to provide a package directory,
+# but in this case nothing exists because there are no static package
+# directories. Therefore, we will just use the empty string.
+package_dir = ""
+
+# Split the package data directory into its components.
+data_dir_components = [*package_name.split("."), "data"]
+
+# It is important to note that '/' must be used as the path separator, even on
+# Windows. Setuptools will automatically convert the slashes where appropriate.
+package_data_glob = "/".join(data_dir_components)
+
+
+# This is a custom build class that is used to dynamically build the data files.
+class my_build_py(build_py):
+    def run(self):
+        if not self.dry_run:  # honor --dry-run flag
+            # Make sure the build directory for the data exists.
+            # Yes, os.path.join() is necessary in this case, which is different
+            # that what is stated above regarding package_data_glob.
+            data_dir = os.path.join(self.build_lib, *data_dir_components)
+            self.mkpath(data_dir)
+
+            # Generate the PEL parser data JSON from the Chip Data XML.
+            # TODO: The list of data file directories will need to be
+            #       configurable via the package config in the bitbake recipes.
+            for chip in ("p10_10", "p10_20", "explorer", "odyssey"):
+                gen_peltool_json(chip, data_dir)
+
+        # Call the superclass run() to ensure everything else builds.
+        super().run()
+
+
+setup(
+    name="openpower-hw-diags-pel-parser-data",
+    version=os.getenv("PELTOOL_VERSION", "1.0"),
+    classifiers=["License :: OSI Approved :: Apache Software License"],
+    cmdclass={"build_py": my_build_py},  # register custom build class
+    packages=[package_name],
+    package_dir={package_name: package_dir},
+    package_data={package_name: [package_data_glob]},
+)
diff --git a/meson.build b/meson.build
index 426467e..04136e9 100644
--- a/meson.build
+++ b/meson.build
@@ -71,7 +71,7 @@
 # Chip Data Files
 #-------------------------------------------------------------------------------
 
-subdir('xml')
+subdir('chip_data')
 
 #-------------------------------------------------------------------------------
 # Test
diff --git a/test/simulator/simulator.cpp b/test/simulator/simulator.cpp
index bca2b99..408d14a 100644
--- a/test/simulator/simulator.cpp
+++ b/test/simulator/simulator.cpp
@@ -13,10 +13,10 @@
 const std::map<SimulatorData::SimChipType, const char*>
     SimulatorData::cv_chipPath = {
         {SAMPLE, "../test/simulator/sample_data/sample.cdb"},
-        {EXPLORER_11, "xml/chip_data_explorer_11.cdb"},
-        {EXPLORER_20, "xml/chip_data_explorer_20.cdb"},
-        {P10_10, "xml/chip_data_p10_10.cdb"},
-        {P10_20, "xml/chip_data_p10_20.cdb"},
+        {EXPLORER_11, "chip_data/chip_data_explorer_11.cdb"},
+        {EXPLORER_20, "chip_data/chip_data_explorer_20.cdb"},
+        {P10_10, "chip_data/chip_data_p10_10.cdb"},
+        {P10_20, "chip_data/chip_data_p10_20.cdb"},
 };
 
 //------------------------------------------------------------------------------
@@ -73,6 +73,35 @@
 
 //------------------------------------------------------------------------------
 
+const char* __attn(AttentionType_t i_type)
+{
+    const char* str = "";
+    switch (i_type)
+    {
+        case ATTN_TYPE_CHIP_CS:
+            str = "CHIP_CS";
+            break;
+        case ATTN_TYPE_UNIT_CS:
+            str = "UNIT_CS";
+            break;
+        case ATTN_TYPE_RECOVERABLE:
+            str = "RECOVERABLE";
+            break;
+        case ATTN_TYPE_SP_ATTN:
+            str = "SP_ATTN";
+            break;
+        case ATTN_TYPE_HOST_ATTN:
+            str = "HOST_ATTN";
+            break;
+        default:
+            HEI_ERR("Unsupported attention type: %u", i_type);
+            assert(0);
+    }
+    return str;
+}
+
+//------------------------------------------------------------------------------
+
 void SimulatorData::endIteration()
 {
     // Start by calling libhei::isolate().
@@ -95,23 +124,44 @@
     // Get the list of signatures found in isolation.
     std::vector<Signature> givenSigList = isoData.getSignatureList();
 
-    // Verify the expected list and given list are the same.
-    ASSERT_EQ(iv_expSigList.size(), givenSigList.size());
-
-    std::sort(iv_expSigList.begin(), iv_expSigList.end());
-    std::sort(givenSigList.begin(), givenSigList.end());
-
-    /* TODO: Currently used for debug. Eventually, we want this written to file.
-    for (const auto& s : givenSigList)
+    // Print out the expected signature list and verify matches with given list.
+    HEI_INF("Signature summary:")
+    bool mismatch = false;
+    for (const auto& e : iv_expSigList)
     {
-        HEI_INF("Signature: %s 0x%04x %u %u %u",
-                (const char*)s.getChip().getChip(), s.getId(), s.getInstance(),
-                s.getBit(), s.getAttnType());
-    }
-    */
+        auto gItr = std::find(givenSigList.begin(), givenSigList.end(), e);
+        if (givenSigList.end() != gItr)
+        {
+            HEI_INF("  Match:      %s 0x%04x %2u %2u %s",
+                    (const char*)e.getChip().getChip(), e.getId(),
+                    e.getInstance(), e.getBit(), __attn(e.getAttnType()));
 
-    ASSERT_TRUE(std::equal(givenSigList.begin(), givenSigList.end(),
-                           iv_expSigList.begin()));
+            // Remove from given signature list so we can determine if there are
+            // any leftovers at the end.
+            givenSigList.erase(gItr);
+        }
+        else
+        {
+            HEI_INF("  No match:   %s 0x%04x %2u %2u %s",
+                    (const char*)e.getChip().getChip(), e.getId(),
+                    e.getInstance(), e.getBit(), __attn(e.getAttnType()));
+
+            mismatch = true;
+        }
+    }
+
+    // Print out any leftover signatures from the given list.
+    for (const auto& g : givenSigList)
+    {
+        HEI_INF("  Unexpected: %s 0x%04x %2u %2u %s",
+                (const char*)g.getChip().getChip(), g.getId(), g.getInstance(),
+                g.getBit(), __attn(g.getAttnType()));
+
+        mismatch = true;
+    }
+
+    // Final check for mismatches.
+    ASSERT_FALSE(mismatch);
 
     // The iteration is complete so we can flush the data.
     flushIterationData();
diff --git a/test/simulator/testcases/exp20_foxhound7.cpp b/test/simulator/testcases/exp20_foxhound7.cpp
index 65a4966..e75f223 100644
--- a/test/simulator/testcases/exp20_foxhound7.cpp
+++ b/test/simulator/testcases/exp20_foxhound7.cpp
@@ -9,7 +9,7 @@
 REG_SCOM(ocmb0, 0x08040000, 0x1000000000000000) // OCMB_CHIPLET_CS_FIR
 REG_SCOM(ocmb0, 0x0804000a, 0x0000000001000000) // OCMB_LFIR
 
-EXP_SIG(ocmb0, 0xbdcd, 0, 39, UNIT_CS)
+EXP_SIG(ocmb0, 0xbdcd, 0, 39, CHIP_CS)
 
 END_ITERATION
 
diff --git a/test/simulator/testcases/omi_dl_fatal.cpp b/test/simulator/testcases/omi_dl_fatal.cpp
index 1284462..b08f44f 100644
--- a/test/simulator/testcases/omi_dl_fatal.cpp
+++ b/test/simulator/testcases/omi_dl_fatal.cpp
@@ -203,7 +203,7 @@
 REG_SCOM(ocmb1, 0x08012800, 0x8000000000000000) // OMI_DL_FIR[0]
 REG_SCOM(ocmb1, 0x08012813, 0x0000000000000001) // OMI_DL_ERR_RPT[63]
 
-EXP_SIG(ocmb1, 0xbbd3, 0, 63, UNIT_CS)
+EXP_SIG(ocmb1, 0xbbd3, 0, 63, CHIP_CS)
 
 END_ITERATION