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

Conversion with recursive ShadowSignals (#359)

* _ShadowSignal.py: conversion:
  enabled taking a ShadowSignal of a ShadowSignal,
  reworked _setName() to aggregate chained slicing/indexing to a single slice or index
  marked the shadowed Signal as  always 'read'
_intbv.py: added the [n:] to __repr__
_toVHDL.py: added a comment

* added test for recursive/chained ShadowSignals

* added missing returned instance

* wrong startvalue

* Changed a docstring to launch GitHub actions on origin
This commit is contained in:
Josy Boelen 2022-08-01 18:57:07 +02:00 committed by GitHub
parent 0477c7e042
commit e6ac73214e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 96 additions and 26 deletions

View File

@ -17,10 +17,10 @@
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
""" Module that provides the ShadowSignal classes
"""
Module that provides the ShadowSignal classes
"""
import warnings
from copy import deepcopy
@ -35,7 +35,7 @@ from myhdl._bin import bin
class _ShadowSignal(_Signal):
__slots__ = ('_waiter', )
__slots__ = ('_waiter',)
def __init__(self, val):
_Signal.__init__(self, val)
@ -58,6 +58,7 @@ class _SliceSignal(_ShadowSignal):
else:
_ShadowSignal.__init__(self, sig[left:right])
self._sig = sig
sig._read = True
self._left = left
self._right = right
if right is None:
@ -66,6 +67,12 @@ class _SliceSignal(_ShadowSignal):
gen = self._genfuncSlice()
self._waiter = _SignalWaiter(gen)
def __repr__(self):
if self._right is None:
return repr(self._sig) + '({})'.format(self._left)
else:
return repr(self._sig) + '({}, {})'.format(self._left, self._right)
def _genfuncIndex(self):
sig, index = self._sig, self._left
set_next = _Signal.next.fset
@ -81,6 +88,24 @@ class _SliceSignal(_ShadowSignal):
yield sig
def _setName(self, hdl):
# if we depend on a ShadowSignal ourselves
# it would be nice if we 'resolve' the slicing chain
# e.g. s[7:4][1:0][1] to s[5]
if isinstance(self._sig, _ShadowSignal):
# self._sig must have a _left and a _right
if self._right is None:
# we're a final index
self._left = self._sig._right + self._left
else:
self._right = self._sig._right + self._right
self._left = self._sig._right + self._left
# step one back up
self._sig = self._sig._sig
else:
# we're at the top of the chain
pass
if self._right is None:
if hdl == 'Verilog':
self._name = "%s[%s]" % (self._sig._name, self._left)
@ -91,6 +116,10 @@ class _SliceSignal(_ShadowSignal):
self._name = "%s[%s-1:%s]" % (self._sig._name, self._left, self._right)
else:
self._name = "%s(%s-1 downto %s)" % (self._sig._name, self._left, self._right)
# we may have 'shadowed' as well (and further down ...)
if self._slicesigs:
for sl in self._slicesigs:
sl._setName(hdl)
def _markRead(self):
self._read = True
@ -306,13 +335,13 @@ class ConcatSignal(_ShadowSignal):
hi = lo
return "\n".join(lines)
# Tristate signal
class BusContentionWarning(UserWarning):
pass
warnings.filterwarnings('always', r".*", BusContentionWarning)
# def Tristate(val, delay=None):

View File

@ -24,12 +24,12 @@ from myhdl._bin import bin
class intbv(object):
#__slots__ = ('_val', '_min', '_max', '_nrbits', '_handleBounds')
# __slots__ = ('_val', '_min', '_max', '_nrbits', '_handleBounds')
def __init__(self, val=0, min=None, max=None, _nrbits=0):
if _nrbits:
self._min = 0
self._max = 2**_nrbits
self._max = 2 ** _nrbits
else:
self._min = min
self._max = max
@ -476,14 +476,14 @@ class intbv(object):
# I would prefer sign extension with hex format, but to
# align with Verilog $display I don't do that
if v < 0:
v = 2**nrbits + v
v = 2 ** nrbits + v
w = (nrbits - 1) // 4 + 1
return "{:0{w}x}".format(v, w=w)
else:
return "{:x}".format(v)
def __repr__(self):
return "intbv(" + repr(self._val) + ")"
return "intbv(" + repr(self._val) + ")[{}:]".format(self._nrbits)
def signed(self):
''' Return new intbv with the values interpreted as signed
@ -541,7 +541,7 @@ class intbv(object):
retVal = self._val
if self._nrbits:
M = 2**(self._nrbits - 1)
M = 2 ** (self._nrbits - 1)
return intbv(retVal, min=-M, max=M)
else:
return intbv(retVal)
@ -561,4 +561,4 @@ class intbv(object):
if self._nrbits:
return intbv(retVal)[self._nrbits:]
else:
return intbv(retVal)
return intbv(retVal)

View File

@ -375,6 +375,7 @@ def _writeModuleHeader(f, intf, needPck, lib, arch, useClauses, doc, stdLogicPor
if stdLogicPorts and s._type is intbv:
s._name = portname + "_num"
convertPort = True
# override the names given by _analyze.py
for sl in s._slicesigs:
sl._setName('VHDL')
else:

View File

@ -1,12 +1,14 @@
import myhdl
from myhdl import *
from myhdl import (block, Signal, intbv, delay, always_comb, instance,
TristateSignal, ConcatSignal, conversion, StopSimulation,
toVerilog, toVHDL)
@block
def bench_SliceSignal():
s = Signal(intbv(0)[8:])
a, b, c = s(7), s(5), s(0)
d, e, f, g = s(8,5), s(6,3), s(8,0), s(4,3)
d, e, f, g = s(8, 5), s(6, 3), s(8, 0), s(4, 3)
N = len(s)
@instance
@ -29,6 +31,38 @@ def test_SliceSignal():
assert conversion.verify(bench_SliceSignal()) == 0
@block
def bench_RecurseShadowSignal():
s = Signal(intbv(0)[16:])
# take some recursive ShadowSignals
su = s(16, 8)
sl = s(8, 0)
suu = su(8, 4)
sul = su(4, 0)
slu = sl(8, 4)
sll = sl(4, 0)
@instance
def check():
for i in range(25):
s.next = 0x4567 + i * 39
yield delay(10)
print(s)
print(int(su))
print(int(sl))
print(suu)
print(sul)
print(slu)
print(sll)
return check
def test_RecurseShadowSignal():
assert conversion.verify(bench_RecurseShadowSignal()) == 0
@block
def bench_ConcatSignal():
@ -39,10 +73,11 @@ def bench_ConcatSignal():
s = ConcatSignal(a, b, c, d)
I_max = 2**len(a)
J_max = 2**len(b)
K_max = 2**len(c)
M_max = 2**len(d)
I_max = 2 ** len(a)
J_max = 2 ** len(b)
K_max = 2 ** len(c)
M_max = 2 ** len(d)
@instance
def check():
for i in range(I_max):
@ -58,9 +93,11 @@ def bench_ConcatSignal():
return check
def test_ConcatSignal():
assert conversion.verify(bench_ConcatSignal()) == 0
@block
def bench_ConcatSignalWithConsts():
@ -78,17 +115,18 @@ def bench_ConcatSignalWithConsts():
s = ConcatSignal(c1, a, c2, b, c3, c, c4, d, c5, e)
I_max = 2**len(a)
J_max = 2**len(b)
K_max = 2**len(c)
M_max = 2**len(d)
I_max = 2 ** len(a)
J_max = 2 ** len(b)
K_max = 2 ** len(c)
M_max = 2 ** len(d)
@instance
def check():
for i in range(I_max):
for j in range(J_max):
for k in range(K_max):
for m in range(M_max):
for n in range(2**len(e)):
for n in range(2 ** len(e)):
a.next = i
b.next = j
c.next = k
@ -135,7 +173,7 @@ def bench_TristateSignal():
b.next = None
c.next = None
yield delay(10)
#print s
# print s
a.next = 1
yield delay(10)
print(s)
@ -149,7 +187,7 @@ def bench_TristateSignal():
print(s)
c.next = None
yield delay(10)
#print s
# print s
return check
@ -186,7 +224,7 @@ def bench_permute(conv=False):
@instance
def stimulus():
for i in range(2**len(a)):
for i in range(2 ** len(a)):
a.next = i
yield delay(10)
print("%d %d" % (x, a))
@ -197,8 +235,10 @@ def bench_permute(conv=False):
return dut, stimulus
def test_permute():
assert conversion.verify(bench_permute()) == 0
bench_permute(toVHDL)
bench_permute(toVerilog)