Skip to content

Commit

Permalink
testing/py3-migen: fix get_var_name() in tracer.py
Browse files Browse the repository at this point in the history
This fixes unit test failures in py3-litedram, which builds upon
py3-migen.

See m-labs/migen#283 for an effort to upstream
the patch and the log of the error this fixes.
  • Loading branch information
maribu authored and omni committed Jan 18, 2024
1 parent 332c98f commit 8c554f6
Show file tree
Hide file tree
Showing 4 changed files with 148 additions and 69 deletions.
113 changes: 113 additions & 0 deletions testing/py3-migen/0001-fix-get_var_name.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
Take get_var_name() from amaranth with minor impedance matching. This
fixes:

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)

See https://github.com/amaranth-lang/amaranth/blob/main/amaranth/tracer.py for
original source.

See https://github.com/m-labs/migen/pull/283 for an effort to upstream the fix.
--- a/migen/fhdl/tracer.py 2024-01-11 10:35:38.211748883 +0100
+++ b/migen/fhdl/tracer.py 2024-01-11 10:36:04.864735268 +0100
@@ -1,56 +1,55 @@
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
-
-_load_build_opcodes = {
- "LOAD_GLOBAL" : _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),
-}
-

def get_var_name(frame):
code = frame.f_code
call_index = frame.f_lasti
- call_opc = opname[code.co_code[call_index]]
- if call_opc not in _call_opcodes:
+ 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_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])
- 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

29 changes: 29 additions & 0 deletions testing/py3-migen/0002-fix-incorrect-use-of-is.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
Fix:

migen/fhdl/visit.py:86
/builds/maribu/aports/testing/py3-migen/src/migen-0.9.2/migen/fhdl/visit.py:86: SyntaxWarning: "is" with a literal. Did you mean "=="?
key=lambda x: -1 if x[0] is "default" else x[0].duid):
migen/fhdl/visit.py:191
/builds/maribu/aports/testing/py3-migen/src/migen-0.9.2/migen/fhdl/visit.py:191: SyntaxWarning: "is" with a literal. Did you mean "=="?
key=lambda x: -1 if x[0] is "default" else x[0].duid)}
migen/test/test_platform.py:47
--- a/migen/fhdl/visit.py 2024-01-11 16:52:08.195971473 +0100
+++ b/migen/fhdl/visit.py 2024-01-11 16:52:44.862281145 +0100
@@ -83,7 +83,7 @@ class NodeVisitor:
def visit_Case(self, node):
self.visit(node.test)
for v, statements in sorted(node.cases.items(),
- key=lambda x: -1 if x[0] is "default" else x[0].duid):
+ key=lambda x: -1 if isinstance(x[0], str) and x[0] == "default" else x[0].duid):
self.visit(statements)

def visit_Fragment(self, node):
@@ -188,7 +188,7 @@ class NodeTransformer:
def visit_Case(self, node):
cases = {v: self.visit(statements)
for v, statements in sorted(node.cases.items(),
- key=lambda x: -1 if x[0] is "default" else x[0].duid)}
+ key=lambda x: -1 if isinstance(x[0], str) and x[0] == "default" else x[0].duid)}
r = Case(self.visit(node.test), cases)
return r

11 changes: 6 additions & 5 deletions testing/py3-migen/APKBUILD
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
# Maintainer: Marian Buschsieweke <[email protected]>
# Contributor: Marian Buschsieweke <[email protected]>

# Maintainer: Marian Buschsieweke <[email protected]>
pkgname=py3-migen
_pkgname=migen
pkgver=0.9.2
pkgrel=0
pkgrel=1
pkgdesc="Python-based tool that aims at automating further the VLSI design process"
url="https://m-labs.hk/gateware/migen/"
license="BSD-2-Clause"
Expand All @@ -22,7 +21,8 @@ checkdepends="
source="
$pkgname-$pkgver.tar.gz::https://github.com/m-labs/migen/archive/refs/tags/$pkgver.tar.gz
d404437655107e99ee93101622cadf08fa103be1.patch
0001-fix-get_var_name.patch
0002-fix-incorrect-use-of-is.patch
"
builddir="$srcdir"/$_pkgname-$pkgver
subpackages="$pkgname-pyc"
Expand All @@ -46,5 +46,6 @@ package() {

sha512sums="
9ff39f9f9b7e99b7d933e39091eb7e98c413ec3e60b98722d813df30fe95484470a1a027ac08bdf065bf688f4bb53af2c4618d3bbc0f1086adab33e149dca98f py3-migen-0.9.2.tar.gz
a905c4fe7ca40f268fd23ec913cae17925aeed94d286093acad2c3e9bcb248824310a6846caed157548adbb0628a072c1cf5e9911bb4ed2001b53e50b93c279c d404437655107e99ee93101622cadf08fa103be1.patch
6287fc34278e84b942a5aaefafa86d1078f393a60f34393c39a4f8226c4ee7913b4f156a517d7deb26a92f90331fed84ac529bbb4dd36ca2d052492e72cf6402 0001-fix-get_var_name.patch
9ad29c4d5f95c31073d34b08dcd7de243330a5eb90f001f73fc4c7a2af17ebbb9855c431ae243ce4df0908f92155e38b60282779670c79e8b04dd44e110d75b9 0002-fix-incorrect-use-of-is.patch
"
64 changes: 0 additions & 64 deletions testing/py3-migen/d404437655107e99ee93101622cadf08fa103be1.patch

This file was deleted.

0 comments on commit 8c554f6

Please sign in to comment.