From: Florent Kermarrec Date: Wed, 11 Nov 2015 11:10:55 +0000 (+0100) Subject: avoid forking migen, we will add custom modules in litex/gen but will use upstream... X-Git-Tag: 24jan2021_ls180~2088 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=619cd8e69548c0c0f4989d27b05196fe711d1742;p=litex.git avoid forking migen, we will add custom modules in litex/gen but will use upstream migen for common modules --- diff --git a/README b/README index b1128061..3f792aab 100644 --- a/README +++ b/README @@ -2,29 +2,32 @@ / / (_) /____ | |/_/ / /__/ / __/ -_)> < /____/_/\__/\__/_/|_| + Migen inside Build your hardware, easily! Copyright 2015 Enjoy-Digital [> Intro --------- -LiteX is an alternative (fork) to Migen/MiSoC maintained and used by Enjoy-Digital -to build our cores, integrate them in complete SoC and load/flash them to the -hardware. +LiteX is an alternative to MiSoC maintained and used by Enjoy-Digital to build +our cores, integrate them in complete SoC and load/flash them to the hardware. -The structure of LiteX is kept close to Migen/MiSoC to ease collaboration -between projects. +The structure of LiteX is kept close to MiSoC to ease collaboration between +projects. + +LiteX is based on Migen. [> License ----------- LiteX is copyright (c) 2015 Enjoy-Digital under BSD Lisense. -Since it is based on MiSoC/Migen, please also refer to LICENSE files in soc/gen -directories or git history to get correct copyrights. +Since it is based on MiSoC, please also refer to LICENSE file in soc directory +or git history to get correct copyrights. [> Sub-packages ------------ +---------------- gen: - Provides tools and simple modules to generate HDL. + Provides specific or experimentatl modules to generate HDL that are not integrated + in Migen. build: Provides tools to build FPGA bitstreams (interface to vendor toolchains) and to diff --git a/litex/boards/targets/de0nano.py b/litex/boards/targets/de0nano.py index 790c69fe..2e8710b3 100644 --- a/litex/boards/targets/de0nano.py +++ b/litex/boards/targets/de0nano.py @@ -2,7 +2,7 @@ import argparse -from litex.gen import * +from migen import * from litex.boards.platforms import de0nano from litex.soc.cores.sdram.settings import IS42S16160 diff --git a/litex/boards/targets/kc705.py b/litex/boards/targets/kc705.py index b63a9fc8..3d2af43c 100644 --- a/litex/boards/targets/kc705.py +++ b/litex/boards/targets/kc705.py @@ -2,8 +2,8 @@ import argparse -from litex.gen import * -from litex.gen.genlib.resetsync import AsyncResetSynchronizer +from migen import * +from migen.genlib.resetsync import AsyncResetSynchronizer from litex.boards.platforms import kc705 from litex.soc.cores.sdram.settings import MT8JTF12864 diff --git a/litex/boards/targets/minispartan6.py b/litex/boards/targets/minispartan6.py index 7fead695..b9f1f4e2 100644 --- a/litex/boards/targets/minispartan6.py +++ b/litex/boards/targets/minispartan6.py @@ -3,8 +3,8 @@ import argparse from fractions import Fraction -from litex.gen import * -from litex.gen.genlib.resetsync import AsyncResetSynchronizer +from migen import * +from migen.genlib.resetsync import AsyncResetSynchronizer from litex.boards.platforms import minispartan6 from litex.soc.cores.sdram.settings import AS4C16M16 diff --git a/litex/boards/targets/papilio_pro.py b/litex/boards/targets/papilio_pro.py index 9e7a86e1..011232ec 100644 --- a/litex/boards/targets/papilio_pro.py +++ b/litex/boards/targets/papilio_pro.py @@ -3,8 +3,8 @@ import argparse from fractions import Fraction -from litex.gen import * -from litex.gen.genlib.resetsync import AsyncResetSynchronizer +from migen import * +from migen.genlib.resetsync import AsyncResetSynchronizer from litex.boards.platforms import papilio_pro from litex.soc.cores.sdram.settings import MT48LC4M16 diff --git a/litex/boards/targets/pipistrello.py b/litex/boards/targets/pipistrello.py index 6ec6fc4b..748350e1 100644 --- a/litex/boards/targets/pipistrello.py +++ b/litex/boards/targets/pipistrello.py @@ -3,8 +3,8 @@ import argparse from fractions import Fraction -from litex.gen import * -from litex.gen.genlib.resetsync import AsyncResetSynchronizer +from migen import * +from migen.genlib.resetsync import AsyncResetSynchronizer from litex.boards.platforms import pipistrello from litex.soc.cores.sdram_settings import MT46H32M16 diff --git a/litex/boards/targets/sim.py b/litex/boards/targets/sim.py index 0990ac6a..d1d35131 100644 --- a/litex/boards/targets/sim.py +++ b/litex/boards/targets/sim.py @@ -3,9 +3,9 @@ import argparse import importlib -from litex.gen import * +from migen import * from litex.boards.platforms import sim -from litex.gen.genlib.io import CRG +from migen.genlib.io import CRG from litex.soc.integration.soc_sdram import * from litex.soc.integration.builder import * diff --git a/litex/boards/targets/simple.py b/litex/boards/targets/simple.py index 8ac27505..d1aed7bb 100644 --- a/litex/boards/targets/simple.py +++ b/litex/boards/targets/simple.py @@ -3,8 +3,8 @@ import argparse import importlib -from litex.gen import * -from litex.gen.genlib.io import CRG +from migen import * +from migen.genlib.io import CRG from litex.soc.integration.soc_core import * from litex.soc.integration.builder import * diff --git a/litex/build/altera/common.py b/litex/build/altera/common.py index 07b6ef76..fafb4983 100644 --- a/litex/build/altera/common.py +++ b/litex/build/altera/common.py @@ -1,6 +1,6 @@ -from litex.gen.fhdl.module import Module -from litex.gen.fhdl.specials import Instance -from litex.gen.genlib.io import DifferentialInput, DifferentialOutput +from migen.fhdl.module import Module +from migen.fhdl.specials import Instance +from migen.genlib.io import DifferentialInput, DifferentialOutput class AlteraDifferentialInputImpl(Module): diff --git a/litex/build/altera/quartus.py b/litex/build/altera/quartus.py index d5eda886..011bd805 100644 --- a/litex/build/altera/quartus.py +++ b/litex/build/altera/quartus.py @@ -4,7 +4,7 @@ import os import subprocess -from litex.gen.fhdl.structure import _Fragment +from migen.fhdl.structure import _Fragment from litex.build.generic_platform import Pins, IOStandard, Misc from litex.build import tools diff --git a/litex/build/generic_platform.py b/litex/build/generic_platform.py index f6320acc..0ef51d1e 100644 --- a/litex/build/generic_platform.py +++ b/litex/build/generic_platform.py @@ -1,9 +1,9 @@ import os -from litex.gen.fhdl.structure import Signal -from litex.gen.genlib.record import Record -from litex.gen.genlib.io import CRG -from litex.gen.fhdl import verilog, edif +from migen.fhdl.structure import Signal +from migen.genlib.record import Record +from migen.genlib.io import CRG +from migen.fhdl import verilog, edif from litex.build import tools diff --git a/litex/build/lattice/common.py b/litex/build/lattice/common.py index 52cf28d9..c25e8b90 100644 --- a/litex/build/lattice/common.py +++ b/litex/build/lattice/common.py @@ -1,7 +1,7 @@ -from litex.gen.fhdl.module import Module -from litex.gen.fhdl.specials import Instance -from litex.gen.genlib.io import * -from litex.gen.genlib.resetsync import AsyncResetSynchronizer +from migen.fhdl.module import Module +from migen.fhdl.specials import Instance +from migen.genlib.io import * +from migen.genlib.resetsync import AsyncResetSynchronizer class LatticeAsyncResetSynchronizerImpl(Module): diff --git a/litex/build/lattice/diamond.py b/litex/build/lattice/diamond.py index cd169fdb..ac967654 100644 --- a/litex/build/lattice/diamond.py +++ b/litex/build/lattice/diamond.py @@ -6,7 +6,7 @@ import sys import subprocess import shutil -from litex.gen.fhdl.structure import _Fragment +from migen.fhdl.structure import _Fragment from litex.build.generic_platform import * from litex.build import tools diff --git a/litex/build/sim/verilator.py b/litex/build/sim/verilator.py index fb8e8710..ab54984f 100644 --- a/litex/build/sim/verilator.py +++ b/litex/build/sim/verilator.py @@ -4,7 +4,7 @@ import os import subprocess -from litex.gen.fhdl.structure import _Fragment +from migen.fhdl.structure import _Fragment from litex.build import tools from litex.build.generic_platform import * diff --git a/litex/build/xilinx/common.py b/litex/build/xilinx/common.py index 69c15384..3b50b667 100644 --- a/litex/build/xilinx/common.py +++ b/litex/build/xilinx/common.py @@ -2,13 +2,13 @@ import os import sys from distutils.version import StrictVersion -from litex.gen.fhdl.structure import * -from litex.gen.fhdl.specials import Instance -from litex.gen.fhdl.module import Module -from litex.gen.fhdl.specials import SynthesisDirective -from litex.gen.genlib.cdc import * -from litex.gen.genlib.resetsync import AsyncResetSynchronizer -from litex.gen.genlib.io import * +from migen.fhdl.structure import * +from migen.fhdl.specials import Instance +from migen.fhdl.module import Module +from migen.fhdl.specials import SynthesisDirective +from migen.genlib.cdc import * +from migen.genlib.resetsync import AsyncResetSynchronizer +from migen.genlib.io import * from litex.build import tools diff --git a/litex/build/xilinx/ise.py b/litex/build/xilinx/ise.py index 8efa5d7a..e8698e5e 100644 --- a/litex/build/xilinx/ise.py +++ b/litex/build/xilinx/ise.py @@ -2,7 +2,7 @@ import os import subprocess import sys -from litex.gen.fhdl.structure import _Fragment +from migen.fhdl.structure import _Fragment from litex.build.generic_platform import * from litex.build import tools from litex.build.xilinx import common diff --git a/litex/build/xilinx/vivado.py b/litex/build/xilinx/vivado.py index 18474d3d..3900fd86 100644 --- a/litex/build/xilinx/vivado.py +++ b/litex/build/xilinx/vivado.py @@ -5,7 +5,7 @@ import os import subprocess import sys -from litex.gen.fhdl.structure import _Fragment +from migen.fhdl.structure import _Fragment from litex.build.generic_platform import * from litex.build import tools from litex.build.xilinx import common diff --git a/litex/gen/MIGEN_LICENSE b/litex/gen/MIGEN_LICENSE deleted file mode 100644 index 4f290601..00000000 --- a/litex/gen/MIGEN_LICENSE +++ /dev/null @@ -1,31 +0,0 @@ -Unless otherwise noted, Migen is copyright (C) 2011-2013 Sebastien Bourdeauducq. -The simulation extension (as mentioned in the comments at the beginning of the -corresponding source files) is copyright (C) 2012 Vermeer Manufacturing Co. All -rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -Other authors retain ownership of their contributions. If a submission can -reasonably be considered independently copyrightable, it's yours and we -encourage you to claim it with appropriate copyright notices. This submission -then falls under the "otherwise noted" category. All submissions are strongly -encouraged to use the two-clause BSD license reproduced above. diff --git a/litex/gen/__init__.py b/litex/gen/__init__.py index 264a79e2..e69de29b 100644 --- a/litex/gen/__init__.py +++ b/litex/gen/__init__.py @@ -1,10 +0,0 @@ -from litex.gen.fhdl.structure import * -from litex.gen.fhdl.module import * -from litex.gen.fhdl.specials import * -from litex.gen.fhdl.bitcontainer import * -from litex.gen.fhdl.decorators import * - -from litex.gen.sim import * - -from litex.gen.genlib.record import * -from litex.gen.genlib.fsm import * diff --git a/litex/gen/fhdl/__init__.py b/litex/gen/fhdl/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/litex/gen/fhdl/bitcontainer.py b/litex/gen/fhdl/bitcontainer.py deleted file mode 100644 index 11a3ede7..00000000 --- a/litex/gen/fhdl/bitcontainer.py +++ /dev/null @@ -1,121 +0,0 @@ -from litex.gen.fhdl import structure as f - - -__all__ = ["log2_int", "bits_for", "value_bits_sign"] - - -def log2_int(n, need_pow2=True): - l = 1 - r = 0 - while l < n: - l *= 2 - r += 1 - if need_pow2 and l != n: - raise ValueError("Not a power of 2") - return r - - -def bits_for(n, require_sign_bit=False): - if n > 0: - r = log2_int(n + 1, False) - else: - require_sign_bit = True - r = log2_int(-n, False) - if require_sign_bit: - r += 1 - return r - - -def value_bits_sign(v): - """Bit length and signedness of a value. - - Parameters - ---------- - v : Value - - Returns - ------- - int, bool - Number of bits required to store `v` or available in `v`, followed by - whether `v` has a sign bit (included in the bit count). - - Examples - -------- - >>> value_bits_sign(f.Signal(8)) - 8, False - >>> value_bits_sign(C(0xaa)) - 8, False - """ - if isinstance(v, (f.Constant, f.Signal)): - return v.nbits, v.signed - elif isinstance(v, (f.ClockSignal, f.ResetSignal)): - return 1, False - elif isinstance(v, f._Operator): - obs = list(map(value_bits_sign, v.operands)) - if v.op == "+" or v.op == "-": - if not obs[0][1] and not obs[1][1]: - # both operands unsigned - return max(obs[0][0], obs[1][0]) + 1, False - elif obs[0][1] and obs[1][1]: - # both operands signed - return max(obs[0][0], obs[1][0]) + 1, True - elif not obs[0][1] and obs[1][1]: - # first operand unsigned (add sign bit), second operand signed - return max(obs[0][0] + 1, obs[1][0]) + 1, True - else: - # first signed, second operand unsigned (add sign bit) - return max(obs[0][0], obs[1][0] + 1) + 1, True - elif v.op == "*": - if not obs[0][1] and not obs[1][1]: - # both operands unsigned - return obs[0][0] + obs[1][0], False - elif obs[0][1] and obs[1][1]: - # both operands signed - return obs[0][0] + obs[1][0] - 1, True - else: - # one operand signed, the other unsigned (add sign bit) - return obs[0][0] + obs[1][0] + 1 - 1, True - elif v.op == "<<<": - if obs[1][1]: - extra = 2**(obs[1][0] - 1) - 1 - else: - extra = 2**obs[1][0] - 1 - return obs[0][0] + extra, obs[0][1] - elif v.op == ">>>": - if obs[1][1]: - extra = 2**(obs[1][0] - 1) - else: - extra = 0 - return obs[0][0] + extra, obs[0][1] - elif v.op == "&" or v.op == "^" or v.op == "|": - if not obs[0][1] and not obs[1][1]: - # both operands unsigned - return max(obs[0][0], obs[1][0]), False - elif obs[0][1] and obs[1][1]: - # both operands signed - return max(obs[0][0], obs[1][0]), True - elif not obs[0][1] and obs[1][1]: - # first operand unsigned (add sign bit), second operand signed - return max(obs[0][0] + 1, obs[1][0]), True - else: - # first signed, second operand unsigned (add sign bit) - return max(obs[0][0], obs[1][0] + 1), True - elif v.op == "<" or v.op == "<=" or v.op == "==" or v.op == "!=" \ - or v.op == ">" or v.op == ">=": - return 1, False - elif v.op == "~": - return obs[0] - else: - raise TypeError - elif isinstance(v, f._Slice): - return v.stop - v.start, value_bits_sign(v.value)[1] - elif isinstance(v, f.Cat): - return sum(value_bits_sign(sv)[0] for sv in v.l), False - elif isinstance(v, f.Replicate): - return (value_bits_sign(v.v)[0])*v.n, False - elif isinstance(v, f._ArrayProxy): - bsc = list(map(value_bits_sign, v.choices)) - return max(bs[0] for bs in bsc), any(bs[1] for bs in bsc) - else: - raise TypeError("Can not calculate bit length of {} {}".format( - type(v), v)) diff --git a/litex/gen/fhdl/conv_output.py b/litex/gen/fhdl/conv_output.py deleted file mode 100644 index 793fad20..00000000 --- a/litex/gen/fhdl/conv_output.py +++ /dev/null @@ -1,35 +0,0 @@ -from operator import itemgetter - - -class ConvOutput: - def __init__(self): - self.main_source = "" - self.data_files = dict() - - def set_main_source(self, src): - self.main_source = src - - def add_data_file(self, filename_base, content): - filename = filename_base - i = 1 - while filename in self.data_files: - parts = filename_base.split(".", maxsplit=1) - parts[0] += "_" + str(i) - filename = ".".join(parts) - i += 1 - self.data_files[filename] = content - return filename - - def __str__(self): - r = self.main_source + "\n" - for filename, content in sorted(self.data_files.items(), - key=itemgetter(0)): - r += filename + ":\n" + content - return r - - def write(self, main_filename): - with open(main_filename, "w") as f: - f.write(self.main_source) - for filename, content in self.data_files.items(): - with open(filename, "w") as f: - f.write(content) diff --git a/litex/gen/fhdl/decorators.py b/litex/gen/fhdl/decorators.py deleted file mode 100644 index 59444eaf..00000000 --- a/litex/gen/fhdl/decorators.py +++ /dev/null @@ -1,107 +0,0 @@ -from litex.gen.fhdl.structure import * -from litex.gen.fhdl.module import Module -from litex.gen.fhdl.tools import insert_reset, rename_clock_domain - - -__all__ = ["CEInserter", "ResetInserter", "ClockDomainsRenamer", - "ModuleTransformer"] - - -class ModuleTransformer: - # overload this in derived classes - def transform_instance(self, i): - pass - - # overload this in derived classes - def transform_fragment(self, i, f): - pass - - def wrap_class(self, victim): - class Wrapped(victim): - def __init__(i, *args, **kwargs): - victim.__init__(i, *args, **kwargs) - self.transform_instance(i) - - def get_fragment(i): - f = victim.get_fragment(i) - self.transform_fragment(i, f) - return f - - Wrapped.__name__ = victim.__name__ - # "{}_{}".format(self.__class__.__name__, victim.__name__) - return Wrapped - - def wrap_instance(self, victim): - self.transform_instance(victim) - orig_get_fragment = victim.get_fragment - - def get_fragment(): - f = orig_get_fragment() - self.transform_fragment(victim, f) - return f - - victim.get_fragment = get_fragment - return victim - - def __call__(self, victim): - if isinstance(victim, Module): - return self.wrap_instance(victim) - else: - return self.wrap_class(victim) - - -class ControlInserter(ModuleTransformer): - control_name = None # override this - - def __init__(self, clock_domains=None): - self.clock_domains = clock_domains - - def transform_instance(self, i): - if self.clock_domains is None: - ctl = Signal(name=self.control_name) - assert not hasattr(i, self.control_name) - setattr(i, self.control_name, ctl) - else: - for cd in self.clock_domains: - name = self.control_name + "_" + cd - ctl = Signal(name=name) - assert not hasattr(i, name) - setattr(i, name, ctl) - - def transform_fragment(self, i, f): - if self.clock_domains is None: - if len(f.sync) != 1: - raise ValueError("Control signal clock domains must be specified when module has more than one domain") - cdn = list(f.sync.keys())[0] - to_insert = [(getattr(i, self.control_name), cdn)] - else: - to_insert = [(getattr(i, self.control_name + "_" + cdn), cdn) - for cdn in self.clock_domains] - self.transform_fragment_insert(i, f, to_insert) - - -class CEInserter(ControlInserter): - control_name = "ce" - - def transform_fragment_insert(self, i, f, to_insert): - for ce, cdn in to_insert: - f.sync[cdn] = [If(ce, *f.sync[cdn])] - - -class ResetInserter(ControlInserter): - control_name = "reset" - - def transform_fragment_insert(self, i, f, to_insert): - for reset, cdn in to_insert: - f.sync[cdn] = insert_reset(reset, f.sync[cdn]) - - -class ClockDomainsRenamer(ModuleTransformer): - def __init__(self, cd_remapping): - if isinstance(cd_remapping, str): - cd_remapping = {"sys": cd_remapping} - self.cd_remapping = cd_remapping - - def transform_fragment(self, i, f): - for old, new in self.cd_remapping.items(): - rename_clock_domain(f, old, new) diff --git a/litex/gen/fhdl/edif.py b/litex/gen/fhdl/edif.py deleted file mode 100644 index f68c99bd..00000000 --- a/litex/gen/fhdl/edif.py +++ /dev/null @@ -1,213 +0,0 @@ -from collections import OrderedDict, namedtuple - -from litex.gen.fhdl.structure import * -from litex.gen.fhdl.namer import build_namespace -from litex.gen.fhdl.tools import list_special_ios -from litex.gen.fhdl.structure import _Fragment -from litex.gen.fhdl.conv_output import ConvOutput - - -_Port = namedtuple("_Port", "name direction") -_Cell = namedtuple("_Cell", "name ports") -_Property = namedtuple("_Property", "name value") -_Instance = namedtuple("_Instance", "name cell properties") -_NetBranch = namedtuple("_NetBranch", "portname instancename") - - -def _write_cells(cells): - r = "" - for cell in cells: - r += """ - (cell {0.name} - (cellType GENERIC) - (view view_1 - (viewType NETLIST) - (interface""".format(cell) - for port in cell.ports: - r += """ - (port {0.name} (direction {0.direction}))""".format(port) - r += """ - ) - ) - )""" - return r - - -def _write_io(ios): - r = "" - for s in ios: - r += """ - (port {0.name} (direction {0.direction}))""".format(s) - return r - - -def _write_instantiations(instances, cell_library): - instantiations = "" - for instance in instances: - instantiations += """ - (instance {0.name} - (viewRef view_1 (cellRef {0.cell} (libraryRef {1})))""".format(instance, cell_library) - for prop in instance.properties: - instantiations += """ - (property {0} (string "{1}"))""".format(prop.name, prop.value) - instantiations += """ - )""" - return instantiations - - -def _write_connections(connections): - r = "" - for netname, branches in connections.items(): - r += """ - (net {0} - (joined""".format(netname) - for branch in branches: - r += """ - (portRef {0}{1})""".format(branch.portname, "" if branch.instancename == "" else " (instanceRef {})".format(branch.instancename)) - r += """ - ) - )""" - return r - - -def _write_edif(cells, ios, instances, connections, cell_library, design_name, part, vendor): - r = """(edif {0} - (edifVersion 2 0 0) - (edifLevel 0) - (keywordMap (keywordLevel 0)) - (external {1} - (edifLevel 0) - (technology (numberDefinition))""".format(design_name, cell_library) - r += _write_cells(cells) - r += """ - ) - (library {0}_lib - (edifLevel 0) - (technology (numberDefinition)) - (cell {0} - (cellType GENERIC) - (view view_1 - (viewType NETLIST) - (interface""".format(design_name) - r += _write_io(ios) - r += """ - (designator "{0}") - ) - (contents""".format(part) - r += _write_instantiations(instances, cell_library) - r += _write_connections(connections) - r += """ - ) - ) - ) - ) - (design {0} - (cellRef {0} (libraryRef {0}_lib)) - (property PART (string "{1}") (owner "{2}")) - ) -)""".format(design_name, part, vendor) - - return r - - -def _generate_cells(f): - cell_dict = OrderedDict() - for special in f.specials: - if isinstance(special, Instance): - port_list = [] - for port in special.items: - if isinstance(port, Instance.Input): - port_list.append(_Port(port.name, "INPUT")) - elif isinstance(port, Instance.Output): - port_list.append(_Port(port.name, "OUTPUT")) - elif isinstance(port, Instance.InOut): - port_list.append(_Port(port.name, "INOUT")) - elif isinstance(port, Instance.Parameter): - pass - else: - raise NotImplementedError("Unsupported instance item") - if special.of in cell_dict: - if set(port_list) != set(cell_dict[special.of]): - raise ValueError("All instances must have the same ports for EDIF conversion") - else: - cell_dict[special.of] = port_list - else: - raise ValueError("EDIF conversion can only handle synthesized fragments") - return [_Cell(k, v) for k, v in cell_dict.items()] - - -def _generate_instances(f, ns): - instances = [] - for special in f.specials: - if isinstance(special, Instance): - props = [] - for prop in special.items: - if isinstance(prop, Instance.Input): - pass - elif isinstance(prop, Instance.Output): - pass - elif isinstance(prop, Instance.InOut): - pass - elif isinstance(prop, Instance.Parameter): - props.append(_Property(name=prop.name, value=prop.value)) - else: - raise NotImplementedError("Unsupported instance item") - instances.append(_Instance(name=ns.get_name(special), cell=special.of, properties=props)) - else: - raise ValueError("EDIF conversion can only handle synthesized fragments") - return instances - - -def _generate_ios(f, ios, ns): - outs = list_special_ios(f, False, True, False) - inouts = list_special_ios(f, False, False, True) - r = [] - for io in ios: - direction = "OUTPUT" if io in outs else "INOUT" if io in inouts else "INPUT" - r.append(_Port(name=ns.get_name(io), direction=direction)) - return r - - -def _generate_connections(f, ios, ns): - r = OrderedDict() - for special in f.specials: - if isinstance(special, Instance): - instname = ns.get_name(special) - for port in special.items: - if isinstance(port, Instance._IO): - s = ns.get_name(port.expr) - if s not in r: - r[s] = [] - r[s].append(_NetBranch(portname=port.name, instancename=instname)) - elif isinstance(port, Instance.Parameter): - pass - else: - raise NotImplementedError("Unsupported instance item") - else: - raise ValueError("EDIF conversion can only handle synthesized fragments") - for s in ios: - io = ns.get_name(s) - if io not in r: - r[io] = [] - r[io].append(_NetBranch(portname=io, instancename="")) - return r - - -def convert(f, ios, cell_library, vendor, device, name="top"): - if not isinstance(f, _Fragment): - f = f.get_fragment() - if f.comb != [] or f.sync != {}: - raise ValueError("EDIF conversion can only handle synthesized fragments") - if ios is None: - ios = set() - cells = _generate_cells(f) - ns = build_namespace(list_special_ios(f, True, True, True)) - instances = _generate_instances(f, ns) - inouts = _generate_ios(f, ios, ns) - connections = _generate_connections(f, ios, ns) - src = _write_edif(cells, inouts, instances, connections, cell_library, name, device, vendor) - - r = ConvOutput() - r.set_main_source(src) - r.ns = ns - return r diff --git a/litex/gen/fhdl/module.py b/litex/gen/fhdl/module.py deleted file mode 100644 index a8607514..00000000 --- a/litex/gen/fhdl/module.py +++ /dev/null @@ -1,185 +0,0 @@ -import collections -from itertools import combinations - -from litex.gen.util.misc import flat_iteration -from litex.gen.fhdl.structure import * -from litex.gen.fhdl.structure import _Fragment -from litex.gen.fhdl.tools import rename_clock_domain - - -__all__ = ["Module", "FinalizeError"] - - -class FinalizeError(Exception): - pass - - -def _flat_list(e): - if isinstance(e, collections.Iterable): - return flat_iteration(e) - else: - return [e] - - -class _ModuleProxy: - def __init__(self, fm): - object.__setattr__(self, "_fm", fm) - - -class _ModuleComb(_ModuleProxy): - def __iadd__(self, other): - self._fm._fragment.comb += _flat_list(other) - return self - - -def _cd_append(d, key, statements): - try: - l = d[key] - except KeyError: - l = [] - d[key] = l - l += _flat_list(statements) - - -class _ModuleSyncCD: - def __init__(self, fm, cd): - self._fm = fm - self._cd = cd - - def __iadd__(self, other): - _cd_append(self._fm._fragment.sync, self._cd, other) - return self - - -class _ModuleSync(_ModuleProxy): - def __iadd__(self, other): - _cd_append(self._fm._fragment.sync, "sys", other) - return self - - def __getattr__(self, name): - return _ModuleSyncCD(self._fm, name) - - def __setattr__(self, name, value): - if not isinstance(value, _ModuleSyncCD): - raise AttributeError("Attempted to assign sync property - use += instead") - - -# _ModuleForwardAttr enables user classes to do e.g.: -# self.subm.foobar = SomeModule() -# and then access the submodule with self.foobar. -class _ModuleForwardAttr: - def __setattr__(self, name, value): - self.__iadd__(value) - setattr(self._fm, name, value) - - -class _ModuleSpecials(_ModuleProxy, _ModuleForwardAttr): - def __iadd__(self, other): - self._fm._fragment.specials |= set(_flat_list(other)) - return self - - -class _ModuleSubmodules(_ModuleProxy): - def __setattr__(self, name, value): - self._fm._submodules += [(name, e) for e in _flat_list(value)] - setattr(self._fm, name, value) - - def __iadd__(self, other): - self._fm._submodules += [(None, e) for e in _flat_list(other)] - return self - - -class _ModuleClockDomains(_ModuleProxy, _ModuleForwardAttr): - def __iadd__(self, other): - self._fm._fragment.clock_domains += _flat_list(other) - return self - - -class Module: - def get_fragment(self): - assert(not self.get_fragment_called) - self.get_fragment_called = True - self.finalize() - return self._fragment - - def __getattr__(self, name): - if name == "comb": - return _ModuleComb(self) - elif name == "sync": - return _ModuleSync(self) - elif name == "specials": - return _ModuleSpecials(self) - elif name == "submodules": - return _ModuleSubmodules(self) - elif name == "clock_domains": - return _ModuleClockDomains(self) - - # hack to have initialized regular attributes without using __init__ - # (which would require derived classes to call it) - elif name == "finalized": - self.finalized = False - return self.finalized - elif name == "_fragment": - self._fragment = _Fragment() - return self._fragment - elif name == "_submodules": - self._submodules = [] - return self._submodules - elif name == "_clock_domains": - self._clock_domains = [] - return self._clock_domains - elif name == "get_fragment_called": - self.get_fragment_called = False - return self.get_fragment_called - - else: - raise AttributeError("'"+self.__class__.__name__+"' object has no attribute '"+name+"'") - - def __setattr__(self, name, value): - if name in ["comb", "sync", "specials", "submodules", "clock_domains"]: - if not isinstance(value, _ModuleProxy): - raise AttributeError("Attempted to assign special Module property - use += instead") - else: - object.__setattr__(self, name, value) - - def _collect_submodules(self): - r = [] - for name, submodule in self._submodules: - if not submodule.get_fragment_called: - r.append((name, submodule.get_fragment())) - return r - - def finalize(self, *args, **kwargs): - if not self.finalized: - self.finalized = True - # finalize existing submodules before finalizing us - subfragments = self._collect_submodules() - self.do_finalize(*args, **kwargs) - # finalize submodules created by do_finalize - subfragments += self._collect_submodules() - # resolve clock domain name conflicts - needs_renaming = set() - for (mod_name1, f1), (mod_name2, f2) in combinations(subfragments, 2): - f1_names = set(cd.name for cd in f1.clock_domains) - f2_names = set(cd.name for cd in f2.clock_domains) - common_names = f1_names & f2_names - if common_names: - if mod_name1 is None or mod_name2 is None: - raise ValueError("Multiple submodules with local clock domains cannot be anonymous") - if mod_name1 == mod_name2: - raise ValueError("Multiple submodules with local clock domains cannot have the same name") - needs_renaming |= common_names - for mod_name, f in subfragments: - for cd in f.clock_domains: - if cd.name in needs_renaming: - rename_clock_domain(f, cd.name, mod_name + "_" + cd.name) - # sum subfragments - for mod_name, f in subfragments: - self._fragment += f - - def do_finalize(self): - pass - - def do_exit(self, *args, **kwargs): - for name, submodule in self._submodules: - submodule.do_exit(*args, **kwargs) diff --git a/litex/gen/fhdl/namer.py b/litex/gen/fhdl/namer.py deleted file mode 100644 index 5e8ecdd3..00000000 --- a/litex/gen/fhdl/namer.py +++ /dev/null @@ -1,258 +0,0 @@ -from collections import OrderedDict -from itertools import combinations - -from litex.gen.fhdl.structure import * - - -class _Node: - def __init__(self): - self.signal_count = 0 - self.numbers = set() - self.use_name = False - self.use_number = False - self.children = OrderedDict() - - -def _display_tree(filename, tree): - from litex.gen.util.treeviz import RenderNode - - def _to_render_node(name, node): - children = [_to_render_node(k, v) for k, v in node.children.items()] - if node.use_name: - if node.use_number: - color = (0.5, 0.9, 0.8) - else: - color = (0.8, 0.5, 0.9) - else: - if node.use_number: - color = (0.9, 0.8, 0.5) - else: - color = (0.8, 0.8, 0.8) - label = "{0}\n{1} signals\n{2}".format(name, node.signal_count, node.numbers) - return RenderNode(label, children, color=color) - - top = _to_render_node("top", tree) - top.to_svg(filename) - - -def _build_tree(signals, basic_tree=None): - root = _Node() - for signal in signals: - current_b = basic_tree - current = root - current.signal_count += 1 - for name, number in signal.backtrace: - if basic_tree is None: - use_number = False - else: - current_b = current_b.children[name] - use_number = current_b.use_number - if use_number: - key = (name, number) - else: - key = name - try: - current = current.children[key] - except KeyError: - new = _Node() - current.children[key] = new - current = new - current.numbers.add(number) - if use_number: - current.all_numbers = sorted(current_b.numbers) - current.signal_count += 1 - return root - - -def _set_use_name(node, node_name=""): - cnames = [(k, _set_use_name(v, k)) for k, v in node.children.items()] - for (c1_prefix, c1_names), (c2_prefix, c2_names) in combinations(cnames, 2): - if not c1_names.isdisjoint(c2_names): - node.children[c1_prefix].use_name = True - node.children[c2_prefix].use_name = True - r = set() - for c_prefix, c_names in cnames: - if node.children[c_prefix].use_name: - for c_name in c_names: - r.add((c_prefix, ) + c_name) - else: - r |= c_names - - if node.signal_count > sum(c.signal_count for c in node.children.values()): - node.use_name = True - r.add((node_name, )) - - return r - - -def _name_signal(tree, signal): - elements = [] - treepos = tree - for step_name, step_n in signal.backtrace: - try: - treepos = treepos.children[(step_name, step_n)] - use_number = True - except KeyError: - treepos = treepos.children[step_name] - use_number = False - if treepos.use_name: - elname = step_name - if use_number: - elname += str(treepos.all_numbers.index(step_n)) - elements.append(elname) - return "_".join(elements) - - -def _build_pnd_from_tree(tree, signals): - return dict((signal, _name_signal(tree, signal)) for signal in signals) - - -def _invert_pnd(pnd): - inv_pnd = dict() - for k, v in pnd.items(): - inv_pnd[v] = inv_pnd.get(v, []) - inv_pnd[v].append(k) - return inv_pnd - - -def _list_conflicting_signals(pnd): - inv_pnd = _invert_pnd(pnd) - r = set() - for k, v in inv_pnd.items(): - if len(v) > 1: - r.update(v) - return r - - -def _set_use_number(tree, signals): - for signal in signals: - current = tree - for step_name, step_n in signal.backtrace: - current = current.children[step_name] - current.use_number = current.signal_count > len(current.numbers) and len(current.numbers) > 1 - -_debug = False - - -def _build_pnd_for_group(group_n, signals): - basic_tree = _build_tree(signals) - _set_use_name(basic_tree) - if _debug: - _display_tree("tree{0}_basic.svg".format(group_n), basic_tree) - pnd = _build_pnd_from_tree(basic_tree, signals) - - # If there are conflicts, try splitting the tree by numbers - # on paths taken by conflicting signals. - conflicting_signals = _list_conflicting_signals(pnd) - if conflicting_signals: - _set_use_number(basic_tree, conflicting_signals) - if _debug: - print("namer: using split-by-number strategy (group {0})".format(group_n)) - _display_tree("tree{0}_marked.svg".format(group_n), basic_tree) - numbered_tree = _build_tree(signals, basic_tree) - _set_use_name(numbered_tree) - if _debug: - _display_tree("tree{0}_numbered.svg".format(group_n), numbered_tree) - pnd = _build_pnd_from_tree(numbered_tree, signals) - else: - if _debug: - print("namer: using basic strategy (group {0})".format(group_n)) - - # ...then add number suffixes by DUID - inv_pnd = _invert_pnd(pnd) - duid_suffixed = False - for name, signals in inv_pnd.items(): - if len(signals) > 1: - duid_suffixed = True - for n, signal in enumerate(sorted(signals, key=lambda x: x.duid)): - pnd[signal] += str(n) - if _debug and duid_suffixed: - print("namer: using DUID suffixes (group {0})".format(group_n)) - - return pnd - - -def _build_signal_groups(signals): - r = [] - for signal in signals: - # build chain of related signals - related_list = [] - cur_signal = signal - while cur_signal is not None: - related_list.insert(0, cur_signal) - cur_signal = cur_signal.related - # add to groups - for _ in range(len(related_list) - len(r)): - r.append(set()) - for target_set, source_signal in zip(r, related_list): - target_set.add(source_signal) - # with the algorithm above and a list of all signals, - # a signal appears in all groups of a lower number than its. - # make signals appear only in their group of highest number. - for s1, s2 in zip(r, r[1:]): - s1 -= s2 - return r - - -def _build_pnd(signals): - groups = _build_signal_groups(signals) - gpnds = [_build_pnd_for_group(n, gsignals) for n, gsignals in enumerate(groups)] - - pnd = dict() - for gn, gpnd in enumerate(gpnds): - for signal, name in gpnd.items(): - result = name - cur_gn = gn - cur_signal = signal - while cur_signal.related is not None: - cur_signal = cur_signal.related - cur_gn -= 1 - result = gpnds[cur_gn][cur_signal] + "_" + result - pnd[signal] = result - - return pnd - - -def build_namespace(signals, reserved_keywords=set()): - pnd = _build_pnd(signals) - ns = Namespace(pnd, reserved_keywords) - # register signals with name_override - for signal in signals: - if signal.name_override is not None: - ns.get_name(signal) - return ns - - -class Namespace: - def __init__(self, pnd, reserved_keywords=set()): - self.counts = {k: 1 for k in reserved_keywords} - self.sigs = {} - self.pnd = pnd - self.clock_domains = dict() - - def get_name(self, sig): - if isinstance(sig, ClockSignal): - sig = self.clock_domains[sig.cd].clk - if isinstance(sig, ResetSignal): - sig = self.clock_domains[sig.cd].rst - if sig is None: - raise ValueError("Attempted to obtain name of non-existent " - "reset signal of domain "+sig.cd) - - if sig.name_override is not None: - sig_name = sig.name_override - else: - sig_name = self.pnd[sig] - try: - n = self.sigs[sig] - except KeyError: - try: - n = self.counts[sig_name] - except KeyError: - n = 0 - self.sigs[sig] = n - self.counts[sig_name] = n + 1 - if n: - return sig_name + "_" + str(n) - else: - return sig_name diff --git a/litex/gen/fhdl/simplify.py b/litex/gen/fhdl/simplify.py deleted file mode 100644 index 747f5628..00000000 --- a/litex/gen/fhdl/simplify.py +++ /dev/null @@ -1,114 +0,0 @@ -from litex.gen.fhdl.structure import * -from litex.gen.fhdl.specials import Memory, _MemoryPort, WRITE_FIRST, NO_CHANGE -from litex.gen.fhdl.decorators import ModuleTransformer -from litex.gen.util.misc import gcd_multiple - - -class FullMemoryWE(ModuleTransformer): - def __init__(self): - self.replacments = dict() - - def transform_fragment(self, i, f): - newspecials = set() - - for orig in f.specials: - if not isinstance(orig, Memory): - newspecials.add(orig) - continue - global_granularity = gcd_multiple([p.we_granularity if p.we_granularity else orig.width for p in orig.ports]) - if global_granularity == orig.width: - newspecials.add(orig) # nothing to do - else: - newmems = [] - for i in range(orig.width//global_granularity): - if orig.init is None: - newinit = None - else: - newinit = [(v >> i*global_granularity) & (2**global_granularity - 1) for v in orig.init] - newmem = Memory(global_granularity, orig.depth, newinit, orig.name_override + "_grain" + str(i)) - newspecials.add(newmem) - newmems.append(newmem) - for port in orig.ports: - port_granularity = port.we_granularity if port.we_granularity else orig.width - newport = _MemoryPort( - adr=port.adr, - - dat_r=port.dat_r[i*global_granularity:(i+1)*global_granularity] if port.dat_r is not None else None, - we=port.we[i*global_granularity//port_granularity] if port.we is not None else None, - dat_w=port.dat_w[i*global_granularity:(i+1)*global_granularity] if port.dat_w is not None else None, - - async_read=port.async_read, - re=port.re, - we_granularity=0, - mode=port.mode, - clock_domain=port.clock.cd) - newmem.ports.append(newport) - newspecials.add(newport) - self.replacments[orig] = newmems - - f.specials = newspecials - - -class MemoryToArray(ModuleTransformer): - def __init__(self): - self.replacements = dict() - - def transform_fragment(self, i, f): - newspecials = set() - - for mem in f.specials: - if not isinstance(mem, Memory): - newspecials.add(mem) - continue - - storage = Array() - self.replacements[mem] = storage - init = [] - if mem.init is not None: - init = mem.init - for d in init: - mem_storage = Signal(mem.width, reset=d) - storage.append(mem_storage) - for _ in range(mem.depth-len(init)): - mem_storage = Signal(mem.width) - storage.append(mem_storage) - - for port in mem.ports: - if port.we_granularity: - raise NotImplementedError - try: - sync = f.sync[port.clock.cd] - except KeyError: - sync = f.sync[port.clock.cd] = [] - - # read - if port.async_read: - f.comb.append(port.dat_r.eq(storage[port.adr])) - else: - if port.mode == WRITE_FIRST and port.we is not None: - adr_reg = Signal.like(port.adr) - rd_stmt = adr_reg.eq(port.adr) - f.comb.append(port.dat_r.eq(storage[adr_reg])) - elif port.mode == NO_CHANGE and port.we is not None: - rd_stmt = If(~port.we, port.dat_r.eq(storage[port.adr])) - else: # READ_FIRST or port.we is None, simplest case - rd_stmt = port.dat_r.eq(storage[port.adr]) - if port.re is None: - sync.append(rd_stmt) - else: - sync.append(If(port.re, rd_stmt)) - - # write - if port.we is not None: - if port.we_granularity: - n = mem.width//port.we_granularity - for i in range(n): - m = i*port.we_granularity - M = (i+1)*port.we_granularity - sync.append(If(port.we[i], - storage[port.adr][m:M].eq(port.dat_w))) - else: - sync.append(If(port.we, - storage[port.adr].eq(port.dat_w))) - - f.specials = newspecials diff --git a/litex/gen/fhdl/specials.py b/litex/gen/fhdl/specials.py deleted file mode 100644 index d4fc2bf1..00000000 --- a/litex/gen/fhdl/specials.py +++ /dev/null @@ -1,360 +0,0 @@ -from operator import itemgetter - -from litex.gen.fhdl.structure import * -from litex.gen.fhdl.structure import _Value -from litex.gen.fhdl.bitcontainer import bits_for, value_bits_sign -from litex.gen.fhdl.tools import * -from litex.gen.fhdl.tracer import get_obj_var_name -from litex.gen.fhdl.verilog import _printexpr as verilog_printexpr - - -__all__ = ["TSTriple", "Instance", "Memory", - "READ_FIRST", "WRITE_FIRST", "NO_CHANGE"] - - -class Special(DUID): - def iter_expressions(self): - for x in []: - yield x - - def rename_clock_domain(self, old, new): - for obj, attr, direction in self.iter_expressions(): - rename_clock_domain_expr(getattr(obj, attr), old, new) - - def list_clock_domains(self): - r = set() - for obj, attr, direction in self.iter_expressions(): - r |= list_clock_domains_expr(getattr(obj, attr)) - return r - - def list_ios(self, ins, outs, inouts): - r = set() - for obj, attr, direction in self.iter_expressions(): - if (direction == SPECIAL_INPUT and ins) \ - or (direction == SPECIAL_OUTPUT and outs) \ - or (direction == SPECIAL_INOUT and inouts): - signals = list_signals(getattr(obj, attr)) - r.update(signals) - return r - - -class Tristate(Special): - def __init__(self, target, o, oe, i=None): - Special.__init__(self) - self.target = wrap(target) - self.o = wrap(o) - self.oe = wrap(oe) - self.i = wrap(i) if i is not None else None - - def iter_expressions(self): - for attr, target_context in [ - ("target", SPECIAL_INOUT), - ("o", SPECIAL_INPUT), - ("oe", SPECIAL_INPUT), - ("i", SPECIAL_OUTPUT)]: - if getattr(self, attr) is not None: - yield self, attr, target_context - - @staticmethod - def emit_verilog(tristate, ns, add_data_file): - def pe(e): - return verilog_printexpr(ns, e)[0] - w, s = value_bits_sign(tristate.target) - r = "assign " + pe(tristate.target) + " = " \ - + pe(tristate.oe) + " ? " + pe(tristate.o) \ - + " : " + str(w) + "'bz;\n" - if tristate.i is not None: - r += "assign " + pe(tristate.i) + " = " + pe(tristate.target) + ";\n" - r += "\n" - return r - - -class TSTriple: - def __init__(self, bits_sign=None, min=None, max=None, reset_o=0, reset_oe=0): - self.o = Signal(bits_sign, min=min, max=max, reset=reset_o) - self.oe = Signal(reset=reset_oe) - self.i = Signal(bits_sign, min=min, max=max) - - def get_tristate(self, target): - return Tristate(target, self.o, self.oe, self.i) - - -class Instance(Special): - class _IO: - def __init__(self, name, expr=None): - self.name = name - if expr is None: - expr = Signal() - self.expr = wrap(expr) - class Input(_IO): - pass - class Output(_IO): - pass - class InOut(_IO): - pass - class Parameter: - def __init__(self, name, value): - self.name = name - if isinstance(value, (int, bool)): - value = Constant(value) - self.value = value - class PreformattedParam(str): - pass - - def __init__(self, of, *items, name="", synthesis_directive=None, **kwargs): - Special.__init__(self) - self.of = of - if name: - self.name_override = name - else: - self.name_override = of - self.items = list(items) - self.synthesis_directive = synthesis_directive - for k, v in sorted(kwargs.items(), key=itemgetter(0)): - item_type, item_name = k.split("_", maxsplit=1) - item_class = { - "i": Instance.Input, - "o": Instance.Output, - "io": Instance.InOut, - "p": Instance.Parameter - }[item_type] - self.items.append(item_class(item_name, v)) - - def get_io(self, name): - for item in self.items: - if isinstance(item, Instance._IO) and item.name == name: - return item.expr - - def iter_expressions(self): - for item in self.items: - if isinstance(item, Instance.Input): - yield item, "expr", SPECIAL_INPUT - elif isinstance(item, Instance.Output): - yield item, "expr", SPECIAL_OUTPUT - elif isinstance(item, Instance.InOut): - yield item, "expr", SPECIAL_INOUT - - @staticmethod - def emit_verilog(instance, ns, add_data_file): - r = instance.of + " " - parameters = list(filter(lambda i: isinstance(i, Instance.Parameter), instance.items)) - if parameters: - r += "#(\n" - firstp = True - for p in parameters: - if not firstp: - r += ",\n" - firstp = False - r += "\t." + p.name + "(" - if isinstance(p.value, Constant): - r += verilog_printexpr(ns, p.value)[0] - elif isinstance(p.value, float): - r += str(p.value) - elif isinstance(p.value, Instance.PreformattedParam): - r += p.value - elif isinstance(p.value, str): - r += "\"" + p.value + "\"" - else: - raise TypeError - r += ")" - r += "\n) " - r += ns.get_name(instance) - if parameters: r += " " - r += "(\n" - firstp = True - for p in instance.items: - if isinstance(p, Instance._IO): - name_inst = p.name - name_design = verilog_printexpr(ns, p.expr)[0] - if not firstp: - r += ",\n" - firstp = False - r += "\t." + name_inst + "(" + name_design + ")" - if not firstp: - r += "\n" - if instance.synthesis_directive is not None: - synthesis_directive = "/* synthesis {} */".format(instance.synthesis_directive) - r += ")" + synthesis_directive + ";\n\n" - else: - r += ");\n\n" - return r - - -(READ_FIRST, WRITE_FIRST, NO_CHANGE) = range(3) - - -class _MemoryPort(Special): - def __init__(self, adr, dat_r, we=None, dat_w=None, - async_read=False, re=None, we_granularity=0, mode=WRITE_FIRST, - clock_domain="sys"): - Special.__init__(self) - self.adr = adr - self.dat_r = dat_r - self.we = we - self.dat_w = dat_w - self.async_read = async_read - self.re = re - self.we_granularity = we_granularity - self.mode = mode - self.clock = ClockSignal(clock_domain) - - def iter_expressions(self): - for attr, target_context in [ - ("adr", SPECIAL_INPUT), - ("we", SPECIAL_INPUT), - ("dat_w", SPECIAL_INPUT), - ("re", SPECIAL_INPUT), - ("dat_r", SPECIAL_OUTPUT), - ("clock", SPECIAL_INPUT)]: - yield self, attr, target_context - - @staticmethod - def emit_verilog(port, ns, add_data_file): - return "" # done by parent Memory object - - -class _MemoryLocation(_Value): - def __init__(self, memory, index): - _Value.__init__(self) - self.memory = memory - self.index = wrap(index) - - -class Memory(Special): - def __init__(self, width, depth, init=None, name=None): - Special.__init__(self) - self.width = width - self.depth = depth - self.ports = [] - self.init = init - self.name_override = get_obj_var_name(name, "mem") - - def __getitem__(self, index): - # simulation only - return _MemoryLocation(self, index) - - def get_port(self, write_capable=False, async_read=False, - has_re=False, we_granularity=0, mode=WRITE_FIRST, - clock_domain="sys"): - if we_granularity >= self.width: - we_granularity = 0 - adr = Signal(max=self.depth) - dat_r = Signal(self.width) - if write_capable: - if we_granularity: - we = Signal(self.width//we_granularity) - else: - we = Signal() - dat_w = Signal(self.width) - else: - we = None - dat_w = None - if has_re: - re = Signal() - else: - re = None - mp = _MemoryPort(adr, dat_r, we, dat_w, - async_read, re, we_granularity, mode, - clock_domain) - self.ports.append(mp) - return mp - - @staticmethod - def emit_verilog(memory, ns, add_data_file): - r = "" - def gn(e): - if isinstance(e, Memory): - return ns.get_name(e) - else: - return verilog_printexpr(ns, e)[0] - adrbits = bits_for(memory.depth-1) - - r += "reg [" + str(memory.width-1) + ":0] " \ - + gn(memory) \ - + "[0:" + str(memory.depth-1) + "];\n" - - adr_regs = {} - data_regs = {} - for port in memory.ports: - if not port.async_read: - if port.mode == WRITE_FIRST and port.we is not None: - adr_reg = Signal(name_override="memadr") - r += "reg [" + str(adrbits-1) + ":0] " \ - + gn(adr_reg) + ";\n" - adr_regs[id(port)] = adr_reg - else: - data_reg = Signal(name_override="memdat") - r += "reg [" + str(memory.width-1) + ":0] " \ - + gn(data_reg) + ";\n" - data_regs[id(port)] = data_reg - - for port in memory.ports: - r += "always @(posedge " + gn(port.clock) + ") begin\n" - if port.we is not None: - if port.we_granularity: - n = memory.width//port.we_granularity - for i in range(n): - m = i*port.we_granularity - M = (i+1)*port.we_granularity-1 - sl = "[" + str(M) + ":" + str(m) + "]" - r += "\tif (" + gn(port.we) + "[" + str(i) + "])\n" - r += "\t\t" + gn(memory) + "[" + gn(port.adr) + "]" + sl + " <= " + gn(port.dat_w) + sl + ";\n" - else: - r += "\tif (" + gn(port.we) + ")\n" - r += "\t\t" + gn(memory) + "[" + gn(port.adr) + "] <= " + gn(port.dat_w) + ";\n" - if not port.async_read: - if port.mode == WRITE_FIRST and port.we is not None: - rd = "\t" + gn(adr_regs[id(port)]) + " <= " + gn(port.adr) + ";\n" - else: - bassign = gn(data_regs[id(port)]) + " <= " + gn(memory) + "[" + gn(port.adr) + "];\n" - if port.mode == READ_FIRST or port.we is None: - rd = "\t" + bassign - elif port.mode == NO_CHANGE: - rd = "\tif (!" + gn(port.we) + ")\n" \ - + "\t\t" + bassign - if port.re is None: - r += rd - else: - r += "\tif (" + gn(port.re) + ")\n" - r += "\t" + rd.replace("\n\t", "\n\t\t") - r += "end\n\n" - - for port in memory.ports: - if port.async_read: - r += "assign " + gn(port.dat_r) + " = " + gn(memory) + "[" + gn(port.adr) + "];\n" - else: - if port.mode == WRITE_FIRST and port.we is not None: - r += "assign " + gn(port.dat_r) + " = " + gn(memory) + "[" + gn(adr_regs[id(port)]) + "];\n" - else: - r += "assign " + gn(port.dat_r) + " = " + gn(data_regs[id(port)]) + ";\n" - r += "\n" - - if memory.init is not None: - content = "" - for d in memory.init: - content += "{:x}\n".format(d) - memory_filename = add_data_file(gn(memory) + ".init", content) - - r += "initial begin\n" - r += "\t$readmemh(\"" + memory_filename + "\", " + gn(memory) + ");\n" - r += "end\n\n" - - return r - - -class SynthesisDirective(Special): - def __init__(self, template, **signals): - Special.__init__(self) - self.template = template - self.signals = signals - - @staticmethod - def emit_verilog(directive, ns, add_data_file): - name_dict = dict((k, ns.get_name(sig)) for k, sig in directive.signals.items()) - formatted = directive.template.format(**name_dict) - return "// synthesis " + formatted + "\n" - - -class Keep(SynthesisDirective): - def __init__(self, signal): - SynthesisDirective.__init__(self, "attribute keep of {s} is true", s=signal) diff --git a/litex/gen/fhdl/structure.py b/litex/gen/fhdl/structure.py deleted file mode 100644 index 7e6d2ca5..00000000 --- a/litex/gen/fhdl/structure.py +++ /dev/null @@ -1,713 +0,0 @@ -import builtins as _builtins -import collections as _collections - -from litex.gen.fhdl import tracer as _tracer -from litex.gen.util.misc import flat_iteration as _flat_iteration - - -class DUID: - """Deterministic Unique IDentifier""" - __next_uid = 0 - def __init__(self): - self.duid = DUID.__next_uid - DUID.__next_uid += 1 - - -class _Value(DUID): - """Base class for operands - - Instances of `_Value` or its subclasses can be operands to - arithmetic, comparison, bitwise, and logic operators. - They can be assigned (:meth:`eq`) or indexed/sliced (using the usual - Python indexing and slicing notation). - - Values created from integers have the minimum bit width to necessary to - represent the integer. - """ - def __bool__(self): - # Special case: Constants and Signals are part of a set or used as - # dictionary keys, and Python needs to check for equality. - if isinstance(self, _Operator) and self.op == "==": - a, b = self.operands - if isinstance(a, Constant) and isinstance(b, Constant): - return a.value == b.value - if isinstance(a, Signal) and isinstance(b, Signal): - return a is b - if (isinstance(a, Constant) and isinstance(b, Signal) - or isinstance(a, Signal) and isinstance(a, Constant)): - return False - raise TypeError("Attempted to convert Migen value to boolean") - - def __invert__(self): - return _Operator("~", [self]) - def __neg__(self): - return _Operator("-", [self]) - - def __add__(self, other): - return _Operator("+", [self, other]) - def __radd__(self, other): - return _Operator("+", [other, self]) - def __sub__(self, other): - return _Operator("-", [self, other]) - def __rsub__(self, other): - return _Operator("-", [other, self]) - def __mul__(self, other): - return _Operator("*", [self, other]) - def __rmul__(self, other): - return _Operator("*", [other, self]) - def __lshift__(self, other): - return _Operator("<<<", [self, other]) - def __rlshift__(self, other): - return _Operator("<<<", [other, self]) - def __rshift__(self, other): - return _Operator(">>>", [self, other]) - def __rrshift__(self, other): - return _Operator(">>>", [other, self]) - def __and__(self, other): - return _Operator("&", [self, other]) - def __rand__(self, other): - return _Operator("&", [other, self]) - def __xor__(self, other): - return _Operator("^", [self, other]) - def __rxor__(self, other): - return _Operator("^", [other, self]) - def __or__(self, other): - return _Operator("|", [self, other]) - def __ror__(self, other): - return _Operator("|", [other, self]) - - def __lt__(self, other): - return _Operator("<", [self, other]) - def __le__(self, other): - return _Operator("<=", [self, other]) - def __eq__(self, other): - return _Operator("==", [self, other]) - def __ne__(self, other): - return _Operator("!=", [self, other]) - def __gt__(self, other): - return _Operator(">", [self, other]) - def __ge__(self, other): - return _Operator(">=", [self, other]) - - def __len__(self): - from litex.gen.fhdl.bitcontainer import value_bits_sign - return value_bits_sign(self)[0] - - def __getitem__(self, key): - n = len(self) - if isinstance(key, int): - if key >= n: - raise IndexError - if key < 0: - key += n - return _Slice(self, key, key+1) - elif isinstance(key, slice): - start, stop, step = key.indices(n) - if step != 1: - return Cat(self[i] for i in range(start, stop, step)) - return _Slice(self, start, stop) - else: - raise TypeError - - def eq(self, r): - """Assignment - - Parameters - ---------- - r : _Value, in - Value to be assigned. - - Returns - ------- - _Assign - Assignment statement that can be used in combinatorial or - synchronous context. - """ - return _Assign(self, r) - - def __hash__(self): - raise TypeError("unhashable type: '{}'".format(type(self).__name__)) - - -def wrap(value): - """Ensures that the passed object is a Migen value. Booleans and integers - are automatically wrapped into ``Constant``.""" - if isinstance(value, (bool, int)): - value = Constant(value) - if not isinstance(value, _Value): - raise TypeError("Object is not a Migen value") - return value - - -class _Operator(_Value): - def __init__(self, op, operands): - _Value.__init__(self) - self.op = op - self.operands = [wrap(o) for o in operands] - - -def Mux(sel, val1, val0): - """Multiplex between two values - - Parameters - ---------- - sel : _Value(1), in - Selector. - val1 : _Value(N), in - val0 : _Value(N), in - Input values. - - Returns - ------- - _Value(N), out - Output `_Value`. If `sel` is asserted, the Mux returns - `val1`, else `val0`. - """ - return _Operator("m", [sel, val1, val0]) - - -class _Slice(_Value): - def __init__(self, value, start, stop): - _Value.__init__(self) - if not isinstance(start, int) or not isinstance(stop, int): - raise TypeError("Slice boundaries must be integers") - self.value = wrap(value) - self.start = start - self.stop = stop - - -class Cat(_Value): - """Concatenate values - - Form a compound `_Value` from several smaller ones by concatenation. - The first argument occupies the lower bits of the result. - The return value can be used on either side of an assignment, that - is, the concatenated value can be used as an argument on the RHS or - as a target on the LHS. If it is used on the LHS, it must solely - consist of `Signal` s, slices of `Signal` s, and other concatenations - meeting these properties. The bit length of the return value is the sum of - the bit lengths of the arguments:: - - len(Cat(args)) == sum(len(arg) for arg in args) - - Parameters - ---------- - *args : _Values or iterables of _Values, inout - `_Value` s to be concatenated. - - Returns - ------- - Cat, inout - Resulting `_Value` obtained by concatentation. - """ - def __init__(self, *args): - _Value.__init__(self) - self.l = [wrap(v) for v in _flat_iteration(args)] - - -class Replicate(_Value): - """Replicate a value - - An input value is replicated (repeated) several times - to be used on the RHS of assignments:: - - len(Replicate(s, n)) == len(s)*n - - Parameters - ---------- - v : _Value, in - Input value to be replicated. - n : int - Number of replications. - - Returns - ------- - Replicate, out - Replicated value. - """ - def __init__(self, v, n): - _Value.__init__(self) - if not isinstance(n, int) or n < 0: - raise TypeError("Replication count must be a positive integer") - self.v = wrap(v) - self.n = n - - -class Constant(_Value): - """A constant, HDL-literal integer `_Value` - - Parameters - ---------- - value : int - bits_sign : int or tuple or None - Either an integer `bits` or a tuple `(bits, signed)` - specifying the number of bits in this `Constant` and whether it is - signed (can represent negative values). `bits_sign` defaults - to the minimum width and signedness of `value`. - """ - def __init__(self, value, bits_sign=None): - from litex.gen.fhdl.bitcontainer import bits_for - - _Value.__init__(self) - - self.value = int(value) - if bits_sign is None: - bits_sign = bits_for(self.value), self.value < 0 - elif isinstance(bits_sign, int): - bits_sign = bits_sign, self.value < 0 - self.nbits, self.signed = bits_sign - if not isinstance(self.nbits, int) or self.nbits <= 0: - raise TypeError("Width must be a strictly positive integer") - - def __hash__(self): - return self.value - - -C = Constant # shorthand - - -class Signal(_Value): - """A `_Value` that can change - - The `Signal` object represents a value that is expected to change - in the circuit. It does exactly what Verilog's `wire` and - `reg` and VHDL's `signal` do. - - A `Signal` can be indexed to access a subset of its bits. Negative - indices (`signal[-1]`) and the extended Python slicing notation - (`signal[start:stop:step]`) are supported. - The indices 0 and -1 are the least and most significant bits - respectively. - - Parameters - ---------- - bits_sign : int or tuple - Either an integer `bits` or a tuple `(bits, signed)` - specifying the number of bits in this `Signal` and whether it is - signed (can represent negative values). `signed` defaults to - `False`. - name : str or None - Name hint for this signal. If `None` (default) the name is - inferred from the variable name this `Signal` is assigned to. - Name collisions are automatically resolved by prepending - names of objects that contain this `Signal` and by - appending integer sequences. - variable : bool - Deprecated. - reset : int - Reset (synchronous) or default (combinatorial) value. - When this `Signal` is assigned to in synchronous context and the - corresponding clock domain is reset, the `Signal` assumes the - given value. When this `Signal` is unassigned in combinatorial - context (due to conditional assignments not being taken), - the `Signal` assumes its `reset` value. Defaults to 0. - name_override : str or None - Do not use the inferred name but the given one. - min : int or None - max : int or None - If `bits_sign` is `None`, the signal bit width and signedness are - determined by the integer range given by `min` (inclusive, - defaults to 0) and `max` (exclusive, defaults to 2). - related : Signal or None - """ - def __init__(self, bits_sign=None, name=None, variable=False, reset=0, name_override=None, min=None, max=None, related=None): - from litex.gen.fhdl.bitcontainer import bits_for - - _Value.__init__(self) - - # determine number of bits and signedness - if bits_sign is None: - if min is None: - min = 0 - if max is None: - max = 2 - max -= 1 # make both bounds inclusive - assert(min < max) - self.signed = min < 0 or max < 0 - self.nbits = _builtins.max(bits_for(min, self.signed), bits_for(max, self.signed)) - else: - assert(min is None and max is None) - if isinstance(bits_sign, tuple): - self.nbits, self.signed = bits_sign - else: - self.nbits, self.signed = bits_sign, False - if not isinstance(self.nbits, int) or self.nbits <= 0: - raise ValueError("Signal width must be a strictly positive integer") - - self.variable = variable # deprecated - self.reset = reset - self.name_override = name_override - self.backtrace = _tracer.trace_back(name) - self.related = related - - def __setattr__(self, k, v): - if k == "reset": - v = wrap(v) - _Value.__setattr__(self, k, v) - - def __repr__(self): - return "" - - @classmethod - def like(cls, other, **kwargs): - """Create Signal based on another. - - Parameters - ---------- - other : _Value - Object to base this Signal on. - - See `migen.fhdl.bitcontainer.value_bits_sign` for details. - """ - from litex.gen.fhdl.bitcontainer import value_bits_sign - return cls(bits_sign=value_bits_sign(other), **kwargs) - - def __hash__(self): - return self.duid - - -class ClockSignal(_Value): - """Clock signal for a given clock domain - - `ClockSignal` s for a given clock domain can be retrieved multiple - times. They all ultimately refer to the same signal. - - Parameters - ---------- - cd : str - Clock domain to obtain a clock signal for. Defaults to `"sys"`. - """ - def __init__(self, cd="sys"): - _Value.__init__(self) - if not isinstance(cd, str): - raise TypeError("Argument of ClockSignal must be a string") - self.cd = cd - - -class ResetSignal(_Value): - """Reset signal for a given clock domain - - `ResetSignal` s for a given clock domain can be retrieved multiple - times. They all ultimately refer to the same signal. - - Parameters - ---------- - cd : str - Clock domain to obtain a reset signal for. Defaults to `"sys"`. - allow_reset_less : bool - If the clock domain is resetless, return 0 instead of reporting an - error. - """ - def __init__(self, cd="sys", allow_reset_less=False): - _Value.__init__(self) - if not isinstance(cd, str): - raise TypeError("Argument of ResetSignal must be a string") - self.cd = cd - self.allow_reset_less = allow_reset_less - - -# statements - - -class _Statement: - pass - - -class _Assign(_Statement): - def __init__(self, l, r): - self.l = wrap(l) - self.r = wrap(r) - - -def _check_statement(s): - if isinstance(s, _collections.Iterable): - return all(_check_statement(ss) for ss in s) - else: - return isinstance(s, _Statement) - - -class If(_Statement): - """Conditional execution of statements - - Parameters - ---------- - cond : _Value(1), in - Condition - *t : Statements - Statements to execute if `cond` is asserted. - - Examples - -------- - >>> a = Signal() - >>> b = Signal() - >>> c = Signal() - >>> d = Signal() - >>> If(a, - ... b.eq(1) - ... ).Elif(c, - ... b.eq(0) - ... ).Else( - ... b.eq(d) - ... ) - """ - def __init__(self, cond, *t): - if not _check_statement(t): - raise TypeError("Not all test body objects are Migen statements") - self.cond = wrap(cond) - self.t = list(t) - self.f = [] - - def Else(self, *f): - """Add an `else` conditional block - - Parameters - ---------- - *f : Statements - Statements to execute if all previous conditions fail. - """ - if not _check_statement(f): - raise TypeError("Not all test body objects are Migen statements") - _insert_else(self, list(f)) - return self - - def Elif(self, cond, *t): - """Add an `else if` conditional block - - Parameters - ---------- - cond : _Value(1), in - Condition - *t : Statements - Statements to execute if previous conditions fail and `cond` - is asserted. - """ - _insert_else(self, [If(cond, *t)]) - return self - - -def _insert_else(obj, clause): - o = obj - while o.f: - assert(len(o.f) == 1) - assert(isinstance(o.f[0], If)) - o = o.f[0] - o.f = clause - - -class Case(_Statement): - """Case/Switch statement - - Parameters - ---------- - test : _Value, in - Selector value used to decide which block to execute - cases : dict - Dictionary of cases. The keys are numeric constants to compare - with `test`. The values are statements to be executed the - corresponding key matches `test`. The dictionary may contain a - string key `"default"` to mark a fall-through case that is - executed if no other key matches. - - Examples - -------- - >>> a = Signal() - >>> b = Signal() - >>> Case(a, { - ... 0: b.eq(1), - ... 1: b.eq(0), - ... "default": b.eq(0), - ... }) - """ - def __init__(self, test, cases): - self.test = wrap(test) - self.cases = dict() - for k, v in cases.items(): - if isinstance(k, (bool, int)): - k = Constant(k) - if (not isinstance(k, Constant) - and not (isinstance(k, str) and k == "default")): - raise TypeError("Case object is not a Migen constant") - if not isinstance(v, _collections.Iterable): - v = [v] - if not _check_statement(v): - raise TypeError("Not all objects for case {} " - "are Migen statements".format(k)) - self.cases[k] = v - - def makedefault(self, key=None): - """Mark a key as the default case - - Deletes/substitutes any previously existing default case. - - Parameters - ---------- - key : int or None - Key to use as default case if no other key matches. - By default, the largest key is the default key. - """ - if key is None: - for choice in self.cases.keys(): - if key is None or choice.value > key.value: - key = choice - self.cases["default"] = self.cases[key] - del self.cases[key] - return self - - -# arrays - - -class _ArrayProxy(_Value): - def __init__(self, choices, key): - _Value.__init__(self) - self.choices = [] - for c in choices: - if isinstance(c, (bool, int)): - c = Constant(c) - self.choices.append(c) - self.key = key - - def __getattr__(self, attr): - return _ArrayProxy([getattr(choice, attr) for choice in self.choices], - self.key) - - def __getitem__(self, key): - return _ArrayProxy([choice.__getitem__(key) for choice in self.choices], - self.key) - - -class Array(list): - """Addressable multiplexer - - An array is created from an iterable of values and indexed using the - usual Python simple indexing notation (no negative indices or - slices). It can be indexed by numeric constants, `_Value` s, or - `Signal` s. - - The result of indexing the array is a proxy for the entry at the - given index that can be used on either RHS or LHS of assignments. - - An array can be indexed multiple times. - - Multidimensional arrays are supported by packing inner arrays into - outer arrays. - - Parameters - ---------- - values : iterable of ints, _Values, Signals - Entries of the array. Each entry can be a numeric constant, a - `Signal` or a `Record`. - - Examples - -------- - >>> a = Array(range(10)) - >>> b = Signal(max=10) - >>> c = Signal(max=10) - >>> b.eq(a[9 - c]) - """ - def __getitem__(self, key): - if isinstance(key, Constant): - return list.__getitem__(self, key.value) - elif isinstance(key, _Value): - return _ArrayProxy(self, key) - else: - return list.__getitem__(self, key) - - -class ClockDomain: - """Synchronous domain - - Parameters - ---------- - name : str or None - Domain name. If None (the default) the name is inferred from the - variable name this `ClockDomain` is assigned to (stripping any - `"cd_"` prefix). - reset_less : bool - The domain does not use a reset signal. Registers within this - domain are still all initialized to their reset state once, e.g. - through Verilog `"initial"` statements. - - Attributes - ---------- - clk : Signal, inout - The clock for this domain. Can be driven or used to drive other - signals (preferably in combinatorial context). - rst : Signal or None, inout - Reset signal for this domain. Can be driven or used to drive. - """ - def __init__(self, name=None, reset_less=False): - self.name = _tracer.get_obj_var_name(name) - if self.name is None: - raise ValueError("Cannot extract clock domain name from code, need to specify.") - if self.name.startswith("cd_"): - self.name = self.name[3:] - if self.name[0].isdigit(): - raise ValueError("Clock domain name cannot start with a number.") - self.clk = Signal(name_override=self.name + "_clk") - if reset_less: - self.rst = None - else: - self.rst = Signal(name_override=self.name + "_rst") - - def rename(self, new_name): - """Rename the clock domain - - Parameters - ---------- - new_name : str - New name - """ - self.name = new_name - self.clk.name_override = new_name + "_clk" - if self.rst is not None: - self.rst.name_override = new_name + "_rst" - - -class _ClockDomainList(list): - def __getitem__(self, key): - if isinstance(key, str): - for cd in self: - if cd.name == key: - return cd - raise KeyError(key) - else: - return list.__getitem__(self, key) - - -(SPECIAL_INPUT, SPECIAL_OUTPUT, SPECIAL_INOUT) = range(3) - - -class _Fragment: - def __init__(self, comb=None, sync=None, specials=None, clock_domains=None): - if comb is None: comb = [] - if sync is None: sync = dict() - if specials is None: specials = set() - if clock_domains is None: clock_domains = _ClockDomainList() - - self.comb = comb - self.sync = sync - self.specials = specials - self.clock_domains = _ClockDomainList(clock_domains) - - def __add__(self, other): - newsync = _collections.defaultdict(list) - for k, v in self.sync.items(): - newsync[k] = v[:] - for k, v in other.sync.items(): - newsync[k].extend(v) - return _Fragment(self.comb + other.comb, newsync, - self.specials | other.specials, - self.clock_domains + other.clock_domains) - - def __iadd__(self, other): - newsync = _collections.defaultdict(list) - for k, v in self.sync.items(): - newsync[k] = v[:] - for k, v in other.sync.items(): - newsync[k].extend(v) - self.comb += other.comb - self.sync = newsync - self.specials |= other.specials - self.clock_domains += other.clock_domains - return self diff --git a/litex/gen/fhdl/tools.py b/litex/gen/fhdl/tools.py deleted file mode 100644 index 3db91831..00000000 --- a/litex/gen/fhdl/tools.py +++ /dev/null @@ -1,298 +0,0 @@ -from litex.gen.fhdl.structure import * -from litex.gen.fhdl.structure import _Slice, _Assign -from litex.gen.fhdl.visit import NodeVisitor, NodeTransformer -from litex.gen.fhdl.bitcontainer import value_bits_sign -from litex.gen.util.misc import flat_iteration - - -class _SignalLister(NodeVisitor): - def __init__(self): - self.output_list = set() - - def visit_Signal(self, node): - self.output_list.add(node) - - -class _TargetLister(NodeVisitor): - def __init__(self): - self.output_list = set() - self.target_context = False - - def visit_Signal(self, node): - if self.target_context: - self.output_list.add(node) - - def visit_Assign(self, node): - self.target_context = True - self.visit(node.l) - self.target_context = False - - def visit_ArrayProxy(self, node): - for choice in node.choices: - self.visit(choice) - - -class _InputLister(NodeVisitor): - def __init__(self): - self.output_list = set() - - def visit_Signal(self, node): - self.output_list.add(node) - - def visit_Assign(self, node): - self.visit(node.r) - - -def list_signals(node): - lister = _SignalLister() - lister.visit(node) - return lister.output_list - - -def list_targets(node): - lister = _TargetLister() - lister.visit(node) - return lister.output_list - - -def list_inputs(node): - lister = _InputLister() - lister.visit(node) - return lister.output_list - - -def _resort_statements(ol): - return [statement for i, statement in - sorted(ol, key=lambda x: x[0])] - - -def group_by_targets(sl): - groups = [] - seen = set() - for order, stmt in enumerate(flat_iteration(sl)): - targets = set(list_targets(stmt)) - group = [(order, stmt)] - disjoint = targets.isdisjoint(seen) - seen |= targets - if not disjoint: - groups, old_groups = [], groups - for old_targets, old_group in old_groups: - if targets.isdisjoint(old_targets): - groups.append((old_targets, old_group)) - else: - targets |= old_targets - group += old_group - groups.append((targets, group)) - return [(targets, _resort_statements(stmts)) - for targets, stmts in groups] - - -def list_special_ios(f, ins, outs, inouts): - r = set() - for special in f.specials: - r |= special.list_ios(ins, outs, inouts) - return r - - -class _ClockDomainLister(NodeVisitor): - def __init__(self): - self.clock_domains = set() - - def visit_ClockSignal(self, node): - self.clock_domains.add(node.cd) - - def visit_ResetSignal(self, node): - self.clock_domains.add(node.cd) - - def visit_clock_domains(self, node): - for clockname, statements in node.items(): - self.clock_domains.add(clockname) - self.visit(statements) - - -def list_clock_domains_expr(f): - cdl = _ClockDomainLister() - cdl.visit(f) - return cdl.clock_domains - - -def list_clock_domains(f): - r = list_clock_domains_expr(f) - for special in f.specials: - r |= special.list_clock_domains() - for cd in f.clock_domains: - r.add(cd.name) - return r - - -def is_variable(node): - if isinstance(node, Signal): - return node.variable - elif isinstance(node, _Slice): - return is_variable(node.value) - elif isinstance(node, Cat): - arevars = list(map(is_variable, node.l)) - r = arevars[0] - for x in arevars: - if x != r: - raise TypeError - return r - else: - raise TypeError - - -def generate_reset(rst, sl): - targets = list_targets(sl) - return [t.eq(t.reset) for t in sorted(targets, key=lambda x: x.duid)] - - -def insert_reset(rst, sl): - return [If(rst, *generate_reset(rst, sl)).Else(*sl)] - - -def insert_resets(f): - newsync = dict() - for k, v in f.sync.items(): - if f.clock_domains[k].rst is not None: - newsync[k] = insert_reset(ResetSignal(k), v) - else: - newsync[k] = v - f.sync = newsync - - -class _Lowerer(NodeTransformer): - def __init__(self): - self.target_context = False - self.extra_stmts = [] - self.comb = [] - - def visit_Assign(self, node): - old_target_context, old_extra_stmts = self.target_context, self.extra_stmts - self.extra_stmts = [] - - self.target_context = True - lhs = self.visit(node.l) - self.target_context = False - rhs = self.visit(node.r) - r = _Assign(lhs, rhs) - if self.extra_stmts: - r = [r] + self.extra_stmts - - self.target_context, self.extra_stmts = old_target_context, old_extra_stmts - return r - - -# Basics are FHDL structure elements that back-ends are not required to support -# but can be expressed in terms of other elements (lowered) before conversion. -class _BasicLowerer(_Lowerer): - def __init__(self, clock_domains): - self.clock_domains = clock_domains - _Lowerer.__init__(self) - - def visit_ArrayProxy(self, node): - # TODO: rewrite without variables - array_muxed = Signal(value_bits_sign(node), variable=True) - if self.target_context: - k = self.visit(node.key) - cases = {} - for n, choice in enumerate(node.choices): - cases[n] = [self.visit_Assign(_Assign(choice, array_muxed))] - self.extra_stmts.append(Case(k, cases).makedefault()) - else: - cases = dict((n, _Assign(array_muxed, self.visit(choice))) - for n, choice in enumerate(node.choices)) - self.comb.append(Case(self.visit(node.key), cases).makedefault()) - return array_muxed - - def visit_ClockSignal(self, node): - return self.clock_domains[node.cd].clk - - def visit_ResetSignal(self, node): - rst = self.clock_domains[node.cd].rst - if rst is None: - if node.allow_reset_less: - return 0 - else: - raise ValueError("Attempted to get reset signal of resetless" - " domain '{}'".format(node.cd)) - else: - return rst - - -class _ComplexSliceLowerer(_Lowerer): - def visit_Slice(self, node): - if not isinstance(node.value, Signal): - slice_proxy = Signal(value_bits_sign(node.value)) - if self.target_context: - a = _Assign(node.value, slice_proxy) - else: - a = _Assign(slice_proxy, node.value) - self.comb.append(self.visit_Assign(a)) - node = _Slice(slice_proxy, node.start, node.stop) - return NodeTransformer.visit_Slice(self, node) - - -def _apply_lowerer(l, f): - f = l.visit(f) - f.comb += l.comb - - for special in f.specials: - for obj, attr, direction in special.iter_expressions(): - if direction != SPECIAL_INOUT: - # inouts are only supported by Migen when connected directly to top-level - # in this case, they are Signal and never need lowering - l.comb = [] - l.target_context = direction != SPECIAL_INPUT - l.extra_stmts = [] - expr = getattr(obj, attr) - expr = l.visit(expr) - setattr(obj, attr, expr) - f.comb += l.comb + l.extra_stmts - - return f - - -def lower_basics(f): - return _apply_lowerer(_BasicLowerer(f.clock_domains), f) - - -def lower_complex_slices(f): - return _apply_lowerer(_ComplexSliceLowerer(), f) - - -class _ClockDomainRenamer(NodeVisitor): - def __init__(self, old, new): - self.old = old - self.new = new - - def visit_ClockSignal(self, node): - if node.cd == self.old: - node.cd = self.new - - def visit_ResetSignal(self, node): - if node.cd == self.old: - node.cd = self.new - - -def rename_clock_domain_expr(f, old, new): - cdr = _ClockDomainRenamer(old, new) - cdr.visit(f) - - -def rename_clock_domain(f, old, new): - rename_clock_domain_expr(f, old, new) - if new != old: - if old in f.sync: - if new in f.sync: - f.sync[new].extend(f.sync[old]) - else: - f.sync[new] = f.sync[old] - del f.sync[old] - for special in f.specials: - special.rename_clock_domain(old, new) - try: - cd = f.clock_domains[old] - except KeyError: - pass - else: - cd.rename(new) diff --git a/litex/gen/fhdl/tracer.py b/litex/gen/fhdl/tracer.py deleted file mode 100644 index a394f93f..00000000 --- a/litex/gen/fhdl/tracer.py +++ /dev/null @@ -1,115 +0,0 @@ -import inspect -from opcode import opname -from collections import defaultdict - - -def get_var_name(frame): - code = frame.f_code - call_index = frame.f_lasti - call_opc = opname[code.co_code[call_index]] - if call_opc != "CALL_FUNCTION" and call_opc != "CALL_FUNCTION_VAR": - return None - index = call_index+3 - while True: - opc = opname[code.co_code[index]] - if opc == "STORE_NAME" or opc == "STORE_ATTR": - name_index = int(code.co_code[index+1]) - return code.co_names[name_index] - elif opc == "STORE_FAST": - name_index = int(code.co_code[index+1]) - return code.co_varnames[name_index] - elif opc == "STORE_DEREF": - name_index = int(code.co_code[index+1]) - return code.co_cellvars[name_index] - elif opc == "LOAD_GLOBAL" or opc == "LOAD_ATTR" or opc == "LOAD_FAST" or opc == "LOAD_DEREF": - index += 3 - elif opc == "DUP_TOP": - index += 1 - elif opc == "BUILD_LIST": - index += 3 - else: - return None - - -def remove_underscore(s): - if len(s) > 2 and s[0] == "_" and s[1] != "_": - s = s[1:] - return s - - -def get_obj_var_name(override=None, default=None): - if override: - return override - - frame = inspect.currentframe().f_back - # We can be called via derived classes. Go back the stack frames - # until we reach the first class that does not inherit from us. - ourclass = frame.f_locals["self"].__class__ - while "self" in frame.f_locals and isinstance(frame.f_locals["self"], ourclass): - frame = frame.f_back - - vn = get_var_name(frame) - if vn is None: - vn = default - else: - vn = remove_underscore(vn) - return vn - -name_to_idx = defaultdict(int) -classname_to_objs = dict() - - -def index_id(l, obj): - for n, e in enumerate(l): - if id(e) == id(obj): - return n - raise ValueError - - -def trace_back(varname=None): - l = [] - frame = inspect.currentframe().f_back.f_back - while frame is not None: - if varname is None: - varname = get_var_name(frame) - if varname is not None: - varname = remove_underscore(varname) - l.insert(0, (varname, name_to_idx[varname])) - name_to_idx[varname] += 1 - - try: - obj = frame.f_locals["self"] - except KeyError: - obj = None - if hasattr(obj, "__del__"): - obj = None - - if obj is None: - if varname is not None: - coname = frame.f_code.co_name - if coname == "": - modules = frame.f_globals["__name__"] - modules = modules.split(".") - coname = modules[len(modules)-1] - coname = remove_underscore(coname) - l.insert(0, (coname, name_to_idx[coname])) - name_to_idx[coname] += 1 - else: - classname = obj.__class__.__name__.lower() - try: - objs = classname_to_objs[classname] - except KeyError: - classname_to_objs[classname] = [obj] - idx = 0 - else: - try: - idx = index_id(objs, obj) - except ValueError: - idx = len(objs) - objs.append(obj) - classname = remove_underscore(classname) - l.insert(0, (classname, idx)) - - varname = None - frame = frame.f_back - return l diff --git a/litex/gen/fhdl/verilog.py b/litex/gen/fhdl/verilog.py deleted file mode 100644 index acca5f52..00000000 --- a/litex/gen/fhdl/verilog.py +++ /dev/null @@ -1,361 +0,0 @@ -from functools import partial -from operator import itemgetter -import collections - -from litex.gen.fhdl.structure import * -from litex.gen.fhdl.structure import _Operator, _Slice, _Assign, _Fragment -from litex.gen.fhdl.tools import * -from litex.gen.fhdl.bitcontainer import bits_for -from litex.gen.fhdl.namer import build_namespace -from litex.gen.fhdl.conv_output import ConvOutput - - -_reserved_keywords = { - "always", "and", "assign", "automatic", "begin", "buf", "bufif0", "bufif1", - "case", "casex", "casez", "cell", "cmos", "config", "deassign", "default", - "defparam", "design", "disable", "edge", "else", "end", "endcase", - "endconfig", "endfunction", "endgenerate", "endmodule", "endprimitive", - "endspecify", "endtable", "endtask", "event", "for", "force", "forever", - "fork", "function", "generate", "genvar", "highz0", "highz1", "if", - "ifnone", "incdir", "include", "initial", "inout", "input", - "instance", "integer", "join", "large", "liblist", "library", "localparam", - "macromodule", "medium", "module", "nand", "negedge", "nmos", "nor", - "noshowcancelled", "not", "notif0", "notif1", "or", "output", "parameter", - "pmos", "posedge", "primitive", "pull0", "pull1" "pulldown", - "pullup", "pulsestyle_onevent", "pulsestyle_ondetect", "remos", "real", - "realtime", "reg", "release", "repeat", "rnmos", "rpmos", "rtran", - "rtranif0", "rtranif1", "scalared", "showcancelled", "signed", "small", - "specify", "specparam", "strong0", "strong1", "supply0", "supply1", - "table", "task", "time", "tran", "tranif0", "tranif1", "tri", "tri0", - "tri1", "triand", "trior", "trireg", "unsigned", "use", "vectored", "wait", - "wand", "weak0", "weak1", "while", "wire", "wor","xnor", "xor" -} - - -def _printsig(ns, s): - if s.signed: - n = "signed " - else: - n = "" - if len(s) > 1: - n += "[" + str(len(s)-1) + ":0] " - n += ns.get_name(s) - return n - - -def _printconstant(node): - if node.signed: - return (str(node.nbits) + "'sd" + str(2**node.nbits + node.value), - True) - else: - return str(node.nbits) + "'d" + str(node.value), False - - -def _printexpr(ns, node): - if isinstance(node, Constant): - return _printconstant(node) - elif isinstance(node, Signal): - return ns.get_name(node), node.signed - elif isinstance(node, _Operator): - arity = len(node.operands) - r1, s1 = _printexpr(ns, node.operands[0]) - if arity == 1: - if node.op == "-": - if s1: - r = node.op + r1 - else: - r = "-$signed({1'd0, " + r1 + "})" - s = True - else: - r = node.op + r1 - s = s1 - elif arity == 2: - r2, s2 = _printexpr(ns, node.operands[1]) - if node.op not in ["<<<", ">>>"]: - if s2 and not s1: - r1 = "$signed({1'd0, " + r1 + "})" - if s1 and not s2: - r2 = "$signed({1'd0, " + r2 + "})" - r = r1 + " " + node.op + " " + r2 - s = s1 or s2 - elif arity == 3: - assert node.op == "m" - r2, s2 = _printexpr(ns, node.operands[1]) - r3, s3 = _printexpr(ns, node.operands[2]) - if s2 and not s3: - r3 = "$signed({1'd0, " + r3 + "})" - if s3 and not s2: - r2 = "$signed({1'd0, " + r2 + "})" - r = r1 + " ? " + r2 + " : " + r3 - s = s2 or s3 - else: - raise TypeError - return "(" + r + ")", s - elif isinstance(node, _Slice): - # Verilog does not like us slicing non-array signals... - if isinstance(node.value, Signal) \ - and len(node.value) == 1 \ - and node.start == 0 and node.stop == 1: - return _printexpr(ns, node.value) - - if node.start + 1 == node.stop: - sr = "[" + str(node.start) + "]" - else: - sr = "[" + str(node.stop-1) + ":" + str(node.start) + "]" - r, s = _printexpr(ns, node.value) - return r + sr, s - elif isinstance(node, Cat): - l = [_printexpr(ns, v)[0] for v in reversed(node.l)] - return "{" + ", ".join(l) + "}", False - elif isinstance(node, Replicate): - return "{" + str(node.n) + "{" + _printexpr(ns, node.v)[0] + "}}", False - else: - raise TypeError("Expression of unrecognized type: '{}'".format(type(node).__name__)) - - -(_AT_BLOCKING, _AT_NONBLOCKING, _AT_SIGNAL) = range(3) - - -def _printnode(ns, at, level, node): - if node is None: - return "" - elif isinstance(node, _Assign): - if at == _AT_BLOCKING: - assignment = " = " - elif at == _AT_NONBLOCKING: - assignment = " <= " - elif is_variable(node.l): - assignment = " = " - else: - assignment = " <= " - return "\t"*level + _printexpr(ns, node.l)[0] + assignment + _printexpr(ns, node.r)[0] + ";\n" - elif isinstance(node, collections.Iterable): - return "".join(list(map(partial(_printnode, ns, at, level), node))) - elif isinstance(node, If): - r = "\t"*level + "if (" + _printexpr(ns, node.cond)[0] + ") begin\n" - r += _printnode(ns, at, level + 1, node.t) - if node.f: - r += "\t"*level + "end else begin\n" - r += _printnode(ns, at, level + 1, node.f) - r += "\t"*level + "end\n" - return r - elif isinstance(node, Case): - if node.cases: - r = "\t"*level + "case (" + _printexpr(ns, node.test)[0] + ")\n" - css = [(k, v) for k, v in node.cases.items() if isinstance(k, Constant)] - css = sorted(css, key=lambda x: x[0].value) - for choice, statements in css: - r += "\t"*(level + 1) + _printexpr(ns, choice)[0] + ": begin\n" - r += _printnode(ns, at, level + 2, statements) - r += "\t"*(level + 1) + "end\n" - if "default" in node.cases: - r += "\t"*(level + 1) + "default: begin\n" - r += _printnode(ns, at, level + 2, node.cases["default"]) - r += "\t"*(level + 1) + "end\n" - r += "\t"*level + "endcase\n" - return r - else: - return "" - else: - raise TypeError("Node of unrecognized type: "+str(type(node))) - - -def _list_comb_wires(f): - r = set() - groups = group_by_targets(f.comb) - for g in groups: - if len(g[1]) == 1 and isinstance(g[1][0], _Assign): - r |= g[0] - return r - - -def _printheader(f, ios, name, ns, - reg_initialization): - sigs = list_signals(f) | list_special_ios(f, True, True, True) - special_outs = list_special_ios(f, False, True, True) - inouts = list_special_ios(f, False, False, True) - targets = list_targets(f) | special_outs - wires = _list_comb_wires(f) | special_outs - r = "module " + name + "(\n" - firstp = True - for sig in sorted(ios, key=lambda x: x.duid): - if not firstp: - r += ",\n" - firstp = False - if sig in inouts: - r += "\tinout " + _printsig(ns, sig) - elif sig in targets: - if sig in wires: - r += "\toutput " + _printsig(ns, sig) - else: - r += "\toutput reg " + _printsig(ns, sig) - else: - r += "\tinput " + _printsig(ns, sig) - r += "\n);\n\n" - for sig in sorted(sigs - ios, key=lambda x: x.duid): - if sig in wires: - r += "wire " + _printsig(ns, sig) + ";\n" - else: - if reg_initialization: - r += "reg " + _printsig(ns, sig) + " = " + _printexpr(ns, sig.reset)[0] + ";\n" - else: - r += "reg " + _printsig(ns, sig) + ";\n" - r += "\n" - return r - - -def _printcomb(f, ns, - display_run, - dummy_signal, - blocking_assign): - r = "" - if f.comb: - if dummy_signal: - # Generate a dummy event to get the simulator - # to run the combinatorial process once at the beginning. - syn_off = "// synthesis translate_off\n" - syn_on = "// synthesis translate_on\n" - dummy_s = Signal(name_override="dummy_s") - r += syn_off - r += "reg " + _printsig(ns, dummy_s) + ";\n" - r += "initial " + ns.get_name(dummy_s) + " <= 1'd0;\n" - r += syn_on - - groups = group_by_targets(f.comb) - - for n, g in enumerate(groups): - if len(g[1]) == 1 and isinstance(g[1][0], _Assign): - r += "assign " + _printnode(ns, _AT_BLOCKING, 0, g[1][0]) - else: - if dummy_signal: - dummy_d = Signal(name_override="dummy_d") - r += "\n" + syn_off - r += "reg " + _printsig(ns, dummy_d) + ";\n" - r += syn_on - - r += "always @(*) begin\n" - if display_run: - r += "\t$display(\"Running comb block #" + str(n) + "\");\n" - if blocking_assign: - for t in g[0]: - r += "\t" + ns.get_name(t) + " = " + _printexpr(ns, t.reset)[0] + ";\n" - r += _printnode(ns, _AT_BLOCKING, 1, g[1]) - else: - for t in g[0]: - r += "\t" + ns.get_name(t) + " <= " + _printexpr(ns, t.reset)[0] + ";\n" - r += _printnode(ns, _AT_NONBLOCKING, 1, g[1]) - if dummy_signal: - r += syn_off - r += "\t" + ns.get_name(dummy_d) + " <= " + ns.get_name(dummy_s) + ";\n" - r += syn_on - r += "end\n" - r += "\n" - return r - - -def _printsync(f, ns): - r = "" - for k, v in sorted(f.sync.items(), key=itemgetter(0)): - r += "always @(posedge " + ns.get_name(f.clock_domains[k].clk) + ") begin\n" - r += _printnode(ns, _AT_SIGNAL, 1, v) - r += "end\n\n" - return r - - -def _call_special_classmethod(overrides, obj, method, *args, **kwargs): - cl = obj.__class__ - if cl in overrides: - cl = overrides[cl] - if hasattr(cl, method): - return getattr(cl, method)(obj, *args, **kwargs) - else: - return None - - -def _lower_specials_step(overrides, specials): - f = _Fragment() - lowered_specials = set() - for special in sorted(specials, key=lambda x: x.duid): - impl = _call_special_classmethod(overrides, special, "lower") - if impl is not None: - f += impl.get_fragment() - lowered_specials.add(special) - return f, lowered_specials - - -def _can_lower(overrides, specials): - for special in specials: - cl = special.__class__ - if cl in overrides: - cl = overrides[cl] - if hasattr(cl, "lower"): - return True - return False - - -def _lower_specials(overrides, specials): - f, lowered_specials = _lower_specials_step(overrides, specials) - while _can_lower(overrides, f.specials): - f2, lowered_specials2 = _lower_specials_step(overrides, f.specials) - f += f2 - lowered_specials |= lowered_specials2 - f.specials -= lowered_specials2 - return f, lowered_specials - - -def _printspecials(overrides, specials, ns, add_data_file): - r = "" - for special in sorted(specials, key=lambda x: x.duid): - pr = _call_special_classmethod(overrides, special, "emit_verilog", ns, add_data_file) - if pr is None: - raise NotImplementedError("Special " + str(special) + " failed to implement emit_verilog") - r += pr - return r - - -def convert(f, ios=None, name="top", - special_overrides=dict(), - create_clock_domains=True, - display_run=False, asic_syntax=False): - r = ConvOutput() - if not isinstance(f, _Fragment): - f = f.get_fragment() - if ios is None: - ios = set() - - for cd_name in sorted(list_clock_domains(f)): - try: - f.clock_domains[cd_name] - except KeyError: - if create_clock_domains: - cd = ClockDomain(cd_name) - f.clock_domains.append(cd) - ios |= {cd.clk, cd.rst} - else: - raise KeyError("Unresolved clock domain: '"+cd_name+"'") - - f = lower_complex_slices(f) - insert_resets(f) - f = lower_basics(f) - fs, lowered_specials = _lower_specials(special_overrides, f.specials) - f += lower_basics(fs) - - ns = build_namespace(list_signals(f) \ - | list_special_ios(f, True, True, True) \ - | ios, _reserved_keywords) - ns.clock_domains = f.clock_domains - r.ns = ns - - src = "/* Machine-generated using LiteX */\n" - src += _printheader(f, ios, name, ns, - reg_initialization=not asic_syntax) - src += _printcomb(f, ns, - display_run=display_run, - dummy_signal=not asic_syntax, - blocking_assign=asic_syntax) - src += _printsync(f, ns) - src += _printspecials(special_overrides, f.specials - lowered_specials, ns, r.add_data_file) - src += "endmodule\n" - r.set_main_source(src) - - return r diff --git a/litex/gen/fhdl/visit.py b/litex/gen/fhdl/visit.py deleted file mode 100644 index 0ccd5095..00000000 --- a/litex/gen/fhdl/visit.py +++ /dev/null @@ -1,202 +0,0 @@ -from copy import copy - -from litex.gen.fhdl.structure import * -from litex.gen.fhdl.structure import (_Operator, _Slice, _Assign, _ArrayProxy, - _Fragment) - - -class NodeVisitor: - def visit(self, node): - if isinstance(node, Constant): - self.visit_Constant(node) - elif isinstance(node, Signal): - self.visit_Signal(node) - elif isinstance(node, ClockSignal): - self.visit_ClockSignal(node) - elif isinstance(node, ResetSignal): - self.visit_ResetSignal(node) - elif isinstance(node, _Operator): - self.visit_Operator(node) - elif isinstance(node, _Slice): - self.visit_Slice(node) - elif isinstance(node, Cat): - self.visit_Cat(node) - elif isinstance(node, Replicate): - self.visit_Replicate(node) - elif isinstance(node, _Assign): - self.visit_Assign(node) - elif isinstance(node, If): - self.visit_If(node) - elif isinstance(node, Case): - self.visit_Case(node) - elif isinstance(node, _Fragment): - self.visit_Fragment(node) - elif isinstance(node, (list, tuple)): - self.visit_statements(node) - elif isinstance(node, dict): - self.visit_clock_domains(node) - elif isinstance(node, _ArrayProxy): - self.visit_ArrayProxy(node) - elif node is not None: - self.visit_unknown(node) - - def visit_Constant(self, node): - pass - - def visit_Signal(self, node): - pass - - def visit_ClockSignal(self, node): - pass - - def visit_ResetSignal(self, node): - pass - - def visit_Operator(self, node): - for o in node.operands: - self.visit(o) - - def visit_Slice(self, node): - self.visit(node.value) - - def visit_Cat(self, node): - for e in node.l: - self.visit(e) - - def visit_Replicate(self, node): - self.visit(node.v) - - def visit_Assign(self, node): - self.visit(node.l) - self.visit(node.r) - - def visit_If(self, node): - self.visit(node.cond) - self.visit(node.t) - self.visit(node.f) - - def visit_Case(self, node): - self.visit(node.test) - for v, statements in node.cases.items(): - self.visit(statements) - - def visit_Fragment(self, node): - self.visit(node.comb) - self.visit(node.sync) - - def visit_statements(self, node): - for statement in node: - self.visit(statement) - - def visit_clock_domains(self, node): - for clockname, statements in node.items(): - self.visit(statements) - - def visit_ArrayProxy(self, node): - for choice in node.choices: - self.visit(choice) - self.visit(node.key) - - def visit_unknown(self, node): - pass - - -# Default methods always copy the node, except for: -# - Signals, ClockSignals and ResetSignals -# - Unknown objects -# - All fragment fields except comb and sync -# In those cases, the original node is returned unchanged. -class NodeTransformer: - def visit(self, node): - if isinstance(node, Constant): - return self.visit_Constant(node) - elif isinstance(node, Signal): - return self.visit_Signal(node) - elif isinstance(node, ClockSignal): - return self.visit_ClockSignal(node) - elif isinstance(node, ResetSignal): - return self.visit_ResetSignal(node) - elif isinstance(node, _Operator): - return self.visit_Operator(node) - elif isinstance(node, _Slice): - return self.visit_Slice(node) - elif isinstance(node, Cat): - return self.visit_Cat(node) - elif isinstance(node, Replicate): - return self.visit_Replicate(node) - elif isinstance(node, _Assign): - return self.visit_Assign(node) - elif isinstance(node, If): - return self.visit_If(node) - elif isinstance(node, Case): - return self.visit_Case(node) - elif isinstance(node, _Fragment): - return self.visit_Fragment(node) - elif isinstance(node, (list, tuple)): - return self.visit_statements(node) - elif isinstance(node, dict): - return self.visit_clock_domains(node) - elif isinstance(node, _ArrayProxy): - return self.visit_ArrayProxy(node) - elif node is not None: - return self.visit_unknown(node) - else: - return None - - def visit_Constant(self, node): - return node - - def visit_Signal(self, node): - return node - - def visit_ClockSignal(self, node): - return node - - def visit_ResetSignal(self, node): - return node - - def visit_Operator(self, node): - return _Operator(node.op, [self.visit(o) for o in node.operands]) - - def visit_Slice(self, node): - return _Slice(self.visit(node.value), node.start, node.stop) - - def visit_Cat(self, node): - return Cat(*[self.visit(e) for e in node.l]) - - def visit_Replicate(self, node): - return Replicate(self.visit(node.v), node.n) - - def visit_Assign(self, node): - return _Assign(self.visit(node.l), self.visit(node.r)) - - def visit_If(self, node): - r = If(self.visit(node.cond)) - r.t = self.visit(node.t) - r.f = self.visit(node.f) - return r - - def visit_Case(self, node): - cases = dict((v, self.visit(statements)) for v, statements in node.cases.items()) - r = Case(self.visit(node.test), cases) - return r - - def visit_Fragment(self, node): - r = copy(node) - r.comb = self.visit(node.comb) - r.sync = self.visit(node.sync) - return r - - # NOTE: this will always return a list, even if node is a tuple - def visit_statements(self, node): - return [self.visit(statement) for statement in node] - - def visit_clock_domains(self, node): - return dict((clockname, self.visit(statements)) for clockname, statements in node.items()) - - def visit_ArrayProxy(self, node): - return _ArrayProxy([self.visit(choice) for choice in node.choices], - self.visit(node.key)) - - def visit_unknown(self, node): - return node diff --git a/litex/gen/genlib/__init__.py b/litex/gen/genlib/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/litex/gen/genlib/cdc.py b/litex/gen/genlib/cdc.py deleted file mode 100644 index 90b5f907..00000000 --- a/litex/gen/genlib/cdc.py +++ /dev/null @@ -1,141 +0,0 @@ -from litex.gen.fhdl.structure import * -from litex.gen.fhdl.module import Module -from litex.gen.fhdl.specials import Special -from litex.gen.fhdl.bitcontainer import value_bits_sign -from litex.gen.genlib.misc import WaitTimer - - -class NoRetiming(Special): - def __init__(self, reg): - Special.__init__(self) - self.reg = reg - - # do nothing - @staticmethod - def lower(dr): - return Module() - - -class MultiRegImpl(Module): - def __init__(self, i, o, odomain, n): - self.i = i - self.o = o - self.odomain = odomain - - w, signed = value_bits_sign(self.i) - self.regs = [Signal((w, signed)) for i in range(n)] - - ### - - src = self.i - for reg in self.regs: - sd = getattr(self.sync, self.odomain) - sd += reg.eq(src) - src = reg - self.comb += self.o.eq(src) - self.specials += [NoRetiming(reg) for reg in self.regs] - - -class MultiReg(Special): - def __init__(self, i, o, odomain="sys", n=2): - Special.__init__(self) - self.i = wrap(i) - self.o = wrap(o) - self.odomain = odomain - self.n = n - - def iter_expressions(self): - yield self, "i", SPECIAL_INPUT - yield self, "o", SPECIAL_OUTPUT - - def rename_clock_domain(self, old, new): - Special.rename_clock_domain(self, old, new) - if self.odomain == old: - self.odomain = new - - def list_clock_domains(self): - r = Special.list_clock_domains(self) - r.add(self.odomain) - return r - - @staticmethod - def lower(dr): - return MultiRegImpl(dr.i, dr.o, dr.odomain, dr.n) - - -class PulseSynchronizer(Module): - def __init__(self, idomain, odomain): - self.i = Signal() - self.o = Signal() - - ### - - toggle_i = Signal() - toggle_o = Signal() - toggle_o_r = Signal() - - sync_i = getattr(self.sync, idomain) - sync_o = getattr(self.sync, odomain) - - sync_i += If(self.i, toggle_i.eq(~toggle_i)) - self.specials += MultiReg(toggle_i, toggle_o, odomain) - sync_o += toggle_o_r.eq(toggle_o) - self.comb += self.o.eq(toggle_o ^ toggle_o_r) - - -class BusSynchronizer(Module): - """Clock domain transfer of several bits at once. - - Ensures that all the bits form a single word that was present - synchronously in the input clock domain (unlike direct use of - ``MultiReg``).""" - def __init__(self, width, idomain, odomain, timeout=128): - self.i = Signal(width) - self.o = Signal(width) - - if width == 1: - self.specials += MultiReg(self.i, self.o, odomain) - else: - sync_i = getattr(self.sync, idomain) - sync_o = getattr(self.sync, odomain) - - starter = Signal(reset=1) - sync_i += starter.eq(0) - self.submodules._ping = PulseSynchronizer(idomain, odomain) - self.submodules._pong = PulseSynchronizer(odomain, idomain) - self.submodules._timeout = WaitTimer(timeout) - self.comb += [ - self._timeout.wait.eq(~self._ping.i), - self._ping.i.eq(starter | self._pong.o | self._timeout.done), - self._pong.i.eq(self._ping.i) - ] - - ibuffer = Signal(width) - obuffer = Signal(width) - sync_i += If(self._pong.o, ibuffer.eq(self.i)) - self.specials += MultiReg(ibuffer, obuffer, odomain) - sync_o += If(self._ping.o, self.o.eq(obuffer)) - - -class GrayCounter(Module): - def __init__(self, width): - self.ce = Signal() - self.q = Signal(width) - self.q_next = Signal(width) - self.q_binary = Signal(width) - self.q_next_binary = Signal(width) - - ### - - self.comb += [ - If(self.ce, - self.q_next_binary.eq(self.q_binary + 1) - ).Else( - self.q_next_binary.eq(self.q_binary) - ), - self.q_next.eq(self.q_next_binary ^ self.q_next_binary[1:]) - ] - self.sync += [ - self.q_binary.eq(self.q_next_binary), - self.q.eq(self.q_next) - ] diff --git a/litex/gen/genlib/coding.py b/litex/gen/genlib/coding.py deleted file mode 100644 index 80d62d6d..00000000 --- a/litex/gen/genlib/coding.py +++ /dev/null @@ -1,98 +0,0 @@ -""" -Encoders and decoders between binary and one-hot representation -""" - -from litex.gen.fhdl.structure import * -from litex.gen.fhdl.module import Module - - -class Encoder(Module): - """Encode one-hot to binary - - If `n` is low, the `o` th bit in `i` is asserted, else none or - multiple bits are asserted. - - Parameters - ---------- - width : int - Bit width of the input - - Attributes - ---------- - i : Signal(width), in - One-hot input - o : Signal(max=width), out - Encoded binary - n : Signal(1), out - Invalid, either none or multiple input bits are asserted - """ - def __init__(self, width): - self.i = Signal(width) # one-hot - self.o = Signal(max=max(2, width)) # binary - self.n = Signal() # invalid: none or multiple - act = dict((1< 0: - state = name - for i in range(delay): - if i == delay - 1: - next_state = target - else: - next_state = AnonymousState() - self.act(state, NextState(next_state)) - state = next_state - else: - self.state_aliases[name] = target - - def ongoing(self, state): - is_ongoing = Signal() - self.act(state, is_ongoing.eq(1)) - return is_ongoing - - def _get_signal(self, d, state): - if state not in self.actions: - self.actions[state] = [] - try: - return d[state] - except KeyError: - is_el = Signal() - d[state] = is_el - return is_el - - def before_entering(self, state): - return self._get_signal(self.before_entering_signals, state) - - def before_leaving(self, state): - return self._get_signal(self.before_leaving_signals, state) - - def after_entering(self, state): - signal = self._get_signal(self.after_entering_signals, state) - self.sync += signal.eq(self.before_entering(state)) - return signal - - def after_leaving(self, state): - signal = self._get_signal(self.after_leaving_signals, state) - self.sync += signal.eq(self.before_leaving(state)) - return signal - - def do_finalize(self): - nstates = len(self.actions) - self.encoding = dict((s, n) for n, s in enumerate(self.actions.keys())) - self.state = Signal(max=nstates, reset=self.encoding[self.reset_state]) - self.next_state = Signal(max=nstates) - - ln = _LowerNext(self.next_state, self.encoding, self.state_aliases) - cases = dict((self.encoding[k], ln.visit(v)) for k, v in self.actions.items() if v) - self.comb += [ - self.next_state.eq(self.state), - Case(self.state, cases).makedefault(self.encoding[self.reset_state]) - ] - self.sync += self.state.eq(self.next_state) - for register, next_value_ce, next_value in ln.registers: - self.sync += If(next_value_ce, register.eq(next_value)) - - # drive entering/leaving signals - for state, signal in self.before_leaving_signals.items(): - encoded = self.encoding[state] - self.comb += signal.eq((self.state == encoded) & ~(self.next_state == encoded)) - if self.reset_state in self.after_entering_signals: - self.after_entering_signals[self.reset_state].reset = 1 - for state, signal in self.before_entering_signals.items(): - encoded = self.encoding[state] - self.comb += signal.eq(~(self.state == encoded) & (self.next_state == encoded)) diff --git a/litex/gen/genlib/io.py b/litex/gen/genlib/io.py deleted file mode 100644 index 5c441e66..00000000 --- a/litex/gen/genlib/io.py +++ /dev/null @@ -1,96 +0,0 @@ -from litex.gen.fhdl.structure import * -from litex.gen.fhdl.module import Module -from litex.gen.fhdl.specials import Special - - -class DifferentialInput(Special): - def __init__(self, i_p, i_n, o): - Special.__init__(self) - self.i_p = wrap(i_p) - self.i_n = wrap(i_n) - self.o = wrap(o) - - def iter_expressions(self): - yield self, "i_p", SPECIAL_INPUT - yield self, "i_n", SPECIAL_INPUT - yield self, "o", SPECIAL_OUTPUT - - @staticmethod - def lower(dr): - raise NotImplementedError("Attempted to use a differential input, but platform does not support them") - - -class DifferentialOutput(Special): - def __init__(self, i, o_p, o_n): - Special.__init__(self) - self.i = wrap(i) - self.o_p = wrap(o_p) - self.o_n = wrap(o_n) - - def iter_expressions(self): - yield self, "i", SPECIAL_INPUT - yield self, "o_p", SPECIAL_OUTPUT - yield self, "o_n", SPECIAL_OUTPUT - - @staticmethod - def lower(dr): - raise NotImplementedError("Attempted to use a differential output, but platform does not support them") - - -class CRG(Module): - def __init__(self, clk, rst=0): - self.clock_domains.cd_sys = ClockDomain() - self.clock_domains.cd_por = ClockDomain(reset_less=True) - - if hasattr(clk, "p"): - clk_se = Signal() - self.specials += DifferentialInput(clk.p, clk.n, clk_se) - clk = clk_se - - # Power on Reset (vendor agnostic) - int_rst = Signal(reset=1) - self.sync.por += int_rst.eq(rst) - self.comb += [ - self.cd_sys.clk.eq(clk), - self.cd_por.clk.eq(clk), - self.cd_sys.rst.eq(int_rst) - ] - - -class DDRInput(Special): - def __init__(self, i, o1, o2, clk=ClockSignal()): - Special.__init__(self) - self.i = wrap(i) - self.o1 = wrap(o1) - self.o2 = wrap(o2) - self.clk = wrap(clk) - - def iter_expressions(self): - yield self, "i", SPECIAL_INPUT - yield self, "o1", SPECIAL_OUTPUT - yield self, "o2", SPECIAL_OUTPUT - yield self, "clk", SPECIAL_INPUT - - @staticmethod - def lower(dr): - raise NotImplementedError("Attempted to use a DDR input, but platform does not support them") - - -class DDROutput(Special): - def __init__(self, i1, i2, o, clk=ClockSignal()): - Special.__init__(self) - self.i1 = i1 - self.i2 = i2 - self.o = o - self.clk = clk - - def iter_expressions(self): - yield self, "i1", SPECIAL_INPUT - yield self, "i2", SPECIAL_INPUT - yield self, "o", SPECIAL_OUTPUT - yield self, "clk", SPECIAL_INPUT - - @staticmethod - def lower(dr): - raise NotImplementedError("Attempted to use a DDR output, but platform does not support them") - diff --git a/litex/gen/genlib/misc.py b/litex/gen/genlib/misc.py deleted file mode 100644 index 42ad878c..00000000 --- a/litex/gen/genlib/misc.py +++ /dev/null @@ -1,88 +0,0 @@ -from litex.gen.fhdl.structure import * -from litex.gen.fhdl.module import Module -from litex.gen.fhdl.bitcontainer import bits_for - - -def split(v, *counts): - r = [] - offset = 0 - for n in counts: - if n != 0: - r.append(v[offset:offset+n]) - else: - r.append(None) - offset += n - return tuple(r) - - -def displacer(signal, shift, output, n=None, reverse=False): - if shift is None: - return output.eq(signal) - if n is None: - n = 2**len(shift) - w = len(signal) - if reverse: - r = reversed(range(n)) - else: - r = range(n) - l = [Replicate(shift == i, w) & signal for i in r] - return output.eq(Cat(*l)) - - -def chooser(signal, shift, output, n=None, reverse=False): - if shift is None: - return output.eq(signal) - if n is None: - n = 2**len(shift) - w = len(output) - cases = {} - for i in range(n): - if reverse: - s = n - i - 1 - else: - s = i - cases[i] = [output.eq(signal[s*w:(s+1)*w])] - return Case(shift, cases).makedefault() - - -def timeline(trigger, events): - lastevent = max([e[0] for e in events]) - counter = Signal(max=lastevent+1) - - counterlogic = If(counter != 0, - counter.eq(counter + 1) - ).Elif(trigger, - counter.eq(1) - ) - # insert counter reset if it doesn't naturally overflow - # (test if lastevent+1 is a power of 2) - if (lastevent & (lastevent + 1)) != 0: - counterlogic = If(counter == lastevent, - counter.eq(0) - ).Else( - counterlogic - ) - - def get_cond(e): - if e[0] == 0: - return trigger & (counter == 0) - else: - return counter == e[0] - sync = [If(get_cond(e), *e[1]) for e in events] - sync.append(counterlogic) - return sync - - -class WaitTimer(Module): - def __init__(self, t): - self.wait = Signal() - self.done = Signal() - - # # # - - count = Signal(bits_for(t), reset=t) - self.comb += self.done.eq(count == 0) - self.sync += \ - If(self.wait, - If(~self.done, count.eq(count - 1)) - ).Else(count.eq(count.reset)) diff --git a/litex/gen/genlib/record.py b/litex/gen/genlib/record.py deleted file mode 100644 index 0038b069..00000000 --- a/litex/gen/genlib/record.py +++ /dev/null @@ -1,179 +0,0 @@ -from litex.gen.fhdl.structure import * -from litex.gen.fhdl.tracer import get_obj_var_name - -from functools import reduce -from operator import or_ - - -(DIR_NONE, DIR_S_TO_M, DIR_M_TO_S) = range(3) - -# Possible layout elements: -# 1. (name, size) -# 2. (name, size, direction) -# 3. (name, sublayout) -# size can be an int, or a (int, bool) tuple for signed numbers -# sublayout must be a list - - -def set_layout_parameters(layout, **layout_dict): - def resolve(p): - if isinstance(p, str): - try: - return layout_dict[p] - except KeyError: - return p - else: - return p - - r = [] - for f in layout: - if isinstance(f[1], (int, tuple, str)): # cases 1/2 - if len(f) == 3: - r.append((f[0], resolve(f[1]), f[2])) - else: - r.append((f[0], resolve(f[1]))) - elif isinstance(f[1], list): # case 3 - r.append((f[0], set_layout_parameters(f[1], **layout_dict))) - else: - raise TypeError - return r - - -def layout_len(layout): - r = 0 - for f in layout: - if isinstance(f[1], (int, tuple)): # cases 1/2 - if len(f) == 3: - fname, fsize, fdirection = f - else: - fname, fsize = f - elif isinstance(f[1], list): # case 3 - fname, fsublayout = f - fsize = layout_len(fsublayout) - else: - raise TypeError - if isinstance(fsize, tuple): - r += fsize[0] - else: - r += fsize - return r - - -def layout_get(layout, name): - for f in layout: - if f[0] == name: - return f - raise KeyError(name) - - -def layout_partial(layout, *elements): - r = [] - for path in elements: - path_s = path.split("/") - last = path_s.pop() - copy_ref = layout - insert_ref = r - for hop in path_s: - name, copy_ref = layout_get(copy_ref, hop) - try: - name, insert_ref = layout_get(insert_ref, hop) - except KeyError: - new_insert_ref = [] - insert_ref.append((hop, new_insert_ref)) - insert_ref = new_insert_ref - insert_ref.append(layout_get(copy_ref, last)) - return r - - -class Record: - def __init__(self, layout, name=None): - self.name = get_obj_var_name(name, "") - self.layout = layout - - if self.name: - prefix = self.name + "_" - else: - prefix = "" - for f in self.layout: - if isinstance(f[1], (int, tuple)): # cases 1/2 - if(len(f) == 3): - fname, fsize, fdirection = f - else: - fname, fsize = f - finst = Signal(fsize, name=prefix + fname) - elif isinstance(f[1], list): # case 3 - fname, fsublayout = f - finst = Record(fsublayout, prefix + fname) - else: - raise TypeError - setattr(self, fname, finst) - - def eq(self, other): - return [getattr(self, f[0]).eq(getattr(other, f[0])) - for f in self.layout if hasattr(other, f[0])] - - def iter_flat(self): - for f in self.layout: - e = getattr(self, f[0]) - if isinstance(e, Signal): - if len(f) == 3: - yield e, f[2] - else: - yield e, DIR_NONE - elif isinstance(e, Record): - yield from e.iter_flat() - else: - raise TypeError - - def flatten(self): - return [signal for signal, direction in self.iter_flat()] - - def raw_bits(self): - return Cat(*self.flatten()) - - def connect(self, *slaves, leave_out=set()): - if isinstance(leave_out, str): - leave_out = {leave_out} - r = [] - for f in self.layout: - field = f[0] - if field not in leave_out: - self_e = getattr(self, field) - if isinstance(self_e, Signal): - direction = f[2] - if direction == DIR_M_TO_S: - r += [getattr(slave, field).eq(self_e) for slave in slaves] - elif direction == DIR_S_TO_M: - r.append(self_e.eq(reduce(or_, [getattr(slave, field) for slave in slaves]))) - else: - raise TypeError - else: - for slave in slaves: - r += self_e.connect(getattr(slave, field), leave_out=leave_out) - return r - - def connect_flat(self, *slaves): - r = [] - iter_slaves = [slave.iter_flat() for slave in slaves] - for m_signal, m_direction in self.iter_flat(): - if m_direction == DIR_M_TO_S: - for iter_slave in iter_slaves: - s_signal, s_direction = next(iter_slave) - assert(s_direction == DIR_M_TO_S) - r.append(s_signal.eq(m_signal)) - elif m_direction == DIR_S_TO_M: - s_signals = [] - for iter_slave in iter_slaves: - s_signal, s_direction = next(iter_slave) - assert(s_direction == DIR_S_TO_M) - s_signals.append(s_signal) - r.append(m_signal.eq(reduce(or_, s_signals))) - else: - raise TypeError - return r - - def __len__(self): - return layout_len(self.layout) - - def __repr__(self): - return "" diff --git a/litex/gen/genlib/resetsync.py b/litex/gen/genlib/resetsync.py deleted file mode 100644 index 061f65bc..00000000 --- a/litex/gen/genlib/resetsync.py +++ /dev/null @@ -1,18 +0,0 @@ -from litex.gen.fhdl.structure import * -from litex.gen.fhdl.specials import Special - - -class AsyncResetSynchronizer(Special): - def __init__(self, cd, async_reset): - Special.__init__(self) - self.cd = cd - self.async_reset = wrap(async_reset) - - def iter_expressions(self): - yield self.cd, "clk", SPECIAL_INPUT - yield self.cd, "rst", SPECIAL_OUTPUT - yield self, "async_reset", SPECIAL_INPUT - - @staticmethod - def lower(dr): - raise NotImplementedError("Attempted to use a reset synchronizer, but platform does not support them") diff --git a/litex/gen/genlib/roundrobin.py b/litex/gen/genlib/roundrobin.py deleted file mode 100644 index b9903dbb..00000000 --- a/litex/gen/genlib/roundrobin.py +++ /dev/null @@ -1,41 +0,0 @@ -from litex.gen.fhdl.structure import * -from litex.gen.fhdl.module import Module - - -(SP_WITHDRAW, SP_CE) = range(2) - - -class RoundRobin(Module): - def __init__(self, n, switch_policy=SP_WITHDRAW): - self.request = Signal(n) - self.grant = Signal(max=max(2, n)) - self.switch_policy = switch_policy - if self.switch_policy == SP_CE: - self.ce = Signal() - - ### - - if n > 1: - cases = {} - for i in range(n): - switch = [] - for j in reversed(range(i+1, i+n)): - t = j % n - switch = [ - If(self.request[t], - self.grant.eq(t) - ).Else( - *switch - ) - ] - if self.switch_policy == SP_WITHDRAW: - case = [If(~self.request[i], *switch)] - else: - case = switch - cases[i] = case - statement = Case(self.grant, cases) - if self.switch_policy == SP_CE: - statement = If(self.ce, statement) - self.sync += statement - else: - self.comb += self.grant.eq(0) diff --git a/litex/gen/genlib/sort.py b/litex/gen/genlib/sort.py deleted file mode 100644 index ff5b6175..00000000 --- a/litex/gen/genlib/sort.py +++ /dev/null @@ -1,71 +0,0 @@ -from litex.gen.fhdl.structure import * -from litex.gen.fhdl.module import Module - - -class BitonicSort(Module): - """Combinatorial sorting network - - The Bitonic sort is implemented as a combinatorial sort using - comparators and multiplexers. Its asymptotic complexity (in terms of - number of comparators/muxes) is O(n log(n)**2), like mergesort or - shellsort. - - http://www.dps.uibk.ac.at/~cosenza/teaching/gpu/sort-batcher.pdf - - http://www.inf.fh-flensburg.de/lang/algorithmen/sortieren/bitonic/bitonicen.htm - - http://www.myhdl.org/doku.php/cookbook:bitonic - - Parameters - ---------- - n : int - Number of inputs and output signals. - m : int - Bit width of inputs and outputs. Or a tuple of `(m, signed)`. - ascending : bool - Sort direction. `True` if input is to be sorted ascending, - `False` for descending. Defaults to ascending. - - Attributes - ---------- - i : list of Signals, in - Input values, each `m` wide. - o : list of Signals, out - Output values, sorted, each `m` bits wide. - """ - def __init__(self, n, m, ascending=True): - self.i = [Signal(m) for i in range(n)] - self.o = [Signal(m) for i in range(n)] - self._sort(self.i, self.o, int(ascending), m) - - def _sort_two(self, i0, i1, o0, o1, dir): - self.comb += [ - o0.eq(i0), - o1.eq(i1), - If(dir == (i0 > i1), - o0.eq(i1), - o1.eq(i0), - )] - - def _merge(self, i, o, dir, m): - n = len(i) - k = n//2 - if n > 1: - t = [Signal(m) for j in range(n)] - for j in range(k): - self._sort_two(i[j], i[j + k], t[j], t[j + k], dir) - self._merge(t[:k], o[:k], dir, m) - self._merge(t[k:], o[k:], dir, m) - else: - self.comb += o[0].eq(i[0]) - - def _sort(self, i, o, dir, m): - n = len(i) - k = n//2 - if n > 1: - t = [Signal(m) for j in range(n)] - self._sort(i[:k], t[:k], 1, m) # ascending - self._sort(i[k:], t[k:], 0, m) # descending - self._merge(t, o, dir, m) - else: - self.comb += o[0].eq(i[0]) diff --git a/litex/gen/sim/__init__.py b/litex/gen/sim/__init__.py deleted file mode 100644 index 327f1c88..00000000 --- a/litex/gen/sim/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from litex.gen.sim.core import Simulator, run_simulation diff --git a/litex/gen/sim/core.py b/litex/gen/sim/core.py deleted file mode 100644 index dbafc711..00000000 --- a/litex/gen/sim/core.py +++ /dev/null @@ -1,335 +0,0 @@ -import operator -import collections -import inspect - -from litex.gen.fhdl.structure import * -from litex.gen.fhdl.structure import (_Value, _Statement, - _Operator, _Slice, _ArrayProxy, - _Assign, _Fragment) -from litex.gen.fhdl.bitcontainer import value_bits_sign -from litex.gen.fhdl.tools import list_signals, list_targets, insert_resets -from litex.gen.fhdl.simplify import MemoryToArray -from litex.gen.fhdl.specials import _MemoryLocation -from litex.gen.sim.vcd import VCDWriter, DummyVCDWriter - - -class ClockState: - def __init__(self, high, half_period, time_before_trans): - self.high = high - self.half_period = half_period - self.time_before_trans = time_before_trans - - -class TimeManager: - def __init__(self, description): - self.clocks = dict() - - for k, period_phase in description.items(): - if isinstance(period_phase, tuple): - period, phase = period_phase - else: - period = period_phase - phase = 0 - half_period = period//2 - if phase >= half_period: - phase -= half_period - high = True - else: - high = False - self.clocks[k] = ClockState(high, half_period, half_period - phase) - - def tick(self): - rising = set() - falling = set() - dt = min(cs.time_before_trans for cs in self.clocks.values()) - for k, cs in self.clocks.items(): - if cs.time_before_trans == dt: - cs.high = not cs.high - if cs.high: - rising.add(k) - else: - falling.add(k) - cs.time_before_trans -= dt - if not cs.time_before_trans: - cs.time_before_trans += cs.half_period - return dt, rising, falling - - -str2op = { - "~": operator.invert, - "+": operator.add, - "-": operator.sub, - "*": operator.mul, - - ">>>": operator.rshift, - "<<<": operator.lshift, - - "&": operator.and_, - "^": operator.xor, - "|": operator.or_, - - "<": operator.lt, - "<=": operator.le, - "==": operator.eq, - "!=": operator.ne, - ">": operator.gt, - ">=": operator.ge, -} - - -def _truncate(value, nbits, signed): - value = value & (2**nbits - 1) - if signed and (value & 2**(nbits - 1)): - value -= 2**nbits - return value - - -class Evaluator: - def __init__(self, clock_domains, replaced_memories): - self.clock_domains = clock_domains - self.replaced_memories = replaced_memories - self.signal_values = dict() - self.modifications = dict() - - def commit(self): - r = set() - for k, v in self.modifications.items(): - if k not in self.signal_values or self.signal_values[k] != v: - self.signal_values[k] = v - r.add(k) - self.modifications.clear() - return r - - def eval(self, node, postcommit=False): - if isinstance(node, Constant): - return node.value - elif isinstance(node, Signal): - if postcommit: - try: - return self.modifications[node] - except KeyError: - pass - try: - return self.signal_values[node] - except KeyError: - return node.reset.value - elif isinstance(node, _Operator): - operands = [self.eval(o, postcommit) for o in node.operands] - if node.op == "-": - if len(operands) == 1: - return -operands[0] - else: - return operands[0] - operands[1] - elif node.op == "m": - return operands[1] if operands[0] else operands[2] - else: - return str2op[node.op](*operands) - elif isinstance(node, _Slice): - v = self.eval(node.value, postcommit) - idx = range(node.start, node.stop) - return sum(((v >> i) & 1) << j for j, i in enumerate(idx)) - elif isinstance(node, Cat): - shift = 0 - r = 0 - for element in node.l: - nbits = len(element) - # make value always positive - r |= (self.eval(element, postcommit) & (2**nbits-1)) << shift - shift += nbits - return r - elif isinstance(node, _ArrayProxy): - return self.eval(node.choices[self.eval(node.key, postcommit)], - postcommit) - elif isinstance(node, _MemoryLocation): - array = self.replaced_memories[node.memory] - return self.eval(array[self.eval(node.index, postcommit)], postcommit) - elif isinstance(node, ClockSignal): - return self.eval(self.clock_domains[node.cd].clk, postcommit) - elif isinstance(node, ResetSignal): - rst = self.clock_domains[node.cd].rst - if rst is None: - if node.allow_reset_less: - return 0 - else: - raise ValueError("Attempted to get reset signal of resetless" - " domain '{}'".format(node.cd)) - else: - return self.eval(rst, postcommit) - else: - raise NotImplementedError - - def assign(self, node, value): - if isinstance(node, Signal): - assert not node.variable - self.modifications[node] = _truncate(value, - node.nbits, node.signed) - elif isinstance(node, Cat): - for element in node.l: - nbits = len(element) - self.assign(element, value & (2**nbits-1)) - value >>= nbits - elif isinstance(node, _Slice): - full_value = self.eval(node.value, True) - # clear bits assigned to by the slice - full_value &= ~((2**node.stop-1) - (2**node.start-1)) - # set them to the new value - value &= 2**(node.stop - node.start)-1 - full_value |= value << node.start - self.assign(node.value, full_value) - elif isinstance(node, _ArrayProxy): - self.assign(node.choices[self.eval(node.key)], value) - elif isinstance(node, _MemoryLocation): - array = self.replaced_memories[node.memory] - self.assign(array[self.eval(node.index)], value) - else: - raise NotImplementedError - - def execute(self, statements): - for s in statements: - if isinstance(s, _Assign): - self.assign(s.l, self.eval(s.r)) - elif isinstance(s, If): - if self.eval(s.cond) & (2**len(s.cond) - 1): - self.execute(s.t) - else: - self.execute(s.f) - elif isinstance(s, Case): - nbits, signed = value_bits_sign(s.test) - test = _truncate(self.eval(s.test), nbits, signed) - found = False - for k, v in s.cases.items(): - if isinstance(k, Constant) and k.value == test: - self.execute(v) - found = True - break - if not found and "default" in s.cases: - self.execute(s.cases["default"]) - elif isinstance(s, collections.Iterable): - self.execute(s) - else: - raise NotImplementedError - - -# TODO: instances via Iverilog/VPI -class Simulator: - def __init__(self, fragment_or_module, generators, clocks={"sys": 10}, vcd_name=None): - if isinstance(fragment_or_module, _Fragment): - self.fragment = fragment_or_module - else: - self.fragment = fragment_or_module.get_fragment() - if not isinstance(generators, dict): - generators = {"sys": generators} - self.generators = dict() - for k, v in generators.items(): - if (isinstance(v, collections.Iterable) - and not inspect.isgenerator(v)): - self.generators[k] = list(v) - else: - self.generators[k] = [v] - - self.time = TimeManager(clocks) - for clock in clocks.keys(): - if clock not in self.fragment.clock_domains: - cd = ClockDomain(name=clock, reset_less=True) - cd.clk.reset = C(self.time.clocks[clock].high) - self.fragment.clock_domains.append(cd) - - mta = MemoryToArray() - mta.transform_fragment(None, self.fragment) - insert_resets(self.fragment) - # comb signals return to their reset value if nothing assigns them - self.fragment.comb[0:0] = [s.eq(s.reset) - for s in list_targets(self.fragment.comb)] - self.evaluator = Evaluator(self.fragment.clock_domains, - mta.replacements) - - if vcd_name is None: - self.vcd = DummyVCDWriter() - else: - signals = list_signals(self.fragment) - for cd in self.fragment.clock_domains: - signals.add(cd.clk) - if cd.rst is not None: - signals.add(cd.rst) - for memory_array in mta.replacements.values(): - signals |= set(memory_array) - signals = sorted(signals, key=lambda x: x.duid) - self.vcd = VCDWriter(vcd_name, signals) - - def __enter__(self): - return self - - def __exit__(self, type, value, traceback): - self.close() - - def close(self): - self.vcd.close() - - def _commit_and_comb_propagate(self): - # TODO: optimize - all_modified = set() - modified = self.evaluator.commit() - all_modified |= modified - while modified: - self.evaluator.execute(self.fragment.comb) - modified = self.evaluator.commit() - all_modified |= modified - for signal in all_modified: - self.vcd.set(signal, self.evaluator.signal_values[signal]) - - def _evalexec_nested_lists(self, x): - if isinstance(x, list): - return [self._evalexec_nested_lists(e) for e in x] - elif isinstance(x, _Value): - return self.evaluator.eval(x) - elif isinstance(x, _Statement): - self.evaluator.execute([x]) - return None - else: - raise ValueError - - def _process_generators(self, cd): - exhausted = [] - for generator in self.generators[cd]: - reply = None - while True: - try: - request = generator.send(reply) - if request is None: - break # next cycle - else: - reply = self._evalexec_nested_lists(request) - except StopIteration: - exhausted.append(generator) - break - for generator in exhausted: - self.generators[cd].remove(generator) - - def _continue_simulation(self): - # TODO: passive generators - return any(self.generators.values()) - - def run(self): - self.evaluator.execute(self.fragment.comb) - self._commit_and_comb_propagate() - - while True: - dt, rising, falling = self.time.tick() - self.vcd.delay(dt) - for cd in rising: - self.evaluator.assign(self.fragment.clock_domains[cd].clk, 1) - if cd in self.fragment.sync: - self.evaluator.execute(self.fragment.sync[cd]) - if cd in self.generators: - self._process_generators(cd) - for cd in falling: - self.evaluator.assign(self.fragment.clock_domains[cd].clk, 0) - self._commit_and_comb_propagate() - - if not self._continue_simulation(): - break - - -def run_simulation(*args, **kwargs): - with Simulator(*args, **kwargs) as s: - s.run() diff --git a/litex/gen/sim/vcd.py b/litex/gen/sim/vcd.py deleted file mode 100644 index 335486bd..00000000 --- a/litex/gen/sim/vcd.py +++ /dev/null @@ -1,75 +0,0 @@ -from itertools import count - -from litex.gen.fhdl.namer import build_namespace - - -def vcd_codes(): - codechars = [chr(i) for i in range(33, 127)] - for n in count(): - q, r = divmod(n, len(codechars)) - code = codechars[r] - while q > 0: - q, r = divmod(q, len(codechars)) - code = codechars[r] + code - yield code - - -class VCDWriter: - def __init__(self, filename, signals): - self.fo = open(filename, "w") - self.codes = dict() - self.signal_values = dict() - self.t = 0 - - try: - ns = build_namespace(signals) - codes = vcd_codes() - for signal in signals: - name = ns.get_name(signal) - code = next(codes) - self.codes[signal] = code - self.fo.write("$var wire {len} {code} {name} $end\n" - .format(name=name, code=code, len=len(signal))) - self.fo.write("$dumpvars\n") - for signal in signals: - value = signal.reset.value - self._write_value(signal, value) - self.signal_values[signal] = value - self.fo.write("$end\n") - self.fo.write("#0\n") - except: - self.close() - raise - - def _write_value(self, signal, value): - l = len(signal) - if value < 0: - value += 2**l - if l > 1: - fmtstr = "b{:0" + str(l) + "b} {}\n" - else: - fmtstr = "{}{}\n" - self.fo.write(fmtstr.format(value, self.codes[signal])) - - def set(self, signal, value): - if self.signal_values[signal] != value: - self._write_value(signal, value) - self.signal_values[signal] = value - - def delay(self, delay): - self.t += delay - self.fo.write("#{}\n".format(self.t)) - - def close(self): - self.fo.close() - - -class DummyVCDWriter: - def set(self, signal, value): - pass - - def delay(self, delay): - pass - - def close(self): - pass diff --git a/litex/gen/util/__init__.py b/litex/gen/util/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/litex/gen/util/misc.py b/litex/gen/util/misc.py deleted file mode 100644 index ff2240bc..00000000 --- a/litex/gen/util/misc.py +++ /dev/null @@ -1,29 +0,0 @@ -from fractions import gcd -import collections - - -def flat_iteration(l): - for element in l: - if isinstance(element, collections.Iterable): - for element2 in flat_iteration(element): - yield element2 - else: - yield element - - -def xdir(obj, return_values=False): - for attr in dir(obj): - if attr[:2] != "__" and attr[-2:] != "__": - if return_values: - yield attr, getattr(obj, attr) - else: - yield attr - - -def gcd_multiple(numbers): - l = len(numbers) - if l == 1: - return numbers[0] - else: - s = l//2 - return gcd(gcd_multiple(numbers[:s]), gcd_multiple(numbers[s:])) diff --git a/litex/soc/cores/cpu/lm32/core.py b/litex/soc/cores/cpu/lm32/core.py index 7d590c84..e4d6e697 100644 --- a/litex/soc/cores/cpu/lm32/core.py +++ b/litex/soc/cores/cpu/lm32/core.py @@ -1,6 +1,6 @@ import os -from litex.gen import * +from migen import * from litex.soc.interconnect import wishbone diff --git a/litex/soc/cores/cpu/mor1kx/core.py b/litex/soc/cores/cpu/mor1kx/core.py index 8511fff5..f2036d81 100644 --- a/litex/soc/cores/cpu/mor1kx/core.py +++ b/litex/soc/cores/cpu/mor1kx/core.py @@ -1,6 +1,6 @@ import os -from litex.gen import * +from migen import * from litex.soc.interconnect import wishbone diff --git a/litex/soc/cores/flash/nor_flash_16.py b/litex/soc/cores/flash/nor_flash_16.py index 3027882a..fa6e0c08 100644 --- a/litex/soc/cores/flash/nor_flash_16.py +++ b/litex/soc/cores/flash/nor_flash_16.py @@ -1,5 +1,5 @@ -from litex.gen import * -from litex.gen.genlib.fsm import FSM, NextState +from migen import * +from migen.genlib.fsm import FSM, NextState from litex.soc.interconnect import wishbone diff --git a/litex/soc/cores/flash/spi_flash.py b/litex/soc/cores/flash/spi_flash.py index 69b86004..289ef39b 100644 --- a/litex/soc/cores/flash/spi_flash.py +++ b/litex/soc/cores/flash/spi_flash.py @@ -1,5 +1,5 @@ -from litex.gen import * -from litex.gen.genlib.misc import timeline +from migen import * +from migen.genlib.misc import timeline from litex.soc.interconnect import wishbone from litex.soc.interconnect.csr import AutoCSR, CSRStorage, CSRStatus diff --git a/litex/soc/cores/gpio.py b/litex/soc/cores/gpio.py index 463e1e20..89ccd54d 100644 --- a/litex/soc/cores/gpio.py +++ b/litex/soc/cores/gpio.py @@ -1,5 +1,5 @@ -from litex.gen import * -from litex.gen.genlib.cdc import MultiReg +from migen import * +from migen.genlib.cdc import MultiReg from litex.soc.interconnect.csr import * diff --git a/litex/soc/cores/identifier.py b/litex/soc/cores/identifier.py index 5baedca1..c63840b9 100644 --- a/litex/soc/cores/identifier.py +++ b/litex/soc/cores/identifier.py @@ -1,4 +1,4 @@ -from litex.gen import * +from migen import * class Identifier(Module): diff --git a/litex/soc/cores/sdram/lasmicon/bankmachine.py b/litex/soc/cores/sdram/lasmicon/bankmachine.py index 7a9b26c8..06fc10da 100644 --- a/litex/soc/cores/sdram/lasmicon/bankmachine.py +++ b/litex/soc/cores/sdram/lasmicon/bankmachine.py @@ -1,7 +1,7 @@ -from litex.gen import * -from litex.gen.genlib.roundrobin import * -from litex.gen.genlib.fsm import FSM, NextState -from litex.gen.genlib.fifo import SyncFIFO +from migen import * +from migen.genlib.roundrobin import * +from migen.genlib.fsm import FSM, NextState +from migen.genlib.fifo import SyncFIFO from litex.soc.cores.sdram.lasmicon.multiplexer import * diff --git a/litex/soc/cores/sdram/lasmicon/core.py b/litex/soc/cores/sdram/lasmicon/core.py index a6625015..dc358b60 100644 --- a/litex/soc/cores/sdram/lasmicon/core.py +++ b/litex/soc/cores/sdram/lasmicon/core.py @@ -1,4 +1,4 @@ -from litex.gen import * +from migen import * from litex.soc.interconnect import dfi, lasmi_bus from litex.soc.cores.sdram.lasmicon.refresher import * diff --git a/litex/soc/cores/sdram/lasmicon/multiplexer.py b/litex/soc/cores/sdram/lasmicon/multiplexer.py index af118c50..66987e07 100644 --- a/litex/soc/cores/sdram/lasmicon/multiplexer.py +++ b/litex/soc/cores/sdram/lasmicon/multiplexer.py @@ -1,9 +1,9 @@ from functools import reduce from operator import or_, and_ -from litex.gen import * -from litex.gen.genlib.roundrobin import * -from litex.gen.genlib.fsm import FSM, NextState +from migen import * +from migen.genlib.roundrobin import * +from migen.genlib.fsm import FSM, NextState from litex.soc.cores.sdram.lasmicon.perf import Bandwidth from litex.soc.interconnect.csr import AutoCSR diff --git a/litex/soc/cores/sdram/lasmicon/perf.py b/litex/soc/cores/sdram/lasmicon/perf.py index dbd62d3a..1e86285e 100644 --- a/litex/soc/cores/sdram/lasmicon/perf.py +++ b/litex/soc/cores/sdram/lasmicon/perf.py @@ -1,4 +1,4 @@ -from litex.gen import * +from migen import * from litex.soc.interconnect.csr import * diff --git a/litex/soc/cores/sdram/lasmicon/refresher.py b/litex/soc/cores/sdram/lasmicon/refresher.py index e4c5da92..5de9b35d 100644 --- a/litex/soc/cores/sdram/lasmicon/refresher.py +++ b/litex/soc/cores/sdram/lasmicon/refresher.py @@ -1,6 +1,6 @@ -from litex.gen import * -from litex.gen.genlib.misc import timeline -from litex.gen.genlib.fsm import FSM +from migen import * +from migen.genlib.misc import timeline +from migen.genlib.fsm import FSM from litex.soc.cores.sdram.lasmicon.multiplexer import * diff --git a/litex/soc/cores/sdram/minicon/core.py b/litex/soc/cores/sdram/minicon/core.py index 13600b7f..cc5800d0 100644 --- a/litex/soc/cores/sdram/minicon/core.py +++ b/litex/soc/cores/sdram/minicon/core.py @@ -1,9 +1,9 @@ from functools import reduce from operator import or_ -from litex.gen import * -from litex.gen.genlib.fsm import FSM, NextState -from litex.gen.genlib.misc import WaitTimer +from migen import * +from migen.genlib.fsm import FSM, NextState +from migen.genlib.misc import WaitTimer from litex.soc.interconnect import dfi as dfibus from litex.soc.interconnect import wishbone diff --git a/litex/soc/cores/sdram/model.py b/litex/soc/cores/sdram/model.py index a8792250..7f9a9291 100644 --- a/litex/soc/cores/sdram/model.py +++ b/litex/soc/cores/sdram/model.py @@ -6,8 +6,8 @@ # TODO: # - add $display support to LiteX gen and manage timing violations? -from litex.gen import * -from litex.gen.fhdl.specials import * +from migen import * +from migen.fhdl.specials import * from litex.soc.interconnect.dfi import * from functools import reduce diff --git a/litex/soc/cores/sdram/phy/gensdrphy.py b/litex/soc/cores/sdram/phy/gensdrphy.py index 303faeb0..799be7e0 100644 --- a/litex/soc/cores/sdram/phy/gensdrphy.py +++ b/litex/soc/cores/sdram/phy/gensdrphy.py @@ -21,9 +21,9 @@ # This PHY only supports CAS Latency 2. # -from litex.gen import * -from litex.gen.genlib.record import * -from litex.gen.fhdl.specials import Tristate +from migen import * +from migen.genlib.record import * +from migen.fhdl.specials import Tristate from litex.soc.interconnect.dfi import * from litex.soc.cores.sdram import settings as sdram_settings diff --git a/litex/soc/cores/sdram/phy/k7ddrphy.py b/litex/soc/cores/sdram/phy/k7ddrphy.py index 385bbc9b..7bd4df85 100644 --- a/litex/soc/cores/sdram/phy/k7ddrphy.py +++ b/litex/soc/cores/sdram/phy/k7ddrphy.py @@ -1,6 +1,6 @@ # tCK=5ns CL=7 CWL=6 -from litex.gen import * +from migen import * from litex.soc.interconnect.dfi import * from litex.soc.interconnect.csr import * diff --git a/litex/soc/cores/sdram/phy/s6ddrphy.py b/litex/soc/cores/sdram/phy/s6ddrphy.py index dfd3e0a2..4781736e 100644 --- a/litex/soc/cores/sdram/phy/s6ddrphy.py +++ b/litex/soc/cores/sdram/phy/s6ddrphy.py @@ -19,8 +19,8 @@ from functools import reduce from operator import or_ -from litex.gen import * -from litex.gen.genlib.record import * +from migen import * +from migen.genlib.record import * from litex.soc.interconnect.dfi import * from litex.soc.cores.sdram import settings as sdram_settings diff --git a/litex/soc/cores/sdram/settings.py b/litex/soc/cores/sdram/settings.py index 0e99ac12..ce575a4a 100644 --- a/litex/soc/cores/sdram/settings.py +++ b/litex/soc/cores/sdram/settings.py @@ -1,7 +1,7 @@ from math import ceil from collections import namedtuple -from litex.gen import * +from migen import * PhySettingsT = namedtuple("PhySettings", "memtype dfi_databits nphases rdphase wrphase rdcmdphase wrcmdphase cl cwl read_latency write_latency") diff --git a/litex/soc/cores/sdram/tester.py b/litex/soc/cores/sdram/tester.py index 28b0318e..6036bff9 100644 --- a/litex/soc/cores/sdram/tester.py +++ b/litex/soc/cores/sdram/tester.py @@ -1,7 +1,7 @@ from functools import reduce from operator import xor -from litex.gen import * +from migen import * from litex.soc.interconnect.csr import * from litex.soc.interconnect import dma_lasmi @@ -114,8 +114,8 @@ class _LFSRTB(Module): print("{0:032x}".format(selfp.dut.o)) if __name__ == "__main__": - from litex.gen.fhdl import verilog - from litex.gen.sim.generic import run_simulation + from migen.fhdl import verilog + from migen.sim.generic import run_simulation lfsr = LFSR(3, 4, [3, 2]) print(verilog.convert(lfsr, ios={lfsr.ce, lfsr.reset, lfsr.o})) diff --git a/litex/soc/cores/spi/core.py b/litex/soc/cores/spi/core.py index 56db5020..1658d949 100644 --- a/litex/soc/cores/spi/core.py +++ b/litex/soc/cores/spi/core.py @@ -1,6 +1,6 @@ -from litex.gen import * -from litex.gen.bank.description import * -from litex.gen.genlib.fsm import FSM, NextState +from migen import * +from migen.bank.description import * +from migen.genlib.fsm import FSM, NextState class SPIMaster(Module, AutoCSR): diff --git a/litex/soc/cores/spi/test.py b/litex/soc/cores/spi/test.py index bed69b14..06560083 100644 --- a/litex/soc/cores/spi/test.py +++ b/litex/soc/cores/spi/test.py @@ -1,6 +1,6 @@ -from litex.gen import * -from litex.gen.genlib.record import * -from litex.gen.sim.generic import run_simulation +from migen import * +from migen.genlib.record import * +from migen.sim.generic import run_simulation from litex.soc.com.spi import SPIMaster diff --git a/litex/soc/cores/timer.py b/litex/soc/cores/timer.py index d98a85e9..fdfefde2 100644 --- a/litex/soc/cores/timer.py +++ b/litex/soc/cores/timer.py @@ -1,4 +1,4 @@ -from litex.gen import * +from migen import * from litex.soc.interconnect.csr import * from litex.soc.interconnect.csr_eventmanager import * diff --git a/litex/soc/cores/uart/core.py b/litex/soc/cores/uart/core.py index d394f5aa..ee6075cc 100644 --- a/litex/soc/cores/uart/core.py +++ b/litex/soc/cores/uart/core.py @@ -1,6 +1,6 @@ -from litex.gen import * -from litex.gen.genlib.record import Record -from litex.gen.genlib.cdc import MultiReg +from migen import * +from migen.genlib.record import Record +from migen.genlib.cdc import MultiReg from litex.soc.interconnect.csr import * from litex.soc.interconnect.csr_eventmanager import * diff --git a/litex/soc/integration/cpu_interface.py b/litex/soc/integration/cpu_interface.py index 4648b1b8..636e305e 100644 --- a/litex/soc/integration/cpu_interface.py +++ b/litex/soc/integration/cpu_interface.py @@ -1,4 +1,4 @@ -from litex.gen import * +from migen import * from litex.soc.interconnect.csr import CSRStatus diff --git a/litex/soc/integration/sdram_init.py b/litex/soc/integration/sdram_init.py index 1f73c1ec..8ca1db00 100644 --- a/litex/soc/integration/sdram_init.py +++ b/litex/soc/integration/sdram_init.py @@ -1,4 +1,4 @@ -from litex.gen import log2_int +from migen import log2_int def get_sdram_phy_header(sdram_phy_settings): diff --git a/litex/soc/integration/soc_core.py b/litex/soc/integration/soc_core.py index 4f55e9c0..86eb958f 100644 --- a/litex/soc/integration/soc_core.py +++ b/litex/soc/integration/soc_core.py @@ -1,6 +1,6 @@ from operator import itemgetter -from litex.gen import * +from migen import * from litex.soc.cores import identifier, timer, uart from litex.soc.cores.cpu import lm32, mor1kx diff --git a/litex/soc/integration/soc_sdram.py b/litex/soc/integration/soc_sdram.py index 3c3a3e83..8967657f 100644 --- a/litex/soc/integration/soc_sdram.py +++ b/litex/soc/integration/soc_sdram.py @@ -1,5 +1,5 @@ -from litex.gen import * -from litex.gen.genlib.record import * +from migen import * +from migen.genlib.record import * from litex.soc.interconnect import wishbone, wishbone2lasmi, lasmi_bus from litex.soc.interconnect.csr import AutoCSR @@ -84,7 +84,7 @@ class SoCSDRAM(SoCCore): # Remove this workaround when fixed by Xilinx. from litex.build.xilinx.vivado import XilinxVivadoToolchain if isinstance(self.platform.toolchain, XilinxVivadoToolchain): - from litex.gen.fhdl.simplify import FullMemoryWE + from migen.fhdl.simplify import FullMemoryWE self.submodules.l2_cache = FullMemoryWE()(l2_cache) else: self.submodules.l2_cache = l2_cache @@ -97,7 +97,7 @@ class SoCSDRAM(SoCCore): # Remove this workaround when fixed by Xilinx. from litex.build.xilinx.vivado import XilinxVivadoToolchain if isinstance(self.platform.toolchain, XilinxVivadoToolchain): - from litex.gen.fhdl.simplify import FullMemoryWE + from migen.fhdl.simplify import FullMemoryWE self.submodules.l2_cache = FullMemoryWE()(l2_cache) else: self.submodules.l2_cache = l2_cache diff --git a/litex/soc/interconnect/csr.py b/litex/soc/interconnect/csr.py index c4458cde..8183b2e0 100644 --- a/litex/soc/interconnect/csr.py +++ b/litex/soc/interconnect/csr.py @@ -1,6 +1,6 @@ -from litex.gen import * -from litex.gen.util.misc import xdir -from litex.gen.fhdl.tracer import get_obj_var_name +from migen import * +from migen.util.misc import xdir +from migen.fhdl.tracer import get_obj_var_name class _CSRBase(DUID): diff --git a/litex/soc/interconnect/csr_bus.py b/litex/soc/interconnect/csr_bus.py index 12819927..5e21d8dc 100644 --- a/litex/soc/interconnect/csr_bus.py +++ b/litex/soc/interconnect/csr_bus.py @@ -1,7 +1,7 @@ -from litex.gen import * -from litex.gen.genlib.record import * -from litex.gen.genlib.misc import chooser -from litex.gen.util.misc import xdir +from migen import * +from migen.genlib.record import * +from migen.genlib.misc import chooser +from migen.util.misc import xdir from litex.soc.interconnect import csr from litex.soc.interconnect.csr import CSRStorage diff --git a/litex/soc/interconnect/csr_eventmanager.py b/litex/soc/interconnect/csr_eventmanager.py index 12b85a0a..56258ff7 100644 --- a/litex/soc/interconnect/csr_eventmanager.py +++ b/litex/soc/interconnect/csr_eventmanager.py @@ -1,8 +1,8 @@ from functools import reduce from operator import or_ -from litex.gen import * -from litex.gen.util.misc import xdir +from migen import * +from migen.util.misc import xdir from litex.soc.interconnect.csr import * diff --git a/litex/soc/interconnect/dfi.py b/litex/soc/interconnect/dfi.py index 25812122..aae56b0d 100644 --- a/litex/soc/interconnect/dfi.py +++ b/litex/soc/interconnect/dfi.py @@ -1,5 +1,5 @@ -from litex.gen import * -from litex.gen.genlib.record import * +from migen import * +from migen.genlib.record import * def phase_cmd_description(addressbits, bankbits): diff --git a/litex/soc/interconnect/dma_lasmi.py b/litex/soc/interconnect/dma_lasmi.py index 1d1e9998..ce3937bc 100644 --- a/litex/soc/interconnect/dma_lasmi.py +++ b/litex/soc/interconnect/dma_lasmi.py @@ -1,5 +1,5 @@ -from litex.gen import * -from litex.gen.genlib.fifo import SyncFIFO +from migen import * +from migen.genlib.fifo import SyncFIFO class Reader(Module): diff --git a/litex/soc/interconnect/lasmi_bus.py b/litex/soc/interconnect/lasmi_bus.py index 841b72b1..c8d2ded2 100644 --- a/litex/soc/interconnect/lasmi_bus.py +++ b/litex/soc/interconnect/lasmi_bus.py @@ -1,9 +1,9 @@ from functools import reduce from operator import or_ -from litex.gen import * -from litex.gen.genlib import roundrobin -from litex.gen.genlib.record import * +from migen import * +from migen.genlib import roundrobin +from migen.genlib.record import * class Interface(Record): diff --git a/litex/soc/interconnect/stream.py b/litex/soc/interconnect/stream.py index a1b44c2e..0c708420 100644 --- a/litex/soc/interconnect/stream.py +++ b/litex/soc/interconnect/stream.py @@ -1,6 +1,6 @@ -from litex.gen import * -from litex.gen.genlib.record import * -from litex.gen.genlib import fifo +from migen import * +from migen.genlib.record import * +from migen.genlib import fifo def _make_m2s(layout): @@ -154,7 +154,7 @@ class Demultiplexer(Module): # XXX from copy import copy -from litex.gen.util.misc import xdir +from migen.util.misc import xdir def pack_layout(l, n): return [("chunk"+str(i), l) for i in range(n)] diff --git a/litex/soc/interconnect/wishbone.py b/litex/soc/interconnect/wishbone.py index c10cda4e..5b51431a 100644 --- a/litex/soc/interconnect/wishbone.py +++ b/litex/soc/interconnect/wishbone.py @@ -1,11 +1,11 @@ from functools import reduce from operator import or_ -from litex.gen import * -from litex.gen.genlib import roundrobin -from litex.gen.genlib.record import * -from litex.gen.genlib.misc import split, displacer, chooser -from litex.gen.genlib.fsm import FSM, NextState +from migen import * +from migen.genlib import roundrobin +from migen.genlib.record import * +from migen.genlib.misc import split, displacer, chooser +from migen.genlib.fsm import FSM, NextState from litex.soc.interconnect import csr diff --git a/litex/soc/interconnect/wishbone2csr.py b/litex/soc/interconnect/wishbone2csr.py index 25efdc6f..1d7171a3 100644 --- a/litex/soc/interconnect/wishbone2csr.py +++ b/litex/soc/interconnect/wishbone2csr.py @@ -1,5 +1,5 @@ -from litex.gen import * -from litex.gen.genlib.misc import timeline +from migen import * +from migen.genlib.misc import timeline from litex.soc.interconnect import csr_bus, wishbone diff --git a/litex/soc/interconnect/wishbone2lasmi.py b/litex/soc/interconnect/wishbone2lasmi.py index bd139afa..9c95689c 100644 --- a/litex/soc/interconnect/wishbone2lasmi.py +++ b/litex/soc/interconnect/wishbone2lasmi.py @@ -1,5 +1,5 @@ -from litex.gen import * -from litex.gen.genlib.fsm import FSM, NextState +from migen import * +from migen.genlib.fsm import FSM, NextState class WB2LASMI(Module):