hdl: consistently use "comb" for combinatorial domain.

Fixes #1097.
This commit is contained in:
Wanda 2024-02-09 20:27:25 +01:00 committed by Catherine
parent b6c5294e50
commit 45dbce13df
11 changed files with 104 additions and 115 deletions

View file

@ -794,7 +794,7 @@ def _convert_fragment(builder, fragment, name_map, hierarchy):
rd_clk_polarity = 0
rd_transparency_mask = 0
for index, port in enumerate(fragment._read_ports):
if port._domain is not None:
if port._domain != "comb":
cd = fragment.domains[port._domain]
rd_clk.append(cd.clk)
if cd.clk_edge == "pos":
@ -870,7 +870,7 @@ def _convert_fragment(builder, fragment, name_map, hierarchy):
# affects further codegen; e.g. whether \sig$next signals will be generated and used.
for domain, statements in fragment.statements.items():
for signal in statements._lhs_signals():
compiler_state.add_driven(signal, sync=domain is not None)
compiler_state.add_driven(signal, sync=domain != "comb")
# Transform all signals used as ports in the current fragment eagerly and outside of
# any hierarchy, to make sure they get sensible (non-prefixed) names.
@ -943,7 +943,7 @@ def _convert_fragment(builder, fragment, name_map, hierarchy):
# For every signal in sync domains, assign \sig$next to the current
# value (\sig).
for signal in group_signals:
if domain is None:
if domain == "comb":
prev_value = _ast.Const(signal.reset, signal.width)
else:
prev_value = signal

View file

@ -48,11 +48,7 @@ class _ModuleBuilderDomains(_ModuleBuilderProxy):
"did you mean <module>.{} instead?"
.format(name, name, name),
SyntaxWarning, stacklevel=2)
if name == "comb":
domain = None
else:
domain = name
return _ModuleBuilderDomain(self._builder, self._depth, domain)
return _ModuleBuilderDomain(self._builder, self._depth, name)
def __getitem__(self, name):
return self.__getattr__(name)
@ -520,20 +516,13 @@ class Module(_ModuleBuilderRoot, Elaboratable):
for name in fsm_states}))
def _add_statement(self, assigns, domain, depth):
def domain_name(domain):
if domain is None:
return "comb"
else:
return domain
while len(self._ctrl_stack) > self.domain._depth:
self._pop_ctrl()
for stmt in Statement.cast(assigns):
if not isinstance(stmt, (Assign, Property)):
raise SyntaxError(
"Only assignments and property checks may be appended to d.{}"
.format(domain_name(domain)))
f"Only assignments and property checks may be appended to d.{domain}")
stmt._MustUse__used = True
@ -543,9 +532,8 @@ class Module(_ModuleBuilderRoot, Elaboratable):
elif self._driving[signal] != domain:
cd_curr = self._driving[signal]
raise SyntaxError(
"Driver-driver conflict: trying to drive {!r} from d.{}, but it is "
"already driven from d.{}"
.format(signal, domain_name(domain), domain_name(cd_curr)))
f"Driver-driver conflict: trying to drive {signal!r} from d.{domain}, but it is "
f"already driven from d.{cd_curr}")
self._statements.setdefault(domain, []).append(stmt)

View file

