Merge pull request #977 from antmicro/jboc/gtkw-endpoint
GTKWSave: improved support for Endpoint
This commit is contained in:
commit
3387853b6b
|
@ -1,5 +1,6 @@
|
||||||
# This file is part of LiteX.
|
# This file is part of LiteX.
|
||||||
#
|
#
|
||||||
|
# Copyright (c) 2021 Antmicro <www.antmicro.com>
|
||||||
# SPDX-License-Identifier: BSD-2-Clause
|
# SPDX-License-Identifier: BSD-2-Clause
|
||||||
#
|
#
|
||||||
|
|
||||||
|
@ -11,6 +12,8 @@ from typing import Optional, Sequence, Any, Callable, Generator, Dict, Tuple
|
||||||
from migen import *
|
from migen import *
|
||||||
from migen.fhdl.namer import Namespace
|
from migen.fhdl.namer import Namespace
|
||||||
|
|
||||||
|
from litex.soc.interconnect import stream
|
||||||
|
|
||||||
|
|
||||||
class SigTrace:
|
class SigTrace:
|
||||||
"""Trace configuration for a single signal"""
|
"""Trace configuration for a single signal"""
|
||||||
|
@ -144,15 +147,33 @@ class GTKWSave:
|
||||||
clks = [cd.clk for cd in self.vns.clock_domains]
|
clks = [cd.clk for cd in self.vns.clock_domains]
|
||||||
self.group(clks, group_name="clocks", alias=False, closed=False, **kwargs)
|
self.group(clks, group_name="clocks", alias=False, closed=False, **kwargs)
|
||||||
|
|
||||||
def add(self, obj: Any, **kwargs):
|
def add(self, obj: Any, no_defaults=False, **kwargs):
|
||||||
# TODO: add automatic default handlers for Litex types (e.g. WishBone, AXI, streams, ...)
|
# TODO: add automatic default handlers for Litex types (e.g. WishBone, AXI, ...)
|
||||||
|
|
||||||
|
def default_mappers(types, mappers):
|
||||||
|
if not no_defaults and isinstance(obj, types):
|
||||||
|
kwargs["mappers"] = DEFAULT_ENDPOINT_MAPPERS + kwargs.get("mappers", [])
|
||||||
|
|
||||||
if isinstance(obj, Record):
|
if isinstance(obj, Record):
|
||||||
|
# automatic settings for supported Record types
|
||||||
|
default_mappers(stream.Endpoint, DEFAULT_ENDPOINT_MAPPERS)
|
||||||
self.group([s for s, _ in obj.iter_flat()], **kwargs)
|
self.group([s for s, _ in obj.iter_flat()], **kwargs)
|
||||||
elif isinstance(obj, Signal):
|
elif isinstance(obj, Signal):
|
||||||
self.signal(obj)
|
self.signal(obj)
|
||||||
|
elif self._is_module_with_attrs(obj, ["sink", "source"], types=stream.Endpoint, required=any):
|
||||||
|
self._add_groupped_attrs(obj, ["sink", "source"], **kwargs) # recurse to Record->Endpoint handler
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError(type(obj), obj)
|
raise NotImplementedError(type(obj), obj)
|
||||||
|
|
||||||
|
def _add_groupped_attrs(self, obj, attrs, **kwargs):
|
||||||
|
# add given attributes of an object in an encapsulating group, with attribute names as subgroup names
|
||||||
|
with self.gtkw.group(kwargs["group_name"], closed=kwargs.get("closed", True)):
|
||||||
|
for attr in attrs:
|
||||||
|
if hasattr(obj, attr):
|
||||||
|
new_kwargs = kwargs.copy()
|
||||||
|
new_kwargs["group_name"] = attr
|
||||||
|
self.add(getattr(obj, attr), **new_kwargs)
|
||||||
|
|
||||||
def make_fsm_state_translation(self, fsm: FSM) -> str:
|
def make_fsm_state_translation(self, fsm: FSM) -> str:
|
||||||
# generate filter file
|
# generate filter file
|
||||||
from vcd.gtkw import make_translation_filter
|
from vcd.gtkw import make_translation_filter
|
||||||
|
@ -203,6 +224,13 @@ class GTKWSave:
|
||||||
name = name[:name.rfind("[")]
|
name = name[:name.rfind("[")]
|
||||||
return name
|
return name
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _is_module_with_attrs(obj, attrs, types, required) -> bool:
|
||||||
|
if not isinstance(obj, Module):
|
||||||
|
return False
|
||||||
|
available = map(lambda a: hasattr(obj, a) and isinstance(getattr(obj, a), types), attrs)
|
||||||
|
return required(available)
|
||||||
|
|
||||||
# Generic mappers ----------------------------------------------------------------------------------
|
# Generic mappers ----------------------------------------------------------------------------------
|
||||||
|
|
||||||
def _regex_map(
|
def _regex_map(
|
||||||
|
@ -320,3 +348,22 @@ def dfi_in_phase_colorer(**kwargs) -> SigMapper:
|
||||||
"orange": suffixes2re(["wrdata_en", "wrdata", "wrdata_mask"]),
|
"orange": suffixes2re(["wrdata_en", "wrdata", "wrdata_mask"]),
|
||||||
"red": suffixes2re(["rddata_en", "rddata", "rddata_valid"]),
|
"red": suffixes2re(["rddata_en", "rddata", "rddata_valid"]),
|
||||||
}, default="indigo", **kwargs)
|
}, default="indigo", **kwargs)
|
||||||
|
|
||||||
|
def endpoint_filter(firstlast=False, payload=True, param=True, **kwargs) -> SigMapper:
|
||||||
|
patterns = suffixes2re(["valid", "ready"])
|
||||||
|
if firstlast: patterns += suffixes2re(["first", "last"])
|
||||||
|
if payload: patterns += ["payload_"]
|
||||||
|
if param: patterns += ["param_"]
|
||||||
|
return regex_filter(patterns, **kwargs)
|
||||||
|
|
||||||
|
def endpoint_sorter(**kwargs) -> SigMapper:
|
||||||
|
return regex_sorter(suffixes2re(["valid", "ready", "first", "last"]), **kwargs)
|
||||||
|
|
||||||
|
def endpoint_colorer(**kwargs) -> SigMapper:
|
||||||
|
return regex_colorer({
|
||||||
|
"yellow": suffixes2re(["valid"]),
|
||||||
|
"orange": suffixes2re(["ready"]),
|
||||||
|
"indigo": suffixes2re(["first", "last"]),
|
||||||
|
}, default="normal", **kwargs)
|
||||||
|
|
||||||
|
DEFAULT_ENDPOINT_MAPPERS = [endpoint_sorter(), endpoint_colorer()]
|
||||||
|
|
Loading…
Reference in New Issue