From patchwork Thu Oct 1 07:08:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amitay Isaacs X-Patchwork-Id: 1374872 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4C246d44pLz9sVN for ; Thu, 1 Oct 2020 17:11:21 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=ozlabs.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; secure) header.d=ozlabs.org header.i=@ozlabs.org header.a=rsa-sha256 header.s=201707 header.b=evVzKa5J; dkim-atps=neutral Received: from bilbo.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 4C246d2h7MzDqTF for ; Thu, 1 Oct 2020 17:11:21 +1000 (AEST) X-Original-To: pdbg@lists.ozlabs.org Delivered-To: pdbg@lists.ozlabs.org Received: from ozlabs.org (bilbo.ozlabs.org [IPv6:2401:3900:2:1::2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4C246W3pcLzDqQt for ; Thu, 1 Oct 2020 17:11:15 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=ozlabs.org Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; secure) header.d=ozlabs.org header.i=@ozlabs.org header.a=rsa-sha256 header.s=201707 header.b=evVzKa5J; dkim-atps=neutral Received: from authenticated.ozlabs.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mail.ozlabs.org (Postfix) with ESMTPSA id 4C245N2wSNz9sVL; Thu, 1 Oct 2020 17:10:16 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ozlabs.org; s=201707; t=1601536275; bh=ScJrdRsIxnBIs6EUArOqWXnkuaflUKjHJ/AGxqh9KZo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=evVzKa5J9wuSG7OOUlTFiju8z0oBcxMbkM6WGpnCmXNmI7R3Pnfcs5UZgYNvlWRi3 jQ4Y/3ADkqpyUZ4NE6tADNzDigVo8Rrhl52TJ0313CNoq8g0dQha57wzT2DkEV25wY B8hbHBCgDj10CMpqLlTayywa+YACGfRpj72RcS0p2fqjNMFnYvECOXWUJhnlEngdfd zX4hXSFpMg540R1MFck8tGqSifLWSwEO5Edp/Q9NLHN5tWOUNvwSEkd6OLINzqruPk CHuPXPpiymIimZWo4oNCgkvFkzh4GeT8rE1zz8weJ+WoxceC86OKHUGLMIJtzMcfz0 6nUjP6RDGtYGQ== From: Amitay Isaacs To: pdbg@lists.ozlabs.org Date: Thu, 1 Oct 2020 17:08:00 +1000 Message-Id: <20201001070814.102735-7-amitay@ozlabs.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201001070814.102735-1-amitay@ozlabs.org> References: <20201001070814.102735-1-amitay@ozlabs.org> MIME-Version: 1.0 Subject: [Pdbg] [PATCH v2 06/20] tests: Import P10 SCOM HWP for address translation tests X-BeenThere: pdbg@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "mailing list for https://github.com/open-power/pdbg development" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Amitay Isaacs Errors-To: pdbg-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Pdbg" Signed-off-by: Amitay Isaacs Reviewed-by: Joel Stanley --- src/tests/p10_cu.H | 102 +++++ src/tests/p10_scom_addr.C | 916 ++++++++++++++++++++++++++++++++++++++ src/tests/p10_scom_addr.H | 700 +++++++++++++++++++++++++++++ src/tests/p10_scominfo.C | 838 ++++++++++++++++++++++++++++++++++ src/tests/p10_scominfo.H | 89 ++++ 5 files changed, 2645 insertions(+) create mode 100644 src/tests/p10_cu.H create mode 100644 src/tests/p10_scom_addr.C create mode 100644 src/tests/p10_scom_addr.H create mode 100644 src/tests/p10_scominfo.C create mode 100644 src/tests/p10_scominfo.H diff --git a/src/tests/p10_cu.H b/src/tests/p10_cu.H new file mode 100644 index 0000000..3577f41 --- /dev/null +++ b/src/tests/p10_cu.H @@ -0,0 +1,102 @@ +/// +/// @file p10_cu.H +/// @brief P10 chip unit definitions +/// +/// HWP Owner: thi@us.ibm.com +/// HWP Team: NEST +/// HWP Level: 1 +/// HWP Consumed by: FSP/HB +/// + +#ifndef P10_CU_H +#define P10_CU_H + +// includes +#include + +extern "C" +{ + + /// P10 chip unit type enumeration + typedef enum + { + P10_NO_CU = 0, ///< P10 chip + PU_PERV_CHIPUNIT = 1, ///< Pervasive + PU_EQ_CHIPUNIT = 2, ///< Quad + PU_C_CHIPUNIT = 3, ///< Core + PU_PEC_CHIPUNIT = 4, ///< PCIe (PEC) + PU_PHB_CHIPUNIT = 5, ///< PCIe (PHB) + PU_NMMU_CHIPUNIT = 6, ///< NMMU + PU_IOHS_CHIPUNIT = 7, ///< IOHS (High speed IO) + PU_MC_CHIPUNIT = 8, ///< MC + PU_MI_CHIPUNIT = 9, ///< MI + PU_MCC_CHIPUNIT = 10, ///< MCC + PU_OMI_CHIPUNIT = 11, ///< OMI + PU_OMIC_CHIPUNIT = 12, ///< OMIC + PU_PAU_CHIPUNIT = 13, ///< PAU + PU_PAUC_CHIPUNIT = 14, ///< PAUC + NONE = 0xFF, ///< None/Invalid + } p10ChipUnits_t; + + /// P10 chip unit pairing struct + struct p10_chipUnitPairing_t + { + /// @brief Default constructor + p10_chipUnitPairing_t() + : chipUnitType(NONE), chipUnitNum(0) {} + /// @brief Construct from type/instance number + p10_chipUnitPairing_t (p10ChipUnits_t type, uint32_t num) + : chipUnitType(type), chipUnitNum(num) {} + + p10ChipUnits_t chipUnitType; ///< chip unit type + uint32_t chipUnitNum; ///< chip unit instance number + }; + + struct p10_chipUnitDescription_t + { + const char* strVal; // Chip unit string + const p10ChipUnits_t enumVal; // Chip unit enum value + const uint8_t maxChipUnitNum; // Max Chip unit num value + }; + + + // Max chip unit positions + const uint8_t MAX_PU_CHIPUNIT_NUM = 0; // P10_NO_CU + const uint8_t MAX_PU_EQ_CHIPUNIT_NUM = 7; + const uint8_t MAX_PU_C_CHIPUNIT_NUM = 31; + const uint8_t MAX_PU_PEC_CHIPUNIT_NUM = 1; + const uint8_t MAX_PU_PHB_CHIPUNIT_NUM = 5; + const uint8_t MAX_PU_NMMU_CHIPUNIT_NUM = 1; + const uint8_t MAX_PU_PERV_CHIPUNIT_NUM = 39; // Special case, with gaps + const uint8_t MAX_PU_IOHS_CHIPUNIT_NUM = 7; + const uint8_t MAX_PU_PAU_CHIPUNIT_NUM = 7; + const uint8_t MAX_PU_MC_CHIPUNIT_NUM = 3; + const uint8_t MAX_PU_MI_CHIPUNIT_NUM = 3; + const uint8_t MAX_PU_MCC_CHIPUNIT_NUM = 7; + const uint8_t MAX_PU_OMIC_CHIPUNIT_NUM = 7; + const uint8_t MAX_PU_OMI_CHIPUNIT_NUM = 15; + const uint8_t MAX_PU_PAUC_CHIPUNIT_NUM = 3; + + // Chip unit string/enum/max targes table + const p10_chipUnitDescription_t ChipUnitDescriptionTable[] = + { + { "pu" , P10_NO_CU, MAX_PU_CHIPUNIT_NUM }, + { "eq" , PU_EQ_CHIPUNIT, MAX_PU_EQ_CHIPUNIT_NUM }, + { "c" , PU_C_CHIPUNIT, MAX_PU_C_CHIPUNIT_NUM }, + { "pec" , PU_PEC_CHIPUNIT, MAX_PU_PEC_CHIPUNIT_NUM }, + { "phb" , PU_PHB_CHIPUNIT, MAX_PU_PHB_CHIPUNIT_NUM }, + { "nmmu" , PU_NMMU_CHIPUNIT, MAX_PU_NMMU_CHIPUNIT_NUM }, + { "perv" , PU_PERV_CHIPUNIT, MAX_PU_PERV_CHIPUNIT_NUM }, // Special case, with gaps + { "iohs" , PU_IOHS_CHIPUNIT, MAX_PU_IOHS_CHIPUNIT_NUM }, + { "mc" , PU_MC_CHIPUNIT, MAX_PU_MC_CHIPUNIT_NUM }, + { "mi" , PU_MI_CHIPUNIT, MAX_PU_MI_CHIPUNIT_NUM }, + { "mcc" , PU_MCC_CHIPUNIT, MAX_PU_MCC_CHIPUNIT_NUM }, + { "omi" , PU_OMI_CHIPUNIT, MAX_PU_OMI_CHIPUNIT_NUM }, + { "omic" , PU_OMIC_CHIPUNIT, MAX_PU_OMIC_CHIPUNIT_NUM }, + { "pau" , PU_PAU_CHIPUNIT, MAX_PU_PAU_CHIPUNIT_NUM }, + { "pauc" , PU_PAUC_CHIPUNIT, MAX_PU_PAUC_CHIPUNIT_NUM }, + }; + +} // extern "C" + +#endif /* P10_CU_H */ diff --git a/src/tests/p10_scom_addr.C b/src/tests/p10_scom_addr.C new file mode 100644 index 0000000..507c5a0 --- /dev/null +++ b/src/tests/p10_scom_addr.C @@ -0,0 +1,916 @@ +/// +/// @file p10_scom_addr.C +/// @brief P10 chip unit SCOM address platform translation code +/// +/// HWP HW Maintainer: Thi Tran +/// HWP FW Maintainer: +/// HWP Consumed by: Cronus, HB, HWSV +/// + +// includes +#include "p10_scom_addr.H" + +#define P10_SCOM_ADDR_C + +extern "C" +{ + /// See function description in header file + + // ##################################### + bool p10_scom_addr::isEqTarget() + { + bool l_eqTarget = false; + + // Must have EQ chiplet ID + if ( (getChipletId() >= EQ0_CHIPLET_ID) && + (getChipletId() <= EQ7_CHIPLET_ID) ) + { + // If endpoint is QME (0xE): + // QME per core (bit 20) must be 0 + // region select (bits 16:19) must be 0 + if ( (getEndpoint() == QME_ENDPOINT) && (!getQMEPerCore()) && + (getRegionSelect() == EQ_REGION_SEL) ) + { + l_eqTarget = true; + } + // associate perv target resources with EQ + else if (isPervTarget()) + { + l_eqTarget = true; + } + } + + return l_eqTarget; + } + + // ######################################## + uint8_t p10_scom_addr::getEqTargetInstance() + { + uint8_t l_instance = 0; + l_instance = (getChipletId() - EQ0_CHIPLET_ID); + return l_instance; + } + + // ##################################### + bool p10_scom_addr::isCoreTarget() + { + bool l_coreTarget = false; + + // Must have EQ chiplet ID + if ( (getChipletId() >= EQ0_CHIPLET_ID) && + (getChipletId() <= EQ7_CHIPLET_ID) ) + { + // Region select must be... + if ( (getRegionSelect() == MULTI_HOT_SELECT_C0) || // 0x8 + (getRegionSelect() == MULTI_HOT_SELECT_C1) || // 0x4 + (getRegionSelect() == MULTI_HOT_SELECT_C2) || // 0x2 + (getRegionSelect() == MULTI_HOT_SELECT_C3) || // 0x1 + (getRegionSelect() == EQ_REGION_SEL) ) // 0x0 + { + // If QME endpoint (0xE), QME per core (bit 20) must be 1 + if ( (getEndpoint() == QME_ENDPOINT) && getQMEPerCore() ) + { + l_coreTarget = true; + } + // or must be PSCOM endpoints -- ensure that ring ID is + // associated with a core resource on the first PSCOM + // endpoint (0x1), all are core rings on the second + // PSCOM endpoint (0x2) + else if ( ((getEndpoint() == PSCOM_ENDPOINT) && // 0x1 + ((getEQRingId() != PERV_RING_ID) && // 0x1 + (getEQRingId() != QME_RING_ID))) || // 0x2 + (getEndpoint() == PSCOM_2_ENDPOINT) ) // 0x2 + { + l_coreTarget = true; + } + } + } + + return l_coreTarget; + } + + // ##################################### + uint8_t p10_scom_addr::getCoreTargetInstance() + { + uint8_t l_instance = 0; + + // First core instance of the quad + l_instance = (getChipletId() - EQ0_CHIPLET_ID) * NUM_CORES_PER_EQ; + + // Get core instance based on region select + if (getRegionSelect() == MULTI_HOT_SELECT_C3) + { + l_instance += 3; + } + else if (getRegionSelect() == MULTI_HOT_SELECT_C2) + { + l_instance += 2; + } + else if (getRegionSelect() == MULTI_HOT_SELECT_C1) + { + l_instance += 1; + } + + return l_instance; + } + + // ##################################### + bool p10_scom_addr::isPecTarget() + { + bool l_pecTarget = false; + + // associate perv target resources with PCIE + if ( (getChipletId() >= PCI0_CHIPLET_ID) && // 0x8 + (getChipletId() <= PCI1_CHIPLET_ID) ) // 0x9 + { + l_pecTarget = isPervTarget(); + } + + // Endpoint must be PSCOM (0x1) + if (getEndpoint() == PSCOM_ENDPOINT) // 0x1 + { + // For PEC addresses via NEST regions: + // Ring ID must be 0x6, sat ID must be 0 + if ( (getChipletId() >= N0_CHIPLET_ID) && // 0x2 + (getChipletId() <= N1_CHIPLET_ID) && // 0x3 + (getRingId() == N0_PE1_RING_ID) && // 0x6 + (getSatId() == PEC_SAT_ID) ) // 0x0 + + { + l_pecTarget = true; + } + // For PEC addresses via PCIE: + else if ( (getChipletId() >= PCI0_CHIPLET_ID) && // 0x8 + (getChipletId() <= PCI1_CHIPLET_ID) ) // 0x9 + { + // Ring IDs must be 0x4-0x5 (iopci rings) or + // Ring ID is 0x2 (pci ring) and sat Id = 0x0 + if ( (getRingId() == IO_PCI0_RING_ID) || // 0x4 + (getRingId() == IO_PCI1_RING_ID) || // 0x5 + ((getRingId() == PCI_RING_ID) && // 0x2 + (getSatId() == PEC_SAT_ID)) ) // 0x0 + { + l_pecTarget = true; + } + } + } + + return l_pecTarget; + } + + // ##################################### + uint8_t p10_scom_addr::getPecTargetInstance() + { + uint8_t l_instance = 0; + + // PEC addresses via NEST regions + l_instance = N1_CHIPLET_ID - getChipletId(); + + // PEC addresses via PCIE + if ( (getChipletId() == PCI0_CHIPLET_ID) || + (getChipletId() == PCI1_CHIPLET_ID) ) + { + l_instance = getChipletId() - PCI0_CHIPLET_ID; + } + + return l_instance; + } + + // ##################################### + bool p10_scom_addr::isPhbTarget() + { + bool l_phbTarget = false; + + // Endpoint must be PSCOM (0x1) + if ( (getEndpoint() == PSCOM_ENDPOINT) ) // 0x1 + { + // PCIE chiplet ID + if ( (getChipletId() >= PCI0_CHIPLET_ID) && // 0x8 + (getChipletId() <= PCI1_CHIPLET_ID) ) // 0x9 + { + // Ring ID of 0x2, Sat ID 1-6 + if ( (getRingId() == PCI_RING_ID) && // 0x2 + (getSatId() >= PHB0_AIB_SAT_ID) && // 0x1 + (getSatId() <= PHB2_PHB_SAT_ID) ) // 0x6 + { + l_phbTarget = true; + } + } + + // N0/N1 chiplet ID + if ( (getChipletId() >= N0_CHIPLET_ID) && // 0x2 + (getChipletId() <= N1_CHIPLET_ID) && // 0x3 + (getRingId() == N0_PE1_RING_ID) && // 0x6 + (getSatId() >= PHB0_AIB_SAT_ID) && // 0x1 + (getSatId() <= PHB2_AIB_SAT_ID) ) // 0x3 + { + l_phbTarget = true; + } + } + + return l_phbTarget; + } + + // ##################################### + uint8_t p10_scom_addr::getPhbTargetInstance() + { + uint8_t l_instance = 0; + + if ( (getChipletId() == N0_CHIPLET_ID) || + (getChipletId() == PCI1_CHIPLET_ID) ) + { + l_instance += 3; + } + + if ( (getRingId() == N0_PE1_RING_ID) ) + { + l_instance += (getSatId() - 1); + } + else if ( (getRingId() == PCI_RING_ID ) ) + { + l_instance += ((getSatId() - 1) % 3); + } + else + { + l_instance += (getRingId() - 3); + } + + return l_instance; + } + + // ##################################### + bool p10_scom_addr::isNmmuTarget() + { + bool l_nmmuTarget = false; + + // Must have NEST chiplet ID + if ( (getChipletId() == N0_CHIPLET_ID) || + (getChipletId() == N1_CHIPLET_ID) ) + { + // Endpoint must be PSCOM, ring ID must be 0x3, Sat ID must be 0/1 + if ( (getEndpoint() == PSCOM_ENDPOINT) && // 0x1 + (getRingId() == N0_MM0_RING_ID) && // 0x3 + (getSatId() >= NMMU_SAT_ID0) && // 0x0 + (getSatId() <= NMMU_SAT_ID1) ) // 0x1 + { + l_nmmuTarget = true; + } + } + + return l_nmmuTarget; + } + + // ##################################### + uint8_t p10_scom_addr::getNmmuTargetInstance() + { + return (getChipletId() - N0_CHIPLET_ID); + } + + // ##################################### + bool p10_scom_addr::isPervTarget() + { + bool l_pervTarget = false; + uint8_t l_index = 0; + + // Check chiplet ID by looping through PERV chiplet ID table + for (l_index = 0; + l_index < sizeof(PervTargetChipletIdTable) / sizeof(p10ChipletId_t); + l_index++) + { + // See if Chiplet ID is a perv chiplet ID from table + if (getChipletId() == PervTargetChipletIdTable[l_index]) + { + if (getEndpoint() == PSCOM_ENDPOINT) // 0x1 + { + // EQ specific PSCOM endpoint logic + // ensure ring being accessed is EQ scoped (non-core) + if ( (getChipletId() >= EQ0_CHIPLET_ID) && + (getChipletId() <= EQ7_CHIPLET_ID) ) + { + if ( (getEQRingId() == PERV_RING_ID) || // 0x1 + (getEQRingId() == QME_RING_ID) ) // 0x2 + { + l_pervTarget = true; + } + } + + // non-EQ chiplet, just match for ring ID = 0 / 1 + else + { + if ( (getRingId() == PSCOM_RING_ID) || // 0x0 + (getRingId() == PERV_RING_ID) ) // 0x1 + { + l_pervTarget = true; + } + } + } + else if (getEndpoint() == CLOCK_CTRL_ENDPOINT) // 0x3 + { + l_pervTarget = true; + } + // Check if Endpoint is a PERV endpoint + else if ( (getEndpoint() == CHIPLET_CTRL_ENDPOINT) || // 0x0 + (getEndpoint() == FIR_ENDPOINT) || // 0x4 + (getEndpoint() == THERMAL_ENDPOINT) || // 0x5 + (getEndpoint() == PCBSLV_ENDPOINT) ) // 0xF + { + if ( getRingId() == PSCOM_RING_ID) // 0x0 + { + l_pervTarget = true; + } + } + + break; + } + } + + return l_pervTarget; + } + + // ##################################### + uint8_t p10_scom_addr::getPervTargetInstance() + { + return getChipletId(); + } + + // ##################################### + bool p10_scom_addr::isIoHsTarget() + { + bool l_iohsTarget = false; + + // IOHS can be targeted by AXON or PAU chiplets (indirect scom), + + // Associate perv target resources with AXON + if ( (getChipletId() >= AXON0_CHIPLET_ID) && // 0x18 + (getChipletId() <= AXON7_CHIPLET_ID) ) // 0x1F + { + l_iohsTarget = isPervTarget(); + + // If not a PERV target check for IOHS target that uses AXON chiplet + if (l_iohsTarget == false) + { + if ( (getEndpoint() == PSCOM_ENDPOINT) && + (getRingId() == AXONE_PDL_RING_ID) && // 0x4 + (getSatId() == DLP_SAT_ID) ) // 0x0 + { + l_iohsTarget = true; + } + } + } + + // Target via PAU chiplets + else if ( isIndirect() && + (getChipletId() >= PAU0_CHIPLET_ID) && // 0x10 + (getChipletId() <= PAU3_CHIPLET_ID) ) // 0x13 + { + // Endpoint must be PSCOM and RingID is IOPPE + if ( (getEndpoint() == PSCOM_ENDPOINT) && + (getRingId() == PAU_IOPPE_RING_ID) ) // 0xB + { + // Group address (bits 22:26 of upper address) must be 0b00000 or 0b00001, + // and indirect register address should be per-group or per-lane + // Group 0: IOHS[0] + // Group 1: IOHS[1] + if ( ( (getIoGroupAddr() == 0x0) || + (getIoGroupAddr() == 0x1) ) && + ((getIoRegAddr() & 0x1E0) != 0x1E0) ) + { + l_iohsTarget = true; + } + } + } + + return l_iohsTarget; + } + + // ##################################### + uint8_t p10_scom_addr::getIoHsTargetInstance() + { + uint8_t l_instance = 0; + + // Chiplet ID is AXON + if ( (getChipletId() >= AXON0_CHIPLET_ID) && + (getChipletId() <= AXON7_CHIPLET_ID) ) + { + l_instance = getChipletId() - AXON0_CHIPLET_ID; + } + // Chiplet ID is PAU + else + { + // If chiplet ID is PAU then this is indirect address. + // Use PAU and Group address (bits 22:26) to calculate instance. + // PAU0 (lower right) -> IOHS0 + IOHS1 + // PAU1 (upper right) -> IOHS2 + IOHS3 + // PAU2 (lower left) -> IOHS4 + IOHS5 + // PAU3 (upper left) -> IOHS6 + IOHS7 + // + // Group address bits (22:26) of upper 32-bit + // Group 0: IOHS[0] + // Group 1: IOHS[1] + if ( (getChipletId() >= PAU0_CHIPLET_ID) && // 0x10 + (getChipletId() <= PAU3_CHIPLET_ID) ) // 0x13 + { + l_instance = (getChipletId() - PAU0_CHIPLET_ID) * 2; + + if (getIoGroupAddr() == 0x1) + { + l_instance += 1; + } + } + } + + return l_instance; + } + + // ##################################### + bool p10_scom_addr::isPauTarget() + { + bool l_pauTarget = false; + + // Endpoint must be PSCOM + if ( getEndpoint() == PSCOM_ENDPOINT) + { + // Check chiplet ID + if ( (getChipletId() >= PAU0_CHIPLET_ID) && + (getChipletId() <= PAU3_CHIPLET_ID) ) + { + if ( (getRingId() == PAU0346_0_RING_ID) || // 0x02 + (getRingId() == PAU0346_1_RING_ID) ) // 0x03 + + { + l_pauTarget = true; + } + else if ( (getChipletId() == PAU2_CHIPLET_ID) || + (getChipletId() == PAU3_CHIPLET_ID) ) + { + if ( (getRingId() == PAU57_0_RING_ID) || // 0x04 + (getRingId() == PAU57_1_RING_ID) ) // 0x05 + { + l_pauTarget = true; + } + } + } + } + + return l_pauTarget; + } + + // ##################################### + uint8_t p10_scom_addr::getPauTargetInstance() + { + uint8_t l_instance = 0; + + if ( (getRingId() == PAU0346_0_RING_ID) || // 0x02 + (getRingId() == PAU0346_1_RING_ID) ) // 0x03 + { + if (getChipletId() == PAU0_CHIPLET_ID) + { + l_instance = 0; + } + else if (getChipletId() == PAU1_CHIPLET_ID) + { + l_instance = 3; + } + else if (getChipletId() == PAU2_CHIPLET_ID) + { + l_instance = 4; + } + else if (getChipletId() == PAU3_CHIPLET_ID) + { + l_instance = 6; + } + } + + else if ( (getRingId() == PAU57_0_RING_ID) || // 0x04 + (getRingId() == PAU57_1_RING_ID) ) // 0x05 + { + if (getChipletId() == PAU2_CHIPLET_ID) + { + l_instance = 5; + } + else if (getChipletId() == PAU3_CHIPLET_ID) + { + l_instance = 7; + } + } + + return l_instance; + } + + // ##################################### + bool p10_scom_addr::isMcTarget() + { + // Same as MI + return isMiTarget(); + } + + // ##################################### + uint8_t p10_scom_addr::getMcTargetInstance() + { + // Same as MI + return getMiTargetInstance(); + } + + // ##################################### + bool p10_scom_addr::isMiTarget() + { + bool l_miTarget = false; + + // Chiplet ID must belong to MCs + if ( (getChipletId() >= MC0_CHIPLET_ID) && // 0x0C + (getChipletId() <= MC3_CHIPLET_ID) ) // 0x0F + { + // allow access to perv endpoints on MC chiplets + if (isPervTarget()) + { + l_miTarget = true; + } + // Endpoint = PSCOM_ENDPOINT, and ringID = MC_0_RING_ID + else if ( (getEndpoint() == PSCOM_ENDPOINT) && // 0x1 + (getRingId() == MC_0_RING_ID) ) // 0x3 + { + // PBI satellite + if (getSatId() == MC_SAT_ID0) // 0x0 (PBI) + { + // avoid match on MCC register space + if (!(((getSatOffset() >= 0x22) && + (getSatOffset() <= 0x2B)) || + ((getSatOffset() >= 0x32) && + (getSatOffset() <= 0x3B)))) + { + l_miTarget = true; + } + } + + // MCBIST satellite ID space + // avoid match on MCC register space in 0xD + if ( (getSatId() == MC_SAT_ID12) || // 0xC,0xE,0xF (MCBIST) + (getSatId() == MC_SAT_ID14) || + (getSatId() == MC_SAT_ID15) ) + { + l_miTarget = true; + } + } + } + + return l_miTarget; + } + + // ##################################### + uint8_t p10_scom_addr::getMiTargetInstance() + { + return getChipletId() - MC0_CHIPLET_ID; + } + + // ##################################### + bool p10_scom_addr::isMccTarget() + { + bool l_mccTarget = false; + + // Chiplet ID must belong to MCs, Endpoint = PSCOM_ENDPOINT, + // and ringID = MC_0_RING_ID + if ( (getChipletId() >= MC0_CHIPLET_ID) && // 0x0C + (getChipletId() <= MC3_CHIPLET_ID) && // 0x0F + (getEndpoint() == PSCOM_ENDPOINT) && // 0x1 + (getRingId() == MC_0_RING_ID) ) // 0x3 + { + // MCC Sat ID + if ( (getSatId() == MC_SAT_ID4) || // 0x4 + (getSatId() == MC_SAT_ID8) || // 0x8 + (getSatId() == MC_SAT_ID5) || // 0x5 + (getSatId() == MC_SAT_ID9) ) // 0x9 + { + l_mccTarget = true; + } + + // MCC register space in PBI + if (getSatId() == MC_SAT_ID0) + { + if (((getSatOffset() >= 0x22) && + (getSatOffset() <= 0x2B)) || + ((getSatOffset() >= 0x32) && + (getSatOffset() <= 0x3B))) + { + l_mccTarget = true; + } + } + + // MCC register space in MCBIST + if (getSatId() == MC_SAT_ID13) + { + l_mccTarget = true; + } + } + + return l_mccTarget; + } + + // ##################################### + uint8_t p10_scom_addr::getMccTargetInstance() + { + uint8_t l_instance = (getChipletId() - MC0_CHIPLET_ID) * 2; + + // MCC Sat ID + if ( (getSatId() == MC_SAT_ID5) || // 5 + (getSatId() == MC_SAT_ID9) ) // 9 + { + l_instance += 1; + } + + // MCC register space in PBI + if ( getSatId() == MC_SAT_ID0 ) // 0 + { + if ((getSatOffset() >= 0x32) && + (getSatOffset() <= 0x3B)) + { + l_instance += 1; + } + } + + // MCC register space in MCBIST + if ( getSatId() == MC_SAT_ID13) // 13 + { + // MSB of SatOffset denotes channel + if (getSatOffset() >= 0x20) + { + l_instance += 1; + } + } + + return l_instance; + } + + // ##################################### + bool p10_scom_addr::isOmiTarget() + { + bool l_omiTarget = false; + + // PAU chiplet, IOPPE ringId (indirect scom) + if ( isIndirect() && // indirect + ( getChipletId() >= PAU0_CHIPLET_ID ) && // 0x10 + ( getChipletId() <= PAU3_CHIPLET_ID ) && // 0x13 + ( getEndpoint() == PSCOM_ENDPOINT ) && // 0x1 + ( getRingId() == PAU_IOPPE_RING_ID) && // 0xB + ( getSatId() == PPE_SAT_ID0) ) // 0x0 + { + // Group address (bits 22:26 of upper address) + // must be 0b00010 or 0b00011 (for OMI) + if ( (getIoGroupAddr() == 0x2 ) || + (getIoGroupAddr() == 0x3 ) ) + { + // Reg address must start with 0xxx (per lane) + uint32_t regAddr = getIoRegAddr(); + + if ( ( regAddr & 0x100 ) == 0x000 ) + { + l_omiTarget = true; + } + } + } + + // MC chiplet direct SCOM + if ( ( getChipletId() >= MC0_CHIPLET_ID ) && // 0x0C + ( getChipletId() <= MC3_CHIPLET_ID ) && // 0x0F + ( getEndpoint() == PSCOM_ENDPOINT ) && // 0x1 + ( getRingId() >= OMI0_RING_ID ) && // 0x5 + ( getRingId() <= OMI1_RING_ID ) && // 0x6 + ( getSatId() == MC_SAT_ID0 ) ) // 0x0 (DL) + { + if (((getSatOffset() >= 16) && // 16:31 (subchannel 0) + (getSatOffset() <= 47)) || // 32:47 (subchannel 1) + ((getSatOffset() >= 48) && // 48:51 (subchannel 0, pm regs) + (getSatOffset() <= 51)) || + ((getSatOffset() >= 56) && // 48:51 (subchannel 1, pm regs) + (getSatOffset() <= 59))) + { + l_omiTarget = true; + } + } + + return l_omiTarget; + } + + // ##################################### + uint8_t p10_scom_addr::getOmiTargetInstance() + { + uint8_t l_instance = 0; + + // PAU chiplet indirect SCOM + if ( (getChipletId() >= PAU0_CHIPLET_ID) && // 0x10 + (getChipletId() <= PAU3_CHIPLET_ID) ) // 0x13 + { + // PAU0 --> OMI 0/1/2/3 + // PAU1 --> OMI 8/9/10/11 + // PAU2 --> OMI 4/5/6/7 + // PAU3 --> OMI 12/13/14/15 + // set basis based on direct chiplet ID + if (getChipletId() == PAU0_CHIPLET_ID) + { + l_instance = 0; + } + else if (getChipletId() == PAU1_CHIPLET_ID) + { + l_instance = 8; + } + else if (getChipletId() == PAU2_CHIPLET_ID) + { + l_instance = 4; + } + else + { + l_instance = 12; + } + + // account for IO group address + if (getIoGroupAddr() == 0x3) + { + l_instance += 2; + } + + // account for IO lane selection + if ( ( getIoLane() >= 8 ) && + ( getIoLane() <= 15) ) + { + l_instance += 1; + } + } + + // MC direct + if ( (getChipletId() >= MC0_CHIPLET_ID) && + (getChipletId() <= MC3_CHIPLET_ID) ) + { + // Instances 0, 4, 8, 12 + l_instance = (getChipletId() - MC0_CHIPLET_ID) * 4; + + // Instances 2, 6, 10, 14 + if ( getRingId() == OMI1_RING_ID ) // 0x6 + { + l_instance += 2; + } + + // Instances 1, 3, 5, 7, 9, 11, 13, 15 + if ( ((getSatOffset() >= 32) && + (getSatOffset() <= 47)) || + ((getSatOffset() >= 56) && + (getSatOffset() <= 59)) ) + { + l_instance += 1; + } + } + + return l_instance; + } + + // ##################################### + bool p10_scom_addr::isOmicTarget() + { + bool l_omicTarget = false; + + // PAU chiplet, IOPPE ringId (indirect scom) + if ( isIndirect() && // indirect + ( getChipletId() >= PAU0_CHIPLET_ID ) && // 0x10 + ( getChipletId() <= PAU3_CHIPLET_ID ) && // 0x13 + ( getEndpoint() == PSCOM_ENDPOINT ) && // 0x1 + ( getRingId() == PAU_IOPPE_RING_ID) && // 0xB + ( getSatId() == PPE_SAT_ID0) ) // 0x0 + { + // Group address (bits 22:26 of upper address) + // must be 0b00010 or 0b00011 (for OMI) + if ( (getIoGroupAddr() == 0x2 ) || + (getIoGroupAddr() == 0x3 ) ) + { + // Reg address must start with 1xxx (per group), + // excluding 1111 (per bus) + uint32_t regAddr = getIoRegAddr(); + + if ( ( ( regAddr & 0x1E0 ) != 0x1E0 ) && + ( ( regAddr & 0x100 ) == 0x100 ) ) + { + l_omicTarget = true; + } + } + } + + // MC chiplet direct SCOM + if ( ( getChipletId() >= MC0_CHIPLET_ID ) && // 0x0C + ( getChipletId() <= MC3_CHIPLET_ID ) && // 0x0F + ( getEndpoint() == PSCOM_ENDPOINT ) && // 0x1 + ( getRingId() >= OMI0_RING_ID ) && // 0x5 + ( getRingId() <= OMI1_RING_ID ) && // 0x6 + ( getSatId() == MC_SAT_ID0 ) && // 0x0 (DL) + ( getSatOffset() >= 0 ) && // shared regs 0-15 + ( getSatOffset() <= 15 ) ) + { + l_omicTarget = true; + } + + return l_omicTarget; + } + + // ##################################### + uint8_t p10_scom_addr::getOmicTargetInstance() + { + uint8_t l_instance = 0; + + // PAU indirect + if ( ( getChipletId() >= PAU0_CHIPLET_ID ) && // 0x10 + ( getChipletId() <= PAU3_CHIPLET_ID ) ) // 0x13 + { + // PAU0 --> OMIC 0/1 + // PAU1 --> OMIC 4/5 + // PAU2 --> OMIC 2/3 + // PAU3 --> OMIC 6/7 + if (getChipletId() == PAU0_CHIPLET_ID) + { + l_instance = 0; + } + else if (getChipletId() == PAU1_CHIPLET_ID) + { + l_instance = 4; + } + else if (getChipletId() == PAU2_CHIPLET_ID) + { + l_instance = 2; + } + else // PAU3_CHIPLET_ID + { + l_instance = 6; + } + + if (getIoGroupAddr() == 0x3) + { + l_instance += 1; + } + } + + // MC direct + if ( ( getChipletId() >= MC0_CHIPLET_ID ) && // 0x0C + ( getChipletId() <= MC3_CHIPLET_ID ) ) // 0x0F + { + l_instance = (getChipletId() - MC0_CHIPLET_ID) * 2; + + if (getRingId() == 0x6) + { + l_instance += 1; + } + } + + return l_instance; + } + + // ##################################### + bool p10_scom_addr::isPaucTarget() + { + bool l_paucTarget = false; + + if ( (getChipletId() >= PAU0_CHIPLET_ID) && // 0x10 + (getChipletId() <= PAU3_CHIPLET_ID) ) // 0x13 + { + // allow access to perv endpoints on MC chiplets + if (isPervTarget()) + { + l_paucTarget = true; + } + else if ( getEndpoint() == PSCOM_ENDPOINT ) // 0x1 + { + // IO PPE access + if ( isDirect() && // direct + (getRingId() == PAU_IOPPE_RING_ID) && // 0xB + ( (getSatId() == PPE_SAT_ID0) || // 0x0 + (getSatId() == PPE_SAT_ID1) ) ) // 0x1 + { + l_paucTarget = true; + } + + // TL access + if ( (getRingId() == PAU_TL_RING_ID) && // 0x6 + ( (getSatId() == TL_SAT_ID) ) ) // 0x0 + { + l_paucTarget = true; + } + + // per-bus IO super wrapper registers + if ( isIndirect() && // indirect + ((getIoRegAddr() & 0x1E0) == 0x1E0) && // register(0:3) = 0b1111 + (getRingId() == PAU_IOPPE_RING_ID) && // 0xB + (getSatId() == PPE_SAT_ID0) ) // 0x0 + { + l_paucTarget = true; + } + } + } + + return l_paucTarget; + } + + // ##################################### + uint8_t p10_scom_addr::getPaucTargetInstance() + { + uint8_t l_instance = (getChipletId() - PAU0_CHIPLET_ID); + + return l_instance; + } + +} // extern "C" + +#undef P10_SCOM_ADDR_C diff --git a/src/tests/p10_scom_addr.H b/src/tests/p10_scom_addr.H new file mode 100644 index 0000000..a764f2a --- /dev/null +++ b/src/tests/p10_scom_addr.H @@ -0,0 +1,700 @@ +/// +/// @file p10_scom_addr.H +/// @brief P10 SCOM address class +/// +/// HWP HW Maintainer: Thi Tran +/// HWP FW Maintainer: +/// HWP Consumed by: Cronus, HB, HWSV +/// + +#ifndef P10_SCOM_ADDR_H +#define P10_SCOM_ADDR_H + +// includes +#include + +extern "C" +{ + /// Constants + const uint32_t NUM_CORES_PER_EQ = 4; // Num of cores in an EQ chiplet + + /// P10 Chiplet ID enumeration + typedef enum + { + PIB_CHIPLET_ID = 0x00, ///< PIB chiplet (FSI) + PERV_CHIPLET_ID = 0x01, ///< TP chiplet + + N0_CHIPLET_ID = 0x02, ///< Nest0 (North) chiplet + N1_CHIPLET_ID = 0x03, ///< Nest1 (South) chiplet + + PCI0_CHIPLET_ID = 0x08, ///< PCIe0 chiplet + PCI1_CHIPLET_ID = 0x09, ///< PCIe1 chiplet + + MC0_CHIPLET_ID = 0x0C, ///< MC0 chiplet + MC1_CHIPLET_ID = 0x0D, ///< MC1 chiplet + MC2_CHIPLET_ID = 0x0E, ///< MC2 chiplet + MC3_CHIPLET_ID = 0x0F, ///< MC3 chiplet + + PAU0_CHIPLET_ID = 0x10, ///< PAU0 chiplet + PAU1_CHIPLET_ID = 0x11, ///< PAU1 chiplet + PAU2_CHIPLET_ID = 0x12, ///< PAU2 chiplet + PAU3_CHIPLET_ID = 0x13, ///< PAU3 chiplet + + AXON0_CHIPLET_ID = 0x18, ///< AXON0 chiplet (high speed io) + AXON1_CHIPLET_ID = 0x19, ///< AXON1 chiplet (high speed io) + AXON2_CHIPLET_ID = 0x1A, ///< AXON2 chiplet (high speed io) + AXON3_CHIPLET_ID = 0x1B, ///< AXON3 chiplet (high speed io) + AXON4_CHIPLET_ID = 0x1C, ///< AXON4 chiplet (high speed io) + AXON5_CHIPLET_ID = 0x1D, ///< AXON5 chiplet (high speed io) + AXON6_CHIPLET_ID = 0x1E, ///< AXON6 chiplet (high speed io) + AXON7_CHIPLET_ID = 0x1F, ///< AXON7 chiplet (high speed io) + + EQ0_CHIPLET_ID = 0x20, ///< Quad0 chiplet (super chiplet) + EQ1_CHIPLET_ID = 0x21, ///< Quad1 chiplet (super chiplet) + EQ2_CHIPLET_ID = 0x22, ///< Quad2 chiplet (super chiplet) + EQ3_CHIPLET_ID = 0x23, ///< Quad3 chiplet (super chiplet) + EQ4_CHIPLET_ID = 0x24, ///< Quad4 chiplet (super chiplet) + EQ5_CHIPLET_ID = 0x25, ///< Quad5 chiplet (super chiplet) + EQ6_CHIPLET_ID = 0x26, ///< Quad6 chiplet (super chiplet) + EQ7_CHIPLET_ID = 0x27, ///< Quad7 chiplet (super chiplet) + } p10ChipletId_t; + + /// P10 SCOM Endpoint ID enumeration + typedef enum + { + CHIPLET_CTRL_ENDPOINT = 0x0, ///< Chiplet Control + PSCOM_ENDPOINT = 0x1, ///< EQ:PSCOM (L3), others: PSCOM + PSCOM_2_ENDPOINT = 0x2, ///< EQ:PSCOM (Core/L2), TP:ITR, Nest:TOD (Time Of Day) + CLOCK_CTRL_ENDPOINT = 0x3, ///< Clock controller + FIR_ENDPOINT = 0x4, ///< FIR + THERMAL_ENDPOINT = 0x5, ///< Thermal + DPLL_ENDPOINT = 0x6, ///< TP (only): DPLL + QME_ENDPOINT = 0xE, ///< EQ (only): QME + PCBSLV_ENDPOINT = 0xF, ///< PCB Slave registers + } p10EndpointID_t; + + /// P10 region select (CoreId/One-hot) + typedef enum + { + EQ_REGION_SEL = 0x0, + MULTI_HOT_SELECT_C0 = 0x8, + MULTI_HOT_SELECT_C1 = 0x4, + MULTI_HOT_SELECT_C2 = 0x2, + MULTI_HOT_SELECT_C3 = 0x1, + } p10RegionSelect_t; + + /// ************************************* + /// Ring ID enums + /// ************************************* + + /// P10 N0 chiplet ring ID enumeration + typedef enum + { + N0_MM0_RING_ID = 0x3, + N0_PE1_RING_ID = 0x6, + } p10_N0_RingId_t; + + /// P10 N1 chiplet ring ID enumeration + /// source: tpc_p10_n1_top.vhdl + typedef enum + { + N1_MM1_RING_ID = 0x3, + N1_PE0_RING_ID = 0x6, + } p10_N1_RingId_t; + + /// P10 PCIe chiplet SCOM ring ID enumeration + typedef enum + { + PCI_RING_ID = 0x2, + IO_PCI0_RING_ID = 0x4, + IO_PCI1_RING_ID = 0x5, + } p10_PCI_RingId_t; + + /// P10 PERV chiplet and PSCOM ring ID enumeration + typedef enum + { + PSCOM_RING_ID = 0x0, + PERV_RING_ID = 0x1, + } p10_PSCOM_PERV_RingId_t; + + /// P10 AXONE chiplet ring ID enumeration + typedef enum + { + AXONE_PDL_RING_ID = 0x4, + } p10_AXONE_RingId_t; + + /// P10 PAU chiplet ring ID enumeration + typedef enum + { + PAU0346_0_RING_ID = 0x2, + PAU0346_1_RING_ID = 0x3, + PAU57_0_RING_ID = 0x4, + PAU57_1_RING_ID = 0x5, + PAU_TL_RING_ID = 0x6, + PAU_IOPPE_RING_ID = 0xB, + } p10_PAU_RingId_t; + + /// P10 MC chiplet ring ID enumeration + typedef enum + { + MC_0_RING_ID = 0x3, + MC_1_RING_ID = 0x4, + OMI0_RING_ID = 0x5, + OMI1_RING_ID = 0x6, + } p10_MC_RingId_t; + + /// P10 EQ chiplet ring ID enumeration + typedef enum + { + QME_RING_ID = 0x2, + L3_RING_ID = 0x3, + } p10_EQ_PSCOM_RingId_t; + + typedef enum + { + L2_RING_ID = 0x0, + C_0_RING_ID = 0x2, + C_1_RING_ID = 0x3, + C_3_RING_ID = 0x5, + } p10_EQ_PSCOM2_RingId_t; + + /// ----------------------- + /// Satellite ID defintions + /// ----------------------- + typedef enum + { + NMMU_SAT_ID0 = 0x0, + NMMU_SAT_ID1 = 0x1, + } p10_NMMU_SatId_t; + + typedef enum + { + PEC_SAT_ID = 0x0, + PHB0_AIB_SAT_ID = 0x1, + PHB1_AIB_SAT_ID = 0x2, + PHB2_AIB_SAT_ID = 0x3, + PHB0_PHB_SAT_ID = 0x4, + PHB1_PHB_SAT_ID = 0x5, + PHB2_PHB_SAT_ID = 0x6, + } p10_PCI_SatId_t; + + typedef enum + { + MC_SAT_ID0 = 0x0, + MC_SAT_ID4 = 0x4, + MC_SAT_ID5 = 0x5, + MC_SAT_ID8 = 0x8, + MC_SAT_ID9 = 0x9, + MC_SAT_ID12 = 0xC, + MC_SAT_ID13 = 0xD, + MC_SAT_ID14 = 0xE, + MC_SAT_ID15 = 0xF, + } p10_MC_SatId_t; + + typedef enum + { + PPE_SAT_ID0 = 0x0, + TL_SAT_ID = 0x0, + PPE_SAT_ID1 = 0x1, + } p10_PAU_SatId_t; + + typedef enum + { + DLP_SAT_ID = 0x0, + } p10_AXONE_SatId_t; + + /// ************************************* + /// Perv target table + /// ************************************* + const p10ChipletId_t PervTargetChipletIdTable[] = + { + PIB_CHIPLET_ID, + PERV_CHIPLET_ID, + N0_CHIPLET_ID, + N1_CHIPLET_ID, + PCI0_CHIPLET_ID, + PCI1_CHIPLET_ID, + MC0_CHIPLET_ID, + MC1_CHIPLET_ID, + MC2_CHIPLET_ID, + MC3_CHIPLET_ID, + PAU0_CHIPLET_ID, + PAU1_CHIPLET_ID, + PAU2_CHIPLET_ID, + PAU3_CHIPLET_ID, + AXON0_CHIPLET_ID, + AXON1_CHIPLET_ID, + AXON2_CHIPLET_ID, + AXON3_CHIPLET_ID, + AXON4_CHIPLET_ID, + AXON5_CHIPLET_ID, + AXON6_CHIPLET_ID, + AXON7_CHIPLET_ID, + EQ0_CHIPLET_ID, + EQ1_CHIPLET_ID, + EQ2_CHIPLET_ID, + EQ3_CHIPLET_ID, + EQ4_CHIPLET_ID, + EQ5_CHIPLET_ID, + EQ6_CHIPLET_ID, + EQ7_CHIPLET_ID, + }; + +// ---------------------- +// For non-EQ chiplets +// ---------------------- +// 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 } 0 0 { D } { E } { F } +// +// A - Is multiCast if bit 1 = 0x1 +// B - Chiplet ID (6 bits) [2:7] +// C - Endpoint ID (4 bits) [12:15] +// D - Ring (4 bits) [18:21] +// E - Sat ID (4 bits) [22:25] +// F - Sat Offset (6 bits) [26:31] + +// ---------------------- +// For EQ/Core chiplets +// ---------------------- +// 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 { G } { H } +// +// A - Is multiCast if bit 1 = 0x1 +// B - Chiplet ID (6 bits) [2:7] +// C - Endpoint ID (4 bits) [12:15] +// D - Region select (4 bits) [16:19] +// E - QME per core (1 bit) [20] +// F - QME Sat Enable (1 bit) [21] +// G - QME Sat sel (2 bits) [22:23] +// H - QME reg (8 bits) [24:31] + + /// P10 SCOM address class + class p10_scom_addr + { + public: + + /// @brief Construct a SCOM address object + /// @param[in] i_addr 64-bit raw SCOM address + p10_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 setAddr(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 getAddr() const + { + return (iv_addr); + } + + /// @brief Determine if SCOM address is direct-form (bit 0) + /// @retval bool True if SCOM address is direct-form, false otherwise + inline bool isDirect() 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 isIndirect() const + { + return (!isDirect()); + } + + /// @brief Determine if SCOM address is multicast (bit 1) + /// @retval bool True if SCOM address is multicast, false otherwise + inline bool isMulticast() const + { + return (((iv_addr >> 30) & 0x1) == 0x1); + } + + /// @brief Determine if SCOM address is unicast + /// @retval bool True if SCOM address is unicast, false otherwise + inline bool isUnicast() const + { + return (!(isMulticast())); + } + + /// @brief Extract pervasive chiplet ID from SCOM address (bits 2:7) + /// @retval uint8_t Pervasive chiplet ID value + inline uint8_t getChipletId() 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 setChipletId(const uint8_t i_chiplet_id) + { + iv_addr &= 0xFFFFFFFFC0FFFFFFULL; + iv_addr |= ((i_chiplet_id & 0x3F) << 24); + return; + } + + /// @brief Extract Endpoint field from SCOM address (bits 12:15) + /// @retval uint8_t Endpoint field value + inline uint8_t getEndpoint() const + { + return ((iv_addr >> 16) & 0xF); + } + + /// @brief Modify the Endpoint field from SCOM address + /// @retval none + inline void setEndpoint(const uint8_t i_port) + { + iv_addr &= 0xFFFFFFFFFFF0FFFFULL; + iv_addr |= ((i_port & 0xF) << 16); + return; + } + + /// @brief Extract region select field (core id) from SCOM address (bits 16:19) + /// @retval uint8_t Region select value + inline uint8_t getRegionSelect() const + { + return ((iv_addr >> 12) & 0xF); + } + + /// @brief Modify the region select field (core id) from SCOM address + /// @retval none + inline void setRegionSelect(const uint8_t i_regionSelect) + { + iv_addr &= 0xFFFFFFFFFFFF0FFFULL; + iv_addr |= ((i_regionSelect & 0xF) << 12); + return; + } + + /// @brief Extract ring field from SCOM address (bits 18:21) + /// @retval uint8_t Ring id value + inline uint8_t getRingId() const + { + return ((iv_addr >> 10) & 0xF); + } + + /// @brief Extract EQ ring field from SCOM address (bits 20:22) + /// @retval uint8_t Ring id value + inline uint8_t getEQRingId() const + { + return ((iv_addr >> 9) & 0x7); + } + + /// @brief Modify SCOM address, update ring field value + /// @param[in] i_ring Ring field value to write + /// @retval none + inline void setRingId(const uint8_t i_ring) + { + iv_addr &= 0xFFFFFFFFFFFF03FFULL; + iv_addr |= ((i_ring & 0x3F) << 10); + return; + } + + /// @brief Extract satellite ID field from SCOM address (bits 22:25) + /// @retval uint8_t Satellite ID field value + inline uint8_t getSatId() const + { + return ((iv_addr >> 6) & 0xF); + } + + /// @brief Extract EQ satellite ID field from SCOM address (bits 23:25) + /// @retval uint8_t Ring id value + inline uint8_t getEQSatId() const + { + return ((iv_addr >> 6) & 0x7); + } + + /// @brief Modify SCOM address, update satellite ID field + /// @param[in] i_sat_id Satellite ID value to write + /// @retval none + inline void setSatId(const uint8_t i_satId) + { + iv_addr &= 0xFFFFFFFFFFFFFC3FULL; + iv_addr |= ((i_satId & 0xF) << 6); + return; + } + + /// @brief Extract satellite register offset field from SCOM address (bits 26:31) + /// @retval uint8_t Satellite register offset field value + inline uint8_t getSatOffset() 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 setSatOffset(const uint8_t i_sat_offset) + { + iv_addr &= 0xFFFFFFFFFFFFFFC0ULL; + iv_addr |= (i_sat_offset & 0x3F); + return; + } + + /// @brief Get the OBUS Super Wrapper Group address (bits 22:26) of + /// an indirect scom address + /// @retval uint8_t Group address + inline uint8_t getIoGroupAddr() const + { + return ((iv_addr >> 37) & 0x1F); + } + + /// @brief Set the OBUS Super Wrapper Group address (bits 22:26) of + /// an indirect scom address + /// @param[in] i_group_addr Group address value to write + /// @retval none + inline void setIoGroupAddr(const uint8_t i_group_addr) + { + iv_addr &= 0xFFFFFC1FFFFFFFFFULL; + iv_addr |= ( ((uint64_t)i_group_addr & 0x1F) << 37 ); + return; + } + + /// @brief Get Super Wrapper Register address (bits 12:20) + /// of an indirect scom address + /// @retval uint32_t Register address + inline uint32_t getIoRegAddr() const + { + return ((iv_addr >> 43) & 0x1FF); + } + + /// @brief Get the OBUS Super Wrapper TX/RX bit (bit 21) + /// of an indirect scom address + /// @retval uint8_t TX/RX bit + inline uint32_t getIoTxRxBit() const + { + return ((iv_addr >> 42) & 0x1); + } + + /// @brief Get the OBUS Super Wrapper Lane (bits 27:31) + /// of an indirect scom address + /// @retval uint8_t Lane + inline uint32_t getIoLane() const + { + return ((iv_addr >> 32) & 0x1F); + } + + /// @brief Set the OBUS Super Wrapper Lane (bits 27:31) + /// of an indirect scom address + /// @retval uint8_t Lane + inline void setIoLane(const uint8_t i_lane) + { + iv_addr &= 0xFFFFFFE0FFFFFFFFULL; + iv_addr |= ( ((uint64_t)i_lane & 0x1F) << 32); + } + + /// IOP indirect SCOMs + /// IOP0.top0.pma0 (PMA0) -> 0x8000xxxx0801113f + /// IOP0.top0.pma1 (PMA1) -> 0x8001xxxx0801113f + /// IOP0.top1.pma0 (PMA2) -> 0x8000xxxx0801153f + /// IOP0.top1.pma1 (PMA3) -> 0x8001xxxx0801153f + /// IOP1.top0.pma0 (PMA0) -> 0x8000xxxx0901113f + /// IOP1.top0.pma1 (PMA1) -> 0x8001xxxx0901113f + /// IOP1.top1.pma0 (PMA2) -> 0x8000xxxx0901153f + /// IOP1.top1.pma1 (PMA3) -> 0x8001xxxx0901153f + + /// @brief Get PEC IOP Control Register value (bits 12:31) from + /// an indirect scom address + /// @retval uint32_t CR register + inline uint32_t getIopIndCRreg() const + { + return ((iv_addr >> 32) & 0xFFFFF); + } + + /// @brief Get IOP TOP value (bit 53) from an indirect scom address + /// @retval uint8_t Top value (0 or 1) + inline uint8_t getIopTop() const + { + return ((iv_addr >> 10) & 0x1); + } + + /// @brief Get PMA value (bit 15) from an indirect scom address + /// @retval uint8_t Top value (0 or 1) + inline uint8_t getPMA() const + { + return ( ((iv_addr >> 48) & 0x1) + (getIopTop() * 2) ); + } + + /// @brief Determine if SCOM address is valid/well-formed + /// @retval bool True if SCOM address is valid, false otherwise + inline bool isValid() const + { + return true; + } + + /// @brief Determine if this address belongs to EQ target type + /// @retval true or false. + bool isEqTarget(); + + /// @brief Determine the EQ instance for this address + /// Function prereq: Address must belong to EQ target type + /// @retval uint8_t EQ target instance + uint8_t getEqTargetInstance(); + + /// @brief Determine if this address belongs to core target type + /// @retval true or false. + bool isCoreTarget(); + + /// @brief Determine the core instance for this address. + /// Function prereq: Address must belong to core target type + /// @retval uint8_t Core target instance + uint8_t getCoreTargetInstance(); + + /// @brief Determine if this address belongs to PEC target type + /// @retval true or false. + bool isPecTarget(); + + /// @brief Determine the pec instance for this address + /// Function prereq: Address must belong to PEC target type + /// @retval uint8_t PEC target instance + uint8_t getPecTargetInstance(); + + /// @brief Determine if this address belongs to PHB target type + /// @retval true or false. + bool isPhbTarget(); + + /// @brief Determine the PHB instance for this address + /// Function prereq: Address must belong to PHB target type + /// @retval uint8_t PHB target instance + uint8_t getPhbTargetInstance(); + + /// @brief Determine if this address belongs to NMMU target type + /// @retval true or false. + bool isNmmuTarget(); + + /// @brief Determine the NMMU instance for this address + /// Function prereq: Address must belong to NMMU target type + /// @retval uint8_t NMMU target instance + uint8_t getNmmuTargetInstance(); + + /// @brief Get the QME Per Core value (bit 20, EQ/Core only) + /// Function prereq: Address must belong to EQ or Core target type + /// @retval uint8_t QME Per Core value + inline uint8_t getQMEPerCore() + { + return (iv_addr >> 11) & 0x1; + } + + /// @brief Get the QME Sat Enable value (bit 21, EQ/Core only) + /// Function prereq: Address must belong to EQ or Core target type + /// @retval uint8_t QME Sat Enable value + inline uint8_t getQMESatEn() + { + return (iv_addr >> 10) & 0x1; + } + + /// @brief Get the QME Sat Select value (bit 22:23, EQ/Core only) + /// Function prereq: Address must belong to EQ or Core target type + /// @retval uint8_t QME Sat Sel value + inline uint8_t getQMESatSel() + { + return (iv_addr >> 8) & 0x3; + } + + /// @brief Get the QME reg value (bit 24:31, EQ/Core only) + /// Function prereq: Address must belong to EQ or Core target type + /// @retval uint8_t QME reg value + inline uint8_t getQMEReg() + { + return (iv_addr & 0xFF); + } + + /// @brief Determine if this address belongs to PERV target type + /// @retval true or false. + bool isPervTarget(); + + /// @brief Determine the PERV instance for this address + /// Function prereq: Address must belong to PERV target type + /// @retval uint8_t PERV target instance. + uint8_t getPervTargetInstance(); + + /// @brief Determine if this address belongs to IOHS target type + /// @retval true or false. + bool isIoHsTarget(); + + /// @brief Determine the IOHS instance for this address + /// Function prereq: Address must belong to IOHS target type + /// @retval uint8_t IOHS target instance. + uint8_t getIoHsTargetInstance(); + + /// @brief Determine if this address belongs to PAU target type + /// @retval true or false. + bool isPauTarget(); + + /// @brief Determine the PAU instance for this address + /// Function prereq: Address must belong to PAU target type + /// @retval uint8_t PAU target instance. + uint8_t getPauTargetInstance(); + + /// @brief Determine if this address belongs to MC target type + /// @retval true or false. + bool isMcTarget(); + + /// @brief Determine the MC instance for this address + /// Function prereq: Address must belong to MI target type + /// @retval uint8_t MC target instance. + uint8_t getMcTargetInstance(); + + /// @brief Determine if this address belongs to MI target type + /// @retval true or false. + bool isMiTarget(); + + /// @brief Determine the MI instance for this address + /// Function prereq: Address must belong to MI target type + /// @retval uint8_t MI target instance. + uint8_t getMiTargetInstance(); + + /// @brief Determine if this address belongs to MCC target type + /// @retval true or false. + bool isMccTarget(); + + /// @brief Determine the MCC instance for this address + /// Function prereq: Address must belong to MCC target type + /// @retval uint8_t MCC target instance. + uint8_t getMccTargetInstance(); + + /// @brief Determine if this address belongs to OMI target type + /// @retval true or false. + bool isOmiTarget(); + + /// @brief Determine the OMI instance for this address + /// Function prereq: Address must belong to OMI target type + /// @retval uint8_t OMI target instance. + uint8_t getOmiTargetInstance(); + + /// @brief Determine if this address belongs to OMIC target type + /// @retval true or false. + bool isOmicTarget(); + + /// @brief Determine the OMIC instance for this address + /// Function prereq: Address must belong to OMIC target type + /// @retval uint8_t OMIC target instance. + uint8_t getOmicTargetInstance(); + + /// @brief Determine if this address belongs to PAUC target type + /// @retval true or false. + bool isPaucTarget(); + + /// @brief Determine the PAUC instance for this address + /// Function prereq: Address must belong to PAUC target type + /// @retval uint8_t PAUC target instance. + uint8_t getPaucTargetInstance(); + + private: + uint64_t iv_addr; ///< 64-bit raw SCOM address + }; + +} // extern "C" + +#endif /* P10_SCOM_ADDR_H */ diff --git a/src/tests/p10_scominfo.C b/src/tests/p10_scominfo.C new file mode 100644 index 0000000..0294a50 --- /dev/null +++ b/src/tests/p10_scominfo.C @@ -0,0 +1,838 @@ +/// +/// @file p10_scominfo.C +/// @brief P10 chip unit SCOM address platform translation code +/// +/// HWP HW Maintainer: Thi Tran +/// HWP FW Maintainer: +/// HWP Consumed by: Cronus, HB, HWSV +/// + +// includes +#include "p10_scominfo.H" +#include "p10_scom_addr.H" + +#define P10_SCOMINFO_C + +extern "C" +{ + + // --------------------------- + // Internal functions + // --------------------------- + + //################################################################################ + /// @brief Calculate the region select (core ID) value for given core + /// instance + /// @param[in] i_coreInstance Core instance number (0-31) + /// @retval uint8_t Region select value + uint8_t calcRegionSelect(uint8_t i_coreInstanceNum) + { + uint8_t l_regionSel = 0; + + if (i_coreInstanceNum % NUM_CORES_PER_EQ == 0) + { + l_regionSel = 8; + } + else if (i_coreInstanceNum % NUM_CORES_PER_EQ == 1) + { + l_regionSel = 4; + } + else if (i_coreInstanceNum % NUM_CORES_PER_EQ == 2) + { + l_regionSel = 2; + } + else + { + l_regionSel = 1; + } + + return l_regionSel; + } + + //################################################################################ + /// @brief Get the chiplet ID for a chip unit instance based on given + /// address and chip unit type + /// @param[in] i_addr SCOM address + /// @param[in] i_chipUnitNum Instance number + /// @param[in] i_chipUnitType Chip unit type + /// @param[out] o_chipletId Output chiplet id + /// @retval Non-zero if error + uint8_t getChipletId(const uint64_t i_addr, + const uint8_t i_chipUnitNum, + const p10ChipUnits_t i_chipUnitType, + uint8_t& o_chipletId) + { + uint8_t l_rc = 0; + + do + { + p10_scom_addr l_scom(i_addr); + + switch (i_chipUnitType) + { + case PU_EQ_CHIPUNIT: + o_chipletId = EQ0_CHIPLET_ID + i_chipUnitNum; + break; + + case PU_C_CHIPUNIT: + o_chipletId = EQ0_CHIPLET_ID + (i_chipUnitNum / NUM_CORES_PER_EQ); + break; + + case PU_PEC_CHIPUNIT: + + // If input address is of Nest chiplets + if ( (l_scom.getChipletId() >= N0_CHIPLET_ID) && + (l_scom.getChipletId() <= N1_CHIPLET_ID) ) + { + o_chipletId = ((i_chipUnitNum) ? (N0_CHIPLET_ID) : (N1_CHIPLET_ID)); + } + // If input address is of PCI chiplets + else + { + o_chipletId = PCI0_CHIPLET_ID + i_chipUnitNum; + } + + break; + + case PU_PHB_CHIPUNIT: + + // If input address is of Nest chiplets + if ( (l_scom.getChipletId() >= N0_CHIPLET_ID) && + (l_scom.getChipletId() <= N1_CHIPLET_ID) ) + { + o_chipletId = ((i_chipUnitNum / 3) ? (N0_CHIPLET_ID) : (N1_CHIPLET_ID)); + } + // If input address is of PCI chiplets + else + { + o_chipletId = (i_chipUnitNum / 3) + PCI0_CHIPLET_ID; + } + + break; + + case PU_NMMU_CHIPUNIT: + o_chipletId = i_chipUnitNum + N0_CHIPLET_ID; + break; + + case PU_PERV_CHIPUNIT: + o_chipletId = i_chipUnitNum; + break; + + case PU_IOHS_CHIPUNIT: + + // If input address is of AXON chiplets + if ( (l_scom.getChipletId() >= AXON0_CHIPLET_ID) && // 0x18 + (l_scom.getChipletId() <= AXON7_CHIPLET_ID) ) // 0x1F + { + o_chipletId = AXON0_CHIPLET_ID + i_chipUnitNum; + } + else if ( (l_scom.getChipletId() >= PAU0_CHIPLET_ID) && + (l_scom.getChipletId() <= PAU3_CHIPLET_ID) ) + { + // PAU0 --> IOHS0, IOHS1 + // PAU1 --> IOHS2, IOHS3 + // PAU2 --> IOHS4, IOHS5 + // PAU3 --> IOHS6, IOHS7 + o_chipletId = (i_chipUnitNum / 2) + PAU0_CHIPLET_ID; + } + else + { + l_rc = 1; + } + + break; + + case PU_MI_CHIPUNIT: + case PU_MC_CHIPUNIT: + o_chipletId = i_chipUnitNum + MC0_CHIPLET_ID; + break; + + case PU_MCC_CHIPUNIT: + o_chipletId = (i_chipUnitNum / 2) + MC0_CHIPLET_ID; + break; + + case PU_OMIC_CHIPUNIT: + + // PAU indirect + if ( (l_scom.getChipletId() >= PAU0_CHIPLET_ID) && // 0x10 + (l_scom.getChipletId() <= PAU3_CHIPLET_ID) ) // 0x13 + { + // PAU0 --> OMIC 0/1 + // PAU1 --> OMIC 4/5 + // PAU2 --> OMIC 2/3 + // PAU3 --> OMIC 6/7 + if (i_chipUnitNum >= 0 && i_chipUnitNum <= 1) + { + o_chipletId = PAU0_CHIPLET_ID; + } + else if (i_chipUnitNum >= 2 && i_chipUnitNum <= 3) + { + o_chipletId = PAU2_CHIPLET_ID; + } + else if (i_chipUnitNum >= 4 && i_chipUnitNum <= 5) + { + o_chipletId = PAU1_CHIPLET_ID; + } + else if (i_chipUnitNum >= 6 && i_chipUnitNum <= 7) + { + o_chipletId = PAU3_CHIPLET_ID; + } + else + { + l_rc = 1; + } + } + // MC direct + else + { + o_chipletId = (i_chipUnitNum / 2) + MC0_CHIPLET_ID; + } + + break; + + case PU_OMI_CHIPUNIT: + + // PAU indirect + if ( (l_scom.getChipletId() >= PAU0_CHIPLET_ID) && // 0x10 + (l_scom.getChipletId() <= PAU3_CHIPLET_ID) ) // 0x13 + { + // PAU0 --> OMI 0/1/2/3 + // PAU1 --> OMI 8/9/10/11 + // PAU2 --> OMI 4/5/6/7 + // PAU3 --> OMI 12/13/14/15 + if (i_chipUnitNum >= 0 && i_chipUnitNum <= 3) + { + o_chipletId = PAU0_CHIPLET_ID; + } + else if (i_chipUnitNum >= 4 && i_chipUnitNum <= 7) + { + o_chipletId = PAU2_CHIPLET_ID; + } + else if (i_chipUnitNum >= 8 && i_chipUnitNum <= 11) + { + o_chipletId = PAU1_CHIPLET_ID; + } + else if (i_chipUnitNum >= 12 && i_chipUnitNum <= 15) + { + o_chipletId = PAU3_CHIPLET_ID; + } + else + { + l_rc = 1; + } + } + // MC direct + else + { + o_chipletId = (i_chipUnitNum / 4) + MC0_CHIPLET_ID; + } + + break; + + case PU_PAUC_CHIPUNIT: + o_chipletId = i_chipUnitNum + PAU0_CHIPLET_ID; + break; + + case PU_PAU_CHIPUNIT: + o_chipletId = (i_chipUnitNum / 2) + PAU0_CHIPLET_ID; + break; + + default: + l_rc = 1; + break; + }; + + } + while (0); + + return (l_rc); + } + + // See header file for function description + uint64_t p10_scominfo_createChipUnitScomAddr( + const p10ChipUnits_t i_p10CU, + const uint8_t i_ecLevel, + const uint8_t i_chipUnitNum, + const uint64_t i_scomAddr, + const uint32_t i_mode) + { + uint8_t l_rc = 0; + p10_scom_addr l_scom(i_scomAddr); + uint8_t l_chipletId = 0; + + do + { + // Make sure i_chipUnitNum is within range + l_rc = validateChipUnitNum(i_chipUnitNum, i_p10CU); + + if (l_rc) + { + break; + } + + // If chip unit type is a chip, return input address + if (i_p10CU == P10_NO_CU) + { + l_scom.setAddr(i_scomAddr); + break; + } + + // Set the chiplet ID + l_rc = getChipletId(i_scomAddr, i_chipUnitNum, i_p10CU, l_chipletId); + + if (l_rc) + { + break; + } + + l_scom.setChipletId(l_chipletId); + + // Set other address fields (ringId, satId, etc...) + // for Chip unit types that are needed. + switch (i_p10CU) + { + case PU_C_CHIPUNIT: + // Set the core's region select (core ID) + l_scom.setRegionSelect(calcRegionSelect(i_chipUnitNum)); + break; + + case PU_PHB_CHIPUNIT: + + // If input address is of Nest chiplets + if ( (l_scom.getChipletId() >= N0_CHIPLET_ID) && + (l_scom.getChipletId() <= N1_CHIPLET_ID) ) + { + l_scom.setSatId(1 + (i_chipUnitNum % 3)); + } + // If input address is of PCI chiplets + else + { + if (l_scom.getRingId() == 2) + { + if ((l_scom.getSatId() >= 1) && + (l_scom.getSatId() <= 3)) + { + l_scom.setSatId(1 + (i_chipUnitNum % 3)); + } + else + { + l_scom.setSatId(4 + (i_chipUnitNum % 3)); + } + } + } + + break; + + case PU_MCC_CHIPUNIT: + + // Set Sat ID + if (i_chipUnitNum % 2) + { + uint8_t l_offset = l_scom.getSatOffset(); + + // MCC Sat ID + // For odd MCC instance, Sat Id is to be set to 5, or 9 + // If input address is an even instance that has: + // SatId = 0x4 --> set translated SatId to 0x5 + // = 0x8 --> set translated SatId to 0x9 + // If input address is an odd instance, leave the SatId + // as input address. + if (l_scom.getSatId() == 0x4) + { + l_scom.setSatId(0x5); + } + else if (l_scom.getSatId() == 0x8) + { + l_scom.setSatId(0x9); + } + // PBI Sat ID + else if (l_scom.getSatId() == 0x0) + { + if ((l_offset >= 0x22) && + (l_offset <= 0x2B)) + { + l_scom.setSatOffset(l_offset + 0x10); + } + } + // MCBIST Sat ID + else if (l_scom.getSatId() == 0xD) + { + if ((l_offset >= 0x00) && + (l_offset <= 0x1F)) + { + l_scom.setSatOffset(l_offset + 0x20); + } + } + } + else + { + uint8_t l_offset = l_scom.getSatOffset(); + + // For even MCC instance, Sat Id is to be set to 4, or 8 + // If input address is an odd instance that has: + // SatId = 0x5 --> set translated SatId to 0x4 + // = 0x9 --> set translated SatId to 0x8 + // If input address is an even instance, leave the SatId + // as input address. + if (l_scom.getSatId() == 0x5) + { + l_scom.setSatId(0x4); + } + else if (l_scom.getSatId() == 0x9) + { + l_scom.setSatId(0x8); + } + // PBI Sat ID + else if (l_scom.getSatId() == 0x0) + { + if ((l_offset >= 0x32) && + (l_offset <= 0x3B)) + { + l_scom.setSatOffset(l_offset - 0x10); + } + } + // MCBIST Sat ID + else if (l_scom.getSatId() == 0xD) + { + if ((l_offset >= 0x20) && + (l_offset <= 0x3F)) + { + l_scom.setSatOffset(l_offset - 0x20); + } + } + } + + break; + + + case PU_IOHS_CHIPUNIT: + + // PAU indirect + if ( (l_scom.getChipletId() >= PAU0_CHIPLET_ID) && // 0x10 + (l_scom.getChipletId() <= PAU3_CHIPLET_ID) ) // 0x13 + { + // for odd IOHS instances, set IO group = 1 + if ( i_chipUnitNum % 2 ) + { + l_scom.setIoGroupAddr(0x1); + } + // for even IOHS instances, set IO group = 0 + else + { + l_scom.setIoGroupAddr(0x0); + } + } + + break; + + case PU_OMI_CHIPUNIT: + + // PAU indirect + if ( (l_scom.getChipletId() >= PAU0_CHIPLET_ID) && // 0x10 + (l_scom.getChipletId() <= PAU3_CHIPLET_ID) ) // 0x13 + { + // for odd OMI instances, set IO lane between 8-15 + if ( i_chipUnitNum % 2 ) + { + l_scom.setIoLane(8 + (l_scom.getIoLane() % 8)); + } + // for even OMI instances, set IO lane between 0-7 + else + { + l_scom.setIoLane(0 + (l_scom.getIoLane() % 8)); + } + + // for odd OMI instances after dividing by 2, set IO group = 3 + if ( (i_chipUnitNum / 2) % 2 ) + { + l_scom.setIoGroupAddr(0x3); + } + // for even OMI instances after dividing by 2, set IO group = 2 + else + { + l_scom.setIoGroupAddr(0x2); + } + } + // MC direct + else + { + // non-PM regs + if ((l_scom.getSatOffset() >= 16) && (l_scom.getSatOffset() <= 47)) + { + // for odd OMI instances, set sat reg ID between 32-47 + if ( i_chipUnitNum % 2 ) + { + l_scom.setSatOffset(32 + (l_scom.getSatOffset() % 16)); + } + // for even OMI instances, set sat reg ID between 16-31 + else + { + l_scom.setSatOffset(16 + (l_scom.getSatOffset() % 16)); + } + } + // PM regs + else + { + // for odd OMI instances, set sat reg ID between 56-59 + if ( i_chipUnitNum % 2 ) + { + l_scom.setSatOffset(56 + (l_scom.getSatOffset() % 4)); + } + // for even OMI instances, set sat reg ID between 48-51 + else + { + l_scom.setSatOffset(48 + (l_scom.getSatOffset() % 4)); + } + + } + + // for odd OMI instances after dividing by 2, set ring ID = 6 + if ( (i_chipUnitNum / 2) % 2 ) + { + l_scom.setRingId(0x6); + } + // for even OMI instances after dividing by 2, set ring ID = 5 + else + { + l_scom.setRingId(0x5); + } + } + + break; + + case PU_OMIC_CHIPUNIT: + + // PAU indirect + if ( (l_scom.getChipletId() >= PAU0_CHIPLET_ID) && // 0x10 + (l_scom.getChipletId() <= PAU3_CHIPLET_ID) ) // 0x13 + { + if (i_chipUnitNum % 2) + { + // For odd OMIC instance, set IO group ID=3 + l_scom.setIoGroupAddr(0x3); + } + else + { + // For even OMIC instance, set IO group ID=2 + l_scom.setIoGroupAddr(0x2); + } + } + // MC direct + else + { + if (i_chipUnitNum % 2) + { + // For odd OMIC instance, set ring ID=6 + l_scom.setRingId(0x6); + } + else + { + // For even OMIC instance, set ring ID=5 + l_scom.setRingId(0x5); + } + } + + break; + + case PU_PAU_CHIPUNIT: + + // Setting RingId for instances 0, 3, 4, and 6 + // If input address has: + // RingId = 0x4 --> set translated RingId to 0x2 + // 0x5 --> set translated RingId to 0x3 + // Leave RingId as is otherwise + if ( (i_chipUnitNum == 0) || + (i_chipUnitNum == 3) || + (i_chipUnitNum == 4) || + (i_chipUnitNum == 6) ) + { + if (l_scom.getRingId() == 0x4) + { + l_scom.setRingId(0x2); + } + else if (l_scom.getRingId() == 0x5) + { + l_scom.setRingId(0x3); + } + } + + // Setting RingId for instances 1, 2, 5, and 7 + // If input address has: + // RingId = 0x2 --> set translated RingId to 0x4 + // 0x3 --> set translated RingId to 0x5 + // Leave RingId as is otherwise + else if ( (i_chipUnitNum == 1) || + (i_chipUnitNum == 2) || + (i_chipUnitNum == 5) || + (i_chipUnitNum == 7) ) + { + if (l_scom.getRingId() == 0x2) + { + l_scom.setRingId(0x4); + } + else if (l_scom.getRingId() == 0x3) + { + l_scom.setRingId(0x5); + } + } + + break; + + default: + break; + } + + // Break out if error + if (l_rc) + { + break; + } + + } + while(0); + + if (l_rc) + { + l_scom.setAddr(FAILED_TRANSLATION); + } + + return l_scom.getAddr(); + } + + // See header file for function description + uint32_t p10_scominfo_isChipUnitScom(const p10ChipUnits_t i_p10CU, + const uint8_t i_ecLevel, + const uint64_t i_scomAddr, + bool& o_chipUnitRelated, + std::vector& o_chipUnitPairing, + const p10TranslationMode_t i_mode) + { + p10_scom_addr l_scom(i_scomAddr); + o_chipUnitRelated = false; + o_chipUnitPairing.clear(); + + // Quad registers which can be addressed by EQ target type + // eq: 0..7 + if (l_scom.isEqTarget()) + { + o_chipUnitRelated = true; + // PU_EQ_CHIPUNIT + o_chipUnitPairing.push_back(p10_chipUnitPairing_t(PU_EQ_CHIPUNIT, + l_scom.getEqTargetInstance())); + } + + // Core, L2, L3 registers which can be addressed by core target type + // c: 0..31 + if (l_scom.isCoreTarget()) + { + o_chipUnitRelated = true; + // PU_C_CHIPUNIT + o_chipUnitPairing.push_back(p10_chipUnitPairing_t(PU_C_CHIPUNIT, + l_scom.getCoreTargetInstance())); + } + + // PEC registers which can be addressed by pec target type + // pec: 0..1 + if (l_scom.isPecTarget()) + { + o_chipUnitRelated = true; + // PU_PEC_CHIPUNIT + o_chipUnitPairing.push_back(p10_chipUnitPairing_t(PU_PEC_CHIPUNIT, + l_scom.getPecTargetInstance())); + } + + // PHB registers + // phb: 0..5 + if (l_scom.isPhbTarget()) + { + o_chipUnitRelated = true; + // PU_PHB_CHIPUNIT + o_chipUnitPairing.push_back(p10_chipUnitPairing_t(PU_PHB_CHIPUNIT, + l_scom.getPhbTargetInstance())); + } + + // NMMU registers + // nmmu: 0..1 + if (l_scom.isNmmuTarget()) + { + o_chipUnitRelated = true; + // PU_NMMU_CHIPUNIT + o_chipUnitPairing.push_back(p10_chipUnitPairing_t(PU_NMMU_CHIPUNIT, + l_scom.getNmmuTargetInstance())); + } + + // IOHS registers + if (l_scom.isIoHsTarget() && + // prevent matching on IOHS SCOMs in ENGD build mode + (i_mode != P10_ENGD_BUILD_MODE)) + { + o_chipUnitRelated = true; + // PU_IOHS_CHIPUNIT + o_chipUnitPairing.push_back(p10_chipUnitPairing_t(PU_IOHS_CHIPUNIT, + l_scom.getIoHsTargetInstance())); + } + + // PAU registers + if (l_scom.isPauTarget()) + { + o_chipUnitRelated = true; + // PU_PAU_CHIPUNIT + o_chipUnitPairing.push_back(p10_chipUnitPairing_t(PU_PAU_CHIPUNIT, + l_scom.getPauTargetInstance())); + } + + // MC registers + if (l_scom.isMcTarget()) + { + o_chipUnitRelated = true; + // PU_MC_CHIPUNIT + o_chipUnitPairing.push_back(p10_chipUnitPairing_t(PU_MC_CHIPUNIT, + l_scom.getMcTargetInstance())); + } + + // MI registers + if (l_scom.isMiTarget()) + { + o_chipUnitRelated = true; + // PU_MI_CHIPUNIT + o_chipUnitPairing.push_back(p10_chipUnitPairing_t(PU_MI_CHIPUNIT, + l_scom.getMiTargetInstance())); + } + + // MCC registers + if (l_scom.isMccTarget()) + { + o_chipUnitRelated = true; + // PU_MCC_CHIPUNIT + o_chipUnitPairing.push_back(p10_chipUnitPairing_t(PU_MCC_CHIPUNIT, + l_scom.getMccTargetInstance())); + } + + // OMI registers + if (l_scom.isOmiTarget()) + { + o_chipUnitRelated = true; + // PU_OMI_CHIPUNIT + o_chipUnitPairing.push_back(p10_chipUnitPairing_t(PU_OMI_CHIPUNIT, + l_scom.getOmiTargetInstance())); + } + + // OMIC registers + if (l_scom.isOmicTarget()) + { + o_chipUnitRelated = true; + // PU_OMIC_CHIPUNIT + o_chipUnitPairing.push_back(p10_chipUnitPairing_t(PU_OMIC_CHIPUNIT, + l_scom.getOmicTargetInstance())); + } + + // PAUC registers + if (l_scom.isPaucTarget() && + // prevent matching on indirect SCOMs (physically targeting IOHS + // scan latches) in ENGD build mode + ((i_mode != P10_ENGD_BUILD_MODE) || + (l_scom.isDirect()))) + { + o_chipUnitRelated = true; + // PU_PAUC_CHIPUNIT + o_chipUnitPairing.push_back(p10_chipUnitPairing_t(PU_PAUC_CHIPUNIT, + l_scom.getPaucTargetInstance())); + } + + // PERV registers + if (l_scom.isPervTarget()) + { + // if running in engineering data build flow context, do not + // emit associations for registers which would have only + // a single association of type PERV + if (!((o_chipUnitPairing.size() == 0) && + (i_mode == P10_ENGD_BUILD_MODE))) + { + o_chipUnitRelated = true; + // PU_PERV_CHIPUNIT + o_chipUnitPairing.push_back(p10_chipUnitPairing_t(PU_PERV_CHIPUNIT, + l_scom.getPervTargetInstance())); + } + } + + /// Address may be of a chip, let it pass through + return (!l_scom.isValid()); + } + + uint32_t p10_scominfo_fixChipUnitScomAddrOrTarget(const p10ChipUnits_t i_p10CU, + const uint8_t i_ecLevel, + const uint32_t i_targetChipUnitNum, + const uint64_t i_scomaddr, + uint64_t& o_modifiedScomAddr, + p10ChipUnits_t& o_p10CU, + uint32_t& o_modifiedChipUnitNum, + const uint32_t i_mode) + { + uint32_t rc = 0; + + o_modifiedScomAddr = i_scomaddr; + o_p10CU = i_p10CU; + o_modifiedChipUnitNum = i_targetChipUnitNum; + + return rc; + } + + //################################################################################ + uint8_t validateChipUnitNum(const uint8_t i_chipUnitNum, + const p10ChipUnits_t i_chipUnitType) + { + uint8_t l_rc = 0; + uint8_t l_index; + + for (l_index = 0; + l_index < (sizeof(ChipUnitDescriptionTable) / sizeof(p10_chipUnitDescription_t)); + l_index++) + { + // Looking for input chip unit type in table + if (i_chipUnitType == ChipUnitDescriptionTable[l_index].enumVal) + { + // Found a match, check input i_chipUnitNum to be <= max chip unit num + // for this unit type + if (i_chipUnitNum > ChipUnitDescriptionTable[l_index].maxChipUnitNum) + { + l_rc = 1; + } + + // Additional check for PERV targets, where there are gaps between instances + else if (i_chipUnitType == PU_PERV_CHIPUNIT) + { + // Note: We allow content in chiplet ID = 0x00 to be referenced with a perv target instance, + // so do not check for instance = 0 here. + if ( ((i_chipUnitNum > 3) && (i_chipUnitNum < 8)) || + ((i_chipUnitNum > 9) && (i_chipUnitNum < 12)) || + ((i_chipUnitNum > 19) && (i_chipUnitNum < 24)) ) + { + l_rc = 1; + } + } + + // Additional check for PAU targets, where instance 1 and 2 are not valid + else if (i_chipUnitType == PU_PAU_CHIPUNIT) + { + if ( (i_chipUnitNum == 1) || (i_chipUnitNum == 2) ) + { + l_rc = 1; + } + } + + break; + } + } + + // Can't find i_chipUnitType in table + if ( l_index >= (sizeof(ChipUnitDescriptionTable) / sizeof(p10_chipUnitDescription_t)) ) + { + l_rc = 1; + } + + return (l_rc); + } + +} // extern "C" + +#undef P10_SCOMINFO_C diff --git a/src/tests/p10_scominfo.H b/src/tests/p10_scominfo.H new file mode 100644 index 0000000..2075d08 --- /dev/null +++ b/src/tests/p10_scominfo.H @@ -0,0 +1,89 @@ +/// +/// @file p10_scominfo.H +/// @brief P10 chip unit SCOM address platform translation code +/// +/// HWP HW Maintainer: Thi Tran +/// HWP FW Maintainer: +/// HWP Consumed by: Cronus, HB, HWSV +/// + +#ifndef P10_SCOMINFO_H +#define P10_SCOMINFO_H + +// includes +#include +#include +#include "p10_cu.H" + +extern "C" +{ + // Modes of translation + typedef enum + { + P10_DEFAULT_MODE = 0, // Default platform behavior + P10_ENGD_BUILD_MODE = 1, // Apply customization for ENGD build + } p10TranslationMode_t; + + typedef enum + { + FAILED_TRANSLATION = 0xFFFFFFFFFFFFFFF1ull + } p10TranslationResult_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_p10CU Enumeration of the chip unit type + /// @param[in] i_ecLevel Chip EC level represented in HEX digit value. Example: i_ecLevel = 0x12 --> EC level 1.2 + /// @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 Translation mode, specifying different addr translation methods. + /// @retval uint64_t Actual SCOM address for the chip unit instance passed in + uint64_t p10_scominfo_createChipUnitScomAddr(const p10ChipUnits_t i_p10CU, + const uint8_t i_ecLevel, + 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_p10CU Enumeration of the chip unit type + /// @param[in] i_ecLevel Chip EC level represented in HEX digit value. Example: i_ecLevel = 0x12 --> EC level 1.2 + /// @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 Translation mode, specifying different addr translation methods. + /// @retval uint32_t Return non-zero for error + uint32_t p10_scominfo_isChipUnitScom(const p10ChipUnits_t i_p10CU, + const uint8_t i_ecLevel, + const uint64_t i_scomAddr, + bool& o_chipUnitRelated, + std::vector& o_chipUnitPairing, + const p10TranslationMode_t i_mode = P10_DEFAULT_MODE); + + /// @brief Alter the unit/unitnum of a target for spys where the clocks-on vs clocks-off targets are different. + /// @param[in] i_p10CU Target used for the spy request + /// @param[in] i_ecLevel Chip EC level represented in HEX digit value. Example: i_ecLevel = 0x12 --> EC level 1.2 + /// @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_p10CU The translated target type + /// @param[out] o_modifiedChipUnitNum The translated target instance number + /// @param[in] i_mode Translation mode, specifying different addr translation methods. + /// @retval uint32_t Return non-zero for error + uint32_t p10_scominfo_fixChipUnitScomAddrOrTarget(const p10ChipUnits_t i_p10CU, + const uint8_t i_ecLevel, + const uint32_t i_targetChipUnitNum, + const uint64_t i_scomaddr, + uint64_t& o_modifiedScomAddr, + p10ChipUnits_t& o_p10CU, + uint32_t& o_modifiedChipUnitNum, + const uint32_t i_mode = 0); + + /// @brief Validate the chip unit number to be within range + /// of a chip unit type. + /// @param[in] i_chipUnitNum Value of chip unit number (instance) + /// @param[in] i_chipUnitType Chip unit type + /// @retval Non-zero if error + uint8_t validateChipUnitNum(const uint8_t i_chipUnitNum, + const p10ChipUnits_t i_chipUnitType); + +} // extern "C" + +#endif /* P10_SCOMINFO_H */