hdl.dsl: add clock domain support.
This commit is contained in:
parent
b2f828387a
commit
015998eba9
|
@ -90,7 +90,7 @@ class _CompatModuleClockDomains(_CompatModuleProxy):
|
||||||
|
|
||||||
@deprecated("TODO")
|
@deprecated("TODO")
|
||||||
def __iadd__(self, other):
|
def __iadd__(self, other):
|
||||||
self._cm._fragment.clock_domains += _flat_list(other)
|
self._cm._module.domains += _flat_list(other)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ from collections import OrderedDict
|
||||||
from collections.abc import Iterable
|
from collections.abc import Iterable
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
|
||||||
|
from ..tools import flatten
|
||||||
from .ast import *
|
from .ast import *
|
||||||
from .ir import *
|
from .ir import *
|
||||||
from .xfrm import *
|
from .xfrm import *
|
||||||
|
@ -20,7 +21,7 @@ class _ModuleBuilderProxy:
|
||||||
object.__setattr__(self, "_depth", depth)
|
object.__setattr__(self, "_depth", depth)
|
||||||
|
|
||||||
|
|
||||||
class _ModuleBuilderDomain(_ModuleBuilderProxy):
|
class _ModuleBuilderDomainExplicit(_ModuleBuilderProxy):
|
||||||
def __init__(self, builder, depth, domain):
|
def __init__(self, builder, depth, domain):
|
||||||
super().__init__(builder, depth)
|
super().__init__(builder, depth)
|
||||||
self._domain = domain
|
self._domain = domain
|
||||||
|
@ -30,13 +31,13 @@ class _ModuleBuilderDomain(_ModuleBuilderProxy):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
class _ModuleBuilderDomains(_ModuleBuilderProxy):
|
class _ModuleBuilderDomainImplicit(_ModuleBuilderProxy):
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
if name == "comb":
|
if name == "comb":
|
||||||
domain = None
|
domain = None
|
||||||
else:
|
else:
|
||||||
domain = name
|
domain = name
|
||||||
return _ModuleBuilderDomain(self._builder, self._depth, domain)
|
return _ModuleBuilderDomainExplicit(self._builder, self._depth, domain)
|
||||||
|
|
||||||
def __getitem__(self, name):
|
def __getitem__(self, name):
|
||||||
return self.__getattr__(name)
|
return self.__getattr__(name)
|
||||||
|
@ -44,7 +45,7 @@ class _ModuleBuilderDomains(_ModuleBuilderProxy):
|
||||||
def __setattr__(self, name, value):
|
def __setattr__(self, name, value):
|
||||||
if name == "_depth":
|
if name == "_depth":
|
||||||
object.__setattr__(self, name, value)
|
object.__setattr__(self, name, value)
|
||||||
elif not isinstance(value, _ModuleBuilderDomain):
|
elif not isinstance(value, _ModuleBuilderDomainExplicit):
|
||||||
raise AttributeError("Cannot assign 'd.{}' attribute; did you mean 'd.{} +='?"
|
raise AttributeError("Cannot assign 'd.{}' attribute; did you mean 'd.{} +='?"
|
||||||
.format(name, name))
|
.format(name, name))
|
||||||
|
|
||||||
|
@ -55,7 +56,7 @@ class _ModuleBuilderDomains(_ModuleBuilderProxy):
|
||||||
class _ModuleBuilderRoot:
|
class _ModuleBuilderRoot:
|
||||||
def __init__(self, builder, depth):
|
def __init__(self, builder, depth):
|
||||||
self._builder = builder
|
self._builder = builder
|
||||||
self.domain = self.d = _ModuleBuilderDomains(builder, depth)
|
self.domain = self.d = _ModuleBuilderDomainImplicit(builder, depth)
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
if name in ("comb", "sync"):
|
if name in ("comb", "sync"):
|
||||||
|
@ -70,11 +71,7 @@ class _ModuleBuilderSubmodules:
|
||||||
object.__setattr__(self, "_builder", builder)
|
object.__setattr__(self, "_builder", builder)
|
||||||
|
|
||||||
def __iadd__(self, modules):
|
def __iadd__(self, modules):
|
||||||
if isinstance(modules, Iterable):
|
for module in flatten([modules]):
|
||||||
for module in modules:
|
|
||||||
self._builder._add_submodule(module)
|
|
||||||
else:
|
|
||||||
module = modules
|
|
||||||
self._builder._add_submodule(module)
|
self._builder._add_submodule(module)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
@ -82,17 +79,33 @@ class _ModuleBuilderSubmodules:
|
||||||
self._builder._add_submodule(submodule, name)
|
self._builder._add_submodule(submodule, name)
|
||||||
|
|
||||||
|
|
||||||
|
class _ModuleBuilderDomainSet:
|
||||||
|
def __init__(self, builder):
|
||||||
|
object.__setattr__(self, "_builder", builder)
|
||||||
|
|
||||||
|
def __iadd__(self, domains):
|
||||||
|
for domain in flatten([domains]):
|
||||||
|
self._builder._add_domain(domain)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __setattr__(self, name, domain):
|
||||||
|
self._builder._add_domain(domain)
|
||||||
|
|
||||||
|
|
||||||
class Module(_ModuleBuilderRoot):
|
class Module(_ModuleBuilderRoot):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
_ModuleBuilderRoot.__init__(self, self, depth=0)
|
_ModuleBuilderRoot.__init__(self, self, depth=0)
|
||||||
self.submodules = _ModuleBuilderSubmodules(self)
|
self.submodules = _ModuleBuilderSubmodules(self)
|
||||||
|
self.domains = _ModuleBuilderDomainSet(self)
|
||||||
|
|
||||||
self._submodules = []
|
|
||||||
self._driving = ValueDict()
|
|
||||||
self._statements = Statement.wrap([])
|
self._statements = Statement.wrap([])
|
||||||
self._ctrl_context = None
|
self._ctrl_context = None
|
||||||
self._ctrl_stack = []
|
self._ctrl_stack = []
|
||||||
|
|
||||||
|
self._driving = ValueDict()
|
||||||
|
self._submodules = []
|
||||||
|
self._domains = []
|
||||||
|
|
||||||
def _check_context(self, construct, context):
|
def _check_context(self, construct, context):
|
||||||
if self._ctrl_context != context:
|
if self._ctrl_context != context:
|
||||||
if self._ctrl_context is None:
|
if self._ctrl_context is None:
|
||||||
|
@ -259,6 +272,9 @@ class Module(_ModuleBuilderRoot):
|
||||||
"a submodule".format(submodule))
|
"a submodule".format(submodule))
|
||||||
self._submodules.append((submodule, name))
|
self._submodules.append((submodule, name))
|
||||||
|
|
||||||
|
def _add_domain(self, cd):
|
||||||
|
self._domains.append(cd)
|
||||||
|
|
||||||
def _flush(self):
|
def _flush(self):
|
||||||
while self._ctrl_stack:
|
while self._ctrl_stack:
|
||||||
self._pop_ctrl()
|
self._pop_ctrl()
|
||||||
|
@ -272,6 +288,7 @@ class Module(_ModuleBuilderRoot):
|
||||||
fragment.add_statements(self._statements)
|
fragment.add_statements(self._statements)
|
||||||
for signal, domain in self._driving.items():
|
for signal, domain in self._driving.items():
|
||||||
fragment.add_driver(signal, domain)
|
fragment.add_driver(signal, domain)
|
||||||
|
fragment.add_domains(self._domains)
|
||||||
return fragment
|
return fragment
|
||||||
|
|
||||||
get_fragment = lower
|
get_fragment = lower
|
||||||
|
|
|
@ -63,7 +63,7 @@ class Fragment:
|
||||||
return signals
|
return signals
|
||||||
|
|
||||||
def add_domains(self, *domains):
|
def add_domains(self, *domains):
|
||||||
for domain in domains:
|
for domain in flatten(domains):
|
||||||
assert isinstance(domain, ClockDomain)
|
assert isinstance(domain, ClockDomain)
|
||||||
assert domain.name not in self.domains
|
assert domain.name not in self.domains
|
||||||
self.domains[domain.name] = domain
|
self.domains[domain.name] = domain
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
from ..hdl.ast import *
|
from ..hdl.ast import *
|
||||||
|
from ..hdl.cd import *
|
||||||
from ..hdl.dsl import *
|
from ..hdl.dsl import *
|
||||||
from .tools import *
|
from .tools import *
|
||||||
|
|
||||||
|
@ -342,6 +343,17 @@ class DSLTestCase(FHDLTestCase):
|
||||||
msg="Trying to add '1', which does not implement .get_fragment(), as a submodule"):
|
msg="Trying to add '1', which does not implement .get_fragment(), as a submodule"):
|
||||||
m.submodules += 1
|
m.submodules += 1
|
||||||
|
|
||||||
|
def test_domain_named_implicit(self):
|
||||||
|
m = Module()
|
||||||
|
m.domains += ClockDomain("sync")
|
||||||
|
self.assertEqual(len(m._domains), 1)
|
||||||
|
|
||||||
|
def test_domain_named_explicit(self):
|
||||||
|
m = Module()
|
||||||
|
m.domains.foo = ClockDomain()
|
||||||
|
self.assertEqual(len(m._domains), 1)
|
||||||
|
self.assertEqual(m._domains[0].name, "foo")
|
||||||
|
|
||||||
def test_lower(self):
|
def test_lower(self):
|
||||||
m1 = Module()
|
m1 = Module()
|
||||||
m1.d.comb += self.c1.eq(self.s1)
|
m1.d.comb += self.c1.eq(self.s1)
|
||||||
|
|
Loading…
Reference in a new issue