from __future__ import division
from builtins import str
__author__ = 'Peter Duffin'
from pyfabil.plugins.firmwareblock import FirmwareBlock
from pyfabil.base.definitions import *
from pyfabil.base.utils import *
import logging
import time
[docs]
class TpmClockmon(FirmwareBlock):
""" FirmwareBlock tests class """
@compatibleboards(BoardMake.TpmBoard, BoardMake.Tpm16Board)
@friendlyname('tpm_clock_monitor')
@maxinstances(2)
def __init__(self, board, **kwargs):
""" TpmClockmon initialiser
:param board: Pointer to board instance
"""
super(TpmClockmon, 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)
self.clock_bit_idx = {
'JESD' : [0, 4, 8, 12],
'DDR' : [1, 5, 9, 13],
'UDP' : [2, 6, 10, 14]
}
self.mmcm_ctrl_bitmask = {
'C2C' : 0x1,
'JESD' : 0x2,
'DSP' : 0x4
}
self.available_clocks = list(self.clock_bit_idx.keys())
self.available_clock_managers = list(self.mmcm_ctrl_bitmask.keys())
[docs]
def enable_clock_monitoring(self, clock_name=None):
if clock_name is None:
clocks = self.available_clocks
else:
clocks = [clock_name]
reg = self.board[f'{self._device}.drp_jesd_mmcm.monitor_interrupt_enable']
for clock in clocks:
if clock.upper() not in self.available_clocks:
raise PluginError(f"No clock named '{clock.upper()}' \n Options are {', '.join(self.available_clocks)} (not case sensitive)")
for bit in self.clock_bit_idx.get(clock.upper(), []):
reg = reg | (1<<bit)
self.board[f'{self._device}.drp_jesd_mmcm.monitor_interrupt_enable'] = reg
return
[docs]
def disable_clock_monitoring(self, clock_name=None):
if clock_name is None:
clocks = self.available_clocks
else:
clocks = [clock_name]
reg = self.board[f'{self._device}.drp_jesd_mmcm.monitor_interrupt_enable']
for clock in clocks:
if clock.upper() not in self.available_clocks:
raise PluginError(f"No clock named '{clock.upper()}' \n Options are {', '.join(self.available_clocks)} (not case sensitive)")
for bit in self.clock_bit_idx.get(clock.upper(), []):
reg = reg & ~(1<<bit)
self.board[f'{self._device}.drp_jesd_mmcm.monitor_interrupt_enable'] = reg
return
[docs]
def check_clock_status(self, clock_name=None):
if clock_name is None:
clocks = self.available_clocks
else:
clocks = [clock_name]
status = {}
for clock in clocks:
if clock.upper() not in self.available_clocks:
raise PluginError(f"No clock named '{clock.upper()}' \n Options are {', '.join(self.available_clocks)} (not case sensitive)")
status_reg = self.board[f'{self._device}.drp_jesd_mmcm.monitor_interrupt_status']
bitmask = sum([2**i for i in self.clock_bit_idx.get(clock.upper(), [])]) # Calculate bitmask from bit indexes
errors = status_reg & bitmask
status[clock.upper()] = not errors > 0 # True if Status OK, no errors
return status
[docs]
def clear_clock_status(self, clock_name=None):
if clock_name is None:
clocks = self.available_clocks
else:
clocks = [clock_name]
reg = self.board[f'{self._device}.drp_jesd_mmcm.monitor_interrupt_status']
for clock in clocks:
if clock.upper() not in self.available_clocks:
raise PluginError(f"No clock named '{clock.upper()}' \n Options are {', '.join(self.available_clocks)} (not case sensitive)")
for bit in self.clock_bit_idx.get(clock.upper(), []):
reg = reg | (1<<bit)
self.board[f'{self._device}.drp_jesd_mmcm.monitor_interrupt_status'] = reg
return
[docs]
def get_available_clocks_to_monitor(self):
return self.available_clocks
[docs]
def check_clock_manager_status(self, name=None):
if name is None:
clock_managers = self.available_clock_managers
else:
clock_managers = [name.upper()]
status = {}
for mmcm in clock_managers:
if mmcm not in self.available_clock_managers:
raise PluginError(f"No clock manager named '{mmcm}' \n Options are {', '.join(self.available_clock_managers)} (not case sensitive)")
lock_status = self.board[f'{self._device}.regfile.mmcm_status.locked'] & self.mmcm_ctrl_bitmask[mmcm] > 0
lock_loss_cnt = self.board[f'{self._device}.regfile.mmcm_status.{mmcm.lower()}_mmcm_lock_loss_cnt']
status[f'{mmcm}_MMCM'] = (lock_status, lock_loss_cnt)
return status
[docs]
def clear_clock_manager_status(self, name=None):
if name is None:
clock_managers = self.available_clock_managers
else:
clock_managers = [name.upper()]
reset = 0x0
for mmcm in clock_managers:
if mmcm not in self.available_clock_managers:
raise PluginError(f"No clock manager named '{mmcm}' \n Options are {', '.join(self.available_clock_managers)} (not case sensitive)")
reset = reset | self.mmcm_ctrl_bitmask[mmcm]
self.board[f'{self._device}.regfile.mmcm_status.lock_loss_cnt_reset'] = reset
return
##################### Superclass method implementations #################################
[docs]
def initialise(self):
""" Initialise TpmClockmon """
logging.info("TpmClockmon has been initialised")
return True
[docs]
def status_check(self):
""" Perform status check
:return: Status
"""
logging.info("TpmClockmon : Checking status")
return Status.OK
[docs]
def clean_up(self):
""" Perform cleanup
:return: Success
"""
logging.info("TpmClockmon : Cleaning up")
return True