fhdl: cd_name→domain.
This commit is contained in:
parent
c5087edfa5
commit
f4340c19bb
|
@ -402,8 +402,8 @@ def convert_fragment(builder, fragment, name, top, clock_domains):
|
||||||
|
|
||||||
# Register all signals driven in the current fragment. This must be done first, as it
|
# Register all signals driven in the current fragment. This must be done first, as it
|
||||||
# affects further codegen; e.g. whether sig$next signals will be generated and used.
|
# affects further codegen; e.g. whether sig$next signals will be generated and used.
|
||||||
for cd_name, signal in fragment.iter_drivers():
|
for domain, signal in fragment.iter_drivers():
|
||||||
xformer.add_driven(signal, sync=cd_name is not None)
|
xformer.add_driven(signal, sync=domain is not None)
|
||||||
|
|
||||||
# Register all signals used as ports in the current fragment. The wires are lazily
|
# Register all signals used as ports in the current fragment. The wires are lazily
|
||||||
# generated, so registering ports eagerly ensures they get correct direction qualifiers.
|
# generated, so registering ports eagerly ensures they get correct direction qualifiers.
|
||||||
|
@ -412,8 +412,8 @@ def convert_fragment(builder, fragment, name, top, clock_domains):
|
||||||
|
|
||||||
# Transform all clocks clocks and resets eagerly and outside of any hierarchy, to make
|
# Transform all clocks clocks and resets eagerly and outside of any hierarchy, to make
|
||||||
# sure they get sensible (non-prefixed) names. This does not affect semantics.
|
# sure they get sensible (non-prefixed) names. This does not affect semantics.
|
||||||
for cd_name, _ in fragment.iter_sync():
|
for domain, _ in fragment.iter_sync():
|
||||||
cd = clock_domains[cd_name]
|
cd = clock_domains[domain]
|
||||||
xformer(cd.clk)
|
xformer(cd.clk)
|
||||||
xformer(cd.rst)
|
xformer(cd.rst)
|
||||||
|
|
||||||
|
@ -433,8 +433,8 @@ def convert_fragment(builder, fragment, name, top, clock_domains):
|
||||||
with process.case() as case:
|
with process.case() as case:
|
||||||
# For every signal in comb domain, assign \sig$next to the reset value.
|
# For every signal in comb domain, assign \sig$next to the reset value.
|
||||||
# For every signal in sync domains, assign \sig$next to the current value (\sig).
|
# For every signal in sync domains, assign \sig$next to the current value (\sig).
|
||||||
for cd_name, signal in fragment.iter_drivers():
|
for domain, signal in fragment.iter_drivers():
|
||||||
if cd_name is None:
|
if domain is None:
|
||||||
prev_value = xformer(ast.Const(signal.reset, signal.nbits))
|
prev_value = xformer(ast.Const(signal.reset, signal.nbits))
|
||||||
else:
|
else:
|
||||||
prev_value = xformer(signal)
|
prev_value = xformer(signal)
|
||||||
|
@ -472,7 +472,7 @@ def convert_fragment(builder, fragment, name, top, clock_domains):
|
||||||
# as the \init reg attribute) to the reset value. Note that this assigns \sig,
|
# as the \init reg attribute) to the reset value. Note that this assigns \sig,
|
||||||
# not \sig$next.
|
# not \sig$next.
|
||||||
with process.sync("init") as sync:
|
with process.sync("init") as sync:
|
||||||
for cd_name, signal in fragment.iter_sync():
|
for domain, signal in fragment.iter_sync():
|
||||||
sync.update(xformer(signal),
|
sync.update(xformer(signal),
|
||||||
xformer(ast.Const(signal.reset, signal.nbits)))
|
xformer(ast.Const(signal.reset, signal.nbits)))
|
||||||
|
|
||||||
|
@ -480,17 +480,17 @@ def convert_fragment(builder, fragment, name, top, clock_domains):
|
||||||
# however, differs between domains: for comb domains, it is `always`, for sync domains
|
# however, differs between domains: for comb domains, it is `always`, for sync domains
|
||||||
# with sync reset, it is `posedge clk`, for sync domains with async rest it is
|
# with sync reset, it is `posedge clk`, for sync domains with async rest it is
|
||||||
# `posedge clk or posedge rst`.
|
# `posedge clk or posedge rst`.
|
||||||
for cd_name, signals in fragment.iter_domains():
|
for domain, signals in fragment.iter_domains():
|
||||||
triggers = []
|
triggers = []
|
||||||
if cd_name is None:
|
if domain is None:
|
||||||
triggers.append(("always",))
|
triggers.append(("always",))
|
||||||
elif cd_name in clock_domains:
|
elif domain in clock_domains:
|
||||||
cd = clock_domains[cd_name]
|
cd = clock_domains[domain]
|
||||||
triggers.append(("posedge", xformer(cd.clk)))
|
triggers.append(("posedge", xformer(cd.clk)))
|
||||||
if cd.async_reset:
|
if cd.async_reset:
|
||||||
triggers.append(("posedge", xformer(cd.rst)))
|
triggers.append(("posedge", xformer(cd.rst)))
|
||||||
else:
|
else:
|
||||||
raise ValueError("Clock domain {} not found in design".format(cd_name))
|
raise ValueError("Clock domain {} not found in design".format(domain))
|
||||||
|
|
||||||
for trigger in triggers:
|
for trigger in triggers:
|
||||||
with process.sync(*trigger) as sync:
|
with process.sync(*trigger) as sync:
|
||||||
|
|
|
@ -29,7 +29,7 @@ class _CompatModuleProxy:
|
||||||
class _CompatModuleComb(_CompatModuleProxy):
|
class _CompatModuleComb(_CompatModuleProxy):
|
||||||
@deprecated("instead of `self.comb +=`, use `m.d.comb +=`")
|
@deprecated("instead of `self.comb +=`, use `m.d.comb +=`")
|
||||||
def __iadd__(self, assigns):
|
def __iadd__(self, assigns):
|
||||||
self._cm._module._add_statement(assigns, cd_name=None, depth=0, compat_mode=True)
|
self._cm._module._add_statement(assigns, domain=None, depth=0, compat_mode=True)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,14 +40,14 @@ class _CompatModuleSyncCD:
|
||||||
|
|
||||||
@deprecated("instead of `self.sync.<domain> +=`, use `m.d.<domain> +=`")
|
@deprecated("instead of `self.sync.<domain> +=`, use `m.d.<domain> +=`")
|
||||||
def __iadd__(self, assigns):
|
def __iadd__(self, assigns):
|
||||||
self._cm._module._add_statement(assigns, cd_name=self._cd, depth=0, compat_mode=True)
|
self._cm._module._add_statement(assigns, domain=self._cd, depth=0, compat_mode=True)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
class _CompatModuleSync(_CompatModuleProxy):
|
class _CompatModuleSync(_CompatModuleProxy):
|
||||||
@deprecated("instead of `self.sync +=`, use `m.d.sync +=`")
|
@deprecated("instead of `self.sync +=`, use `m.d.sync +=`")
|
||||||
def __iadd__(self, assigns):
|
def __iadd__(self, assigns):
|
||||||
self._cm._module._add_statement(assigns, cd_name="sync", depth=0, compat_mode=True)
|
self._cm._module._add_statement(assigns, domain="sync", depth=0, compat_mode=True)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
|
|
|
@ -20,22 +20,22 @@ class _ModuleBuilderProxy:
|
||||||
|
|
||||||
|
|
||||||
class _ModuleBuilderDomain(_ModuleBuilderProxy):
|
class _ModuleBuilderDomain(_ModuleBuilderProxy):
|
||||||
def __init__(self, builder, depth, cd_name):
|
def __init__(self, builder, depth, domain):
|
||||||
super().__init__(builder, depth)
|
super().__init__(builder, depth)
|
||||||
self._cd_name = cd_name
|
self._domain = domain
|
||||||
|
|
||||||
def __iadd__(self, assigns):
|
def __iadd__(self, assigns):
|
||||||
self._builder._add_statement(assigns, cd_name=self._cd_name, depth=self._depth)
|
self._builder._add_statement(assigns, domain=self._domain, depth=self._depth)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
class _ModuleBuilderDomains(_ModuleBuilderProxy):
|
class _ModuleBuilderDomains(_ModuleBuilderProxy):
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
if name == "comb":
|
if name == "comb":
|
||||||
cd_name = None
|
domain = None
|
||||||
else:
|
else:
|
||||||
cd_name = name
|
domain = name
|
||||||
return _ModuleBuilderDomain(self._builder, self._depth, cd_name)
|
return _ModuleBuilderDomain(self._builder, self._depth, domain)
|
||||||
|
|
||||||
def __getitem__(self, name):
|
def __getitem__(self, name):
|
||||||
return self.__getattr__(name)
|
return self.__getattr__(name)
|
||||||
|
@ -228,12 +228,12 @@ class Module(_ModuleBuilderRoot):
|
||||||
|
|
||||||
self._statements.append(Switch(switch_test, switch_cases))
|
self._statements.append(Switch(switch_test, switch_cases))
|
||||||
|
|
||||||
def _add_statement(self, assigns, cd_name, depth, compat_mode=False):
|
def _add_statement(self, assigns, domain, depth, compat_mode=False):
|
||||||
def cd_human_name(cd_name):
|
def domain_name(domain):
|
||||||
if cd_name is None:
|
if domain is None:
|
||||||
return "comb"
|
return "comb"
|
||||||
else:
|
else:
|
||||||
return cd_name
|
return domain
|
||||||
|
|
||||||
while len(self._ctrl_stack) > self.domain._depth:
|
while len(self._ctrl_stack) > self.domain._depth:
|
||||||
self._pop_ctrl()
|
self._pop_ctrl()
|
||||||
|
@ -242,17 +242,17 @@ class Module(_ModuleBuilderRoot):
|
||||||
if not compat_mode and not isinstance(assign, Assign):
|
if not compat_mode and not isinstance(assign, Assign):
|
||||||
raise SyntaxError(
|
raise SyntaxError(
|
||||||
"Only assignments may be appended to d.{}"
|
"Only assignments may be appended to d.{}"
|
||||||
.format(cd_human_name(cd_name)))
|
.format(domain_name(domain)))
|
||||||
|
|
||||||
for signal in assign._lhs_signals():
|
for signal in assign._lhs_signals():
|
||||||
if signal not in self._driving:
|
if signal not in self._driving:
|
||||||
self._driving[signal] = cd_name
|
self._driving[signal] = domain
|
||||||
elif self._driving[signal] != cd_name:
|
elif self._driving[signal] != domain:
|
||||||
cd_curr = self._driving[signal]
|
cd_curr = self._driving[signal]
|
||||||
raise SyntaxError(
|
raise SyntaxError(
|
||||||
"Driver-driver conflict: trying to drive {!r} from d.{}, but it is "
|
"Driver-driver conflict: trying to drive {!r} from d.{}, but it is "
|
||||||
"already driven from d.{}"
|
"already driven from d.{}"
|
||||||
.format(signal, cd_human_name(cd_name), cd_human_name(cd_curr)))
|
.format(signal, domain_name(domain), domain_name(cd_curr)))
|
||||||
|
|
||||||
self._statements.append(assign)
|
self._statements.append(assign)
|
||||||
|
|
||||||
|
@ -273,8 +273,8 @@ class Module(_ModuleBuilderRoot):
|
||||||
for submodule, name in self._submodules:
|
for submodule, name in self._submodules:
|
||||||
fragment.add_subfragment(submodule.get_fragment(platform), name)
|
fragment.add_subfragment(submodule.get_fragment(platform), name)
|
||||||
fragment.add_statements(self._statements)
|
fragment.add_statements(self._statements)
|
||||||
for signal, cd_name in self._driving.items():
|
for signal, domain in self._driving.items():
|
||||||
fragment.drive(signal, cd_name)
|
fragment.drive(signal, domain)
|
||||||
return fragment
|
return fragment
|
||||||
|
|
||||||
get_fragment = lower
|
get_fragment = lower
|
||||||
|
|
|
@ -20,28 +20,28 @@ class Fragment:
|
||||||
def iter_ports(self):
|
def iter_ports(self):
|
||||||
yield from self.ports
|
yield from self.ports
|
||||||
|
|
||||||
def drive(self, signal, cd_name=None):
|
def drive(self, signal, domain=None):
|
||||||
if cd_name not in self.drivers:
|
if domain not in self.drivers:
|
||||||
self.drivers[cd_name] = ValueSet()
|
self.drivers[domain] = ValueSet()
|
||||||
self.drivers[cd_name].add(signal)
|
self.drivers[domain].add(signal)
|
||||||
|
|
||||||
def iter_domains(self):
|
def iter_domains(self):
|
||||||
yield from self.drivers.items()
|
yield from self.drivers.items()
|
||||||
|
|
||||||
def iter_drivers(self):
|
def iter_drivers(self):
|
||||||
for cd_name, signals in self.drivers.items():
|
for domain, signals in self.drivers.items():
|
||||||
for signal in signals:
|
for signal in signals:
|
||||||
yield cd_name, signal
|
yield domain, signal
|
||||||
|
|
||||||
def iter_comb(self):
|
def iter_comb(self):
|
||||||
yield from self.drivers[None]
|
yield from self.drivers[None]
|
||||||
|
|
||||||
def iter_sync(self):
|
def iter_sync(self):
|
||||||
for cd_name, signals in self.drivers.items():
|
for domain, signals in self.drivers.items():
|
||||||
if cd_name is None:
|
if domain is None:
|
||||||
continue
|
continue
|
||||||
for signal in signals:
|
for signal in signals:
|
||||||
yield cd_name, signal
|
yield domain, signal
|
||||||
|
|
||||||
def add_statements(self, *stmts):
|
def add_statements(self, *stmts):
|
||||||
self.statements += Statement.wrap(stmts)
|
self.statements += Statement.wrap(stmts)
|
||||||
|
@ -55,8 +55,8 @@ class Fragment:
|
||||||
# (on RHS of statements, or in clock domains).
|
# (on RHS of statements, or in clock domains).
|
||||||
self_driven = union(s._lhs_signals() for s in self.statements)
|
self_driven = union(s._lhs_signals() for s in self.statements)
|
||||||
self_used = union(s._rhs_signals() for s in self.statements)
|
self_used = union(s._rhs_signals() for s in self.statements)
|
||||||
for cd_name, _ in self.iter_sync():
|
for domain, _ in self.iter_sync():
|
||||||
cd = clock_domains[cd_name]
|
cd = clock_domains[domain]
|
||||||
self_used.add(cd.clk)
|
self_used.add(cd.clk)
|
||||||
if cd.rst is not None:
|
if cd.rst is not None:
|
||||||
self_used.add(cd.rst)
|
self_used.add(cd.rst)
|
||||||
|
|
|
@ -102,9 +102,9 @@ class FragmentTransformer:
|
||||||
new_fragment.add_statements(fragment.statements)
|
new_fragment.add_statements(fragment.statements)
|
||||||
|
|
||||||
def map_drivers(self, fragment, new_fragment):
|
def map_drivers(self, fragment, new_fragment):
|
||||||
for cd_name, signals in fragment.iter_domains():
|
for domain, signals in fragment.iter_domains():
|
||||||
for signal in signals:
|
for signal in signals:
|
||||||
new_fragment.drive(signal, cd_name)
|
new_fragment.drive(signal, domain)
|
||||||
|
|
||||||
def on_fragment(self, fragment):
|
def on_fragment(self, fragment):
|
||||||
new_fragment = Fragment()
|
new_fragment = Fragment()
|
||||||
|
@ -134,11 +134,11 @@ class DomainRenamer(FragmentTransformer, ValueTransformer, StatementTransformer)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def map_drivers(self, fragment, new_fragment):
|
def map_drivers(self, fragment, new_fragment):
|
||||||
for cd_name, signals in fragment.iter_domains():
|
for domain, signals in fragment.iter_domains():
|
||||||
if cd_name in self.domains:
|
if domain in self.domains:
|
||||||
cd_name = self.domains[cd_name]
|
domain = self.domains[domain]
|
||||||
for signal in signals:
|
for signal in signals:
|
||||||
new_fragment.drive(signal, cd_name)
|
new_fragment.drive(signal, domain)
|
||||||
|
|
||||||
|
|
||||||
class _ControlInserter(FragmentTransformer):
|
class _ControlInserter(FragmentTransformer):
|
||||||
|
@ -149,23 +149,23 @@ class _ControlInserter(FragmentTransformer):
|
||||||
|
|
||||||
def on_fragment(self, fragment):
|
def on_fragment(self, fragment):
|
||||||
new_fragment = super().on_fragment(fragment)
|
new_fragment = super().on_fragment(fragment)
|
||||||
for cd_name, signals in fragment.iter_domains():
|
for domain, signals in fragment.iter_domains():
|
||||||
if cd_name is None or cd_name not in self.controls:
|
if domain is None or domain not in self.controls:
|
||||||
continue
|
continue
|
||||||
self._insert_control(new_fragment, cd_name, signals)
|
self._insert_control(new_fragment, domain, signals)
|
||||||
return new_fragment
|
return new_fragment
|
||||||
|
|
||||||
def _insert_control(self, fragment, cd_name, signals):
|
def _insert_control(self, fragment, domain, signals):
|
||||||
raise NotImplementedError # :nocov:
|
raise NotImplementedError # :nocov:
|
||||||
|
|
||||||
|
|
||||||
class ResetInserter(_ControlInserter):
|
class ResetInserter(_ControlInserter):
|
||||||
def _insert_control(self, fragment, cd_name, signals):
|
def _insert_control(self, fragment, domain, signals):
|
||||||
stmts = [s.eq(Const(s.reset, s.nbits)) for s in signals if not s.reset_less]
|
stmts = [s.eq(Const(s.reset, s.nbits)) for s in signals if not s.reset_less]
|
||||||
fragment.add_statements(Switch(self.controls[cd_name], {1: stmts}))
|
fragment.add_statements(Switch(self.controls[domain], {1: stmts}))
|
||||||
|
|
||||||
|
|
||||||
class CEInserter(_ControlInserter):
|
class CEInserter(_ControlInserter):
|
||||||
def _insert_control(self, fragment, cd_name, signals):
|
def _insert_control(self, fragment, domain, signals):
|
||||||
stmts = [s.eq(s) for s in signals]
|
stmts = [s.eq(s) for s in signals]
|
||||||
fragment.add_statements(Switch(self.controls[cd_name], {0: stmts}))
|
fragment.add_statements(Switch(self.controls[domain], {0: stmts}))
|
||||||
|
|
Loading…
Reference in a new issue