1
0
mirror of https://github.com/myhdl/myhdl.git synced 2025-01-24 21:52:56 +08:00

Removed support for Python 3.7 (which is End Of Life since 2023-06-27) (#430)

* Removed support for Python 3.7 (which is End Of Life since 2023-06-27)
Removed stray ast.Str and the like , which throw deprecation warnings in Python 3.12

* corrected import pathj for raises_kind

* corrected `ord` value assignemnt in _toVerilog.py
removed forgotten ast.dump call from _analyze.py
This commit is contained in:
Josy Boelen 2024-06-03 11:57:39 +02:00 committed by GitHub
parent e95762e4ef
commit e356d8a589
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 122 additions and 284 deletions

View File

@ -34,7 +34,7 @@ jobs:
strategy: strategy:
fail-fast: false # So that one fail doesn't stop remaining tests fail-fast: false # So that one fail doesn't stop remaining tests
matrix: matrix:
python-version: ["3.7", "3.8", "3.9", "3.10", "pypy-3.9", "3.11"] python-version: ["3.8", "3.9", "pypy-3.9", "3.10", "pypy-3.10","3.11", "3.12"]
target: [core, iverilog, ghdl] target: [core, iverilog, ghdl]
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [run_lint, build_ghdl_linux, build_iverilog_linux] needs: [run_lint, build_ghdl_linux, build_iverilog_linux]
@ -85,7 +85,7 @@ jobs:
strategy: strategy:
fail-fast: false # So that one fail doesn't stop remaining tests fail-fast: false # So that one fail doesn't stop remaining tests
matrix: matrix:
python-version: ["3.11"] python-version: ["3.12"]
#target: [core, iverilog, ghdl] #target: [core, iverilog, ghdl]
target: [core, ghdl] target: [core, ghdl]
runs-on: windows-latest runs-on: windows-latest

View File

@ -49,7 +49,7 @@ traceSignals -- function that enables signal tracing in a VCD file
toVerilog -- function that converts a design to Verilog toVerilog -- function that converts a design to Verilog
""" """
__version__ = "0.11.45" __version__ = "0.11.46"
class StopSimulation(Exception): class StopSimulation(Exception):

View File

@ -30,7 +30,6 @@ import ast
import builtins import builtins
from itertools import chain from itertools import chain
import myhdl
import myhdl import myhdl
from myhdl import * from myhdl import *
from myhdl import ConversionError from myhdl import ConversionError
@ -268,12 +267,8 @@ class _FirstPassVisitor(ast.NodeVisitor, _ConversionMixin):
def visit_Call(self, node): def visit_Call(self, node):
# ast.Call signature changed in python 3.5 # ast.Call signature changed in python 3.5
# http://greentreesnakes.readthedocs.org/en/latest/nodes.html#Call # http://greentreesnakes.readthedocs.org/en/latest/nodes.html#Call
if sys.version_info >= (3, 5):
starargs = any(isinstance(arg, ast.Starred) for arg in node.args) starargs = any(isinstance(arg, ast.Starred) for arg in node.args)
kwargs = any(kw.arg is None for kw in node.keywords) kwargs = any(kw.arg is None for kw in node.keywords)
else:
starargs = node.starargs is not None
kwargs = node.kwargs is not None
if starargs: if starargs:
self.raiseError(node, _error.NotSupported, "extra positional arguments") self.raiseError(node, _error.NotSupported, "extra positional arguments")
@ -297,8 +292,8 @@ class _FirstPassVisitor(ast.NodeVisitor, _ConversionMixin):
# put official docstrings aside for separate processing # put official docstrings aside for separate processing
node.doc = None node.doc = None
if node.body and isinstance(node.body[0], ast.Expr) and \ if node.body and isinstance(node.body[0], ast.Expr) and \
isinstance(node.body[0].value, ast.Str): isinstance(node.body[0].value, ast.Constant) and isinstance(node.body[0].value.value, str):
node.doc = node.body[0].value.s node.doc = node.body[0].value.value
node.body = node.body[1:] node.body = node.body[1:]
self.visitList(node.body) self.visitList(node.body)
@ -594,7 +589,11 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
# # node.obj = _EdgeDetector() # # node.obj = _EdgeDetector()
elif f is ord: elif f is ord:
node.obj = int(-1) node.obj = int(-1)
if not (isinstance(node.args[0], ast.Str) and (len(node.args[0].s) == 1)): if isinstance(node.args[0], ast.Constant) and \
isinstance(node.args[0].value, str) and \
(len(node.args[0].value) == 1):
pass
else:
self.raiseError(node, _error.NotSupported, self.raiseError(node, _error.NotSupported,
"ord: expect string argument with length 1") "ord: expect string argument with length 1")
elif f is delay: elif f is delay:
@ -682,8 +681,6 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
elif v == 1: elif v == 1:
node.edge = sig.posedge node.edge = sig.posedge
if sys.version_info >= (3, 9, 0):
def visit_Constant(self, node): def visit_Constant(self, node):
node.obj = None # safeguarding? node.obj = None # safeguarding?
# ToDo check for tuples? # ToDo check for tuples?
@ -700,25 +697,6 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
# Str # Str
node.obj = node.value node.obj = node.value
else:
def visit_Num(self, node):
n = node.n
# assign to value attribute for backwards compatibility
node.value = n
if n in (0, 1):
node.obj = bool(n)
elif isinstance(n, int):
node.obj = n
else:
node.obj = None
def visit_Str(self, node):
node.obj = node.s
def visit_NameConstant(self, node):
node.obj = node.value
def visit_Continue(self, node): def visit_Continue(self, node):
self.labelStack[-1].isActive = True self.labelStack[-1].isActive = True
@ -918,12 +896,12 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
for n in node.args: for n in node.args:
if isinstance(n, ast.BinOp) and isinstance(n.op, ast.Mod) and \ if isinstance(n, ast.BinOp) and isinstance(n.op, ast.Mod) and \
isinstance(n.left, ast.Str): isinstance(n.left, ast.Constant) and isinstance(n.left.value, str):
if isinstance(n.right, ast.Tuple): if isinstance(n.right, ast.Tuple):
a.extend(n.right.elts) a.extend(n.right.elts)
else: else:
a.append(n.right) a.append(n.right)
s = n.left.s s = n.left.value
while s: while s:
if not s: if not s:
break break
@ -950,8 +928,8 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
s = s[m.end():] s = s[m.end():]
continue continue
self.raiseError(node, _error.UnsupportedFormatString, "%s" % s) self.raiseError(node, _error.UnsupportedFormatString, "%s" % s)
elif isinstance(n, ast.Str): elif isinstance(n, ast.Constant) and isinstance(n.value, str):
f.append(n.s) f.append(n.value)
else: else:
f.append(defaultConvSpec) f.append(defaultConvSpec)
a.append(n) a.append(n)

View File

@ -937,9 +937,9 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
# in python3 a negative Num is represented as an USub of a positive Num # in python3 a negative Num is represented as an USub of a positive Num
# Fix: restore python2 behavior by a shortcut: invert value of Constant, inherit # Fix: restore python2 behavior by a shortcut: invert value of Constant, inherit
# vhdl type from UnaryOp node, and visit the modified operand # vhdl type from UnaryOp node, and visit the modified operand
if sys.version_info >= (3, 8, 0): if isinstance(node.op, ast.USub) and isinstance(node.operand, ast.Constant) and isinstance(node.operand.value, int):
if isinstance(node.op, ast.USub) and isinstance(node.operand, ast.Constant): # assume number
node.operand.n = -node.operand.n node.operand.value = -node.operand.value
node.operand.vhd = node.vhd node.operand.vhd = node.vhd
self.visit(node.operand) self.visit(node.operand)
return return
@ -966,35 +966,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.visit(node.operand) self.visit(node.operand)
self.write(")") self.write(")")
self.write(suf) self.write(suf)
else:
if isinstance(node.op, ast.USub) and isinstance(node.operand, ast.Num):
node.operand.n = -node.operand.n
node.operand.vhd = node.vhd
self.visit(node.operand)
return
pre, suf = self.inferCast(node.vhd, node.vhdOri)
if isinstance(node.op, ast.UAdd):
op = ""
else:
op = opmap[type(node.op)]
if isinstance(node.operand, ast.Num):
self.write("(")
self.write(op)
self.write("(")
self.write(pre)
self.visit(node.operand)
self.write(suf)
self.write(")")
self.write(")")
else:
self.write(pre)
self.write("(")
self.write(op)
self.visit(node.operand)
self.write(")")
self.write(suf)
def visit_Attribute(self, node): def visit_Attribute(self, node):
if isinstance(node.ctx, ast.Store): if isinstance(node.ctx, ast.Store):
@ -1185,20 +1156,16 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
return return
elif f is ord: elif f is ord:
opening, closing = '', '' opening, closing = '', ''
v = ord(node.args[0].s) v = ord(node.args[0].value)
node.args[0].s = v node.args[0].value = v
self.write(v) self.write(v)
return return
elif f is int: elif f is int:
opening, closing = '', '' opening, closing = '', ''
pre, suf = self.inferCast(node.vhd, node.vhdOri) pre, suf = self.inferCast(node.vhd, node.vhdOri)
# convert number argument to integer # convert number argument to integer
if sys.version_info >= (3, 8, 0):
if isinstance(node.args[0], ast.Constant): if isinstance(node.args[0], ast.Constant):
node.args[0].n = int(node.args[0].n) node.args[0].n = int(node.args[0].value)
else:
if isinstance(node.args[0], ast.Num):
node.args[0].n = int(node.args[0].n)
elif inspect.isclass(f) and issubclass(f, intbv): elif inspect.isclass(f) and issubclass(f, intbv):
pre, post = "", "" pre, post = "", ""
arg = node.args[0] arg = node.args[0]
@ -1277,8 +1244,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.visit(right) self.visit(right)
self.write(suf) self.write(suf)
if sys.version_info >= (3, 9, 0):
def visit_Constant(self, node): def visit_Constant(self, node):
if node.value is None: if node.value is None:
# NameConstant # NameConstant
@ -1320,60 +1285,19 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
typemark = 'unsigned' typemark = 'unsigned'
self.write("%s'(\"%s\")" % (typemark, node.value)) self.write("%s'(\"%s\")" % (typemark, node.value))
else:
def visit_Num(self, node):
n = node.n
if isinstance(node.vhd, vhd_std_logic):
self.write("'%s'" % n)
elif isinstance(node.vhd, vhd_boolean):
self.write("%s" % bool(n))
# elif isinstance(node.vhd, (vhd_unsigned, vhd_signed)):
# self.write('"%s"' % tobin(n, node.vhd.size))
elif isinstance(node.vhd, vhd_unsigned):
if abs(n) < 2 ** 31:
self.write("to_unsigned(%s, %s)" % (n, node.vhd.size))
else:
self.write('unsigned\'("%s")' % tobin(n, node.vhd.size))
elif isinstance(node.vhd, vhd_signed):
if abs(n) < 2 ** 31:
self.write("to_signed(%s, %s)" % (n, node.vhd.size))
else:
self.write('signed\'("%s")' % tobin(n, node.vhd.size))
else:
if n < 0:
self.write("(")
self.write(n)
if n < 0:
self.write(")")
def visit_Str(self, node):
typemark = 'string'
if isinstance(node.vhd, vhd_unsigned):
typemark = 'unsigned'
self.write("%s'(\"%s\")" % (typemark, node.s))
def visit_NameConstant(self, node):
node.id = str(node.value)
self.getName(node)
def visit_Continue(self, node, *args): def visit_Continue(self, node, *args):
self.write("next;") self.write("next;")
def visit_Expr(self, node): def visit_Expr(self, node):
expr = node.value expr = node.value
# docstrings on unofficial places # docstrings on unofficial places
if isinstance(expr, ast.Str): if isinstance(expr, ast.Constant) and isinstance(expr.value, str):
doc = _makeDoc(expr.s, self.ind) doc = _makeDoc(expr.value, self.ind)
self.write(doc) self.write(doc)
return return
# skip extra semicolons # skip extra semicolons
if sys.version_info >= (3, 8, 0):
if isinstance(expr, ast.Constant): if isinstance(expr, ast.Constant):
return return
else:
if isinstance(expr, ast.Num):
return
self.visit(expr) self.visit(expr)
# ugly hack to detect an orphan "task" call # ugly hack to detect an orphan "task" call
if isinstance(expr, ast.Call) and hasattr(expr, 'tree'): if isinstance(expr, ast.Call) and hasattr(expr, 'tree'):
@ -2419,7 +2343,7 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
if f is concat: if f is concat:
s = 0 s = 0
for a in node.args: for a in node.args:
if isinstance(a, ast.Str): if isinstance(a, ast.Constant) and isinstance(a.value, str):
a.vhd = vhd_unsigned(a.vhd.size) a.vhd = vhd_unsigned(a.vhd.size)
elif isinstance(a.vhd, vhd_signed): elif isinstance(a.vhd, vhd_signed):
a.vhd = vhd_unsigned(a.vhd.size) a.vhd = vhd_unsigned(a.vhd.size)
@ -2458,8 +2382,6 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
right.vhd = vhd_signed(right.vhd.size + 1) right.vhd = vhd_signed(right.vhd.size + 1)
node.vhdOri = copy(node.vhd) node.vhdOri = copy(node.vhd)
if sys.version_info >= (3, 9, 0):
def visit_Constant(self, node): def visit_Constant(self, node):
if node.value is None: if node.value is None:
# NameConstant # NameConstant
@ -2478,23 +2400,6 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
node.vhd = vhd_string() node.vhd = vhd_string()
node.vhdOri = copy(node.vhd) node.vhdOri = copy(node.vhd)
else:
def visit_Str(self, node):
node.vhd = vhd_string()
node.vhdOri = copy(node.vhd)
def visit_Num(self, node):
if node.n < 0:
node.vhd = vhd_int()
else:
node.vhd = vhd_nat()
node.vhdOri = copy(node.vhd)
def visit_NameConstant(self, node):
node.vhd = inferVhdlObj(node.value)
node.vhdOri = copy(node.vhd)
def visit_For(self, node): def visit_For(self, node):
var = node.target.id var = node.target.id
# make it possible to detect loop variable # make it possible to detect loop variable
@ -2513,7 +2418,7 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
self.inferShiftType(node) self.inferShiftType(node)
elif isinstance(node.op, (ast.BitAnd, ast.BitOr, ast.BitXor)): elif isinstance(node.op, (ast.BitAnd, ast.BitOr, ast.BitXor)):
self.inferBitOpType(node) self.inferBitOpType(node)
elif isinstance(node.op, ast.Mod) and isinstance(node.left, ast.Str): # format string elif isinstance(node.op, ast.Mod) and isinstance(node.left, ast.Constant) and isinstance(node.left.value, str): # format string
pass pass
else: else:
self.inferBinOpType(node) self.inferBinOpType(node)

View File

@ -858,16 +858,12 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
return return
elif f is ord: elif f is ord:
opening, closing = '', '' opening, closing = '', ''
node.args[0].s = str(ord(node.args[0].s)) node.args[0].value = str(ord(node.args[0].value))
elif f is int: elif f is int:
opening, closing = '', '' opening, closing = '', ''
# convert number argument to integer # convert number argument to integer
if sys.version_info >= (3, 8, 0):
if isinstance(node.args[0], ast.Constant): if isinstance(node.args[0], ast.Constant):
node.args[0].n = int(node.args[0].n) node.args[0].value = int(node.args[0].value)
else:
if isinstance(node.args[0], ast.Num):
node.args[0].n = int(node.args[0].n)
elif f in (intbv, modbv): elif f in (intbv, modbv):
self.visit(node.args[0]) self.visit(node.args[0])
return return
@ -919,8 +915,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.write(")") self.write(")")
self.context = None self.context = None
if sys.version_info >= (3, 9, 0):
def visit_Constant(self, node): def visit_Constant(self, node):
if node.value is None: if node.value is None:
# NameConstant # NameConstant
@ -943,43 +937,19 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
else: else:
self.write(s) self.write(s)
else:
def visit_Num(self, node):
if self.context == _context.PRINT:
self.write('"%s"' % node.n)
else:
self.write(self.IntRepr(node.n))
def visit_Str(self, node):
s = node.s
if self.context == _context.PRINT:
self.write('"%s"' % s)
elif len(s) == s.count('0') + s.count('1'):
self.write("%s'b%s" % (len(s), s))
else:
self.write(s)
def visit_NameConstant(self, node):
self.write(nameconstant_map[node.obj])
def visit_Continue(self, node): def visit_Continue(self, node):
self.write("disable %s;" % self.labelStack[-1]) self.write("disable %s;" % self.labelStack[-1])
def visit_Expr(self, node): def visit_Expr(self, node):
expr = node.value expr = node.value
# docstrings on unofficial places # docstrings on unofficial places
if isinstance(expr, ast.Str): if isinstance(expr, ast.Constant) and isinstance(expr.value, str):
doc = _makeDoc(expr.s, self.ind) doc = _makeDoc(expr.value, self.ind)
self.write(doc) self.write(doc)
return return
# skip extra semicolons # skip extra semicolons
if sys.version_info >= (3, 8, 0):
if isinstance(expr, ast.Constant): if isinstance(expr, ast.Constant):
return return
else:
if isinstance(expr, ast.Num):
return
self.visit(expr) self.visit(expr)
# ugly hack to detect an orphan "task" call # ugly hack to detect an orphan "task" call
if isinstance(expr, ast.Call) and hasattr(expr, 'tree'): if isinstance(expr, ast.Call) and hasattr(expr, 'tree'):
@ -1708,12 +1678,8 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
node.signed = node.operand.signed node.signed = node.operand.signed
if isinstance(node.op, ast.USub): if isinstance(node.op, ast.USub):
node.obj = int(-1) node.obj = int(-1)
if sys.version_info >= (3, 8, 0):
if isinstance(node.operand, ast.Constant): if isinstance(node.operand, ast.Constant):
node.signed = True node.signed = True
else:
if isinstance(node.operand, ast.Num):
node.signed = True
def visit_Attribute(self, node): def visit_Attribute(self, node):
if isinstance(node.ctx, ast.Store): if isinstance(node.ctx, ast.Store):
@ -1753,22 +1719,9 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
return return
self.generic_visit(node) self.generic_visit(node)
if sys.version_info >= (3, 9, 0):
def visit_Constant(self, node): def visit_Constant(self, node):
node.signed = False node.signed = False
else:
def visit_Num(self, node):
node.signed = False
def visit_Str(self, node):
node.signed = False
def visit_NameConstant(self, node):
node.signed = False
def visit_Name(self, node): def visit_Name(self, node):
if isinstance(node.ctx, ast.Store): if isinstance(node.ctx, ast.Store):
self.setName(node) self.setName(node)

View File

@ -13,6 +13,7 @@ def bench_SliceSignal():
@instance @instance
def check(): def check():
''' Running bench_SliceSignal '''
for i in range(N): for i in range(N):
s.next = i s.next = i
yield delay(10) yield delay(10)

View File

@ -51,7 +51,7 @@ setup(
license="LGPL", license="LGPL",
platforms='any', platforms='any',
keywords="HDL ASIC FPGA hardware design", keywords="HDL ASIC FPGA hardware design",
python_requires='>=3.7', python_requires='>=3.8',
classifiers=[ classifiers=[
'Development Status :: 5 - Production/Stable', 'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers', 'Intended Audience :: Developers',
@ -60,10 +60,11 @@ setup(
'Operating System :: OS Independent', 'Operating System :: OS Independent',
'Programming Language :: Python', 'Programming Language :: Python',
'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
'Programming Language :: Python :: 3 :: Only', 'Programming Language :: Python :: 3 :: Only',
] ]
) )