1 2 #include <analyzer/plugins/plugin.hpp> 3 #include <hei_util.hpp> 4 #include <util/pdbg.hpp> 5 #include <util/trace.hpp> 6 7 namespace analyzer 8 { 9 10 namespace Ody 11 { 12 13 /** 14 * @brief Adds all chips in the OCMB PLL domain with active PLL unlock 15 * attentions to the callout list. 16 * 17 * An OCMB PLL domain is scoped to just the OCMBs under the same processor chip. 18 * If more than one OCMB within the PLL domain is reporting a PLL unlock 19 * attention, the clock source (the processor) is called out with high priority 20 * and all connected OCMBs are called out with low priority. Otherwise, single 21 * OCMB is called out high and the connected processor low. 22 */ 23 void pll_unlock(unsigned int, const libhei::Chip& i_ocmbChip, 24 ServiceData& io_servData) 25 { 26 using namespace util::pdbg; 27 28 auto nodeId = libhei::hash<libhei::NodeId_t>("PLL_UNLOCK"); 29 30 auto sigList = io_servData.getIsolationData().getSignatureList(); 31 32 // The PLL list is initially the same size of the signature list. 33 std::vector<libhei::Signature> pllList{sigList.size()}; 34 35 // Copy all signatures PLL signatures that match the node ID and parent 36 // processor chip. 37 auto procTrgt = getParentProcessor(getTrgt(i_ocmbChip)); 38 auto itr = std::copy_if(sigList.begin(), sigList.end(), pllList.begin(), 39 [&nodeId, &procTrgt](const auto& s) { 40 return (nodeId == s.getId() && 41 procTrgt == getParentProcessor(getTrgt(s.getChip()))); 42 }); 43 44 // Shrink the size of the PLL list if necessary. 45 pllList.resize(std::distance(pllList.begin(), itr)); 46 47 // There should be at list one signature in the list. 48 if (0 == pllList.size()) 49 { 50 throw std::logic_error("Expected at least one PLL unlock signature. " 51 "i_ocmbChip=" + 52 std::string{getPath(i_ocmbChip)}); 53 } 54 55 // The hardware callouts will be all OCMBs with PLL unlock attentions and 56 // the connected processor chip. The callout priorities are dependent on the 57 // number of chips at attention. 58 if (1 == pllList.size()) 59 { 60 // There is only one OCMB chip with a PLL unlock. So, the error is 61 // likely in the OCMB. 62 io_servData.calloutTarget(getTrgt(pllList.front().getChip()), 63 callout::Priority::HIGH, true); 64 io_servData.calloutTarget(procTrgt, callout::Priority::LOW, false); 65 } 66 else 67 { 68 // There are more than one OCMB chip with a PLL unlock. So, the error is 69 // likely the clock source, which is the processor. 70 io_servData.calloutTarget(procTrgt, callout::Priority::HIGH, true); 71 for (const auto& sig : pllList) 72 { 73 io_servData.calloutTarget(getTrgt(sig.getChip()), 74 callout::Priority::LOW, false); 75 } 76 } 77 } 78 79 } // namespace Ody 80 81 PLUGIN_DEFINE_NS(ODYSSEY_10, Ody, pll_unlock); 82 83 } // namespace analyzer 84