From e95762e4efe7077b9e330fc132e69b53c6f81976 Mon Sep 17 00:00:00 2001 From: Josy Boelen Date: Sun, 4 Feb 2024 18:40:30 +0100 Subject: [PATCH] Init list of enums (#428) * correct initial_values for List Of Signal(enum) * added dedicated test for ListOfSignal(enum) --- myhdl/__init__.py | 2 +- myhdl/conversion/_toVHDL.py | 13 ++- myhdl/conversion/_toVerilog.py | 42 ++++---- .../conversion/general/test_listofenums.py | 97 +++++++++++++++++++ 4 files changed, 129 insertions(+), 25 deletions(-) create mode 100644 myhdl/test/conversion/general/test_listofenums.py diff --git a/myhdl/__init__.py b/myhdl/__init__.py index abbba11c..adc765c6 100644 --- a/myhdl/__init__.py +++ b/myhdl/__init__.py @@ -49,7 +49,7 @@ traceSignals -- function that enables signal tracing in a VCD file toVerilog -- function that converts a design to Verilog """ -__version__ = "0.11.44" +__version__ = "0.11.45" class StopSimulation(Exception): diff --git a/myhdl/conversion/_toVHDL.py b/myhdl/conversion/_toVHDL.py index 3d92b11c..b9820730 100644 --- a/myhdl/conversion/_toVHDL.py +++ b/myhdl/conversion/_toVHDL.py @@ -224,7 +224,6 @@ class _ToVHDLConvertor(object): raise ToVHDLError(_error.PortInList, portname) # add enum types to port-related set if isinstance(s._val, EnumItemType): - print('EnumItemType', s._val) obj = s._val._type if obj in _enumTypeSet: _enumTypeSet.remove(obj) @@ -544,14 +543,20 @@ def _writeSigDecls(f, intf, siglist, memlist): val_str = ( ' := (others => \'%s\')' % str(int(m.mem[0]._init))) + elif isinstance(m.mem[0]._init, EnumItemType): + val_str = (' := (others => {})'.format(m.mem[0]._init._toVHDL())) else: val_str = ( ' := (others => %dX"%s")' % (sig_vhdl_objs[0].size, str(m.mem[0]._init))) else: - _val_str = ',\n '.join( - ['%dX"%s"' % (obj.size, str(each._init)) for - obj, each in zip(sig_vhdl_objs, m.mem)]) + if isinstance(m.mem[0]._init, EnumItemType): + _val_str = ',\n '.join(['{}'.format(each._init._toVHDL()) for + each in m.mem]) + else: + _val_str = ',\n '.join( + ['%dX"%s"' % (obj.size, str(each._init)) for + obj, each in zip(sig_vhdl_objs, m.mem)]) val_str = ' := (\n ' + _val_str + ')' diff --git a/myhdl/conversion/_toVerilog.py b/myhdl/conversion/_toVerilog.py index fcac4de6..6607c95a 100644 --- a/myhdl/conversion/_toVerilog.py +++ b/myhdl/conversion/_toVerilog.py @@ -37,19 +37,18 @@ import warnings import myhdl from myhdl import * from myhdl import ToVerilogError, ToVerilogWarning +from myhdl._block import _Block +from myhdl._enum import EnumItemType from myhdl._extractHierarchy import (_HierExtr, _isMem, _getMemInfo, _UserVerilogCode, _userCodeMap) - +from myhdl._getHierarchy import _getHierarchy from myhdl._instance import _Instantiator +from myhdl._Signal import _Signal, Constant +from myhdl._ShadowSignal import _TristateSignal, _TristateDriver from myhdl.conversion._misc import (_error, _kind, _context, _ConversionMixin, _Label, _genUniqueSuffix, _isConstant) from myhdl.conversion._analyze import (_analyzeSigs, _analyzeGens, _analyzeTopFunc, _Ram, _Rom) -from myhdl._Signal import _Signal, Constant -from myhdl._ShadowSignal import _TristateSignal, _TristateDriver - -from myhdl._block import _Block -from myhdl._getHierarchy import _getHierarchy _converting = 0 _profileFunc = None @@ -501,20 +500,23 @@ def _intRepr(n, radix=''): # write size for large integers (beyond 32 bits signed) # with some safety margin # XXX signed indication 's' ??? - p = abs(n) - size = '' - num = str(p).rstrip('L') - if radix == "hex" or p >= 2 ** 30: - radix = "'h" - num = hex(p)[2:].rstrip('L') - if p >= 2 ** 30: - size = int(math.ceil(math.log(p + 1, 2))) + 1 # sign bit! -# if not radix: -# radix = "'d" - r = "%s%s%s" % (size, radix, num) - if n < 0: # add brackets and sign on negative numbers - r = "(-%s)" % r - return r + if isinstance(n, EnumItemType): + return n._toVerilog() + else: + p = abs(n) + size = '' + num = str(p).rstrip('L') + if radix == "hex" or p >= 2 ** 30: + radix = "'h" + num = hex(p)[2:].rstrip('L') + if p >= 2 ** 30: + size = int(math.ceil(math.log(p + 1, 2))) + 1 # sign bit! + # if not radix: + # radix = "'d" + r = "%s%s%s" % (size, radix, num) + if n < 0: # add brackets and sign on negative numbers + r = "(-%s)" % r + return r def _convertGens(genlist, vfile): diff --git a/myhdl/test/conversion/general/test_listofenums.py b/myhdl/test/conversion/general/test_listofenums.py new file mode 100644 index 00000000..e2db58d3 --- /dev/null +++ b/myhdl/test/conversion/general/test_listofenums.py @@ -0,0 +1,97 @@ +''' +Created on 4 feb. 2024 + +@author: josy +''' + +from myhdl import (block, Signal, intbv, delay, always_comb, always_seq, enum, + always, instance, StopSimulation, ResetSignal, Constant, + conversion) +from myhdl import ConversionError +from myhdl.conversion._misc import _error + + +@block +def listofenums(Clk, Reset, Start, Progress, Ended): + listofenums_states = enum('IDLE', 'Doing_Nothing', 'Procrastinating', 'Getting_Ready', 'Executing', encoding='one_hot') + + smn, smp = [Signal(listofenums_states.IDLE) for __ in range(2)] + stack = [Constant(listofenums_states.IDLE), + Constant(listofenums_states.Doing_Nothing), + Constant(listofenums_states.Procrastinating), + Constant(listofenums_states.Getting_Ready), + Constant(listofenums_states.Executing)] + NBR_STATES = len(stack) + stateindex = Signal(intbv(0)[3:]) + + @always_comb + def smcomb(): + Ended.next = 0 + + # if smp == listofenums_states.IDLE: + if Start: + smn.next = stack[1] + # else: + # smn.next = smp + elif Progress: + if stateindex < NBR_STATES - 1: + smn.next = stack[stateindex + 1] + else: + smn.next = smp + else: + smn.next = smp + + ''' + note that if we exchange the two following lines + we get a failing conversion to VHDL (only; Verilog is fine ...) + ''' + if smp == listofenums_states.Executing: + # if stateindex == NBR_STATES - 1: + Ended.next = 1 + + # smn.next = smp + # if smp == listofenums_states.IDLE: + # if Start: + # smn.next = listofenums_states.Doing_Nothing + # + # elif smp == listofenums_states.Doing_Nothing: + # if Start: + # smn.next = listofenums_states.Procrastinating + # + # elif smp == listofenums_states.Procrastinating: + # if Start: + # smn.next = listofenums_states.Getting_Ready + # + # elif smp == listofenums_states.Getting_Ready: + # if Start: + # smn.next = listofenums_states.Executing + # + # elif smp == listofenums_states.Executing: + # smn.next = listofenums_states.Executing + # Ended.next = 1 + # + # else: + # smn.next = listofenums_states.IDLE + + @always_seq(Clk.posedge, reset=Reset) + def smsync(): + smp.next = smn + if Start or Progress: + if stateindex < NBR_STATES - 1: + stateindex.next = stateindex + 1 + + return smcomb, smsync + + +def test_listofenums(): + Clk, Start, Progress, Ended = [Signal(bool(0)) for __ in range(4)] + Reset = ResetSignal(0, 1, False) + assert listofenums(Clk, Reset, Start, Progress, Ended).analyze_convert() == 0 + + +if __name__ == '__main__': + Clk, Start, Progress, Ended = [Signal(bool(0)) for __ in range(4)] + Reset = ResetSignal(0, 1, False) + dfc = listofenums(Clk, Reset, Start, Progress, Ended) + dfc.convert(hdl='Verilog', initial_values=True) + dfc.convert(hdl='VHDL', initial_values=True)