# -*- coding: utf-8 -*-
#
# Copyright (c) 2022 CSIRO Space and Astronomy.
#
# Distributed under the terms of the CSIRO Open Source Software Licence
# Agreement. See LICENSE for more info.
import json
import typing
import pyxrt
from ska_low_cbf_fpga.fpga_icl import IclField
from ska_low_cbf_fpga.hardware_info import FpgaHardwareInfo
[docs]class XrtInfo(FpgaHardwareInfo):
"""
Hardware info monitoring via pyxrt xrt_info_device.
Access via item index, e.g. ``my_xrt_info["thermal"]``.
Some flattening of data structures is performed.
"""
[docs] def __init__(self, device: typing.Union[str, pyxrt.device]):
if isinstance(device, str):
self._device = pyxrt.device(device)
elif isinstance(device, pyxrt.device):
self._device = device
else:
raise TypeError(
"device must be str or pyxrt.device. "
f"{type(device)} not supported."
)
@property
def xclbin_uuid(self) -> str:
"""Get the UUID of the active xclbin firmware."""
return self._device.get_xclbin_uuid().to_string()
@property
def fpga_temperature(self) -> IclField[int]:
"""
Get FPGA temperature in degrees Celsius.
"""
LOC_KEY = "fpga0" # others locations are: pcb_top_front/rear etc
readings = self["thermal"]
temperature = 0
for i in readings:
if i["location_id"] == LOC_KEY and i["is_present"] == "true":
temperature = int(i["temp_C"])
break
return IclField(
description="FPGA temperture in °C",
format="%d",
type_=int,
value=temperature,
user_write=False,
)
@property
def fpga_power(self) -> IclField[float]:
"""
Get FPGA power consumption in Watts.
"""
# drv = self._driver
POWER_KEY = "power_consumption_watts"
readings = self["electrical"]
power = float(readings[POWER_KEY]) if POWER_KEY in readings else 0
return IclField(
description="FPGA power consumption in W",
format="%f",
type_=float,
value=power,
user_write=False,
)
[docs] def __getitem__(self, item: str):
"""Access info parameters via item index syntax.
:param item: probably one of the values defined in ``_INFO_PARAMS``
"""
if item not in self._INFO_PARAMS.keys():
raise KeyError(f"{item} is not an available health parameter")
raw = self._device.get_info(getattr(pyxrt.xrt_info_device, item))
type_ = self._INFO_PARAMS[item]
if type_ == "json":
parsed = json.loads(raw)
# many of these are dicts with one top-level key
if len(parsed.keys()) == 1:
parsed = parsed[next(iter(parsed))]
# and then often a list with one element
if type(parsed) == list and len(parsed) == 1:
parsed = parsed[0]
return parsed
elif type(type_) == type:
if type_ == bool:
# We need str '0' to evaluate as False
return bool(int(raw))
return type_(raw)
else:
raise ValueError(f"Unsupported type {self._INFO_PARAMS[item]}")