From 0ab215e5ed761a2bab07b9fe29eb8ad87eae0be9 Mon Sep 17 00:00:00 2001 From: whitequark Date: Tue, 2 Jul 2019 19:02:16 +0000 Subject: [PATCH] hdl.ast: recognize a Enum used as decoder and format it better. --- nmigen/hdl/ast.py | 17 ++++++++++++++--- nmigen/test/test_hdl_ast.py | 10 ++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) 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): -- 2.30.2