remove migen fork from litex
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Fri, 23 Feb 2018 12:37:26 +0000 (13:37 +0100)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Fri, 23 Feb 2018 12:37:26 +0000 (13:37 +0100)
26 files changed:
litex/gen/MIGEN_LICENSE [deleted file]
litex/gen/fhdl/bitcontainer.py [deleted file]
litex/gen/fhdl/conv_output.py [deleted file]
litex/gen/fhdl/decorators.py [deleted file]
litex/gen/fhdl/module.py [deleted file]
litex/gen/fhdl/namer.py [deleted file]
litex/gen/fhdl/simplify.py [deleted file]
litex/gen/fhdl/specials.py [deleted file]
litex/gen/fhdl/structure.py [deleted file]
litex/gen/fhdl/tools.py [deleted file]
litex/gen/fhdl/tracer.py [deleted file]
litex/gen/fhdl/visit.py [deleted file]
litex/gen/genlib/__init__.py [deleted file]
litex/gen/genlib/cdc.py [deleted file]
litex/gen/genlib/coding.py [deleted file]
litex/gen/genlib/divider.py [deleted file]
litex/gen/genlib/fifo.py [deleted file]
litex/gen/genlib/fsm.py [deleted file]
litex/gen/genlib/io.py [deleted file]
litex/gen/genlib/misc.py [deleted file]
litex/gen/genlib/record.py [deleted file]
litex/gen/genlib/resetsync.py [deleted file]
litex/gen/genlib/roundrobin.py [deleted file]
litex/gen/genlib/sort.py [deleted file]
litex/gen/util/__init__.py [deleted file]
litex/gen/util/misc.py [deleted file]

