sim._pyrtl: translate ArrayProxy to pattern matching when supported.
Current the value compiler translates ArrayProxy into if-elif trees which can cause the compiler to crash due to deep recursion (#359). After this commit, it instead translates them into pattern matching when it is supported (on Python >= 3.10) to avoid this problem.
This commit is contained in:
parent
c4be739d48
commit
3a51b61284
|
@ -1,6 +1,7 @@
|
||||||
import os
|
import os
|
||||||
import tempfile
|
import tempfile
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
import sys
|
||||||
|
|
||||||
from ..hdl import *
|
from ..hdl import *
|
||||||
from ..hdl.ast import SignalSet
|
from ..hdl.ast import SignalSet
|
||||||
|
@ -10,6 +11,7 @@ from ._base import BaseProcess
|
||||||
|
|
||||||
__all__ = ["PyRTLProcess"]
|
__all__ = ["PyRTLProcess"]
|
||||||
|
|
||||||
|
_USE_PATTERN_MATCHING = (sys.version_info >= (3, 10))
|
||||||
|
|
||||||
class PyRTLProcess(BaseProcess):
|
class PyRTLProcess(BaseProcess):
|
||||||
__slots__ = ("is_comb", "runnable", "passive", "run")
|
__slots__ = ("is_comb", "runnable", "passive", "run")
|
||||||
|
@ -228,16 +230,28 @@ class _RHSValueCompiler(_ValueCompiler):
|
||||||
gen_index = self.emitter.def_var("rhs_index", f"{index_mask:#x} & {self(value.index)}")
|
gen_index = self.emitter.def_var("rhs_index", f"{index_mask:#x} & {self(value.index)}")
|
||||||
gen_value = self.emitter.gen_var("rhs_proxy")
|
gen_value = self.emitter.gen_var("rhs_proxy")
|
||||||
if value.elems:
|
if value.elems:
|
||||||
for index, elem in enumerate(value.elems):
|
if _USE_PATTERN_MATCHING:
|
||||||
if index == 0:
|
self.emitter.append(f"match {gen_index}:")
|
||||||
self.emitter.append(f"if {index} == {gen_index}:")
|
|
||||||
else:
|
|
||||||
self.emitter.append(f"elif {index} == {gen_index}:")
|
|
||||||
with self.emitter.indent():
|
with self.emitter.indent():
|
||||||
self.emitter.append(f"{gen_value} = {self(elem)}")
|
for index, elem in enumerate(value.elems):
|
||||||
self.emitter.append(f"else:")
|
self.emitter.append(f"case {index}:")
|
||||||
with self.emitter.indent():
|
with self.emitter.indent():
|
||||||
self.emitter.append(f"{gen_value} = {self(value.elems[-1])}")
|
self.emitter.append(f"{gen_value} = {self(elem)}")
|
||||||
|
self.emitter.append("case _:")
|
||||||
|
with self.emitter.indent():
|
||||||
|
self.emitter.append(f"{gen_value} = {self(value.elems[-1])}")
|
||||||
|
else:
|
||||||
|
for index, elem in enumerate(value.elems):
|
||||||
|
if index == 0:
|
||||||
|
self.emitter.append(f"if {index} == {gen_index}:")
|
||||||
|
else:
|
||||||
|
self.emitter.append(f"elif {index} == {gen_index}:")
|
||||||
|
with self.emitter.indent():
|
||||||
|
self.emitter.append(f"{gen_value} = {self(elem)}")
|
||||||
|
self.emitter.append(f"else:")
|
||||||
|
with self.emitter.indent():
|
||||||
|
self.emitter.append(f"{gen_value} = {self(value.elems[-1])}")
|
||||||
|
|
||||||
return gen_value
|
return gen_value
|
||||||
else:
|
else:
|
||||||
return f"0"
|
return f"0"
|
||||||
|
@ -319,16 +333,27 @@ class _LHSValueCompiler(_ValueCompiler):
|
||||||
index_mask = (1 << len(value.index)) - 1
|
index_mask = (1 << len(value.index)) - 1
|
||||||
gen_index = self.emitter.def_var("index", f"{self.rrhs(value.index)} & {index_mask:#x}")
|
gen_index = self.emitter.def_var("index", f"{self.rrhs(value.index)} & {index_mask:#x}")
|
||||||
if value.elems:
|
if value.elems:
|
||||||
for index, elem in enumerate(value.elems):
|
if _USE_PATTERN_MATCHING:
|
||||||
if index == 0:
|
self.emitter.append(f"match {gen_index}:")
|
||||||
self.emitter.append(f"if {index} == {gen_index}:")
|
|
||||||
else:
|
|
||||||
self.emitter.append(f"elif {index} == {gen_index}:")
|
|
||||||
with self.emitter.indent():
|
with self.emitter.indent():
|
||||||
self(elem)(arg)
|
for index, elem in enumerate(value.elems):
|
||||||
self.emitter.append(f"else:")
|
self.emitter.append(f"case {index}:")
|
||||||
with self.emitter.indent():
|
with self.emitter.indent():
|
||||||
self(value.elems[-1])(arg)
|
self(elem)(arg)
|
||||||
|
self.emitter.append("case _:")
|
||||||
|
with self.emitter.indent():
|
||||||
|
self(value.elems[-1])(arg)
|
||||||
|
else:
|
||||||
|
for index, elem in enumerate(value.elems):
|
||||||
|
if index == 0:
|
||||||
|
self.emitter.append(f"if {index} == {gen_index}:")
|
||||||
|
else:
|
||||||
|
self.emitter.append(f"elif {index} == {gen_index}:")
|
||||||
|
with self.emitter.indent():
|
||||||
|
self(elem)(arg)
|
||||||
|
self.emitter.append(f"else:")
|
||||||
|
with self.emitter.indent():
|
||||||
|
self(value.elems[-1])(arg)
|
||||||
else:
|
else:
|
||||||
self.emitter.append(f"pass")
|
self.emitter.append(f"pass")
|
||||||
return gen
|
return gen
|
||||||
|
|
Loading…
Reference in a new issue