[Pdbg] [RFC PATCH 07/11] tests: Add tests to ensure parity with EKB address translations

Amitay Isaacs amitay at ozlabs.org
Tue Nov 12 13:12:47 AEDT 2019


From: Alistair Popple <alistair at popple.id.au>

The EKB address translation source cannot be imported directly into
libpdbg as it would require moving the project to C++. So instead the
translation functions have been manually moved into libpdbg. Obviously
this introduces the possibility of differences between the two
implementations.

A test case was added to guard against this possibility by doing a
comparative test with the original implementation. This involves
testing every address offset for every target type and possible index.

As there is no simple way of establishing which addresses and indices
are valid for each target we have to test all of them.

Signed-off-by: Alistair Popple <alistair at popple.id.au>
---
 Makefile.am                                  |    9 +-
 configure.ac                                 |    1 +
 src/tests/libpdbg_p9_fapi_translation_test.C |  126 ++
 src/tests/p9_cu.H                            |  119 ++
 src/tests/p9_scom_addr.H                     |  647 ++++++++
 src/tests/p9_scominfo.C                      | 1494 ++++++++++++++++++
 src/tests/p9_scominfo.H                      |   94 ++
 7 files changed, 2489 insertions(+), 1 deletion(-)
 create mode 100644 src/tests/libpdbg_p9_fapi_translation_test.C
 create mode 100644 src/tests/p9_cu.H
 create mode 100644 src/tests/p9_scom_addr.H
 create mode 100644 src/tests/p9_scominfo.C
 create mode 100644 src/tests/p9_scominfo.H

