Source code for chipscopy.api.ila.ila_capture

# Copyright (C) 2021-2022, Xilinx, Inc.
# Copyright (C) 2022-2023, Advanced Micro Devices, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import enum
from dataclasses import dataclass
from pprint import pformat
from typing import Dict, Any, Optional, List

from chipscopy.client.axis_ila_core_client import (
    ILATriggerCondition as TCF_ILATriggerCondition,
    ILATriggerMode as TCF_ILATriggerMode,
    ILACaptureCondition as TCF_ILACaptureCondition,
    ILACaptureMode as TCF_ILACaptureMode,
)
from chipscopy.api import dataclass_fields, filter_props
from chipscopy.shared.ila_util import (
    prop_to_enum,
    replace_enum_values,
)

""" Constant for indicating 'trigger in the middle of waveform window."""
ILA_TRIGGER_POSITION_HALF = -1

""" Constant for 'Maximum window sample depth."""
ILA_WINDOW_SIZE_MAX = -1


[docs]class ILACaptureCondition(enum.Enum): """ For Basic Capture Control, the global boolean operator of participating probe comparators. ==================== ================================ Enum Value Description ==================== ================================ ALWAYS Capture all samples. AND AND probe comparators to filter data. OR OR probe comparators to filter data. NAND NAND probe comparators to filter data. NOR NOR probe comparators to filter data. ==================== ================================ """ ALWAYS = 4 OR = 0 AND = 1 NOR = 2 NAND = 3
[docs]class ILATriggerCondition(enum.Enum): """ For Trigger Condition, set trigger mode including basic trigger global boolean operator of participating probe comparators ===================== ================================ Enum Value Description ===================== ================================ AND Basic Trigger mode: AND probe comparators. OR Basic Trigger mode: OR probe comparators. NAND Basic Trigger mode: NAND probe comparators. NOR Basic Trigger mode: NOR probe comparators. IMMEDIATELY Trigger now. TRIGGER_STATE_MACHINE Advanced Trigger mode: TSM file decides when to trigger. ===================== ================================ """ OR = 0 AND = 1 NOR = 2 NAND = 3 IMMEDIATELY = 4 TRIGGER_STATE_MACHINE = 5
[docs]class ILATrigInMode(enum.Enum): """ ===================== ================================ Enum Value Description ===================== ================================ DISABLED No TRIG-IN port use. TRIG_IN_ONLY Trigger only on TRIG-IN port. TRIGGER_OR_TRIG_IN Trigger on basic/trigger mode or on TRIG-IN port. ===================== ================================ """ DISABLED = 0 TRIG_IN_ONLY = 1 TRIGGER_OR_TRIG_IN = 2
[docs]class ILATrigOutMode(enum.Enum): """ Choices for Trig-Out port. ==================== ================================ Enum Value Description ==================== ================================ DISABLED Disables the TRIG_OUT port. TRIGGER_ONLY Result of the basic/advanced trigger condition. TRIG_IN_ONLY Propagates the TRIG_IN port to the TRIG_OUT port. TRIGGER_OR_TRIG_IN OR-ing of the basic/advanced trigger and TRIG_IN port. ==================== ================================ """ DISABLED = 0 TRIGGER_ONLY = 1 TRIG_IN_ONLY = 2 TRIGGER_OR_TRIG_IN = 3
[docs]class ILAState(enum.Enum): """ ILA State Transitions: IDLE -> PRE_TRIGGER -> TRIGGER -> POST_TRIGGER -> IDLE ===================== ================================ Enum Value Description ===================== ================================ IDLE Not armed. PRE_TRIGGER Capturing pre-trigger samples. TRIGGER Waiting for trigger. POST_TRIGGER Capturing post-trigger samples. ===================== ================================ """ IDLE = 0 PRE_TRIGGER = 1 TRIGGER = 2 POST_TRIGGER = 3
[docs]@dataclass(frozen=True) class ILAControl: """Trigger setup""" capture_condition: ILACaptureCondition """Basic capture cntrol global boolean operator. See :class:`ILACaptureCondition`""" trig_in_mode: ILATrigInMode """Usage of TRIG-IN port. See :class:`ILATrigInMode`""" trig_out_mode: ILATrigOutMode """Usage of TRIG-OUT port. See :class:`ILATrigOutMode`""" trigger_condition: ILATriggerCondition """Global boolean operator, for trigger probes. See :class:`ILATriggerCondition`""" trigger_position: int """Trigger position index, within data window.""" window_count: int """Number of data windows.""" window_size: int """Sample count for a window.""" def __str__(self) -> str: return pformat(self.__dict__, 2)
ILA_CONTROL_MEMBERS = dataclass_fields(ILAControl)
[docs]@dataclass(frozen=True) class ILAStatus: """Dynamic status of ILA capture controller""" capture_state: ILAState """Capture state. See :class:`ILAState`""" is_armed: bool """Trigger is armed.""" is_full: bool """Data buffer is full.""" is_trigger_at_startup: bool """ILA is armed at startup.""" samples_captured: int """Number of samples captured in current data window.""" windows_captured: int """Number of fully captured data windows.""" samples_requested: int """Number of samples per window, as requested when was ILA armed.""" windows_requested: int """Number of windows, as requested when ILA was armed.""" trigger_position_requested: int """Trigger position, as requested when ILA was armed.""" tsm_counters: List[int] """Trigger State Machine counter values.""" tsm_flags: List[bool] """Trigger State Machine flag values.""" tsm_state: int """Trigger State Machine current state index.""" tsm_state_name: str = "" """Trigger State Machine current state name.""" def __str__(self) -> str: return pformat(self.__dict__, 2)
ILA_STATUS_MEMBERS = dataclass_fields(ILAStatus) # ILAStatus functions def post_process_status(props: {}, state_names: Optional[Dict[int, str]] = None) -> None: props["capture_state"] = ILAState[props["capture_state"]] props["is_trigger_at_startup"] = props.get("is_tas", False) props["samples_requested"] = props.get("window_depth_readback") props["windows_requested"] = props.get("window_count_readback") props["trigger_position_requested"] = props.get("trigger_pos_readback") props["tsm_counters"] = [ props.get(name, 0) for name in ["tsm_counter0", "tsm_counter1", "tsm_counter2", "tsm_counter3"] ] if state_names: props["tsm_state_name"] = state_names.get(props["tsm_state"], "") def tcf_props_to_status(props: {}, state_names: Optional[Dict[int, str]] = None) -> ILAStatus: """Make immutable ILAStatus instance from status dict.""" post_process_status(props, state_names) return ILAStatus(**filter_props(props, ILA_STATUS_MEMBERS)) def tcf_refresh_status(tcf_node, state_names: Optional[Dict[int, str]] = None) -> ILAStatus: """Read dynamic status.""" props = tcf_node.refresh_property_group(["status"]) return tcf_props_to_status(props, state_names) # ILAControl functions __enum_control = ( ("capture_condition", ILACaptureCondition), ("trig_out_mode", ILATrigOutMode), ("trigger_condition", ILATriggerCondition), ) def control_from_tcf(props: {}) -> ILAControl: # No translation for trigger_position, window_count, window_size, trigger_out_mode cc = props.copy() is_tsm = props["trigger_mode"] in [ TCF_ILATriggerMode.ADVANCED_OR_TRIG_IN.name, TCF_ILATriggerMode.ADVANCED_ONLY.name, ] is_trigger_or_trig_in = props["trigger_mode"] in [ TCF_ILATriggerMode.BASIC_OR_TRIG_IN.name, TCF_ILATriggerMode.ADVANCED_OR_TRIG_IN.name, TCF_ILATriggerMode.TRIG_IN_ONLY.name, ] # trigger condition del cc["trigger_mode"] if is_tsm: cc["trigger_condition"] = ILATriggerCondition.TRIGGER_STATE_MACHINE # trig_in_mode if is_trigger_or_trig_in: cc["trig_in_mode"] = ( ILATrigInMode.TRIGGER_OR_TRIG_IN if is_trigger_or_trig_in else ILATrigInMode.TRIG_IN ) else: cc["trig_in_mode"] = ILATrigInMode.DISABLED # capture mode, capture condition del cc["capture_mode"] if props["capture_mode"] == TCF_ILACaptureMode.ALWAYS: cc["capture_condition"] = ILACaptureCondition.ALWAYS prop_to_enum(cc, __enum_control) return ILAControl(**filter_props(cc, ILA_CONTROL_MEMBERS)) def control_to_tcf(cc: ILAControl) -> Dict[str, Any]: # trigger condition tcf_t_condition = cc.trigger_condition.name # trigger mode if cc.trig_in_mode == ILATrigInMode.TRIG_IN_ONLY: tcf_t_mode = TCF_ILATriggerMode.TRIG_IN_ONLY.name elif cc.trigger_condition == ILATriggerCondition.TRIGGER_STATE_MACHINE: if cc.trig_in_mode == ILATrigInMode.TRIGGER_OR_TRIG_IN: tcf_t_mode = TCF_ILATriggerMode.ADVANCED_OR_TRIG_IN.name else: tcf_t_mode = TCF_ILATriggerMode.ADVANCED_ONLY.name elif cc.trig_in_mode == ILATrigInMode.TRIGGER_OR_TRIG_IN: tcf_t_mode = TCF_ILATriggerMode.BASIC_OR_TRIG_IN.name else: tcf_t_mode = TCF_ILATriggerMode.BASIC_ONLY.name # capture mode, capture condition if cc.capture_condition == ILACaptureCondition.ALWAYS: tcf_capture_mode = TCF_ILACaptureMode.ALWAYS.name tcf_capture_condition = TCF_ILACaptureCondition.AND.name else: tcf_capture_mode = TCF_ILACaptureMode.BASIC tcf_capture_condition = cc.capture_condition.name res = { "capture_mode": tcf_capture_mode, "capture_condition": tcf_capture_condition, "trig_out_mode": cc.trig_out_mode.name, "trigger_mode": tcf_t_mode, "trigger_condition": tcf_t_condition, "trigger_position": cc.trigger_position, "window_count": cc.window_count, "window_size": cc.window_size, } replace_enum_values(res) return res