From 77663828865d2ade244f1593c8f66208c8a682a8 Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke Date: Thu, 11 Jan 2024 10:50:16 +0100 Subject: [PATCH] migen/fhdl/tracer.py: update get_var_name() from amaranth This fixes exceptions when running the litedram tests. See below for the log of one of the test failures this fixes. The other test failures are pretty much identical. ``` ______________________________________________________________________________________________________ TestSimSerializers.test_sim_serializer_16_phase90 ______________________________________________________________________________________________________ self = def test(self): new = default.copy() new.update(kwargs) > self.serializer_test(**new) test/test_phy_utils.py:106: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/test_phy_utils.py:54: in serializer_test dut = Serializer(clk=clk, clkdiv=clkdiv, i_dw=data_width, o_dw=1) litedram/phy/utils.py:240: in __init__ if i is None: i = Signal(i_dw) /usr/lib/python3.11/site-packages/migen/fhdl/structure.py:395: in __init__ self.backtrace = _tracer.trace_back(name) /usr/lib/python3.11/site-packages/migen/fhdl/tracer.py:111: in trace_back varname = get_var_name(frame) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ frame = def get_var_name(frame): code = frame.f_code call_index = frame.f_lasti while call_index > 0 and opname[code.co_code[call_index]] == "CACHE": call_index -= 2 while True: call_opc = opname[code.co_code[call_index]] if call_opc in("EXTENDED_ARG",): call_index += 2 else: break if call_opc not in _call_opcodes: return None index = call_index+_call_opcodes[call_opc] while True: opc = opname[code.co_code[index]] if opc == "STORE_NAME" or opc == "STORE_ATTR": name_index = int(code.co_code[index+1]) return code.co_names[name_index] elif opc == "STORE_FAST": name_index = int(code.co_code[index+1]) return code.co_varnames[name_index] elif opc == "STORE_DEREF": name_index = int(code.co_code[index+1]) if version_info >= (3, 11): name_index -= code.co_nlocals > return code.co_cellvars[name_index] E IndexError: tuple index out of range /usr/lib/python3.11/site-packages/migen/fhdl/tracer.py:64: IndexError ``` --- migen/fhdl/tracer.py | 76 ++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 45 deletions(-) diff --git a/migen/fhdl/tracer.py b/migen/fhdl/tracer.py index 259cfc21..c5ffede6 100644 --- a/migen/fhdl/tracer.py +++ b/migen/fhdl/tracer.py @@ -1,39 +1,9 @@ import inspect +import sys from sys import version_info from opcode import opname from collections import defaultdict -# All opcodes are 2 bytes in length in Python 3.6 -def _bytecode_length_version_guard(old_len): - return old_len if version_info[1] < 6 else 2 - -_call_opcodes = { - "CALL_FUNCTION" : _bytecode_length_version_guard(3), - "CALL_FUNCTION_KW" : _bytecode_length_version_guard(3), -} - -if version_info[1] < 6: - _call_opcodes["CALL_FUNCTION_VAR"] = 3 - _call_opcodes["CALL_FUNCTION_VAR_KW"] = 3 -elif version_info[1] < 7: - _call_opcodes["CALL_FUNCTION_EX"] = 2 -else: - _call_opcodes["CALL_FUNCTION_EX"] = 2 - _call_opcodes["CALL_METHOD"] = 2 - _call_opcodes["CALL"] = 2 - -_load_build_opcodes = { - "LOAD_GLOBAL" : _bytecode_length_version_guard(3), - "LOAD_NAME" : _bytecode_length_version_guard(3), - "LOAD_ATTR" : _bytecode_length_version_guard(3), - "LOAD_FAST" : _bytecode_length_version_guard(3), - "LOAD_DEREF" : _bytecode_length_version_guard(3), - "DUP_TOP" : _bytecode_length_version_guard(1), - "BUILD_LIST" : _bytecode_length_version_guard(3), - "CACHE" : _bytecode_length_version_guard(3), - "COPY" : _bytecode_length_version_guard(3), -} - def get_var_name(frame): code = frame.f_code @@ -42,28 +12,44 @@ def get_var_name(frame): call_index -= 2 while True: call_opc = opname[code.co_code[call_index]] - if call_opc in("EXTENDED_ARG",): + if call_opc in ("EXTENDED_ARG",): call_index += 2 else: break - if call_opc not in _call_opcodes: + if call_opc not in ("CALL_FUNCTION", "CALL_FUNCTION_KW", "CALL_FUNCTION_EX", + "CALL_METHOD", "CALL", "CALL_KW"): return None - index = call_index+_call_opcodes[call_opc] + + index = call_index + 2 + imm = 0 while True: opc = opname[code.co_code[index]] - if opc == "STORE_NAME" or opc == "STORE_ATTR": - name_index = int(code.co_code[index+1]) - return code.co_names[name_index] + if opc == 'EXTENDED_ARG': + imm |= int(code.co_code[index + 1]) + imm <<= 8 + index += 2 + elif opc in ("STORE_NAME", "STORE_ATTR"): + imm |= int(code.co_code[index + 1]) + return code.co_names[imm] elif opc == "STORE_FAST": - name_index = int(code.co_code[index+1]) - return code.co_varnames[name_index] + imm |= int(code.co_code[index + 1]) + if sys.version_info >= (3, 11): + return code._varname_from_oparg(imm) + else: + return code.co_varnames[imm] elif opc == "STORE_DEREF": - name_index = int(code.co_code[index+1]) - if version_info >= (3, 11): - name_index -= code.co_nlocals - return code.co_cellvars[name_index] - elif opc in _load_build_opcodes: - index += _load_build_opcodes[opc] + imm |= int(code.co_code[index + 1]) + if sys.version_info >= (3, 11): + return code._varname_from_oparg(imm) + else: + if imm < len(code.co_cellvars): + return code.co_cellvars[imm] + else: + return code.co_freevars[imm - len(code.co_cellvars)] + elif opc in ("LOAD_GLOBAL", "LOAD_NAME", "LOAD_ATTR", "LOAD_FAST", "LOAD_DEREF", + "DUP_TOP", "BUILD_LIST", "CACHE", "COPY"): + imm = 0 + index += 2 else: return None