diff --git a/litex/gen/MIGEN_LICENSE b/litex/gen/MIGEN_LICENSE
deleted file mode 100644 (file)
index 4f29060..0000000
+++ /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/fhdl/bitcontainer.py b/litex/gen/fhdl/bitcontainer.py
deleted file mode 100644 (file)
index e7894bc..0000000
+++ /dev/null
@@ -1,120 +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):
-    if n == 0:
-        return 0
-    r = (n - 1).bit_length()
-    if need_pow2 and (1 << r) != 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 _bitwise_binary_bits_sign(a, b):
-    if not a[1] and not b[1]:
-        # both operands unsigned
-        return max(a[0], b[0]), False
-    elif a[1] and b[1]:
-        # both operands signed
-        return max(a[0], b[0]), True
-    elif not a[1] and b[1]:
-        # first operand unsigned (add sign bit), second operand signed
-        return max(a[0] + 1, b[0]), True
-    else:
-        # first signed, second operand unsigned (add sign bit)
-        return max(a[0], b[0] + 1), True
-
-
-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 len(obs) == 1:
-                if v.op == "-" and not obs[0][1]:
-                    return obs[0][0] + 1, True
-                else:
-                    return obs[0]
-            n, s = _bitwise_binary_bits_sign(*obs)
-            return n + 1, s
-        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 == "|":
-            return _bitwise_binary_bits_sign(*obs)
-        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]
-        elif v.op == "m":
-            return _bitwise_binary_bits_sign(obs[1], obs[2])
-        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 (file)
index 793fad2..0000000
+++ /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 (file)
index d33ee71..0000000
+++ /dev/null
@@ -1,110 +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__
-        Wrapped.__doc__ = victim.__doc__
-        Wrapped.__module__ = victim.__module__
-        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 not f.sync:
-                return
-            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/module.py b/litex/gen/fhdl/module.py
deleted file mode 100644 (file)
index a860751..0000000
+++ /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 (file)
index c75480d..0000000
+++ /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
-    swno = {signal for signal in signals if signal.name_override is not None}
-    for signal in sorted(swno, key=lambda x: x.duid):
-        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 (file)
index 864ab37..0000000
+++ /dev/null
@@ -1,204 +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
-from litex.gen.fhdl.bitcontainer import log2_int
-
-
-class FullMemoryWE(ModuleTransformer):
-    def __init__(self):
-        self.replacements = 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.replacements[orig] = newmems
-
-        f.specials = newspecials
-        for oldmem in self.replacements.keys():
-            f.specials -= set(oldmem.ports)
-
-
-class MemoryToArray(ModuleTransformer):
-    def __init__(self):
-        self.replacements = dict()
-
-    def transform_fragment(self, i, f):
-        newspecials = set()
-        processed_ports = 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:
-                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[m:M])))
-                    else:
-                        sync.append(If(port.we,
-                                       storage[port.adr].eq(port.dat_w)))
-
-                processed_ports.add(port)
-
-        newspecials -= processed_ports
-        f.specials = newspecials
-
-
-class SplitMemory(ModuleTransformer):
-    """Split memories with depths that are not powers of two into smaller
-    power-of-two memories.
-
-    This prevents toolchains from rounding up and wasting resources."""
-
-    def transform_fragment(self, i, f):
-        old_specials, f.specials = f.specials, set()
-        old_ports = set()
-
-        for old in old_specials:
-            if not isinstance(old, Memory):
-                f.specials.add(old)
-                continue
-            try:
-                log2_int(old.depth, need_pow2=True)
-                f.specials.add(old)
-            except ValueError:
-                new, comb, sync = self._split_mem(old)
-                old_ports |= set(old.ports)
-                f.specials.update(new)
-                f.comb += comb
-                for cd, sy in sync.items():
-                    s = f.sync.setdefault(cd, [])
-                    s += sy
-        f.specials -= old_ports
-
-    def _split_mem(self, mem):
-        depths = [1 << i for i in range(log2_int(mem.depth, need_pow2=False))
-                  if mem.depth & (1 << i)]
-        depths.reverse()
-        inits = None
-        if mem.init is not None:
-            inits = list(mem.init)
-        mems = []
-        for i, depth in enumerate(depths):
-            init = None
-            if inits is not None:
-                init = inits[:depth]
-                del inits[:depth]
-            name = "{}_part{}".format(mem.name_override, i)
-            mems.append(Memory(width=mem.width, depth=depth,
-                               init=init, name=name))
-        ports = []
-        comb = []
-        sync = {}
-        for port in mem.ports:
-            p, c, s = self._split_port(port, mems)
-            ports += p
-            comb += c
-            sy = sync.setdefault(port.clock.cd, [])
-            sy += s
-        return mems + ports, comb, sync
-
-    def _split_port(self, port, mems):
-        ports = [mem.get_port(write_capable=port.we is not None,
-                              async_read=port.async_read,
-                              has_re=port.re is not None,
-                              we_granularity=port.we_granularity,
-                              mode=port.mode,
-                              clock_domain=port.clock.cd)
-                 for mem in mems]
-
-        sel = Signal(max=len(ports), reset=len(ports) - 1)
-        sel_r = Signal.like(sel)
-        eq = sel_r.eq(sel)
-        if port.re is not None:
-            eq = If(port.re, eq)
-        comb, sync = [], []
-        if port.async_read:
-            comb += [eq]
-        else:
-            sync += [eq]
-        comb += reversed([If(~port.adr[len(p.adr)], sel.eq(i))
-                          for i, p in enumerate(ports)])
-        comb += [p.adr.eq(port.adr) for p in ports]
-        comb.append(port.dat_r.eq(Array([p.dat_r for p in ports])[sel_r]))
-        if port.we is not None:
-            comb.append(Array([p.we for p in ports])[sel].eq(port.we))
-            comb += [p.dat_w.eq(port.dat_w) for p in ports]
-        if port.re is not None:
-            comb += [p.re.eq(port.re) for p in ports]
-        return ports, comb, sync
diff --git a/litex/gen/fhdl/specials.py b/litex/gen/fhdl/specials.py
deleted file mode 100644 (file)
index e3fdafd..0000000
+++ /dev/null
@@ -1,358 +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,
-            attr=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
-        if attr is None:
-            attr = set()
-        self.attr = attr
-        for k, v in sorted(kwargs.items(), key=itemgetter(0)):
-            try:
-                item_type, item_name = k.split("_", maxsplit=1)
-            except ValueError:
-                raise TypeError("Wrong format for value '" + str(k) +
-                                "', format should be 'type_name'")
-
-            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"
-
-        directives = instance.synthesis_directive
-        if directives is None:
-            directives = []
-        elif type(directives) == str :
-            directives = [directives,]
-
-        r += ")";
-        for directive in directives:
-            r += "\n\t/* synthesis {} */".format(directive)
-        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
diff --git a/litex/gen/fhdl/structure.py b/litex/gen/fhdl/structure.py
deleted file mode 100644 (file)
index c4afc43..0000000
+++ /dev/null
@@ -1,765 +0,0 @@
-import builtins as _builtins
-import collections as _collections
-import re as _re
-
-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(b, 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("Cannot use type {} ({}) as key".format(
-                type(key), repr(key)))
-
-    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 '{}' of type {} is not a Migen value"
-                        .format(value, type(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.
-    reset_less : bool
-        If `True`, do not generate reset logic for this `Signal` in
-        synchronous statements. The `reset` value is only used as a
-        combinatorial default or as the initial value. Defaults to `False`.
-    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
-    attr : set of synthesis attributes
-    """
-    _name_re = _re.compile(r"^[a-zA-Z_][a-zA-Z0-9_]*$")
-
-    def __init__(self, bits_sign=None, name=None, variable=False, reset=0,
-                 reset_less=False, name_override=None, min=None, max=None,
-                 related=None, attr=None):
-        from litex.gen.fhdl.bitcontainer import bits_for
-
-        _Value.__init__(self)
-
-        for n in [name, name_override]:
-            if n is not None and not self._name_re.match(n):
-                raise ValueError("Signal name {} is not a valid Python identifier"
-                                 .format(repr(n)))
-
-        # 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 isinstance(reset, (bool, int)):
-            reset = Constant(reset, (self.nbits, self.signed))
-        if not isinstance(self.nbits, int) or self.nbits <= 0:
-            raise ValueError("Signal width must be a strictly positive integer")
-        if attr is None:
-            attr = set()
-
-        self.variable = variable  # deprecated
-        self.reset = reset
-        self.reset_less = reset_less
-        self.name_override = name_override
-        self.backtrace = _tracer.trace_back(name)
-        self.related = related
-        self.attr = attr
-
-    def __setattr__(self, k, v):
-        if k == "reset":
-            v = wrap(v)
-        _Value.__setattr__(self, k, v)
-
-    def __repr__(self):
-        return "<Signal " + (self.backtrace[-1][0] or "anonymous") + " at " + hex(id(self)) + ">"
-
-    @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
-        kw = dict(bits_sign=value_bits_sign(other))
-        if isinstance(other, cls):
-            kw.update(variable=other.variable,
-                    reset=other.reset.value, reset_less=other.reset_less,
-                    related=other.related, attr=set(other.attr))
-        kw.update(kwargs)
-        return cls(**kw)
-
-    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, Constant 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 (isinstance(choice, str) and choice == "default")
-                        or choice.value > key.value):
-                    key = choice
-        if not isinstance(key, str) or key != "default":
-            key = wrap(key)
-        stmts = self.cases[key]
-        del self.cases[key]
-        self.cases["default"] = stmts
-        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)
-
-    def __contains__(self, cd_or_name):
-        if isinstance(cd_or_name, str):
-            for cd in self:
-                if cd.name == cd_or_name:
-                    return True
-            return False
-        else:
-            return list.__contains__(self, cd_or_name)
-
-
-(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
-
-
-class Display(_Statement):
-    def __init__(self, s, *args):
-        self.s = s
-        self.args = args
-
-class Finish(_Statement):
-    pass
diff --git a/litex/gen/fhdl/tools.py b/litex/gen/fhdl/tools.py
deleted file mode 100644 (file)
index eefb5e0..0000000
+++ /dev/null
@@ -1,340 +0,0 @@
-from litex.gen.fhdl.structure import *
-from litex.gen.fhdl.structure import _Slice, _Assign, _Fragment
-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)
-            if not t.reset_less]
-
-
-def insert_reset(rst, sl):
-    return sl + [If(rst, *generate_reset(rst, 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 sorted(f.specials, key=lambda s: s.duid):
-        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)
-
-
-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
diff --git a/litex/gen/fhdl/tracer.py b/litex/gen/fhdl/tracer.py
deleted file mode 100644 (file)
index a4b1b90..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-import inspect
-from sys import version_info
-from opcode import opname
-from collections import defaultdict
-
-# All opcodes are 2 bytes in length in Python 3.6
-def _bytecode_length_version_guard(old_len):
-    return old_len if version_info[1] < 6 else 2
-
-_call_opcodes = {
-    "CALL_FUNCTION" : _bytecode_length_version_guard(3),
-    "CALL_FUNCTION_KW" : _bytecode_length_version_guard(3),
-}
-
-if version_info[1] < 6:
-    _call_opcodes["CALL_FUNCTION_VAR"] = 3
-    _call_opcodes["CALL_FUNCTION_VAR_KW"] = 3
-else:
-    _call_opcodes["CALL_FUNCTION_VAR_KW"] = 2
-
-_load_build_opcodes = {
-    "LOAD_GLOBAL" : _bytecode_length_version_guard(3),
-    "LOAD_ATTR" : _bytecode_length_version_guard(3),
-    "LOAD_FAST" : _bytecode_length_version_guard(3),
-    "LOAD_DEREF" : _bytecode_length_version_guard(3),
-    "DUP_TOP" : _bytecode_length_version_guard(1),
-    "BUILD_LIST" : _bytecode_length_version_guard(3),
-}
-
-
-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 not in _call_opcodes:
-        return None
-    index = call_index+_call_opcodes[call_opc]
-    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 in _load_build_opcodes:
-            index += _load_build_opcodes[opc]
-        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 == "<module>":
-                    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/visit.py b/litex/gen/fhdl/visit.py
deleted file mode 100644 (file)
index 676ceb9..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-from copy import copy
-from operator import itemgetter
-
-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)
-        else:
-            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 sorted(node.cases.items(),
-                                    key=lambda x: str(x[0])):
-            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 sorted(node.items(), key=itemgetter(0)):
-            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)
-        else:
-            return self.visit_unknown(node)
-
-    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 = {v: self.visit(statements)
-                 for v, statements in sorted(node.cases.items(),
-                                             key=lambda x: str(x[0]))}
-        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 {clockname: self.visit(statements)
-            for clockname, statements in sorted(node.items(),
-                                                key=itemgetter(0))}
-
-    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 (file)
index e69de29..0000000
diff --git a/litex/gen/genlib/cdc.py b/litex/gen/genlib/cdc.py
deleted file mode 100644 (file)
index 3ba1a26..0000000
+++ /dev/null
@@ -1,253 +0,0 @@
-"""
-Clock domain crossing module
-"""
-from math import gcd
-
-from litex.gen.fhdl.structure import *
-from litex.gen.fhdl.module import Module
-from litex.gen.fhdl.specials import Special, Memory
-from litex.gen.fhdl.bitcontainer import value_bits_sign
-from litex.gen.fhdl.decorators import ClockDomainsRenamer
-from litex.gen.genlib.misc import WaitTimer
-from litex.gen.genlib.resetsync import AsyncResetSynchronizer
-
-
-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), reset_less=True)
-                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)
-        for reg in self.regs:
-            reg.attr.add("no_retiming")
-
-
-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(reset_less=True)
-        toggle_o = Signal()  # registered reset_less by MultiReg
-        toggle_o_r = Signal(reset_less=True)
-
-        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, reset_less=True)
-
-        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 = ClockDomainsRenamer(idomain)(
-                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, reset_less=True)
-            obuffer = Signal(width)  # registered reset_less by MultiReg
-            sync_i += If(self._pong.o, ibuffer.eq(self.i))
-            ibuffer.attr.add("no_retiming")
-            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)
-        ]
-
-
-class GrayDecoder(Module):
-    def __init__(self, width):
-        self.i = Signal(width)
-        self.o = Signal(width, reset_less=True)
-
-        # # #
-
-        o_comb = Signal(width)
-        self.comb += o_comb[-1].eq(self.i[-1])
-        for i in reversed(range(width-1)):
-            self.comb += o_comb[i].eq(o_comb[i+1] ^ self.i[i])
-        self.sync += self.o.eq(o_comb)
-
-
-class ElasticBuffer(Module):
-    def __init__(self, width, depth, idomain, odomain):
-        self.din = Signal(width)
-        self.dout = Signal(width)
-
-        # # #
-
-        reset = Signal()
-        cd_write = ClockDomain()
-        cd_read = ClockDomain()
-        self.comb += [
-            cd_write.clk.eq(ClockSignal(idomain)),
-            cd_read.clk.eq(ClockSignal(odomain)),
-            reset.eq(ResetSignal(idomain) | ResetSignal(odomain))
-        ]
-        self.specials += [
-            AsyncResetSynchronizer(cd_write, reset),
-            AsyncResetSynchronizer(cd_read, reset)
-        ]
-        self.clock_domains += cd_write, cd_read
-
-        wrpointer = Signal(max=depth, reset=depth//2)
-        rdpointer = Signal(max=depth)
-
-        storage = Memory(width, depth)
-        self.specials += storage
-
-        wrport = storage.get_port(write_capable=True, clock_domain="write")
-        rdport = storage.get_port(clock_domain="read")
-        self.specials += wrport, rdport
-
-        self.sync.write += wrpointer.eq(wrpointer + 1)
-        self.sync.read += rdpointer.eq(rdpointer + 1)
-
-        self.comb += [
-            wrport.we.eq(1),
-            wrport.adr.eq(wrpointer),
-            wrport.dat_w.eq(self.din),
-
-            rdport.adr.eq(rdpointer),
-            self.dout.eq(rdport.dat_r)
-        ]
-
-
-def lcm(a, b):
-    """Compute the lowest common multiple of a and b"""
-    return (a*b)//gcd(a, b)
-
-
-class Gearbox(Module):
-    def __init__(self, iwidth, idomain, owidth, odomain):
-        self.i = Signal(iwidth)
-        self.o = Signal(owidth, reset_less=True)
-
-        # # #
-
-        rst = Signal()
-        cd_write = ClockDomain()
-        cd_read = ClockDomain()
-        self.comb += [
-            rst.eq(ResetSignal(idomain) | ResetSignal(odomain)),
-            cd_write.clk.eq(ClockSignal(idomain)),
-            cd_read.clk.eq(ClockSignal(odomain)),
-            cd_write.rst.eq(rst),
-            cd_read.rst.eq(rst)
-        ]
-        self.clock_domains += cd_write, cd_read
-
-        storage = Signal(2*lcm(iwidth, owidth), reset_less=True)
-        wrchunks = len(storage)//iwidth
-        rdchunks = len(storage)//owidth
-        wrpointer = Signal(max=wrchunks, reset=0 if iwidth > owidth else wrchunks//2)
-        rdpointer = Signal(max=rdchunks, reset=rdchunks//2 if iwidth > owidth else 0)
-
-        self.sync.write += \
-            If(wrpointer == wrchunks-1,
-                wrpointer.eq(0)
-            ).Else(
-                wrpointer.eq(wrpointer + 1)
-            )
-        cases = {}
-        for i in range(wrchunks):
-            cases[i] = [storage[iwidth*i:iwidth*(i+1)].eq(self.i)]
-        self.sync.write += Case(wrpointer, cases)
-
-
-        self.sync.read += \
-            If(rdpointer == rdchunks-1,
-                rdpointer.eq(0)
-            ).Else(
-                rdpointer.eq(rdpointer + 1)
-            )
-        cases = {}
-        for i in range(rdchunks):
-            cases[i] = [self.o.eq(storage[owidth*i:owidth*(i+1)])]
-        self.sync.read += Case(rdpointer, cases)
\ No newline at end of file
diff --git a/litex/gen/genlib/coding.py b/litex/gen/genlib/coding.py
deleted file mode 100644 (file)
index 80d62d6..0000000
+++ /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<<j, self.o.eq(j)) for j in range(width))
-        act["default"] = self.n.eq(1)
-        self.comb += Case(self.i, act)
-
-
-class PriorityEncoder(Module):
-    """Priority encode requests to binary
-
-    If `n` is low, the `o` th bit in `i` is asserted and the bits below
-    `o` are unasserted, else `o == 0`. The LSB has priority.
-
-    Parameters
-    ----------
-    width : int
-        Bit width of the input
-
-    Attributes
-    ----------
-    i : Signal(width), in
-        Input requests
-    o : Signal(max=width), out
-        Encoded binary
-    n : Signal(1), out
-        Invalid, no input bits are asserted
-    """
-    def __init__(self, width):
-        self.i = Signal(width)  # one-hot, lsb has priority
-        self.o = Signal(max=max(2, width))  # binary
-        self.n = Signal()  # none
-        for j in range(width)[::-1]:  # last has priority
-            self.comb += If(self.i[j], self.o.eq(j))
-        self.comb += self.n.eq(self.i == 0)
-
-
-class Decoder(Module):
-    """Decode binary to one-hot
-
-    If `n` is low, the `i` th bit in `o` is asserted, the others are
-    not, else `o == 0`.
-
-    Parameters
-    ----------
-    width : int
-        Bit width of the output
-
-    Attributes
-    ----------
-    i : Signal(max=width), in
-        Input binary
-    o : Signal(width), out
-        Decoded one-hot
-    n : Signal(1), in
-        Invalid, no output bits are to be asserted
-    """
-
-    def __init__(self, width):
-        self.i = Signal(max=max(2, width))  # binary
-        self.n = Signal()  # none/invalid
-        self.o = Signal(width)  # one-hot
-        act = dict((j, self.o.eq(1<<j)) for j in range(width))
-        self.comb += Case(self.i, act)
-        self.comb += If(self.n, self.o.eq(0))
-
-
-class PriorityDecoder(Decoder):
-    pass  # same
diff --git a/litex/gen/genlib/divider.py b/litex/gen/genlib/divider.py
deleted file mode 100644 (file)
index 841e7ad..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-from litex.gen.fhdl.structure import *
-from litex.gen.fhdl.module import Module
-
-
-class Divider(Module):
-    def __init__(self, w):
-        self.start_i = Signal()
-        self.dividend_i = Signal(w)
-        self.divisor_i = Signal(w)
-        self.ready_o = Signal()
-        self.quotient_o = Signal(w)
-        self.remainder_o = Signal(w)
-
-        ###
-
-        qr = Signal(2*w)
-        counter = Signal(max=w+1)
-        divisor_r = Signal(w)
-        diff = Signal(w+1)
-
-        self.comb += [
-            self.quotient_o.eq(qr[:w]),
-            self.remainder_o.eq(qr[w:]),
-            self.ready_o.eq(counter == 0),
-            diff.eq(qr[w-1:] - divisor_r)
-        ]
-        self.sync += [
-            If(self.start_i,
-                counter.eq(w),
-                qr.eq(self.dividend_i),
-                divisor_r.eq(self.divisor_i)
-            ).Elif(~self.ready_o,
-                    If(diff[w],
-                        qr.eq(Cat(0, qr[:2*w-1]))
-                    ).Else(
-                        qr.eq(Cat(1, qr[:w-1], diff[:w]))
-                    ),
-                    counter.eq(counter - 1)
-            )
-        ]
diff --git a/litex/gen/genlib/fifo.py b/litex/gen/genlib/fifo.py
deleted file mode 100644 (file)
index 630a42e..0000000
+++ /dev/null
@@ -1,211 +0,0 @@
-from litex.gen.fhdl.structure import *
-from litex.gen.fhdl.module import Module
-from litex.gen.fhdl.specials import Memory
-from litex.gen.fhdl.bitcontainer import log2_int
-from litex.gen.fhdl.decorators import ClockDomainsRenamer
-from litex.gen.genlib.cdc import MultiReg, GrayCounter
-
-
-def _inc(signal, modulo):
-    if modulo == 2**len(signal):
-        return signal.eq(signal + 1)
-    else:
-        return If(signal == (modulo - 1),
-            signal.eq(0)
-        ).Else(
-            signal.eq(signal + 1)
-        )
-
-
-class _FIFOInterface:
-    """
-    Data written to the input interface (`din`, `we`, `writable`) is
-    buffered and can be read at the output interface (`dout`, `re`,
-    `readable`). The data entry written first to the input
-    also appears first on the output.
-
-    Parameters
-    ----------
-    width : int
-        Bit width for the data.
-    depth : int
-        Depth of the FIFO.
-
-    Attributes
-    ----------
-    din : in, width
-        Input data
-    writable : out
-        There is space in the FIFO and `we` can be asserted to load new data.
-    we : in
-        Write enable signal to latch `din` into the FIFO. Does nothing if
-        `writable` is not asserted.
-    dout : out, width
-        Output data. Only valid if `readable` is asserted.
-    readable : out
-        Output data `dout` valid, FIFO not empty.
-    re : in
-        Acknowledge `dout`. If asserted, the next entry will be
-        available on the next cycle (if `readable` is high then).
-    """
-    def __init__(self, width, depth):
-        self.we = Signal()
-        self.writable = Signal()  # not full
-        self.re = Signal()
-        self.readable = Signal()  # not empty
-
-        self.din = Signal(width)
-        self.dout = Signal(width)
-        self.width = width
-        self.depth = depth
-
-
-class SyncFIFO(Module, _FIFOInterface):
-    """Synchronous FIFO (first in, first out)
-
-    Read and write interfaces are accessed from the same clock domain.
-    If different clock domains are needed, use :class:`AsyncFIFO`.
-
-    {interface}
-    level : out
-        Number of unread entries.
-    replace : in
-        Replaces the last entry written into the FIFO with `din`. Does nothing
-        if that entry has already been read (i.e. the FIFO is empty).
-        Assert in conjunction with `we`.
-    """
-    __doc__ = __doc__.format(interface=_FIFOInterface.__doc__)
-
-    def __init__(self, width, depth, fwft=True):
-        _FIFOInterface.__init__(self, width, depth)
-
-        self.level = Signal(max=depth+1)
-        self.replace = Signal()
-
-        ###
-
-        produce = Signal(max=depth)
-        consume = Signal(max=depth)
-        storage = Memory(self.width, depth)
-        self.specials += storage
-
-        wrport = storage.get_port(write_capable=True)
-        self.specials += wrport
-        self.comb += [
-            If(self.replace,
-                wrport.adr.eq(produce-1)
-            ).Else(
-                wrport.adr.eq(produce)
-            ),
-            wrport.dat_w.eq(self.din),
-            wrport.we.eq(self.we & (self.writable | self.replace))
-        ]
-        self.sync += If(self.we & self.writable & ~self.replace,
-            _inc(produce, depth))
-
-        do_read = Signal()
-        self.comb += do_read.eq(self.readable & self.re)
-
-        rdport = storage.get_port(async_read=fwft, has_re=not fwft)
-        self.specials += rdport
-        self.comb += [
-            rdport.adr.eq(consume),
-            self.dout.eq(rdport.dat_r)
-        ]
-        if not fwft:
-            self.comb += rdport.re.eq(do_read)
-        self.sync += If(do_read, _inc(consume, depth))
-
-        self.sync += \
-            If(self.we & self.writable & ~self.replace,
-                If(~do_read, self.level.eq(self.level + 1))
-            ).Elif(do_read,
-                self.level.eq(self.level - 1)
-            )
-        self.comb += [
-            self.writable.eq(self.level != depth),
-            self.readable.eq(self.level != 0)
-        ]
-
-
-class SyncFIFOBuffered(Module, _FIFOInterface):
-    def __init__(self, width, depth):
-        _FIFOInterface.__init__(self, width, depth)
-        self.submodules.fifo = fifo = SyncFIFO(width, depth, False)
-
-        self.writable = fifo.writable
-        self.din = fifo.din
-        self.we = fifo.we
-        self.dout = fifo.dout
-        self.level = Signal(max=depth+2)
-
-        ###
-
-        self.comb += fifo.re.eq(fifo.readable & (~self.readable | self.re))
-        self.sync += \
-            If(fifo.re,
-                self.readable.eq(1),
-            ).Elif(self.re,
-                self.readable.eq(0),
-            )
-        self.comb += self.level.eq(fifo.level + self.readable)
-
-
-class AsyncFIFO(Module, _FIFOInterface):
-    """Asynchronous FIFO (first in, first out)
-
-    Read and write interfaces are accessed from different clock domains,
-    named `read` and `write`. Use `ClockDomainsRenamer` to rename to
-    other names.
-
-    {interface}
-    """
-    __doc__ = __doc__.format(interface=_FIFOInterface.__doc__)
-
-    def __init__(self, width, depth):
-        _FIFOInterface.__init__(self, width, depth)
-
-        ###
-
-        depth_bits = log2_int(depth, True)
-
-        produce = ClockDomainsRenamer("write")(GrayCounter(depth_bits+1))
-        consume = ClockDomainsRenamer("read")(GrayCounter(depth_bits+1))
-        self.submodules += produce, consume
-        self.comb += [
-            produce.ce.eq(self.writable & self.we),
-            consume.ce.eq(self.readable & self.re)
-        ]
-
-        produce_rdomain = Signal(depth_bits+1)
-        produce.q.attr.add("no_retiming")
-        self.specials += MultiReg(produce.q, produce_rdomain, "read")
-        consume_wdomain = Signal(depth_bits+1)
-        consume.q.attr.add("no_retiming")
-        self.specials += MultiReg(consume.q, consume_wdomain, "write")
-        if depth_bits == 1:
-            self.comb += self.writable.eq((produce.q[-1] == consume_wdomain[-1])
-                | (produce.q[-2] == consume_wdomain[-2]))
-        else:
-            self.comb += [
-                self.writable.eq((produce.q[-1] == consume_wdomain[-1])
-                | (produce.q[-2] == consume_wdomain[-2])
-                | (produce.q[:-2] != consume_wdomain[:-2]))
-            ]
-        self.comb += self.readable.eq(consume.q != produce_rdomain)
-
-        storage = Memory(self.width, depth)
-        self.specials += storage
-        wrport = storage.get_port(write_capable=True, clock_domain="write")
-        self.specials += wrport
-        self.comb += [
-            wrport.adr.eq(produce.q_binary[:-1]),
-            wrport.dat_w.eq(self.din),
-            wrport.we.eq(produce.ce)
-        ]
-        rdport = storage.get_port(clock_domain="read")
-        self.specials += rdport
-        self.comb += [
-            rdport.adr.eq(consume.q_next_binary[:-1]),
-            self.dout.eq(rdport.dat_r)
-        ]
diff --git a/litex/gen/genlib/fsm.py b/litex/gen/genlib/fsm.py
deleted file mode 100644 (file)
index 044b95d..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-from collections import OrderedDict
-
-from litex.gen.fhdl.structure import *
-from litex.gen.fhdl.structure import _Statement, _Slice, _ArrayProxy
-from litex.gen.fhdl.module import Module, FinalizeError
-from litex.gen.fhdl.visit import NodeTransformer
-from litex.gen.fhdl.bitcontainer import value_bits_sign
-
-
-__all__ = ["AnonymousState", "NextState", "NextValue", "FSM"]
-
-
-class AnonymousState:
-    pass
-
-
-# do not use namedtuple here as it inherits tuple
-# and the latter is used elsewhere in FHDL
-class NextState(_Statement):
-    def __init__(self, state):
-        self.state = state
-
-
-class NextValue(_Statement):
-    def __init__(self, target, value):
-        self.target = target
-        self.value = value
-
-
-def _target_eq(a, b):
-    if type(a) != type(b):
-        return False
-    ty = type(a)
-    if ty == Constant:
-        return a.value == b.value
-    elif ty == Signal:
-        return a is b
-    elif ty == Cat:
-        return all(_target_eq(x, y) for x, y in zip(a.l, b.l))
-    elif ty == _Slice:
-        return (_target_eq(a.value, b.value)
-                    and a.start == b.start
-                    and a.stop == b.stop)
-    elif ty == _ArrayProxy:
-        return (all(_target_eq(x, y) for x, y in zip(a.choices, b.choices))
-                    and _target_eq(a.key, b.key))
-    else:
-        raise ValueError("NextValue cannot be used with target type '{}'"
-                         .format(ty))
-
-
-class _LowerNext(NodeTransformer):
-    def __init__(self, next_state_signal, encoding, aliases):
-        self.next_state_signal = next_state_signal
-        self.encoding = encoding
-        self.aliases = aliases
-        # (target, next_value_ce, next_value)
-        self.registers = []
-
-    def _get_register_control(self, target):
-        for x in self.registers:
-            if _target_eq(target, x[0]):
-                return x[1], x[2]
-        raise KeyError
-
-    def visit_unknown(self, node):
-        if isinstance(node, NextState):
-            try:
-                actual_state = self.aliases[node.state]
-            except KeyError:
-                actual_state = node.state
-            return self.next_state_signal.eq(self.encoding[actual_state])
-        elif isinstance(node, NextValue):
-            try:
-                next_value_ce, next_value = self._get_register_control(node.target)
-            except KeyError:
-                related = node.target if isinstance(node.target, Signal) else None
-                next_value = Signal(bits_sign=value_bits_sign(node.target), related=related)
-                next_value_ce = Signal(related=related)
-                self.registers.append((node.target, next_value_ce, next_value))
-            return next_value.eq(node.value), next_value_ce.eq(1)
-        else:
-            return node
-
-class FSM(Module):
-    """
-    Finite state machine
-
-    Any Python objects can be used as states, e.g. strings.
-
-    Parameters
-    ----------
-    reset_state
-        Reset state. Defaults to the first added state.
-
-    Examples
-    --------
-
-    >>> self.active = Signal()
-    >>> self.bitno = Signal(3)
-    >>>
-    >>> fsm = FSM(reset_state="START")
-    >>> self.submodules += fsm
-    >>>
-    >>> fsm.act("START",
-    ...     self.active.eq(1),
-    ...     If(strobe,
-    ...         NextState("DATA")
-    ...     )
-    ... )
-    >>> fsm.act("DATA",
-    ...     self.active.eq(1),
-    ...     If(strobe,
-    ...         NextValue(self.bitno, self.bitno + 1)
-    ...         If(self.bitno == 7,
-    ...             NextState("END")
-    ...         )
-    ...     )
-    ... )
-    >>> fsm.act("END",
-    ...     self.active.eq(0),
-    ...     NextState("STOP")
-    ... )
-
-    """
-    def __init__(self, reset_state=None):
-        self.actions = OrderedDict()
-        self.state_aliases = dict()
-        self.reset_state = reset_state
-
-        self.before_entering_signals = OrderedDict()
-        self.before_leaving_signals = OrderedDict()
-        self.after_entering_signals = OrderedDict()
-        self.after_leaving_signals = OrderedDict()
-
-    def act(self, state, *statements):
-        """
-        Schedules `statements` to be executed in `state`. Statements may include:
-
-            * combinatorial statements of form `a.eq(b)`, equivalent to
-              `self.comb += a.eq(b)` when the FSM is in the given `state`;
-            * synchronous statements of form `NextValue(a, b)`, equivalent to
-              `self.sync += a.eq(b)` when the FSM is in the given `state`;
-            * a statement of form `NextState(new_state)`, selecting the next state;
-            * `If`, `Case`, etc.
-        """
-        if self.finalized:
-            raise FinalizeError
-        if self.reset_state is None:
-            self.reset_state = state
-        if state not in self.actions:
-            self.actions[state] = []
-        self.actions[state] += statements
-
-    def delayed_enter(self, name, target, delay):
-        if self.finalized:
-            raise FinalizeError
-        if delay > 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):
-        """
-        Returns a signal that has the value 1 when the FSM is in the given `state`,
-        and 0 otherwise.
-        """
-        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 (file)
index a30218c..0000000
+++ /dev/null
@@ -1,98 +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):
-    """ Clock and Reset Generator """
-
-    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 (file)
index a28e30d..0000000
+++ /dev/null
@@ -1,104 +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))
-
-
-class BitSlip(Module):
-    def __init__(self, dw):
-        self.i = Signal(dw)
-        self.o = Signal(dw)
-        self.value = Signal(max=dw)
-
-        # # #
-
-        r = Signal(2*dw)
-        self.sync += r.eq(Cat(r[dw:], self.i))
-        cases = {}
-        for i in range(dw):
-            cases[i] = self.o.eq(r[i:dw+i])
-        self.sync += Case(self.value, cases)
diff --git a/litex/gen/genlib/record.py b/litex/gen/genlib/record.py
deleted file mode 100644 (file)
index a82f916..0000000
+++ /dev/null
@@ -1,195 +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
-                freset_less = False
-                if(len(f) == 4):
-                    fname, fsize, fdirection, freset_less = f
-                elif(len(f) == 3):
-                    fname, fsize, fdirection = f
-                else:
-                    fname, fsize = f
-                finst = Signal(fsize, name=prefix + fname, reset_less=freset_less)
-            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, keep=None, omit=None):
-        if keep is None:
-            _keep = set([f[0] for f in self.layout])
-        elif isinstance(keep, list):
-            _keep = set(keep)
-        else:
-            _keep = keep
-        if omit is None:
-            _omit = set()
-        elif isinstance(omit, list):
-            _omit = set(omit)
-        else:
-            _omit = omit
-
-        _keep = _keep - _omit
-
-        r = []
-        for f in self.layout:
-            field = f[0]
-            self_e = getattr(self, field)
-            if isinstance(self_e, Signal):
-                if field in _keep:
-                    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), keep=keep, omit=omit)
-        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 "<Record " + ":".join(f[0] for f in self.layout) + " at " + hex(id(self)) + ">"
diff --git a/litex/gen/genlib/resetsync.py b/litex/gen/genlib/resetsync.py
deleted file mode 100644 (file)
index 061f65b..0000000
+++ /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 (file)
index b9903db..0000000
+++ /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 (file)
index ff5b617..0000000
+++ /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/util/__init__.py b/litex/gen/util/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/litex/gen/util/misc.py b/litex/gen/util/misc.py
deleted file mode 100644 (file)
index 0eadc2b..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-from math 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:]))