From: whitequark Date: Tue, 2 Jul 2019 19:02:16 +0000 (+0000) Subject: hdl.ast: recognize a Enum used as decoder and format it better. X-Git-Tag: locally_working~125 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=0ab215e5ed761a2bab07b9fe29eb8ad87eae0be9;p=nmigen.git hdl.ast: recognize a Enum used as decoder and format it better. --- diff --git a/nmigen/hdl/ast.py b/nmigen/hdl/ast.py index 54393fe..ef7d7c7 100644 --- a/nmigen/hdl/ast.py +++ b/nmigen/hdl/ast.py @@ -3,6 +3,7 @@ import builtins import traceback from collections import OrderedDict from collections.abc import Iterable, MutableMapping, MutableSet, MutableSequence +from enum import Enum from .. import tracer from ..tools import * @@ -575,9 +576,11 @@ class Signal(Value, DUID): defaults to 0) and ``max`` (exclusive, defaults to 2). attrs : dict Dictionary of synthesis attributes. - decoder : function + decoder : function or Enum A function converting integer signal values to human-readable strings (e.g. FSM state - names). + names). If an ``Enum`` subclass is passed, it is concisely decoded using format string + ``"{0.name:}/{0.value:}"``, or a number if the signal value is not a member of + the enumeration. Attributes ---------- @@ -627,7 +630,15 @@ class Signal(Value, DUID): self.reset_less = bool(reset_less) self.attrs = OrderedDict(() if attrs is None else attrs) - self.decoder = decoder + if isinstance(decoder, type) and issubclass(decoder, Enum): + def enum_decoder(value): + try: + return "{0.name:}/{0.value:}".format(decoder(value)) + except ValueError: + return str(value) + self.decoder = enum_decoder + else: + self.decoder = decoder @classmethod def like(cls, other, name=None, name_suffix=None, src_loc_at=0, **kwargs): diff --git a/nmigen/test/test_hdl_ast.py b/nmigen/test/test_hdl_ast.py index 9fbf637..6ef1193 100644 --- a/nmigen/test/test_hdl_ast.py +++ b/nmigen/test/test_hdl_ast.py @@ -1,3 +1,5 @@ +from enum import Enum + from ..hdl.ast import * from .tools import * @@ -486,6 +488,14 @@ class SignalTestCase(FHDLTestCase): s8 = Signal.like(s1, name_suffix="_ff") self.assertEqual(s8.name, "s1_ff") + def test_decoder(self): + class Color(Enum): + RED = 1 + BLUE = 2 + s = Signal(decoder=Color) + self.assertEqual(s.decoder(1), "RED/1") + self.assertEqual(s.decoder(3), "3") + class ClockSignalTestCase(FHDLTestCase): def test_domain(self):