Closes #275.
"Memory",
"Record",
"DomainRenamer", "ResetInserter", "EnableInserter",
- "CEInserter", # TODO(nmigen-0.2): remove this
]
from ...hdl.ir import Fragment, Instance
from ...hdl.dsl import Module
from .module import Module as CompatModule
+from .structure import Signal
from ...lib.io import Pin
+import builtins
+import warnings
from collections import OrderedDict
+from ...utils import bits_for
from ..._utils import deprecated, extend
from ...hdl import ast
-from ...hdl.ast import (DUID, Value, Signal, Mux, Slice as _Slice, Cat, Repl, Const, C,
+from ...hdl.ast import (DUID,
+ Shape, signed, unsigned,
+ Value, Const, C, Mux, Slice as _Slice, Part, Cat, Repl,
+ Signal as NativeSignal,
ClockSignal, ResetSignal,
Array, ArrayProxy as _ArrayProxy)
from ...hdl.cd import ClockDomain
return Value.cast(v)
-@extend(Cat)
-@property
-@deprecated("instead of `Cat.l`, use `Cat.parts`")
-def l(self):
- return self.parts
+class CompatSignal(NativeSignal):
+ def __init__(self, bits_sign=None, name=None, variable=False, reset=0,
+ reset_less=False, name_override=None, min=None, max=None,
+ related=None, attr=None, src_loc_at=0, **kwargs):
+ if min is not None or max is not None:
+ warnings.warn("instead of `Signal(min={min}, max={max})`, "
+ "use `Signal(range({min}, {max}))`"
+ .format(min=min or 0, max=max or 2),
+ DeprecationWarning, stacklevel=2 + src_loc_at)
+
+ if bits_sign is None:
+ if min is None:
+ min = 0
+ if max is None:
+ max = 2
+ max -= 1 # make both bounds inclusive
+ if min > max:
+ raise ValueError("Lower bound {} should be less or equal to higher bound {}"
+ .format(min, max + 1))
+ sign = min < 0 or max < 0
+ if min == max:
+ bits = 0
+ else:
+ bits = builtins.max(bits_for(min, sign), bits_for(max, sign))
+ shape = signed(bits) if sign else unsigned(bits)
+ else:
+ if not (min is None and max is None):
+ raise ValueError("Only one of bits/signedness or bounds may be specified")
+ shape = bits_sign
+ super().__init__(shape=shape, name=name_override or name,
+ reset=reset, reset_less=reset_less,
+ attrs=attr, src_loc_at=1 + src_loc_at, **kwargs)
-@deprecated("instead of `Replicate`, use `Repl`")
-def Replicate(v, n):
- return Repl(v, n)
+
+Signal = CompatSignal
@deprecated("instead of `Constant`, use `Const`")
return Const(value, bits_sign)
+@deprecated("instead of `Replicate`, use `Repl`")
+def Replicate(v, n):
+ return Repl(v, n)
+
+
+@extend(Const)
+@property
+@deprecated("instead of `.nbits`, use `.width`")
+def nbits(self):
+ return self.width
+
+
+@extend(NativeSignal)
+@property
+@deprecated("instead of `.nbits`, use `.width`")
+def nbits(self):
+ return self.width
+
+
+@extend(NativeSignal)
+@NativeSignal.nbits.setter
+@deprecated("instead of `.nbits = x`, use `.width = x`")
+def nbits(self, value):
+ self.width = value
+
+
+@extend(NativeSignal)
+@deprecated("instead of `.part`, use `.bit_select`")
+def part(self, offset, width):
+ return Part(self, offset, width, src_loc_at=2)
+
+
+@extend(Cat)
+@property
+@deprecated("instead of `.l`, use `.parts`")
+def l(self):
+ return self.parts
+
+
+@extend(ast.Operator)
+@property
+@deprecated("instead of `.op`, use `.operator`")
+def op(self):
+ return self.operator
+
+
@extend(_ArrayProxy)
@property
@deprecated("instead `_ArrayProxy.choices`, use `ArrayProxy.elems`")
cond = Value.cast(cond)
if len(cond) != 1:
cond = cond.bool()
- super().__init__(cond, {("1",): ast.Statement.wrap(stmts)})
+ super().__init__(cond, {("1",): ast.Statement.cast(stmts)})
@deprecated("instead of `.Elif(cond, ...)`, use `with m.Elif(cond): ...`")
def Elif(self, cond, *stmts):
if len(cond) != 1:
cond = cond.bool()
self.cases = OrderedDict((("-" + k,), v) for (k,), v in self.cases.items())
- self.cases[("1" + "-" * len(self.test),)] = ast.Statement.wrap(stmts)
+ self.cases[("1" + "-" * len(self.test),)] = ast.Statement.cast(stmts)
self.test = Cat(self.test, cond)
return self
@deprecated("instead of `.Else(...)`, use `with m.Else(): ...`")
def Else(self, *stmts):
- self.cases[()] = ast.Statement.wrap(stmts)
+ self.cases[()] = ast.Statement.cast(stmts)
return self
elif isinstance(key, str) and key == "default":
key = ()
else:
- key = ("{:0{}b}".format(wrap(key).value, len(self.test)),)
+ key = ("{:0{}b}".format(ast.Value.cast(key).value, len(self.test)),)
stmts = self.cases[key]
del self.cases[key]
self.cases[()] = stmts
del self.fwft
+@extend(NativeFIFOInterface)
+@property
+@deprecated("instead of `fifo.din`, use `fifo.w_data`")
+def din(self):
+ return self.w_data
+
+
+@extend(NativeFIFOInterface)
+@NativeFIFOInterface.din.setter
+@deprecated("instead of `fifo.din = x`, use `fifo.w_data = x`")
+def din(self, w_data):
+ self.w_data = w_data
+
+
+@extend(NativeFIFOInterface)
+@property
+@deprecated("instead of `fifo.writable`, use `fifo.w_rdy`")
+def writable(self):
+ return self.w_rdy
+
+
+@extend(NativeFIFOInterface)
+@NativeFIFOInterface.writable.setter
+@deprecated("instead of `fifo.writable = x`, use `fifo.w_rdy = x`")
+def writable(self, w_rdy):
+ self.w_rdy = w_rdy
+
+
+@extend(NativeFIFOInterface)
+@property
+@deprecated("instead of `fifo.we`, use `fifo.w_en`")
+def we(self):
+ return self.w_en
+
+
+@extend(NativeFIFOInterface)
+@NativeFIFOInterface.we.setter
+@deprecated("instead of `fifo.we = x`, use `fifo.w_en = x`")
+def we(self, w_en):
+ self.w_en = w_en
+
+
+@extend(NativeFIFOInterface)
+@property
+@deprecated("instead of `fifo.dout`, use `fifo.r_data`")
+def dout(self):
+ return self.r_data
+
+
+@extend(NativeFIFOInterface)
+@NativeFIFOInterface.dout.setter
+@deprecated("instead of `fifo.dout = x`, use `fifo.r_data = x`")
+def dout(self, r_data):
+ self.r_data = r_data
+
+
+@extend(NativeFIFOInterface)
+@property
+@deprecated("instead of `fifo.readable`, use `fifo.r_rdy`")
+def readable(self):
+ return self.r_rdy
+
+
+@extend(NativeFIFOInterface)
+@NativeFIFOInterface.readable.setter
+@deprecated("instead of `fifo.readable = x`, use `fifo.r_rdy = x`")
+def readable(self, r_rdy):
+ self.r_rdy = r_rdy
+
+
+@extend(NativeFIFOInterface)
+@property
+@deprecated("instead of `fifo.re`, use `fifo.r_en`")
+def re(self):
+ return self.r_en
+
+
+@extend(NativeFIFOInterface)
+@NativeFIFOInterface.re.setter
+@deprecated("instead of `fifo.re = x`, use `fifo.r_en = x`")
+def re(self, r_en):
+ self.r_en = r_en
+
+
@extend(NativeFIFOInterface)
def read(self):
"""Read method for simulation."""
from ..._utils import deprecated, _ignore_deprecated
from ...hdl.xfrm import ValueTransformer, StatementTransformer
from ...hdl.ast import *
+from ...hdl.ast import Signal as NativeSignal
from ..fhdl.module import CompatModule, CompatFinalizeError
-from ..fhdl.structure import If, Case
+from ..fhdl.structure import Signal, If, Case
__all__ = ["AnonymousState", "NextState", "NextValue", "FSM"]
ty = type(a)
if ty == Const:
return a.value == b.value
- elif ty == Signal:
+ elif ty == NativeSignal or ty == Signal:
return a is b
elif ty == Cat:
return all(_target_eq(x, y) for x, y in zip(a.l, b.l))
self.decoding = {n: s for s, n in self.encoding.items()}
decoder = lambda n: "{}/{}".format(self.decoding[n], n)
- self.state = Signal(max=nstates, reset=self.encoding[self.reset_state], decoder=decoder)
+ self.state = Signal(range(nstates), reset=self.encoding[self.reset_state], decoder=decoder)
self.next_state = Signal.like(self.state)
for state, signal in self.before_leaving_signals.items():
from .ir import Elaboratable, Fragment, Instance
from .mem import Memory
from .rec import Record
-from .xfrm import DomainRenamer, ResetInserter, EnableInserter, \
- CEInserter # TODO(nmigen-0.2): remove this
+from .xfrm import DomainRenamer, ResetInserter, EnableInserter
__all__ = [
"Memory",
"Record",
"DomainRenamer", "ResetInserter", "EnableInserter",
- "CEInserter", # TODO(nmigen-0.2): remove this
]
from abc import ABCMeta, abstractmethod
-import builtins
import traceback
import warnings
import typing
return Const(obj.value, Shape.cast(type(obj)))
raise TypeError("Object {!r} cannot be converted to an nMigen value".format(obj))
- # TODO(nmigen-0.2): remove this
- @classmethod
- @deprecated("instead of `Value.wrap`, use `Value.cast`")
- def wrap(cls, obj):
- return cls.cast(obj)
-
def __init__(self, *, src_loc_at=0):
super().__init__()
self.src_loc = tracer.get_src_loc(1 + src_loc_at)
"""
return ~premise | conclusion
- # TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
- @deprecated("instead of `.part`, use `.bit_select`")
- def part(self, offset, width):
- return Part(self, offset, width, src_loc_at=1)
-
def bit_select(self, offset, width):
"""Part-select with bit granularity.
self.width, self.signed = shape
self.value = self.normalize(self.value, shape)
- # TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
- @property
- @deprecated("instead of `const.nbits`, use `const.width`")
- def nbits(self):
- return self.width
-
def shape(self):
return Shape(self.width, self.signed)
self.operator = operator
self.operands = [Value.cast(op) for op in operands]
- # TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
- @property
- @deprecated("instead of `.op`, use `.operator`")
- def op(self):
- return self.operator
-
def shape(self):
def _bitwise_binary_shape(a_shape, b_shape):
a_bits, a_sign = a_shape
super().__init__(src_loc_at=src_loc_at)
self.value = Value.cast(value)
self.start = start
- self.stop = stop
-
- # TODO(nmigen-0.2): remove this
- @property
- @deprecated("instead of `slice.end`, use `slice.stop`")
- def end(self):
- return self.stop
+ self.stop = stop
def shape(self):
return Shape(self.stop - self.start)
return "(repl {!r} {})".format(self.value, self.count)
-@final
+# @final
class Signal(Value, DUID):
"""A varying integer value.
attrs : dict
"""
- def __init__(self, shape=None, *, name=None, reset=0, reset_less=False, min=None, max=None,
+ def __init__(self, shape=None, *, name=None, reset=0, reset_less=False,
attrs=None, decoder=None, src_loc_at=0):
super().__init__(src_loc_at=src_loc_at)
- if isinstance(reset, Enum):
- reset = reset.value
- if not isinstance(reset, int):
- raise TypeError("Reset value has to be an int or an integral Enum")
-
- # TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
- if min is not None or max is not None:
- warnings.warn("instead of `Signal(min={min}, max={max})`, "
- "use `Signal(range({min}, {max}))`"
- .format(min=min or 0, max=max or 2),
- DeprecationWarning, stacklevel=2 + src_loc_at)
-
if name is not None and not isinstance(name, str):
raise TypeError("Name must be a string, not {!r}".format(name))
self.name = name or tracer.get_var_name(depth=2 + src_loc_at, default="$signal")
if shape is None:
- if min is None:
- min = 0
- if max is None:
- max = 2
- max -= 1 # make both bounds inclusive
- if min > max:
- raise ValueError("Lower bound {} should be less or equal to higher bound {}"
- .format(min, max + 1))
- self.signed = min < 0 or max < 0
- if min == max:
- self.width = 0
- else:
- self.width = builtins.max(bits_for(min, self.signed),
- bits_for(max, self.signed))
+ shape = unsigned(1)
+ self.width, self.signed = Shape.cast(shape, src_loc_at=1 + src_loc_at)
- else:
- if not (min is None and max is None):
- raise ValueError("Only one of bits/signedness or bounds may be specified")
- self.width, self.signed = Shape.cast(shape, src_loc_at=1 + src_loc_at)
+ if isinstance(reset, Enum):
+ reset = reset.value
+ if not isinstance(reset, int):
+ raise TypeError("Reset value has to be an int or an integral Enum")
reset_width = bits_for(reset, self.signed)
if reset != 0 and reset_width > self.width:
.format(reset, reset_width, self.width),
SyntaxWarning, stacklevel=2 + src_loc_at)
- self.reset = int(reset)
+ self.reset = reset
self.reset_less = bool(reset_less)
self.attrs = OrderedDict(() if attrs is None else attrs)
else:
self.decoder = decoder
- @classmethod
- @deprecated("instead of `Signal.range(...)`, use `Signal(range(...))`")
- def range(cls, *args, src_loc_at=0, **kwargs):
- return cls(range(*args), src_loc_at=2 + src_loc_at, **kwargs)
-
- @classmethod
- @deprecated("instead of `Signal.enum(...)`, use `Signal(...)`")
- def enum(cls, enum_type, *, src_loc_at=0, **kwargs):
- if not issubclass(enum_type, Enum):
- raise TypeError("Type {!r} is not an enumeration")
- return cls(enum_type, src_loc_at=2 + src_loc_at, **kwargs)
-
- @classmethod
- def like(cls, other, *, name=None, name_suffix=None, src_loc_at=0, **kwargs):
+ # Not a @classmethod because nmigen.compat requires it.
+ @staticmethod
+ def like(other, *, name=None, name_suffix=None, src_loc_at=0, **kwargs):
"""Create Signal based on another.
Parameters
new_name = other.name + str(name_suffix)
else:
new_name = tracer.get_var_name(depth=2 + src_loc_at, default="$like")
- kw = dict(shape=cls.cast(other).shape(), name=new_name)
- if isinstance(other, cls):
+ kw = dict(shape=Value.cast(other).shape(), name=new_name)
+ if isinstance(other, Signal):
kw.update(reset=other.reset, reset_less=other.reset_less,
attrs=other.attrs, decoder=other.decoder)
kw.update(kwargs)
- return cls(**kw, src_loc_at=1 + src_loc_at)
-
- # TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
- @property
- @deprecated("instead of `signal.nbits`, use `signal.width`")
- def nbits(self):
- return self.width
-
- @nbits.setter
- @deprecated("instead of `signal.nbits = x`, use `signal.width = x`")
- def nbits(self, value):
- self.width = value
+ return Signal(**kw, src_loc_at=1 + src_loc_at)
def shape(self):
return Shape(self.width, self.signed)
def __init__(self, *, src_loc_at=0):
self.src_loc = tracer.get_src_loc(1 + src_loc_at)
- # TODO(nmigen-0.2): remove this
- @classmethod
- @deprecated("instead of `Statement.wrap`, use `Statement.cast`")
- def wrap(cls, obj):
- return cls.cast(obj)
-
@staticmethod
def cast(obj):
if isinstance(obj, Iterable):
self._hash = hash((self.value.operator,
tuple(ValueKey(o) for o in self.value.operands)))
elif isinstance(self.value, Slice):
- self._hash = hash((ValueKey(self.value.value), self.value.start, self.value.end))
+ self._hash = hash((ValueKey(self.value.value), self.value.start, self.value.stop))
elif isinstance(self.value, Part):
self._hash = hash((ValueKey(self.value.value), ValueKey(self.value.offset),
self.value.width, self.value.stride))
elif isinstance(self.value, Slice):
return (ValueKey(self.value.value) == ValueKey(other.value.value) and
self.value.start == other.value.start and
- self.value.end == other.value.end)
+ self.value.stop == other.value.stop)
elif isinstance(self.value, Part):
return (ValueKey(self.value.value) == ValueKey(other.value.value) and
ValueKey(self.value.offset) == ValueKey(other.value.offset) and
class SignalKey:
def __init__(self, signal):
self.signal = signal
- if type(signal) is Signal:
+ if isinstance(signal, Signal):
self._intern = (0, signal.duid)
elif type(signal) is ClockSignal:
self._intern = (1, signal.domain)
return obj
return Layout(obj, src_loc_at=1 + src_loc_at)
- # TODO(nmigen-0.2): remove this
- @classmethod
- @deprecated("instead of `Layout.wrap`, use `Layout.cast`")
- def wrap(cls, obj, *, src_loc_at=0):
- return cls.cast(obj, src_loc_at=1 + src_loc_at)
-
def __init__(self, fields, *, src_loc_at=0):
self.fields = OrderedDict()
for field in fields:
"DomainCollector", "DomainRenamer", "DomainLowerer",
"SampleDomainInjector", "SampleLowerer",
"SwitchCleaner", "LHSGroupAnalyzer", "LHSGroupFilter",
- "ResetInserter", "EnableInserter", "CEInserter"]
+ "ResetInserter", "EnableInserter"]
class ValueVisitor(metaclass=ABCMeta):
new_value = self.on_AnyConst(value)
elif type(value) is AnySeq:
new_value = self.on_AnySeq(value)
- elif type(value) is Signal:
+ elif isinstance(value, Signal):
+ # Uses `isinstance()` and not `type() is` because nmigen.compat requires it.
new_value = self.on_Signal(value)
elif isinstance(value, Record):
# Uses `isinstance()` and not `type() is` to allow inheriting from Record.
new_value = self.on_Slice(value)
elif type(value) is Part:
new_value = self.on_Part(value)
- elif isinstance(value, Cat):
- # Uses `isinstance()` and not `type() is` because nmigen.compat requires it.
+ elif type(value) is Cat:
new_value = self.on_Cat(value)
elif type(value) is Repl:
new_value = self.on_Repl(value)
en_port = Mux(self.controls[clk_port.domain], en_port, Const(0, len(en_port)))
new_fragment.named_ports["EN"] = en_port, en_dir
return new_fragment
-
-
-CEInserter = staticmethod(
- deprecated("instead of `CEInserter`, use `EnableInserter`")(EnableInserter))
__all__ = ["FFSynchronizer", "ResetSynchronizer"]
-# TODO(nmigen-0.2): remove this
-__all__ += ["MultiReg"]
def _check_stages(stages):
return m
-# TODO(nmigen-0.2): remove this
-MultiReg = deprecated("instead of `MultiReg`, use `FFSynchronizer`")(FFSynchronizer)
-
-
class ResetSynchronizer(Elaboratable):
"""Synchronize deassertion of a clock domain reset.
self.r_rdy = Signal() # readable; not empty
self.r_en = Signal()
- # TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
- @property
- @deprecated("instead of `fifo.din`, use `fifo.w_data`")
- def din(self):
- return self.w_data
-
- # TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
- @din.setter
- @deprecated("instead of `fifo.din = x`, use `fifo.w_data = x`")
- def din(self, w_data):
- self.w_data = w_data
-
- # TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
- @property
- @deprecated("instead of `fifo.writable`, use `fifo.w_rdy`")
- def writable(self):
- return self.w_rdy
-
- # TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
- @writable.setter
- @deprecated("instead of `fifo.writable = x`, use `fifo.w_rdy = x`")
- def writable(self, w_rdy):
- self.w_rdy = w_rdy
-
- # TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
- @property
- @deprecated("instead of `fifo.we`, use `fifo.w_en`")
- def we(self):
- return self.w_en
-
- # TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
- @we.setter
- @deprecated("instead of `fifo.we = x`, use `fifo.w_en = x`")
- def we(self, w_en):
- self.w_en = w_en
-
- # TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
- @property
- @deprecated("instead of `fifo.dout`, use `fifo.r_data`")
- def dout(self):
- return self.r_data
-
- # TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
- @dout.setter
- @deprecated("instead of `fifo.dout = x`, use `fifo.r_data = x`")
- def dout(self, r_data):
- self.r_data = r_data
-
- # TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
- @property
- @deprecated("instead of `fifo.readable`, use `fifo.r_rdy`")
- def readable(self):
- return self.r_rdy
-
- # TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
- @readable.setter
- @deprecated("instead of `fifo.readable = x`, use `fifo.r_rdy = x`")
- def readable(self, r_rdy):
- self.r_rdy = r_rdy
-
- # TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
- @property
- @deprecated("instead of `fifo.re`, use `fifo.r_en`")
- def re(self):
- return self.r_en
-
- # TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
- @re.setter
- @deprecated("instead of `fifo.re = x`, use `fifo.r_en = x`")
- def re(self, r_en):
- self.r_en = r_en
-
def _incr(signal, modulo):
if modulo == 2 ** len(signal):
self.assertEqual(s10.shape(), unsigned(0))
s11 = Signal(range(1))
self.assertEqual(s11.shape(), unsigned(1))
- # deprecated
- with warnings.catch_warnings():
- warnings.filterwarnings(action="ignore", category=DeprecationWarning)
- d6 = Signal(max=16)
- self.assertEqual(d6.shape(), unsigned(4))
- d7 = Signal(min=4, max=16)
- self.assertEqual(d7.shape(), unsigned(4))
- d8 = Signal(min=-4, max=16)
- self.assertEqual(d8.shape(), signed(5))
- d9 = Signal(min=-20, max=16)
- self.assertEqual(d9.shape(), signed(6))
- d10 = Signal(max=1)
- self.assertEqual(d10.shape(), unsigned(0))
def test_shape_wrong(self):
with self.assertRaises(TypeError,
msg="Width must be a non-negative integer, not -10"):
Signal(-10)
- def test_min_max_deprecated(self):
- with self.assertWarns(DeprecationWarning,
- msg="instead of `Signal(min=0, max=10)`, use `Signal(range(0, 10))`"):
- Signal(max=10)
- with warnings.catch_warnings():
- warnings.filterwarnings(action="ignore", category=DeprecationWarning)
- with self.assertRaises(ValueError,
- msg="Lower bound 10 should be less or equal to higher bound 4"):
- Signal(min=10, max=4)
- with self.assertRaises(ValueError,
- msg="Only one of bits/signedness or bounds may be specified"):
- Signal(2, min=10)
-
def test_name(self):
s1 = Signal()
self.assertEqual(s1.name, "s1")
rst_i = Const(0)
m = Module()
+
# Power-on-reset domain
m.domains += ClockDomain("por", reset_less=True, local=True)
delay = int(15e-6 * self.default_clk_frequency)
- timer = Signal(max=delay)
+ timer = Signal(range(delay))
ready = Signal()
m.d.comb += ClockSignal("por").eq(clk_i)
with m.If(timer == delay):
m.d.por += ready.eq(1)
with m.Else():
m.d.por += timer.eq(timer + 1)
+
# Primary domain
m.domains += ClockDomain("sync")
m.d.comb += ClockSignal("sync").eq(clk_i)
m.submodules.reset_sync = ResetSynchronizer(~ready | rst_i, domain="sync")
else:
m.d.comb += ResetSignal("sync").eq(~ready)
+
return m
def should_skip_port_component(self, port, attrs, component):