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