verilog_utils.py 8.32 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
from __future__ import print_function
'''
# Copyright (C) 2015, Elphel.inc.
# Methods that mimic Verilog tasks used for simulation  
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

@author:     Andrey Filippov
@copyright:  2015 Elphel, Inc.
@license:    GPLv3.0+
@contact:    andrey@elphel.coml
@deffield    updated: Updated
'''
__author__ = "Andrey Filippov"
__copyright__ = "Copyright 2015, Elphel, Inc."
__license__ = "GPL"
__version__ = "3.0+"
__maintainer__ = "Andrey Filippov"
__email__ = "andrey@elphel.com"
__status__ = "Development"
#import sys
#import x393_mem
#MCNTRL_TEST01_CHN4_STATUS_CNTRL=0
34
NUM_FINE_STEPS=    5
35 36 37 38 39
def hx(obj,length=None):
    frmt="0x%x"
    if (length):
        frmt="0x%0"+str(length)+"x"
    s=""        
40
    try:
41 42 43 44 45 46 47
        s=frmt%obj
        s1=s[0:2]
        for i in range(2,len(s)):
            if s[i] != '0':
                break
            s1+="o"
        s=s1+s[len(s1):]    
48
    except:
49 50
        s=str(obj)
    return s
51 52 53 54
'''
Simulate Verilog concatenation. Input list tuple of items, each being a pair of (value, width)
'''    
def concat(items):
Andrey Filippov's avatar
Andrey Filippov committed
55
#    print(items)
56 57 58 59
    val=0
    width=0
    for vw in reversed(items):
        v=vw[0]
60
        if not isinstance(v,(int,long)):
Andrey Filippov's avatar
Andrey Filippov committed
61
            if v:
62
                v=1 # So True/False will also work, not just 0/1
Andrey Filippov's avatar
Andrey Filippov committed
63 64
            else:
                v=0
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
        val |= (v & ((1 << vw[1])-1))<<width
        width += vw[1]
    return (val,width)

def bits(val,field):
    try:
        high=field[0]
        low=field[1]
        if low > high:
            low,high=high,low
    except:
        low=field+0 # will be error if not a number
        high=low
    return (val >> low) & ((1 << (high-low+1))-1)    
def getParWidthLo(bitRange):
        if bitRange=='INTEGER':
            return (32,0)
        else:
            try:
Andrey Filippov's avatar
Andrey Filippov committed
84
#                print(">>bitRange=%s"%bitRange,end=" ")
85
                if bitRange[0] != '[':
Andrey Filippov's avatar
Andrey Filippov committed
86
#                    print("\nbitRange[0]=%s"%(bitRange[0]))
87 88 89 90 91
                    return None # may also fail through except if bitRange=""
                startPosHi=1
                endPosHi=bitRange.index(':')
                startPosLo=endPosHi+1
                endPosLo=bitRange.index(']')
Andrey Filippov's avatar
Andrey Filippov committed
92 93
#                print("startPosHi=%d, endPosHi=%d, startPosLo=%d, endPosLo=%d"%(startPosHi,endPosHi,startPosLo,endPosLo))
                
94 95 96 97 98
                if endPosHi<0:
                    endPosHi=endPosLo
                    startPosLo=-1
            except:
                return None
Andrey Filippov's avatar
Andrey Filippov committed
99
#            print("1: startPosHi=%d, endPosHi=%d, startPosLo=%d, endPosLo=%d"%(startPosHi,endPosHi,startPosLo,endPosLo))
100 101 102 103
            if endPosHi <0:
                return None # no ":" or terminating "]"
            loBit=0
            try:
Andrey Filippov's avatar
Andrey Filippov committed
104 105 106 107 108 109
                if startPosLo > 0:
#                    print("2. startPosHi=%d, endPosHi=%d, startPosLo=%d, endPosLo=%d"%(startPosHi,endPosHi,startPosLo,endPosLo))
#                    print("bitRange[startPosLo,endPosLo]=%s"%(bitRange[startPosLo:endPosLo]))
#                    print("bitRange[startPosHi,endPosHi]=%s"%(bitRange[startPosHi:endPosHi]))
                    loBit=int(bitRange[startPosLo:endPosLo])
                    width=int(bitRange[startPosHi:endPosHi])-loBit+1
110 111 112 113 114 115
                return (width,loBit)
            except:
                return None # could not parse: undefined width
                    
def getParWidth(bitRange):
    wl=getParWidthLo(bitRange)
116
#    print("\n***wl=%s, bitRange=%s"%(str(wl),str(bitRange)))
117 118 119 120 121 122
#    print("bitRange=%s wl=%s"%(bitRange,str(wl)))
    if not wl:
        return None
    else:
        return wl[0]
                    
