Source code for chipscopy.api.ibert.gt

# 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.

from typing import TYPE_CHECKING, Dict, Union, Any

from chipscopy.api.ibert.aliases import CHILDREN, RX_KEY, TX_KEY, TYPE, PLL_SOURCE, PLL_KEY
from chipscopy.api.ibert.rx import RX
from chipscopy.api.ibert.serial_object_base import SerialObjectBase
from chipscopy.api.ibert.tx import TX
from chipscopy.api.ibert.pll import PLL
from more_itertools import one
from typing_extensions import final

if TYPE_CHECKING:  # pragma: no cover
    from chipscopy.api.ibert.gt_group import GTGroup  # noqa


[docs]@final class GT(SerialObjectBase["GTGroup", Union[TX, RX]]): def __init__(self, gt_info: Dict[str, Any], parent, tcf_node): SerialObjectBase.__init__(self, gt_info, parent, tcf_node) # This is used by the filter_by method in QueryList self.filter_by = {"name": self.name, "type": self.type, "handle": self.handle} self.pll: list[PLL] = [] "PLL driving this GT" self.rx: RX = None """RX of the GT""" self.tx: TX = None """TX of the GT""" # def __repr__(self) -> str: # return self.name
[docs] def reset(self): """ Reset the TX and RX in the GT """ self.setup() if self.rx: self.rx.reset() if self.tx: self.tx.reset()
[docs] def update_pll(self): """Updates the reference to the pll attribute based on the appropriate property value""" if not self.setup_done: raise RuntimeError("Call this only after setup is complete for the GT") if PLL_SOURCE not in self._property_for_alias: return _, pll_names_for_this_gt = self._property.refresh( self._property_for_alias[PLL_SOURCE] ).popitem() if pll_names_for_this_gt: for pll in self.parent.plls: if pll.name == pll_names_for_this_gt: self.pll.append(pll) else: print("No PLL defined for this GT")
def setup(self): if self.setup_done: return obj_info = self.core_tcf_node.get_obj_info(self.handle) self._build_aliases(obj_info) if not obj_info.get(CHILDREN): return # Build the child objects for child_name, child_obj_info in obj_info[CHILDREN].items(): obj: Union[TX, RX] if child_obj_info[TYPE] == RX_KEY: obj = RX(child_obj_info, self, self.core_tcf_node) elif child_obj_info[TYPE] == TX_KEY: obj = TX(child_obj_info, self, self.core_tcf_node) elif child_obj_info[TYPE].startswith(PLL_KEY): obj = PLL(child_obj_info, self, self.core_tcf_node) else: continue obj.setup() self._children.append(obj) # We always expect a GT to have one valid RX and one valid TX, no more, no less. self.rx = one( self._children.filter_by(type=RX_KEY), too_short=RuntimeError(f"No RX associated with GT {self.handle}!"), too_long=RuntimeError(f"More than one RX found for GT {self.handle}!"), ) self.tx = one( self._children.filter_by(type=TX_KEY), too_short=RuntimeError(f"No TX associated with GT {self.handle}!"), too_long=RuntimeError(f"More than one TX found for GT {self.handle}!"), ) self.setup_done = True