Add plugin function for PLL unlock clock callouts
Change-Id: Ic0e9c9d7fee7afb5a6534266ab011d9d41d9ca48
Signed-off-by: Zane Shelley <zshelle@us.ibm.com>
diff --git a/analyzer/plugins/p10-plugins.cpp b/analyzer/plugins/p10-plugins.cpp
index dd14457..7e20d2d 100644
--- a/analyzer/plugins/p10-plugins.cpp
+++ b/analyzer/plugins/p10-plugins.cpp
@@ -1,5 +1,7 @@
#include <analyzer/plugins/plugin.hpp>
+#include <hei_util.hpp>
+#include <util/pdbg.hpp>
#include <util/trace.hpp>
namespace analyzer
@@ -17,10 +19,44 @@
* clock, the clock is called out with high priority. Otherwise, the clock
* callout priority is medium.
*/
-void pll_unlock(unsigned int i_instance, const libhei::Chip&, ServiceData&)
+void pll_unlock(unsigned int i_instance, const libhei::Chip&,
+ ServiceData& io_servData)
{
- // TODO
- trace::inf("pll_unlock plugin: i_instance=%u", i_instance);
+ auto nodeId = libhei::hash<libhei::NodeId_t>("PLL_UNLOCK");
+
+ auto sigList = io_servData.getIsolationData().getSignatureList();
+
+ // The PLL list is initially the same size of the signature list.
+ std::vector<libhei::Signature> pllList{sigList.size()};
+
+ // Copy all signatures that match the node ID and bit position. Note that
+ // in this case the bit position is the same as the plugin instance.
+ auto itr = std::copy_if(sigList.begin(), sigList.end(), pllList.begin(),
+ [&nodeId, &i_instance](const auto& s) {
+ return (nodeId == s.getId() &&
+ i_instance == s.getBit());
+ });
+
+ // Shrink the size of the PLL list if necessary.
+ pllList.resize(std::distance(pllList.begin(), itr));
+
+ // The clock callout priority is dependent on the number of chips with PLL
+ // unlock attentions.
+ auto clockPriority =
+ (1 < pllList.size()) ? callout::Priority::HIGH : callout::Priority::MED;
+
+ // Callout the clock.
+ auto clockCallout = (0 == i_instance) ? callout::ClockType::OSC_REF_CLOCK_0
+ : callout::ClockType::OSC_REF_CLOCK_1;
+ io_servData.calloutClock(clockCallout, clockPriority, true);
+
+ // Callout the processors connected to this clock that are reporting PLL
+ // unlock attentions. Always a medium callout and no guarding.
+ for (const auto& sig : pllList)
+ {
+ io_servData.calloutTarget(util::pdbg::getTrgt(sig.getChip()),
+ callout::Priority::MED, false);
+ }
}
} // namespace P10
diff --git a/analyzer/ras-data/data/ras-data-p10-10.json b/analyzer/ras-data/data/ras-data-p10-10.json
index d31ddc5..3c8f88c 100644
--- a/analyzer/ras-data/data/ras-data-p10-10.json
+++ b/analyzer/ras-data/data/ras-data-p10-10.json
@@ -936,12 +936,10 @@
{ "type": "action", "name": "self_L" }
],
"pll_unlock_0": [
- { "type": "plugin", "name": "pll_unlock", "instance": 0 },
- { "type": "callout_self", "priority": "MED", "guard": false }
+ { "type": "plugin", "name": "pll_unlock", "instance": 0 }
],
"pll_unlock_1": [
- { "type": "plugin", "name": "pll_unlock", "instance": 1 },
- { "type": "callout_self", "priority": "MED", "guard": false }
+ { "type": "plugin", "name": "pll_unlock", "instance": 1 }
],
"pcb_slave_parity": [
{ "type": "action", "name": "self_H" }
diff --git a/analyzer/ras-data/data/ras-data-p10-20.json b/analyzer/ras-data/data/ras-data-p10-20.json
index 8ed5f00..a9dc314 100644
--- a/analyzer/ras-data/data/ras-data-p10-20.json
+++ b/analyzer/ras-data/data/ras-data-p10-20.json
@@ -936,12 +936,10 @@
{ "type": "action", "name": "self_L" }
],
"pll_unlock_0": [
- { "type": "plugin", "name": "pll_unlock", "instance": 0 },
- { "type": "callout_self", "priority": "MED", "guard": false }
+ { "type": "plugin", "name": "pll_unlock", "instance": 0 }
],
"pll_unlock_1": [
- { "type": "plugin", "name": "pll_unlock", "instance": 1 },
- { "type": "callout_self", "priority": "MED", "guard": false }
+ { "type": "plugin", "name": "pll_unlock", "instance": 1 }
],
"pcb_slave_parity": [
{ "type": "action", "name": "self_H" }
diff --git a/test/meson.build b/test/meson.build
index 81ca2e2..45c5749 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -38,9 +38,11 @@
'bin_stream_test',
'ffdc_file_test',
'resolution_test',
+ 'test-pll-unlock',
]
analyzer_src = files(
+ '../analyzer/plugins/p10-plugins.cpp',
'../analyzer/service_data.cpp',
'../analyzer/resolution.cpp',
)
diff --git a/test/test-pll-unlock.cpp b/test/test-pll-unlock.cpp
new file mode 100644
index 0000000..c09bf90
--- /dev/null
+++ b/test/test-pll-unlock.cpp
@@ -0,0 +1,149 @@
+#include <stdio.h>
+
+#include <analyzer/plugins/plugin.hpp>
+#include <hei_util.hpp>
+#include <util/pdbg.hpp>
+#include <util/trace.hpp>
+
+#include "gtest/gtest.h"
+
+using namespace analyzer;
+
+static const auto nodeId =
+ static_cast<libhei::NodeId_t>(libhei::hash<libhei::NodeId_t>("PLL_UNLOCK"));
+
+// Sub-test #1 - single PLL unlock attention on proc 1, clock 1
+TEST(PllUnlock, TestSet1)
+{
+ pdbg_targets_init(nullptr);
+
+ libhei::Chip chip1{util::pdbg::getTrgt("/proc1"), P10_20};
+
+ libhei::Signature sig11{chip1, nodeId, 0, 1, libhei::ATTN_TYPE_CHECKSTOP};
+
+ auto plugin = PluginMap::getSingleton().get(chip1.getType(), "pll_unlock");
+
+ libhei::IsolationData isoData{};
+ isoData.addSignature(sig11);
+ ServiceData sd{sig11, AnalysisType::SYSTEM_CHECKSTOP, isoData};
+
+ // Call the PLL unlock plugin.
+ plugin(1, chip1, sd);
+
+ nlohmann::json j{};
+ std::string s{};
+
+ // Callout list
+ j = sd.getCalloutList();
+ s = R"([
+ {
+ "Deconfigured": false,
+ "Guarded": false,
+ "LocationCode": "P0",
+ "Priority": "M"
+ },
+ {
+ "Deconfigured": false,
+ "Guarded": false,
+ "LocationCode": "/proc1",
+ "Priority": "M"
+ }
+])";
+ EXPECT_EQ(s, j.dump(4));
+
+ // Callout FFDC
+ j = sd.getCalloutFFDC();
+ s = R"([
+ {
+ "Callout Type": "Clock Callout",
+ "Clock Type": "OSC_REF_CLOCK_1",
+ "Priority": "medium"
+ },
+ {
+ "Callout Type": "Hardware Callout",
+ "Guard": false,
+ "Priority": "medium",
+ "Target": "/proc1"
+ }
+])";
+ EXPECT_EQ(s, j.dump(4));
+}
+
+// Sub-test #2 - PLL unlock attention on multiple procs and clocks. Isolating
+// only to proc 1 clock 0 PLL unlock attentions.
+TEST(PllUnlock, TestSet2)
+{
+ pdbg_targets_init(nullptr);
+
+ libhei::Chip chip0{util::pdbg::getTrgt("/proc0"), P10_20};
+ libhei::Chip chip1{util::pdbg::getTrgt("/proc1"), P10_20};
+
+ // PLL unlock signatures for each clock per processor.
+ libhei::Signature sig00{chip0, nodeId, 0, 0, libhei::ATTN_TYPE_CHECKSTOP};
+ libhei::Signature sig01{chip0, nodeId, 0, 1, libhei::ATTN_TYPE_CHECKSTOP};
+ libhei::Signature sig10{chip1, nodeId, 0, 0, libhei::ATTN_TYPE_CHECKSTOP};
+ libhei::Signature sig11{chip1, nodeId, 0, 1, libhei::ATTN_TYPE_CHECKSTOP};
+
+ // Plugins for each processor.
+ auto plugin = PluginMap::getSingleton().get(chip1.getType(), "pll_unlock");
+
+ libhei::IsolationData isoData{};
+ isoData.addSignature(sig00);
+ isoData.addSignature(sig01);
+ isoData.addSignature(sig10);
+ isoData.addSignature(sig11);
+ ServiceData sd{sig10, AnalysisType::SYSTEM_CHECKSTOP, isoData};
+
+ // Call the PLL unlock plugin.
+ plugin(0, chip1, sd);
+
+ nlohmann::json j{};
+ std::string s{};
+
+ // Callout list
+ j = sd.getCalloutList();
+ s = R"([
+ {
+ "Deconfigured": false,
+ "Guarded": false,
+ "LocationCode": "P0",
+ "Priority": "H"
+ },
+ {
+ "Deconfigured": false,
+ "Guarded": false,
+ "LocationCode": "/proc0",
+ "Priority": "M"
+ },
+ {
+ "Deconfigured": false,
+ "Guarded": false,
+ "LocationCode": "/proc1",
+ "Priority": "M"
+ }
+])";
+ EXPECT_EQ(s, j.dump(4));
+
+ // Callout FFDC
+ j = sd.getCalloutFFDC();
+ s = R"([
+ {
+ "Callout Type": "Clock Callout",
+ "Clock Type": "OSC_REF_CLOCK_0",
+ "Priority": "high"
+ },
+ {
+ "Callout Type": "Hardware Callout",
+ "Guard": false,
+ "Priority": "medium",
+ "Target": "/proc0"
+ },
+ {
+ "Callout Type": "Hardware Callout",
+ "Guard": false,
+ "Priority": "medium",
+ "Target": "/proc1"
+ }
+])";
+ EXPECT_EQ(s, j.dump(4));
+}