From c05531edb86a043d4afd9d98ae83b961857be8dc Mon Sep 17 00:00:00 2001 From: Eric Buschmann <eric.buschmann@cern.ch> Date: Mon, 24 Jun 2024 23:43:21 +0000 Subject: [PATCH 01/23] Return results from selftest --- models/board_id.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/board_id.py b/models/board_id.py index abe68ca..bfc9063 100644 --- a/models/board_id.py +++ b/models/board_id.py @@ -66,7 +66,7 @@ class BoardID(SelfTestExecutor): def self_test_main(self, **kwargs): - self.get_board_info() + return self.get_board_info() def self_test_check_result(self, result): -- GitLab From 8a2472c1c074a1d9d811172d2b2a88329836ee78 Mon Sep 17 00:00:00 2001 From: Carlo Alberto Gottardo <carlo.alberto.gottardo@cern.ch> Date: Thu, 18 Jul 2024 16:07:33 +0200 Subject: [PATCH 02/23] read limits for LTM4700 and TMP435 --- boards/flx182.py | 8 +++++++- templates/sysmon.html | 20 +++++++++++++++++--- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/boards/flx182.py b/boards/flx182.py index fb3b38a..c0c6693 100644 --- a/boards/flx182.py +++ b/boards/flx182.py @@ -61,9 +61,14 @@ config = { "title" : "LTM4700", "patterns" : { "voltage" : "(?P<name>in\\d+_input)", + "voltage_min" : "(?P<name>in\\d+_min)(?!_alarm)", + "voltage_max" : "(?P<name>in\\d+_max)(?!_alarm)", + "voltage_crit" : "(?P<name>in\\d+_crit)(?!_alarm)", "current" : "(?P<name>curr\\d+_input)", - "temp" : "(?P<name>temp\\d+_input)", + "current_max" : "(?P<name>curr\\d+_max)(?!_alarm)", "power" : "(?P<name>power\\d+_input)", + "temp" : "(?P<name>temp\\d+_input)", + "temp_max" : "(?P<name>temp\\d+_crit)(?!_alarm)", }, }, @@ -72,6 +77,7 @@ config = { "title" : "TMP435", "patterns" : { "probe" : "(?P<name>temp\\d+_input)", + "max" : "(?P<name>temp\\d+_crit)(?!_alarm)(?!_hyst)", }, "self_test" : { "description" : "TMP435 readout", diff --git a/templates/sysmon.html b/templates/sysmon.html index a06c9c9..ff87d15 100644 --- a/templates/sysmon.html +++ b/templates/sysmon.html @@ -10,7 +10,9 @@ <tr> <th scope="col">Sensor</th> <th scope="col">Local temperature [deg C]</th> + <th scope="col">Max [deg C]</th> <th scope="col">Probe temperature [deg C]</th> + <th scope="col">Max [deg C]</th> </tr> </thead> <tbody> @@ -19,7 +21,9 @@ <tr> <th scope="row">{{device_data['name']}}</th> <td>{{ "{:.3f}".format(device_data["probe"]['temp1_input'] / 1000) }} </td> + <td>{{ "{:.3f}".format(device_data["max"]['temp1_crit'] / 1000) }} </td> <td>{{ "{:.3f}".format(device_data["probe"]['temp2_input'] / 1000) }} </td> + <td>{{ "{:.3f}".format(device_data["max"]['temp2_crit'] / 1000) }} </td> </tr> {% endfor %} @@ -37,7 +41,9 @@ <tr> <th scope="col">Sensor</th> <th scope="col">Voltage [V]</th> + <th scope="col">Range [V]</th> <th scope="col">Current [A]</th> + <th scope="col">Max [A]</th> <th scope="col">Power [W]</th> <th scope="col">Temperature [deg C]</th> </tr> @@ -49,13 +55,17 @@ <td></td> <td></td> <td></td> + <td></td> + <td></td> <td>{{ "{:.3f}".format(device_data["temp"]['temp3_input'] / 1000) }}</td> </tr> <tr> - <th scope="row">Input</th> + <th scope="row">INPUT</th> <td>{{ "{:.3f}".format(device_data["voltage"]['in1_input'] / 1000) }} </td> + <td>{{ "[{:.3f}, {:.3f}]".format(device_data["voltage_min"]['in1_min'] / 1000, device_data["voltage_crit"]['in1_crit'] / 1000) }} </td> <td>{{ "{:.3f}".format(device_data["current"]['curr1_input'] / 1000) }} </td> + <td>{{ "{:.3f}".format(device_data["current_max"]['curr1_max'] / 1000) }} </td> <td>{{ "{:.3f}".format(device_data["power"]['power1_input'] / 1e6) }} </td> <td></td> </tr> @@ -63,7 +73,9 @@ <tr> <th scope="row">OUT1</th> <td>{{ "{:.3f}".format(device_data["voltage"]['in2_input'] / 1000) }} </td> + <td>{{ "[{:.3f}, {:.3f}]".format(device_data["voltage_min"]['in2_min'] / 1000, device_data["voltage_max"]['in2_max'] / 1000) }} </td> <td>{{ "{:.3f}".format(device_data["current"]['curr2_input'] / 1000) }} </td> + <td>{{ "{:.3f}".format(device_data["current_max"]['curr2_max'] / 1000) }} </td> <td>{{ "{:.3f}".format(device_data["power"]['power2_input'] / 1e6) }} </td> <td>{{ "{:.3f}".format(device_data["temp"]['temp1_input'] / 1000) }} </td> </tr> @@ -71,7 +83,9 @@ <tr> <th scope="row">OUT2</th> <td>{{ "{:.3f}".format(device_data["voltage"]['in3_input'] / 1000) }} </td> + <td>{{ "[{:.3f}, {:.3f}]".format(device_data["voltage_min"]['in3_min'] / 1000, device_data["voltage_max"]['in3_max'] / 1000) }} </td> <td>{{ "{:.3f}".format(device_data["current"]['curr3_input'] / 1000) }} </td> + <td>{{ "{:.3f}".format(device_data["current_max"]['curr3_max'] / 1000) }} </td> <td>{{ "{:.3f}".format(device_data["power"]['power3_input'] / 1e6) }} </td> <td>{{ "{:.3f}".format(device_data["temp"]['temp2_input'] / 1000) }} </td> </tr> @@ -120,7 +134,7 @@ </thead> <tbody> - {% for name, value in device_data['temperature'].items() | sort %} + {% for name, value in device_data['temperature'].items() | sort %} <tr> <th scope="row">{{name}}</th> <td>{{ "{:.1f}".format(value) }} C</td> @@ -143,7 +157,7 @@ </thead> <tbody> - {% for name, value in device_data['voltage'].items() | sort %} + {% for name, value in device_data['voltage'].items() | sort %} <tr> <th scope="row">{{name}}</th> <td>{{ "{:.3f}".format(value) }} V</td> -- GitLab From b471693f987e1c7e3bf8c4c9c59ddfdfd314acd3 Mon Sep 17 00:00:00 2001 From: Carlo Alberto Gottardo <carlo.alberto.gottardo@cern.ch> Date: Thu, 18 Jul 2024 18:22:29 +0200 Subject: [PATCH 03/23] Limits and tolerance for INA226 --- boards/flx182.py | 12 ++++++++++++ models/ina226.py | 27 +++++++++++++++++++++------ templates/ina226.html | 14 ++++++++++---- 3 files changed, 43 insertions(+), 10 deletions(-) diff --git a/boards/flx182.py b/boards/flx182.py index c0c6693..0d80996 100644 --- a/boards/flx182.py +++ b/boards/flx182.py @@ -39,6 +39,18 @@ config = { "name" : "ina226", "self_test" : { "description" : "INA226 chip readout", + }, + "reference" : { + "12P0V" : {"V" : 12.00, "V_tolerance" : 0.03, "I" : 12.00, "I_max" : 1.0}, + "MGTAVCC" : {"V" : 0.88 , "V_tolerance" : 0.03, "I" : 0.88 , "I_max" : 3.5}, + "MGTAVTT" : {"V" : 1.20 , "V_tolerance" : 0.03, "I" : 1.20 , "I_max" : 6.5}, + "SYS12" : {"V" : 1.20 , "V_tolerance" : 0.03, "I" : 1.20 , "I_max" : 4.1}, + "SYS15" : {"V" : 1.50 , "V_tolerance" : 0.03, "I" : 1.50 , "I_max" : 1.6}, + "SYS18" : {"V" : 1.80 , "V_tolerance" : 0.03, "I" : 1.80 , "I_max" : 1.5}, + "SYS25" : {"V" : 2.50 , "V_tolerance" : 0.03, "I" : 2.50 , "I_max" : 0.5}, + "SYS33" : {"V" : 3.30 , "V_tolerance" : 0.03, "I" : 3.30 , "I_max" : 6.0}, + "SYS38" : {"V" : 3.80 , "V_tolerance" : 0.03, "I" : 3.80 , "I_max" : 1.0}, + "VCCINT" : {"V" : 0.80 , "V_tolerance" : 0.03, "I" : 0.80 , "I_max" : 50.0} } }, diff --git a/models/ina226.py b/models/ina226.py index a6e7df6..d018ecb 100644 --- a/models/ina226.py +++ b/models/ina226.py @@ -11,7 +11,7 @@ class INA226(SelfTestExecutor): self.config = config self.device_path = config["device_path"] self.name = config["name"] - self.devices = get_devices(self.device_path, self.name) + self.devices = get_devices(self.device_path, self.name) # returns hashmap of all readings available for this device @@ -34,12 +34,27 @@ class INA226(SelfTestExecutor): print(err) return {} + voltage = v1_raw * v1_scale / 1000.0 + current = i3_raw * i3_scale / 1000.0 + power = p2_raw * p2_scale / 1000.0 + V_dev = -1 + V_tol = -1 + I_max = -1 + + if label in self.config["reference"]: + rail = self.config["reference"][label] + V_dev = (voltage - rail["V"]) / rail["V"] + V_tol = self.config["reference"][label]["V_tolerance"] + I_max = self.config["reference"][label]["I_max"] + data = { - "V0" : v0_raw * v0_scale, - "V1" : v1_raw * v1_scale, - "P2" : p2_raw * p2_scale, - "I3" : i3_raw * i3_scale, - "R_shunt" : r_shunt + "V" : voltage, + "Vdev" : V_dev, + "Vtol" : V_tol, + "I" : current, + "Imax" : I_max, + "P" : power, + "R_shunt" : r_shunt / 1000.0 } return data, label diff --git a/templates/ina226.html b/templates/ina226.html index bf30a7e..744d0dd 100644 --- a/templates/ina226.html +++ b/templates/ina226.html @@ -9,7 +9,10 @@ <tr> <th scope="col">Name</th> <th scope="col">VCC [V]</th> + <th scope="col">VCC deviation [%]</th> + <th scope="col">VCC tolerance [%]</th> <th scope="col">I [A]</th> + <th scope="col">I max [A]</th> <th scope="col">P [W]</th> <th scope="col">R_sh [mOhm]</th> </tr> @@ -19,10 +22,13 @@ {% for label, device in data.items() | sort %} <tr> <th scope="row">{{ label }}</th> - <td>{{ "{:.3f}".format(device["V1"] / 1000) }}</td> - <td>{{ "{:.3f}".format(device["I3"] / 1000) }}</td> - <td>{{ "{:.3f}".format(device["P2"] / 1000) }}</td> - <td>{{ "{:.3f}".format(device["R_shunt"] * 1000) }}</td> + <td>{{ "{:.3f}".format(device["V"]) }}</td> + <td>{{ "{:.3f}".format(device["Vdev"]) }}</td> + <td>{{ "{:.3f}".format(device["Vtol"]) }}</td> + <td>{{ "{:.3f}".format(device["I"]) }}</td> + <td>{{ "{:.3f}".format(device["Imax"]) }}</td> + <td>{{ "{:.3f}".format(device["P"]) }}</td> + <td>{{ "{:.3f}".format(device["R_shunt"]) }}</td> </tr> {% endfor %} -- GitLab From 025659017f0d5fdc4fc8eaf6be5af84d22ed57a4 Mon Sep 17 00:00:00 2001 From: Carlo Alberto Gottardo <carlo.alberto.gottardo@cern.ch> Date: Fri, 19 Jul 2024 18:21:34 +0200 Subject: [PATCH 04/23] Added hwmon limits from Xilinx document. --- boards/flx182.py | 83 ++++++++++++++++++++++++++++++++++++++++++++++-- models/sysmon.py | 13 ++++++-- 2 files changed, 91 insertions(+), 5 deletions(-) diff --git a/boards/flx182.py b/boards/flx182.py index 0d80996..b26c36a 100644 --- a/boards/flx182.py +++ b/boards/flx182.py @@ -40,6 +40,7 @@ config = { "self_test" : { "description" : "INA226 chip readout", }, + #tolerance and max current set by hand "reference" : { "12P0V" : {"V" : 12.00, "V_tolerance" : 0.03, "I" : 12.00, "I_max" : 1.0}, "MGTAVCC" : {"V" : 0.88 , "V_tolerance" : 0.03, "I" : 0.88 , "I_max" : 3.5}, @@ -66,6 +67,74 @@ config = { "voltage" : "in_voltage(?P<id>\\d+)_(?P<name>.+)_input", "temperature" : "in_temp(?P<id>\\d+)_(?P<name>.+)_input", }, + "reference" : { + # Reference Versal Prime Series Data Sheet: DC and AC Switching Characteristics + # DS956 2024-04-30 + # Table: Recommended Operating Conditions + "max_max" : {"nominal" : 36, "min" : 0, "max" : 100, "source" : "N/A"}, + "temp" : {"nominal" : 36, "min" : 0, "max" : 100, "source" : "N/A"}, + "gty_avcc_103" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, + "gty_avcc_104" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, + "gty_avcc_105" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, + "gty_avcc_106" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, + "gty_avcc_200" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, + "gty_avcc_201" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, + "gty_avcc_202" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, + "gty_avcc_203" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, + "gty_avcc_204" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, + "gty_avcc_205" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, + "gty_avcc_206" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, + "gty_avccaux_103" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, + "gty_avccaux_104" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, + "gty_avccaux_105" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, + "gty_avccaux_106" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, + "gty_avccaux_200" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, + "gty_avccaux_201" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, + "gty_avccaux_202" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, + "gty_avccaux_203" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, + "gty_avccaux_204" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, + "gty_avccaux_205" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, + "gty_avccaux_206" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, + "gty_avtt_103" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, + "gty_avtt_104" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, + "gty_avtt_105" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, + "gty_avtt_106" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, + "gty_avtt_200" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, + "gty_avtt_201" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, + "gty_avtt_202" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, + "gty_avtt_203" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, + "gty_avtt_204" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, + "gty_avtt_205" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, + "gty_avtt_206" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, + "vcc_batt" : {"nominal" : 0, "min" : 1.200, "max" : 1.500, "source" : "DS956", "desc" : "Battery power supply"}, + "vcc_pmc" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "PMC primary power supply, mid (M) voltage"}, + "vcc_psfp" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "PS full-power domain power supply, mid (M) voltage"}, + "vcc_pslp" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "PS low-power domain power supply, mid (M) voltage"}, + "vcc_ram" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "PL RAM and clocking network" }, + "vcc_soc" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "Network on Chip (NoC) and DDR memory controller power supply"}, + "vccaux" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "Auxiliary power supply "}, + "vccaux_pmc" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "PMC auxiliary power supply voltage"}, + "vccaux_smon" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "PMC system monitor power supply relative to GND_SMON"}, + "vccint" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "PL primary power supply"}, + "vcco_306" : {"nominal" : 1.800, "min" : 1.710, "max" : 3.400, "source" : "DS956", "desc" : "HDIO bank 3 output driver"}, + "vcco_406" : {"nominal" : 1.800, "min" : 1.710, "max" : 3.400, "source" : "DS956", "desc" : "HDIO bank 4 output driver"}, + "vcco_500" : {"nominal" : 1.800, "min" : 1.710, "max" : 3.400, "source" : "DS956", "desc" : "PSIO bank 5 power supply"}, + "vcco_501" : {"nominal" : 1.800, "min" : 1.710, "max" : 3.400, "source" : "DS956", "desc" : "PSIO bank 5 power supply"}, + "vcco_502" : {"nominal" : 1.800, "min" : 1.710, "max" : 3.400, "source" : "DS956", "desc" : "PSIO bank 5 power supply"}, + "vcco_503" : {"nominal" : 1.800, "min" : 1.710, "max" : 3.400, "source" : "DS956", "desc" : "PSIO bank 5 power supply"}, + "vcco_700" : {"nominal" : 1.200, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, + "vcco_701" : {"nominal" : 1.200, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, + "vcco_702" : {"nominal" : 1.500, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, + "vcco_703" : {"nominal" : 1.200, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, + "vcco_704" : {"nominal" : 1.200, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, + "vcco_705" : {"nominal" : 1.200, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, + "vcco_706" : {"nominal" : 1.500, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, + "vcco_707" : {"nominal" : 1.500, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, + "vcco_708" : {"nominal" : 1.500, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, + "vcco_709" : {"nominal" : 1.200, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, + "vcco_710" : {"nominal" : 1.200, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, + "vcco_711" : {"nominal" : 1.200, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"} + } }, "ltm4700" : { @@ -82,7 +151,7 @@ config = { "temp" : "(?P<name>temp\\d+_input)", "temp_max" : "(?P<name>temp\\d+_crit)(?!_alarm)", }, - }, + }, #end of ltm4700 "tmp435" : { "device_path" : "/sys/class/hwmon/", @@ -93,6 +162,16 @@ config = { }, "self_test" : { "description" : "TMP435 readout", + }, + #max temp by common sense + "reference" : { + "MGTAVCC_TMP" : {"max" : 50.0 }, + "MGTAVTT_TMP" : {"max" : 50.0 }, + "SYS12_TMP" : {"max" : 50.0 }, + "SYS15_TMP" : {"max" : 50.0 }, + "SYS18_TMP" : {"max" : 50.0 }, + "SYS25_TMP" : {"max" : 50.0 }, + "SYS33_TMP" : {"max" : 50.0 }, } }, @@ -105,7 +184,7 @@ config = { }, }, "self_test" : { - "description" : "HWMON device readout (SYSMON, TMP435, etc)", + "description" : "HWMON device readout (SYSMON, LTM4700, TMP435, etc)", } }, diff --git a/models/sysmon.py b/models/sysmon.py index 5c3b60c..208e9a3 100644 --- a/models/sysmon.py +++ b/models/sysmon.py @@ -55,7 +55,7 @@ class SYSMON(SelfTestExecutor): # read temperature, voltage, current, etc of a single device of specific class - def read_device(self, device_path, compiled_patterns): + def read_device(self, device_path, compiled_patterns): result = {} file_names = listdir(device_path) for pattern_name, pattern in compiled_patterns.items(): @@ -74,7 +74,14 @@ class SYSMON(SelfTestExecutor): return {"error" : f"Can't access HWMON device: {device_class}"} class_config = self.config["device_classes"][device_class] - compiled_patterns = compile_patterns(class_config["patterns"]) + compiled_patterns = compile_patterns(class_config["patterns"]) + + #read reference values if available + #if "reference" in class_config: + # references = class_config["reference"] + #else: + # references = {} + result = { "title" : class_config["title"], "class" : device_class, @@ -83,7 +90,7 @@ class SYSMON(SelfTestExecutor): # read all devices of the requested class # device is folder path to IIO device, e.g. "/sys/bus/iio/devices/iio:device4" - for device_path in devices: + for device_path in devices: result["devices"][device_path] = self.read_device(device_path, compiled_patterns) result["devices"][device_path]["name"] = get_name(device_path) -- GitLab From 249c3a05a67e34ee572161310e310febafcfe3b7 Mon Sep 17 00:00:00 2001 From: Carlo Alberto Gottardo <carlo.alberto.gottardo@cern.ch> Date: Mon, 22 Jul 2024 18:10:34 +0200 Subject: [PATCH 05/23] same limit format for LTM4700, TMP and SYSMON --- boards/flx182.py | 147 ++++++++++++++++++++++-------------------- models/sysmon.py | 94 ++++++++++++++++++++++++--- templates/sysmon.html | 67 ++++++++++--------- 3 files changed, 195 insertions(+), 113 deletions(-) diff --git a/boards/flx182.py b/boards/flx182.py index b26c36a..cfd206b 100644 --- a/boards/flx182.py +++ b/boards/flx182.py @@ -71,69 +71,73 @@ config = { # Reference Versal Prime Series Data Sheet: DC and AC Switching Characteristics # DS956 2024-04-30 # Table: Recommended Operating Conditions - "max_max" : {"nominal" : 36, "min" : 0, "max" : 100, "source" : "N/A"}, - "temp" : {"nominal" : 36, "min" : 0, "max" : 100, "source" : "N/A"}, - "gty_avcc_103" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, - "gty_avcc_104" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, - "gty_avcc_105" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, - "gty_avcc_106" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, - "gty_avcc_200" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, - "gty_avcc_201" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, - "gty_avcc_202" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, - "gty_avcc_203" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, - "gty_avcc_204" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, - "gty_avcc_205" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, - "gty_avcc_206" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, - "gty_avccaux_103" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, - "gty_avccaux_104" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, - "gty_avccaux_105" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, - "gty_avccaux_106" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, - "gty_avccaux_200" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, - "gty_avccaux_201" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, - "gty_avccaux_202" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, - "gty_avccaux_203" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, - "gty_avccaux_204" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, - "gty_avccaux_205" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, - "gty_avccaux_206" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, - "gty_avtt_103" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, - "gty_avtt_104" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, - "gty_avtt_105" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, - "gty_avtt_106" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, - "gty_avtt_200" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, - "gty_avtt_201" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, - "gty_avtt_202" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, - "gty_avtt_203" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, - "gty_avtt_204" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, - "gty_avtt_205" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, - "gty_avtt_206" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, - "vcc_batt" : {"nominal" : 0, "min" : 1.200, "max" : 1.500, "source" : "DS956", "desc" : "Battery power supply"}, - "vcc_pmc" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "PMC primary power supply, mid (M) voltage"}, - "vcc_psfp" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "PS full-power domain power supply, mid (M) voltage"}, - "vcc_pslp" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "PS low-power domain power supply, mid (M) voltage"}, - "vcc_ram" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "PL RAM and clocking network" }, - "vcc_soc" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "Network on Chip (NoC) and DDR memory controller power supply"}, - "vccaux" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "Auxiliary power supply "}, - "vccaux_pmc" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "PMC auxiliary power supply voltage"}, - "vccaux_smon" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "PMC system monitor power supply relative to GND_SMON"}, - "vccint" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "PL primary power supply"}, - "vcco_306" : {"nominal" : 1.800, "min" : 1.710, "max" : 3.400, "source" : "DS956", "desc" : "HDIO bank 3 output driver"}, - "vcco_406" : {"nominal" : 1.800, "min" : 1.710, "max" : 3.400, "source" : "DS956", "desc" : "HDIO bank 4 output driver"}, - "vcco_500" : {"nominal" : 1.800, "min" : 1.710, "max" : 3.400, "source" : "DS956", "desc" : "PSIO bank 5 power supply"}, - "vcco_501" : {"nominal" : 1.800, "min" : 1.710, "max" : 3.400, "source" : "DS956", "desc" : "PSIO bank 5 power supply"}, - "vcco_502" : {"nominal" : 1.800, "min" : 1.710, "max" : 3.400, "source" : "DS956", "desc" : "PSIO bank 5 power supply"}, - "vcco_503" : {"nominal" : 1.800, "min" : 1.710, "max" : 3.400, "source" : "DS956", "desc" : "PSIO bank 5 power supply"}, - "vcco_700" : {"nominal" : 1.200, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, - "vcco_701" : {"nominal" : 1.200, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, - "vcco_702" : {"nominal" : 1.500, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, - "vcco_703" : {"nominal" : 1.200, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, - "vcco_704" : {"nominal" : 1.200, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, - "vcco_705" : {"nominal" : 1.200, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, - "vcco_706" : {"nominal" : 1.500, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, - "vcco_707" : {"nominal" : 1.500, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, - "vcco_708" : {"nominal" : 1.500, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, - "vcco_709" : {"nominal" : 1.200, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, - "vcco_710" : {"nominal" : 1.200, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, - "vcco_711" : {"nominal" : 1.200, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"} + "temperature" : { + "max_max" : {"nominal" : 36, "min" : 0, "max" : 50, "source" : "N/A"}, + "temp" : {"nominal" : 36, "min" : 0, "max" : 50, "source" : "N/A"}, + }, + "voltage" : { + "gty_avcc_103" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, + "gty_avcc_104" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, + "gty_avcc_105" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, + "gty_avcc_106" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, + "gty_avcc_200" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, + "gty_avcc_201" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, + "gty_avcc_202" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, + "gty_avcc_203" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, + "gty_avcc_204" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, + "gty_avcc_205" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, + "gty_avcc_206" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, + "gty_avccaux_103" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, + "gty_avccaux_104" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, + "gty_avccaux_105" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, + "gty_avccaux_106" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, + "gty_avccaux_200" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, + "gty_avccaux_201" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, + "gty_avccaux_202" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, + "gty_avccaux_203" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, + "gty_avccaux_204" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, + "gty_avccaux_205" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, + "gty_avccaux_206" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, + "gty_avtt_103" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, + "gty_avtt_104" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, + "gty_avtt_105" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, + "gty_avtt_106" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, + "gty_avtt_200" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, + "gty_avtt_201" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, + "gty_avtt_202" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, + "gty_avtt_203" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, + "gty_avtt_204" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, + "gty_avtt_205" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, + "gty_avtt_206" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, + "vcc_batt" : {"nominal" : 0, "min" : 1.200, "max" : 1.500, "source" : "DS956", "desc" : "Battery power supply"}, + "vcc_pmc" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "PMC primary power supply, mid (M) voltage"}, + "vcc_psfp" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "PS full-power domain power supply, mid (M) voltage"}, + "vcc_pslp" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "PS low-power domain power supply, mid (M) voltage"}, + "vcc_ram" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "PL RAM and clocking network" }, + "vcc_soc" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "Network on Chip (NoC) and DDR memory controller power supply"}, + "vccaux" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "Auxiliary power supply "}, + "vccaux_pmc" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "PMC auxiliary power supply voltage"}, + "vccaux_smon" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "PMC system monitor power supply relative to GND_SMON"}, + "vccint" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "PL primary power supply"}, + "vcco_306" : {"nominal" : 1.800, "min" : 1.710, "max" : 3.400, "source" : "DS956", "desc" : "HDIO bank 3 output driver"}, + "vcco_406" : {"nominal" : 1.800, "min" : 1.710, "max" : 3.400, "source" : "DS956", "desc" : "HDIO bank 4 output driver"}, + "vcco_500" : {"nominal" : 1.800, "min" : 1.710, "max" : 3.400, "source" : "DS956", "desc" : "PSIO bank 5 power supply"}, + "vcco_501" : {"nominal" : 1.800, "min" : 1.710, "max" : 3.400, "source" : "DS956", "desc" : "PSIO bank 5 power supply"}, + "vcco_502" : {"nominal" : 1.800, "min" : 1.710, "max" : 3.400, "source" : "DS956", "desc" : "PSIO bank 5 power supply"}, + "vcco_503" : {"nominal" : 1.800, "min" : 1.710, "max" : 3.400, "source" : "DS956", "desc" : "PSIO bank 5 power supply"}, + "vcco_700" : {"nominal" : 1.200, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, + "vcco_701" : {"nominal" : 1.200, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, + "vcco_702" : {"nominal" : 1.500, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, + "vcco_703" : {"nominal" : 1.200, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, + "vcco_704" : {"nominal" : 1.200, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, + "vcco_705" : {"nominal" : 1.200, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, + "vcco_706" : {"nominal" : 1.500, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, + "vcco_707" : {"nominal" : 1.500, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, + "vcco_708" : {"nominal" : 1.500, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, + "vcco_709" : {"nominal" : 1.200, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, + "vcco_710" : {"nominal" : 1.200, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, + "vcco_711" : {"nominal" : 1.200, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"} + } } }, @@ -158,20 +162,21 @@ config = { "title" : "TMP435", "patterns" : { "probe" : "(?P<name>temp\\d+_input)", - "max" : "(?P<name>temp\\d+_crit)(?!_alarm)(?!_hyst)", }, "self_test" : { "description" : "TMP435 readout", }, #max temp by common sense "reference" : { - "MGTAVCC_TMP" : {"max" : 50.0 }, - "MGTAVTT_TMP" : {"max" : 50.0 }, - "SYS12_TMP" : {"max" : 50.0 }, - "SYS15_TMP" : {"max" : 50.0 }, - "SYS18_TMP" : {"max" : 50.0 }, - "SYS25_TMP" : {"max" : 50.0 }, - "SYS33_TMP" : {"max" : 50.0 }, + "probe" : { + "MGTAVCC_TMP" : {"min" : 20.0, "nominal" : 40.0, "max" : 60.0 }, + "MGTAVTT_TMP" : {"min" : 20.0, "nominal" : 40.0, "max" : 60.0 }, + "SYS12_TMP" : {"min" : 20.0, "nominal" : 40.0, "max" : 60.0 }, + "SYS15_TMP" : {"min" : 20.0, "nominal" : 40.0, "max" : 60.0 }, + "SYS18_TMP" : {"min" : 20.0, "nominal" : 40.0, "max" : 60.0 }, + "SYS25_TMP" : {"min" : 20.0, "nominal" : 40.0, "max" : 60.0 }, + "SYS33_TMP" : {"min" : 20.0, "nominal" : 40.0, "max" : 60.0 }, + } } }, diff --git a/models/sysmon.py b/models/sysmon.py index 208e9a3..4997df7 100644 --- a/models/sysmon.py +++ b/models/sysmon.py @@ -65,6 +65,7 @@ class SYSMON(SelfTestExecutor): # read all sensor outputs of SYSMON def read_all(self, device_class): + if not device_class in self.config["device_classes"]: return { "error" : f"Unknown HWMON device class {device_class}. " + f'Valid choices: {list(self.config["device_classes"].keys())}'} @@ -73,16 +74,10 @@ class SYSMON(SelfTestExecutor): if not devices: return {"error" : f"Can't access HWMON device: {device_class}"} + #struct that describes the hwmon device class_config = self.config["device_classes"][device_class] - compiled_patterns = compile_patterns(class_config["patterns"]) - - #read reference values if available - #if "reference" in class_config: - # references = class_config["reference"] - #else: - # references = {} - result = { + result = { "title" : class_config["title"], "class" : device_class, "devices" : {} @@ -90,15 +85,94 @@ class SYSMON(SelfTestExecutor): # read all devices of the requested class # device is folder path to IIO device, e.g. "/sys/bus/iio/devices/iio:device4" + compiled_patterns = compile_patterns(class_config["patterns"]) for device_path in devices: result["devices"][device_path] = self.read_device(device_path, compiled_patterns) result["devices"][device_path]["name"] = get_name(device_path) - return result - + # Process readings to add reference values + if device_class == "xlnx,versal-sysmon": + return self.process_versal_sysmon(result, class_config, device_path) + elif device_class == "tmp435": + return self.process_tmp(result, class_config) + elif device_class == "ltm4700": + return self.process_ltm(result, class_config, device_path) + def self_test_main(self, **kwargs): result = {} for device_class in self.config["device_classes"]: result[device_class] = self.read_all(device_class) return result + + + def process_versal_sysmon(self, result, class_config, device_path): + compiled_patterns = compile_patterns(class_config["patterns"]) + for quantity in compiled_patterns: + for measurment_name in result["devices"][device_path][quantity]: + value = result["devices"][device_path][quantity][measurment_name] + if measurment_name in class_config["reference"][quantity]: + nominal = class_config["reference"][quantity][measurment_name]["nominal"] + max_value = class_config["reference"][quantity][measurment_name]["max"] + min_value = class_config["reference"][quantity][measurment_name]["min"] + new_value = {"read" : value, "min" : min_value, "nominal" : nominal, "max": max_value} + else: + new_value = {"read" : value, "min" : float('nan'), "nominal" : float('nan'), "max": float('nan')} + + result["devices"][device_path][quantity][measurment_name] = new_value + return result + + + # Each TMP probe is on a different file device. + # Data has to be reformatted to have the same format as versal-sysmon's + def process_tmp(self, result, class_config): + compiled_patterns = compile_patterns(class_config["patterns"]) + new_devices = {'/sys/class/hwmon/hwmonX' : {}} + for device_path, device_data in result["devices"].items(): + probe_name = device_data['name'] + local_value = device_data['probe']['temp1_input']/1000.0 + probe_value = device_data['probe']['temp2_input']/1000.0 + if probe_name in class_config["reference"]["probe"]: + nominal = class_config["reference"]["probe"][probe_name]["nominal"] + max_value = class_config["reference"]["probe"][probe_name]["max"] + min_value = class_config["reference"]["probe"][probe_name]["min"] + measurement = {"local" : local_value, "probe" : probe_value, "min" : min_value, "nominal" : nominal, "max": max_value} + else: + measurement = {"local" : local_value, "probe" : probe_value, "min" : float('nan'), "nominal" : float('nan'), "max": float('nan')} + new_devices['/sys/class/hwmon/hwmonX'][probe_name] = measurement + result['devices'] = new_devices + return result + + + # Limits derived from hardware + def process_ltm(self, result, class_config, device_path): + new_device_data = {'voltage':{}, 'current':{}, 'power':{}, 'temperature':{}} + data = result["devices"][device_path] + for key in ['in1', 'in2', 'in3']: + new_device_data['voltage'][key] = { + 'read': data['voltage'].get(f'{key}_input', float('nan'))/1000.0, + 'min': data['voltage_min'].get(f'{key}_min', float('nan'))/1000.0, + 'max': data['voltage_max'].get(f'{key}_max', float('nan'))/1000.0 + } + for key in ['curr1', 'curr2', 'curr3']: + new_device_data['current'][key] = { + 'read': data['current'].get(f'{key}_input', float('nan'))/1000.0, + 'max': data['current_max'].get(f'{key}_max', float('nan')) + } + for key in ['curr1', 'curr2', 'curr3']: + new_device_data['current'][key] = { + 'read': data['current'].get(f'{key}_input', float('nan'))/1000.0, + 'max': data['current_max'].get(f'{key}_max', float('nan'))/1000.0 + } + for key in ['power1', 'power2', 'power3']: + new_device_data['power'][key] = { + 'read': data['power'].get(f'{key}_input', float('nan'))/1e6 + } + for key in ['temp1', 'temp2', 'temp3']: + new_device_data['temperature'][key] = { + 'read': data['temp'].get(f'{key}_input', float('nan'))/1000.0, + 'max': data['temp_max'].get(f'{key}_max', float('nan'))/1000.0 + } + result["devices"][device_path] = new_device_data + return result + diff --git a/templates/sysmon.html b/templates/sysmon.html index ff87d15..a6f182e 100644 --- a/templates/sysmon.html +++ b/templates/sysmon.html @@ -9,24 +9,23 @@ <thead> <tr> <th scope="col">Sensor</th> - <th scope="col">Local temperature [deg C]</th> - <th scope="col">Max [deg C]</th> - <th scope="col">Probe temperature [deg C]</th> + <th scope="col">Local temp [deg C]</th> + <th scope="col">Probe temp [deg C]</th> <th scope="col">Max [deg C]</th> </tr> </thead> <tbody> {% for device_path, device_data in data["devices"].items() | sort %} + {% for name, value in device_data.items() | sort %} <tr> - <th scope="row">{{device_data['name']}}</th> - <td>{{ "{:.3f}".format(device_data["probe"]['temp1_input'] / 1000) }} </td> - <td>{{ "{:.3f}".format(device_data["max"]['temp1_crit'] / 1000) }} </td> - <td>{{ "{:.3f}".format(device_data["probe"]['temp2_input'] / 1000) }} </td> - <td>{{ "{:.3f}".format(device_data["max"]['temp2_crit'] / 1000) }} </td> + <th scope="row">{{name}}</th> + <td>{{ "{:.1f}".format(value["local"]) }}</td> + <td>{{ "{:.1f}".format(value["probe"]) }}</td> + <td>{{ "{:.1f}".format(value["max"])}}</td> </tr> {% endfor %} - + {% endfor %} </tbody> </table> @@ -57,37 +56,38 @@ <td></td> <td></td> <td></td> - <td>{{ "{:.3f}".format(device_data["temp"]['temp3_input'] / 1000) }}</td> + <td>{{ "{:.3f}".format(device_data["temperature"]['temp3']['read']) }}</td> </tr> <tr> <th scope="row">INPUT</th> - <td>{{ "{:.3f}".format(device_data["voltage"]['in1_input'] / 1000) }} </td> - <td>{{ "[{:.3f}, {:.3f}]".format(device_data["voltage_min"]['in1_min'] / 1000, device_data["voltage_crit"]['in1_crit'] / 1000) }} </td> - <td>{{ "{:.3f}".format(device_data["current"]['curr1_input'] / 1000) }} </td> - <td>{{ "{:.3f}".format(device_data["current_max"]['curr1_max'] / 1000) }} </td> - <td>{{ "{:.3f}".format(device_data["power"]['power1_input'] / 1e6) }} </td> + <td>{{ "{:.3f}".format(device_data["voltage"]['in1']['read']) }} </td> + <td>{{ "[{:.3f}, {:.3f}]".format(device_data["voltage"]['in1']['min'], device_data["voltage"]['in1']['max']) }} </td> + <td>{{ "{:.3f}".format(device_data["current"]['curr1']['read']) }} </td> + <td>{{ "{:.3f}".format(device_data["current"]['curr1']['max']) }} </td> + <td>{{ "{:.3f}".format(device_data["power"]['power1']['read']) }} </td> + <td>{{ "{:.3f}".format(device_data["temperature"]['temp1']['read']) }} </td> <td></td> </tr> <tr> <th scope="row">OUT1</th> - <td>{{ "{:.3f}".format(device_data["voltage"]['in2_input'] / 1000) }} </td> - <td>{{ "[{:.3f}, {:.3f}]".format(device_data["voltage_min"]['in2_min'] / 1000, device_data["voltage_max"]['in2_max'] / 1000) }} </td> - <td>{{ "{:.3f}".format(device_data["current"]['curr2_input'] / 1000) }} </td> - <td>{{ "{:.3f}".format(device_data["current_max"]['curr2_max'] / 1000) }} </td> - <td>{{ "{:.3f}".format(device_data["power"]['power2_input'] / 1e6) }} </td> - <td>{{ "{:.3f}".format(device_data["temp"]['temp1_input'] / 1000) }} </td> + <td>{{ "{:.3f}".format(device_data["voltage"]['in2']['read']) }} </td> + <td>{{ "[{:.3f}, {:.3f}]".format(device_data["voltage"]['in2']['min'], device_data["voltage"]['in2']['max']) }} </td> + <td>{{ "{:.3f}".format(device_data["current"]['curr2']['read']) }} </td> + <td>{{ "{:.3f}".format(device_data["current"]['curr2']['max']) }} </td> + <td>{{ "{:.3f}".format(device_data["power"]['power2']['read']) }} </td> + <td>{{ "{:.3f}".format(device_data["temperature"]['temp2']['read']) }} </td> </tr> <tr> <th scope="row">OUT2</th> - <td>{{ "{:.3f}".format(device_data["voltage"]['in3_input'] / 1000) }} </td> - <td>{{ "[{:.3f}, {:.3f}]".format(device_data["voltage_min"]['in3_min'] / 1000, device_data["voltage_max"]['in3_max'] / 1000) }} </td> - <td>{{ "{:.3f}".format(device_data["current"]['curr3_input'] / 1000) }} </td> - <td>{{ "{:.3f}".format(device_data["current_max"]['curr3_max'] / 1000) }} </td> - <td>{{ "{:.3f}".format(device_data["power"]['power3_input'] / 1e6) }} </td> - <td>{{ "{:.3f}".format(device_data["temp"]['temp2_input'] / 1000) }} </td> + <td>{{ "{:.3f}".format(device_data["voltage"]['in3']['read']) }} </td> + <td>{{ "[{:.3f}, {:.3f}]".format(device_data["voltage"]['in3']['min'], device_data["voltage"]['in3']['max']) }} </td> + <td>{{ "{:.3f}".format(device_data["current"]['curr3']['read']) }} </td> + <td>{{ "{:.3f}".format(device_data["current"]['curr3']['max']) }} </td> + <td>{{ "{:.3f}".format(device_data["power"]['power3']['read']) }} </td> + <td>{{ "{:.3f}".format(device_data["temperature"]['temp3']['read']) }} </td> </tr> </tbody> @@ -129,7 +129,8 @@ <thead> <tr> <th scope="col">Input</th> - <th scope="col">Value</th> + <th scope="col">Value (deg C)</th> + <th scope="col">[Min, Max] (deg C)</th> </tr> </thead> <tbody> @@ -137,7 +138,8 @@ {% for name, value in device_data['temperature'].items() | sort %} <tr> <th scope="row">{{name}}</th> - <td>{{ "{:.1f}".format(value) }} C</td> + <td>{{ "{:.1f}".format(value["read"]) }}</td> + <td>{{ "[{:.1F}, {:.1F}]".format(value["min"], value["max"])}}</td> </tr> {% endfor %} @@ -152,15 +154,16 @@ <thead> <tr> <th scope="col">Input</th> - <th scope="col">Value</th> + <th scope="col">Value (V)</th> + <th scope="col">[Min, Max] (V)</th> </tr> </thead> <tbody> - {% for name, value in device_data['voltage'].items() | sort %} <tr> <th scope="row">{{name}}</th> - <td>{{ "{:.3f}".format(value) }} V</td> + <td>{{ "{:.3f}".format(value["read"]) }}</td> + <td>{{ "[{:.3f}, {:.3f}]".format(value["min"], value["max"]) }}</td> </tr> {% endfor %} -- GitLab From 1b7d60af10efb3b8e3fa67b56472b92d757dd797 Mon Sep 17 00:00:00 2001 From: Carlo Alberto Gottardo <carlo.alberto.gottardo@cern.ch> Date: Tue, 23 Jul 2024 16:04:51 +0200 Subject: [PATCH 06/23] Voltage and current limits on tables --- boards/flx182.py | 50 +++++++++++++++++++++++-------------------- models/ina226.py | 11 +++++----- models/sysmon.py | 29 ++++++++++++++++++++----- templates/ina226.html | 16 ++++++-------- templates/sysmon.html | 16 ++++++++++++-- 5 files changed, 76 insertions(+), 46 deletions(-) diff --git a/boards/flx182.py b/boards/flx182.py index cfd206b..752a8c4 100644 --- a/boards/flx182.py +++ b/boards/flx182.py @@ -42,16 +42,16 @@ config = { }, #tolerance and max current set by hand "reference" : { - "12P0V" : {"V" : 12.00, "V_tolerance" : 0.03, "I" : 12.00, "I_max" : 1.0}, - "MGTAVCC" : {"V" : 0.88 , "V_tolerance" : 0.03, "I" : 0.88 , "I_max" : 3.5}, - "MGTAVTT" : {"V" : 1.20 , "V_tolerance" : 0.03, "I" : 1.20 , "I_max" : 6.5}, - "SYS12" : {"V" : 1.20 , "V_tolerance" : 0.03, "I" : 1.20 , "I_max" : 4.1}, - "SYS15" : {"V" : 1.50 , "V_tolerance" : 0.03, "I" : 1.50 , "I_max" : 1.6}, - "SYS18" : {"V" : 1.80 , "V_tolerance" : 0.03, "I" : 1.80 , "I_max" : 1.5}, - "SYS25" : {"V" : 2.50 , "V_tolerance" : 0.03, "I" : 2.50 , "I_max" : 0.5}, - "SYS33" : {"V" : 3.30 , "V_tolerance" : 0.03, "I" : 3.30 , "I_max" : 6.0}, - "SYS38" : {"V" : 3.80 , "V_tolerance" : 0.03, "I" : 3.80 , "I_max" : 1.0}, - "VCCINT" : {"V" : 0.80 , "V_tolerance" : 0.03, "I" : 0.80 , "I_max" : 50.0} + "12P0V" : {"V" : 12.00, "V_min" : 11.0, "V_max" : 23.0, "I" : 1, "I_max" : 8, "desc" : "+/- 1V expected from power supply"}, + "MGTAVCC" : {"V" : 0.88 , "V_min" : 0.854, "V_max" : 0.906, "I" : 1.5 , "I_max" : 3.5, "desc" : "V limits from FPGA recommended ranges"}, + "MGTAVTT" : {"V" : 1.20 , "V_min" : 1.164, "V_max" : 1.236, "I" : 3.4 , "I_max" : 6.5, "desc" : "V limits from FPGA recommended ranges"}, + "SYS12" : {"V" : 1.20 , "V_min" : 1.164, "V_max" : 1.236, "I" : 0.8 , "I_max" : 1.5, "desc" : "V limits from FPGA recommended ranges"}, + "SYS15" : {"V" : 1.50 , "V_min" : 1.455, "V_max" : 1.545, "I" : 0.9 , "I_max" : 1.5, "desc" : "V limits from FPGA recommended ranges"}, + "SYS18" : {"V" : 1.80 , "V_min" : 1.710, "V_max" : 1.890, "I" : 0.8 , "I_max" : 1.5, "desc" : "V limits from 25G FF"}, + "SYS25" : {"V" : 2.50 , "V_min" : 2.15, "V_max" : 2.85, "I" : 0.3 , "I_max" : 0.5, "desc" : ""}, + "SYS33" : {"V" : 3.30 , "V_min" : 3.15, "V_max" : 3.45, "I" : 3.30 , "I_max" : 6.0, "desc" : "V limits from 14/16G FF"}, + "SYS38" : {"V" : 3.80 , "V_min" : 3.50, "V_max" : 4.10, "I" : 0.0 , "I_max" : 5, "desc" : ""}, + "VCCINT" : {"V" : 0.80 , "V_min" : 0.775, "V_max" : 0.825, "I" : 20.0 , "I_max" : 50.0,"desc" : ""} } }, @@ -72,8 +72,8 @@ config = { # DS956 2024-04-30 # Table: Recommended Operating Conditions "temperature" : { - "max_max" : {"nominal" : 36, "min" : 0, "max" : 50, "source" : "N/A"}, - "temp" : {"nominal" : 36, "min" : 0, "max" : 50, "source" : "N/A"}, + "max_max" : {"nominal" : 36, "min" : 0, "max" : 50, "source" : "N/A", "desc" : "FPGA diode temperature (latched max)"}, + "temp" : {"nominal" : 36, "min" : 0, "max" : 50, "source" : "N/A", "desc" : "FPGA diode temperature"}, }, "voltage" : { "gty_avcc_103" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, @@ -110,9 +110,9 @@ config = { "gty_avtt_205" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, "gty_avtt_206" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, "vcc_batt" : {"nominal" : 0, "min" : 1.200, "max" : 1.500, "source" : "DS956", "desc" : "Battery power supply"}, - "vcc_pmc" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "PMC primary power supply, mid (M) voltage"}, - "vcc_psfp" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "PS full-power domain power supply, mid (M) voltage"}, - "vcc_pslp" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "PS low-power domain power supply, mid (M) voltage"}, + "vcc_pmc" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "PMC primary power supply"}, + "vcc_psfp" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "PS full-power domain power supply"}, + "vcc_pslp" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "PS low-power domain power supply"}, "vcc_ram" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "PL RAM and clocking network" }, "vcc_soc" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "Network on Chip (NoC) and DDR memory controller power supply"}, "vccaux" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "Auxiliary power supply "}, @@ -166,16 +166,15 @@ config = { "self_test" : { "description" : "TMP435 readout", }, - #max temp by common sense "reference" : { "probe" : { - "MGTAVCC_TMP" : {"min" : 20.0, "nominal" : 40.0, "max" : 60.0 }, - "MGTAVTT_TMP" : {"min" : 20.0, "nominal" : 40.0, "max" : 60.0 }, - "SYS12_TMP" : {"min" : 20.0, "nominal" : 40.0, "max" : 60.0 }, - "SYS15_TMP" : {"min" : 20.0, "nominal" : 40.0, "max" : 60.0 }, - "SYS18_TMP" : {"min" : 20.0, "nominal" : 40.0, "max" : 60.0 }, - "SYS25_TMP" : {"min" : 20.0, "nominal" : 40.0, "max" : 60.0 }, - "SYS33_TMP" : {"min" : 20.0, "nominal" : 40.0, "max" : 60.0 }, + "LTM4642_TMP" : {"min" : 20.0, "nominal" : 30.0, "max" : 50.0, "desc" : "LTM4642, 2.5V (DDR, ETH) and 3.8V (FF) rails"}, + "MGTAVCC_TMP" : {"min" : 20.0, "nominal" : 40.0, "max" : 60.0, "desc" : "LTM4638, 0.88V rail (FPGA) "}, + "MGTAVTT_TMP" : {"min" : 20.0, "nominal" : 40.0, "max" : 60.0, "desc" : "LTM4638, 1.2V rail (FPGA, DDR)"}, + "SYS12_TMP" : {"min" : 20.0, "nominal" : 40.0, "max" : 60.0, "desc" : "LTM4638, 1.2V rail (FPGA, DDR)"}, + "SYS15_TMP" : {"min" : 20.0, "nominal" : 40.0, "max" : 60.0, "desc" : "LTM4638, 1.5V rail (FPGA)"}, + "SYS18_TMP" : {"min" : 20.0, "nominal" : 40.0, "max" : 60.0, "desc" : "LTM4638, 1.8V rail (FPGA, FF, Si5345)"}, + "SYS33_TMP" : {"min" : 20.0, "nominal" : 40.0, "max" : 60.0, "desc" : "LTM4638, 3.3V rail (FF, Si5345, QSPI)"}, } } }, @@ -186,6 +185,11 @@ config = { "patterns" : { "probe" : "(?P<name>temp\\d+_input)", }, + "reference" : { + "probe" : { + "DRAM temperature sensor" : {"min" : 20.0, "nominal" : 33.0, "max" : 50.0, "desc" : "DRAM temperature"}, + } + } }, }, "self_test" : { diff --git a/models/ina226.py b/models/ina226.py index d018ecb..89b53b7 100644 --- a/models/ina226.py +++ b/models/ina226.py @@ -42,17 +42,16 @@ class INA226(SelfTestExecutor): I_max = -1 if label in self.config["reference"]: - rail = self.config["reference"][label] - V_dev = (voltage - rail["V"]) / rail["V"] - V_tol = self.config["reference"][label]["V_tolerance"] + V_min = self.config["reference"][label]["V_min"] + V_max = self.config["reference"][label]["V_max"] I_max = self.config["reference"][label]["I_max"] data = { "V" : voltage, - "Vdev" : V_dev, - "Vtol" : V_tol, + "V_min" : V_min, + "V_max" : V_max, "I" : current, - "Imax" : I_max, + "I_max" : I_max, "P" : power, "R_shunt" : r_shunt / 1000.0 } diff --git a/models/sysmon.py b/models/sysmon.py index 4997df7..e8e805d 100644 --- a/models/sysmon.py +++ b/models/sysmon.py @@ -97,6 +97,8 @@ class SYSMON(SelfTestExecutor): return self.process_tmp(result, class_config) elif device_class == "ltm4700": return self.process_ltm(result, class_config, device_path) + elif device_class == "jc42": + return self.process_jc42(result, class_config) def self_test_main(self, **kwargs): @@ -115,9 +117,10 @@ class SYSMON(SelfTestExecutor): nominal = class_config["reference"][quantity][measurment_name]["nominal"] max_value = class_config["reference"][quantity][measurment_name]["max"] min_value = class_config["reference"][quantity][measurment_name]["min"] - new_value = {"read" : value, "min" : min_value, "nominal" : nominal, "max": max_value} + description = class_config["reference"][quantity][measurment_name]["desc"] + new_value = {"read" : value, "min" : min_value, "nominal" : nominal, "max": max_value, "desc" : description} else: - new_value = {"read" : value, "min" : float('nan'), "nominal" : float('nan'), "max": float('nan')} + new_value = {"read" : value, "min" : float('nan'), "nominal" : float('nan'), "max": float('nan'), "desc" : ""} result["devices"][device_path][quantity][measurment_name] = new_value return result @@ -135,10 +138,11 @@ class SYSMON(SelfTestExecutor): if probe_name in class_config["reference"]["probe"]: nominal = class_config["reference"]["probe"][probe_name]["nominal"] max_value = class_config["reference"]["probe"][probe_name]["max"] - min_value = class_config["reference"]["probe"][probe_name]["min"] - measurement = {"local" : local_value, "probe" : probe_value, "min" : min_value, "nominal" : nominal, "max": max_value} + min_value = class_config["reference"]["probe"][probe_name]["min"] + description = class_config["reference"]["probe"][probe_name]["desc"] + measurement = {"local" : local_value, "probe" : probe_value, "min" : min_value, "nominal" : nominal, "max": max_value, "desc" : description} else: - measurement = {"local" : local_value, "probe" : probe_value, "min" : float('nan'), "nominal" : float('nan'), "max": float('nan')} + measurement = {"local" : local_value, "probe" : probe_value, "min" : float('nan'), "nominal" : float('nan'), "max": float('nan'), "desc" : ""} new_devices['/sys/class/hwmon/hwmonX'][probe_name] = measurement result['devices'] = new_devices return result @@ -176,3 +180,18 @@ class SYSMON(SelfTestExecutor): result["devices"][device_path] = new_device_data return result + + def process_jc42(self, result, class_config): + value = result['devices']['/sys/class/hwmon/hwmon8']['probe']['temp1_input']/1000.0 + name = result['devices']['/sys/class/hwmon/hwmon8']['name'] + if name in class_config['reference']['probe']: + min_value = class_config['reference']['probe'][name]["min"] + max_value = class_config['reference']['probe'][name]["max"] + description = class_config['reference']['probe'][name]["desc"] + measurement = {"read" : value, "min" : min_value, "max": max_value, "desc" : description} + else: + measurement = {"read" : value, "min" : float('nan'), "max": float('nan'), "desc" : ""} + + result['devices']['/sys/class/hwmon/hwmon8'] = {} + result['devices']['/sys/class/hwmon/hwmon8'][name] = measurement + return result \ No newline at end of file diff --git a/templates/ina226.html b/templates/ina226.html index 744d0dd..4ef15ca 100644 --- a/templates/ina226.html +++ b/templates/ina226.html @@ -8,13 +8,11 @@ <thead> <tr> <th scope="col">Name</th> - <th scope="col">VCC [V]</th> - <th scope="col">VCC deviation [%]</th> - <th scope="col">VCC tolerance [%]</th> - <th scope="col">I [A]</th> - <th scope="col">I max [A]</th> + <th scope="col">Voltage (V)</th> + <th scope="col">V range (V)</th> + <th scope="col">I (A)</th> + <th scope="col">Max I (A)</th> <th scope="col">P [W]</th> - <th scope="col">R_sh [mOhm]</th> </tr> </thead> <tbody> @@ -23,12 +21,10 @@ <tr> <th scope="row">{{ label }}</th> <td>{{ "{:.3f}".format(device["V"]) }}</td> - <td>{{ "{:.3f}".format(device["Vdev"]) }}</td> - <td>{{ "{:.3f}".format(device["Vtol"]) }}</td> + <td>{{ "[{:.3f}, {:.3f}]".format(device["V_min"], device["V_max"]) }}</td> <td>{{ "{:.3f}".format(device["I"]) }}</td> - <td>{{ "{:.3f}".format(device["Imax"]) }}</td> + <td>{{ "{:.3f}".format(device["I_max"]) }}</td> <td>{{ "{:.3f}".format(device["P"]) }}</td> - <td>{{ "{:.3f}".format(device["R_shunt"]) }}</td> </tr> {% endfor %} diff --git a/templates/sysmon.html b/templates/sysmon.html index a6f182e..ff7e0c1 100644 --- a/templates/sysmon.html +++ b/templates/sysmon.html @@ -12,6 +12,7 @@ <th scope="col">Local temp [deg C]</th> <th scope="col">Probe temp [deg C]</th> <th scope="col">Max [deg C]</th> + <th scope="col">Description</th> </tr> </thead> <tbody> @@ -23,6 +24,7 @@ <td>{{ "{:.1f}".format(value["local"]) }}</td> <td>{{ "{:.1f}".format(value["probe"]) }}</td> <td>{{ "{:.1f}".format(value["max"])}}</td> + <td>{{ value["desc"] }}</td> </tr> {% endfor %} {% endfor %} @@ -102,16 +104,22 @@ <tr> <th scope="col">Device</th> <th scope="col">Temperature [deg C]</th> + <th scope="col">Max Temp [deg C]</th> </tr> </thead> <tbody> {% for device_path, device_data in data["devices"].items() | sort %} + {% for key, meas in device_data.items() | sort %} + <tr> - <th scope="row">{{device_data['name']}}</th> - <td>{{ "{:.3f}".format(device_data["probe"]['temp1_input'] / 1000) }} </td> + <th scope="row">{{key}}</th> + <td>{{ "{:.3f}".format(meas["read"]) }} </td> + <td>{{ "{:.3f}".format(meas["max"]) }} </td> </tr> {% endfor %} + {% endfor %} + </tbody> </table> @@ -131,6 +139,7 @@ <th scope="col">Input</th> <th scope="col">Value (deg C)</th> <th scope="col">[Min, Max] (deg C)</th> + <th scope="col">Description</th> </tr> </thead> <tbody> @@ -140,6 +149,7 @@ <th scope="row">{{name}}</th> <td>{{ "{:.1f}".format(value["read"]) }}</td> <td>{{ "[{:.1F}, {:.1F}]".format(value["min"], value["max"])}}</td> + <td>{{ value["desc"] }}</td> </tr> {% endfor %} @@ -156,6 +166,7 @@ <th scope="col">Input</th> <th scope="col">Value (V)</th> <th scope="col">[Min, Max] (V)</th> + <th scope="col">Description</th> </tr> </thead> <tbody> @@ -164,6 +175,7 @@ <th scope="row">{{name}}</th> <td>{{ "{:.3f}".format(value["read"]) }}</td> <td>{{ "[{:.3f}, {:.3f}]".format(value["min"], value["max"]) }}</td> + <td>{{ value["desc"] }}</td> </tr> {% endfor %} -- GitLab From 64ede4b2d32487245256d95616fcdce4d1e0d5f0 Mon Sep 17 00:00:00 2001 From: Carlo Alberto Gottardo <carlo.alberto.gottardo@cern.ch> Date: Tue, 6 Aug 2024 13:24:00 +0200 Subject: [PATCH 07/23] HWMON test conditions --- boards/flx182.py | 2 +- controllers/sysmon.py | 2 - models/self_test_executor.py | 2 +- models/sysmon.py | 112 ++++++++++++++++++++++++++++------- templates/sysmon.html | 2 + 5 files changed, 94 insertions(+), 26 deletions(-) diff --git a/boards/flx182.py b/boards/flx182.py index 752a8c4..20367f0 100644 --- a/boards/flx182.py +++ b/boards/flx182.py @@ -109,7 +109,7 @@ config = { "gty_avtt_204" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, "gty_avtt_205" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, "gty_avtt_206" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, - "vcc_batt" : {"nominal" : 0, "min" : 1.200, "max" : 1.500, "source" : "DS956", "desc" : "Battery power supply"}, +# "vcc_batt" : {"nominal" : 0, "min" : 1.200, "max" : 1.500, "source" : "DS956", "desc" : "Battery power supply"}, "vcc_pmc" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "PMC primary power supply"}, "vcc_psfp" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "PS full-power domain power supply"}, "vcc_pslp" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "PS low-power domain power supply"}, diff --git a/controllers/sysmon.py b/controllers/sysmon.py index ba67770..bd6ebfb 100644 --- a/controllers/sysmon.py +++ b/controllers/sysmon.py @@ -23,5 +23,3 @@ class SYSMON_Controller(): return render_template("error.html", error=data["error"]) else: return render_template("sysmon.html", data=data) - - \ No newline at end of file diff --git a/models/self_test_executor.py b/models/self_test_executor.py index 057ac01..6bed147 100644 --- a/models/self_test_executor.py +++ b/models/self_test_executor.py @@ -36,7 +36,7 @@ class SelfTestExecutor(): human_readable_name_getter=None): if result is None or not result: - return { "status" : "error", "result" : "Test results are missing" } + return { "status" : "error", "result" : "No test results available" } devices_with_errors = [] devices_with_missing_data = [] diff --git a/models/sysmon.py b/models/sysmon.py index e8e805d..427bd95 100644 --- a/models/sysmon.py +++ b/models/sysmon.py @@ -1,5 +1,4 @@ -import re, os, pdb - +import re, os, pdb, math from os import path, listdir from util.iio import load_file, get_devices from os.path import isfile @@ -108,21 +107,67 @@ class SYSMON(SelfTestExecutor): return result + def check_measured_value(self, meas_type, name, read_value, min_value, max_value): + check = {"status" : "", "msg" : ""} + if math.isnan(read_value): + check["status"] = "BAD" + check["msg"] = "{0} {1} is NaN".format(meas_type, name) + elif (not math.isnan(max_value) and read_value > max_value) : + check["status"] = "HIGH" + check["msg"] = "{0} {1} is {2} above max {3}".format(meas_type, name, read_value, max_value) + elif (not math.isnan(min_value) and read_value < min_value): + check["status"] = "LOW" + check["msg"] = "{0} {1} is {2} below min {3}".format(meas_type, name, read_value, min_value) + else: + check["status"] = "OK" + return check + + + def self_test_check_result(self, result): + status_ok = True + msg = [] + for device_type in result: + if 'devices' not in device_type: + if 'error' in result[device_type]: + msg.append(result[device_type]["error"]) + status_ok = False + else: + for device_path in result[device_type]['devices']: + for quantity in result[device_type]['devices'][device_path]: + if quantity == "name": + continue + for measurement_name in result[device_type]['devices'][device_path][quantity]: + measurement = result[device_type]['devices'][device_path][quantity][measurement_name] + if measurement["status"] != "OK": + msg.append(measurement["msg"]) + status_ok = False + if status_ok: + msg = ["OK"] + msg_level = "success" + else: + msg_level = "error" + + return { "status" : msg_level, "result" : msg } + + + def process_versal_sysmon(self, result, class_config, device_path): compiled_patterns = compile_patterns(class_config["patterns"]) for quantity in compiled_patterns: - for measurment_name in result["devices"][device_path][quantity]: - value = result["devices"][device_path][quantity][measurment_name] - if measurment_name in class_config["reference"][quantity]: - nominal = class_config["reference"][quantity][measurment_name]["nominal"] - max_value = class_config["reference"][quantity][measurment_name]["max"] - min_value = class_config["reference"][quantity][measurment_name]["min"] - description = class_config["reference"][quantity][measurment_name]["desc"] - new_value = {"read" : value, "min" : min_value, "nominal" : nominal, "max": max_value, "desc" : description} - else: - new_value = {"read" : value, "min" : float('nan'), "nominal" : float('nan'), "max": float('nan'), "desc" : ""} - - result["devices"][device_path][quantity][measurment_name] = new_value + for measurement_name in result["devices"][device_path][quantity]: + value = result["devices"][device_path][quantity][measurement_name] + # New result format + new_value = {"read" : value, "min" : float('nan'), "nominal" : float('nan'), "max": float('nan'), "desc" : ""} + # Populate reference fields + if measurement_name in class_config["reference"][quantity]: + new_value["nominal"] = class_config["reference"][quantity][measurement_name]["nominal"] + new_value["max"] = class_config["reference"][quantity][measurement_name]["max"] + new_value["min"] = class_config["reference"][quantity][measurement_name]["min"] + new_value["desc"] = class_config["reference"][quantity][measurement_name]["desc"] + # Check value + check = self.check_measured_value(quantity, measurement_name, value, new_value["min"], new_value["max"]) + new_value = {**new_value, **check} + result["devices"][device_path][quantity][measurement_name] = new_value return result @@ -135,14 +180,17 @@ class SYSMON(SelfTestExecutor): probe_name = device_data['name'] local_value = device_data['probe']['temp1_input']/1000.0 probe_value = device_data['probe']['temp2_input']/1000.0 + measurement = {"local" : local_value, "probe" : probe_value, "min" : float('nan'), "nominal" : float('nan'), "max": float('nan'), "desc" : ""} + if probe_name in class_config["reference"]["probe"]: - nominal = class_config["reference"]["probe"][probe_name]["nominal"] - max_value = class_config["reference"]["probe"][probe_name]["max"] - min_value = class_config["reference"]["probe"][probe_name]["min"] - description = class_config["reference"]["probe"][probe_name]["desc"] - measurement = {"local" : local_value, "probe" : probe_value, "min" : min_value, "nominal" : nominal, "max": max_value, "desc" : description} - else: - measurement = {"local" : local_value, "probe" : probe_value, "min" : float('nan'), "nominal" : float('nan'), "max": float('nan'), "desc" : ""} + measurement["nominal"] = class_config["reference"]["probe"][probe_name]["nominal"] + measurement["max"] = class_config["reference"]["probe"][probe_name]["max"] + measurement["min"] = class_config["reference"]["probe"][probe_name]["min"] + measurement["desc"] = class_config["reference"]["probe"][probe_name]["desc"] + + # Check value + check = self.check_measured_value(quantity, measurement_name, value, new_value["min"], new_value["max"]) + measurement = {**measurement, **check} new_devices['/sys/class/hwmon/hwmonX'][probe_name] = measurement result['devices'] = new_devices return result @@ -158,25 +206,45 @@ class SYSMON(SelfTestExecutor): 'min': data['voltage_min'].get(f'{key}_min', float('nan'))/1000.0, 'max': data['voltage_max'].get(f'{key}_max', float('nan'))/1000.0 } + check = check_measured_value('voltage', key, new_device_data["read"], new_device_data["min"], new_device_data["max"]) + new_device_data = {**new_device_data, **check} + for key in ['curr1', 'curr2', 'curr3']: new_device_data['current'][key] = { 'read': data['current'].get(f'{key}_input', float('nan'))/1000.0, + 'min': float('nan'), 'max': data['current_max'].get(f'{key}_max', float('nan')) } + check = check_measured_value('current', key, new_device_data["read"], new_device_data["min"], new_device_data["max"]) + new_device_data = {**new_device_data, **check} + for key in ['curr1', 'curr2', 'curr3']: new_device_data['current'][key] = { 'read': data['current'].get(f'{key}_input', float('nan'))/1000.0, + 'min': float('nan'), 'max': data['current_max'].get(f'{key}_max', float('nan'))/1000.0 } + check = check_measured_value('current', key, new_device_data["read"], new_device_data["min"], new_device_data["max"]) + new_device_data = {**new_device_data, **check} + for key in ['power1', 'power2', 'power3']: new_device_data['power'][key] = { - 'read': data['power'].get(f'{key}_input', float('nan'))/1e6 + 'read': data['power'].get(f'{key}_input', float('nan'))/1e6, + 'min': float('nan'), + 'max': float('nan') } + check = check_measured_value('current', key, new_device_data["read"], new_device_data["min"], new_device_data["max"]) + new_device_data = {**new_device_data, **check} + for key in ['temp1', 'temp2', 'temp3']: new_device_data['temperature'][key] = { 'read': data['temp'].get(f'{key}_input', float('nan'))/1000.0, + 'min': float('nan'), 'max': data['temp_max'].get(f'{key}_max', float('nan'))/1000.0 } + check = check_measured_value('current', key, new_device_data["read"], new_device_data["min"], new_device_data["max"]) + new_device_data = {**new_device_data, **check} + result["devices"][device_path] = new_device_data return result diff --git a/templates/sysmon.html b/templates/sysmon.html index ff7e0c1..c42046b 100644 --- a/templates/sysmon.html +++ b/templates/sysmon.html @@ -167,6 +167,7 @@ <th scope="col">Value (V)</th> <th scope="col">[Min, Max] (V)</th> <th scope="col">Description</th> + <th scope="col">Status</th> </tr> </thead> <tbody> @@ -176,6 +177,7 @@ <td>{{ "{:.3f}".format(value["read"]) }}</td> <td>{{ "[{:.3f}, {:.3f}]".format(value["min"], value["max"]) }}</td> <td>{{ value["desc"] }}</td> + <td>{{ value["status"] }}</td> </tr> {% endfor %} -- GitLab From 632a881b5c6790782e0d05f2d7e49087adfd4150 Mon Sep 17 00:00:00 2001 From: Carlo Alberto Gottardo <carlo.alberto.gottardo@cern.ch> Date: Tue, 6 Aug 2024 13:41:24 +0200 Subject: [PATCH 08/23] Include raw data in json report --- models/sysmon.py | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/models/sysmon.py b/models/sysmon.py index 427bd95..8079797 100644 --- a/models/sysmon.py +++ b/models/sysmon.py @@ -107,6 +107,7 @@ class SYSMON(SelfTestExecutor): return result + # Check whether the measured value is within range def check_measured_value(self, meas_type, name, read_value, min_value, max_value): check = {"status" : "", "msg" : ""} if math.isnan(read_value): @@ -123,9 +124,11 @@ class SYSMON(SelfTestExecutor): return check + # Test outcome def self_test_check_result(self, result): status_ok = True msg = [] + raw_data = {} for device_type in result: if 'devices' not in device_type: if 'error' in result[device_type]: @@ -138,6 +141,7 @@ class SYSMON(SelfTestExecutor): continue for measurement_name in result[device_type]['devices'][device_path][quantity]: measurement = result[device_type]['devices'][device_path][quantity][measurement_name] + raw_data[measurement_name] = measurement["read"] if measurement["status"] != "OK": msg.append(measurement["msg"]) status_ok = False @@ -147,10 +151,10 @@ class SYSMON(SelfTestExecutor): else: msg_level = "error" - return { "status" : msg_level, "result" : msg } - + return { "status" : msg_level, "result" : msg, "data" : raw_data } + # Format sysmon meaurements def process_versal_sysmon(self, result, class_config, device_path): compiled_patterns = compile_patterns(class_config["patterns"]) for quantity in compiled_patterns: @@ -196,7 +200,7 @@ class SYSMON(SelfTestExecutor): return result - # Limits derived from hardware + # Format ltm meaurements def process_ltm(self, result, class_config, device_path): new_device_data = {'voltage':{}, 'current':{}, 'power':{}, 'temperature':{}} data = result["devices"][device_path] @@ -249,16 +253,20 @@ class SYSMON(SelfTestExecutor): return result + # Format jc42 meaurements def process_jc42(self, result, class_config): value = result['devices']['/sys/class/hwmon/hwmon8']['probe']['temp1_input']/1000.0 name = result['devices']['/sys/class/hwmon/hwmon8']['name'] + measurement = {"read" : value, "min" : float('nan'), "max": float('nan'), "desc" : ""} + if name in class_config['reference']['probe']: - min_value = class_config['reference']['probe'][name]["min"] - max_value = class_config['reference']['probe'][name]["max"] - description = class_config['reference']['probe'][name]["desc"] + measurement["min"] = class_config['reference']['probe'][name]["min"] + measurement["max"] = class_config['reference']['probe'][name]["max"] + measurement["desc"] = class_config['reference']['probe'][name]["desc"] measurement = {"read" : value, "min" : min_value, "max": max_value, "desc" : description} - else: - measurement = {"read" : value, "min" : float('nan'), "max": float('nan'), "desc" : ""} + + check = check_measured_value('temperature', name, value, measurement["min"], measurement["max"]) + measurement = {**measurement, **check} result['devices']['/sys/class/hwmon/hwmon8'] = {} result['devices']['/sys/class/hwmon/hwmon8'][name] = measurement -- GitLab From b062053d0c6df6442294b8fe5f934ba9729673ae Mon Sep 17 00:00:00 2001 From: Carlo Alberto Gottardo <carlo.alberto.gottardo@cern.ch> Date: Tue, 6 Aug 2024 14:17:36 +0200 Subject: [PATCH 09/23] remove useless raw_data result field --- models/sysmon.py | 4 +--- templates/sysmon.html | 2 ++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/models/sysmon.py b/models/sysmon.py index 8079797..0139335 100644 --- a/models/sysmon.py +++ b/models/sysmon.py @@ -128,7 +128,6 @@ class SYSMON(SelfTestExecutor): def self_test_check_result(self, result): status_ok = True msg = [] - raw_data = {} for device_type in result: if 'devices' not in device_type: if 'error' in result[device_type]: @@ -141,7 +140,6 @@ class SYSMON(SelfTestExecutor): continue for measurement_name in result[device_type]['devices'][device_path][quantity]: measurement = result[device_type]['devices'][device_path][quantity][measurement_name] - raw_data[measurement_name] = measurement["read"] if measurement["status"] != "OK": msg.append(measurement["msg"]) status_ok = False @@ -151,7 +149,7 @@ class SYSMON(SelfTestExecutor): else: msg_level = "error" - return { "status" : msg_level, "result" : msg, "data" : raw_data } + return { "status" : msg_level, "result" : msg} # Format sysmon meaurements diff --git a/templates/sysmon.html b/templates/sysmon.html index c42046b..34a100d 100644 --- a/templates/sysmon.html +++ b/templates/sysmon.html @@ -140,6 +140,7 @@ <th scope="col">Value (deg C)</th> <th scope="col">[Min, Max] (deg C)</th> <th scope="col">Description</th> + <th scope="col">Status</th> </tr> </thead> <tbody> @@ -150,6 +151,7 @@ <td>{{ "{:.1f}".format(value["read"]) }}</td> <td>{{ "[{:.1F}, {:.1F}]".format(value["min"], value["max"])}}</td> <td>{{ value["desc"] }}</td> + <td>{{ value["status"] }}</td> </tr> {% endfor %} -- GitLab From d67352487770aa0e0dbe6ec31dd4c689b4f764e5 Mon Sep 17 00:00:00 2001 From: Carlo Alberto Gottardo <carlo.alberto.gottardo@cern.ch> Date: Wed, 7 Aug 2024 14:23:54 +0200 Subject: [PATCH 10/23] extract and show DNA --- boards/flx182.py | 1 + models/board_id.py | 52 ++++++++++++++++++++++++++++++++------------- templates/base.html | 2 +- 3 files changed, 39 insertions(+), 16 deletions(-) diff --git a/boards/flx182.py b/boards/flx182.py index 20367f0..b10b447 100644 --- a/boards/flx182.py +++ b/boards/flx182.py @@ -23,6 +23,7 @@ config = { "interface" : "zynq_mpsoc", "board" : "FLX-182", "revision" : "3", + "DNAaddress" : [0xF1250024, 0xF1250020], "self_test" : { "description" : "Identify the board", } diff --git a/models/board_id.py b/models/board_id.py index abe68ca..a139c2d 100644 --- a/models/board_id.py +++ b/models/board_id.py @@ -1,5 +1,5 @@ -import pdb, re -from os import path +import pdb, re, mmap, os +from os import path, sysconf from os.path import isdir from util.iio import load_file from models.self_test_executor import SelfTestExecutor, field_present @@ -12,6 +12,7 @@ class BoardID(SelfTestExecutor): self.config = config self.idcode = None + def get_id(self): if not "interface" in self.config: return {"error" : "You must specify interface type for retrieving the IDCODE!" } @@ -19,9 +20,6 @@ class BoardID(SelfTestExecutor): if self.config['interface'] == 'zynq_mpsoc': return self.get_id_zynq_mpsoc() - #TODO: add interface that reads a specific memory location for IDCODE - # to support Zynq7000 using periphery library - else: return {"error" : "Unsupported interface for retrieving the IDCODE" } @@ -48,29 +46,52 @@ class BoardID(SelfTestExecutor): return {"error" : f"Cannot extract IDCODE from string '{pm_response}'"} idcode = int(match.group('idcode'), 16) - return {"idcode" : idcode} + return hex(idcode) + + + def devmem(self, target_adr, length=4): + page_size= os.sysconf("SC_PAGE_SIZE") + reg_base = int(target_adr // page_size) * page_size + seek_size= int(target_adr % page_size) + map_size = seek_size+length + fd = os.open("/dev/mem", os.O_RDWR|os.O_SYNC) + mem = mmap.mmap(fd, map_size, mmap.MAP_SHARED, mmap.PROT_READ|mmap.PROT_WRITE, offset=reg_base) + mem.seek(seek_size, os.SEEK_SET) + value = mem.read(length) + os.close(fd) + return value + + + def get_dna(self): + if not "DNAaddress" in self.config: + return {"error" : "You must specify a memory address to retrieve the FPGA DNA!" } + else: + dna_msb = int.from_bytes(self.devmem(self.config['DNAaddress'][0]), "little") + dna_lsb = int.from_bytes(self.devmem(self.config['DNAaddress'][1]), "little") + dna = ( dna_msb << 32 ) | dna_lsb + return hex(dna) def get_board_name(self): board = self.config['board'] revision = self.config['revision'] - idcode = self.get_id()["idcode"] - return f"{board}_rev_{revision}_{idcode:X}" + idcode = self.get_id() + dna = self.get_dna() + return f"{board}_rev_{revision}_id_{idcode}_dna_{dna}" def get_board_info(self): - result = self.get_id() - for key, value in self.config.items(): - result[key] = value + result = {"board" : self.config['board'], "revision" : self.config['revision'], "idcode" : self.get_id(), "dna" : self.get_dna()} return result def self_test_main(self, **kwargs): - self.get_board_info() + return self.get_board_info() def self_test_check_result(self, result): - if result is None or not result: + + if result is None: return { "status" : "error", "result" : "Test results are missing" } if not field_present(result, "idcode"): @@ -82,8 +103,9 @@ class BoardID(SelfTestExecutor): if not field_present(result, "revision"): return { "status" : "error", "result" : "Board revision is not specified" } - return { "status" : "success", "result" : - f"{result['board']} rev. {result['revision']}; IDCODE=0x{result['idcode']:X}" } + if not field_present(result, "dna"): + return { "status" : "error", "result" : "DNA is not specified" } + return { "status" : "success", "result" : "OK" } diff --git a/templates/base.html b/templates/base.html index 4d066e3..d346a62 100644 --- a/templates/base.html +++ b/templates/base.html @@ -19,7 +19,7 @@ {% if "error" in board_id %} <span class="badge rounded-pill bg-danger">IDCODE READOUT ERROR</span> {% else %} - <span class="badge rounded-pill bg-primary">{{ "{:X}".format(board_id['idcode']) }}</span> + <span class="badge rounded-pill bg-primary">{{ "Rev {} | ID {} | DNA {}".format(board_id["revision"], board_id["idcode"], board_id["dna"]) }}</span> {% endif %} {% endif %} </h1></div> -- GitLab From bc7c48465bdd9f7dcf50934d8186267faf543b85 Mon Sep 17 00:00:00 2001 From: Carlo Alberto Gottardo <carlo.alberto.gottardo@cern.ch> Date: Wed, 7 Aug 2024 17:06:07 +0200 Subject: [PATCH 11/23] HWMON test ok --- boards/flx182.py | 2 +- models/sysmon.py | 53 ++++++++++++++++++++----------------------- templates/sysmon.html | 10 +++++--- 3 files changed, 32 insertions(+), 33 deletions(-) diff --git a/boards/flx182.py b/boards/flx182.py index b10b447..56fb66c 100644 --- a/boards/flx182.py +++ b/boards/flx182.py @@ -179,7 +179,7 @@ config = { } } }, - +# "jc42" : { "device_path" : "/sys/class/hwmon/", "title" : "JC-42.4", diff --git a/models/sysmon.py b/models/sysmon.py index 0139335..2ea9995 100644 --- a/models/sysmon.py +++ b/models/sysmon.py @@ -43,7 +43,6 @@ class SYSMON(SelfTestExecutor): def __init__(self, config): self.config = config - # Check if device is available def device_exists(self, device_class): if not device_class in self.config["device_classes"]: @@ -115,10 +114,10 @@ class SYSMON(SelfTestExecutor): check["msg"] = "{0} {1} is NaN".format(meas_type, name) elif (not math.isnan(max_value) and read_value > max_value) : check["status"] = "HIGH" - check["msg"] = "{0} {1} is {2} above max {3}".format(meas_type, name, read_value, max_value) + check["msg"] = "{0} {1} is {2} > max {3}".format(meas_type, name, read_value, max_value) elif (not math.isnan(min_value) and read_value < min_value): check["status"] = "LOW" - check["msg"] = "{0} {1} is {2} below min {3}".format(meas_type, name, read_value, min_value) + check["msg"] = "{0} {1} is {2} < min {3}".format(meas_type, name, read_value, min_value) else: check["status"] = "OK" return check @@ -129,7 +128,7 @@ class SYSMON(SelfTestExecutor): status_ok = True msg = [] for device_type in result: - if 'devices' not in device_type: + if 'devices' not in result[device_type]: if 'error' in result[device_type]: msg.append(result[device_type]["error"]) status_ok = False @@ -140,11 +139,13 @@ class SYSMON(SelfTestExecutor): continue for measurement_name in result[device_type]['devices'][device_path][quantity]: measurement = result[device_type]['devices'][device_path][quantity][measurement_name] + if "status" not in measurement: + continue if measurement["status"] != "OK": msg.append(measurement["msg"]) status_ok = False if status_ok: - msg = ["OK"] + msg = "OK" msg_level = "success" else: msg_level = "error" @@ -177,7 +178,7 @@ class SYSMON(SelfTestExecutor): # Data has to be reformatted to have the same format as versal-sysmon's def process_tmp(self, result, class_config): compiled_patterns = compile_patterns(class_config["patterns"]) - new_devices = {'/sys/class/hwmon/hwmonX' : {}} + new_devices = {'/sys/class/hwmon/hwmonX' : {'temperature' : {} }} for device_path, device_data in result["devices"].items(): probe_name = device_data['name'] local_value = device_data['probe']['temp1_input']/1000.0 @@ -191,9 +192,9 @@ class SYSMON(SelfTestExecutor): measurement["desc"] = class_config["reference"]["probe"][probe_name]["desc"] # Check value - check = self.check_measured_value(quantity, measurement_name, value, new_value["min"], new_value["max"]) + check = self.check_measured_value('temperature', probe_name, probe_value, measurement["min"], measurement["max"]) measurement = {**measurement, **check} - new_devices['/sys/class/hwmon/hwmonX'][probe_name] = measurement + new_devices['/sys/class/hwmon/hwmonX']['temperature'][probe_name] = measurement result['devices'] = new_devices return result @@ -208,17 +209,9 @@ class SYSMON(SelfTestExecutor): 'min': data['voltage_min'].get(f'{key}_min', float('nan'))/1000.0, 'max': data['voltage_max'].get(f'{key}_max', float('nan'))/1000.0 } - check = check_measured_value('voltage', key, new_device_data["read"], new_device_data["min"], new_device_data["max"]) - new_device_data = {**new_device_data, **check} - - for key in ['curr1', 'curr2', 'curr3']: - new_device_data['current'][key] = { - 'read': data['current'].get(f'{key}_input', float('nan'))/1000.0, - 'min': float('nan'), - 'max': data['current_max'].get(f'{key}_max', float('nan')) - } - check = check_measured_value('current', key, new_device_data["read"], new_device_data["min"], new_device_data["max"]) - new_device_data = {**new_device_data, **check} + d = new_device_data['voltage'][key] + check = self.check_measured_value('voltage', key, d["read"], d["min"], d["max"]) + new_device_data['voltage'][key] = {**new_device_data['voltage'][key], **check} for key in ['curr1', 'curr2', 'curr3']: new_device_data['current'][key] = { @@ -226,8 +219,9 @@ class SYSMON(SelfTestExecutor): 'min': float('nan'), 'max': data['current_max'].get(f'{key}_max', float('nan'))/1000.0 } - check = check_measured_value('current', key, new_device_data["read"], new_device_data["min"], new_device_data["max"]) - new_device_data = {**new_device_data, **check} + d = new_device_data['current'][key] + check = self.check_measured_value('current', key, d["read"], d["min"], d["max"]) + new_device_data['current'][key] = {**new_device_data['current'][key], **check} for key in ['power1', 'power2', 'power3']: new_device_data['power'][key] = { @@ -235,8 +229,9 @@ class SYSMON(SelfTestExecutor): 'min': float('nan'), 'max': float('nan') } - check = check_measured_value('current', key, new_device_data["read"], new_device_data["min"], new_device_data["max"]) - new_device_data = {**new_device_data, **check} + d = new_device_data['power'][key] + check = self.check_measured_value('power', key, d["read"], d["min"], d["max"]) + new_device_data['power'][key] = {**new_device_data['power'][key], **check} for key in ['temp1', 'temp2', 'temp3']: new_device_data['temperature'][key] = { @@ -244,8 +239,9 @@ class SYSMON(SelfTestExecutor): 'min': float('nan'), 'max': data['temp_max'].get(f'{key}_max', float('nan'))/1000.0 } - check = check_measured_value('current', key, new_device_data["read"], new_device_data["min"], new_device_data["max"]) - new_device_data = {**new_device_data, **check} + d = new_device_data['temperature'][key] + check = self.check_measured_value('temperature', key, d["read"], d["min"], d["max"]) + new_device_data['temperature'][key] = {**new_device_data['temperature'][key], **check} result["devices"][device_path] = new_device_data return result @@ -261,11 +257,10 @@ class SYSMON(SelfTestExecutor): measurement["min"] = class_config['reference']['probe'][name]["min"] measurement["max"] = class_config['reference']['probe'][name]["max"] measurement["desc"] = class_config['reference']['probe'][name]["desc"] - measurement = {"read" : value, "min" : min_value, "max": max_value, "desc" : description} - check = check_measured_value('temperature', name, value, measurement["min"], measurement["max"]) + check = self.check_measured_value('temperature', name, value, measurement["min"], measurement["max"]) measurement = {**measurement, **check} - result['devices']['/sys/class/hwmon/hwmon8'] = {} - result['devices']['/sys/class/hwmon/hwmon8'][name] = measurement + result['devices']['/sys/class/hwmon/hwmon8'] = {"temperature" : {}} + result['devices']['/sys/class/hwmon/hwmon8']["temperature"][name] = measurement return result \ No newline at end of file diff --git a/templates/sysmon.html b/templates/sysmon.html index 34a100d..5e0aa38 100644 --- a/templates/sysmon.html +++ b/templates/sysmon.html @@ -11,19 +11,21 @@ <th scope="col">Sensor</th> <th scope="col">Local temp [deg C]</th> <th scope="col">Probe temp [deg C]</th> - <th scope="col">Max [deg C]</th> + <th scope="col">Probe max [deg C]</th> + <th scope="col">Status</th> <th scope="col">Description</th> </tr> </thead> <tbody> {% for device_path, device_data in data["devices"].items() | sort %} - {% for name, value in device_data.items() | sort %} + {% for name, value in device_data["temperature"].items() | sort %} <tr> <th scope="row">{{name}}</th> <td>{{ "{:.1f}".format(value["local"]) }}</td> <td>{{ "{:.1f}".format(value["probe"]) }}</td> <td>{{ "{:.1f}".format(value["max"])}}</td> + <td>{{ value["status"]}}</td> <td>{{ value["desc"] }}</td> </tr> {% endfor %} @@ -105,17 +107,19 @@ <th scope="col">Device</th> <th scope="col">Temperature [deg C]</th> <th scope="col">Max Temp [deg C]</th> + <th scope="col">Status</th> </tr> </thead> <tbody> {% for device_path, device_data in data["devices"].items() | sort %} - {% for key, meas in device_data.items() | sort %} + {% for key, meas in device_data["temperature"].items() | sort %} <tr> <th scope="row">{{key}}</th> <td>{{ "{:.3f}".format(meas["read"]) }} </td> <td>{{ "{:.3f}".format(meas["max"]) }} </td> + <td>{{ meas["status"] }} </td> </tr> {% endfor %} {% endfor %} -- GitLab From c279e6fe2e8b5a89a43171ca82719be01ea84735 Mon Sep 17 00:00:00 2001 From: Carlo Alberto Gottardo <carlo.alberto.gottardo@cern.ch> Date: Wed, 7 Aug 2024 18:02:58 +0200 Subject: [PATCH 12/23] INA226 test --- boards/flx182.py | 36 +++++++++++++++++++-------- models/board_id.py | 2 +- models/ina226.py | 58 +++++++++++++++++++++++++++++++++++++------ models/sysmon.py | 6 ++--- templates/ina226.html | 4 +++ 5 files changed, 84 insertions(+), 22 deletions(-) diff --git a/boards/flx182.py b/boards/flx182.py index 56fb66c..525be38 100644 --- a/boards/flx182.py +++ b/boards/flx182.py @@ -43,16 +43,30 @@ config = { }, #tolerance and max current set by hand "reference" : { - "12P0V" : {"V" : 12.00, "V_min" : 11.0, "V_max" : 23.0, "I" : 1, "I_max" : 8, "desc" : "+/- 1V expected from power supply"}, - "MGTAVCC" : {"V" : 0.88 , "V_min" : 0.854, "V_max" : 0.906, "I" : 1.5 , "I_max" : 3.5, "desc" : "V limits from FPGA recommended ranges"}, - "MGTAVTT" : {"V" : 1.20 , "V_min" : 1.164, "V_max" : 1.236, "I" : 3.4 , "I_max" : 6.5, "desc" : "V limits from FPGA recommended ranges"}, - "SYS12" : {"V" : 1.20 , "V_min" : 1.164, "V_max" : 1.236, "I" : 0.8 , "I_max" : 1.5, "desc" : "V limits from FPGA recommended ranges"}, - "SYS15" : {"V" : 1.50 , "V_min" : 1.455, "V_max" : 1.545, "I" : 0.9 , "I_max" : 1.5, "desc" : "V limits from FPGA recommended ranges"}, - "SYS18" : {"V" : 1.80 , "V_min" : 1.710, "V_max" : 1.890, "I" : 0.8 , "I_max" : 1.5, "desc" : "V limits from 25G FF"}, - "SYS25" : {"V" : 2.50 , "V_min" : 2.15, "V_max" : 2.85, "I" : 0.3 , "I_max" : 0.5, "desc" : ""}, - "SYS33" : {"V" : 3.30 , "V_min" : 3.15, "V_max" : 3.45, "I" : 3.30 , "I_max" : 6.0, "desc" : "V limits from 14/16G FF"}, - "SYS38" : {"V" : 3.80 , "V_min" : 3.50, "V_max" : 4.10, "I" : 0.0 , "I_max" : 5, "desc" : ""}, - "VCCINT" : {"V" : 0.80 , "V_min" : 0.775, "V_max" : 0.825, "I" : 20.0 , "I_max" : 50.0,"desc" : ""} + "voltage" : { + "12P0V" : {"nominal" : 12.00, "min" : 11.0, "max" : 23.0, "desc" : "+/- 1V expected from power supply"}, + "MGTAVCC" : {"nominal" : 0.88 , "min" : 0.854, "max" : 0.906, "desc" : "V limits from FPGA recommended ranges"}, + "MGTAVTT" : {"nominal" : 1.20 , "min" : 1.164, "max" : 1.236, "desc" : "V limits from FPGA recommended ranges"}, + "SYS12" : {"nominal" : 1.20 , "min" : 1.164, "max" : 1.236, "desc" : "V limits from FPGA recommended ranges"}, + "SYS15" : {"nominal" : 1.50 , "min" : 1.455, "max" : 1.545, "desc" : "V limits from FPGA recommended ranges"}, + "SYS18" : {"nominal" : 1.80 , "min" : 1.710, "max" : 1.890, "desc" : "V limits from 25G FF"}, + "SYS25" : {"nominal" : 2.50 , "min" : 2.15, "max" : 2.85, "desc" : ""}, + "SYS33" : {"nominal" : 3.30 , "min" : 3.15, "max" : 3.45, "desc" : "V limits from 14/16G FF"}, + "SYS38" : {"nominal" : 3.80 , "min" : 3.50, "max" : 4.10, "desc" : ""}, + "VCCINT" : {"nominal" : 0.80 , "min" : 0.775, "max" : 0.825, "desc" : ""} + }, + "current" : { + "12P0V" : {"nominal" : 1, "max" : 8, "desc" : ""}, + "MGTAVCC" : {"nominal" : 1.5 , "max" : 3.5, "desc" : ""}, + "MGTAVTT" : {"nominal" : 3.4 , "max" : 6.5, "desc" : ""}, + "SYS12" : {"nominal" : 0.8 , "max" : 1.5, "desc" : ""}, + "SYS15" : {"nominal" : 0.9 , "max" : 1.5, "desc" : ""}, + "SYS18" : {"nominal" : 0.8 , "max" : 1.5, "desc" : ""}, + "SYS25" : {"nominal" : 0.3 , "max" : 0.5, "desc" : ""}, + "SYS33" : {"nominal" : 3.30 , "max" : 6.0, "desc" : ""}, + "SYS38" : {"nominal" : 0.0 , "max" : 5, "desc" : ""}, + "VCCINT" : {"nominal" : 20.0 , "max" : 50.0, "desc" : ""} + } } }, @@ -179,7 +193,7 @@ config = { } } }, -# + "jc42" : { "device_path" : "/sys/class/hwmon/", "title" : "JC-42.4", diff --git a/models/board_id.py b/models/board_id.py index a139c2d..2b13549 100644 --- a/models/board_id.py +++ b/models/board_id.py @@ -106,6 +106,6 @@ class BoardID(SelfTestExecutor): if not field_present(result, "dna"): return { "status" : "error", "result" : "DNA is not specified" } - return { "status" : "success", "result" : "OK" } + return { "status" : "success", "result" : result["dna"] } diff --git a/models/ina226.py b/models/ina226.py index 89b53b7..e2332da 100644 --- a/models/ina226.py +++ b/models/ina226.py @@ -1,4 +1,5 @@ import pdb +import math from os import path from os.path import isdir from util.iio import load_file, get_devices @@ -14,6 +15,22 @@ class INA226(SelfTestExecutor): self.devices = get_devices(self.device_path, self.name) + def check_measured_value(self, meas_type, name, read_value, min_value, max_value): + check = {"status" : "", "msg" : ""} + if math.isnan(read_value): + check["status"] = "BAD" + check["msg"] = "{0} {1} NaN".format(meas_type, name) + elif (not math.isnan(max_value) and read_value > max_value) : + check["status"] = "HIGH" + check["msg"] = "{0} {1} {2} > max {3}".format(meas_type, name, read_value, max_value) + elif (not math.isnan(min_value) and read_value < min_value): + check["status"] = "LOW" + check["msg"] = "{0} {1} {2} < min {3}".format(meas_type, name, read_value, min_value) + else: + check["status"] = "OK" + return check + + # returns hashmap of all readings available for this device def get_data(self, device): if not isdir(device): @@ -41,19 +58,24 @@ class INA226(SelfTestExecutor): V_tol = -1 I_max = -1 - if label in self.config["reference"]: - V_min = self.config["reference"][label]["V_min"] - V_max = self.config["reference"][label]["V_max"] - I_max = self.config["reference"][label]["I_max"] + if label in self.config["reference"]["voltage"]: + V_min = self.config["reference"]["voltage"][label]["min"] + V_max = self.config["reference"]["voltage"][label]["max"] + + if label in self.config["reference"]["current"]: + I_max = self.config["reference"]["current"][label]["max"] data = { "V" : voltage, "V_min" : V_min, "V_max" : V_max, + "V_status" : self.check_measured_value('voltage', label, voltage, V_min, V_max)["status"], + "V_msg" : self.check_measured_value('voltage', label, voltage, V_min, V_max)["msg"], "I" : current, "I_max" : I_max, - "P" : power, - "R_shunt" : r_shunt / 1000.0 + "I_status" : self.check_measured_value('current', label, current, float('nan'), I_max)["status"], + "I_msg" : self.check_measured_value('current', label, current, float('nan'), I_max)["msg"], + "P" : power } return data, label @@ -62,7 +84,6 @@ class INA226(SelfTestExecutor): # returns data for all devices def read_all(self): result = {} - for device in self.devices: device_data = self.get_data(device) if device_data: @@ -70,3 +91,26 @@ class INA226(SelfTestExecutor): result[label] = data return result + + def self_test_main(self, **kwargs): + return self.read_all() + + + def self_test_check_result(self, result): + status_ok = True + msg = [] + for entry in result: + if result[entry]["V_status"] != "OK": + status_ok = False + msg.append(result[entry]["V_msg"]) + if result[entry]["I_status"] != "OK": + status_ok = False + msg.append(result[entry]["I_msg"]) + + if status_ok: + msg = "OK" + msg_level = "success" + else: + msg_level = "error" + + return { "status" : msg_level, "result" : msg} \ No newline at end of file diff --git a/models/sysmon.py b/models/sysmon.py index 2ea9995..32c43fe 100644 --- a/models/sysmon.py +++ b/models/sysmon.py @@ -111,13 +111,13 @@ class SYSMON(SelfTestExecutor): check = {"status" : "", "msg" : ""} if math.isnan(read_value): check["status"] = "BAD" - check["msg"] = "{0} {1} is NaN".format(meas_type, name) + check["msg"] = "{0} {1} NaN".format(meas_type, name) elif (not math.isnan(max_value) and read_value > max_value) : check["status"] = "HIGH" - check["msg"] = "{0} {1} is {2} > max {3}".format(meas_type, name, read_value, max_value) + check["msg"] = "{0} {1} {2} > max {3}".format(meas_type, name, read_value, max_value) elif (not math.isnan(min_value) and read_value < min_value): check["status"] = "LOW" - check["msg"] = "{0} {1} is {2} < min {3}".format(meas_type, name, read_value, min_value) + check["msg"] = "{0} {1} {2} < min {3}".format(meas_type, name, read_value, min_value) else: check["status"] = "OK" return check diff --git a/templates/ina226.html b/templates/ina226.html index 4ef15ca..c2d3998 100644 --- a/templates/ina226.html +++ b/templates/ina226.html @@ -10,8 +10,10 @@ <th scope="col">Name</th> <th scope="col">Voltage (V)</th> <th scope="col">V range (V)</th> + <th scope="col">V status</th> <th scope="col">I (A)</th> <th scope="col">Max I (A)</th> + <th scope="col">I status</th> <th scope="col">P [W]</th> </tr> </thead> @@ -22,8 +24,10 @@ <th scope="row">{{ label }}</th> <td>{{ "{:.3f}".format(device["V"]) }}</td> <td>{{ "[{:.3f}, {:.3f}]".format(device["V_min"], device["V_max"]) }}</td> + <td>{{ device["V_status"] }}</td> <td>{{ "{:.3f}".format(device["I"]) }}</td> <td>{{ "{:.3f}".format(device["I_max"]) }}</td> + <td>{{ device["I_status"] }}</td> <td>{{ "{:.3f}".format(device["P"]) }}</td> </tr> {% endfor %} -- GitLab From fbdfb0d5929e1ae517f131b98ad42029eba49c55 Mon Sep 17 00:00:00 2001 From: Carlo Alberto Gottardo <carlo.alberto.gottardo@cern.ch> Date: Thu, 8 Aug 2024 15:41:13 +0200 Subject: [PATCH 13/23] Tests for SI570 and FFLY --- boards/flx182.py | 6 ++++++ models/sfp.py | 47 ++++++++++++++++++++++++++++++++++++++++++++++- models/si570.py | 26 ++++++++++++++++++++++++-- 3 files changed, 76 insertions(+), 3 deletions(-) diff --git a/boards/flx182.py b/boards/flx182.py index 525be38..e0e03c7 100644 --- a/boards/flx182.py +++ b/boards/flx182.py @@ -379,6 +379,7 @@ config = { "i2c_bus" : "/dev/i2c-8", "i2c_addr" : 0x50, "type" : "CERN-B-* Transmitter", + "max_temp" : 75, # "select" : { # "gpio" : "gpiochip3", # "line" : 6, @@ -389,6 +390,7 @@ config = { "type" : "CERN-B-* Receiver", "i2c_bus" : "/dev/i2c-8", "i2c_addr" : 0x54, + "max_temp" : 75, # "select" : { # "gpio" : "gpiochip3", # "line" : 2, @@ -399,6 +401,7 @@ config = { "type" : "CERN-B-* Transmitter", "i2c_bus" : "/dev/i2c-9", "i2c_addr" : 0x50, + "max_temp" : 75, # "select" : { # "gpio" : "gpiochip3", # "line" : 14, @@ -409,6 +412,7 @@ config = { "type" : "CERN-B-* Receiver", "i2c_bus" : "/dev/i2c-9", "i2c_addr" : 0x54, + "max_temp" : 75, # "select" : { # "gpio" : "gpiochip3", # "line" : 10, @@ -416,8 +420,10 @@ config = { # } }, "FireFly_J29" : { + "type" : "B04 Transceiver", "i2c_bus" : "/dev/i2c-10", "i2c_addr" : 0x50, + "max_temp" : 75, # "select" : { # "gpio" : "gpiochip3", # "line" : 18, diff --git a/models/sfp.py b/models/sfp.py index f75bdc5..622d755 100644 --- a/models/sfp.py +++ b/models/sfp.py @@ -13,7 +13,6 @@ class SFP(SelfTestExecutor): # returns configuration of all known SI570 devices def read_all(self): data = {} - try: for name, config in self.devices.items(): device = SFP_Device(config) @@ -22,3 +21,49 @@ class SFP(SelfTestExecutor): return {"error" : "Can't read SFP devices: {}".format(err)} return data + + + def self_test_main(self, **kwargs): + return self.read_all() + + + def self_test_check_result(self, result): + msg_level = "success" + msg = [] + + if len(result.keys()) is not 5: + msg_level = "error" + + for label in self.config["mapping"].keys(): + + # Missing FF + if label not in result.keys(): + msg_level = "error" + msg.append("{} not detected".format(label)) + continue + + # Wrong FF type + reference = self.config["mapping"][label] + reading = result[label] + + expected_type = reference['type'] + expected_y12 = True if "CERN" in expected_type else False + read_part_number = reading['part_number'] + if expected_y12 and "Y12" not in read_part_number: + msg_level = "error" + msg.append("{} is not a Y12 module. (P/N: {})".format(label, read_part_number)) + if not expected_y12 and "B04" not in read_part_number: + msg_level = "error" + msg.append("{} is not a B04 module (P/N: {})".format(label, read_part_number)) + + # Temperature + ref_value = reference['max_temp'] + read_value = reading['temperature'] + if read_value > ref_value: + msg_level = "error" + msg.append("{} temp {} > {}".format(label, read_value, ref_value)) + + if msg_level == "success": + msg = "OK" + + return { "status" : msg_level, "result" : msg} diff --git a/models/si570.py b/models/si570.py index f86824f..59982da 100644 --- a/models/si570.py +++ b/models/si570.py @@ -2,7 +2,7 @@ import pdb from functools import wraps from util.si570 import read_device, set_frequency, reset, load_nvm -from util.si570 import fmin_MHz, fmax_MHz, compute_fxtal, fxtal_MHz_nominal +from util.si570 import fmin_MHz, fmax_MHz, compute_fxtal, fxtal_MHz_nominal, read_default_frequency from util.i2c import I2CError from threading import Lock @@ -159,7 +159,29 @@ class SI570(SelfTestExecutor): return result + def compare_clocks(self, name, fout, fref, ppm): + if abs(fout - fref) > 2*ppm*1e-6*fref: + return "Clock {} at {:.6f} MHz instead of {:.6f}".format(name, fout, fref) + else: + return "OK" + + def self_test_check_result(self, result): - return self.self_test_check_device_list(result) + device_check = self.self_test_check_device_list(result) + device_check['result'] = [device_check['result']] + for device in result: + reading = result[device] + if "error" in reading: + continue + else: + fout = reading['FOUT'] + fref = self.config["mapping"][device]["freq_MHz"] + ppm = float(self.config["mapping"][device]["stability"].strip('ppm')) + check = "OK" #self.compare_clocks(device, fout, fref, ppm) + if check != "OK": + device_check['status'] = "error" + device_check['result'].append(check) + + return { "status" : device_check['status'], "result" : device_check['result']} -- GitLab From acc44535590a081873c893f37012a93be46a0779 Mon Sep 17 00:00:00 2001 From: Eric Buschmann <eric.buschmann@cern.ch> Date: Thu, 8 Aug 2024 19:27:33 +0000 Subject: [PATCH 14/23] Add FLX-182B and ADM1266 --- boards/flx182.py | 4 +- boards/flx182b.py | 1279 ++++++++++++++++++++++++++++++++++++++++ controllers/adm1266.py | 25 + models/adm1266.py | 44 ++ routes/__init__.py | 9 + templates/adm1266.html | 69 +++ templates/base.html | 4 + util/adm1266.py | 92 +++ 8 files changed, 1524 insertions(+), 2 deletions(-) create mode 100644 boards/flx182b.py create mode 100644 controllers/adm1266.py create mode 100644 models/adm1266.py create mode 100644 templates/adm1266.html create mode 100644 util/adm1266.py diff --git a/boards/flx182.py b/boards/flx182.py index fb3b38a..ffb1bdb 100644 --- a/boards/flx182.py +++ b/boards/flx182.py @@ -1124,7 +1124,7 @@ config = { }, "ff2_pma_near_loopback" : { - "comment" : "FireFly 2 (J27, J27) Near-End PMA Loopback", + "comment" : "FireFly 2 (J27, J28) Near-End PMA Loopback", "links" : [ "FF2_0", "FF2_1", "FF2_2", "FF2_3", "FF2_4", "FF2_5", "FF2_6", "FF2_7", "FF2_8", "FF2_9", "FF2_10", "FF2_11", ], @@ -1147,7 +1147,7 @@ config = { }, "ff2_fiber_loopback" : { - "comment" : "FireFly 2 (J27, J27) Physical Loopback", + "comment" : "FireFly 2 (J27, J28) Physical Loopback", "links" : [ "FF2_0", "FF2_1", "FF2_2", "FF2_3", "FF2_4", "FF2_5", "FF2_6", "FF2_7", "FF2_8", "FF2_9", "FF2_10", "FF2_11", ], diff --git a/boards/flx182b.py b/boards/flx182b.py new file mode 100644 index 0000000..b0df411 --- /dev/null +++ b/boards/flx182b.py @@ -0,0 +1,1279 @@ +__author__ = "Elena Zhivun" +__version__ = "0.0.1" +__maintainer__ = "Elena Zhivun" +__email__ = "elena.zhivun@cern.ch" + + +# This frequency will be assumed for the reference clocks on IN1 of SI5345_A +# and SI5345_B in case if the alternative part is used that doesn't have I2C +# communications +default_si570_frequency = 40.08 + +# Possible alternative frequencies for SI570 chips at IN1 of SI5345_A and SI5345_B +alt_si570_frequencies = [200.0] + +# Change the settings below to match your platform + +config = { + "global" : { + "title" : "FLX182 system monitor" + }, + + "board_id" : { + "interface" : "zynq_mpsoc", + "board" : "FLX-182", + "revision" : "3_1b", + "self_test" : { + "description" : "Identify the board", + } + }, + + "self_test" : { + "endpoint" : "https://bnl-board-database.web.cern.ch", + }, + + # fancy summary table for INA226 + # TODO: merge with HWMON + "ina226" : { + "device_path" : "/sys/bus/iio/devices/", + "name" : "ina226", + "self_test" : { + "description" : "INA226 chip readout", + } + }, + + # crudely summarize IIO/HWMON devices with available driver + # "name" in the regular expression determines the row title + # TODO: this class should be handling INA226 + "hwmon" : { + "device_classes" : { + "xlnx,versal-sysmon" : { + "device_path" : "/sys/bus/iio/devices/", + "title" : "SYSMON", + "patterns" : { + "voltage" : "in_voltage(?P<id>\\d+)_(?P<name>.+)_input", + "temperature" : "in_temp(?P<id>\\d+)_(?P<name>.+)_input", + }, + }, + + "ltm4700" : { + "device_path" : "/sys/class/hwmon/", + "title" : "LTM4700", + "patterns" : { + "voltage" : "(?P<name>in\\d+_input)", + "current" : "(?P<name>curr\\d+_input)", + "temp" : "(?P<name>temp\\d+_input)", + "power" : "(?P<name>power\\d+_input)", + }, + }, + + "tmp435" : { + "device_path" : "/sys/class/hwmon/", + "title" : "TMP435", + "patterns" : { + "probe" : "(?P<name>temp\\d+_input)", + }, + "self_test" : { + "description" : "TMP435 readout", + } + }, + + "jc42" : { + "device_path" : "/sys/class/hwmon/", + "title" : "JC-42.4", + "patterns" : { + "probe" : "(?P<name>temp\\d+_input)", + }, + }, + }, + "self_test" : { + "description" : "HWMON device readout (SYSMON, TMP435, etc)", + } + }, + + + "si53156" : { + "mapping" : { + "U36" : { + "i2c_bus" : "/dev/i2c-7", + "i2c_addr" : 0x6b, + "name" : "PCIe clk buffer (U37)" + }, + }, + + "self_test" : { + "description" : "Probe SI53156", + } + }, + + + # displays clocks listed in Linux device tree and + # controlled by kernel via the Common Clock Framework + # "ccf_clocks" : { + # "whitelist" : [ + # "si570_sys_clk_40_for_SI5345A", + # "si570_sys_clk_40_for_SI5345B", + # "si570_sys_clk_100", + # "si570_lti_ref_clk", + # "si570_100G_ref_clk", + # "si570_ref_clk" + # ], + # "clk_dump_path" : "/sys/kernel/debug/clk/clk_dump" + # }, + + + #"adm106x" : { + # "mapping" : { + # "U68" : { + # "i2c_bus" : "/dev/i2c-6", + # "i2c_addr" : 0x34, + # }, + # "U69" : { + # "i2c_bus" : "/dev/i2c-6", + # "i2c_addr" : 0x35, + # }, + # }, + + # "self_test" : { + # "description" : "ADM106x chip readout", + # } + #}, + + "adm1266" : { + "mapping" : { + "U68" : { + "i2c_bus" : "/dev/i2c-6", + "i2c_addr" : 0x40, + }, + }, + + "self_test" : { + "description" : "ADM1266 chip readout", + } + }, + + "si5345" : { + "mapping" : { + "si5345_a" : { + "comment" : "SI5345_A (U60)", + "i2c_bus" : "/dev/i2c-11", + "i2c_addr" : 0x68, + # if the device is found at one of the alternative addresses, + # it's base I2C address will be updated to match the i2c_addr + "i2c_addr_alt" : [0x7c], + "f_xaxb_MHz" : 48.0, + "f_in0_MHz" : 125.0, + "f_in1_MHz" : 40.08, + "f_in2_MHz" : 0.0, + "f_in3_MHz" : 0.0, + "in_sel" : 0b00, # device in_sel pins value + }, + "si5345_b" : { + "comment" : "SI5345_B (U59)", + "i2c_bus" : "/dev/i2c-11", + "i2c_addr" : 0x69, + "i2c_addr_alt" : [0x7d], + "f_xaxb_MHz" : 48.0, + "f_in0_MHz" : 40.08, + "f_in1_MHz" : 40.08, + "f_in2_MHz" : 0.0, + "f_in3_MHz" : 0.0, + "in_sel" : 0b00, # device in_sel pins value + }, + }, + + "self_test" : { + "description" : "SI5345 readout", + } + }, + + # si569 might be replaced by Crystek CVPD-922 + "si570" : { + # Valid stability values: 7ppm, 20ppm, 50ppm + + # Protected flag forbids updating the clock, for example + # because the system will become unstable if it is touched + + # If system or memory clock are not marked as protected + # the webapp will freeze the OS on startup since it + # resets the clocks to calculate fxtal + + "mapping" : { + + "ddr4_clk" : { + "i2c_bus" : "/dev/i2c-6", + "i2c_addr" : 0x60, + "freq_MHz" : 200, + "stability" : "20ppm", + "protected" : True, + }, + + "sys_clk_100" : { + "i2c_bus" : "/dev/i2c-7", + "i2c_addr" : 0x55, + "freq_MHz" : 100, + "stability" : "20ppm", + "protected" : False, + }, + + # NOTE: alternative part may be placed + "SI5345A_ref_clk" : { + "i2c_bus" : "/dev/i2c-7", + "i2c_addr" : 0x60, + "freq_MHz" : default_si570_frequency, + "stability" : "20ppm", + "protected" : False, + }, + + # NOTE: alternative part may be placed + "SI5345B_ref_clk" : { + "i2c_bus" : "/dev/i2c-8", + "i2c_addr" : 0x60, + "freq_MHz" : default_si570_frequency, + "stability" : "20ppm", + "protected" : False, + }, + + # NOTE: alternative part may be placed + "lti_ref_clk" : { + "i2c_bus" : "/dev/i2c-9", + "i2c_addr" : 0x60, + "freq_MHz" : 240.474, + "stability" : "20ppm", + "protected" : False, + }, + + "100G_ref_clk" : { + "i2c_bus" : "/dev/i2c-10", + "i2c_addr" : 0x60, + "freq_MHz" : 322.265625, + "stability" : "20ppm", + "protected" : False, + }, + + "ps_ref_clk" : { + "i2c_bus" : "/dev/i2c-11", + "i2c_addr" : 0x5d, + "freq_MHz" : 33.333333, # schematic says 30.3333333? + "stability" : "20ppm", + "protected" : True, + }, + }, + "self_test" : { + "description" : "SI570 device readout", + "warn_on_error" : True, + } + }, + + "sfp" : { + "mapping" : { + "FireFly_J36" : { + "i2c_bus" : "/dev/i2c-8", + "i2c_addr" : 0x50, + "type" : "CERN-B-* Transmitter", + # "select" : { + # "gpio" : "gpiochip3", + # "line" : 6, + # "active_level" : 0 + # } + }, + "FireFly_J35" : { + "type" : "CERN-B-* Receiver", + "i2c_bus" : "/dev/i2c-8", + "i2c_addr" : 0x54, + # "select" : { + # "gpio" : "gpiochip3", + # "line" : 2, + # "active_level" : 0 + # } + }, + "FireFly_J33" : { + "type" : "CERN-B-* Transmitter", + "i2c_bus" : "/dev/i2c-9", + "i2c_addr" : 0x50, + # "select" : { + # "gpio" : "gpiochip3", + # "line" : 14, + # "active_level" : 0 + # } + }, + "FireFly_J32" : { + "type" : "CERN-B-* Receiver", + "i2c_bus" : "/dev/i2c-9", + "i2c_addr" : 0x54, + # "select" : { + # "gpio" : "gpiochip3", + # "line" : 10, + # "active_level" : 0 + # } + }, + "FireFly_J34" : { + "i2c_bus" : "/dev/i2c-10", + "i2c_addr" : 0x50, + # "select" : { + # "gpio" : "gpiochip3", + # "line" : 18, + # "active_level" : 0 + # } + }, + }, + "self_test" : { + "description" : "SFP and FireFly module readout", + } + }, + + "process_runners" : { + "memtester" : { + "binary" : ["/usr/bin/memtester", "/usr/sbin/memtester"], + "mask_variable" : "MEMTESTER_TEST_MASK", + "mask_default" : "6144", + "name" : "memtester", + "title" : "DRAM test", + "self_test" : { + "description" : "DRAM module test", + } + }, + + "iperf3" : { + "binary" : ["/usr/bin/iperf3"], + "name" : "iperf3", + "title" : "Ethernet", + "self_test" : { + "description" : "Ethernet test", + } + }, + + "mtd" : { + "binary" : ["<app_root_path>/executables/mtd_test.sh"], + "name" : "mtd", + "default_device" : 4, + "title" : "QSPI flash", + "self_test" : { + "description" : "QSPI flash test", + } + } + }, + + "gpio" : { + "self_test" : { + "description" : "GPIO readout", + }, + "mapping" : { + "gpiochip0" : { + "comment" : "Versal AXI GPIO", + "lines" : { + # GPIO_0 port in Vivado + 0 : { + "label" : "LED_2", + "direction" : "out", + "value" : False + }, + 1 : { + "label" : "i2c_sw_reset_b", + "direction" : "out", + "value" : True + }, + 2 : { + "label" : "LED_1", + "direction" : "out", + "value" : False + }, + 3 : { + "label" : "LED_0", + "direction" : "out", + "value" : False + }, + 4 : { + "label" : "LED_3", + "direction" : "out", + "value" : False + }, + 5 : { + "label" : "fan_fail_b", + "direction" : "in" + }, + 6 : { + "label" : "fan_fullsp", + "direction" : "in" + }, + 7 : { + "label" : "pcie_perst_b", + "direction" : "in" + }, + 8 : { + "label" : "ff3_prsnt_b", + "direction" : "in" + }, + 9 : { + "label" : "ioexpan1_intr_b", + "direction" : "in", + }, + 10 : { + "label" : "fan_overtemp_b", + "direction" : "in" + }, + 11 : { + "label" : "fan_pwm_out", + "direction" : "in" + }, + 12 : { + "label" : "ioexpand2_rst_b", + "direction" : "out", + "value" : True + }, + 13 : { + "label" : "ioexpand2_intr_b", + "direction" : "in" + }, + 14 : { + "label" : "fan_tach", + "direction" : "in" + }, + 15 : { + "label" : "pcie_wake_b", + "direction" : "out", + "value" : True, + }, + 16 : { + "label" : "ioexpand1_rst_b", + "direction" : "out", + "value" : True + }, + + # There is gpio-hog on these lines + # 17 : { + # "label" : "qspi1_rst_b (R433 DNP)", + # "direction" : "out", + # "value" : True + # }, + # 18 : { + # "label" : "qspi_rst_b", + # "direction" : "out", + # "value" : True + # }, + # 19 : { + # "label" : "qspi0_rst_b (R432 DNP)", + # "direction" : "out", + # "value" : True + # }, + + 20 : { + "label" : "ARM_CPU_controls_GPIO", + "direction" : "out", + "value" : False + }, + + # GPIO_1 port in Vivado + 21 : { + "label" : "si5345a_sa1", + "direction" : "out", + "value" : False + }, + 22 : { + "label" : "si5345b_rst_b", + "direction" : "out", + "value" : True + }, + 23 : { + "label" : "si5345a_lol_b", + "direction" : "in" + }, + 24 : { + "label" : "si5345a_finc", + "direction" : "out", + "value" : False + }, + 25 : { + "label" : "si5345b_sa0", + "direction" : "out", + "value" : True + }, + 26 : { + "label" : "si5345a_fdec", + "direction" : "out", + "value" : False + }, + 27 : { + "label" : "si5345b_fdec", + "direction" : "out", + "value" : False + }, + 28 : { + "label" : "si5345b_lol_b", + "direction" : "in" + }, + 29 : { + "label" : "si5345a_intr_b", + "direction" : "in" + }, + 30 : { + "label" : "si5345a_output_enable_b", + "direction" : "out", + "value" : False + }, + 31 : { + "label" : "si5345b_sa1", + "direction" : "out", + "value" : False + }, + 32 : { + "label" : "si5345b_intr_b", + "direction" : "in" + }, + 33 : { + "label" : "si5345a_sa0", + "direction" : "out", + "value" : False + }, + 34 : { + "label" : "si5345b_output_enable_b", + "direction" : "out", + "value" : False + }, + 35 : { + "label" : "si5345b_insel0", + "direction" : "out", + "value" : False + }, + 36 : { + "label" : "si5345b_insel1", + "direction" : "out", + "value" : False + }, + 37 : { + "label" : "si5345a_insel0", + "direction" : "out", + "value" : False + }, + 38 : { + "label" : "si5345a_rst_b", + "direction" : "out", + "value" : True + }, + 39 : { + "label" : "si5345b_finc", + "direction" : "out", + "value" : False + }, + 40 : { + "label" : "si5345a_insel1", + "direction" : "out", + "value" : False + }, + 41 : { + "label" : "pcie_pwrbrk", + "direction" : "in", + }, + } + }, + + + "gpiochip1" : { + "comment" : "Versal PMC Bank 1 GPIO", + "lines" : { + 37 : { + "label" : "ADM1066 VX1 (U68)", + "direction" : "out", + "value" : True, + }, + 38 : { + "label" : "PCIE_PERST_B (R337 DNP)", + "direction" : "in", + }, + 39 : { + "label" : "PCIE_PERST_B (R780 DNP)", + "direction" : "in" + }, + } + }, + + #"gpiochip2" : { + # "comment" : "ADM1266 GPIO (U33)", + #}, + + "gpiochip3" : { + "comment" : "I2C GPIO expander TCA6424A (U80)", + "lines" : { + 0 : { + "label" : "alert_sys12", + "direction" : "in" + }, + 1 : { + "label" : "alert_vcc_int", + "direction" : "in" + }, + 2 : { + "label" : "sys12_temp_alert_b", + "direction" : "in" + }, + 3 : { + "label" : "sys12_temp_err_b", + "direction" : "in" + }, + 4 : { + "label" : "sys15_temp_alert_b", + "direction" : "in" + }, + 5 : { + "label" : "alert_sys15", + "direction" : "in" + }, + 6 : { + "label" : "alert_sys33", + "direction" : "in" + }, + 7 : { + "label" : "alert_sys38", + "direction" : "in" + }, + 8 : { + "label" : "sys33_temp_alert_b", + "direction" : "in" + }, + 9 : { + "label" : "sys33_temp_err_b", + "direction" : "in", + }, + 10 : { + "label" : "ltm4700_alert_b", + "direction" : "in" + }, + 11 : { + "label" : "vcc_int_fault", + "direction" : "in" + }, + 12 : { + "label" : "sys18_temp_err_b", + "direction" : "in" + }, + 13 : { + "label" : "alert_sys18", + "direction" : "in" + }, + 14 : { + "label" : "sys18_temp_alert_b", + "direction" : "in" + }, + 15 : { + "label" : "alert_sys25", + "direction" : "in" + }, + 16 : { + "label" : "alert_mgtavcc", + "direction" : "in" + }, + 17 : { + "label" : "mgtavcc_temp_alert_b", + "direction" : "in" + }, + 18 : { + "label" : "mgtavcc_temp_err_b", + "direction" : "in" + }, + 19 : { + "label" : "alert_12p0v", + "direction" : "in" + }, + 20 : { + "label" : "mgtavtt_temp_err_b", + "direction" : "in" + }, + 21 : { + "label" : "mgtavtt_temp_alert_b", + "direction" : "in" + }, + 22 : { + "label" : "alert_mgtavtt", + "direction" : "in" + }, + 23 : { + "label" : "sys15_tmp_err_b", + "direction" : "in" + }, + } + }, + + + "gpiochip4" : { + "comment" : "I2C GPIO expander TCA6424A (U81)", + "lines" : { + 0 : { + "label" : "ff1_rx_rst_b", + "direction" : "out", + "value" : True + }, + 1 : { + "label" : "ff1_rx_intr_b", + "direction" : "in" + }, + 2 : { + # Mark as "in" if controlled by the SFP model + "label" : "ff1_rx_select_b", + "direction" : "out", + "value" : False + }, + 3 : { + "label" : "ff1_rx_prsnt_b", + "direction" : "in" + }, + + 4 : { + "label" : "ff1_tx_rst_b", + "direction" : "out", + "value" : True + }, + 5 : { + "label" : "ff1_tx_intr_b", + "direction" : "in" + }, + 6 : { + # Mark as "in" if controlled by the SFP model + "label" : "ff1_tx_select_b", + "direction" : "out", + "value" : False + }, + 7 : { + "label" : "ff1_tx_prsnt_b", + "direction" : "in" + }, + 8 : { + "label" : "ff2_rx_rst_b", + "direction" : "out", + "value" : True + }, + 9 : { + "label" : "ff2_rx_intr_b", + "direction" : "in", + }, + 10 : { + # Mark as "in" if controlled by the SFP model + "label" : "ff2_rx_select_b", + "direction" : "out", + "value" : False + }, + 11 : { + "label" : "ff2_rx_prsnt_b", + "direction" : "in" + }, + 12 : { + "label" : "ff2_tx_rst_b", + "direction" : "out", + "value" : True + }, + 13 : { + "label" : "ff2_tx_intr_b", + "direction" : "in" + }, + 14 : { + # Mark as "in" if controlled by the SFP model + "label" : "ff2_tx_select_b", + "direction" : "out", + "value" : False + }, + 15 : { + "label" : "ff2_tx_prsnt_b", + "direction" : "in" + }, + 16 : { + "label" : "ff3_rst_b", + "direction" : "out", + "value" : True + }, + 17 : { + "label" : "ff3_intr_b", + "direction" : "in" + }, + 18 : { + # Mark as "in" if controlled by the SFP model + "label" : "ff3_select_b", + "direction" : "out", + "value" : False + }, + 19 : { + "label" : "ltm4642_temp_alt_b", + "direction" : "in" + }, + 20 : { + "label" : "ltm4642_temp_err_b", + "direction" : "in" + }, + 21 : { + "label" : "versal_cfg_done_gpio", + "direction" : "in" + }, + 22 : { + "label" : "i2c_gpio_por", + "direction" : "in" + }, + 23 : { + "label" : "versal_error_out_gpio", + "direction" : "in" + }, + } + }, + }, + + }, + + + "chipscopy" : { + "cs_server_url" : "TCP:192.168.0.18:3042", + "hw_server_url" : "TCP:192.168.0.18:3121", + "device_family" : "versal", + "bypass_version_check" : False, + }, + + "chipscopy-ddrmc" : { + "self_test" : { + "description" : "Chipscopy-based DDRMC test", + }, + }, + + "chipscopy-ibert" : { + # Allow scheduling scans in entire quad at once. This may or may not work well + # and may or may not be faster than doing the scans one by one + + # True = schedule scans in the entire quad at once + # False = schedule scans one by one (use that if Eye Scan page freezes) + 'scan_by_quad' : False, + + # how long before the scheduler gives up on the scan + 'scan_timeout_seconds' : 300, + + "self_test" : { + "description" : "Chipscopy-based IBERT test and eye scans", + }, + + # please list the links where RX is from the same quad contiguously + # one after another so that scans can be scheduled in batches + "gt_links" : { + "PCIE_0" : { + "rx" : { "quad" : "Quad_103", "channel" : 0}, + "tx" : { "quad" : "Quad_103", "channel" : 0}, + }, + "PCIE_1" : { + "rx" : { "quad" : "Quad_103", "channel" : 1}, + "tx" : { "quad" : "Quad_103", "channel" : 1}, + }, + "PCIE_2" : { + "rx" : { "quad" : "Quad_103", "channel" : 2}, + "tx" : { "quad" : "Quad_103", "channel" : 2}, + }, + "PCIE_3" : { + "rx" : { "quad" : "Quad_103", "channel" : 3}, + "tx" : { "quad" : "Quad_103", "channel" : 3}, + }, + "PCIE_4" : { + "rx" : { "quad" : "Quad_104", "channel" : 0}, + "tx" : { "quad" : "Quad_104", "channel" : 0}, + }, + "PCIE_5" : { + "rx" : { "quad" : "Quad_104", "channel" : 1}, + "tx" : { "quad" : "Quad_104", "channel" : 1}, + }, + "PCIE_6" : { + "rx" : { "quad" : "Quad_104", "channel" : 2}, + "tx" : { "quad" : "Quad_104", "channel" : 2}, + }, + "PCIE_7" : { + "rx" : { "quad" : "Quad_104", "channel" : 3}, + "tx" : { "quad" : "Quad_104", "channel" : 3}, + }, + "PCIE_8" : { + "rx" : { "quad" : "Quad_105", "channel" : 0}, + "tx" : { "quad" : "Quad_105", "channel" : 0}, + }, + "PCIE_9" : { + "rx" : { "quad" : "Quad_105", "channel" : 1}, + "tx" : { "quad" : "Quad_105", "channel" : 1}, + }, + "PCIE_10" : { + "rx" : { "quad" : "Quad_105", "channel" : 2}, + "tx" : { "quad" : "Quad_105", "channel" : 2}, + }, + "PCIE_11" : { + "rx" : { "quad" : "Quad_105", "channel" : 3}, + "tx" : { "quad" : "Quad_105", "channel" : 3}, + }, + "PCIE_12" : { + "rx" : { "quad" : "Quad_106", "channel" : 0}, + "tx" : { "quad" : "Quad_106", "channel" : 0}, + }, + "PCIE_13" : { + "rx" : { "quad" : "Quad_106", "channel" : 1}, + "tx" : { "quad" : "Quad_106", "channel" : 1}, + }, + "PCIE_14" : { + "rx" : { "quad" : "Quad_106", "channel" : 2}, + "tx" : { "quad" : "Quad_106", "channel" : 2}, + }, + "PCIE_15" : { + "rx" : { "quad" : "Quad_106", "channel" : 3}, + "tx" : { "quad" : "Quad_106", "channel" : 3}, + }, + "FF3_0" : { + "rx" : { "quad" : "Quad_200", "channel" : 0}, + "tx" : { "quad" : "Quad_200", "channel" : 0}, + }, + "FF3_1" : { + "rx" : { "quad" : "Quad_200", "channel" : 1}, + "tx" : { "quad" : "Quad_200", "channel" : 1}, + }, + "FF3_2" : { + "rx" : { "quad" : "Quad_200", "channel" : 2}, + "tx" : { "quad" : "Quad_200", "channel" : 2}, + }, + "FF3_3" : { + "rx" : { "quad" : "Quad_200", "channel" : 3}, + "tx" : { "quad" : "Quad_200", "channel" : 3}, + }, + "FF1_0" : { + "rx" : { "quad" : "Quad_201", "channel" : 0}, + "tx" : { "quad" : "Quad_201", "channel" : 0}, + }, + "FF1_1" : { + "rx" : { "quad" : "Quad_201", "channel" : 1}, + "tx" : { "quad" : "Quad_201", "channel" : 1}, + }, + "FF1_2" : { + "rx" : { "quad" : "Quad_201", "channel" : 2}, + "tx" : { "quad" : "Quad_201", "channel" : 2}, + }, + "FF1_3" : { + "rx" : { "quad" : "Quad_201", "channel" : 3}, + "tx" : { "quad" : "Quad_201", "channel" : 3}, + }, + "FF1_4" : { + "rx" : { "quad" : "Quad_202", "channel" : 0}, + "tx" : { "quad" : "Quad_202", "channel" : 0}, + }, + "FF1_5" : { + "rx" : { "quad" : "Quad_202", "channel" : 1}, + "tx" : { "quad" : "Quad_202", "channel" : 1}, + }, + "FF1_6" : { + "rx" : { "quad" : "Quad_202", "channel" : 2}, + "tx" : { "quad" : "Quad_202", "channel" : 2}, + }, + "FF1_7" : { + "rx" : { "quad" : "Quad_202", "channel" : 3}, + "tx" : { "quad" : "Quad_202", "channel" : 3}, + }, + "FF1_8" : { + "rx" : { "quad" : "Quad_203", "channel" : 0}, + "tx" : { "quad" : "Quad_203", "channel" : 0}, + }, + "FF1_9" : { + "rx" : { "quad" : "Quad_203", "channel" : 1}, + "tx" : { "quad" : "Quad_203", "channel" : 1}, + }, + "FF1_10" : { + "rx" : { "quad" : "Quad_203", "channel" : 2}, + "tx" : { "quad" : "Quad_203", "channel" : 2}, + }, + "FF1_11" : { + "rx" : { "quad" : "Quad_203", "channel" : 3}, + "tx" : { "quad" : "Quad_203", "channel" : 3}, + }, + "FF2_0" : { + "rx" : { "quad" : "Quad_204", "channel" : 0}, + "tx" : { "quad" : "Quad_204", "channel" : 0}, + }, + "FF2_1" : { + "rx" : { "quad" : "Quad_204", "channel" : 1}, + "tx" : { "quad" : "Quad_204", "channel" : 1}, + }, + "FF2_2" : { + "rx" : { "quad" : "Quad_204", "channel" : 2}, + "tx" : { "quad" : "Quad_204", "channel" : 2}, + }, + "FF2_3" : { + "rx" : { "quad" : "Quad_204", "channel" : 3}, + "tx" : { "quad" : "Quad_204", "channel" : 3}, + }, + "FF2_4" : { + "rx" : { "quad" : "Quad_205", "channel" : 0}, + "tx" : { "quad" : "Quad_205", "channel" : 0}, + }, + "FF2_5" : { + "rx" : { "quad" : "Quad_205", "channel" : 1}, + "tx" : { "quad" : "Quad_205", "channel" : 1}, + }, + "FF2_6" : { + "rx" : { "quad" : "Quad_205", "channel" : 2}, + "tx" : { "quad" : "Quad_205", "channel" : 2}, + }, + "FF2_7" : { + "rx" : { "quad" : "Quad_205", "channel" : 3}, + "tx" : { "quad" : "Quad_205", "channel" : 3}, + }, + "FF2_8" : { + "rx" : { "quad" : "Quad_206", "channel" : 0}, + "tx" : { "quad" : "Quad_206", "channel" : 0}, + }, + "FF2_9" : { + "rx" : { "quad" : "Quad_206", "channel" : 1}, + "tx" : { "quad" : "Quad_206", "channel" : 1}, + }, + "FF2_10" : { + "rx" : { "quad" : "Quad_206", "channel" : 2}, + "tx" : { "quad" : "Quad_206", "channel" : 2}, + }, + "FF2_11" : { + "rx" : { "quad" : "Quad_206", "channel" : 3}, + "tx" : { "quad" : "Quad_206", "channel" : 3}, + }, + }, + + "apply_default_link_config_on_start_up" : False, + + "default_link_config" : { + "tx" : { + "Pattern" : "PRBS 31", + "Differential Control" : "804 mV", + }, + "rx" : { + "Loopback" : "Near-End PMA", + "Pattern" : "PRBS 31", + "Termination Voltage" : "800mv", + } + }, + + + "scans" : { + + "pcie_pma_near_loopback" : { + "comment" : "PCIe Near-End PMA Loopback", + "links" : [ + "PCIE_0", "PCIE_1", "PCIE_2", "PCIE_3", "PCIE_4", "PCIE_5", "PCIE_6", "PCIE_7", + "PCIE_8", "PCIE_9", "PCIE_10", "PCIE_11", "PCIE_12", "PCIE_13", "PCIE_14", "PCIE_15", + ], + + "scan" : { + "Target BER" : 1e-6, + "Horizontal Step" : 2, + "Vertical Step" : 2, + }, + + "tx" : { + "Pattern" : "PRBS 31", + "Differential Control" : "804 mV", + }, + + "rx" : { + "Loopback" : "Near-End PMA", + "Pattern" : "PRBS 31", + "Termination Voltage" : "500mv", + } + }, + + "pcie_fiber_loopback" : { + "comment" : "PCIe Physical Loopback", + "links" : [ + "PCIE_0", "PCIE_1", "PCIE_2", "PCIE_3", "PCIE_4", "PCIE_5", "PCIE_6", "PCIE_7", + "PCIE_8", "PCIE_9", "PCIE_10", "PCIE_11", "PCIE_12", "PCIE_13", "PCIE_14", "PCIE_15", + ], + + "scan" : { + "Target BER" : 1e-6, + "Horizontal Step" : 2, + "Vertical Step" : 2, + }, + + "tx" : { + "Pattern" : "PRBS 31", + "Differential Control" : "804 mV", + }, + + "rx" : { + "Loopback" : "User Design", + "Pattern" : "PRBS 31", + "Termination Voltage" : "500mv", + } + }, + + + "ff1_pma_near_loopback" : { + "comment" : "FireFly 1 (J32, J33) Near-End PMA Loopback", + "links" : [ "FF1_0", "FF1_1", "FF1_2", "FF1_3", "FF1_4", "FF1_5", "FF1_6", "FF1_7", + "FF1_8", "FF1_9", "FF1_10", "FF1_11", ], + + "scan" : { + "Target BER" : 1e-6, + "Horizontal Step" : 2, + "Vertical Step" : 2, + }, + + "tx" : { + "Pattern" : "PRBS 31", + "Differential Control" : "804 mV", + }, + + "rx" : { + "Loopback" : "Near-End PMA", + "Pattern" : "PRBS 31", + "Termination Voltage" : "500mv", + } + }, + + "ff1_fiber_loopback" : { + "comment" : "FireFly 1 (J32, J33) Physical Loopback", + "links" : [ "FF1_0", "FF1_1", "FF1_2", "FF1_3", "FF1_4", "FF1_5", "FF1_6", "FF1_7", + "FF1_8", "FF1_9", "FF1_10", "FF1_11", ], + + "scan" : { + "Target BER" : 1e-6, + "Horizontal Step" : 2, + "Vertical Step" : 2, + }, + + "tx" : { + "Pattern" : "PRBS 31", + "Differential Control" : "804 mV", + }, + + "rx" : { + "Loopback" : "User Design", + "Pattern" : "PRBS 31", + "Termination Voltage" : "500mv", + } + }, + + "ff2_pma_near_loopback" : { + "comment" : "FireFly 2 (J32, J33) Near-End PMA Loopback", + "links" : [ "FF2_0", "FF2_1", "FF2_2", "FF2_3", "FF2_4", "FF2_5", "FF2_6", "FF2_7", + "FF2_8", "FF2_9", "FF2_10", "FF2_11", ], + + "scan" : { + "Target BER" : 1e-6, + "Horizontal Step" : 2, + "Vertical Step" : 2, + }, + + "tx" : { + "Pattern" : "PRBS 31", + "Differential Control" : "804 mV", + }, + + "rx" : { + "Loopback" : "Near-End PMA", + "Pattern" : "PRBS 31", + "Termination Voltage" : "500mv", + } + }, + + "ff2_fiber_loopback" : { + "comment" : "FireFly 2 (J32, J33) Physical Loopback", + "links" : [ "FF2_0", "FF2_1", "FF2_2", "FF2_3", "FF2_4", "FF2_5", "FF2_6", "FF2_7", + "FF2_8", "FF2_9", "FF2_10", "FF2_11", ], + + "scan" : { + "Target BER" : 1e-6, + "Horizontal Step" : 2, + "Vertical Step" : 2, + }, + + "tx" : { + "Pattern" : "PRBS 31", + "Differential Control" : "804 mV", + }, + + "rx" : { + "Loopback" : "User Design", + "Pattern" : "PRBS 31", + "Termination Voltage" : "500mv", + } + }, + + "ff3_pma_near_loopback" : { + "comment" : "FireFly 3 (J34) Near-End PMA Loopback", + "links" : [ "FF3_0", "FF3_1", "FF3_2", "FF3_3", ], + + "scan" : { + "Target BER" : 1e-6, + "Horizontal Step" : 2, + "Vertical Step" : 2, + }, + + "tx" : { + "Pattern" : "PRBS 31", + "Differential Control" : "804 mV", + }, + + "rx" : { + "Loopback" : "Near-End PMA", + "Pattern" : "PRBS 31", + "Termination Voltage" : "500mv", + } + }, + + "ff3_fiber_loopback" : { + "comment" : "FireFly 3 (J34) Physical Loopback", + "links" : [ "FF3_0", "FF3_1", "FF3_2", "FF3_3", ], + + "scan" : { + "Target BER" : 1e-6, + "Horizontal Step" : 2, + "Vertical Step" : 2, + }, + + "tx" : { + "Pattern" : "PRBS 31", + "Differential Control" : "804 mV", + }, + + "rx" : { + "Loopback" : "User Design", + "Pattern" : "PRBS 31", + "Termination Voltage" : "500mv", + } + }, + + }, + }, + +} + + +# check that the I2C bus looks more or less as expected +# to protect the devices from being overwritten +# import re +# import subprocess + +# output = subprocess.check_output(["i2cdetect", "-l"]).decode('utf-8') +# pattern = r"i2c-3\s+i2c\s+xiic-i2c\s+[0-9a-fA-F]+\.i2c\s+I2C adapter" + +# if not re.search(pattern, output): +# print(output) +# raise RuntimeError("Expected xiic-i2c driver on i2c-3 bus! Aborting the self-test!") + + +# check the SI570 frequency and update the configuration +# when alternative parts are used + +from util.si570 import read_default_frequency +from util.i2c import I2CError +import math, pdb + + +def check_and_redefine_clock(ref_clk_name, target_clk_name, alt_frequency, tolerance=5e-2): + try: + ref_clk = config['si570']['mapping'][ref_clk_name] + f_actual = read_default_frequency(ref_clk) + if math.isclose(f_actual, alt_frequency, rel_tol=tolerance): + print(f"{ref_clk_name} is {alt_frequency} MHz instead of {default_si570_frequency} MHz!") + config['si5345']["mapping"][target_clk_name]["f_in1_MHz"] = alt_frequency + ref_clk["freq_MHz"] = alt_frequency + except I2CError: + pass + + +for alt_frequency in alt_si570_frequencies: + check_and_redefine_clock(ref_clk_name="SI5345A_ref_clk", target_clk_name='si5345_a', + alt_frequency=alt_frequency) + check_and_redefine_clock(ref_clk_name="SI5345B_ref_clk", target_clk_name='si5345_b', + alt_frequency=alt_frequency) + + + + diff --git a/controllers/adm1266.py b/controllers/adm1266.py new file mode 100644 index 0000000..16f3ecd --- /dev/null +++ b/controllers/adm1266.py @@ -0,0 +1,25 @@ +from flask import render_template, request, current_app +from markupsafe import Markup +from models.adm1266 import ADM1266 +import pdb + + +class ADM1266_Controller(): + def __init__(self, config): + self.config = config + self.skip_io = current_app.config["USER_SKIP_IO"] if "USER_SKIP_IO" in current_app.config else False + self.model = ADM1266(config) if not self.skip_io else None + + + def read_all(self): + if self.skip_io: + return render_template("error.html", error="I/O is disabled in test mode") + + data = self.model.read_all() + + for name, device in data.items(): + if "error" in device: + device["device_type"] = "(N/A)" + continue + + return render_template("adm1266.html", data=data) diff --git a/models/adm1266.py b/models/adm1266.py new file mode 100644 index 0000000..f30542e --- /dev/null +++ b/models/adm1266.py @@ -0,0 +1,44 @@ +import pdb +from util.adm1266 import ADM1266 as ADM1266_Device +from util.i2c import I2CError +from threading import Lock +from functools import wraps +from models.self_test_executor import SelfTestExecutor + + +def make_device(settings): + return ADM1266_Device(i2c_bus=settings["i2c_bus"], i2c_addr=settings["i2c_addr"]) + + +class ADM1266(SelfTestExecutor): + def __init__(self, config): + self.config = config + self.lock = Lock() + self.devices = {} + + for name, settings in config["mapping"].items(): + try: + self.devices[name] = make_device(settings) + except I2CError as err: + self.devices[name] = None + + + def read(self, name): + + with self.lock: + try: + if self.devices[name] is None: + self.devices[name] = make_device(self.config["mapping"][name]) + return self.devices[name].read() + except (IOError, I2CError) as err: + return { "error" : str(err) } + + + def read_all(self): + result = {} + for name, settings in self.config["mapping"].items(): + result[name] = self.read(name) + return result + + + \ No newline at end of file diff --git a/routes/__init__.py b/routes/__init__.py index cd00258..666b3a3 100644 --- a/routes/__init__.py +++ b/routes/__init__.py @@ -15,6 +15,7 @@ from controllers.ina226 import INA226_Controller as INA226 from controllers.ccf_clocks import CCF_ClocksController as CCF_Clocks from controllers.gpio import GPIO_Controller as GPIO from controllers.adm106x import ADM106x_Controller as ADM106x +from controllers.adm1266 import ADM1266_Controller as ADM1266 from controllers.vivado_ddrmc import Vivado_DDRMC_Controller as Vivado_DDRMC from controllers.vivado_ibert import Vivado_IBERT_Controller as Vivado_IBERT from controllers.chipscopy_ddrmc import Chipscopy_DDRMC_Controller as Chipscopy_DDRMC @@ -151,6 +152,14 @@ def create_app(name, config): def adm106x_read_all(): return adm106x.read_all() + if "adm1266" in board_config: + with app.app_context(): + adm1266 = ADM1266(board_config["adm1266"]) + self_test_models["adm1266"] = adm1266.model + + @app.route("/adm1266") + def adm1266_read_all(): + return adm1266.read_all() if "si5345" in board_config: with app.app_context(): diff --git a/templates/adm1266.html b/templates/adm1266.html new file mode 100644 index 0000000..a6a40ab --- /dev/null +++ b/templates/adm1266.html @@ -0,0 +1,69 @@ +{% extends "base.html" %} +{% block title %}System clocks{% endblock %} +{% block content %} + +<h2>ADM1266 report</h2> + +{% for name, device in data.items() %} + +<h3>{{name}}: {{device["device_type"]}} + {% if device["error"] %} + <span class="badge rounded-pill bg-danger">ERROR</span> + {% endif %} +</h3> + +{% if device["error"] %} + +<div class="alert alert-danger"> + {{device['error']}} +</div> + +{% else %} +<div class="container"> + +<h4>Input pins</h4> + +<table class="table table-striped"> + <thead> + <tr> + <th scope="col">Name</th> + <th scope="col">ADC readout [V]</th> + <th scope="col">UV fault limit [V]</th> + <th scope="col">UV warning limit [V]</th> + <th scope="col">OV warning limit [V]</th> + <th scope="col">OV fault limit [V]</th> + <th scope="col">Status</th> + </tr> + </thead> + <tbody> + + {% for idx, pin in device["pins"].items() | sort %} + + {% if pin["status"] %} + <tr class="table-warning"> + {% else %} + <tr> + {% endif %} + <th scope="row">{{ pin["pin"] }}</th> + <td>{{ "{:.3f}".format(pin["vout"]) }}</td> + <td>{{ "{:.3f}".format(pin["uv_fault"]) }}</td> + <td>{{ "{:.3f}".format(pin["uv_warn"]) }}</td> + <td>{{ "{:.3f}".format(pin["ov_warn"]) }}</td> + <td>{{ "{:.3f}".format(pin["ov_fault"]) }}</td> + <td>{{ pin["status"] }}</td> + </tr> + + {% endfor %} + + </tbody> +</table> + + +</div> +{% endif %} + +<hr> + +{% endfor %} + +{% endblock %} \ No newline at end of file diff --git a/templates/base.html b/templates/base.html index 4d066e3..63db22b 100644 --- a/templates/base.html +++ b/templates/base.html @@ -75,6 +75,10 @@ {% if "adm106x" in config %} <li><a class="dropdown-item" href="/adm106x">ADM106x</a></li> {% endif %} + + {% if "adm1266" in config %} + <li><a class="dropdown-item" href="/adm1266">ADM1266</a></li> + {% endif %} </ul> </li> diff --git a/util/adm1266.py b/util/adm1266.py new file mode 100644 index 0000000..251ab76 --- /dev/null +++ b/util/adm1266.py @@ -0,0 +1,92 @@ +import pdb +from util.i2c import i2c_handler, I2CError, I2C + +def sign_extend(value, bits): + sign = 1 << (bits - 1) + return (value & (sign - 1)) - (value & sign) + +class ADM1266(): + + pins = { + 0 : "VH1", + 1 : "VH2", + 2 : "VH3", + 3 : "VH4", + 4 : "VP1", + 5 : "VP2", + 6 : "VP3", + 7 : "VP4", + 8 : "VP5", + 9 : "VP6", + 10 : "VP7", + 11 : "VP8", + 12 : "VP9", + 13 : "VP10", + 14 : "VP11", + 15 : "VP12", + 16 : "VP13", + } + + flags = { + 1 << 4 : "UV fault", + 1 << 5 : "UV warn", + 1 << 6 : "OV warn", + 1 << 7 : "OV fault", + } + + NUM_CHANNELS = 17 + + PAGE = 0x00 + VOUT_MODE = 0x20 + VOUT_OV_FAULT_LIMIT = 0x40 + VOUT_OV_WARN_LIMIT = 0x42 + VOUT_UV_WARN_LIMIT = 0x43 + VOUT_UV_FAULT_LIMIT = 0x44 + STATUS_VOUT = 0x7A + READ_VOUT = 0x8B + + def write_reg(self, cmd, data): + with i2c_handler(self.i2c_bus) as i2c: + messages = [ + { "data" : [cmd] + data, "read" : False } + ] + + i2c.transfer(self.i2c_addr, messages) + + def read_reg(self, cmd, size): + with i2c_handler(self.i2c_bus) as i2c: + messages = [ + { "data" : [cmd], "read" : False }, + { "data" : [0x00] * size, "read" : True } + ] + + messages = i2c.transfer(self.i2c_addr, messages) + return messages[1].data + + def __init__(self, i2c_bus, i2c_addr): + self.i2c_addr = i2c_addr + self.i2c_bus = i2c_bus + + def read(self): + result = { 'pins' : {} } + + for i in range(0, self.NUM_CHANNELS): + self.write_reg(self.PAGE, [i]) + + exp = sign_extend(self.read_reg(self.VOUT_MODE, 1)[0] & 0x1F, 5) + status = self.read_reg(self.STATUS_VOUT, 1)[0] + vout = int.from_bytes(self.read_reg(self.READ_VOUT, 2), 'little') * 2 ** exp + ov_fault = int.from_bytes(self.read_reg(self.VOUT_OV_FAULT_LIMIT, 2), 'little') * 2 ** exp + ov_warn = int.from_bytes(self.read_reg(self.VOUT_OV_WARN_LIMIT, 2), 'little') * 2 ** exp + uv_warn = int.from_bytes(self.read_reg(self.VOUT_UV_WARN_LIMIT, 2), 'little') * 2 ** exp + uv_fault = int.from_bytes(self.read_reg(self.VOUT_UV_FAULT_LIMIT, 2), 'little') * 2 ** exp + + status_str = "" + + for f, s in self.flags.items(): + if status & f: + status_str += s + + result['pins'][i] = { 'pin' : self.pins[i], 'vout' : vout, 'uv_fault' : uv_fault, 'uv_warn' : uv_warn, 'ov_warn' : ov_warn, 'ov_fault' : ov_fault, 'status' : status_str} + + return result -- GitLab From 0fb00656f3ebede368a4e94b43f8b71f131ac574 Mon Sep 17 00:00:00 2001 From: Eric Buschmann <eric.buschmann@cern.ch> Date: Thu, 8 Aug 2024 21:37:16 +0000 Subject: [PATCH 15/23] Update ADM1266 --- boards/flx182b.py | 24 +++++--------------- models/adm1266.py | 2 +- templates/adm1266.html | 10 +++++++++ util/adm1266.py | 51 +++++++++++++++++++++++++----------------- 4 files changed, 47 insertions(+), 40 deletions(-) diff --git a/boards/flx182b.py b/boards/flx182b.py index b0df411..094e75b 100644 --- a/boards/flx182b.py +++ b/boards/flx182b.py @@ -121,29 +121,17 @@ config = { # "clk_dump_path" : "/sys/kernel/debug/clk/clk_dump" # }, - - #"adm106x" : { - # "mapping" : { - # "U68" : { - # "i2c_bus" : "/dev/i2c-6", - # "i2c_addr" : 0x34, - # }, - # "U69" : { - # "i2c_bus" : "/dev/i2c-6", - # "i2c_addr" : 0x35, - # }, - # }, - - # "self_test" : { - # "description" : "ADM106x chip readout", - # } - #}, - "adm1266" : { "mapping" : { "U68" : { "i2c_bus" : "/dev/i2c-6", "i2c_addr" : 0x40, + "rails" : ["12P0V", "NC", "NC", "NC", + "VCCINT", "MGTAVCC", "MGTAVTT", "SYS12", + "MGTYVCCAUX", "SYS15", "SYS18", "SYS25", + "SYS33", "SYS38", "3V3_AUX", "VCC5V", + "DDR4_B_VTT" + ], }, }, diff --git a/models/adm1266.py b/models/adm1266.py index f30542e..0652a85 100644 --- a/models/adm1266.py +++ b/models/adm1266.py @@ -7,7 +7,7 @@ from models.self_test_executor import SelfTestExecutor def make_device(settings): - return ADM1266_Device(i2c_bus=settings["i2c_bus"], i2c_addr=settings["i2c_addr"]) + return ADM1266_Device(i2c_bus=settings["i2c_bus"], i2c_addr=settings["i2c_addr"], rails=settings["rails"]) class ADM1266(SelfTestExecutor): diff --git a/templates/adm1266.html b/templates/adm1266.html index a6a40ab..9d86cbe 100644 --- a/templates/adm1266.html +++ b/templates/adm1266.html @@ -21,12 +21,21 @@ {% else %} <div class="container"> + <ul> + <li>Chip ID: {{ device["chip_id"] }}</li> + <li>Firmware revision: {{ device["fw_rev"] }}</li> + <li>Bootloader revision: {{ device["boot_rev"] }} </li> + <li>Chip revision: {{ device["chip_rev"] }} </li> + <li>Powerup counter: {{ device["powerup_counter"] }}</li> + </ul> + <h4>Input pins</h4> <table class="table table-striped"> <thead> <tr> <th scope="col">Name</th> + <th scope="col">Rail</th> <th scope="col">ADC readout [V]</th> <th scope="col">UV fault limit [V]</th> <th scope="col">UV warning limit [V]</th> @@ -45,6 +54,7 @@ <tr> {% endif %} <th scope="row">{{ pin["pin"] }}</th> + <td>{{ pin["rail"] }}</td> <td>{{ "{:.3f}".format(pin["vout"]) }}</td> <td>{{ "{:.3f}".format(pin["uv_fault"]) }}</td> <td>{{ "{:.3f}".format(pin["uv_warn"]) }}</td> diff --git a/util/adm1266.py b/util/adm1266.py index 251ab76..3685bfb 100644 --- a/util/adm1266.py +++ b/util/adm1266.py @@ -7,25 +7,13 @@ def sign_extend(value, bits): class ADM1266(): - pins = { - 0 : "VH1", - 1 : "VH2", - 2 : "VH3", - 3 : "VH4", - 4 : "VP1", - 5 : "VP2", - 6 : "VP3", - 7 : "VP4", - 8 : "VP5", - 9 : "VP6", - 10 : "VP7", - 11 : "VP8", - 12 : "VP9", - 13 : "VP10", - 14 : "VP11", - 15 : "VP12", - 16 : "VP13", - } + pins = [ + "VH1", "VH2", "VH3", "VH4", + "VP1", "VP2", "VP3", "VP4", + "VP5", "VP6", "VP7", "VP8", + "VP9", "VP10", "VP11", "VP12", + "VP13", + ] flags = { 1 << 4 : "UV fault", @@ -44,6 +32,9 @@ class ADM1266(): VOUT_UV_FAULT_LIMIT = 0x44 STATUS_VOUT = 0x7A READ_VOUT = 0x8B + IC_DEVICE = 0xAD + IC_DEVICE_REV = 0xAE + POWERUP_COUNTER = 0xE4 def write_reg(self, cmd, data): with i2c_handler(self.i2c_bus) as i2c: @@ -63,13 +54,29 @@ class ADM1266(): messages = i2c.transfer(self.i2c_addr, messages) return messages[1].data - def __init__(self, i2c_bus, i2c_addr): + def __init__(self, i2c_bus, i2c_addr, rails): self.i2c_addr = i2c_addr self.i2c_bus = i2c_bus + self.rails = rails def read(self): result = { 'pins' : {} } + chip_id = self.read_reg(self.IC_DEVICE, 4) + result['chip_id'] = f'{chip_id[1]:02X}{chip_id[2]:02X}{chip_id[3]:02X}' + + data = self.read_reg(self.IC_DEVICE_REV, 9) + fw_rev = data[1:4] + boot_rev = data[4:7] + chip_rev = data[7:9] + + result['fw_rev'] = f'{fw_rev[0]}.{fw_rev[1]}.{fw_rev[2]}' + result['boot_rev'] = f'{boot_rev[0]}.{boot_rev[1]}.{boot_rev[2]}' + result['chip_rev'] = f'{chr(chip_rev[0])}{chr(chip_rev[1])}' + + counter = int.from_bytes(self.read_reg(self.POWERUP_COUNTER, 3)[1:2], 'little') + result['powerup_counter'] = counter + for i in range(0, self.NUM_CHANNELS): self.write_reg(self.PAGE, [i]) @@ -87,6 +94,8 @@ class ADM1266(): if status & f: status_str += s - result['pins'][i] = { 'pin' : self.pins[i], 'vout' : vout, 'uv_fault' : uv_fault, 'uv_warn' : uv_warn, 'ov_warn' : ov_warn, 'ov_fault' : ov_fault, 'status' : status_str} + rail = self.rails[i] if i < len(self.rails) else "N/A" + + result['pins'][i] = { 'pin' : self.pins[i], 'rail' : rail, 'vout' : vout, 'uv_fault' : uv_fault, 'uv_warn' : uv_warn, 'ov_warn' : ov_warn, 'ov_fault' : ov_fault, 'status' : status_str} return result -- GitLab From e81fc26fbc4ab44d371be86a0ca4b70c6f579b9f Mon Sep 17 00:00:00 2001 From: Carlo Alberto Gottardo <carlo.alberto.gottardo@cern.ch> Date: Fri, 9 Aug 2024 15:59:32 +0200 Subject: [PATCH 16/23] Dwell BER in place of Target BER for Chipscopy 2024.1 --- boards/flx182.py | 16 ++++++++-------- examples/chipscopy_ibert.py | 5 +++-- examples/scan_data/chipscopy_data.json | 2 +- models/chipscopy_ibert.py | 2 +- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/boards/flx182.py b/boards/flx182.py index e0e03c7..ce7306d 100644 --- a/boards/flx182.py +++ b/boards/flx182.py @@ -1161,7 +1161,7 @@ config = { ], "scan" : { - "Target BER" : 1e-6, + "Dwell BER" : 1e-6, "Horizontal Step" : 2, "Vertical Step" : 2, }, @@ -1186,7 +1186,7 @@ config = { ], "scan" : { - "Target BER" : 1e-6, + "Dwell BER" : 1e-6, "Horizontal Step" : 2, "Vertical Step" : 2, }, @@ -1210,7 +1210,7 @@ config = { "FF1_8", "FF1_9", "FF1_10", "FF1_11", ], "scan" : { - "Target BER" : 1e-6, + "Dwell BER" : 1e-6, "Horizontal Step" : 2, "Vertical Step" : 2, }, @@ -1233,7 +1233,7 @@ config = { "FF1_8", "FF1_9", "FF1_10", "FF1_11", ], "scan" : { - "Target BER" : 1e-6, + "Dwell BER" : 1e-6, "Horizontal Step" : 2, "Vertical Step" : 2, }, @@ -1256,7 +1256,7 @@ config = { "FF2_8", "FF2_9", "FF2_10", "FF2_11", ], "scan" : { - "Target BER" : 1e-6, + "Dwell BER" : 1e-6, "Horizontal Step" : 2, "Vertical Step" : 2, }, @@ -1279,7 +1279,7 @@ config = { "FF2_8", "FF2_9", "FF2_10", "FF2_11", ], "scan" : { - "Target BER" : 1e-6, + "Dwell BER" : 1e-6, "Horizontal Step" : 2, "Vertical Step" : 2, }, @@ -1301,7 +1301,7 @@ config = { "links" : [ "FF3_0", "FF3_1", "FF3_2", "FF3_3", ], "scan" : { - "Target BER" : 1e-6, + "Dwell BER" : 1e-6, "Horizontal Step" : 2, "Vertical Step" : 2, }, @@ -1323,7 +1323,7 @@ config = { "links" : [ "FF3_0", "FF3_1", "FF3_2", "FF3_3", ], "scan" : { - "Target BER" : 1e-6, + "Dwell BER" : 1e-6, "Horizontal Step" : 2, "Vertical Step" : 2, }, diff --git a/examples/chipscopy_ibert.py b/examples/chipscopy_ibert.py index 3b5fe69..ac29925 100644 --- a/examples/chipscopy_ibert.py +++ b/examples/chipscopy_ibert.py @@ -20,7 +20,7 @@ def convert_to_dict(scan): y_values = set() result = {} result.update(scan.scan_data.all_params) - target_ber = result["Target BER"] + target_ber = result["Dwell BER"] data_in = scan.scan_data.processed for (x, y) in data_in.scan_points.keys(): @@ -117,7 +117,7 @@ for eye_scan in eye_scans: eye_scan.params[EYE_SCAN_VERT_RANGE].value = "100%" eye_scan.params[EYE_SCAN_TARGET_BER].value = 1e-6 - eye_scan.start(show_progress_bar=False) + eye_scan.start(show_progress_bar=True) print(f"Started eye scan {eye_scan}") print("Waiting for the scans to complete...") @@ -125,6 +125,7 @@ print("Waiting for the scans to complete...") for eye_scan in eye_scans: eye_scan.wait_till_done() +pdb.set_trace() scan = eye_scans[0] data_dict = convert_to_dict(scan) diff --git a/examples/scan_data/chipscopy_data.json b/examples/scan_data/chipscopy_data.json index da77512..f547f6b 100644 --- a/examples/scan_data/chipscopy_data.json +++ b/examples/scan_data/chipscopy_data.json @@ -4,7 +4,7 @@ "Prescale": 0, "Clock Divider": 0, "Counts per UI": 32, - "Target BER": 1e-06, + "Dwell BER": 1e-06, "Horizontal Range": "-0.500 UI to 0.500 UI", "Vertical Range": "100%", "Maximum Horizontal Range": 32, diff --git a/models/chipscopy_ibert.py b/models/chipscopy_ibert.py index 63d6901..236188b 100644 --- a/models/chipscopy_ibert.py +++ b/models/chipscopy_ibert.py @@ -547,7 +547,7 @@ def extract_data(scan): data_out = [[1 for x in range(len(x_axis))] for y in range(len(y_axis))] open_points = 0 num_points = len(y_axis) * len(x_axis) - target_ber = result["Target BER"] + target_ber = result["Dwell BER"] for i in range(len(x_axis)): for j in range(len(y_axis)): -- GitLab From 1b0d584682f04dad5d080b578428bc7633c5370b Mon Sep 17 00:00:00 2001 From: Eric Buschmann <eric.buschmann@cern.ch> Date: Wed, 14 Aug 2024 20:06:52 +0000 Subject: [PATCH 17/23] Use labels to identify gpiochip devices --- boards/flx182.py | 8 ++++---- boards/flx182b.py | 19 ++++++++----------- models/gpio.py | 8 +++++--- templates/gpio.html | 2 +- util/gpio.py | 23 +++++++++++++++++++++++ 5 files changed, 41 insertions(+), 19 deletions(-) diff --git a/boards/flx182.py b/boards/flx182.py index ffb1bdb..b91d7a1 100644 --- a/boards/flx182.py +++ b/boards/flx182.py @@ -346,7 +346,7 @@ config = { "description" : "GPIO readout", }, "mapping" : { - "gpiochip0" : { + "20100000000.gpio" : { "comment" : "Versal AXI GPIO", "lines" : { # GPIO_0 port in Vivado @@ -555,7 +555,7 @@ config = { }, - "gpiochip1" : { + "pmc_gpio" : { "comment" : "Versal PMC Bank 1 GPIO", "lines" : { 37 : { @@ -575,7 +575,7 @@ config = { }, - "gpiochip2" : { + "11-0022" : { "comment" : "I2C GPIO expander TCA6424A (U65)", "lines" : { 0 : { @@ -678,7 +678,7 @@ config = { }, - "gpiochip3" : { + "11-0023" : { "comment" : "I2C GPIO expander TCA6424A (U66)", "lines" : { 0 : { diff --git a/boards/flx182b.py b/boards/flx182b.py index 094e75b..24408f0 100644 --- a/boards/flx182b.py +++ b/boards/flx182b.py @@ -347,7 +347,7 @@ config = { "description" : "GPIO readout", }, "mapping" : { - "gpiochip0" : { + "20100000000.gpio" : { "comment" : "Versal AXI GPIO", "lines" : { # GPIO_0 port in Vivado @@ -556,30 +556,27 @@ config = { }, - "gpiochip1" : { + "pmc_gpio" : { "comment" : "Versal PMC Bank 1 GPIO", "lines" : { 37 : { - "label" : "ADM1066 VX1 (U68)", + "label" : "ADM1266 GPIO1 (U33)", "direction" : "out", "value" : True, }, 38 : { - "label" : "PCIE_PERST_B (R337 DNP)", + "label" : "PCIE_PERST_B (R396 DNP)", "direction" : "in", }, 39 : { - "label" : "PCIE_PERST_B (R780 DNP)", + "label" : "PCIE_PERST_B (R398 DNP)", "direction" : "in" }, } }, - #"gpiochip2" : { - # "comment" : "ADM1266 GPIO (U33)", - #}, - - "gpiochip3" : { + + "11-0022" : { "comment" : "I2C GPIO expander TCA6424A (U80)", "lines" : { 0 : { @@ -682,7 +679,7 @@ config = { }, - "gpiochip4" : { + "11-0023" : { "comment" : "I2C GPIO expander TCA6424A (U81)", "lines" : { 0 : { diff --git a/models/gpio.py b/models/gpio.py index b90385b..bc6da8c 100644 --- a/models/gpio.py +++ b/models/gpio.py @@ -13,6 +13,8 @@ class GPIO(SelfTestExecutor): params["has_inputs"] = self.has_direction(params["lines"], "in") params["has_outputs"] = self.has_direction(params["lines"], "out") + params["device"] = gpio.detect(device) + self.initialize_lines() @@ -52,7 +54,7 @@ class GPIO(SelfTestExecutor): else: return {"error" : "Bit value '{}' must be '0' or '1'".format(bit)} with self.lock: - gpio.set_line(device, bit, value_bool) + gpio.set_line(self.config["mapping"][device]["device"], bit, value_bool) self.config["mapping"][device]["lines"][bit]["value"] = value_bool result[bit] = value_bool except Exception as err: @@ -75,7 +77,7 @@ class GPIO(SelfTestExecutor): if props["direction"] == "out" and "value" in props: value = props["value"] else: - value = gpio.get_line(device, line) + value = gpio.get_line(self.config["mapping"][device]["device"], line) if props["direction"] == "out": props["value"] = value result["lines"][line]["value"] = value @@ -97,7 +99,7 @@ class GPIO(SelfTestExecutor): continue with self.lock: value = props["value"] if "value" in props else False - gpio.set_line(device, line, value) + gpio.set_line(self.config["mapping"][device]["device"], line, value) props["value"] = value diff --git a/templates/gpio.html b/templates/gpio.html index 27682ad..d60bf53 100644 --- a/templates/gpio.html +++ b/templates/gpio.html @@ -12,7 +12,7 @@ {% else %} <div class="container py-4 px-0"> - <h2>{{ device }} + <h2>{{ device }} ({{ params["device"] }}) <small class="text-muted">{{ params["comment"] }}</small></h2> {% if params["has_outputs"] %} diff --git a/util/gpio.py b/util/gpio.py index 1d63a83..0e92e11 100644 --- a/util/gpio.py +++ b/util/gpio.py @@ -1,5 +1,8 @@ import periphery from periphery import GPIO as GPIO_periphery +import fcntl +import struct +import glob GPIOError = periphery.GPIOError @@ -14,3 +17,23 @@ def get_line(device, line): value = gpio.read() gpio.close() return value + + +GPIO_GET_CHIPINFO_IOCTL = 0x8044B401 + +def detect(chip_label): + chips = glob.glob("/dev/gpiochip*") + for chip in chips: + f = open(chip, "rb") + + gpiochip_info = struct.Struct("32s 32s L") + buffer = gpiochip_info.pack(b' ', b' ', 0) + result = fcntl.ioctl(f, GPIO_GET_CHIPINFO_IOCTL, buffer) + + name, label, lines = gpiochip_info.unpack(result) + + name = name.rstrip(b'\0').decode("utf-8") + label = label.rstrip(b'\0').decode("utf-8") + + if label == chip_label: + return name -- GitLab From fde83de563d6b8affc9f0f48deb2259217f3ade1 Mon Sep 17 00:00:00 2001 From: Eric Buschmann <eric.buschmann@cern.ch> Date: Wed, 14 Aug 2024 20:21:48 +0000 Subject: [PATCH 18/23] Update configuration for FLX-182B --- boards/flx182b.py | 149 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 138 insertions(+), 11 deletions(-) diff --git a/boards/flx182b.py b/boards/flx182b.py index 24408f0..7b0c957 100644 --- a/boards/flx182b.py +++ b/boards/flx182b.py @@ -23,6 +23,7 @@ config = { "interface" : "zynq_mpsoc", "board" : "FLX-182", "revision" : "3_1b", + "DNAaddress" : [0xF1250024, 0xF1250020], "self_test" : { "description" : "Identify the board", } @@ -39,6 +40,33 @@ config = { "name" : "ina226", "self_test" : { "description" : "INA226 chip readout", + }, + #tolerance and max current set by hand + "reference" : { + "voltage" : { + "12P0V" : {"nominal" : 12.00, "min" : 11.0, "max" : 23.0, "desc" : "+/- 1V expected from power supply"}, + "MGTAVCC" : {"nominal" : 0.88 , "min" : 0.854, "max" : 0.906, "desc" : "V limits from FPGA recommended ranges"}, + "MGTAVTT" : {"nominal" : 1.20 , "min" : 1.164, "max" : 1.236, "desc" : "V limits from FPGA recommended ranges"}, + "SYS12" : {"nominal" : 1.20 , "min" : 1.164, "max" : 1.236, "desc" : "V limits from FPGA recommended ranges"}, + "SYS15" : {"nominal" : 1.50 , "min" : 1.455, "max" : 1.545, "desc" : "V limits from FPGA recommended ranges"}, + "SYS18" : {"nominal" : 1.80 , "min" : 1.710, "max" : 1.890, "desc" : "V limits from 25G FF"}, + "SYS25" : {"nominal" : 2.50 , "min" : 2.15, "max" : 2.85, "desc" : ""}, + "SYS33" : {"nominal" : 3.30 , "min" : 3.15, "max" : 3.45, "desc" : "V limits from 14/16G FF"}, + "SYS38" : {"nominal" : 3.80 , "min" : 3.50, "max" : 4.10, "desc" : ""}, + "VCCINT" : {"nominal" : 0.80 , "min" : 0.775, "max" : 0.825, "desc" : ""} + }, + "current" : { + "12P0V" : {"nominal" : 1, "max" : 8, "desc" : ""}, + "MGTAVCC" : {"nominal" : 1.5 , "max" : 3.5, "desc" : ""}, + "MGTAVTT" : {"nominal" : 3.4 , "max" : 6.5, "desc" : ""}, + "SYS12" : {"nominal" : 0.8 , "max" : 1.5, "desc" : ""}, + "SYS15" : {"nominal" : 0.9 , "max" : 1.5, "desc" : ""}, + "SYS18" : {"nominal" : 0.8 , "max" : 1.5, "desc" : ""}, + "SYS25" : {"nominal" : 0.3 , "max" : 0.5, "desc" : ""}, + "SYS33" : {"nominal" : 3.30 , "max" : 6.0, "desc" : ""}, + "SYS38" : {"nominal" : 0.0 , "max" : 5, "desc" : ""}, + "VCCINT" : {"nominal" : 20.0 , "max" : 50.0, "desc" : ""} + } } }, @@ -54,6 +82,78 @@ config = { "voltage" : "in_voltage(?P<id>\\d+)_(?P<name>.+)_input", "temperature" : "in_temp(?P<id>\\d+)_(?P<name>.+)_input", }, + "reference" : { + # Reference Versal Prime Series Data Sheet: DC and AC Switching Characteristics + # DS956 2024-04-30 + # Table: Recommended Operating Conditions + "temperature" : { + "max_max" : {"nominal" : 36, "min" : 0, "max" : 50, "source" : "N/A", "desc" : "FPGA diode temperature (latched max)"}, + "temp" : {"nominal" : 36, "min" : 0, "max" : 50, "source" : "N/A", "desc" : "FPGA diode temperature"}, + }, + "voltage" : { + "gty_avcc_103" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, + "gty_avcc_104" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, + "gty_avcc_105" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, + "gty_avcc_106" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, + "gty_avcc_200" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, + "gty_avcc_201" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, + "gty_avcc_202" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, + "gty_avcc_203" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, + "gty_avcc_204" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, + "gty_avcc_205" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, + "gty_avcc_206" : {"nominal" : 0.880, "min" : 0.854, "max" : 0.906, "source" : "DS956", "desc" : "GTY primary analog (PLL) power supply"}, + "gty_avccaux_103" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, + "gty_avccaux_104" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, + "gty_avccaux_105" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, + "gty_avccaux_106" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, + "gty_avccaux_200" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, + "gty_avccaux_201" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, + "gty_avccaux_202" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, + "gty_avccaux_203" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, + "gty_avccaux_204" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, + "gty_avccaux_205" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, + "gty_avccaux_206" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "GTY aux analog (PLL) power supply"}, + "gty_avtt_103" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, + "gty_avtt_104" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, + "gty_avtt_105" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, + "gty_avtt_106" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, + "gty_avtt_200" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, + "gty_avtt_201" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, + "gty_avtt_202" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, + "gty_avtt_203" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, + "gty_avtt_204" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, + "gty_avtt_205" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, + "gty_avtt_206" : {"nominal" : 1.200, "min" : 1.164, "max" : 1.236, "source" : "DS956", "desc" : "GTY termination power supply"}, +# "vcc_batt" : {"nominal" : 0, "min" : 1.200, "max" : 1.500, "source" : "DS956", "desc" : "Battery power supply"}, + "vcc_pmc" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "PMC primary power supply"}, + "vcc_psfp" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "PS full-power domain power supply"}, + "vcc_pslp" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "PS low-power domain power supply"}, + "vcc_ram" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "PL RAM and clocking network" }, + "vcc_soc" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "Network on Chip (NoC) and DDR memory controller power supply"}, + "vccaux" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "Auxiliary power supply "}, + "vccaux_pmc" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "PMC auxiliary power supply voltage"}, + "vccaux_smon" : {"nominal" : 1.500, "min" : 1.455, "max" : 1.545, "source" : "DS956", "desc" : "PMC system monitor power supply relative to GND_SMON"}, + "vccint" : {"nominal" : 0.800, "min" : 0.775, "max" : 0.825, "source" : "DS956", "desc" : "PL primary power supply"}, + "vcco_306" : {"nominal" : 1.800, "min" : 1.710, "max" : 3.400, "source" : "DS956", "desc" : "HDIO bank 3 output driver"}, + "vcco_406" : {"nominal" : 1.800, "min" : 1.710, "max" : 3.400, "source" : "DS956", "desc" : "HDIO bank 4 output driver"}, + "vcco_500" : {"nominal" : 1.800, "min" : 1.710, "max" : 3.400, "source" : "DS956", "desc" : "PSIO bank 5 power supply"}, + "vcco_501" : {"nominal" : 1.800, "min" : 1.710, "max" : 3.400, "source" : "DS956", "desc" : "PSIO bank 5 power supply"}, + "vcco_502" : {"nominal" : 1.800, "min" : 1.710, "max" : 3.400, "source" : "DS956", "desc" : "PSIO bank 5 power supply"}, + "vcco_503" : {"nominal" : 1.800, "min" : 1.710, "max" : 3.400, "source" : "DS956", "desc" : "PSIO bank 5 power supply"}, + "vcco_700" : {"nominal" : 1.200, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, + "vcco_701" : {"nominal" : 1.200, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, + "vcco_702" : {"nominal" : 1.500, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, + "vcco_703" : {"nominal" : 1.200, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, + "vcco_704" : {"nominal" : 1.200, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, + "vcco_705" : {"nominal" : 1.200, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, + "vcco_706" : {"nominal" : 1.500, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, + "vcco_707" : {"nominal" : 1.500, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, + "vcco_708" : {"nominal" : 1.500, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, + "vcco_709" : {"nominal" : 1.200, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, + "vcco_710" : {"nominal" : 1.200, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"}, + "vcco_711" : {"nominal" : 1.200, "min" : 0.950, "max" : 1.575, "source" : "DS956", "desc" : "XPIO bank 7 output driver"} + } + } }, "ltm4700" : { @@ -61,11 +161,16 @@ config = { "title" : "LTM4700", "patterns" : { "voltage" : "(?P<name>in\\d+_input)", + "voltage_min" : "(?P<name>in\\d+_min)(?!_alarm)", + "voltage_max" : "(?P<name>in\\d+_max)(?!_alarm)", + "voltage_crit" : "(?P<name>in\\d+_crit)(?!_alarm)", "current" : "(?P<name>curr\\d+_input)", - "temp" : "(?P<name>temp\\d+_input)", + "current_max" : "(?P<name>curr\\d+_max)(?!_alarm)", "power" : "(?P<name>power\\d+_input)", + "temp" : "(?P<name>temp\\d+_input)", + "temp_max" : "(?P<name>temp\\d+_crit)(?!_alarm)", }, - }, + }, #end of ltm4700 "tmp435" : { "device_path" : "/sys/class/hwmon/", @@ -75,6 +180,17 @@ config = { }, "self_test" : { "description" : "TMP435 readout", + }, + "reference" : { + "probe" : { + "LTM4642_TMP" : {"min" : 20.0, "nominal" : 30.0, "max" : 50.0, "desc" : "LTM4642, 2.5V (DDR, ETH) and 3.8V (FF) rails"}, + "MGTAVCC_TMP" : {"min" : 20.0, "nominal" : 40.0, "max" : 60.0, "desc" : "LTM4638, 0.88V rail (FPGA) "}, + "MGTAVTT_TMP" : {"min" : 20.0, "nominal" : 40.0, "max" : 60.0, "desc" : "LTM4638, 1.2V rail (FPGA, DDR)"}, + "SYS12_TMP" : {"min" : 20.0, "nominal" : 40.0, "max" : 60.0, "desc" : "LTM4638, 1.2V rail (FPGA, DDR)"}, + "SYS15_TMP" : {"min" : 20.0, "nominal" : 40.0, "max" : 60.0, "desc" : "LTM4638, 1.5V rail (FPGA)"}, + "SYS18_TMP" : {"min" : 20.0, "nominal" : 40.0, "max" : 60.0, "desc" : "LTM4638, 1.8V rail (FPGA, FF, Si5345)"}, + "SYS33_TMP" : {"min" : 20.0, "nominal" : 40.0, "max" : 60.0, "desc" : "LTM4638, 3.3V rail (FF, Si5345, QSPI)"}, + } } }, @@ -84,10 +200,15 @@ config = { "patterns" : { "probe" : "(?P<name>temp\\d+_input)", }, + "reference" : { + "probe" : { + "DRAM temperature sensor" : {"min" : 20.0, "nominal" : 33.0, "max" : 50.0, "desc" : "DRAM temperature"}, + } + } }, }, "self_test" : { - "description" : "HWMON device readout (SYSMON, TMP435, etc)", + "description" : "HWMON device readout (SYSMON, LTM4700, TMP435, etc)", } }, @@ -259,6 +380,7 @@ config = { "i2c_bus" : "/dev/i2c-8", "i2c_addr" : 0x50, "type" : "CERN-B-* Transmitter", + "max_temp" : 75, # "select" : { # "gpio" : "gpiochip3", # "line" : 6, @@ -269,6 +391,7 @@ config = { "type" : "CERN-B-* Receiver", "i2c_bus" : "/dev/i2c-8", "i2c_addr" : 0x54, + "max_temp" : 75, # "select" : { # "gpio" : "gpiochip3", # "line" : 2, @@ -279,6 +402,7 @@ config = { "type" : "CERN-B-* Transmitter", "i2c_bus" : "/dev/i2c-9", "i2c_addr" : 0x50, + "max_temp" : 75, # "select" : { # "gpio" : "gpiochip3", # "line" : 14, @@ -289,6 +413,7 @@ config = { "type" : "CERN-B-* Receiver", "i2c_bus" : "/dev/i2c-9", "i2c_addr" : 0x54, + "max_temp" : 75, # "select" : { # "gpio" : "gpiochip3", # "line" : 10, @@ -296,8 +421,10 @@ config = { # } }, "FireFly_J34" : { + "type" : "B04 Transceiver", "i2c_bus" : "/dev/i2c-10", "i2c_addr" : 0x50, + "max_temp" : 75, # "select" : { # "gpio" : "gpiochip3", # "line" : 18, @@ -1035,7 +1162,7 @@ config = { ], "scan" : { - "Target BER" : 1e-6, + "Dwell BER" : 1e-6, "Horizontal Step" : 2, "Vertical Step" : 2, }, @@ -1060,7 +1187,7 @@ config = { ], "scan" : { - "Target BER" : 1e-6, + "Dwell BER" : 1e-6, "Horizontal Step" : 2, "Vertical Step" : 2, }, @@ -1084,7 +1211,7 @@ config = { "FF1_8", "FF1_9", "FF1_10", "FF1_11", ], "scan" : { - "Target BER" : 1e-6, + "Dwell BER" : 1e-6, "Horizontal Step" : 2, "Vertical Step" : 2, }, @@ -1107,7 +1234,7 @@ config = { "FF1_8", "FF1_9", "FF1_10", "FF1_11", ], "scan" : { - "Target BER" : 1e-6, + "Dwell BER" : 1e-6, "Horizontal Step" : 2, "Vertical Step" : 2, }, @@ -1130,7 +1257,7 @@ config = { "FF2_8", "FF2_9", "FF2_10", "FF2_11", ], "scan" : { - "Target BER" : 1e-6, + "Dwell BER" : 1e-6, "Horizontal Step" : 2, "Vertical Step" : 2, }, @@ -1153,7 +1280,7 @@ config = { "FF2_8", "FF2_9", "FF2_10", "FF2_11", ], "scan" : { - "Target BER" : 1e-6, + "Dwell BER" : 1e-6, "Horizontal Step" : 2, "Vertical Step" : 2, }, @@ -1175,7 +1302,7 @@ config = { "links" : [ "FF3_0", "FF3_1", "FF3_2", "FF3_3", ], "scan" : { - "Target BER" : 1e-6, + "Dwell BER" : 1e-6, "Horizontal Step" : 2, "Vertical Step" : 2, }, @@ -1197,7 +1324,7 @@ config = { "links" : [ "FF3_0", "FF3_1", "FF3_2", "FF3_3", ], "scan" : { - "Target BER" : 1e-6, + "Dwell BER" : 1e-6, "Horizontal Step" : 2, "Vertical Step" : 2, }, -- GitLab From 5af07c23a54af33ec00203c53b36dead5210bcf7 Mon Sep 17 00:00:00 2001 From: felix <felix@130-199-21-158.dhcp.bnl.gov> Date: Wed, 14 Aug 2024 17:09:41 -0400 Subject: [PATCH 19/23] Remove absent components --- boards/flx182.py | 48 ++++++++++++++++------------------------------- boards/flx182b.py | 48 ++++++++++++++++------------------------------- 2 files changed, 32 insertions(+), 64 deletions(-) diff --git a/boards/flx182.py b/boards/flx182.py index f3ada46..3dcfc36 100644 --- a/boards/flx182.py +++ b/boards/flx182.py @@ -212,22 +212,6 @@ config = { } }, - - "si53156" : { - "mapping" : { - "U37" : { - "i2c_bus" : "/dev/i2c-7", - "i2c_addr" : 0x6b, - "name" : "PCIe clk buffer (U37)" - }, - }, - - "self_test" : { - "description" : "Probe SI53156", - } - }, - - # displays clocks listed in Linux device tree and # controlled by kernel via the Common Clock Framework # "ccf_clocks" : { @@ -342,22 +326,22 @@ config = { "protected" : False, }, - # NOTE: alternative part may be placed - "lti_ref_clk" : { - "i2c_bus" : "/dev/i2c-9", - "i2c_addr" : 0x60, - "freq_MHz" : 240.474, - "stability" : "20ppm", - "protected" : False, - }, - - "100G_ref_clk" : { - "i2c_bus" : "/dev/i2c-10", - "i2c_addr" : 0x60, - "freq_MHz" : 322.265625, - "stability" : "20ppm", - "protected" : False, - }, + # No I2C access +# "lti_ref_clk" : { +# "i2c_bus" : "/dev/i2c-9", +# "i2c_addr" : 0x60, +# "freq_MHz" : 240.474, +# "stability" : "20ppm", +# "protected" : False, +# }, +# +# "100G_ref_clk" : { +# "i2c_bus" : "/dev/i2c-10", +# "i2c_addr" : 0x60, +# "freq_MHz" : 322.265625, +# "stability" : "20ppm", +# "protected" : False, +# }, "ps_ref_clk" : { "i2c_bus" : "/dev/i2c-11", diff --git a/boards/flx182b.py b/boards/flx182b.py index 7b0c957..780d0e3 100644 --- a/boards/flx182b.py +++ b/boards/flx182b.py @@ -212,22 +212,6 @@ config = { } }, - - "si53156" : { - "mapping" : { - "U36" : { - "i2c_bus" : "/dev/i2c-7", - "i2c_addr" : 0x6b, - "name" : "PCIe clk buffer (U37)" - }, - }, - - "self_test" : { - "description" : "Probe SI53156", - } - }, - - # displays clocks listed in Linux device tree and # controlled by kernel via the Common Clock Framework # "ccf_clocks" : { @@ -343,22 +327,22 @@ config = { "protected" : False, }, - # NOTE: alternative part may be placed - "lti_ref_clk" : { - "i2c_bus" : "/dev/i2c-9", - "i2c_addr" : 0x60, - "freq_MHz" : 240.474, - "stability" : "20ppm", - "protected" : False, - }, - - "100G_ref_clk" : { - "i2c_bus" : "/dev/i2c-10", - "i2c_addr" : 0x60, - "freq_MHz" : 322.265625, - "stability" : "20ppm", - "protected" : False, - }, + # No I2C access +# "lti_ref_clk" : { +# "i2c_bus" : "/dev/i2c-9", +# "i2c_addr" : 0x60, +# "freq_MHz" : 240.474, +# "stability" : "20ppm", +# "protected" : False, +# }, +# +# "100G_ref_clk" : { +# "i2c_bus" : "/dev/i2c-10", +# "i2c_addr" : 0x60, +# "freq_MHz" : 322.265625, +# "stability" : "20ppm", +# "protected" : False, +# }, "ps_ref_clk" : { "i2c_bus" : "/dev/i2c-11", -- GitLab From 32102a8028ea9a28beb42dafbbecfa47f05e8b73 Mon Sep 17 00:00:00 2001 From: Eric Buschmann <eric.buschmann@cern.ch> Date: Thu, 15 Aug 2024 19:29:46 +0000 Subject: [PATCH 20/23] Add settings for 28G transceiver --- controllers/sfp.py | 12 ++++++++++-- models/sfp.py | 5 +++++ routes/__init__.py | 4 ++++ templates/sfp.html | 40 ++++++++++++++++++++++++++++++++++++++++ util/sfp.py | 23 +++++++++++++++++++++++ 5 files changed, 82 insertions(+), 2 deletions(-) diff --git a/controllers/sfp.py b/controllers/sfp.py index efc1f9a..20d1dd5 100644 --- a/controllers/sfp.py +++ b/controllers/sfp.py @@ -1,4 +1,4 @@ -from flask import render_template, current_app +from flask import render_template, current_app, redirect, request from markupsafe import Markup from models.sfp import SFP @@ -8,6 +8,7 @@ class SFP_Controller(): self.config = config self.skip_io = current_app.config["USER_SKIP_IO"] if "USER_SKIP_IO" in current_app.config else False self.model = SFP(config) if not self.skip_io else None + self.name = "sfp" def read_all(self): @@ -25,5 +26,12 @@ class SFP_Controller(): else: return render_template("error.html", error="No data received from SFP devices") - + + def configure(self, device_name): + if self.skip_io: + return redirect(f"/{self.name}") + + self.model.configure(device_name, dict(request.form)) + + return redirect(f"/{self.name}") diff --git a/models/sfp.py b/models/sfp.py index 622d755..af8797d 100644 --- a/models/sfp.py +++ b/models/sfp.py @@ -67,3 +67,8 @@ class SFP(SelfTestExecutor): msg = "OK" return { "status" : msg_level, "result" : msg} + + def configure(self, device_name, config): + cfg = self.devices[device_name] + device = SFP_Device(cfg) + device.configure(config) diff --git a/routes/__init__.py b/routes/__init__.py index 666b3a3..53106aa 100644 --- a/routes/__init__.py +++ b/routes/__init__.py @@ -104,6 +104,10 @@ def create_app(name, config): def sfp_read_all(): return sfp.read_all() + @app.route("/sfp/configure/<device_name>", methods=["POST"]) + def sfp_configure(device_name): + return sfp.configure(device_name) + # api.add_resource(SFP_API.SFP_List, "/api/sfp", # resource_class_kwargs={"model" : sfp.model}) diff --git a/templates/sfp.html b/templates/sfp.html index 13adf5e..4bc6607 100644 --- a/templates/sfp.html +++ b/templates/sfp.html @@ -31,4 +31,44 @@ </tbody> </table> +<hr> + +<h2>Settings</h2> + + + <table class="table table-striped"> + <thead> + <tr> + <th scope="col">Name</th> + <th scope="col">Enable CDR</th> + <th scope="col">CDR Rate</th> + <th scope="col"></th> + </tr> + </thead> + <tbody> + + {% for label, params in data.items() | sort %} + {% if params["part_number"] == "B042804005170" %} + <form method="post" class="mb-4" role=form> + <tr> + <th>{{label}}</th> + <td> + <input type="checkbox" id="cdr" name="cdr" checked> + </td> + <td> + <input type="radio" id="25g" name="rate" value="25g"> + <label for="25g">25.5-26G</label> + <input type="radio" id="28g" name="rate" value="28g" checked> + <label for="28g">27.5-28.1G</label> + </td> + <td> + <button class="btn btn-primary" type="submit" formaction="/sfp/configure/{{label}}">Update</button> + </td> + </tr> + </form> + {% endif %} + {% endfor %} + </tbody> + </table> + {% endblock %} \ No newline at end of file diff --git a/util/sfp.py b/util/sfp.py index b5ac315..760b54f 100644 --- a/util/sfp.py +++ b/util/sfp.py @@ -83,6 +83,8 @@ register_maps = { "address" : 22, "type" : "samtec" }, + "cdr_enable" : 98, + "cdr_rate" : 99, }, "CERN-B-* Receiver" : regs_samtec_cern, @@ -238,7 +240,28 @@ class SFP(): "error" : str(err) } return data + + def configure(self, config): + with self.open_device(): + part_number = self.__read_field("part_number") + # Only applies to the 28G transceivers + + if part_number == "B042804005170": + cdr = 0 + rate = 0 + + if('cdr' in config): + cdr = 0xFF + + if(config['rate'] == '25g'): + rate = 0 + else: + rate = 0xFF + + i2c_addr = self.device["i2c_addr"] + self.i2c.write(i2c_addr, self.registers["cdr_enable"], cdr) + self.i2c.write(i2c_addr, self.registers["cdr_rate"], rate) class TransactionValidator(): -- GitLab From 31181d774989e674c7ae8a89ce7f427e98e31588 Mon Sep 17 00:00:00 2001 From: Eric Buschmann <eric.buschmann@cern.ch> Date: Thu, 15 Aug 2024 21:30:04 +0000 Subject: [PATCH 21/23] Added GTY reset --- controllers/sfp.py | 8 ++++++++ models/board_id.py | 18 +++--------------- models/sfp.py | 9 ++++++++- routes/__init__.py | 4 ++++ templates/sfp.html | 6 ++++++ util/devmem.py | 24 ++++++++++++++++++++++++ 6 files changed, 53 insertions(+), 16 deletions(-) create mode 100644 util/devmem.py diff --git a/controllers/sfp.py b/controllers/sfp.py index 20d1dd5..1c9fdd3 100644 --- a/controllers/sfp.py +++ b/controllers/sfp.py @@ -35,3 +35,11 @@ class SFP_Controller(): self.model.configure(device_name, dict(request.form)) return redirect(f"/{self.name}") + + def reset(self): + if self.skip_io: + return redirect(f"/{self.name}") + + self.model.reset() + + return redirect(f"/{self.name}") diff --git a/models/board_id.py b/models/board_id.py index 2b13549..cbce791 100644 --- a/models/board_id.py +++ b/models/board_id.py @@ -2,6 +2,7 @@ import pdb, re, mmap, os from os import path, sysconf from os.path import isdir from util.iio import load_file +from util.devmem import devmem_read from models.self_test_executor import SelfTestExecutor, field_present @@ -49,25 +50,12 @@ class BoardID(SelfTestExecutor): return hex(idcode) - def devmem(self, target_adr, length=4): - page_size= os.sysconf("SC_PAGE_SIZE") - reg_base = int(target_adr // page_size) * page_size - seek_size= int(target_adr % page_size) - map_size = seek_size+length - fd = os.open("/dev/mem", os.O_RDWR|os.O_SYNC) - mem = mmap.mmap(fd, map_size, mmap.MAP_SHARED, mmap.PROT_READ|mmap.PROT_WRITE, offset=reg_base) - mem.seek(seek_size, os.SEEK_SET) - value = mem.read(length) - os.close(fd) - return value - - def get_dna(self): if not "DNAaddress" in self.config: return {"error" : "You must specify a memory address to retrieve the FPGA DNA!" } else: - dna_msb = int.from_bytes(self.devmem(self.config['DNAaddress'][0]), "little") - dna_lsb = int.from_bytes(self.devmem(self.config['DNAaddress'][1]), "little") + dna_msb = int.from_bytes(devmem_read(self.config['DNAaddress'][0]), "little") + dna_lsb = int.from_bytes(devmem_read(self.config['DNAaddress'][1]), "little") dna = ( dna_msb << 32 ) | dna_lsb return hex(dna) diff --git a/models/sfp.py b/models/sfp.py index af8797d..42c6028 100644 --- a/models/sfp.py +++ b/models/sfp.py @@ -1,6 +1,8 @@ import pdb from util.sfp import SFP as SFP_Device from util.i2c import I2CError +from util.devmem import devmem_write +import time from models.self_test_executor import SelfTestExecutor @@ -31,7 +33,7 @@ class SFP(SelfTestExecutor): msg_level = "success" msg = [] - if len(result.keys()) is not 5: + if len(result.keys()) != 5: msg_level = "error" for label in self.config["mapping"].keys(): @@ -72,3 +74,8 @@ class SFP(SelfTestExecutor): cfg = self.devices[device_name] device = SFP_Device(cfg) device.configure(config) + + def reset(self): + devmem_write(0x20100020000, int(0xFFFFFFFF).to_bytes(4, 'little')) + time.sleep(0.1) + devmem_write(0x20100020000, int(0).to_bytes(4, 'little')) diff --git a/routes/__init__.py b/routes/__init__.py index 53106aa..e831150 100644 --- a/routes/__init__.py +++ b/routes/__init__.py @@ -108,6 +108,10 @@ def create_app(name, config): def sfp_configure(device_name): return sfp.configure(device_name) + @app.route("/sfp/reset", methods=["POST"]) + def sfp_reset(): + return sfp.reset() + # api.add_resource(SFP_API.SFP_List, "/api/sfp", # resource_class_kwargs={"model" : sfp.model}) diff --git a/templates/sfp.html b/templates/sfp.html index 4bc6607..3cf6827 100644 --- a/templates/sfp.html +++ b/templates/sfp.html @@ -71,4 +71,10 @@ </tbody> </table> +<hr> + +<form method="post" class="mb-4" role=form> + <button class="btn btn-primary" type="submit" formaction="/sfp/reset">Reset GTY Tx/Rx & PLL</button> +</form> + {% endblock %} \ No newline at end of file diff --git a/util/devmem.py b/util/devmem.py new file mode 100644 index 0000000..08f5f33 --- /dev/null +++ b/util/devmem.py @@ -0,0 +1,24 @@ +import os, mmap + +def devmem_read(target_adr, length=4): + page_size= os.sysconf("SC_PAGE_SIZE") + reg_base = int(target_adr // page_size) * page_size + seek_size= int(target_adr % page_size) + map_size = seek_size+length + fd = os.open("/dev/mem", os.O_RDWR|os.O_SYNC) + mem = mmap.mmap(fd, map_size, mmap.MAP_SHARED, mmap.PROT_READ|mmap.PROT_WRITE, offset=reg_base) + mem.seek(seek_size, os.SEEK_SET) + value = mem.read(length) + os.close(fd) + return value + +def devmem_write(target_adr, value): + page_size= os.sysconf("SC_PAGE_SIZE") + reg_base = int(target_adr // page_size) * page_size + seek_size= int(target_adr % page_size) + map_size = seek_size+len(value) + fd = os.open("/dev/mem", os.O_RDWR|os.O_SYNC) + mem = mmap.mmap(fd, map_size, mmap.MAP_SHARED, mmap.PROT_READ|mmap.PROT_WRITE, offset=reg_base) + mem.seek(seek_size, os.SEEK_SET) + value = mem.write(value) + os.close(fd) -- GitLab From 465f203d5b68fa9346e2949f0b68acad65aa2184 Mon Sep 17 00:00:00 2001 From: Eric Buschmann <eric.buschmann@cern.ch> Date: Wed, 30 Oct 2024 15:21:50 -0400 Subject: [PATCH 22/23] Only compare part of the FireFly part number --- templates/sfp.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/templates/sfp.html b/templates/sfp.html index 3cf6827..d0989b5 100644 --- a/templates/sfp.html +++ b/templates/sfp.html @@ -48,7 +48,7 @@ <tbody> {% for label, params in data.items() | sort %} - {% if params["part_number"] == "B042804005170" %} + {% if params["part_number"][:3] == "B04" %} <form method="post" class="mb-4" role=form> <tr> <th>{{label}}</th> @@ -56,9 +56,9 @@ <input type="checkbox" id="cdr" name="cdr" checked> </td> <td> - <input type="radio" id="25g" name="rate" value="25g"> + <input type="radio" id="25g" name="rate" value="25g" checked> <label for="25g">25.5-26G</label> - <input type="radio" id="28g" name="rate" value="28g" checked> + <input type="radio" id="28g" name="rate" value="28g"> <label for="28g">27.5-28.1G</label> </td> <td> @@ -77,4 +77,4 @@ <button class="btn btn-primary" type="submit" formaction="/sfp/reset">Reset GTY Tx/Rx & PLL</button> </form> -{% endblock %} \ No newline at end of file +{% endblock %} -- GitLab From 999048dd08b4654a199784058c10eda68b5fd4ad Mon Sep 17 00:00:00 2001 From: "Carlo A. Gottardo" <cerlo.alberto.gottardo@cern.ch> Date: Thu, 31 Oct 2024 16:33:05 +0100 Subject: [PATCH 23/23] add button to load default Si5345 configuration and reset GTY & PLL --- boards/flx182b.py | 3 ++- controllers/si5345.py | 50 +++++++++++++++++++++++++++------------- routes/__init__.py | 10 +++++++- templates/self_test.html | 1 + 4 files changed, 46 insertions(+), 18 deletions(-) diff --git a/boards/flx182b.py b/boards/flx182b.py index 780d0e3..f0db6d4 100644 --- a/boards/flx182b.py +++ b/boards/flx182b.py @@ -249,6 +249,7 @@ config = { "mapping" : { "si5345_a" : { "comment" : "SI5345_A (U60)", + "default_preset" : "Si5345-RevD-5345EVB2_si5345a_200_to_320-Registers.txt", "i2c_bus" : "/dev/i2c-11", "i2c_addr" : 0x68, # if the device is found at one of the alternative addresses, @@ -263,6 +264,7 @@ config = { }, "si5345_b" : { "comment" : "SI5345_B (U59)", + "default_preset" : "Si5345-RevD-5345EVB2_si5345a_200_to_320-Registers.txt", "i2c_bus" : "/dev/i2c-11", "i2c_addr" : 0x69, "i2c_addr_alt" : [0x7d], @@ -274,7 +276,6 @@ config = { "in_sel" : 0b00, # device in_sel pins value }, }, - "self_test" : { "description" : "SI5345 readout", } diff --git a/controllers/si5345.py b/controllers/si5345.py index 87b6ae6..1514e1e 100644 --- a/controllers/si5345.py +++ b/controllers/si5345.py @@ -25,7 +25,7 @@ class SI5345_Controller(): if self.skip_io: return render_template("error.html", error="I/O is disabled in test mode") - data = self.model.read_all() + data = self.model.read_all() if data: forms = self.build_forms() @@ -85,6 +85,13 @@ class SI5345_Controller(): return redirect(f"/{self.name}") + def load_configuration(self, device_name, register_data): + result = self.model.load_configuration(device_name, register_data) + if "error" in result: + return render_template(f"{self.name}.html", data=data, forms=forms, + error=result["error"]) + + def upload_register_configuration(self): if self.skip_io: return redirect(f"/{self.name}") @@ -100,14 +107,11 @@ class SI5345_Controller(): f = form.file.data register_data = f.stream.readlines() - result = self.model.load_configuration(device_name, register_data) - if "error" in result: - return render_template(f"{self.name}.html", data=data, forms=forms, - error=result["error"]) - + self.load_configuration(device_name, register_data) + return redirect(f"/{self.name}") - + def select_preset_configuration(self): if self.skip_io: @@ -117,12 +121,12 @@ class SI5345_Controller(): form = forms["preset_select"] device_name = form.device_name.data data = self.model.read_all() - + if not form.validate(): return render_template(f"{self.name}.html", data=data, forms=forms, - error="Please select a valid preset!") - - file_name = path.join(current_app.root_path, "chip_configs", "si5345", form.preset_name.data) + error="Please select a valid preset!") + + file_name = path.join(current_app.root_path, "chip_configs", "si5345", form.preset_name.data) if not isfile(file_name): return render_template(f"{self.name}.html", data=data, forms=forms, @@ -130,14 +134,28 @@ class SI5345_Controller(): with open(file_name, 'r') as file: register_data = file.readlines() + self.load_configuration(device_name, register_data) - result = self.model.load_configuration(device_name, register_data) + return redirect(f"/{self.name}") - if "error" in result: - return render_template(f"{self.name}.html", data=data, forms=forms, - error=result["error"]) - return redirect(f"/{self.name}") + def load_default_preset(self): + if self.skip_io: + return redirect(f"/{self.name}") + + for device in self.config['mapping'].keys(): + preset = self.config['mapping'][device]['default_preset'] + file_name = path.join(current_app.root_path, "chip_configs", "si5345", preset) + + if not isfile(file_name): + forms = self.build_forms() + data = self.model.read_all() + return render_template(f"{self.name}.html", data=data, forms=forms, + error="Preset file doesn't exist!") + + with open(file_name, 'r') as file: + register_data = file.readlines() + self.load_configuration(device, register_data) def _reset(self, device_name, reset_function): diff --git a/routes/__init__.py b/routes/__init__.py index e831150..def5f40 100644 --- a/routes/__init__.py +++ b/routes/__init__.py @@ -182,7 +182,7 @@ def create_app(name, config): return si5345.update_input_config() @app.route("/si5345/select_preset", methods=["POST"]) - def si5345_select_preset(): + def si5345_select_preset(use_default = False): return si5345.select_preset_configuration() @app.route("/si5345/upload_config", methods=["POST"]) @@ -197,6 +197,13 @@ def create_app(name, config): def si5345_hard_reset(device_name): return si5345.hard_rst(device_name) + if "si5345" in board_config and "sfp" in board_config: + @app.route("/configure_firefly", methods=["POST"]) + def configure_firefly(): + si5345.load_default_preset() + sfp.reset() + return redirect(request.referrer) + if "si53156" in board_config: with app.app_context(): @@ -212,6 +219,7 @@ def create_app(name, config): return si53156.configure() + # Initialize user-space test pages and api for key, resource in board_config["process_runners"].items(): name = resource["name"] diff --git a/templates/self_test.html b/templates/self_test.html index 3bc003b..5ae644f 100644 --- a/templates/self_test.html +++ b/templates/self_test.html @@ -58,6 +58,7 @@ <button class="btn btn-danger" type="submit" formaction="{{url_for('self_test_stop')}}">Stop</button> {% else %} <button class="btn btn-primary" type="submit" formaction="{{url_for('self_test_start')}}">Start</button> + <button class="btn btn-primary" type="submit" formaction="{{url_for('configure_firefly')}}">Configure for eye scans</button> {% endif %} </form> -- GitLab