@ -86,7 +86,8 @@ class Fragment:
if port_dir == dir:
yield port
def add_driver(self, signal, domain=None):
def add_driver(self, signal, domain="comb"):
assert isinstance(domain, str)
if domain not in self.drivers:
self.drivers[domain] = SignalSet()
self.drivers[domain].add(signal)
@ -97,12 +98,12 @@ class Fragment:
yield domain, signal
def iter_comb(self):
if None in self.drivers:
yield from self.drivers[None]
if "comb" in self.drivers:
yield from self.drivers["comb"]
def iter_sync(self):
for domain, signals in self.drivers.items():
if domain is None:
if domain == "comb":
continue
for signal in signals:
yield domain, signal
@ -111,7 +112,7 @@ class Fragment:
signals = SignalSet()
signals |= self.ports.keys()
for domain, domain_signals in self.drivers.items():
if domain is not None:
if domain != "comb":
cd = self.domains[domain]
signals.add(cd.clk)
if cd.rst is not None:
@ -129,7 +130,7 @@ class Fragment:
yield from self.domains
def add_statements(self, domain, *stmts):
assert domain is None or isinstance(domain, str)
assert isinstance(domain, str)
for stmt in Statement.cast(stmts):
stmt._MustUse__used = True
self.statements.setdefault(domain, _StatementList()).append(stmt)
@ -338,7 +339,7 @@ class Fragment:
new_domains = []
for domain_name in collector.used_domains - collector.defined_domains:
if domain_name is None:
if domain_name == "comb":
continue
value = missing_domain(domain_name)
if value is None:
@ -589,7 +590,7 @@ class Fragment:
add_signal_name(port)
for domain_name, domain_signals in self.drivers.items():
if domain_name is not None:
if domain_name != "comb":
domain = self.domains[domain_name]
add_signal_name(domain.clk)
if domain.rst is not None:

View file

@ -34,16 +34,14 @@ class MemorySimWrite:
class MemoryInstance(Fragment):
class _ReadPort:
def __init__(self, *, domain, addr, data, en, transparency):
assert domain is None or isinstance(domain, str)
if domain == "comb":
domain = None
assert isinstance(domain, str)
self._domain = domain
self._addr = Value.cast(addr)
self._data = Value.cast(data)
self._en = Value.cast(en)
self._transparency = tuple(transparency)
assert len(self._en) == 1
if domain is None:
if domain == "comb":
assert isinstance(self._en, Const)
assert self._en.width == 1
assert self._en.value == 1

View file

@ -333,7 +333,7 @@ class DomainCollector(ValueVisitor, StatementVisitor):
self._local_domains = set()
def _add_used_domain(self, domain_name):
if domain_name is None:
if domain_name == "comb":
return
if domain_name in self._local_domains:
return
@ -517,7 +517,7 @@ class DomainLowerer(FragmentTransformer, ValueTransformer, StatementTransformer)
def _insert_resets(self, fragment):
for domain_name, signals in fragment.drivers.items():
if domain_name is None:
if domain_name == "comb":
continue
domain = fragment.domains[domain_name]
if domain.rst is None:
@ -629,12 +629,14 @@ class _ControlInserter(FragmentTransformer):
self.src_loc = None
if isinstance(controls, Value):
controls = {"sync": controls}
if "comb" in controls:
raise ValueError("Cannot add controls on the 'comb' domain")
self.controls = OrderedDict(controls)
def on_fragment(self, fragment):
new_fragment = super().on_fragment(fragment)
for domain, signals in fragment.drivers.items():
if domain is None or domain not in self.controls:
if domain == "comb" or domain not in self.controls:
continue
self._insert_control(new_fragment, domain, signals)
return new_fragment

View file

@ -421,7 +421,7 @@ class _FragmentCompiler:
for domain_name in domains:
domain_stmts = fragment.statements.get(domain_name, _StatementList())
domain_process = PyRTLProcess(is_comb=domain_name is None)
domain_process = PyRTLProcess(is_comb=domain_name == "comb")
domain_signals = domain_stmts._lhs_signals()
if isinstance(fragment, MemoryInstance):
@ -433,7 +433,7 @@ class _FragmentCompiler:
emitter.append(f"def run():")
emitter._level += 1
if domain_name is None:
if domain_name == "comb":
for signal in domain_signals:
signal_index = self.state.get_signal(signal)
emitter.append(f"next_{signal_index} = {signal.reset}")
@ -448,7 +448,7 @@ class _FragmentCompiler:
lhs = _LHSValueCompiler(self.state, emitter, rhs=rhs)
for port in fragment._read_ports:
if port._domain is not None:
if port._domain != "comb":
continue
addr = rhs(port._addr)