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:
Jin Xue 2022-09-24 18:22:47 +08:00 committed by GitHub
parent c4be739d48
commit 3a51b61284
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1,6 +1,7 @@
import os
import tempfile
from contextlib import contextmanager
import sys
from ..hdl import *
from ..hdl.ast import SignalSet
@ -10,6 +11,7 @@ from ._base import BaseProcess
__all__ = ["PyRTLProcess"]
_USE_PATTERN_MATCHING = (sys.version_info >= (3, 10))
class PyRTLProcess(BaseProcess):
__slots__ = ("is_comb", "runnable", "passive", "run")
@ -228,6 +230,17 @@ class _RHSValueCompiler(_ValueCompiler):
gen_index = self.emitter.def_var("rhs_index", f"{index_mask:#x} & {self(value.index)}")
gen_value = self.emitter.gen_var("rhs_proxy")
if value.elems:
if _USE_PATTERN_MATCHING:
self.emitter.append(f"match {gen_index}:")
with self.emitter.indent():
for index, elem in enumerate(value.elems):
self.emitter.append(f"case {index}:")
with self.emitter.indent():
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}:")
@ -238,6 +251,7 @@ class _RHSValueCompiler(_ValueCompiler):
self.emitter.append(f"else:")
with self.emitter.indent():
self.emitter.append(f"{gen_value} = {self(value.elems[-1])}")
return gen_value
else:
return f"0"
@ -319,6 +333,17 @@ class _LHSValueCompiler(_ValueCompiler):
index_mask = (1 << len(value.index)) - 1
gen_index = self.emitter.def_var("index", f"{self.rrhs(value.index)} & {index_mask:#x}")
if value.elems:
if _USE_PATTERN_MATCHING:
self.emitter.append(f"match {gen_index}:")
with self.emitter.indent():
for index, elem in enumerate(value.elems):
self.emitter.append(f"case {index}:")
with self.emitter.indent():
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}:")