from __future__ import division
from builtins import str
__author__ = 'chiello'
from pyfabil.plugins.firmwareblock import FirmwareBlock
from pyfabil.base.definitions import *
from pyfabil.base.utils import *
import logging
import time
ad_fpga = [
{"name": "VM_FE0", "ref": 3.5000, "fpga": 0, "ch": 6, "divider": 11.5/(31.6+11.5)},
{"name": "VM_FE1", "ref": 3.5000, "fpga": 1, "ch": 8, "divider": 11.5/(31.6+11.5)},
{"name": "ACS_FE0_VI", "ref": 3.5000, "fpga": 0, "ch": 5, "divider": 0.0450, "unit": "A"},
{"name": "ACS_FE1_VI", "ref": 3.5000, "fpga": 1, "ch": 14, "divider": 0.0450, "unit": "A"},
{"name": "VM_DDR0_VTT", "ref": 0.6750, "fpga": 0, "ch": 9},
{"name": "VM_DDR0_VREF", "ref": 0.6750, "fpga": 0, "ch": 14},
{"name": "VM_AGP0", "ref": 0.9850, "fpga": 0, "ch": 0},
{"name": "VM_AGP1", "ref": 0.9850, "fpga": 0, "ch": 1},
{"name": "VM_AGP2", "ref": 0.9850, "fpga": 0, "ch": 2},
{"name": "VM_AGP3", "ref": 0.9850, "fpga": 0, "ch": 3},
{"name": "VM_AGP4", "ref": 0.9850, "fpga": 1, "ch": 0},
{"name": "VM_AGP5", "ref": 0.9850, "fpga": 1, "ch": 1},
{"name": "VM_AGP6", "ref": 0.9850, "fpga": 1, "ch": 2},
{"name": "VM_AGP7", "ref": 0.9850, "fpga": 1, "ch": 3},
{"name": "VM_CLK0B", "ref": 3.3000, "fpga": 0, "ch": 8, "divider": 11.5/(31.6+11.5)},
{"name": "VM_CLK1B", "ref": 3.3000, "fpga": 1, "ch": 7, "divider": 11.5/(31.6+11.5)},
{"name": "VM_MGT0_AUX", "ref": 1.8000, "fpga": 0, "ch": 15, "divider": 11.5/(20+11.5)},
{"name": "VM_MGT1_AUX", "ref": 1.8000, "fpga": 1, "ch": 11, "divider": 11.5/(20+11.5)},
{"name": "VM_ADA0", "ref": 3.3000, "fpga": 0, "ch": 13, "divider": 11.5/(31.6+11.5)},
{"name": "VM_ADA1", "ref": 3.3000, "fpga": 0, "ch": 12, "divider": 11.5/(31.6+11.5)},
{"name": "VM_ADA2", "ref": 3.3000, "fpga": 1, "ch": 4, "divider": 11.5/(31.6+11.5)},
{"name": "VM_ADA3", "ref": 3.3000, "fpga": 1, "ch": 5, "divider": 11.5/(31.6+11.5)},
{"name": "VM_PLL", "ref": 3.3000, "fpga": 0, "ch": 7, "divider": 11.5/(31.6+11.5)},
{"name": "VM_MAN1V2", "ref": 1.2000, "fpga": 0, "ch": 11, "divider": 10.2/(4.99+10.2)},
{"name": "VM_MAN2V5", "ref": 2.5000, "fpga": 0, "ch": 10, "divider": 11.5/(20+11.5)},
{"name": "VM_MAN3V3", "ref": 3.3000, "fpga": 0, "ch": 4, "divider": 11.5/(31.6+11.5)},
{"name": "VM_DDR1_VTT", "ref": 0.6750, "fpga": 1, "ch": 12},
{"name": "VM_DDR1_VREF", "ref": 0.6750, "fpga": 1, "ch": 13},
{"name": "VM_DDR_VDD", "ref": 1.3500, "fpga": 1, "ch": 9, "divider": 10.2/(4.99+10.2)},
{"name": "VM_SW_DVDD", "ref": 1.6500, "fpga": 1, "ch": 6, "divider": 20/(15+20)},
{"name": "VM_SW_AMP", "ref": 3.5000, "fpga": 1, "ch": 15, "divider": 11.5/(31.6+11.5)},
]
# ACS_FE0_VI & ACS_FE1_VI known defective
# VM_MAN1V2 & VM_SW_AMP will not be as expected as not turned on
# ADAs default to disabled so VM_ADA0, VM_ADA1, VM_ADA2 & VM_ADA3 will be approx 0 in this configuration
# Other readings should be as expected ("ref" measurement)
[docs]
def get_value_index(name, device):
if device == "fpga1":
fpga_ind = 0
else:
fpga_ind = 1
for i in range(0, len(ad_fpga)):
if (name == ad_fpga[i]["name"]) and (fpga_ind == ad_fpga[i]["fpga"]):
return i
return -1
[docs]
class TpmSysmon(FirmwareBlock):
""" FirmwareBlock tests class """
@compatibleboards(BoardMake.TpmBoard, BoardMake.Tpm16Board)
@friendlyname('tpm_sysmon')
@maxinstances(2)
def __init__(self, board, **kwargs):
""" TpmSysmon initialiser
:param board: Pointer to board instance
"""
super(TpmSysmon, self).__init__(board)
self._board_type = kwargs.get('board_type', 'XTPM')
if 'device' not in list(kwargs.keys()):
raise PluginError("TpmFpga: Require a node instance")
self._device = kwargs['device']
if self._device == Device.FPGA_1:
self._device = 'fpga1'
elif self._device == Device.FPGA_2:
self._device = 'fpga2'
else:
raise PluginError("TpmFpga: Invalid device %s" % self._device)
[docs]
def initialize(self):
""" Reset System Monitor """
self.board['%s.sys_mon.sysmonrr' % self._device] = 0x1
self.board['%s.sys_mon.sysmonrr' % self._device] = 0x0
[docs]
def get_fpga_temperature(self):
""" Read FPGA temperature"""
rdval = self.board['%s.sys_mon.temp' % self._device]
temp = ((rdval * 501.3743) / 65536) - 273.67777
return temp
[docs]
def read_adx(self, ad_idx):
""" Read specified AD to get VAUX"""
if int(ad_idx) > 15 or int(ad_idx) < 0:
logging.error('%s sysmon, invalid AD index %s' % (self._device, str(ad_idx)))
return -1
else:
rdval = self.board['%s.sys_mon.vaux_%s' % (self._device, str(ad_idx))]
voltage = float(rdval) * 1/65536
return voltage
[docs]
def read_conf_regs(self):
""" Read consifguration registers"""
rdval0 = self.board['%s.sys_mon.conf_reg_0' % self._device]
rdval1 = self.board['%s.sys_mon.conf_reg_1' % self._device]
rdval2 = self.board['%s.sys_mon.conf_reg_2' % self._device]
rdval3 = self.board['%s.sys_mon.conf_reg_3' % self._device]
return rdval0, rdval1, rdval2, rdval3
[docs]
def get_vcc_int(self):
""" Read internal VCC"""
val = self.board['%s.sys_mon.vccint' % self._device]
val = float(val)/65536*3
return val
[docs]
def get_vcc_aux(self):
""" Read internal VAUX"""
val = self.board['%s.sys_mon.vccaux' % self._device]
val = float(val)/65536*3
return val
[docs]
def get_vcc_fe(self):
expected = 0.934
nominal = 3.5
if self._device == "fpga1":
vcc = self.read_adx(6)
else:
vcc = self.read_adx(8)
vcc = vcc / expected * nominal
return vcc
[docs]
def get_available_voltages(self):
voltages = []
if self._device == "fpga1":
fpga_ind = 0
else:
fpga_ind = 1
for i in range(0, len(ad_fpga)):
if fpga_ind == ad_fpga[i]["fpga"] and ad_fpga[i].get("unit") != "A":
voltages.append(ad_fpga[i]["name"])
return voltages
[docs]
def get_available_currents(self):
currents = []
if self._device == "fpga1":
fpga_ind = 0
else:
fpga_ind = 1
for i in range(0, len(ad_fpga)):
if fpga_ind == ad_fpga[i]["fpga"] and ad_fpga[i].get("unit") == "A":
currents.append(ad_fpga[i]["name"])
return currents
[docs]
def get_measure_val(self, name):
index = get_value_index(name,self._device)
if index == -1:
logging.error("ERROR: measure not available check provided name")
return -1
else:
val = self.read_adx(ad_fpga[index]["ch"])
if "divider" in ad_fpga[index]:
val = val / ad_fpga[index]["divider"]
return val
[docs]
def get_voltage(self, voltage=None):
if voltage is None:
voltages = self.get_available_voltages()
else:
if voltage not in self.get_available_voltages():
# raise PluginError(f"No voltage named '{voltage}' \n Options are {', '.join(self.get_available_voltages())}")
return {}
voltages = [voltage]
rt = {}
for name in voltages:
rt[name] = round(self.get_measure_val(name), 2)
return rt
[docs]
def get_current(self, current=None):
if current is None:
currents = self.get_available_currents()
else:
if current not in self.get_available_currents():
# raise PluginError(f"No current named '{current}' \n Options are {', '.join(self.get_available_currents())}")
return {}
currents = [current]
rt = {}
for name in currents:
rt[name] = round(self.get_measure_val(name), 2)
return rt
##################### Superclass method implementations #################################
[docs]
def initialise(self):
""" Initialise TpmSysmon """
logging.info("TpmSysmon has been initialised")
return True
[docs]
def status_check(self):
""" Perform status check
:return: Status
"""
logging.info("TpmSysmon : Checking status")
return Status.OK
[docs]
def clean_up(self):
""" Perform cleanup
:return: Success
"""
logging.info("TpmSysmon : Cleaning up")
return True