diff --git a/Makefile.am b/Makefile.am
index 44f5d7c..45787b3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -12,7 +12,8 @@ GIT_SHA1 ?= `git --work-tree=$(top_srcdir) --git-dir=$(top_srcdir)/.git describe
 libpdbg_tests = libpdbg_target_test \
 		libpdbg_probe_test1 \
 		libpdbg_probe_test2 \
-		libpdbg_probe_test3
+		libpdbg_probe_test3 \
+		libpdbg_p9_fapi_translation_test
 
 bin_PROGRAMS = pdbg
 check_PROGRAMS = $(libpdbg_tests) libpdbg_dtree_test \
@@ -256,6 +257,12 @@ libpdbg_dtree_test_CFLAGS = $(libpdbg_test_cflags)
 libpdbg_dtree_test_LDFLAGS = $(libpdbg_test_ldflags)
 libpdbg_dtree_test_LDADD = $(libpdbg_test_ldadd)
 
+libpdbg_p9_fapi_translation_test_SOURCES = src/tests/libpdbg_p9_fapi_translation_test.C \
+					   src/tests/p9_scominfo.C
+libpdbg_p9_fapi_translation_test_CFLAGS = $(libpdbg_test_cflags)
+libpdbg_p9_fapi_translation_test_LDFLAGS = $(libpdbg_test_ldflags)
+libpdbg_p9_fapi_translation_test_LDADD = $(libpdbg_test_ldadd)
+
 M4_V = $(M4_V_$(V))
 M4_V_ = $(M4_V_$(AM_DEFAULT_VERBOSITY))
 M4_V_0 = @echo "  M4      " $@;
diff --git a/configure.ac b/configure.ac
index 4a19e7e..5098c13 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3,6 +3,7 @@ AM_INIT_AUTOMAKE([subdir-objects])
 AM_SILENT_RULES([yes])
 
 AC_PROG_CC
+AC_PROG_CXX
 AM_PROG_AS
 AC_PROG_LIBTOOL
 
diff --git a/src/tests/libpdbg_p9_fapi_translation_test.C b/src/tests/libpdbg_p9_fapi_translation_test.C
new file mode 100644
index 0000000..0b2d23b
--- /dev/null
+++ b/src/tests/libpdbg_p9_fapi_translation_test.C
@@ -0,0 +1,126 @@
+#include <stdio.h>
+#include <inttypes.h>
+
+#define class klass
+#include "libpdbg/libpdbg.h"
+#include "libpdbg/hwunit.h"
+#include "libpdbg/target.h"
+#undef class
+
+#include "p9_scominfo.H"
+
+#define MAX_INDEX 30
+
+extern struct hw_unit_info p9_core_hw_unit;
+extern struct hw_unit_info p9_ex_hw_unit;
+extern struct hw_unit_info p9_mba_hw_unit;
+extern struct hw_unit_info p9_mcs_hw_unit;
+extern struct hw_unit_info p9_xbus_hw_unit;
+extern struct hw_unit_info p9_abus_hw_unit;
+extern struct hw_unit_info p9_l4_hw_unit;
+extern struct hw_unit_info p9_eq_hw_unit;
+extern struct hw_unit_info p9_mca_hw_unit;
+extern struct hw_unit_info p9_mcbist_hw_unit;
+extern struct hw_unit_info p9_mi_hw_unit;
+extern struct hw_unit_info p9_dmi_hw_unit;
+extern struct hw_unit_info p9_obus_hw_unit;
+extern struct hw_unit_info p9_obus_brick_hw_unit;
+extern struct hw_unit_info p9_sbe_hw_unit;
+extern struct hw_unit_info p9_ppe_hw_unit;
+extern struct hw_unit_info p9_pec_hw_unit;
+extern struct hw_unit_info p9_phb_hw_unit;
+extern struct hw_unit_info p9_mc_hw_unit;
+extern struct hw_unit_info p9_mem_port_hw_unit;
+extern struct hw_unit_info p9_nmmu_hw_unit;
+extern struct hw_unit_info p9_pau_hw_unit;
+extern struct hw_unit_info p9_iohs_hw_unit;
+extern struct hw_unit_info p9_fc_hw_unit;
+extern struct hw_unit_info p9_pauc_hw_unit;
+extern struct hw_unit_info p9_chiplet_hw_unit;
+
+int test_unit_translation(struct pdbg_target *target, p9ChipUnits_t cu, int index, uint64_t addr)
+{
+	uint64_t pdbg_addr, fapi_addr;
+
+	target->index = index;
+
+	/* TODO: Check standard chiplet translation */
+	if (!target->translate)
+		return 1;
+
+	pdbg_addr = target->translate(target, addr);
+	fapi_addr = p9_scominfo_createChipUnitScomAddr(cu, index, addr, 0);
+
+	if (pdbg_addr != fapi_addr)
+		printf("PDBG Address 0x%016" PRIx64 " does not match FAPI Address 0x%016" PRIx64
+		       " for address 0x%016" PRIx64 " on target %s@%d\n",
+		       pdbg_addr, fapi_addr, addr, pdbg_target_path(target), index);
+
+	return pdbg_addr == fapi_addr;
+}
+
+int main(void)
+{
+	uint64_t addr;
+	int i, index;
+	struct pdbg_target *p9_cu[NONE] = {0};
+
+	pdbg_set_logfunc(NULL);
+
+	p9_cu[PU_C_CHIPUNIT] = (struct pdbg_target *) p9_core_hw_unit.hw_unit;
+        p9_cu[PU_EQ_CHIPUNIT] = (struct pdbg_target *) p9_eq_hw_unit.hw_unit;
+        p9_cu[PU_EX_CHIPUNIT] = (struct pdbg_target *) p9_ex_hw_unit.hw_unit;
+        p9_cu[PU_XBUS_CHIPUNIT] = (struct pdbg_target *) p9_xbus_hw_unit.hw_unit;
+        p9_cu[PU_OBUS_CHIPUNIT] = (struct pdbg_target *) p9_obus_hw_unit.hw_unit;
+        p9_cu[PU_PEC_CHIPUNIT] = (struct pdbg_target *) p9_pec_hw_unit.hw_unit;
+        p9_cu[PU_PHB_CHIPUNIT] = (struct pdbg_target *) p9_phb_hw_unit.hw_unit;
+        p9_cu[PU_MI_CHIPUNIT] = (struct pdbg_target *) p9_mi_hw_unit.hw_unit;
+        p9_cu[PU_DMI_CHIPUNIT] = (struct pdbg_target *) p9_dmi_hw_unit.hw_unit;
+        p9_cu[PU_MCS_CHIPUNIT] = (struct pdbg_target *) p9_mcs_hw_unit.hw_unit;
+        p9_cu[PU_MCA_CHIPUNIT] = (struct pdbg_target *) p9_mca_hw_unit.hw_unit;
+        p9_cu[PU_MCBIST_CHIPUNIT] = (struct pdbg_target *) p9_mcbist_hw_unit.hw_unit;
+        p9_cu[PU_PERV_CHIPUNIT] = (struct pdbg_target *) p9_chiplet_hw_unit.hw_unit;
+        p9_cu[PU_PPE_CHIPUNIT] = (struct pdbg_target *) p9_ppe_hw_unit.hw_unit;
+        p9_cu[PU_SBE_CHIPUNIT] = (struct pdbg_target *) p9_sbe_hw_unit.hw_unit;
+        p9_cu[PU_MC_CHIPUNIT] = (struct pdbg_target *) p9_mc_hw_unit.hw_unit;
+
+
+	/* Need to initialise the dn_name so pdbg_target_path doesn't segfault */
+	((struct pdbg_target *) p9_core_hw_unit.hw_unit)->dn_name = "p9_core";
+	((struct pdbg_target *) p9_chiplet_hw_unit.hw_unit)->dn_name = "p9_chiplet";
+	((struct pdbg_target *) p9_ex_hw_unit.hw_unit)->dn_name = "p9_ex";
+	((struct pdbg_target *) p9_mba_hw_unit.hw_unit)->dn_name = "p9_mba";
+	((struct pdbg_target *) p9_mcs_hw_unit.hw_unit)->dn_name = "p9_mcs";
+	((struct pdbg_target *) p9_xbus_hw_unit.hw_unit)->dn_name = "p9_xbus";
+	((struct pdbg_target *) p9_abus_hw_unit.hw_unit)->dn_name = "p9_abus";
+	((struct pdbg_target *) p9_l4_hw_unit.hw_unit)->dn_name = "p9_l4";
+	((struct pdbg_target *) p9_eq_hw_unit.hw_unit)->dn_name = "p9_eq";
+	((struct pdbg_target *) p9_mca_hw_unit.hw_unit)->dn_name = "p9_mca";
+	((struct pdbg_target *) p9_mcbist_hw_unit.hw_unit)->dn_name = "p9_mcbist";
+	((struct pdbg_target *) p9_mi_hw_unit.hw_unit)->dn_name = "p9_mi";
+	((struct pdbg_target *) p9_dmi_hw_unit.hw_unit)->dn_name = "p9_dmi";
+	((struct pdbg_target *) p9_obus_hw_unit.hw_unit)->dn_name = "p9_obus";
+	((struct pdbg_target *) p9_obus_brick_hw_unit.hw_unit)->dn_name = "p9_obus_brick";
+	((struct pdbg_target *) p9_sbe_hw_unit.hw_unit)->dn_name = "p9_sbe";
+	((struct pdbg_target *) p9_ppe_hw_unit.hw_unit)->dn_name = "p9_ppe";
+	((struct pdbg_target *) p9_pec_hw_unit.hw_unit)->dn_name = "p9_pec";
+	((struct pdbg_target *) p9_phb_hw_unit.hw_unit)->dn_name = "p9_phb";
+	((struct pdbg_target *) p9_mc_hw_unit.hw_unit)->dn_name = "p9_mc";
+	((struct pdbg_target *) p9_mem_port_hw_unit.hw_unit)->dn_name = "p9_mem_port";
+	((struct pdbg_target *) p9_nmmu_hw_unit.hw_unit)->dn_name = "p9_nmmu";
+	((struct pdbg_target *) p9_pau_hw_unit.hw_unit)->dn_name = "p9_pau";
+	((struct pdbg_target *) p9_iohs_hw_unit.hw_unit)->dn_name = "p9_iohs";
+	((struct pdbg_target *) p9_fc_hw_unit.hw_unit)->dn_name = "p9_fc";
+	((struct pdbg_target *) p9_pauc_hw_unit.hw_unit)->dn_name = "p9_pauc";
+
+	for (i = 0; i < NONE; i++) {
+		if (p9_cu[i])
+			for (index = 0; index < MAX_INDEX; index++) {
+				printf("Testing %s@%d\n", pdbg_target_path(p9_cu[i]), index);
+
+				/* Test every sat offset */
+				for (addr = 0; addr < 0xffffffff; addr += 0x40)
+					assert(test_unit_translation(p9_cu[i], (p9ChipUnits_t) i, index, addr));
+			}
+	}
+}
diff --git a/src/tests/p9_cu.H b/src/tests/p9_cu.H
new file mode 100644
index 0000000..3abcd14
--- /dev/null
+++ b/src/tests/p9_cu.H
@@ -0,0 +1,119 @@
+/* IBM_PROLOG_BEGIN_TAG                                                   */
+/* This is an automatically generated prolog.                             */
+/*                                                                        */
+/* $Source: chips/p9/common/scominfo/p9_cu.H $                            */
+/*                                                                        */
+/* IBM CONFIDENTIAL                                                       */
+/*                                                                        */
+/* EKB Project                                                            */
+/*                                                                        */
+/* COPYRIGHT 2015,2018                                                    */
+/* [+] International Business Machines Corp.                              */
+/*                                                                        */
+/*                                                                        */
+/* The source code for this program is not published or otherwise         */
+/* divested of its trade secrets, irrespective of what has been           */
+/* deposited with the U.S. Copyright Office.                              */
+/*                                                                        */
+/* IBM_PROLOG_END_TAG                                                     */
+///
+/// @file p9_cu.H
+/// @brief P9 chip unit definitions
+///
+/// HWP HWP Owner: jmcgill at us.ibm.com
+/// HWP FW Owner: dcrowell at us.ibm.com
+/// HWP Team: Infrastructure
+/// HWP Level: 2
+/// HWP Consumed by: FSP/HB
+///
+
+#ifndef P9_CU_H
+#define P9_CU_H
+
+// includes
+#include <stdint.h>
+
+extern "C"
+{
+
+    /// P9 chip unit type enumeration
+    typedef enum
+    {
+        P9C_CHIP,            ///< Cumulus chip (included for future expansion)
+        P9N_CHIP,            ///< Nimbus chip (included for future expansion)
+        P9A_CHIP,            ///< Axone chip (included for future expansion)
+        PU_C_CHIPUNIT,       ///< Core
+        PU_EQ_CHIPUNIT,      ///< Quad
+        PU_EX_CHIPUNIT,      ///< EX
+        PU_XBUS_CHIPUNIT,    ///< XBUS
+        PU_OBUS_CHIPUNIT,    ///< OBUS
+        PU_NV_CHIPUNIT,      ///< NV Link Brick
+        PU_PEC_CHIPUNIT,     ///< PCIe (PEC)
+        PU_PHB_CHIPUNIT,     ///< PCIe (PHB)
+        PU_MI_CHIPUNIT,      ///< MI (Cumulus only)
+        PU_DMI_CHIPUNIT,     ///< DMI (Cumulus only)
+        PU_MCC_CHIPUNIT,     ///< MCC MC Channels (Axone only)
+        PU_OMIC_CHIPUNIT,    ///< OMI Cplt (Axone only)
+        PU_OMI_CHIPUNIT,     ///< OMI (Axone only)
+        PU_MCS_CHIPUNIT,     ///< MCS (Nimbus only)
+        PU_MCA_CHIPUNIT,     ///< MCA (Nimbus only)
+        PU_MCBIST_CHIPUNIT,  ///< MCBIST (Nimbus only)
+        PU_PERV_CHIPUNIT,    ///< Pervasive
+        PU_PPE_CHIPUNIT,     ///< PPE
+        PU_SBE_CHIPUNIT,     ///< SBE
+        PU_CAPP_CHIPUNIT,    ///< CAPP
+        PU_MC_CHIPUNIT,    ///< mc
+        NONE,                ///< None/Invalid
+    } p9ChipUnits_t;
+
+    /// P9 chip unit pairing struct
+    struct p9_chipUnitPairing_t
+    {
+        /// @brief Default constructor
+        p9_chipUnitPairing_t()
+            : chipUnitType(NONE), chipUnitNum(0) {}
+        /// @brief Construct from type/instance number
+        p9_chipUnitPairing_t (p9ChipUnits_t type, uint32_t num)
+            : chipUnitType(type), chipUnitNum(num) {}
+
+        p9ChipUnits_t chipUnitType;  ///< chip unit type
+        uint32_t chipUnitNum;        ///< chip unit instance number
+    };
+
+    /// P9 PPE Chip Unit Instance Number enumeration
+    /// PPE name        Nimbus    Cumulus   Axone
+    /// SBE             0         0         0
+    /// GPE0..3         10..13    10..13    10..13
+    /// CME0            20..25    20..25    20..25
+    /// CME1            30..35    30..35    30..35
+    /// IO PPE (xbus)   40        40        40
+    /// IO PPE (obus)   41,44     41..44    41,44
+    /// IO PPE (dmi)    NA        45,46     NA
+    /// Powerbus PPEs   50        50        50
+    /// IO PPE (omi)    NA        NA        56..61
+    typedef enum
+    {
+        PPE_SBE_CHIPUNIT_NUM         =  0,
+        PPE_GPE0_CHIPUNIT_NUM        = 10,
+        PPE_GPE3_CHIPUNIT_NUM        = 13,
+        PPE_EQ0_CME0_CHIPUNIT_NUM    = 20,   // Quad0-CME0
+        PPE_EQ5_CME0_CHIPUNIT_NUM    = 25,   // Quad5-CME0
+        PPE_EQ0_CME1_CHIPUNIT_NUM    = 30,   // Quad0-CME1
+        PPE_EQ5_CME1_CHIPUNIT_NUM    = 35,   // Quad5-CME1
+        PPE_IO_XBUS_CHIPUNIT_NUM     = 40,
+        PPE_IO_OB0_CHIPUNIT_NUM      = 41,
+        PPE_IO_OB1_CHIPUNIT_NUM      = 42,
+        PPE_IO_OB2_CHIPUNIT_NUM      = 43,
+        PPE_IO_OB3_CHIPUNIT_NUM      = 44,
+        PPE_IO_DMI0_CHIPUNIT_NUM     = 45,
+        PPE_IO_DMI1_CHIPUNIT_NUM     = 46,
+        PPE_PB0_CHIPUNIT_NUM         = 50,
+        PPE_PB2_CHIPUNIT_NUM         = 52,
+        PPE_OMI_CHIPUNIT_NUM         = 56,
+        PPE_LAST_CHIPUNIT_NUM        = PPE_OMI_CHIPUNIT_NUM,
+    } p9_ppe_chip_unit_instance_num_t;
+
+} // extern "C"
+
+#endif /* P9_CU_H */
+
diff --git a/src/tests/p9_scom_addr.H b/src/tests/p9_scom_addr.H
new file mode 100644
index 0000000..c4c1202
--- /dev/null
+++ b/src/tests/p9_scom_addr.H
@@ -0,0 +1,647 @@
+/* IBM_PROLOG_BEGIN_TAG                                                   */
+/* This is an automatically generated prolog.                             */
+/*                                                                        */
+/* $Source: chips/p9/common/scominfo/p9_scom_addr.H $                     */
+/*                                                                        */
+/* IBM CONFIDENTIAL                                                       */
+/*                                                                        */
+/* EKB Project                                                            */
+/*                                                                        */
+/* COPYRIGHT 2015,2018                                                    */
+/* [+] International Business Machines Corp.                              */
+/*                                                                        */
+/*                                                                        */
+/* The source code for this program is not published or otherwise         */
+/* divested of its trade secrets, irrespective of what has been           */
+/* deposited with the U.S. Copyright Office.                              */
+/*                                                                        */
+/* IBM_PROLOG_END_TAG                                                     */
+///
+/// @file p9_scom_addr.H
+/// @brief P9 SCOM address class
+///
+/// HWP HWP Owner: jmcgill at us.ibm.com
+/// HWP FW Owner: dcrowell at us.ibm.com
+/// HWP Team: Infrastructure
+/// HWP Level: 2
+/// HWP Consumed by: FSP/HB
+///
+
+#ifndef P9_SCOM_ADDR_H
+#define P9_SCOM_ADDR_H
+
+// includes
+#include <stdint.h>
+
+extern "C"
+{
+    /// P9 Chiplet ID enumeration
+    typedef enum
+    {
+        PIB_CHIPLET_ID  = 0x00,     ///< PIB chiplet
+        PERV_CHIPLET_ID = 0x01,     ///< TP chiplet
+        N0_CHIPLET_ID   = 0x02,     ///< Nest0 (North) chiplet
+        N1_CHIPLET_ID   = 0x03,     ///< Nest1 (East) chiplet
+        N2_CHIPLET_ID   = 0x04,     ///< Nest2 (South) chiplet
+        N3_CHIPLET_ID   = 0x05,     ///< Nest3 (West) chiplet
+        XB_CHIPLET_ID   = 0x06,     ///< XBus chiplet
+        MC01_CHIPLET_ID = 0x07,     ///< MC01 (West) chiplet
+        MC23_CHIPLET_ID = 0x08,     ///< MC23 (East) chiplet
+        OB0_CHIPLET_ID  = 0x09,     ///< OBus0 chiplet
+        OB1_CHIPLET_ID  = 0x0A,     ///< OBus1 chiplet (Cumulus only)
+        OB2_CHIPLET_ID  = 0x0B,     ///< OBus2 chiplet (Cumulus only)
+        OB3_CHIPLET_ID  = 0x0C,     ///< OBus3 chiplet
+        PCI0_CHIPLET_ID = 0x0D,     ///< PCIe0 chiplet
+        PCI1_CHIPLET_ID = 0x0E,     ///< PCIe1 chiplet
+        PCI2_CHIPLET_ID = 0x0F,     ///< PCIe2 chiplet
+        EP00_CHIPLET_ID = 0x10,     ///< Quad0 chiplet (EX0/1)
+        EP01_CHIPLET_ID = 0x11,     ///< Quad1 chiplet (EX2/3)
+        EP02_CHIPLET_ID = 0x12,     ///< Quad2 chiplet (EX4/5)
+        EP03_CHIPLET_ID = 0x13,     ///< Quad3 chiplet (EX6/7)
+        EP04_CHIPLET_ID = 0x14,     ///< Quad4 chiplet (EX8/9)
+        EP05_CHIPLET_ID = 0x15,     ///< Quad5 chiplet (EX10/11)
+        EC00_CHIPLET_ID = 0x20,     ///< Core0 chiplet (Quad0, EX0, C0)
+        EC01_CHIPLET_ID = 0x21,     ///< Core1 chiplet (Quad0, EX0, C1)
+        EC02_CHIPLET_ID = 0x22,     ///< Core2 chiplet (Quad0, EX1, C0)
+        EC03_CHIPLET_ID = 0x23,     ///< Core3 chiplet (Quad0, EX1, C1)
+        EC04_CHIPLET_ID = 0x24,     ///< Core4 chiplet (Quad1, EX2, C0)
+        EC05_CHIPLET_ID = 0x25,     ///< Core5 chiplet (Quad1, EX2, C1)
+        EC06_CHIPLET_ID = 0x26,     ///< Core6 chiplet (Quad1, EX3, C0)
+        EC07_CHIPLET_ID = 0x27,     ///< Core7 chiplet (Quad1, EX3, C1)
+        EC08_CHIPLET_ID = 0x28,     ///< Core8 chiplet (Quad2, EX4, C0)
+        EC09_CHIPLET_ID = 0x29,     ///< Core9 chiplet (Quad2, EX4, C1)
+        EC10_CHIPLET_ID = 0x2A,     ///< Core10 chiplet (Quad2, EX5, C0)
+        EC11_CHIPLET_ID = 0x2B,     ///< Core11 chiplet (Quad2, EX5, C1)
+        EC12_CHIPLET_ID = 0x2C,     ///< Core12 chiplet (Quad3, EX6, C0)
+        EC13_CHIPLET_ID = 0x2D,     ///< Core13 chiplet (Quad3, EX6, C1)
+        EC14_CHIPLET_ID = 0x2E,     ///< Core14 chiplet (Quad3, EX7, C0)
+        EC15_CHIPLET_ID = 0x2F,     ///< Core15 chiplet (Quad3, EX7, C1)
+        EC16_CHIPLET_ID = 0x30,     ///< Core16 chiplet (Quad4, EX8, C0)
+        EC17_CHIPLET_ID = 0x31,     ///< Core17 chiplet (Quad4, EX8, C1)
+        EC18_CHIPLET_ID = 0x32,     ///< Core18 chiplet (Quad4, EX9, C0)
+        EC19_CHIPLET_ID = 0x33,     ///< Core19 chiplet (Quad4, EX9, C1)
+        EC20_CHIPLET_ID = 0x34,     ///< Core20 chiplet (Quad5, EX10, C0)
+        EC21_CHIPLET_ID = 0x35,     ///< Core21 chiplet (Quad5, EX10, C1)
+        EC22_CHIPLET_ID = 0x36,     ///< Core22 chiplet (Quad5, EX11, C0)
+        EC23_CHIPLET_ID = 0x37      ///< Core23 chiplet (Quad5, EX11, C1)
+    } p9_chiplet_id_t;
+
+    /// P9 Chiplet ID enumeration
+    typedef enum
+    {
+        PPE_EP00_CHIPLET_ID = 0x09,     ///< Quad0
+        PPE_EP01_CHIPLET_ID = 0x0A,     ///< Quad1
+        PPE_EP02_CHIPLET_ID = 0x0B,     ///< Quad2
+        PPE_EP03_CHIPLET_ID = 0x0C,     ///< Quad3
+        PPE_EP04_CHIPLET_ID = 0x0D,     ///< Quad4
+        PPE_EP05_CHIPLET_ID = 0x0E      ///< Quad5
+    } p9_ppe_chiplet_id_t;
+
+    /// P9 SCOM port ID enumeration
+    typedef enum
+    {
+        GPREG_PORT_ID = 0x0,        ///< GP registers
+        UNIT_PORT_ID = 0x1,         ///< Functional registers
+        CME_PORT_ID = 0x2,          ///< CME registers
+        CC_PORT_ID = 0x3,           ///< Clock control registers
+        FIR_PORT_ID = 0x4,          ///< Common FIR registers
+        CPM_PORT_ID = 0x5,          ///< CPM registers
+        GPE_PORT_ID = 0x6,          ///< PPE GPE registers (For TP only)
+        SBE_PORT_ID = 0xE,          ///< SBE PM registers (For TP only)
+        PCBSLV_PORT_ID = 0xF        ///< PCB Slave registers
+    } p9_port_id_t;
+
+    /// P9 Core chiplet SCOM ring ID enumeration
+    /// source: tpc_p9_core_top.vhdl
+    typedef enum
+    {
+        EC_PSCM_RING_ID = 0x0,      ///< PSCOM
+        EC_PERV_RING_ID = 0x1,      ///< PERV
+        EC_PC_0_RING_ID = 0x2,      ///< PC_0
+        EC_PC_1_RING_ID = 0x3,      ///< PC_1
+        EC_PC_2_RING_ID = 0x4,      ///< PC_2
+        EC_PC_3_RING_ID = 0x5       ///< PC_3
+    } p9_ec_ring_id_t;
+
+    /// P9 Quad chiplet SCOM ring ID enumeration
+    /// source: tpc_p9_l3_top.vhdl
+    typedef enum
+    {
+        EQ_PSCM_RING_ID = 0x0,      ///< PSCOM
+        EQ_PERV_RING_ID = 0x1,      ///< PERV
+        EQ_L2_0_RING_ID = 0x2,      ///< L2_0
+        EQ_L2_1_RING_ID = 0x3,      ///< L2_1
+        EQ_NC_0_RING_ID = 0x4,      ///< NC_0
+        EQ_NC_1_RING_ID = 0x5,      ///< NC_1
+        EQ_L3_0_RING_ID = 0x6,      ///< L3_0
+        EQ_L3_1_RING_ID = 0x7,      ///< L3_1
+        EQ_CME_0_RING_ID = 0x8,     ///< CME_0
+        EQ_CME_1_RING_ID = 0x9,     ///< CME_1
+        EQ_L2_0_TRA_RING_ID = 0xA,  ///< L2_0_TRA
+        EQ_L2_1_TRA_RING_ID = 0xB   ///< L2_1_TRA
+    } p9_eq_ring_id_t;
+
+    /// P9 N0 chiplet SCOM ring ID enumeration
+    /// source: tpc_p9_n0_top.vhdl
+    typedef enum
+    {
+        N0_PSCM_RING_ID = 0x0,      ///< PSCOM
+        N0_PERV_RING_ID = 0x1,      ///< PERV
+        N0_CXA0_0_RING_ID = 0x2,    ///< CXA0_0
+        N0_NX_0_RING_ID = 0x4,      ///< NX_0
+        N0_PBIOE0_0_RING_ID = 0x6,  ///< PBIOE0_0
+        N0_PBIOE1_0_RING_ID = 0x7,  ///< PBIOE1_0
+        N0_PBIOE2_0_RING_ID = 0x8   ///< PBIOE2_0
+    } p9_n0_ring_id_t;
+
+    /// P9 N1 chiplet SCOM ring ID enumeration
+    /// source: tpc_p9_n1_top.vhdl
+    typedef enum
+    {
+        N1_PSCM_RING_ID = 0x0,      ///< PSCOM
+        N1_PERV_RING_ID = 0x1,      ///< PERV
+        N1_MC23_0_RING_ID = 0x2,    ///< MC23_0
+        N1_MCD_0_RING_ID = 0x4,     ///< MCD_0
+        N1_MCD_1_RING_ID = 0x5,     ///< MCD_1
+        N1_VA_0_RING_ID = 0x6       ///< VA_0
+    } p9_n1_ring_id_t;
+
+    /// P9 N2 chiplet SCOM ring ID enumeration
+    /// source: tpc_p9_n2_top.vhdl
+    typedef enum
+    {
+        N2_PSCM_RING_ID = 0x0,      ///< PSCOM
+        N2_PERV_RING_ID = 0x1,      ///< PERV
+        N2_CXA1_0_RING_ID = 0x2,    ///< CXA1_0
+        N2_PCIS0_0_RING_ID = 0x3,   ///< PCIS0_0
+        N2_PCIS1_0_RING_ID = 0x4,   ///< PCIS1_0
+        N2_PCIS2_0_RING_ID = 0x5,   ///< PCIS2_0
+        N2_IOPSI_0_RING_ID = 0x6    ///< IOPSI_0
+    } p9_n2_ring_id_t;
+
+    typedef enum
+    {
+        PEC_SAT_ID = 0x0
+    } p9_pec_sat_id_t;
+
+    /// P9 N3 chiplet SCOM ring ID enumeration
+    /// source: tpc_p9_n3_top.vhdl
+    typedef enum
+    {
+        N3_PSCM_RING_ID = 0x0,      ///< PSCOM
+        N3_PERV_RING_ID = 0x1,      ///< PERV
+        N3_MC01_0_RING_ID = 0x2,    ///< MC01_0
+        N3_NPU_0_RING_ID = 0x4,     ///< NPU_0
+        N3_NPU_1_RING_ID = 0x5,     ///< NPU_1
+        N3_PB_0_RING_ID = 0x6,      ///< PB_0
+        N3_PB_1_RING_ID = 0x7,      ///< PB_1
+        N3_PB_2_RING_ID = 0x8,      ///< PB_2
+        N3_PB_3_RING_ID = 0x9,      ///< PB_3
+        N3_BR_0_RING_ID = 0xa,      ///< BR_0
+        N3_MM_0_RING_ID = 0xb,      ///< MM_0
+        N3_INT_0_RING_ID = 0xc,     ///< INT_0
+        N3_PB_4_RING_ID = 0xd,      ///< PB_4
+        N3_PB_5_RING_ID = 0xe,      ///< PB_5
+        N3_NPU_2_RING_ID = 0xf,     ///< NPU_2
+    } p9_n3_ring_id_t;
+
+
+    /// P9 N3 satellite ids
+    typedef enum
+    {
+        P9_N3_MCS01_SAT_ID = 0,
+        P9_N3_MCS23_SAT_ID = 2
+    } p9_n3_sat_id_t;
+
+    /// P9 XBUS chiplet SCOM ring ID enumeration
+    /// source: tpc_p9_xb_top.vhdl
+    typedef enum
+    {
+        XB_PSCM_RING_ID = 0x0,      ///< PSCOM
+        XB_PERV_RING_ID = 0x1,      ///< PERV
+        XB_IOPPE_0_RING_ID = 0x2,   ///< IOPPE
+        XB_IOX_0_RING_ID = 0x3,     ///< IOX_0
+        XB_IOX_1_RING_ID = 0x4,     ///< IOX_1
+        XB_IOX_2_RING_ID = 0x5,     ///< IOX_2
+        XB_PBIOX_0_RING_ID = 0x6,   ///< PBIOX_0
+        XB_PBIOX_1_RING_ID = 0x7,   ///< PBIOX_1
+        XB_PBIOX_2_RING_ID = 0x8    ///< PBIOX_2
+    } p9_xb_ring_id_t;
+
+    typedef enum
+    {
+        XB_PB_SAT_ID = 0x0
+    } p9_xb_pb_sat_id_t;
+
+    typedef enum
+    {
+        XB_IOF_SAT_ID = 0x0,
+        XB_PPE_SAT_ID = 0x1
+    } p9_xb_iof_sat_id_t;
+
+    /// P9 MC chiplet SCOM ring ID enumeration
+    /// source: tpc_p9_mcslow_top.vhdl
+    typedef enum
+    {
+        MC_PSCM_RING_ID = 0x0,      ///< PSCOM
+        MC_PERV_RING_ID = 0x1,      ///< PERV
+        MC_MC01_0_RING_ID = 0x2,    ///< MC01_0 / MC23_0
+        MC_MCTRA_0_RING_ID = 0x3,   ///< MCTRA01_0 / MCTRA23_0
+        MC_IOM01_0_RING_ID = 0x4,   ///< IOM01_0 / IOM45_0
+        MC_IOM01_1_RING_ID = 0x5,   ///< IOM01_1 / IOM45_1
+        MC_IOM23_0_RING_ID = 0x6,   ///< IOM23_0 / IOM67_0
+        MC_IOM23_1_RING_ID = 0x7,   ///< IOM23_1 / IOM67_1
+        MC_MC01_1_RING_ID = 0x8,    ///< MC01_1 / MC23_1
+    } p9_mc_ring_id_t;
+
+    typedef enum
+    {
+        MC_DIR_SAT_ID_PBI_01 = 0x0,
+        MC_DIR_SAT_ID_PBI_23 = 0x2,
+        MC_DIR_SAT_ID_SRQ_0 = 0x4,
+        MC_DIR_SAT_ID_SRQ_1 = 0x5,
+        MC_DIR_SAT_ID_SRQ_2 = 0x6,
+        MC_DIR_SAT_ID_SRQ_3 = 0x7,
+        MC_DIR_SAT_ID_ECC64_0 = 0x8,
+        MC_DIR_SAT_ID_ECC64_1 = 0x9,
+        MC_DIR_SAT_ID_ECC64_2 = 0xa,
+        MC_DIR_SAT_ID_ECC64_3 = 0xb
+    } p9_mc_dir0_sat_id_t;
+
+    //These are for registers that reside in the MCS chiplet, but
+    //are used for MCA registers and should be targetted with MCA
+    //target type.  There is no way to identify them other than by
+    //register offset value.  All registers know of this type are
+    //listed bellow, but a range is used for checking
+    typedef enum
+    {
+        MC_MCS_MCA_OFFSET_MCP0XLT0  = 0x20,
+        MC_MCS_MCA_OFFSET_MCP0XLT1  = 0x21,
+        MC_MCS_MCA_OFFSET_MCP0XLT2  = 0x22,
+        MC_MCS_MCA_OFFSET_MCPERF0  = 0x23,
+        MC_MCS_MCA_OFFSET_MCPERF2  = 0x24,
+        MC_MCS_MCA_OFFSET_MCAMOC  = 0x25,
+        MC_MCS_MCA_OFFSET_MCEPSQ  = 0x26,
+        MC_MCS_MCA_OFFSET_MCBUSYQ  = 0x27,
+        MC_MCS_MCA_OFFSET_MCERRINJ  = 0x28,
+        MC_MCS_MCA_OFFSET_MCEBUSCL  = 0x29,
+        MC_MCS_MCA_OFFSET_MCWAT  = 0x2A,
+        MC_MCS_MCA_OFFSET_MCPERF3  = 0x2B
+    } p9_mcs_mca_offset_t;
+
+    typedef enum
+    {
+        MC_IND_SAT_ID = 0x0,
+        MC_DIR_SAT_ID_MCBIST = 0xC,
+        P9C_SAT_ID_CHAN_MCBIST = 0xD
+    } p9_mc_dir1_sat_id_t;
+
+
+    /// Cumulus mc rings
+    typedef enum
+    {
+        P9C_MC_PSCM_RING_ID  = 0x0,
+        P9C_MC_PERV_RING_ID  = 0x1,
+        P9C_MC_CHAN_RING_ID  = 0x2,
+        P9C_MC_MCTRA_RING_ID = 0x3,
+        P9C_MC_IO_RING_ID    = 0x4,
+        P9C_MC_PPE_RING_ID   = 0x5,
+        P9C_MC_BIST_RING_ID  = 0x8
+    } p9c_mc_ring_id_t;
+
+    typedef enum
+    {
+        P9C_MC_PPE_SAT_ID = 0x1
+    } p9c_mc_ppe_sat_id_t;
+
+    typedef enum
+    {
+        P9C_MC_OFFSET_IND = 0x3F
+    } p9c_mc_sat_offset_t;
+
+    /// P9 OB chiplet SCOM ring ID enumeration
+    /// source: tpc_p9_ob_top.vhdl
+    typedef enum
+    {
+        OB_PSCM_RING_ID = 0x0,      ///< PSCOM
+        OB_PERV_RING_ID = 0x1,      ///< PERV
+        OB_PBIOA_0_RING_ID = 0x2,   ///< PBIOA_0
+        OB_IOO_0_RING_ID = 0x3,     ///< IOO_0
+        OB_PPE_RING_ID = 0x4        ///< PPE
+    } p9_ob_ring_id_t;
+
+    typedef enum
+    {
+        OB_PB_SAT_ID = 0x0
+    } p9_ob_pb_sat_id_t;
+
+    typedef enum
+    {
+        OB_IOO_SAT_ID = 0x0,
+        OB_PPE_SAT_ID = 0x1
+    } p9_ob_ioo_sat_id_t;
+
+    /// P9 PCIe chiplet SCOM ring ID enumeration
+    /// source: tpc_p9_pci[012]_top.vhdl
+    typedef enum
+    {
+        PCI_PSCM_RING_ID = 0x0,      ///< PSCOM
+        PCI_PERV_RING_ID = 0x1,      ///< TRA
+        PCI_PE_0_RING_ID = 0x2,      ///< PE_0
+        PCI_IOPCI_0_RING_ID = 0x3    ///< IOPCI_0
+    } p9_pci_ring_id_t;
+
+    /// P9 PPE GPE ring enumeration (bits 16:21)
+    typedef enum
+    {
+        PPE_SBE_RING_ID  = 0x00,
+        PPE_GPE0_RING_ID = 0x00,
+        PPE_GPE1_RING_ID = 0x08,
+        PPE_GPE2_RING_ID = 0x10,
+        PPE_GPE3_RING_ID = 0x18,
+    } p9_tp_ring_id_t;
+
+    /// Satellite ID for PERV
+    typedef enum
+    {
+        PERV_DBG_SAT_ID = 0xF,
+    } p9_perv_sat_id_t;
+
+    /// Satellite ID for SBE
+    typedef enum
+    {
+        PPE_SBE_SAT_ID = 0x0,
+    } p9_tp_sbe_sat_id_t;
+
+    /// Satellite ID for PPE GPE
+    typedef enum
+    {
+        PPE_GPE_SAT_ID = 0x0,
+    } p9_tp_gpe_sat_id_t;
+
+    /// Satellite ID for PPE CME
+    typedef enum
+    {
+        PPE_CME_SAT_ID = 0x0,
+    } p9_eq_ppe_sat_id_t;
+
+    /// Satellite ID for PPE PB
+    typedef enum
+    {
+        PPE_PB_SAT_ID = 0x0,
+    } p9_n3_ppe_sat_id;
+
+    /// P9A MC chiplet SCOM ring ID enumeration
+    /// source: tpc_p9u_mc01_top.vhdl
+    typedef enum
+    {
+        P9A_MC_PSCM_RING_ID = 0x0,       ///< PSCOM
+        P9A_MC_PERV_RING_ID = 0x1,       ///< PERV
+        P9A_MC_CHAN_RING_ID = 0x2,       ///< Channel registers
+        P9A_MC_OMIC0_RING_ID = 0x4,      ///< OMIC0
+        P9A_MC_OMIC1_RING_ID = 0x5,      ///< OMIC1
+        P9A_MC_OMIC2_RING_ID = 0x6,      ///< OMIC2
+        P9A_MC_MC01_RING_ID = 0x8,       ///< MC01
+        P9A_MC_OMIC0_PPE_RING_ID = 0x9,  ///< OMIC0 PPE
+        P9A_MC_OMIC1_PPE_RING_ID = 0xA,  ///< OMIC1 PPE
+        P9A_MC_OMIC2_PPE_RING_ID = 0xB,  ///< OMIC2 PPE
+        P9A_MC_OMI_DL_RING_ID = 0xC,     ///< OMI DL rings
+    } p9a_mc_ring_id_t;
+
+    // P9A Sat id enumeration
+    typedef enum
+    {
+        P9A_MC_IND_SAT_ID = 0x0,          ///< Indirect sat_id
+        P9A_MC_DSTL_CHAN0_SAT_ID = 0x4,   ///< USTL registers channel 0
+        P9A_MC_DSTL_CHAN1_SAT_ID = 0x5,   ///< USTL registers channel 1
+        P9A_MC_DSTL_CHAN2_SAT_ID = 0x6,   ///< USTL registers channel 2
+        P9A_MC_DSTL_CHAN3_SAT_ID = 0x7,   ///< USTL registers channel 3
+        P9A_MC_USTL_CHAN0_SAT_ID = 0x8,   ///< USTL registers channel 0
+        P9A_MC_USTL_CHAN1_SAT_ID = 0x9,   ///< USTL registers channel 1
+        P9A_MC_USTL_CHAN2_SAT_ID = 0xA,   ///< USTL registers channel 2
+        P9A_MC_USTL_CHAN3_SAT_ID = 0xB,   ///< USTL registers channel 3
+        P9A_MC_DL_REG0_SAT_ID = 0xD,      ///< OMI reg0 (omi0..2)
+        P9A_MC_DL_REG1_SAT_ID = 0xE,      ///< OMI reg1 (omi3..5)
+        P9A_MC_DL_REG2_SAT_ID = 0xF,      ///< OMI reg2 (omi6..7)
+    } p9a_mc_sat_id_t;
+
+    typedef enum
+    {
+        P9A_MC_DL_OMI0_FRST_REG = 0x10,   ///< First register of OMI % 3 == 0
+        P9A_MC_DL_OMI1_FRST_REG = 0x20,   ///< First register of OMI % 3 == 1
+        P9A_MC_DL_OMI2_FRST_REG = 0x30,   ///< First register of OMI % 3 == 2
+        P9A_MC_IND_REG = 0x3F,            ///< Indirect regiser
+    } p9a_mc_reg_offsets_t;
+
+    typedef enum
+    {
+        P9A_MC_OMI0_FRST_LANE = 0x0,      ///< First lane of OMI % 3 = 0
+        P9A_MC_OMI1_FRST_LANE = 0x8,      ///< First lane of OMI % 3 = 1
+        P9A_MC_OMI2_FRST_LANE = 0x10,     ///< First lane of OMI % 3 = 2
+    } p9a_mc_lane_t;
+
+//        8             7             6             5             4             3          2         1
+//
+//  |0 1 2 3| |4 5 6 7| |8 9 10 11| |12 13 14 15| |16 17 18 19| |20 21 22 23| |24 25 26 27| |28 29 30 31|
+//    {A}{     B      }             {   C    }          {      D      }{     E      }{        F          }
+//
+// A - Is multiCast if bit 1 = 0x1
+// B - Contains Chiplet ID (6 bits) [2:7]
+// C - Contains Port Number (4 bits) [12:15]
+// D - Ring (4 bits) [18:21]
+// E - Sat ID (4 bits) [22:25]
+// F - Sat Offset (6 bits) [26:31]
+
+    /// P9 SCOM address class
+    class p9_scom_addr
+    {
+
+        public:
+            /// @brief Construct a SCOM address object
+            /// @param[in] i_addr 64-bit raw SCOM address
+            p9_scom_addr(const uint64_t i_addr)
+                : iv_addr(i_addr)
+            {
+            }
+
+            /// @brief Set full/raw SCOM address
+            /// @param[in] i_addr 64-bit SCOM address
+            /// @retval none
+            inline void set_addr(const uint64_t i_addr)
+            {
+                iv_addr = i_addr;
+                return;
+            }
+
+            /// @brief Retrieve full/raw SCOM address
+            /// @retval uint64_t 64-bit SCOM address
+            inline uint64_t get_addr() const
+            {
+                return (iv_addr);
+            }
+
+            /// @brief Determine if SCOM address is direct-form
+            /// @retval bool True if SCOM address is direct-form, false otherwise
+            inline bool is_direct() const
+            {
+                return (((iv_addr >> 63) & 0x1) == 0x0);
+            }
+
+            /// @brief Determine if SCOM address is indirect-form
+            /// @retval bool True if SCOM address is indirect-form, false otherwise
+            inline bool is_indirect() const
+            {
+                return (!is_direct());
+            }
+
+            /// @brief Determine if SCOM address is unicast
+            /// @retval bool True if SCOM address is unicast, false otherwise
+            inline bool is_unicast() const
+            {
+                return (!(is_multicast()));
+            }
+
+            /// @brief Determine if SCOM address is multicast
+            /// @retval bool True if SCOM address is multicast, false otherwise
+            inline bool is_multicast() const
+            {
+                return (((iv_addr >> 30) & 0x1) == 0x1);
+            }
+
+            /// @brief Extract pervasive chiplet ID from SCOM address
+            /// @retval uint8_t Pervasive chiplet ID value
+            inline uint8_t get_chiplet_id() const
+            {
+                return ((iv_addr >> 24) & 0x3F);
+            }
+
+            /// @brief Modify SCOM address, update pervasive chiplet ID
+            /// @param[in] i_chiplet_id Chiplet ID value to write
+            /// @retval none
+            inline void set_chiplet_id(const uint8_t i_chiplet_id)
+            {
+                iv_addr &= 0xFFFFFFFFC0FFFFFFULL;
+                iv_addr |= ((i_chiplet_id & 0x3F) << 24);
+                return;
+            }
+
+            /// @brief Extract port field from SCOM address
+            /// @retval uint8_t Port field value
+            inline uint8_t get_port() const
+            {
+                return ((iv_addr >> 16) & 0xF);
+            }
+
+            /// @brief Modify the port field from SCOM address
+            /// @retval uint8_t Port field value
+            inline void set_port(const uint8_t i_port)
+            {
+                iv_addr &= 0xFFFFFFFFFFF0FFFFULL;
+                iv_addr |= ((i_port & 0xF) << 16);
+                return;
+            }
+
+            /// @brief Extract ring field from SCOM address
+            /// @retval uint8_t Ring field value
+            inline uint8_t get_ring() const
+            {
+                return ((iv_addr >> 10) & 0x3F);
+            }
+
+            /// @brief Modify SCOM address, update ring field value
+            /// @param[in] i_ring Ring field value to write
+            /// @retval none
+            inline void set_ring(const uint8_t i_ring)
+            {
+                iv_addr &= 0xFFFFFFFFFFFF03FFULL;
+                iv_addr |= ((i_ring & 0x3F) << 10);
+                return;
+            }
+
+            /// @brief Extract satellite ID field from SCOM address
+            /// @retval uint8_t Satellite ID field value
+            inline uint8_t get_sat_id() const
+            {
+                return ((iv_addr >> 6) & 0xF);
+            }
+
+            /// @brief Modify SCOM address, update satellite ID field
+            /// @param[in] i_sat_id Satellite ID value to write
+            /// @retval none
+            inline void set_sat_id(const uint8_t i_sat_id)
+            {
+                iv_addr &= 0xFFFFFFFFFFFFFC3FULL;
+                iv_addr |= ((i_sat_id & 0xF) << 6);
+                return;
+            }
+
+            /// @brief Extract satellite register offset field from SCOM address
+            /// @retval uint8_t Satellite register offset field value
+            inline uint8_t get_sat_offset() const
+            {
+                return (iv_addr & 0x3F);
+            }
+
+            /// @brief Modify SCOM address, update satellite offset field
+            /// @param[in] i_sat_offset Satellite offset value to write
+            /// @retval none
+            inline void set_sat_offset(const uint8_t i_sat_offset)
+            {
+                iv_addr &= 0xFFFFFFFFFFFFFFC0ULL;
+                iv_addr |= (i_sat_offset & 0x3F);
+                return;
+            }
+
+            /// @brief Extract the RX or TX Group ID of an indirect scom address
+            /// @retval uint8_t RX/TX group id
+            inline uint8_t get_rxtx_group_id()
+            {
+                return (iv_addr >> 37) & 0x3F;
+            }
+
+            /// @brief Modify SCOM address, update the RX or TX Group ID
+            /// @param[in] i_grp_id Group id to set
+            /// @retval none
+            inline void set_rxtx_group_id(uint8_t i_grp_id)
+            {
+                iv_addr &= 0xFFFFF81FFFFFFFFFULL;
+                iv_addr |= (i_grp_id & 0x3FULL) << 37;
+            }
+
+            /// @brief Extract the RX or TX Group ID of an indirect scom address
+            /// @retval uint8_t RX/TX group id
+            inline uint8_t get_lane_id()
+            {
+                return (iv_addr >> 32) & 0x1F;
+            }
+
+            /// @brief Modify SCOM address, update the RX or TX Group ID
+            /// @param[in] i_grp_id Group id to set
+            /// @retval none
+            inline void set_lane_id(uint8_t i_grp_id)
+            {
+                iv_addr &= 0xFFFFFFE0FFFFFFFFULL;
+                iv_addr |= (i_grp_id & 0x1FULL) << 32;
+            }
+
+            /// @brief Extract the indirect address field of a scom address
+            /// @retval uint16_t indirect address field
+            inline uint16_t get_ind_addr()
+            {
+                return (iv_addr >> 43) & 0x1FF;
+            }
+
+            /// @brief Determine if SCOM address is valid/well-formed
+            /// @retval bool True if SCOM address is valid, false otherwise
+            inline bool is_valid() const
+            {
+                return true;
+            }
+
+        private:
+            uint64_t iv_addr;   ///< 64-bit raw SCOM address
+    };
+
+} // extern "C"
+
+#endif /* P9_SCOM_ADDR_H */
diff --git a/src/tests/p9_scominfo.C b/src/tests/p9_scominfo.C
new file mode 100644
index 0000000..745fb35
--- /dev/null
+++ b/src/tests/p9_scominfo.C
@@ -0,0 +1,1494 @@
+/* IBM_PROLOG_BEGIN_TAG                                                   */
+/* This is an automatically generated prolog.                             */
+/*                                                                        */
+/* $Source: chips/p9/common/scominfo/p9_scominfo.C $                      */
+/*                                                                        */
+/* IBM CONFIDENTIAL                                                       */
+/*                                                                        */
+/* EKB Project                                                            */
+/*                                                                        */
+/* COPYRIGHT 2015,2018                                                    */
+/* [+] International Business Machines Corp.                              */
+/*                                                                        */
+/*                                                                        */
+/* The source code for this program is not published or otherwise         */
+/* divested of its trade secrets, irrespective of what has been           */
+/* deposited with the U.S. Copyright Office.                              */
+/*                                                                        */
+/* IBM_PROLOG_END_TAG                                                     */
+///
+/// @file p9_scominfo.C
+/// @brief P9 chip unit SCOM address platform translation code
+///
+/// HWP HWP Owner: jmcgill at us.ibm.com
+/// HWP FW Owner: dcrowell at us.ibm.com
+/// HWP Team: Infrastructure
+/// HWP Level: 1
+/// HWP Consumed by: FSP/HB
+///
+
+// includes
+#include "p9_scominfo.H"
+#include "p9_scom_addr.H"
+
+#define P9_SCOMINFO_C
+
+// bgass Aug 13 2018.  The decision was made to make
+// OMI target numbers line up logically with the memory
+// parent targets (MC, MI, MCC)                  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
+const static int P9_SCOMINFO_OMI_SWIZZLE[]   = { 4, 5, 6, 7, 2, 3, 0, 1, 12, 13, 14, 15, 10, 11, 8, 9 };
+const static int P9_SCOMINFO_OMI_UNSWIZZLE[] = { 6, 7, 4, 5, 0, 1, 2, 3, 14, 15, 12, 13, 8, 9, 10, 11 };
+
+extern "C"
+{
+    uint64_t p9_scominfo_createChipUnitScomAddr(const p9ChipUnits_t i_p9CU, const uint8_t i_chipUnitNum,
+            const uint64_t i_scomAddr, const uint32_t i_mode)
+    {
+        p9_scom_addr l_scom(i_scomAddr);
+        uint8_t l_ring = l_scom.get_ring();
+        uint8_t l_chiplet_id = l_scom.get_chiplet_id();
+        uint8_t l_sat_id = l_scom.get_sat_id();
+        uint8_t l_sat_offset = l_scom.get_sat_offset();
+
+
+        //Used to help generate entries for the SCOMdef documentation,
+        //These aren't general PIB addresses
+        if ((i_mode & PPE_MODE) == PPE_MODE)
+        {
+            switch (i_p9CU)
+            {
+
+                case PU_EX_CHIPUNIT:
+                    if (PPE_EP05_CHIPLET_ID >= l_scom.get_chiplet_id() &&
+                        l_scom.get_chiplet_id() >= PPE_EP00_CHIPLET_ID)
+                    {
+                        l_scom.set_chiplet_id(PPE_EP00_CHIPLET_ID + (i_chipUnitNum / 2));
+                        l_scom.set_port( ( i_chipUnitNum % 2 ) + 1 );
+                    }
+
+                    break;
+
+                default:
+                    l_scom.set_addr(FAILED_TRANSLATION);
+                    break;
+            }
+        }
+        //Regular PIB addresses (not PPE)
+        else
+        {
+            switch (i_p9CU)
+            {
+                case PU_PERV_CHIPUNIT:
+                    l_scom.set_chiplet_id(i_chipUnitNum);
+                    break;
+
+                case PU_C_CHIPUNIT:
+                    l_scom.set_chiplet_id(EC00_CHIPLET_ID + i_chipUnitNum);
+                    break;
+
+                case PU_EX_CHIPUNIT:
+                    if (EP05_CHIPLET_ID >= l_scom.get_chiplet_id() &&
+                        l_scom.get_chiplet_id() >= EP00_CHIPLET_ID)
+                    {
+                        l_scom.set_chiplet_id(EP00_CHIPLET_ID + (i_chipUnitNum / 2));
+                        uint8_t l_ringId = (l_scom.get_ring() & 0xF); // Clear bits 16:17
+                        l_ringId = ( l_ringId - ( l_ringId % 2 ) ) + ( i_chipUnitNum % 2 );
+                        l_scom.set_ring( l_ringId & 0xF );
+                    }
+                    else if (EC23_CHIPLET_ID >= l_scom.get_chiplet_id() &&
+                             l_scom.get_chiplet_id() >= EC00_CHIPLET_ID)
+                    {
+                        l_scom.set_chiplet_id( EC00_CHIPLET_ID +
+                                               (l_scom.get_chiplet_id() % 2) +
+                                               (i_chipUnitNum * 2));
+                    }
+
+                    break;
+
+                case PU_EQ_CHIPUNIT:
+                    l_scom.set_chiplet_id(EP00_CHIPLET_ID + i_chipUnitNum);
+                    break;
+
+                case PU_CAPP_CHIPUNIT:
+                    l_scom.set_chiplet_id(N0_CHIPLET_ID + (i_chipUnitNum * 2));
+                    break;
+
+                case PU_MCS_CHIPUNIT:
+                    l_scom.set_chiplet_id(N3_CHIPLET_ID - (2 * (i_chipUnitNum / 2)));
+                    l_scom.set_sat_id(2 * (i_chipUnitNum % 2));
+                    break;
+
+                case PU_MCBIST_CHIPUNIT:
+                    l_scom.set_chiplet_id(MC01_CHIPLET_ID + i_chipUnitNum);
+                    break;
+
+                case PU_MCA_CHIPUNIT:
+                    if (l_scom.get_chiplet_id() == MC01_CHIPLET_ID || l_scom.get_chiplet_id() ==  MC23_CHIPLET_ID)
+                    {
+                        l_scom.set_chiplet_id(MC01_CHIPLET_ID + (i_chipUnitNum / 4));
+
+                        if ( (l_scom.get_ring() & 0xF) == MC_MC01_0_RING_ID)
+                        {
+                            // mc
+                            l_scom.set_sat_id( ( l_scom.get_sat_id() - ( l_scom.get_sat_id() % 4 ) ) +
+                                               ( i_chipUnitNum % 4 ));
+                        }
+                        else
+                        {
+                            // iomc
+                            l_scom.set_ring( (MC_IOM01_0_RING_ID + (i_chipUnitNum % 4)) & 0xF );
+                        }
+                    }
+                    else
+                    {
+                        //mcs->mca regisers
+                        uint8_t i_mcs_unitnum = ( i_chipUnitNum / 2 );
+                        l_scom.set_chiplet_id(N3_CHIPLET_ID - (2 * (i_mcs_unitnum / 2)));
+                        l_scom.set_sat_id(2 * (i_mcs_unitnum % 2));
+                        uint8_t i_mcs_sat_offset = (0x2F & l_scom.get_sat_offset());
+                        i_mcs_sat_offset |= ((i_chipUnitNum % 2) << 4);
+                        l_scom.set_sat_offset(i_mcs_sat_offset);
+                    }
+
+                    break;
+
+                case PU_MC_CHIPUNIT:
+                    l_scom.set_chiplet_id(MC01_CHIPLET_ID + i_chipUnitNum);
+                    break;
+
+                case PU_MI_CHIPUNIT:
+                    //-------------------------------------------
+                    // MI
+                    //-------------------------------------------
+                    //          Chiplet   Ring   Satid   Off
+                    //MCS0           05     02       0   !SCOM3
+                    //MCS1           05     02       2   !SCOM3
+                    //MCS2           03     02       0   !SCOM3
+                    //MCS3           03     02       2   !SCOM3
+                    l_scom.set_chiplet_id(N3_CHIPLET_ID - (2 * (i_chipUnitNum / 2)));
+                    l_scom.set_sat_id(2 * (i_chipUnitNum % 2));
+                    break;
+
+                case PU_DMI_CHIPUNIT:
+                    if (((l_chiplet_id == N3_CHIPLET_ID) || (l_chiplet_id == N1_CHIPLET_ID)))
+                    {
+                        //SCOM3   (See mc_clscom_rlm.fig <= 0xB vs mc_scomfir_rlm.fig > 0xB)
+                        //DMI0           05     02       0   0x2X (X <= 0xB)
+                        //DMI1           05     02       0   0x3X (X <= 0xB)
+                        //DMI2           05     02       2   0x2X (X <= 0xB)
+                        //DMI3           05     02       2   0x3X (X <= 0xB)
+                        //DMI4           03     02       0   0x2X (X <= 0xB)
+                        //DMI5           03     02       0   0x3X (X <= 0xB)
+                        //DMI6           03     02       2   0x2X (X <= 0xB)
+                        //DMI7           03     02       2   0x3X (X <= 0xB)
+                        l_scom.set_chiplet_id(N3_CHIPLET_ID - (2 * (i_chipUnitNum / 4)));
+                        l_scom.set_sat_id(2 * ((i_chipUnitNum / 2) % 2));
+                        l_sat_offset = (l_sat_offset & 0xF) + ((2 + (i_chipUnitNum % 2)) << 4);
+                        l_scom.set_sat_offset(l_sat_offset);
+                    }
+
+                    if (((l_chiplet_id == MC01_CHIPLET_ID) || (l_chiplet_id == MC23_CHIPLET_ID)))
+                    {
+                        //-------------------------------------------
+                        // DMI
+                        //-------------------------------------------
+                        //SCOM1,2
+                        //DMI0           07     02       0
+                        //DMI1           07     02       1
+                        //DMI2           07     02       2
+                        //DMI3           07     02       3
+                        //DMI4           08     02       0
+                        //DMI5           08     02       1
+                        //DMI6           08     02       2
+                        //DMI7           08     02       3
+                        if (l_ring == P9C_MC_CHAN_RING_ID)
+                        {
+                            l_scom.set_chiplet_id(MC01_CHIPLET_ID + (i_chipUnitNum / 4));
+                            uint8_t l_msat = l_scom.get_sat_id();
+                            l_msat = l_msat & 0xC;
+                            l_scom.set_sat_id(l_msat + i_chipUnitNum % 4);
+                        }
+
+                        //SCOM4
+                        //DMI0           07     08     0xD   0x0X
+                        //DMI1           07     08     0xD   0x1X
+                        //DMI2           07     08     0xD   0x2X
+                        //DMI3           07     08     0xD   0x3X
+                        //DMI4           08     08     0xD   0x0X
+                        //DMI5           08     08     0xD   0x1X
+                        //DMI6           08     08     0xD   0x2X
+                        //DMI7           08     08     0xD   0x3X
+                        if (l_ring == P9C_MC_BIST_RING_ID)
+                        {
+                            l_scom.set_chiplet_id(MC01_CHIPLET_ID + (i_chipUnitNum / 4));
+                            l_sat_offset = (l_sat_offset & 0xF) + ((i_chipUnitNum % 4) << 4);
+                            l_scom.set_sat_offset(l_sat_offset);
+                        }
+
+                        //-------------------------------------------
+                        // DMI IO
+                        //-------------------------------------------
+                        //          Chiplet   Ring   Satid    Off    RXTXGrp
+                        //DMI0           07     04       0   0x3F       0x00
+                        //DMI1           07     04       0   0x3F       0x01
+                        //DMI2           07     04       0   0x3F       0x02
+                        //DMI3           07     04       0   0x3F       0x03
+                        //DMI4           08     04       0   0x3F       0x00
+                        //DMI5           08     04       0   0x3F       0x01
+                        //DMI6           08     04       0   0x3F       0x02
+                        //DMI7           08     04       0   0x3F       0x03
+
+                        //DMI0           07     04       0   0x3F       0x20
+                        //DMI1           07     04       0   0x3F       0x21
+                        //DMI2           07     04       0   0x3F       0x22
+                        //DMI3           07     04       0   0x3F       0x23
+                        //DMI4           08     04       0   0x3F       0x20
+                        //DMI5           08     04       0   0x3F       0x21
+                        //DMI6           08     04       0   0x3F       0x22
+                        //DMI7           08     04       0   0x3F       0x23
+                        //
+                        //0 MC01.CHAN0  IOM01.TX_WRAP.TX3
+                        //1 MC01.CHAN1  IOM01.TX_WRAP.TX2
+                        //2 MC01.CHAN2  IOM01.TX_WRAP.TX0
+                        //3 MC01.CHAN3  IOM01.TX_WRAP.TX1
+                        //4 MC23.CHAN0  IOM23.TX_WRAP.TX3
+                        //5 MC23.CHAN1  IOM23.TX_WRAP.TX2
+                        //6 MC23.CHAN2  IOM23.TX_WRAP.TX0
+                        //7 MC23.CHAN3  IOM23.TX_WRAP.TX1
+                        // 3, 2, 0, 1
+                        if (l_ring == P9C_MC_IO_RING_ID)
+                        {
+                            l_scom.set_chiplet_id(MC01_CHIPLET_ID + (i_chipUnitNum / 4));
+                            uint8_t l_rxtx_grp = l_scom.get_rxtx_group_id();
+                            l_rxtx_grp = l_rxtx_grp & 0xF0;
+
+                            switch ((i_chipUnitNum % 4))
+                            {
+                                case  0:
+                                    l_rxtx_grp += 3;
+                                    break;
+
+                                case  1:
+                                    l_rxtx_grp += 2;
+                                    break;
+
+                                case  2:
+                                    l_rxtx_grp += 0;
+                                    break;
+
+                                case  3:
+                                    l_rxtx_grp += 1;
+                                    break;
+
+                                default:
+                                    //escape to bunker - math broke
+                                    break;
+                            }
+
+                            l_scom.set_rxtx_group_id(l_rxtx_grp); // 3,2,0,1
+                        }
+
+                    }
+
+                    break;
+
+                case PU_MCC_CHIPUNIT:
+                    if (((l_chiplet_id == N3_CHIPLET_ID) || (l_chiplet_id == N1_CHIPLET_ID)))
+                    {
+                        //SCOM3   (See mc_clscom_rlm.fig <= 0xB vs mc_scomfir_rlm.fig > 0xB)
+                        //DMI0           05     02       0   0x2X (X <= 0xB)
+                        //DMI1           05     02       0   0x3X (X <= 0xB)
+                        //DMI2           05     02       2   0x2X (X <= 0xB)
+                        //DMI3           05     02       2   0x3X (X <= 0xB)
+                        //DMI4           03     02       0   0x2X (X <= 0xB)
+                        //DMI5           03     02       0   0x3X (X <= 0xB)
+                        //DMI6           03     02       2   0x2X (X <= 0xB)
+                        //DMI7           03     02       2   0x3X (X <= 0xB)
+                        l_scom.set_chiplet_id(N3_CHIPLET_ID - (2 * (i_chipUnitNum / 4)));
+                        l_scom.set_sat_id(2 * ((i_chipUnitNum / 2) % 2));
+                        uint8_t l_satoff = (l_sat_offset & 0xF) + ((2 + (i_chipUnitNum % 2)) << 4);
+                        l_scom.set_sat_offset(l_satoff);
+                    }
+
+                    if (((l_chiplet_id == MC01_CHIPLET_ID) || (l_chiplet_id == MC23_CHIPLET_ID)))
+                    {
+                        //CHANX.USTL.  Sat_id: 10 + port_id (8,9,10,11)
+                        //CHANX.DSTL.  Sat_id: 01 + port_id (4,5,6,7)
+                        l_scom.set_chiplet_id(MC01_CHIPLET_ID + (i_chipUnitNum / 4));
+
+                        if (P9A_MC_DSTL_CHAN0_SAT_ID <= l_sat_id && l_sat_id <= P9A_MC_DSTL_CHAN3_SAT_ID)
+                        {
+                            l_scom.set_sat_id(P9A_MC_DSTL_CHAN0_SAT_ID + (i_chipUnitNum % 4));
+                        }
+
+                        if (P9A_MC_USTL_CHAN0_SAT_ID <= l_sat_id && l_sat_id <= P9A_MC_USTL_CHAN3_SAT_ID)
+                        {
+                            l_scom.set_sat_id(P9A_MC_USTL_CHAN0_SAT_ID + (i_chipUnitNum % 4));
+                        }
+                    }
+
+                    break;
+
+                case PU_OMIC_CHIPUNIT:
+                    l_scom.set_chiplet_id(MC01_CHIPLET_ID + (i_chipUnitNum / 3));
+
+                    if (P9A_MC_OMIC0_RING_ID <= l_ring && l_ring <= P9A_MC_OMIC2_RING_ID)
+                    {
+                        l_scom.set_ring(P9A_MC_OMIC0_RING_ID + (i_chipUnitNum % 3));
+                    }
+
+                    if (P9A_MC_OMIC0_PPE_RING_ID <= l_ring && l_ring <= P9A_MC_OMIC2_PPE_RING_ID)
+                    {
+                        l_scom.set_ring(P9A_MC_OMIC0_PPE_RING_ID + (i_chipUnitNum % 3));
+                    }
+
+                    break;
+
+                case PU_OMI_CHIPUNIT:
+                    {
+                        //Unswizzle the OMI chip unit number
+                        uint8_t l_chipUnitNum = P9_SCOMINFO_OMI_UNSWIZZLE[i_chipUnitNum];
+
+                        l_scom.set_chiplet_id(MC01_CHIPLET_ID + (l_chipUnitNum / 8));
+
+                        if (P9A_MC_OMIC0_RING_ID <= l_ring && l_ring <= P9A_MC_OMIC2_RING_ID)
+                        {
+                            // IO Ind regsiters  (Ring 4,5,6) reg == 63
+                            // 0701103F MCP_OMI0. Lanes 0-7    omi0
+                            // 0701103F MCP_OMI0. Lanes 8-15   omi1
+                            // 0701103F MCP_OMI0. Lanes 16-23  omi2
+                            // 0701143F MCP_OMI1. Lanes 0-7    omi3
+                            // 0701143F MCP_OMI1. Lanes 8-15   omi4
+                            // 0701143F MCP_OMI1. Lanes 16-23  omi5
+                            // 0701183F MCP_OMI2. Lanes 0-7    omi6
+                            // 0701183F MCP_OMI2. Lanes 8-15   omi7
+                            l_scom.set_ring(P9A_MC_OMIC0_RING_ID + ((l_chipUnitNum % 8) / 3));
+                            uint8_t l_lane = l_scom.get_lane_id();
+                            l_lane = l_lane % 8;
+                            uint8_t l_chipnum = l_chipUnitNum;
+
+                            if (l_chipnum >= 8)
+                            {
+                                l_chipnum++;
+                            }
+
+                            l_scom.set_lane_id(((l_chipnum % 3) * 8) + l_lane);
+                        }
+
+                        if (l_ring == P9A_MC_OMI_DL_RING_ID)
+                        {
+                            // DL Registers
+                            // reg0 dl0 -> omi0  ring: 12  sat_id: 13  regs 16..31
+                            // reg0 dl1 -> omi1  ring: 12  sat_id: 13  regs 32..47
+                            // reg0 dl2 -> omi2  ring: 12  sat_id: 13  regs 48..63
+                            // reg1 dl0 -> omi3  ring: 12  sat_id: 14  regs 16..31
+                            // reg1 dl1 -> omi4  ring: 12  sat_id: 14  regs 32..47
+                            // reg1 dl2 -> omi5  ring: 12  sat_id: 14  regs 48..63
+                            // reg2 dl0 -> omi6  ring: 12  sat_id: 15  regs 16..31
+                            // reg2 dl1 -> omi7  ring: 12  sat_id: 15  regs 32..47
+                            l_scom.set_sat_id(P9A_MC_DL_REG0_SAT_ID + ((l_chipUnitNum % 8) / 3));
+                            uint8_t l_satoff = l_sat_offset % 16;
+                            uint8_t l_chipnum = l_chipUnitNum;
+
+                            if (l_chipnum >= 8)
+                            {
+                                l_chipnum++;
+                            }
+
+                            l_scom.set_sat_offset((((l_chipnum % 3) * 16) + P9A_MC_DL_OMI0_FRST_REG) +
+                                                  l_satoff);
+                        }
+                    }
+                    break;
+
+                case PU_NV_CHIPUNIT:
+                    if (i_mode == P9N_DD1_SI_MODE)
+                    {
+                        l_scom.set_sat_id((l_scom.get_sat_id() % 4) + ((i_chipUnitNum / 2) * 4));
+                        l_scom.set_sat_offset( (l_scom.get_sat_offset() % 32) +
+                                               (32 * (i_chipUnitNum % 2)));
+                    }
+                    else if (i_mode != P9A_DD1_SI_MODE && i_mode != P9A_DD2_SI_MODE)
+                    {
+                        uint64_t l_sa = i_scomAddr;
+
+                        //                       rrrrrrSTIDxxx---
+                        //                       000100       yyy
+                        //       x"4900" & "00" when "00100010", -- stk0, ntl0, 00-07, hyp-only
+                        //       x"0b00" & "11" when "00101001", -- stk0, ntl1, 24-31, user-acc
+                        //                             STID
+                        //       x"5900" & "00" when "01100010", -- stk1, ntl0, 00-07, hyp-only
+                        //       x"1b00" & "11" when "01101001", -- stk1, ntl1, 24-31, user-acc
+                        //                             STID
+                        //       x"6900" & "00" when "10100010", -- stk2, ntl0, 00-07, hyp-only
+                        //       x"2b00" & "11" when "10101001", -- stk2, ntl1, 24-31, user-acc
+
+                        if ((i_chipUnitNum / 2) == 0)
+                        {
+                            l_sa = (l_sa & 0xFFFFFFFFFFFF007FULL) | 0x0000000000001100ULL ;
+                        }
+
+                        if ((i_chipUnitNum / 2) == 1)
+                        {
+                            l_sa = (l_sa & 0xFFFFFFFFFFFF007FULL) | 0x0000000000001300ULL ;
+                        }
+
+                        if ((i_chipUnitNum / 2) == 2)
+                        {
+                            l_sa = (l_sa & 0xFFFFFFFFFFFF007FULL) | 0x0000000000001500ULL ;
+                        }
+
+                        uint64_t l_eo = (l_sa & 0x71) >> 3;
+
+                        if (l_eo > 5 && (i_chipUnitNum % 2 == 0))
+                        {
+                            l_sa -= 0x20ULL; // 0b100 000
+                        }
+
+                        if (l_eo <= 5 && (i_chipUnitNum % 2 == 1))
+                        {
+                            l_sa += 0x20ULL; // 0b100 000
+                        }
+
+                        l_scom.set_addr(l_sa);
+                    }
+                    else
+                    {
+                        //NV not supported on Axone - unused
+                        l_scom.set_addr(FAILED_TRANSLATION);
+                    }
+
+                    break;
+
+                case PU_PEC_CHIPUNIT:
+                    if (l_scom.get_chiplet_id() == N2_CHIPLET_ID)
+                    {
+                        // nest
+                        l_scom.set_ring( (N2_PCIS0_0_RING_ID + i_chipUnitNum) & 0xF);
+                    }
+                    else
+                    {
+                        // iopci / pci
+                        l_scom.set_chiplet_id(PCI0_CHIPLET_ID + i_chipUnitNum);
+                    }
+
+                    break;
+
+                case PU_PHB_CHIPUNIT:
+                    if (l_scom.get_chiplet_id() == N2_CHIPLET_ID)
+                    {
+                        // nest
+                        if (i_chipUnitNum == 0)
+                        {
+                            l_scom.set_ring(N2_PCIS0_0_RING_ID & 0xF);
+                            l_scom.set_sat_id(((l_scom.get_sat_id() < 4) ? (1) : (4)));
+                        }
+                        else
+                        {
+                            l_scom.set_ring( (N2_PCIS0_0_RING_ID + (i_chipUnitNum / 3) + 1) & 0xF);
+                            l_scom.set_sat_id( ((l_scom.get_sat_id() < 4) ? (1) : (4)) +
+                                               ((i_chipUnitNum % 2) ? (0) : (1)) +
+                                               (2 * (i_chipUnitNum / 5)));
+                        }
+                    }
+                    else
+                    {
+                        // pci
+                        if (i_chipUnitNum == 0)
+                        {
+                            l_scom.set_chiplet_id(PCI0_CHIPLET_ID);
+                            l_scom.set_sat_id(((l_scom.get_sat_id() < 4) ? (1) : (4)));
+                        }
+                        else
+                        {
+                            l_scom.set_chiplet_id(PCI0_CHIPLET_ID + (i_chipUnitNum / 3) + 1);
+                            l_scom.set_sat_id(((l_scom.get_sat_id() < 4) ? (1) : (4)) +
+                                              ((i_chipUnitNum % 2) ? (0) : (1)) +
+                                              (2 * (i_chipUnitNum / 5)));
+                        }
+                    }
+
+                    break;
+
+                case PU_OBUS_CHIPUNIT:
+                    l_scom.set_chiplet_id(OB0_CHIPLET_ID + i_chipUnitNum);
+                    break;
+
+                case PU_XBUS_CHIPUNIT:
+
+                    l_ring &= 0xF;
+
+                    if (XB_IOX_2_RING_ID >= l_ring &&
+                        l_ring >= XB_IOX_0_RING_ID)
+                    {
+                        l_scom.set_ring( (XB_IOX_0_RING_ID + i_chipUnitNum) & 0xF);
+                    }
+
+                    else if (XB_PBIOX_2_RING_ID >= l_ring &&
+                             l_ring >= XB_PBIOX_0_RING_ID)
+                    {
+                        l_scom.set_ring( (XB_PBIOX_0_RING_ID + i_chipUnitNum) & 0xF);
+                    }
+
+                    break;
+
+                case PU_SBE_CHIPUNIT:
+                    l_scom.set_chiplet_id(i_chipUnitNum);
+                    break;
+
+                case PU_PPE_CHIPUNIT:
+
+                    // PPE SBE
+                    if (i_chipUnitNum == PPE_SBE_CHIPUNIT_NUM)
+                    {
+                        l_scom.set_chiplet_id(PIB_CHIPLET_ID);
+                        l_scom.set_port(SBE_PORT_ID);
+                        l_scom.set_ring(PPE_SBE_RING_ID);
+                        l_scom.set_sat_id(PPE_SBE_SAT_ID);
+                        l_scom.set_sat_offset(0x0F & l_scom.get_sat_offset());
+                        break;
+                    }
+
+                    // Need to set SAT offset if address is that of PPE SBE
+                    if (l_scom.get_port() == SBE_PORT_ID)
+                    {
+                        // Adjust offset if input address is of SBE
+                        // (ex: 000E0005 --> GPE: xxxxxx1x)
+                        l_scom.set_sat_offset(l_scom.get_sat_offset() | 0x10);
+                    }
+
+                    // PPE GPE
+                    if ( (i_chipUnitNum >= PPE_GPE0_CHIPUNIT_NUM) && (i_chipUnitNum <= PPE_GPE3_CHIPUNIT_NUM) )
+                    {
+                        l_scom.set_chiplet_id(PIB_CHIPLET_ID);
+                        l_scom.set_port(GPE_PORT_ID);
+                        l_scom.set_ring( (i_chipUnitNum - PPE_GPE0_CHIPUNIT_NUM) * 8 );
+                        l_scom.set_sat_id(PPE_GPE_SAT_ID);
+                    }
+
+                    // PPE CME
+                    else if ( (i_chipUnitNum >= PPE_EQ0_CME0_CHIPUNIT_NUM) && (i_chipUnitNum <= PPE_EQ5_CME1_CHIPUNIT_NUM) )
+                    {
+                        if (i_chipUnitNum >= PPE_EQ0_CME1_CHIPUNIT_NUM)
+                        {
+                            l_scom.set_chiplet_id(EP00_CHIPLET_ID +
+                                                  (i_chipUnitNum % PPE_EQ0_CME1_CHIPUNIT_NUM));
+                        }
+                        else
+                        {
+                            l_scom.set_chiplet_id(EP00_CHIPLET_ID +
+                                                  (i_chipUnitNum % PPE_EQ0_CME0_CHIPUNIT_NUM));
+                        }
+
+                        l_scom.set_port(UNIT_PORT_ID);
+                        l_scom.set_ring( ((i_chipUnitNum / PPE_EQ0_CME1_CHIPUNIT_NUM) + 8) & 0xF );
+                        l_scom.set_sat_id(PPE_CME_SAT_ID);
+                    }
+
+                    // PPE IO (XBUS/OBUS)
+                    else if ( (i_chipUnitNum >= PPE_IO_XBUS_CHIPUNIT_NUM) && (i_chipUnitNum <= PPE_IO_OB3_CHIPUNIT_NUM) )
+                    {
+                        l_scom.set_chiplet_id( XB_CHIPLET_ID +
+                                               (i_chipUnitNum % PPE_IO_XBUS_CHIPUNIT_NUM) +
+                                               ((i_chipUnitNum / PPE_IO_OB0_CHIPUNIT_NUM) * 2) );
+                        l_scom.set_port(UNIT_PORT_ID);
+
+                        if (i_chipUnitNum == PPE_IO_XBUS_CHIPUNIT_NUM)
+                        {
+                            l_scom.set_ring(XB_IOPPE_0_RING_ID & 0xF);
+                        }
+                        else
+                        {
+                            l_scom.set_ring(OB_PPE_RING_ID & 0xF);
+                        }
+
+                        l_scom.set_sat_id(OB_PPE_SAT_ID); // Same SAT_ID value for XBUS
+                    }
+
+                    // PPE IO (DMI)
+                    else if ( (i_chipUnitNum >= PPE_IO_DMI0_CHIPUNIT_NUM) && (i_chipUnitNum <= PPE_IO_DMI1_CHIPUNIT_NUM))
+                    {
+                        l_scom.set_chiplet_id(MC01_CHIPLET_ID + (i_chipUnitNum - PPE_IO_DMI0_CHIPUNIT_NUM));
+                        l_scom.set_ring(MC_IOM01_1_RING_ID);
+                        l_scom.set_port(UNIT_PORT_ID);
+                        l_scom.set_sat_id(P9C_MC_PPE_SAT_ID);
+                    }
+
+                    // PPE PB
+                    else if ( (i_chipUnitNum >= PPE_PB0_CHIPUNIT_NUM) && (i_chipUnitNum <= PPE_PB2_CHIPUNIT_NUM) )
+                    {
+                        l_scom.set_chiplet_id(N3_CHIPLET_ID); // TODO: Need to set ChipID for PB1 and PB2 in Cummulus
+                        l_scom.set_port(UNIT_PORT_ID);
+                        l_scom.set_ring(N3_PB_3_RING_ID & 0xF);
+                        l_scom.set_sat_id(PPE_PB_SAT_ID);
+                    }
+
+                    // Invalid i_chipUnitNum
+                    else
+                    {
+                        l_scom.set_addr(FAILED_TRANSLATION);
+                    }
+
+                    break;
+
+                default:
+                    l_scom.set_addr(FAILED_TRANSLATION);
+                    break;
+            }
+        }
+
+        return l_scom.get_addr();
+    }
+
+
+    uint32_t p9_scominfo_xlate_mi(bool& o_chipUnitRelated, std::vector<p9_chipUnitPairing_t>& o_chipUnitPairing,
+                                  p9_scom_addr& i_scom, const p9ChipUnits_t mcc_dmi, const int i_low0, const int i_low1, const uint32_t i_mode)
+    {
+        uint8_t l_chiplet_id = i_scom.get_chiplet_id();
+        uint8_t l_port = i_scom.get_port();
+        uint8_t l_ring = i_scom.get_ring();
+        uint8_t l_sat_id = i_scom.get_sat_id();
+        uint8_t l_sat_offset = i_scom.get_sat_offset();
+
+        //==== AXONE MC/MI/OMIC/OMI  ============================================================================
+        //==== MI target ===============================================
+        if (((l_chiplet_id == N3_CHIPLET_ID) || (l_chiplet_id == N1_CHIPLET_ID)) &&
+            (l_port == UNIT_PORT_ID) &&
+            (l_ring == N3_MC01_0_RING_ID) &&
+            (l_sat_id == P9_N3_MCS01_SAT_ID || l_sat_id == P9_N3_MCS23_SAT_ID))
+        {
+            //-------------------------------------------
+            // DMI/MCC
+            //-------------------------------------------
+            //SCOM3   (See mc_clscom_rlm.fig <= 0xB vs mc_scomfir_rlm.fig > 0xB)
+            //DMI0           05     02       0   0x2X (X <= 0xB)
+            //DMI1           05     02       0   0x3X (X <= 0xB)
+            //DMI2           05     02       2   0x2X (X <= 0xB)
+            //DMI3           05     02       2   0x3X (X <= 0xB)
+            //DMI4           03     02       0   0x2X (X <= 0xB)
+            //DMI5           03     02       0   0x3X (X <= 0xB)
+            //DMI6           03     02       2   0x2X (X <= 0xB)
+            //DMI7           03     02       2   0x3X (X <= 0xB)
+            if ((i_low0 <= l_sat_offset && l_sat_offset <= 0x2B) ||
+                (i_low1 <= l_sat_offset && l_sat_offset <= 0x3B))
+            {
+                uint8_t l_off_nib0 = (l_sat_offset >> 4);
+                o_chipUnitRelated = true;
+                o_chipUnitPairing.push_back(p9_chipUnitPairing_t(mcc_dmi,
+                                            ((l_chiplet_id == N3_CHIPLET_ID) ? (0) : (4)) +
+                                            (l_off_nib0 - 2) + l_sat_id));
+            }
+            //-------------------------------------------
+            // MI
+            //-------------------------------------------
+            //          Chiplet   Ring   Satid   Off
+            //MCS0           05     02       0   !SCOM3
+            //MCS1           05     02       2   !SCOM3
+            //MCS2           03     02       0   !SCOM3
+            //MCS3           03     02       2   !SCOM3
+            else
+            {
+                o_chipUnitRelated = true;
+                o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_MI_CHIPUNIT,
+                                            (l_sat_id / 2) +
+                                            ((l_chiplet_id == N3_CHIPLET_ID) ? (0) : (2))));
+            }
+        }
+
+        return 0;
+    }
+
+    uint32_t p9_scominfo_isChipUnitScom(const uint64_t i_scomAddr, bool& o_chipUnitRelated,
+                                        std::vector<p9_chipUnitPairing_t>& o_chipUnitPairing, const uint32_t i_mode)
+    {
+        p9_scom_addr l_scom(i_scomAddr);
+        o_chipUnitRelated = false;
+
+        uint32_t rc = 0;
+
+        uint8_t l_chiplet_id = l_scom.get_chiplet_id();
+        uint8_t l_port = l_scom.get_port();
+        uint8_t l_ring = l_scom.get_ring();
+        uint8_t l_sat_id = l_scom.get_sat_id();
+        uint8_t l_sat_offset = l_scom.get_sat_offset();
+
+        if ((i_mode & PPE_MODE) == PPE_MODE)
+        {
+            if (PPE_EP00_CHIPLET_ID <= l_chiplet_id &&
+                l_chiplet_id <= PPE_EP05_CHIPLET_ID)
+            {
+                o_chipUnitRelated = true;
+                o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_EX_CHIPUNIT,
+                                            ((l_chiplet_id - PPE_EP00_CHIPLET_ID) * 2) +
+                                            (l_port - 1)));
+
+            }
+
+        }
+
+        else if (l_scom.is_unicast())
+        {
+            // common 'pervasive' registers associated with each pervasive chiplet type
+            // permit addressing by PERV target type (for all pervasive chiplet instances)
+            // or by C/EX/EQ target types (by their associated pervasive chiplet instances)
+            if (((l_port == GPREG_PORT_ID) ||
+                 ((l_port >= CME_PORT_ID) && (l_port <= CPM_PORT_ID)) ||
+                 (l_port == PCBSLV_PORT_ID) ||
+                 (l_port == UNIT_PORT_ID && l_ring == EC_PSCM_RING_ID) || //Catches all PSCOM regs
+                 (l_port == UNIT_PORT_ID && l_ring == EC_PERV_RING_ID
+                  && l_sat_id == PERV_DBG_SAT_ID))) // Each chiplet also has a DBG macro
+            {
+                o_chipUnitRelated = true;
+                // PU_PERV_CHIPUNIT
+                o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_PERV_CHIPUNIT,
+                                            l_chiplet_id));
+
+                // PU_C_CHIPUNIT / PU_EX_CHIPUNIT
+                if ((l_chiplet_id >= EC00_CHIPLET_ID) && (l_chiplet_id <= EC23_CHIPLET_ID))
+                {
+                    o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_C_CHIPUNIT,
+                                                l_chiplet_id - EC00_CHIPLET_ID));
+                    o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_EX_CHIPUNIT,
+                                                (l_chiplet_id - EC00_CHIPLET_ID) / 2));
+                }
+
+                // PU_EQ_CHIPUNIT
+                if ((l_chiplet_id >= EP00_CHIPLET_ID) && (l_chiplet_id <= EP05_CHIPLET_ID))
+                {
+                    o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_EQ_CHIPUNIT,
+                                                l_chiplet_id - EP00_CHIPLET_ID));
+                }
+            }
+
+            // core registers which can be addressed by either C/EX target types
+            // c: 0..24
+            if (((l_chiplet_id >= EC00_CHIPLET_ID) && (l_chiplet_id <= EC23_CHIPLET_ID)) &&
+                (l_port == UNIT_PORT_ID) &&
+                ((l_ring >= EC_PERV_RING_ID) && (l_ring <= EC_PC_3_RING_ID)))
+            {
+                o_chipUnitRelated = true;
+                // PU_C_CHIPUNIT
+                o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_C_CHIPUNIT,
+                                            l_chiplet_id - EC00_CHIPLET_ID));
+                // PU_EX_CHIPUNIT
+                o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_EX_CHIPUNIT,
+                                            (l_chiplet_id - EC00_CHIPLET_ID) / 2));
+            }
+
+            // quad registers which can be addressed by either EQ/EX target types
+            // ex: 0..12
+            // eq: 0..6
+            if (((l_chiplet_id >= EP00_CHIPLET_ID) && (l_chiplet_id <= EP05_CHIPLET_ID)) &&
+                (l_port == UNIT_PORT_ID) &&
+                (((l_ring >= EQ_PERV_RING_ID)  && (l_ring <= EQ_L3_1_RING_ID)) ||
+                 ((l_ring >= EQ_CME_0_RING_ID) && (l_ring <= EQ_L2_1_TRA_RING_ID))))
+            {
+                o_chipUnitRelated = true;
+                // PU_EQ_CHIPUNIT
+                o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_EQ_CHIPUNIT,
+                                            l_chiplet_id - EP00_CHIPLET_ID));
+
+                // PU_EX_CHIPUNIT
+                if ((l_ring == EQ_L2_0_RING_ID)  || (l_ring == EQ_NC_0_RING_ID) || (l_ring == EQ_L3_0_RING_ID) ||
+                    (l_ring == EQ_CME_0_RING_ID) || (l_ring == EQ_L2_0_TRA_RING_ID))
+                {
+                    o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_EX_CHIPUNIT,
+                                                (l_chiplet_id - EP00_CHIPLET_ID) * 2));
+                }
+                // PU_EX_CHIPUNIT
+                else if ((l_ring == EQ_L2_1_RING_ID)  || (l_ring == EQ_NC_1_RING_ID) || (l_ring == EQ_L3_1_RING_ID) ||
+                         (l_ring == EQ_CME_1_RING_ID) || (l_ring == EQ_L2_1_TRA_RING_ID))
+                {
+                    o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_EX_CHIPUNIT,
+                                                ((l_chiplet_id - EP00_CHIPLET_ID) * 2) + 1));
+                }
+            }
+
+            // PU_CAPP_CHIPUNIT
+            // capp: 0..1
+            if ((((l_chiplet_id == N0_CHIPLET_ID) && (l_ring == N0_CXA0_0_RING_ID)) ||
+                 ((l_chiplet_id == N2_CHIPLET_ID) && (l_ring == N2_CXA1_0_RING_ID))) &&
+                (l_port == UNIT_PORT_ID))
+            {
+                o_chipUnitRelated = true;
+                o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_CAPP_CHIPUNIT,
+                                            (l_chiplet_id / 2) - 1));
+            }
+
+            //==== NIMBUS MCBIST/MCA =======================================================================================================
+            if (i_mode == P9N_DD1_SI_MODE || i_mode == P9N_DD2_SI_MODE)
+            {
+                // PU_MCS_CHIPUNIT (nest)
+                // mcs: 0..3
+                if (((l_chiplet_id == N3_CHIPLET_ID) || (l_chiplet_id == N1_CHIPLET_ID)) &&
+                    (l_port == UNIT_PORT_ID) &&
+                    (l_ring == N3_MC01_0_RING_ID) &&
+                    ((l_sat_id == MC_DIR_SAT_ID_PBI_01) || (l_sat_id == MC_DIR_SAT_ID_PBI_23)) &&
+                    (((0x2F & l_sat_offset) < MC_MCS_MCA_OFFSET_MCP0XLT0 || MC_MCS_MCA_OFFSET_MCPERF3 < (0x2F & l_sat_offset))))
+                {
+                    o_chipUnitRelated = true;
+                    o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_MCS_CHIPUNIT,
+                                                ((l_chiplet_id == N3_CHIPLET_ID) ? (0) : (2)) +
+                                                (l_sat_id / 2)));
+                }
+
+                // PU_MCBIST_CHIPUNIT (mc)
+                // mcbist: 0..1
+                if (((l_chiplet_id == MC01_CHIPLET_ID) || (l_chiplet_id == MC23_CHIPLET_ID)) &&
+                    (((l_port == UNIT_PORT_ID) &&
+                      (((l_ring == MC_MC01_1_RING_ID) &&
+                        ((l_sat_id & 0xC) == MC_DIR_SAT_ID_MCBIST)) || //MCBIST has 2 bit sat_id
+                       ((l_ring == MC_PERV_RING_ID) || //Translate MC perv regs with MCBIST
+                        (l_ring == XB_PSCM_RING_ID) ||
+                        (l_ring == MC_MCTRA_0_RING_ID)) )) || //Translate TRA regs with MCBIST
+                     (l_port != UNIT_PORT_ID)) )   //Translate MC perv regs with MCBIST
+                {
+                    o_chipUnitRelated = true;
+                    o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_MCBIST_CHIPUNIT,
+                                                l_chiplet_id - MC01_CHIPLET_ID));
+                }
+
+                // PU_MCA_CHIPUNIT (mc)
+                // mca: 0..7
+                // These regisers are in the mcs chiplet but are logically mca targetted
+                if (((l_chiplet_id == N3_CHIPLET_ID) || (l_chiplet_id == N1_CHIPLET_ID)) &&
+                    (l_port == UNIT_PORT_ID) &&
+                    (l_ring == N3_MC01_0_RING_ID) &&
+                    ((l_sat_id == MC_DIR_SAT_ID_PBI_01) || (l_sat_id == MC_DIR_SAT_ID_PBI_23)) &&
+                    (((0x2F & l_sat_offset) >= MC_MCS_MCA_OFFSET_MCP0XLT0 && MC_MCS_MCA_OFFSET_MCPERF3 >= (0x2F & l_sat_offset))))
+                {
+                    o_chipUnitRelated = true;
+                    o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_MCA_CHIPUNIT,
+                                                ((((l_chiplet_id == N3_CHIPLET_ID) ? (0) : (2)) +
+                                                  (l_sat_id / 2)) * 2) +
+                                                ((l_sat_offset & 0x10) >> 4) ));
+                }
+
+                // PU_MCA_CHIPUNIT (mc)
+                // mca: 0..7
+                if (((l_chiplet_id == MC01_CHIPLET_ID) || (l_chiplet_id == MC23_CHIPLET_ID)) &&
+                    (l_port == UNIT_PORT_ID) &&
+                    (l_ring == MC_MC01_0_RING_ID) &&
+                    ((l_sat_id >= MC_DIR_SAT_ID_SRQ_0) && (l_sat_id <= MC_DIR_SAT_ID_ECC64_3)))
+                {
+                    o_chipUnitRelated = true;
+                    o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_MCA_CHIPUNIT,
+                                                (4 * (l_chiplet_id - MC01_CHIPLET_ID)) +
+                                                (l_sat_id % 4)));
+                }
+
+                // PU_MCA_CHIPUNIT (iomc)
+                // mca: 0..7
+                if (((l_chiplet_id == MC01_CHIPLET_ID) || (l_chiplet_id == MC23_CHIPLET_ID)) &&
+                    (l_port == UNIT_PORT_ID) &&
+                    ((l_ring >= MC_IOM01_0_RING_ID) && (l_ring <= MC_IOM23_1_RING_ID)) &&
+                    (l_sat_id == MC_IND_SAT_ID))
+                {
+                    o_chipUnitRelated = true;
+                    o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_MCA_CHIPUNIT,
+                                                (4 * (l_chiplet_id - MC01_CHIPLET_ID)) +
+                                                (l_ring - MC_IOM01_0_RING_ID)));
+                }
+
+                //<<< END OF NIMBUS MCBIST/MCA ===========================================================================
+            }
+            else if (i_mode == P9C_DD1_SI_MODE || i_mode == P9C_DD2_SI_MODE)
+            {
+                //==== CUMULUS MC/MI/DMI==================================================================================
+                rc = p9_scominfo_xlate_mi(o_chipUnitRelated, o_chipUnitPairing, l_scom, PU_DMI_CHIPUNIT, 0x20, 0x30, i_mode);
+
+                if (rc)
+                {
+                    return rc;
+                }
+
+                // Figtree references: mc_top_baseaddr.fig, e9_uchip_offset.fig
+                //-------------------------------------------
+                // MC
+                //-------------------------------------------
+                // MC            07     08     0xC(!0xD)
+                // MC            08     08     0xC(!0xD)
+                //Probably any other chipelt 07/08 registers that don't fall into the DMI target range
+                if (((l_chiplet_id == MC01_CHIPLET_ID) || (l_chiplet_id == MC23_CHIPLET_ID)) &&
+                    ( ( (l_port == UNIT_PORT_ID) &&
+                        (
+                            ( (l_ring == P9C_MC_BIST_RING_ID) &&
+                              (l_sat_id != P9C_SAT_ID_CHAN_MCBIST)
+                            ) ||
+                            ( (l_ring == P9C_MC_PERV_RING_ID) || //Translate MC perv regs with MC
+                              (l_ring == P9C_MC_PSCM_RING_ID) ||
+                              (l_ring == P9C_MC_MCTRA_RING_ID) ||
+                              (l_ring == P9C_MC_PPE_RING_ID)
+                            ) ||
+                            ( (l_ring == P9C_MC_IO_RING_ID) &&
+                              (l_sat_id == MC_IND_SAT_ID) &&
+                              (l_sat_offset != P9C_MC_OFFSET_IND)
+                            )
+                        )
+                      ) || //Translate TRA regs with MCBIST
+                      (l_port != UNIT_PORT_ID)
+                    ) )   //Translate MC perv regs with MCBIST
+                {
+
+                    o_chipUnitRelated = true;
+                    o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_MC_CHIPUNIT,
+                                                l_chiplet_id - MC01_CHIPLET_ID));
+
+                }
+
+                if (((l_chiplet_id == MC01_CHIPLET_ID) || (l_chiplet_id == MC23_CHIPLET_ID)) &&
+                    (l_port == UNIT_PORT_ID))
+                {
+                    //-------------------------------------------
+                    // DMI
+                    //-------------------------------------------
+                    //SCOM1,2
+                    //DMI0           07     02       0
+                    //DMI1           07     02       1
+                    //DMI2           07     02       2
+                    //DMI3           07     02       3
+                    //DMI4           08     02       0
+                    //DMI5           08     02       1
+                    //DMI6           08     02       2
+                    //DMI7           08     02       3
+                    if (l_ring == P9C_MC_CHAN_RING_ID)
+                    {
+                        o_chipUnitRelated = true;
+                        o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_DMI_CHIPUNIT,
+                                                    ((l_chiplet_id == MC01_CHIPLET_ID ? (0) : (4))) +
+                                                    (0x3 & l_sat_id)));
+
+                    }
+
+                    //SCOM4
+                    //DMI0           07     08     0xD   0x0X
+                    //DMI1           07     08     0xD   0x1X
+                    //DMI2           07     08     0xD   0x2X
+                    //DMI3           07     08     0xD   0x3X
+                    //DMI4           08     08     0xD   0x0X
+                    //DMI5           08     08     0xD   0x1X
+                    //DMI6           08     08     0xD   0x2X
+                    //DMI7           08     08     0xD   0x3X
+                    if (l_ring == P9C_MC_BIST_RING_ID && l_sat_id == P9C_SAT_ID_CHAN_MCBIST)
+                    {
+                        uint8_t l_off_nib0 = (l_sat_offset >> 4);
+                        o_chipUnitRelated = true;
+                        o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_DMI_CHIPUNIT,
+                                                    ((l_chiplet_id == MC01_CHIPLET_ID ? (0) : (4))) +
+                                                    l_off_nib0));
+
+                    }
+
+                    //-------------------------------------------
+                    // DMI IO
+                    //-------------------------------------------
+                    //          Chiplet   Ring   Satid    Off    RXTXGrp
+                    //DMI0           07     04       0   0x3F       0x00
+                    //DMI1           07     04       0   0x3F       0x01
+                    //DMI2           07     04       0   0x3F       0x02
+                    //DMI3           07     04       0   0x3F       0x03
+                    //DMI4           08     04       0   0x3F       0x00
+                    //DMI5           08     04       0   0x3F       0x01
+                    //DMI6           08     04       0   0x3F       0x02
+                    //DMI7           08     04       0   0x3F       0x03
+
+                    //DMI0           07     04       0   0x3F       0x20
+                    //DMI1           07     04       0   0x3F       0x21
+                    //DMI2           07     04       0   0x3F       0x22
+                    //DMI3           07     04       0   0x3F       0x23
+                    //DMI4           08     04       0   0x3F       0x20
+                    //DMI5           08     04       0   0x3F       0x21
+                    //DMI6           08     04       0   0x3F       0x22
+                    //DMI7           08     04       0   0x3F       0x23
+                    //
+                    //0 MC01.CHAN0  IOM01.TX_WRAP.TX3
+                    //1 MC01.CHAN1  IOM01.TX_WRAP.TX2
+                    //2 MC01.CHAN2  IOM01.TX_WRAP.TX0
+                    //3 MC01.CHAN3  IOM01.TX_WRAP.TX1
+                    //4 MC23.CHAN0  IOM23.TX_WRAP.TX3
+                    //5 MC23.CHAN1  IOM23.TX_WRAP.TX2
+                    //6 MC23.CHAN2  IOM23.TX_WRAP.TX0
+                    //7 MC23.CHAN3  IOM23.TX_WRAP.TX1
+                    // 3, 2, 0, 1
+                    if (l_ring == P9C_MC_IO_RING_ID && l_sat_id == MC_IND_SAT_ID &&
+                        l_sat_offset == P9C_MC_OFFSET_IND )
+                    {
+                        uint32_t l_rxtx_grp = l_scom.get_rxtx_group_id();
+                        uint32_t l_ind_addr = l_scom.get_ind_addr();
+
+                        //From iofrc_bus_reg_intf.vhdl
+                        //gcr_pkt_equal_addr  <=     (gcr_reg_reg_addr(0 to 3) = "1111")
+                        //                            and not (gcr_reg_reg_addr = "111111111");  --Ignore protected FIR address
+                        if (((l_ind_addr & 0x1E0) == 0x1E0) && (l_ind_addr != 0x1FF))
+                        {
+                            o_chipUnitRelated = true;
+                            o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_MC_CHIPUNIT,
+                                                        l_chiplet_id - MC01_CHIPLET_ID));
+
+                        }
+                        else
+                        {
+
+                            if (l_rxtx_grp >= 0x20)
+                            {
+                                l_rxtx_grp -= 0x20;
+                            }
+
+                            uint8_t l_adder = 0;
+
+                            switch (l_rxtx_grp % 4)
+                            {
+                                case 3:
+                                    l_adder = 0;
+                                    break;
+
+                                case 2:
+                                    l_adder = 1;
+                                    break;
+
+                                case 0:
+                                    l_adder = 2;
+                                    break;
+
+                                case 1:
+                                    l_adder = 3;
+                                    break;
+
+                                default:
+                                    //escape to bunker - math broke
+                                    break;
+                            }
+
+                            o_chipUnitRelated = true;
+                            o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_DMI_CHIPUNIT,
+                                                        ((l_chiplet_id == MC01_CHIPLET_ID ? (0) : (4))) +
+                                                        l_adder));
+                        }
+                    }
+
+                    //DMI PPE Registers
+                    if ( l_ring == P9C_MC_PPE_RING_ID )
+                    {
+                        o_chipUnitRelated = true;
+                        o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_PPE_CHIPUNIT,
+                                                    (l_chiplet_id - MC01_CHIPLET_ID) + PPE_IO_DMI0_CHIPUNIT_NUM));
+                    }
+                }
+
+                //<<< END OF CUMULUS MC/MI/DMI===========================================================================
+            }
+            else
+            {
+                //==== AXONE MC/MI/OMIC/OMI  ============================================================================
+                rc = p9_scominfo_xlate_mi(o_chipUnitRelated, o_chipUnitPairing, l_scom, PU_MCC_CHIPUNIT, 0x23, 0x33, i_mode);
+
+                if (rc)
+                {
+                    return rc;
+                }
+
+                // Unused rings: 3,7,13-15   Used, 1*,2*,4*,5*,6*,8*,9*,10*,11*,12*
+                //==== MC target ===============================================
+                //Ring 1, 8 (All registers can include MC type as needed
+                if (((l_chiplet_id == MC01_CHIPLET_ID) || (l_chiplet_id == MC23_CHIPLET_ID)))
+                {
+                    o_chipUnitRelated = true;
+                    o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_MC_CHIPUNIT,
+                                                l_chiplet_id - MC01_CHIPLET_ID));
+
+                    //==== MCC/DMI target ==========================================
+                    //  tc_unit_scom_cch_out(2) => tc_mc01_0_scom_cch_int Ring: 2
+                    //CHANX.USTL.  Sat_id: 10 + port_id (8,9,10,11)
+                    //CHANX.DSTL.  Sat_id: 01 + port_id (4,5,6,7)
+                    if (l_ring == P9A_MC_CHAN_RING_ID && l_port == UNIT_PORT_ID)
+                    {
+                        if ((P9A_MC_DSTL_CHAN0_SAT_ID <= l_sat_id && l_sat_id <= P9A_MC_DSTL_CHAN3_SAT_ID) ||
+                            (P9A_MC_USTL_CHAN0_SAT_ID <= l_sat_id && l_sat_id <= P9A_MC_USTL_CHAN3_SAT_ID))
+                        {
+                            o_chipUnitRelated = true;
+                            o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_MCC_CHIPUNIT,
+                                                        ((l_chiplet_id - MC01_CHIPLET_ID) * 4) + (l_sat_id % 4)));
+                        }
+                    }
+
+                    //==== OMIC target =============================================
+                    //tc_unit_scom_cch_out(9)  => tc_omippe00_0_scom_cch_int
+                    //tc_unit_scom_cch_out(10) => tc_omippe01_0_scom_cch_int
+                    //tc_unit_scom_cch_out(11) => tc_omippe02_0_scom_cch_int
+                    //Ring (9,10,11) (OMI0,1,2) PPE
+                    //Ring (4,5,6)   (OMI0,1,2) BUSCTL Include indirect registers so
+                    //               they can be accessed via OMIC and OMI
+                    if (P9A_MC_OMIC0_RING_ID <= l_ring && l_ring <= P9A_MC_OMIC2_RING_ID  && l_port == UNIT_PORT_ID)
+                    {
+                        o_chipUnitRelated = true;
+                        o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_OMIC_CHIPUNIT,
+                                                    ((l_chiplet_id - MC01_CHIPLET_ID) * 3) +
+                                                    (l_ring - P9A_MC_OMIC0_RING_ID)));
+
+                        // IO Ind regsiters  (Ring 4,5,6) reg == 63
+                        // 0701103F MCP_OMI0. Lanes 0-7    omi0
+                        // 0701103F MCP_OMI0. Lanes 8-15   omi1
+                        // 0701103F MCP_OMI0. Lanes 16-23  omi2
+                        // 0701143F MCP_OMI1. Lanes 0-7    omi3
+                        // 0701143F MCP_OMI1. Lanes 8-15   omi4
+                        // 0701143F MCP_OMI1. Lanes 16-23  omi5
+                        // 0701183F MCP_OMI2. Lanes 0-7    omi6
+                        // 0701183F MCP_OMI2. Lanes 8-15   omi7
+                        if (l_sat_id == P9A_MC_IND_SAT_ID && l_sat_offset == P9A_MC_IND_REG)
+                        {
+                            uint32_t l_ind_reg = l_scom.get_ind_addr();
+
+                            //Bit 0 of the ind register address == 0 indicates if it is per-lane
+                            if ((l_ind_reg & 0x100) == 0x000)
+                            {
+                                uint32_t l_ind_lane = l_scom.get_lane_id();
+                                o_chipUnitRelated = true;
+                                o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_OMI_CHIPUNIT,
+                                                            P9_SCOMINFO_OMI_SWIZZLE[((l_chiplet_id - MC01_CHIPLET_ID) * 8) +
+                                                                    ((l_ring - P9A_MC_OMIC0_RING_ID) * 3) +
+                                                                    ((l_ind_lane / 8))]));
+                            }
+                        }
+                    }
+
+                    if (P9A_MC_OMIC0_PPE_RING_ID <= l_ring && l_ring < P9A_MC_OMIC2_PPE_RING_ID  && l_port == UNIT_PORT_ID)
+                    {
+                        o_chipUnitRelated = true;
+                        o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_OMIC_CHIPUNIT,
+                                                    ((l_chiplet_id - MC01_CHIPLET_ID) * 3) +
+                                                    (l_ring - P9A_MC_OMIC0_PPE_RING_ID)));
+                    }
+
+                    //==== OMI target ==============================================
+                    // DL Registers
+                    // reg0 dl0 -> omi0  ring: 12  sat_id: 13  regs 16..31
+                    // reg0 dl1 -> omi1  ring: 12  sat_id: 13  regs 32..47
+                    // reg0 dl2 -> omi2  ring: 12  sat_id: 13  regs 48..63
+                    // reg1 dl0 -> omi3  ring: 12  sat_id: 14  regs 16..31
+                    // reg1 dl1 -> omi4  ring: 12  sat_id: 14  regs 32..47
+                    // reg1 dl2 -> omi5  ring: 12  sat_id: 14  regs 48..63
+                    // reg2 dl0 -> omi6  ring: 12  sat_id: 15  regs 16..31
+                    // reg2 dl1 -> omi7  ring: 12  sat_id: 15  regs 32..47
+                    if (l_ring == P9A_MC_OMI_DL_RING_ID && l_port == UNIT_PORT_ID)
+                    {
+                        if (P9A_MC_DL_REG0_SAT_ID <= l_sat_id && l_sat_id <= P9A_MC_DL_REG2_SAT_ID)
+                        {
+                            if (P9A_MC_DL_OMI0_FRST_REG <= l_sat_offset)
+                            {
+                                o_chipUnitRelated = true;
+                                o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_OMI_CHIPUNIT,
+                                                            P9_SCOMINFO_OMI_SWIZZLE[((l_chiplet_id - MC01_CHIPLET_ID) * 8) +
+                                                                    ((l_sat_id - P9A_MC_DL_REG0_SAT_ID) * 3) +
+                                                                    ((l_sat_offset / 16) - 1)]));
+                            }
+                        }
+                    }
+                }
+            }
+
+            // PU_NV_CHIPUNIT
+            if (i_mode == P9N_DD1_SI_MODE)
+            {
+                // See npu_misc_regs.vhdl, line 2710,
+                // sc_addr(0 to 6) represents sat_id(0..3) and sat_offset(0..2)
+                // only stkX, ntlX registers are translated to NX target type
+                // nv: 0..5
+                if ((l_chiplet_id == N3_CHIPLET_ID) &&
+                    (l_port == UNIT_PORT_ID) &&
+                    (((l_ring == N3_NPU_0_RING_ID) && ((l_sat_id % 4) == 3) && l_sat_id <= 11)))
+                {
+                    o_chipUnitRelated = true;
+                    o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_NV_CHIPUNIT,
+                                                (2 * (l_sat_id / 4)) +
+                                                (l_sat_offset / 32)));
+                }
+            }
+            else if (i_mode != P9A_DD1_SI_MODE && i_mode != P9A_DD2_SI_MODE)
+            {
+                //DD2 NV link (and Cumulus until we know better)
+                // See npu_misc_regs.vhdl
+                // sc_addr(0 to 7)  bits 1 to 4 are the sat_id bit 0 is the lsb of the ring
+                //  rings 4 and 5 are used.
+                //                       rrrrrrSTIDxxx---
+                //                       000100
+                //       x"4900" & "00" when "00100010", -- stk0, ntl0, 00-07, hyp-only
+                //       x"4900" & "01" when "00100011", -- stk0, ntl0, 08-15, hyp-only
+                //       x"4900" & "10" when "00100100", -- stk0, ntl0, 16-23, hyp-only
+                //       x"0900" & "11" when "00100101", -- stk0, ntl0, 24-31, user-acc
+                //       x"4b00" & "00" when "00100110", -- stk0, ntl1, 00-07, hyp-only
+                //       x"4b00" & "01" when "00100111", -- stk0, ntl1, 08-15, hyp-only
+                //       x"4b00" & "10" when "00101000", -- stk0, ntl1, 16-23, hyp-only --          addresses 0x140-147
+                //       x"0b00" & "11" when "00101001", -- stk0, ntl1, 24-31, user-acc
+                //                             STID
+                //       x"5900" & "00" when "01100010", -- stk1, ntl0, 00-07, hyp-only
+                //       x"5900" & "01" when "01100011", -- stk1, ntl0, 08-15, hyp-only
+                //       x"5900" & "10" when "01100100", -- stk1, ntl0, 16-23, hyp-only
+                //       x"1900" & "11" when "01100101", -- stk1, ntl0, 24-31, user-acc
+                //       x"5b00" & "00" when "01100110", -- stk1, ntl1, 00-07, hyp-only
+                //       x"5b00" & "01" when "01100111", -- stk1, ntl1, 08-15, hyp-only
+                //       x"5b00" & "10" when "01101000", -- stk1, ntl1, 16-23, hyp-only --          addresses 0x340-347
+                //       x"1b00" & "11" when "01101001", -- stk1, ntl1, 24-31, user-acc
+                //                             STID
+                //       x"6900" & "00" when "10100010", -- stk2, ntl0, 00-07, hyp-only
+                //       x"6900" & "01" when "10100011", -- stk2, ntl0, 08-15, hyp-only
+                //       x"6900" & "10" when "10100100", -- stk2, ntl0, 16-23, hyp-only
+                //       x"2900" & "11" when "10100101", -- stk2, ntl0, 24-31, user-acc
+                //       x"6b00" & "00" when "10100110", -- stk2, ntl1, 00-07, hyp-only
+                //       x"6b00" & "01" when "10100111", -- stk2, ntl1, 08-15, hyp-only
+                //       x"6b00" & "10" when "10101000", -- stk2, ntl1, 16-23, hyp-only --          addresses 0x540-54f
+                //       x"2b00" & "11" when "10101001", -- stk2, ntl1, 24-31, user-acc
+                if ((l_chiplet_id == N3_CHIPLET_ID) &&
+                    (l_port == UNIT_PORT_ID))
+                {
+
+                    //We have to do ugly bit manipulation here anyway.  It is clearer
+                    //just to do it with the raw scom address.
+                    //Combine the ring(6) sat_id(4) and high order 3 bits of sat_offset
+                    //to compare with vhdl values for NV registers
+                    uint64_t npuaddr = (i_scomAddr & 0xFFF8ULL) >> 3;
+
+                    if (0x0222ULL <= npuaddr && npuaddr <= 0x0225ULL)
+                    {
+                        o_chipUnitRelated = true;
+                        o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_NV_CHIPUNIT, 0));
+                    }
+
+                    if (0x0226ULL <= npuaddr && npuaddr <= 0x0229ULL)
+                    {
+                        o_chipUnitRelated = true;
+                        o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_NV_CHIPUNIT, 1));
+                    }
+
+                    if (0x0262ULL <= npuaddr && npuaddr <= 0x0265ULL)
+                    {
+                        o_chipUnitRelated = true;
+                        o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_NV_CHIPUNIT, 2));
+                    }
+
+                    if (0x0266ULL <= npuaddr && npuaddr <= 0x0269ULL)
+                    {
+                        o_chipUnitRelated = true;
+                        o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_NV_CHIPUNIT, 3));
+                    }
+
+                    if (0x02A2ULL <= npuaddr && npuaddr <= 0x02A5ULL)
+                    {
+                        o_chipUnitRelated = true;
+                        o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_NV_CHIPUNIT, 4));
+                    }
+
+                    if (0x02A6ULL <= npuaddr && npuaddr <= 0x02A9ULL)
+                    {
+                        o_chipUnitRelated = true;
+                        o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_NV_CHIPUNIT, 5));
+                    }
+                }
+
+            }
+
+            // PU_PEC_CHIPUNIT (nest)
+            // pec: 0..2
+            if ((l_chiplet_id == N2_CHIPLET_ID) &&
+                (l_port == UNIT_PORT_ID) &&
+                ((l_ring >= N2_PCIS0_0_RING_ID) && (l_ring <= N2_PCIS2_0_RING_ID)) &&
+                (l_sat_id == PEC_SAT_ID))
+            {
+                o_chipUnitRelated = true;
+                o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_PEC_CHIPUNIT,
+                                            (l_ring - N2_PCIS0_0_RING_ID)));
+            }
+
+            // PU_PEC_CHIPUNIT (iopci/pci)
+            // source: iop_scom_cntl_rlm_mac.vhdl
+            // pec: 0..2
+            if (((l_chiplet_id >= PCI0_CHIPLET_ID) && (l_chiplet_id <= PCI2_CHIPLET_ID)) &&
+                ((l_port != UNIT_PORT_ID) ||
+                 ((l_port == UNIT_PORT_ID) &&
+                  ((l_ring == PCI_IOPCI_0_RING_ID) || (l_ring == PCI_PE_0_RING_ID) ||
+                   (l_ring == PCI_PERV_RING_ID)) &&
+                  (l_sat_id == PEC_SAT_ID))))
+            {
+                if ((l_chiplet_id >= PCI0_CHIPLET_ID) && (l_chiplet_id <= PCI2_CHIPLET_ID))
+                {
+                    o_chipUnitRelated = true;
+                    o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_PEC_CHIPUNIT,
+                                                (l_chiplet_id - PCI0_CHIPLET_ID)));
+                }
+            }
+
+            // PU_PHB_CHIPUNIT (nest)
+            // phb: 0..5
+            if ((l_chiplet_id == N2_CHIPLET_ID) &&
+                (l_port == UNIT_PORT_ID) &&
+                ((l_ring >= N2_PCIS0_0_RING_ID) && (l_ring <= N2_PCIS2_0_RING_ID)) &&
+                (((l_ring - l_sat_id) >= 2) && ((l_ring - l_sat_id) < l_ring)))
+            {
+                o_chipUnitRelated = true;
+                o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_PHB_CHIPUNIT,
+                                            ((l_ring - N2_PCIS0_0_RING_ID) ?
+                                             (((l_ring - N2_PCIS0_0_RING_ID) * 2) - 1) :
+                                             (0)) +
+                                            (l_sat_id - 1)));
+            }
+
+            // PU_PHB_CHIPUNIT (pci)
+            // phb: 0..5
+            if (((l_chiplet_id >= PCI0_CHIPLET_ID) && (l_chiplet_id <= PCI2_CHIPLET_ID)) &&
+                (l_port == UNIT_PORT_ID) &&
+                (l_ring == PCI_PE_0_RING_ID) &&
+                (((l_sat_id >= 1) && (l_sat_id <= (l_chiplet_id - PCI0_CHIPLET_ID + 1))) || // aib_stack
+                 ((l_sat_id >= 4) && (l_sat_id <= (l_chiplet_id - PCI0_CHIPLET_ID + 4)))))  // pbcq_etu
+            {
+                o_chipUnitRelated = true;
+                o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_PHB_CHIPUNIT,
+                                            ((l_chiplet_id - PCI0_CHIPLET_ID) ?
+                                             (((l_chiplet_id - PCI0_CHIPLET_ID) * 2) - 1) :
+                                             (0)) +
+                                            l_sat_id -
+                                            ((l_sat_id >= 4) ? (4) : (1))));
+            }
+
+            // PU_OBUS_CHIPUNIT
+            // obus: 0..3
+            if (((l_chiplet_id >= OB0_CHIPLET_ID) && (l_chiplet_id <= OB3_CHIPLET_ID)))
+            {
+                o_chipUnitRelated = true;
+                o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_OBUS_CHIPUNIT,
+                                            (l_chiplet_id - OB0_CHIPLET_ID)));
+            }
+
+            // PU_XBUS_CHIPUNIT
+            // xbus: 0..2
+            if ((l_chiplet_id == XB_CHIPLET_ID) &&
+                (l_port == UNIT_PORT_ID) &&
+                (((l_ring >= XB_IOX_0_RING_ID) && (l_ring <= XB_IOX_2_RING_ID) && (l_sat_id == XB_IOF_SAT_ID)) ||
+                 ((l_ring >= XB_PBIOX_0_RING_ID) && (l_ring <= XB_PBIOX_2_RING_ID) && (l_sat_id == XB_PB_SAT_ID))))
+            {
+                o_chipUnitRelated = true;
+                o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_XBUS_CHIPUNIT,
+                                            l_ring % 3));
+            }
+
+            // -----------------------------------------------------------------------------
+            // Common 'ppe' registers associated with each pervasive chiplet type
+            // Permit addressing by PPE target type (for all ppe chiplet instances)
+            // -----------------------------------------------------------------------------
+
+            // SBE PM registers
+            //    Port ID = 14
+            if ( (l_port == SBE_PORT_ID) &&
+                 (l_chiplet_id == PIB_CHIPLET_ID) &&
+                 (l_ring == PPE_SBE_RING_ID) &&
+                 (l_sat_id == PPE_SBE_SAT_ID) )
+            {
+                o_chipUnitRelated = true;
+                // PU_SBE_CHIPUNIT
+                o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_SBE_CHIPUNIT,
+                                            l_chiplet_id));
+                // PU_PPE_CHIPUNIT
+                o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_PPE_CHIPUNIT,
+                                            l_chiplet_id));
+            }
+
+            // GPE registers
+            //    Port ID = 1
+            if ( (l_port == GPE_PORT_ID) &&
+                 (l_chiplet_id == PIB_CHIPLET_ID) &&
+                 ( (l_ring == PPE_GPE0_RING_ID) ||
+                   (l_ring == PPE_GPE1_RING_ID) ||
+                   (l_ring == PPE_GPE2_RING_ID) ||
+                   (l_ring == PPE_GPE3_RING_ID) ) &&
+                 (l_sat_id == PPE_GPE_SAT_ID) )
+            {
+                o_chipUnitRelated = true;
+                // PU_PPE_CHIPUNIT
+                o_chipUnitPairing.push_back(p9_chipUnitPairing_t(
+                                                PU_PPE_CHIPUNIT,
+                                                PPE_GPE0_CHIPUNIT_NUM + (l_ring / 8)));
+            }
+
+            // CME registers which can be addressed by PPE target type
+            //    Port ID = 1
+            //    0x10 <= Chiplet ID <= 0x15
+            //    Ring_ID = 0x8 or Ring_ID = 0x9
+            //    SAT_ID = 0
+            if ( (l_port == UNIT_PORT_ID) &&
+                 ((l_chiplet_id >= EP00_CHIPLET_ID) && (l_chiplet_id <= EP05_CHIPLET_ID)) &&
+                 ( (l_ring == EQ_CME_0_RING_ID) || (l_ring == EQ_CME_1_RING_ID) ) &&
+                 (l_sat_id == PPE_CME_SAT_ID) )
+            {
+                o_chipUnitRelated = true;
+                o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_PPE_CHIPUNIT,
+                                            (l_chiplet_id - EP00_CHIPLET_ID) +
+                                            PPE_EQ0_CME0_CHIPUNIT_NUM +
+                                            ((l_ring % 8) * 10)));
+            }
+
+            // PB registers which can be addressed by PPE target type
+            //    Port ID = 1
+            //    Chiplet ID = 0x05
+            //    Ring_ID = 0x9
+            //    SAT_ID = 0
+            if ( (l_port == UNIT_PORT_ID) &&
+                 (l_chiplet_id == N3_CHIPLET_ID) &&
+                 (l_ring == N3_PB_3_RING_ID) &&
+                 (l_sat_id == PPE_PB_SAT_ID) )
+            {
+                o_chipUnitRelated = true;
+                // TODO: Need to update for PB1/PB2 of Cummulus whenever address
+                //       values are available.
+                o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_PPE_CHIPUNIT,
+                                            PPE_PB0_CHIPUNIT_NUM));
+            }
+
+            // XBUS registers which can be addressed by PPE target type (IOPPE)
+            //    Port ID = 1
+            //    Chiplet ID = 0x06
+            //    Ring_ID = 0x2
+            //    SAT_ID = 1
+            if ( (l_port == UNIT_PORT_ID) &&
+                 (l_chiplet_id == XB_CHIPLET_ID) &&
+                 (l_ring == XB_IOPPE_0_RING_ID) &&
+                 (l_sat_id == XB_PPE_SAT_ID) )
+            {
+                o_chipUnitRelated = true;
+                o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_PPE_CHIPUNIT,
+                                            PPE_IO_XBUS_CHIPUNIT_NUM));
+            }
+
+            // OBUS registers which can be addressed by PPE target type (IOPPE)
+            //    Port ID = 1
+            //    Chiplet ID = 0x09, 0x0A, 0x0B, or 0x0C
+            //    Ring_ID = 0x4
+            //    SAT_ID = 1
+            if ( (l_port == UNIT_PORT_ID) &&
+                 ((l_chiplet_id >= OB0_CHIPLET_ID) && (l_chiplet_id <= OB3_CHIPLET_ID)) &&
+                 (l_ring == OB_PPE_RING_ID) &&
+                 (l_sat_id == OB_PPE_SAT_ID) )
+            {
+                o_chipUnitRelated = true;
+                o_chipUnitPairing.push_back(p9_chipUnitPairing_t(PU_PPE_CHIPUNIT,
+                                            (l_chiplet_id - OB0_CHIPLET_ID) + PPE_IO_OB0_CHIPUNIT_NUM));
+            }
+        }
+
+        return (!l_scom.is_valid());
+    }
+
+    uint32_t p9_scominfo_fixChipUnitScomAddrOrTarget(const p9ChipUnits_t i_p9CU, const uint32_t i_targetChipUnitNum,
+            const uint64_t i_scomaddr, uint64_t& o_modifiedScomAddr, p9ChipUnits_t& o_p9CU,
+            uint32_t& o_modifiedChipUnitNum, const uint32_t i_mode)
+    {
+        uint32_t rc = 0;
+
+        o_modifiedScomAddr = i_scomaddr;
+        o_p9CU = i_p9CU;
+        o_modifiedChipUnitNum = i_targetChipUnitNum;
+
+        return rc;
+    }
+
+
+} // extern "C"
+
+#undef P9_SCOMINFO_C
diff --git a/src/tests/p9_scominfo.H b/src/tests/p9_scominfo.H
new file mode 100644
index 0000000..d153213
--- /dev/null
+++ b/src/tests/p9_scominfo.H
@@ -0,0 +1,94 @@
+/* IBM_PROLOG_BEGIN_TAG                                                   */
+/* This is an automatically generated prolog.                             */
+/*                                                                        */
+/* $Source: chips/p9/common/scominfo/p9_scominfo.H $                      */
+/*                                                                        */
+/* IBM CONFIDENTIAL                                                       */
+/*                                                                        */
+/* EKB Project                                                            */
+/*                                                                        */
+/* COPYRIGHT 2015,2017                                                    */
+/* [+] International Business Machines Corp.                              */
+/*                                                                        */
+/*                                                                        */
+/* The source code for this program is not published or otherwise         */
+/* divested of its trade secrets, irrespective of what has been           */
+/* deposited with the U.S. Copyright Office.                              */
+/*                                                                        */
+/* IBM_PROLOG_END_TAG                                                     */
+///
+/// @file p9_scominfo.H
+/// @brief P9 chip unit SCOM address platform translation code
+///
+/// HWP HWP Owner: jmcgill at us.ibm.com
+/// HWP FW Owner: dcrowell at us.ibm.com
+/// HWP Team: Infrastructure
+/// HWP Level: 1
+/// HWP Consumed by: FSP/HB
+///
+
+#ifndef P9_SCOMINFO_H
+#define P9_SCOMINFO_H
+
+// includes
+#include <stdint.h>
+#include <vector>
+#include "p9_cu.H"
+
+extern "C"
+{
+
+    //Modes for scominfo functions
+    static const uint32_t P9N_DD1_SI_MODE = 0x0;
+    static const uint32_t PPE_MODE = 0x1;
+    static const uint32_t P9N_DD2_SI_MODE = 0x2;
+    static const uint32_t P9C_DD1_SI_MODE = 0x4;
+    static const uint32_t P9C_DD2_SI_MODE = 0x8;
+    static const uint32_t P9A_DD1_SI_MODE = 0x10;
+    static const uint32_t P9A_DD2_SI_MODE = 0x20;
+
+    typedef enum
+    {
+        STANDARD_MODE = 0
+    } p9TranslationMode_t;
+
+    typedef enum
+    {
+        FAILED_TRANSLATION = 0xFFFFFFFFFFFFFFF1ull
+    } p9TranslationResult_t;
+
+    /// @brief Creates the actual SCOM address based on the chip unit type, instance, and the input SCOM address (relative to chip unit instance 0)
+    /// @param[in] i_p9CU Enumeration of the chip unit type
+    /// @param[in] i_chipUnitNum Instance number of the chip unit
+    /// @param[in] i_scomAddr The input SCOM address associated with the chip unit type
+    /// @param[in] i_mode Used for special purposes, default to 0 = p9n dd1, 1 = ppe_mode, 2 = p9n dd2.X, 4 = p9c dd1.X, 8 = p9c dd2
+    /// @retval uint64_t Actual SCOM address for the chip unit instance passed in
+    uint64_t p9_scominfo_createChipUnitScomAddr(const p9ChipUnits_t i_p9CU, const uint8_t i_chipUnitNum,
+            const uint64_t i_scomAddr, const uint32_t i_mode = 0);
+
+    /// @brief Determine if the provided SCOM address correlates to any chip units (if so creates a list of chipUnitPairing structures which correspond)
+    /// @param[in] i_scomAddr SCOM address to be tested
+    /// @param[out] o_chipUnitRelated Returns true if SCOM address is associated with any chip units
+    /// @param[out] o_chipUnitPairing Collection of chipUnitPairing enums
+    /// @param[in] i_mode Used for special purposes, default to 0
+    /// @retval uint32_t Return non-zero for error
+    uint32_t p9_scominfo_isChipUnitScom(const uint64_t i_scomAddr, bool& o_chipUnitRelated,
+                                        std::vector<p9_chipUnitPairing_t>& o_chipUnitPairing, const uint32_t i_mode = 0);
+
+
+    /// @brief Alter the unit/unitnum of a target for spys where the clocks-on vs clocks-off targets are different.
+    /// @param[in] i_p9CU target used for the spy request
+    /// @param[in] i_targetChipUnitNum the instance number of the target used for the spy request
+    /// @param[in] i_scomaddr the scom from the clocks-on portion of the spy
+    /// @param[out] o_modifiedScomAddr the translated scom address (none may be needed)
+    /// @param[out] o_p9CU the translated target type
+    /// @param[out] o_modifiedChipUnitNum the translated target instance number
+    /// @param[in] i_mode Could be used in the future to indicate if the translation is from clocks-on or clocks-off state
+    /// @retval uint32_t Return non-zero for error
+    uint32_t p9_scominfo_fixChipUnitScomAddrOrTarget(const p9ChipUnits_t i_p9CU, const uint32_t i_targetChipUnitNum,
+            const uint64_t i_scomaddr, uint64_t& o_modifiedScomAddr, p9ChipUnits_t& o_p9CU,
+            uint32_t& o_modifiedChipUnitNum, const uint32_t i_mode = 0);
+
+} // extern "C"
+
+#endif /* P9_SCOMINFO_H */
-- 
2.21.0



More information about the Pdbg mailing list