From a71fd1d31b452a91b8e023b016ef40fde9bfe55f Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Thu, 27 Oct 2022 15:27:57 +0200 Subject: [PATCH] gen/common: Introduce LiteXModule class to simplify Modules creation and avoid common mistakes. LiteXModule can be used as a remplacement of Migen's Module and in this initial version: - Automatically inherit from AutoCSR (Forgeting to inherit from AutoCSR on a Module was a common mistake). - Simplify design creation with: - m.module_x = .. equivalent of Migen's m.submodules.module_x = .. - m.special_x = .. equivalent of Migen's m.specials.special_x = .. - m.cd_x = .. equivalent of Migen's m.clock_domains.cd_x = .. - m += module_x equivalent of Migen's m.submodules += module_x. - m += special_x equivalent of Migen's m.specials += special_x. - m += cd_x equivalent of Migen's m.clock_domains += cd_x. -> Forgeting to attach a correctly a Sub-module/Special was a very common mistake and having to use m.submodules., m.specials., m.clock_domains. was not natural. --- litex/gen/common.py | 46 +++++++++++++++++++++++++++++++++++- litex/soc/integration/soc.py | 3 ++- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/litex/gen/common.py b/litex/gen/common.py index e75b42eb8..ac14a4020 100644 --- a/litex/gen/common.py +++ b/litex/gen/common.py @@ -1,11 +1,16 @@ # # This file is part of LiteX. # -# This file is Copyright (c) 2018 Florent Kermarrec +# This file is Copyright (c) 2018-2022 Florent Kermarrec # SPDX-License-Identifier: BSD-2-Clause from migen import * +from migen.fhdl.module import _ModuleProxy +from migen.fhdl.specials import Special +from litex.soc.interconnect.csr import AutoCSR + +# Bit/Bytes Reversing ------------------------------------------------------------------------------ def reverse_bits(s): return s[::-1] @@ -15,3 +20,42 @@ def reverse_bytes(s): n = (len(s) + 7)//8 return Cat(*[s[i*8:min((i + 1)*8, len(s))] for i in reversed(range(n))]) + +# LiteX Module ------------------------------------------------------------------------------------- + +class LiteXModule(Module, AutoCSR): + def __setattr__(m, name, value): + # Migen: + if name in ["comb", "sync", "specials", "submodules", "clock_domains"]: + if not isinstance(value, _ModuleProxy): + raise AttributeError("Attempted to assign special Module property - use += instead") + # LiteX fix-up: Automatically collect specials/submodules/clock_domains: + # - m.module_x = .. equivalent of Migen's m.submodules.module_x = .. + elif isinstance(value, Module) and ((name, value) not in m._submodules): + setattr(m.submodules, name, value) + # - m.special_x = .. equivalent of Migen's m.specials.special_x = .. + elif isinstance(value, Special) and (value not in m._fragment.specials): + setattr(m.specials, name, value) + # - m.cd_x = .. equivalent of Migen's m.clock_domains.cd_x = .. + elif isinstance(value, ClockDomain) and (value not in m._fragment.clock_domains): + setattr(m.clock_domains, name, value) + # Else use default __setattr__. + else: + object.__setattr__(m, name, value) + + # LiteX fix-up: Automatically collect specials/submodules/clock_domains: + def __iadd__(m, other): + # - m += module_x equivalent of Migen's m.submodules += module_x. + if isinstance(other, Module): + print(other) + m.submodules += other + # - m += special_x equivalent of Migen's m.specials += special_x. + elif isinstnace(other, Special): + m.specials += other + # - m += cd_x equivalent of Migen's m.clock_domains += cd_x. + elif isinstance(other, ClockDomain): + m.clock_domains += other + # Else use default __iadd__. + else: + object.__iadd__(m, other) + return m diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index 8ca3d229c..fe8b5e4b0 100755 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -15,6 +15,7 @@ import datetime from math import log2, ceil from migen import * +from litex.gen import LiteXModule from litex.soc.cores import cpu @@ -766,7 +767,7 @@ class SoCController(Module, AutoCSR): # SoC ---------------------------------------------------------------------------------------------- -class SoC(Module): +class SoC(LiteXModule): mem_map = {} def __init__(self, platform, sys_clk_freq, bus_standard = "wishbone",