123 124 125 126 127 128 129 130
def hexMultiple(data):
    if isinstance(data,list) or isinstance(data,tuple):
        rslt=[]
        for item in data:
            if isinstance(item,list) or isinstance(item,tuple):
                subResult=[]
                for subItem in item:
                    try:
131
                        subResult.append("0x%x"%subItem)
132
                    except:
133
                        subResult.append(str(subItem))
134 135 136 137 138 139 140 141 142 143 144 145
                rslt.append(subResult)
            else:
                try:
                    rslt.append("0x%x"%item)
                except:
                    rslt.append(str(item))
        rslt=str(rslt)
    else:
        try:
            rslt = "0x%x"%item
        except:
            rslt = str(item)
146 147 148 149 150 151 152 153
    return rslt
        
def checkIntArgs(names,var_dict):
    for name in names:
        try:
            v=var_dict[name]
        except:
            raise Exception("ERROR: '%s' is not among %s"%(name,str(var_dict.keys())))    
154
        if not isinstance(v,(int,long)):
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
            print ("Expected an integer for '%s', got '%s"%(name,v))
            try:
                d=int(v,16)
                print ("Did you mean 0x%x ?"%d)
            except:
                pass
            raise Exception("Not a number for '%s' : '%s'"%(name,v))
def smooth2d(arr2d):
    smooth=[]
    l=len(arr2d)-1
    for i in range(l+1):
        im=(0,i-1)[i>0]
        ip=(l,i+1)[i<l]
        row=[]
        for j in range(len(arr2d[i])):
            row.append(0.5*arr2d[i][j]+0.25*(arr2d[ip][j]+arr2d[im][j]))
        smooth.append(row)
    return smooth                      
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
   
def split_delay(dly):
    """
    Convert hardware composite delay into continuous one
    <dly> 8-bit (5+3) hardware delay value (or a list of delays)
    Returns continuous delay value (or a list of delays)
    """
    if isinstance(dly,list) or isinstance(dly,tuple):
        rslt=[]
        for d in dly:
            rslt.append(split_delay(d))
        return rslt
    try:
        if isinstance(dly,float):
            dly=int(dly+0.5)
        dly_int=dly>>3
        dly_fine=dly & 0x7
        if dly_fine > (NUM_FINE_STEPS-1):
            dly_fine= NUM_FINE_STEPS-1
        return dly_int*NUM_FINE_STEPS+dly_fine
    except:
        return None    

def combine_delay(dly):
    """
    Convert continuous delay value to the 5+3 bit encoded one
    <dly> continuous (0..159) delay (or a list of delays)
    Returns  8-bit (5+3) hardware delay value (or a list of delays)
    """
    if isinstance(dly,list) or isinstance(dly,tuple):
        rslt=[]
        for d in dly:
            rslt.append(combine_delay(d))
        return rslt
    try:
        if isinstance(dly,float):
            dly=int(dly+0.5)
        return ((dly/NUM_FINE_STEPS)<<3)+(dly%NUM_FINE_STEPS)
    except:
        return None

def convert_mem16_to_w32(mem16):
    """
    Convert a list of 16-bit memory words
    into a list of 32-bit data as encoded in the buffer memory
    Each 4 of the input words provide 2 of the output elements
    <mem16> - a list of the memory data
    Returns a list of 32-bit buffer data
    """
    res32=[]
    for i in range(0,len(mem16),4):
        res32.append(((mem16[i+3] & 0xff) << 24) |
                     ((mem16[i+2] & 0xff) << 16) |
                     ((mem16[i+1] & 0xff) << 8) |
                     ((mem16[i+0] & 0xff) << 0))
        res32.append((((mem16[i+3]>>8) & 0xff) << 24) |
                     (((mem16[i+2]>>8) & 0xff) << 16) |
                     (((mem16[i+1]>>8) & 0xff) << 8) |
                     (((mem16[i+0]>>8) & 0xff) << 0))
    return res32

def convert_w32_to_mem16(w32):
    """
    Convert a list of 32-bit data as encoded in the buffer memory
    into a list of 16-bit memory words (so each bit corresponds to DQ line
    Each 2 of the input words provide 4 of the output elements
    <w32> - a list of the 32-bit buffer data
    Returns a list of 16-bit memory data
    """
    mem16=[]
    for i in range(0,len(w32),2):
        mem16.append(((w32[i]>> 0) & 0xff) | (((w32[i+1] >>  0) & 0xff) << 8)) 
        mem16.append(((w32[i]>> 8) & 0xff) | (((w32[i+1] >>  8) & 0xff) << 8)) 
        mem16.append(((w32[i]>>16) & 0xff) | (((w32[i+1] >> 16) & 0xff) << 8)) 
        mem16.append(((w32[i]>>24) & 0xff) | (((w32[i+1] >> 24) & 0xff) << 8)) 
    return mem16