OpenCores
URL https://opencores.org/ocsvn/radiohdl/radiohdl/trunk

Subversion Repositories radiohdl

[/] [radiohdl/] [trunk/] [base/] [common.py] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 danv
###############################################################################
2
#
3
# Copyright (C) 2012
4
# ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
5
# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
6
#
7
# This program is free software: you can redistribute it and/or modify
8
# it under the terms of the GNU General Public License as published by
9
# the Free Software Foundation, either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# This program is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
#
20
###############################################################################
21
 
22
"""Common definitions
23
 
24
"""
25
 
26
################################################################################
27
# System imports
28
 
29
import time
30
import math
31
import operator
32
import inspect
33
import itertools
34
import os
35
import os.path
36
 
37
################################################################################
38
# Constants
39
 
40
c_nibble_w       = 4
41
c_byte_w         = 8
42
c_halfword_w     = 16
43
c_word_w         = 32
44
c_longword_w     = 64
45
 
46
c_byte_sz        = 1
47
c_halfword_sz    = 2
48
c_word_sz        = 4
49
c_longword_sz    = 8
50
 
51
c_nibble_mod     = 2**c_nibble_w        # = 0x10
52
c_nibble_mask    = 2**c_nibble_w-1      # = 0x0F
53
c_byte_mod       = 2**c_byte_w          # = 0x100
54
c_byte_mask      = 2**c_byte_w-1        # = 0x0FF
55
c_halfword_mod   = 2**c_halfword_w      # = 0x10000
56
c_halfword_mask  = 2**c_halfword_w-1    # = 0x0FFFF
57
c_word_mod       = 2**c_word_w          # = 0x100000000
58
c_word_mask      = 2**c_word_w-1        # = 0x0FFFFFFFF
59
c_word_sign      = 2**(c_word_w-1)      # = 0x010000000
60
c_longword_mod   = 2**c_longword_w      # = 0x10000000000000000
61
c_longword_mask  = 2**c_longword_w-1    # = 0x0FFFFFFFFFFFFFFFF
62
c_longword_sign  = 2**(c_longword_w-1)  # = 0x01000000000000000
63
 
64
c_nof_complex    = 2
65
 
66
 
67
################################################################################
68
# Functions
69
 
70
def greatest_common_div(A, B):
71
    """
72
    Find the greatest common divisor of A and B.
73
    """
74
    while B != 0:
75
        rem = A % B
76
        A = B
77
        B = rem
78
    return A
79
 
80
def ceil_div(num, den):
81
    """ Return integer ceil value of num / den """
82
    return int(math.ceil( num / float(den) ) )
83
 
84
def ceil_log2(num):
85
    """ Return integer ceil value of log2(num) """
86
    return int(math.ceil(math.log(int(num), 2) ) )
87
 
88
def ceil_pow2(num):
89
    """ Return power of 2 value that is equal or greater than num """
90
    return 2**ceil_log2(num)
91
 
92
def sel_a_b(sel, a, b):
93
    if sel==True:
94
        return a
95
    else:
96
        return b
97
 
98
def smallest(a, b):
99
    if a<b:
100
        return a
101
    else:
102
        return b
103
 
104
def largest(a, b):
105
    if a>b:
106
        return a
107
    else:
108
        return b
109
 
110
def signed32(v):
111
    if v < c_word_sign:
112
        return v
113
    else:
114
        return v-c_word_mod
115
 
116
def signed64(v):
117
    if v < c_longword_sign:
118
        return v
119
    else:
120
        return v-c_longword_mod
121
 
122
def int_clip(inp, w):
123
    # Purpose : Clip an integer value to w bits
124
    # Input:
125
    # - inp      = Integer value
126
    # - w        = Output width in number of bits
127
    # Description: Output range -2**(w-1) to +2**(w-1)-1
128
    # Return:
129
    # - outp     = Clipped value
130
    outp=0
131
    if w>0:
132
        clip_p= 2**(w-1)-1
133
        clip_n=-2**(w-1)
134
        if inp > clip_p:
135
            outp=clip_p
136
        elif inp < clip_n:
137
            outp=clip_n
138
        else:
139
            outp=inp
140
    return outp
141
 
142
def int_wrap(inp, w):
143
    # Purpose: Wrap an integer value to w bits
144
    # Input:
145
    # - inp      = Integer value
146
    # - w        = Output width in number of bits
147
    # Description: Remove MSbits, output range -2**(w-1) to +2**(w-1)-1
148
    # Return:
149
    # - outp     = Wrapped value
150
    outp=0
151
    if w>0:
152
        wrap_mask=2**(w-1)-1
153
        wrap_sign=2**(w-1)
154
        if (inp & wrap_sign) == 0:
155
            outp=inp & wrap_mask
156
        else:
157
            outp=(inp & wrap_mask) - wrap_sign
158
    return outp
159
 
160
def int_round(inp, w, direction="HALF_AWAY"):
161
    # Purpose : Round the w LSbits of an integer value
162
    # Input:
163
    # - inp       = Integer value
164
    # - w         = Number of LSbits to round
165
    # - direction = "HALF_AWAY", "HALF_UP"
166
    # Description:
167
    #   direction = "HALF_AWAY" --> Round half away from zero so +0.5 --> 1, -0.5 --> -1.
168
    #   direction = "HALF_UP"   --> Round half to +infinity   so +0.5 --> 1, -0.5 --> 0.
169
    # Return:
170
    # - outp     = Rounded value
171
    outp=inp
172
    if w>0:
173
        round_factor=2**w
174
        round_p=2**(w-1)
175
        round_n=2**(w-1)-1
176
        if direction == "HALF_UP":
177
            outp=(inp+round_p)/round_factor
178
        if direction == "HALF_AWAY":
179
            if inp >= 0:
180
                outp=(inp+round_p)/round_factor
181
            else:
182
                outp=(inp+round_n)/round_factor
183
    return outp
184
 
185
def int_truncate(inp, w):
186
    # Purpose : Truncate the w LSbits of an integer value
187
    # Input:
188
    # - inp      = Integer value
189
    # - w        = Number of LSbits to truncate
190
    # Description: Remove LSBits.
191
    # Return:
192
    # - outp     = Truncated value
193
    outp=inp
194
    if w>0:
195
        if inp >= 0:
196
            outp=inp>>w
197
        else:
198
            outp=-((-inp)>>w)
199
    return outp
200
 
201
 
202
def int_requantize(inp, inp_w, outp_w, lsb_w=0, lsb_round=False, msb_clip=False, gain_w=0):
203
    # Purpose : Requantize integer value similar as common_requantize.vhd
204
    # Input:
205
    # - inp       = Integer value
206
    # - inp_w     = Input data width
207
    # - outp_w    = Output data width
208
    # - lsb_w     = Number of LSbits to truncate
209
    # - lsb_round = when true round else truncate the input LSbits
210
    # - msb_clip  = when true clip else wrap the input MSbits
211
    # - gain_w    = Output gain in number of bits
212
    # Description: First round or truncate the LSbits, then clip or wrap the MSbits and then apply optional output gain
213
    # Return:
214
    # - outp     = Requantized value
215
 
216
    # Input width
217
    r = int_wrap(inp, inp_w)
218
    # Remove LSBits using ROUND or TRUNCATE
219
    if lsb_round:
220
        r = int_round(r, lsb_w)
221
    else:
222
        r = int_truncate(r, lsb_w)
223
    # Remove MSBits using CLIP or WRAP
224
    if msb_clip:
225
        r = int_clip(r, outp_w)
226
    else:
227
        r = int_wrap(r, outp_w)
228
    # Output gain
229
    r = r<<gain_w
230
    outp = int_wrap(r, outp_w)
231
    return outp
232
 
233
 
234
def flatten(x):
235
    """
236
    Flatten lists of lists of any depth. Preserves tuples.
237
    """
238
    result = []
239
    for el in x:
240
        if hasattr(el, "__iter__") and not isinstance(el, basestring) and type(el)!=tuple and not issubclass(type(el), tuple):
241
            result.extend(flatten(el))
242
        else:
243
            result.append(el)
244
    return result
245
 
246
def do_until(method, val, op=operator.eq, ms_retry=10, s_timeout=4, **kwargs):
247
    """
248
    Default: DO [method] UNTIL [method==val]
249
    Example: do_until( self.read_status, 0) will execute self.read_status() until all
250
    elements in the returned list equal 0.
251
    Use **kwargs to pass keyworded arguments to the input method;
252
    Use ms_retry to set the time in milliseconds before rerunning the method;
253
    Use s_timeout to set the time in seconds before timeout occurs (returns 1). Use
254
    s_timeout<0 to disable the time out
255
    All standard Python operators (see operator class) are supported, the default
256
    is eq (equal to).
257
    """
258
    list_ok = 0
259
    start = time.time()
260
    while list_ok == 0:
261
        if s_timeout>=0:
262
            if time.time() - start >= s_timeout:
263
                print('do_until: Timeout occured!')
264
                return 'Timeout'
265
        data = []
266
        if len(kwargs) > 0:
267
            data.append(method(**kwargs))
268
        else:
269
            data.append(method())
270
        flat_data = flatten(data)
271
        list_ok = 1
272
        for i in range(0, len(flat_data)):
273
            if not op(flat_data[i], val):
274
                list_ok = 0
275
        if list_ok == 0:
276
            time.sleep(ms_retry/1000)
277
    if list_ok == 1:
278
        return flat_data[0]
279
 
280
def do_until_lt(method, val, ms_retry=10, s_timeout=4, **kwargs): return do_until(method, val, operator.lt, ms_retry, s_timeout, **kwargs)
281
def do_until_le(method, val, ms_retry=10, s_timeout=4, **kwargs): return do_until(method, val, operator.le, ms_retry, s_timeout, **kwargs)
282
def do_until_eq(method, val, ms_retry=10, s_timeout=4, **kwargs): return do_until(method, val, operator.eq, ms_retry, s_timeout, **kwargs)
283
def do_until_ne(method, val, ms_retry=10, s_timeout=4, **kwargs): return do_until(method, val, operator.ne, ms_retry, s_timeout, **kwargs)
284
def do_until_ge(method, val, ms_retry=10, s_timeout=4, **kwargs): return do_until(method, val, operator.ge, ms_retry, s_timeout, **kwargs)
285
def do_until_gt(method, val, ms_retry=10, s_timeout=4, **kwargs): return do_until(method, val, operator.gt, ms_retry, s_timeout, **kwargs)
286
 
287
def reverse_byte(byte):
288
    """
289
    Fast way to reverse a byte on 64-bit platforms.
290
    """
291
    #return (byte * 0x0202020202L & 0x010884422010L) % 1023
292
    return(byte * 0x0202020202 & 0x010884422010) % 1023  # PD: check
293
 
294
def reverse_word(word):
295
    """
296
    Fast way to reverse a word on 64-bit platforms.
297
    """
298
    B0 = (word & 0xFF)
299
    B1 = (word & 0xFF00) >> 8
300
    B2 = (word & 0xFF0000) >> 16
301
    B3 = (word & 0xFF000000) >> 24
302
    reversed_word = (reverse_byte(B0) << 24) | (reverse_byte(B1) << 16) | (reverse_byte(B2) << 8) | (reverse_byte(B3))
303
    return reversed_word
304
 
305
def add_list(aList, bArg):
306
    """
307
    Element by element add list b to list a or add value b to each element in list a
308
    """
309
    aLen  = len(aList)
310
    bList = listify(bArg)
311
    if len(bList)==1:
312
        bList = bList[0]*aLen
313
    s = []
314
    for i in range(aLen):
315
        s.append(aList[i] + bList[i])
316
    return s
317
 
318
def add_list_elements(in_list):
319
    """
320
    Multiply list elements together, e.g. [1,2,3,4,5,6] -> 1+2+3+4+5+6=21
321
    """
322
    return reduce(lambda x, y: x+y, in_list)
323
 
324
def subtract_list(aList, bArg):
325
    """
326
    Element by element subract list b from list a or subract value b from each element in list a
327
    """
328
    aLen  = len(aList)
329
    bList = listify(bArg)
330
    if len(bList)==1:
331
        bList = bList[0]*aLen
332
    s = []
333
    for i in range(aLen):
334
        s.append(aList[i] - bList[i])
335
    return s
336
 
337
def multiply_list(aList, bArg):
338
    """
339
    Element by element multiply list b with list a or multiply value b with each element in list a
340
    """
341
    aLen  = len(aList)
342
    bList = listify(bArg)
343
    if len(bList)==1:
344
        bList = bList[0]*aLen
345
    s = []
346
    for i in range(aLen):
347
        s.append(aList[i] * bList[i])
348
    return s
349
 
350
def multiply_list_elements(in_list):
351
    """
352
    Multiply list elements together, e.g. [1,2,3,4,5,6] -> 1*2*3*4*5*6=720.
353
    """
354
    return reduce(lambda x, y: x*y, in_list)
355
 
356
def divide_list(aList, bArg):
357
    """
358
    Element by element divide list a by list b or divide each element in list a by value b
359
    """
360
    aLen  = len(aList)
361
    bList = listify(bArg)
362
    if len(bList)==1:
363
        bList = bList[0]*aLen
364
    for i in range(aLen):
365
        s.append(aList[i] / bList[i])
366
    return s
367
 
368
def split_list(source_list, split_size=None, sublist_items=None, nof_output_lists=None):
369
    """
370
    Splits a list based on split_size. Optionally, the indices passed in sublist_items
371
    are extracted from each sublist.
372
    """
373
    if split_size==None:
374
        split_size=len(source_list)/nof_output_lists
375
    sublists = [source_list[i:i+split_size] for i in xrange(0, len(source_list), split_size)]
376
    if sublist_items==None:
377
        return sublists
378
    else:
379
        if len(listify(sublist_items))==1:
380
            return [listify(operator.itemgetter(*listify(sublist_items))(sl)) for sl in sublists]
381
        else:
382
            return [list(operator.itemgetter(*listify(sublist_items))(sl)) for sl in sublists]
383
 
384
def create_multidimensional_list(shape, element=None):
385
    """Creating a multidimensional list (obtained from create_empty_array_of_shape() at stackoverflow)
386
 
387
       For example shape = [2, 3] returns [[None, None, None], [None, None, None]]
388
    """
389
    if shape:
390
       return [create_multidimensional_list(shape[1:], element) for i in xrange(shape[0])]
391
    else:
392
       return element
393
 
394
def index_a_in_b(a, b, duplicates=False):
395
    """
396
    Find the elements of list a in list b and return their indices (relative to b).
397
    Does not return duplicates by default.
398
    """
399
    if duplicates==False:
400
        return [i for i,item in enumerate(b) if item in a]
401
    else:
402
        hits = []
403
        for item_in_a in a:
404
            hits.append( [i for i,item in enumerate(b) if item == item_in_a] )
405
        return flatten(hits)
406
 
407
def index_a_in_multi_b(a, b):
408
    """
409
    Find a in multi-dimensional list b. Returns first hit only.
410
    """
411
    if a == b: return []
412
    try:
413
        for i,e in enumerate(b):
414
            r = index_a_in_multi_b(a,e)
415
            if r is not None:
416
                r.insert(0,i)
417
                return r
418
    except TypeError:
419
        pass
420
    return None
421
 
422
def unique(in_list):
423
    """
424
    Extract unique list elements (without changing the order like set() does)
425
    """
426
    seen = {}
427
    result = []
428
    for item in in_list:
429
       if item in seen: continue
430
       seen[item] = 1
431
       result.append(item)
432
    return result
433
 
434
def reverse_list(in_list):
435
    """Return list in reversed index order"""
436
    return list(reversed(in_list))
437
 
438
def sort_list_indices(in_list, lowToHigh = True):
439
    """Return list of original indices of in_list for the sorted(in_list)"""
440
    result = sorted(range(len(in_list)), key = lambda ix : in_list[ix])
441
    if lowToHigh==True:
442
        return result
443
    else:
444
        return reverse_list(result)
445
 
446
def list_duplicates(in_list):
447
    """
448
    find duplicate list elements
449
    """
450
    # http://stackoverflow.com/questions/9835762/find-and-list-duplicates-in-python-list
451
    seen = set()
452
    seen_add = seen.add
453
    # adds all elements it doesn't know yet to seen and all other to seen_twice
454
    seen_twice = set( x for x in in_list if x in seen or seen_add(x) )
455
    # turn the set into a list (as requested)
456
    return list( seen_twice )
457
 
458
def all_the_same(lst):
459
    """
460
    Returns True if all the list elements are identical.
461
    """
462
    return lst[1:] == lst[:-1]
463
 
464
def all_equal_to(lst, value):
465
    """
466
    Returns True if all the list elements equal 'value'.
467
    """
468
    if all_the_same(lst)==True and lst[0]==value:
469
        return True
470
    else:
471
        return False
472
 
473
def rotate_list(in_list, n):
474
    """
475
    Rotates the list. Positive numbers rotate left. Negative numbers rotate right.
476
    """
477
    return in_list[n:] + in_list[:n]
478
 
479
def to_uword(arg):
480
    """
481
    Represent 32 bit value as unsigned word. Note that:
482
 
483
      common.to_signed(common.to_uword(-1), 32) = -1
484
 
485
    """
486
    vRet = []
487
    vList = listify(arg)
488
    for value in vList:
489
        v = int(value) & c_word_mask     # mask the 32 bits, also accept float value by converting to int
490
        vRet.append(v)
491
    return unlistify(vRet)
492
 
493
def to_unsigned(arg, width):
494
    """
495
    Interpret value[width-1:0] as unsigned
496
    """
497
    c_mask = 2**width-1
498
    vRet = []
499
    vList = listify(arg)
500
    for value in vList:
501
        v = int(value) & c_mask     # mask the lower [width-1:0] bits, also accept float value by converting to int
502
        vRet.append(v)
503
    return unlistify(vRet)
504
 
505
def to_signed(arg, width):
506
    """
507
    Interpret arg value[width-1:0] or list of arg values as signed (two's complement)
508
    """
509
    c_wrap = 2**width
510
    c_mask = 2**width-1
511
    c_sign = 2**(width-1)
512
    vRet = []
513
    vList = listify(arg)
514
    for value in vList:
515
        v = int(value) & c_mask   # mask the lower [width-1:0] bits, also accept float value by converting to int
516
        if v & c_sign:
517
            v -= c_wrap           # keep negative values and wrap too large positive values
518
        vRet.append(v)
519
    return unlistify(vRet)
520
 
521
def max_abs(data):
522
    return max(max(data), -min(data))
523
 
524
def insert(orig, new, pos):
525
    """
526
    Inserts new (string, element) inside original string or list at pos.
527
    """
528
    return orig[:pos] + new + orig[pos:]
529
 
530
def deinterleave(input_stream, nof_out, block_size=1):
531
    """
532
    Deinterleave a stream (=flat list) into nof_out output streams based on block_size.
533
    >> deinterleave( [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16], 4, 2 )
534
    >> [ [1,2,9,10], [3,4,11,12], [5,6,13,14], [7,8,15,16] ]
535
    Note: len(input_stream)/nof_out/block_size should yield an integer.
536
    Note: This method behaves exactly like common_deinterleave.vhd.
537
    """
538
    # Check passed arguments:
539
    if ( float(len(input_stream))/nof_out/block_size%1==0):
540
        # Split the list into block_sized sublists:
541
        if block_size>1:
542
            block_list = split_list(input_stream, block_size)
543
        else:
544
            block_list = input_stream
545
 
546
        # Split block_list into 2 sublists so we can transpose them
547
        sublist_size = nof_out
548
        block_2arr = split_list(block_list, sublist_size)
549
        transposed = transpose(block_2arr)
550
 
551
        # Flatten the list so we can re-split it:
552
        flat_out_list = flatten(transposed)
553
 
554
        # Divide this new stream across nof_out:
555
        sublist_size = len(input_stream)/nof_out
556
 
557
        result = split_list(flat_out_list, sublist_size)
558
        return result
559
    else:
560
        print('deinterleave: Error: len(input_stream)/nof_out/block_size should yield an integer!')
561
 
562
def interleave(input_streams, block_size=1):
563
    """
564
    Interleave a list of multiple lists into one based on block size.
565
    Note: This method behaves exactly like common_interleave.vhd.
566
    """
567
    # flatten the list
568
    flat_list = flatten(input_streams)
569
 
570
    # Use deinterleave function to pull the stream apart block-wise and restore the correct order
571
    nof_lists = len(input_streams[0]) / block_size
572
    deint_block_list = deinterleave(flat_list, nof_lists, block_size)
573
 
574
    # Flatten the list
575
    result = flatten(deint_block_list)
576
    return result
577
 
578
def reinterleave(input_streams, nof_out, block_size_in=1, block_size_out=1):
579
    """
580
    Re-interleave X input streams across nof_out output streams. The input streams are first
581
    deinterleaved with block_size_in, then nof_out interleaved streams are made with block_size_out.
582
    Note: This method behaves exactly like common_reinterleave.vhd.
583
    """
584
    nof_in = len(input_streams)
585
 
586
    # Array of deinterleavers:
587
    # ------------------------
588
    # deint_arr: [nof_in][deinterleaved streams]:
589
    deint_arr = []
590
    for in_no in range(nof_in):
591
        deint_arr.append(deinterleave(input_streams[in_no], nof_out, block_size_in))
592
 
593
    # Deinterleavers -> interleavers interconnect:
594
    inter_in_arr = []
595
    for i in range(nof_out):
596
        inter_in = []
597
        for j in range(nof_in):
598
            inter_in.append(deint_arr[j][i])
599
        inter_in_arr.append(inter_in)
600
 
601
    # Array of interleavers:
602
    # ----------------------
603
    # inter_arr: [nof_out][interleaved streams]:
604
    inter_out_arr = []
605
    for out_no in range(nof_out):
606
         inter_out_arr.append(interleave(inter_in_arr[out_no], block_size_out))
607
    return inter_out_arr
608
 
609
def transpose(matrix):
610
    """
611
    Transpose by using zip()
612
    """
613
    result = []
614
    transposed = zip(*matrix)
615
    # Python's zip() returns a list of tuples. We do not want that as tuples
616
    # should only be used to bind items together; methods like flatten()
617
    # preserve tuples (as tuples should not be broken - that's why they're 
618
    # tuples in the first place) wich would mean the output of a transpose 
619
    # could not be flattened. So, convert the list of tuples to a list of lists:
620
    for i in transposed:
621
        result.append(list(i))
622
    return result
623
 
624
def straighten(matrix, padding=' '):
625
    """
626
    Straighten a crooked matrix by padding the shorter lists with the padding
627
    up to the same length as the longest list.
628
    """
629
    padded_matrix = []
630
    max_len = len(max(matrix))
631
    for row in matrix:
632
        padded_matrix.append(pad(row, max_len, padding))
633
    return padded_matrix
634
 
635
def pad(lst, length, padding=' '):
636
    """
637
    Pad a list up to length with padding
638
    """
639
    return lst+[padding]*(length-len(lst))
640
 
641
def depth(x):
642
    """
643
    Returns the depth of x. Returns 0 if x is not iterable (not a list or tuple).
644
    """
645
    if isinstance(x, list) or isinstance(x, tuple):
646
        for level in itertools.count():
647
            if not x:
648
                return level
649
            x = list(itertools.chain.from_iterable(s for s in x if isinstance(s, list) or isinstance(s, tuple)))
650
    else:
651
        return 0
652
 
653
def listify(x):
654
    """
655
    Can be used to force method input to a list.
656
    """
657
    # The isinstance() built-in function is recommended over the type() built-in function for testing the type of an object
658
    if isinstance(x, list):
659
        return x
660
    else:
661
        return [x]
662
 
663
def unlistify(x):
664
    """
665
    Converts 1-element list to x.
666
    """
667
    # The isinstance() built-in function is recommended over the type() built-in function for testing the type of an object
668
    if isinstance(x, list):
669
        if len(x)==1:
670
            return x[0]
671
        else:
672
            return x
673
    else:
674
        return x
675
 
676
def tuplefy(x):
677
    """
678
    Similar to listify().
679
    This method enables user to iterate through tuples of inconsistent depth by
680
    always returning a non-flat tuple.
681
    Pushes a flat tuple (depth=1) e.g. (0,1,2) one level deeper: ( (0,1,2), ).
682
    Non-flat tuples are returned untouched.
683
    A non-tuple (depth=0) is also pushed into a tuple 2 levels deep.
684
    """
685
    if depth(x)==1:
686
        return (x,)
687
    elif depth(x)==0:
688
       return ( (x,), )
689
    else:
690
        return x
691
 
692
def method_name(caller_depth=0):
693
    """
694
    Returns the name of the caller method.
695
    """
696
    # Note: inspect.stack()[0][3] would return the name of this method.
697
    return inspect.stack()[caller_depth+1][3]
698
 
699
def method_arg_names(method):
700
    """
701
    Returns the names of the arguments of passed method.
702
    """
703
    return inspect.getargspec(method)[0]
704
 
705
def concat_complex(list_complex, width_in_bits):
706
    """
707
    Concatenates the real and imaginary part into one integer.
708
    The specifed width counts for both the real and imaginary part.
709
    Real part is mapped on the LSB. Imaginary part is shifted to the MSB.
710
    """
711
    result = []
712
    for i in range(len(list_complex)):
713
        real = int(list_complex[i].real) & (2**width_in_bits-1)
714
        imag = int(list_complex[i].imag) & (2**width_in_bits-1)
715
        result.append((imag << width_in_bits) + real)
716
    return result
717
 
718
def unconcat_complex(list_concat, width_in_bits):
719
    """
720
    Unconcatenates the real and imaginary part from an integer list into
721
    a complex list with separate real and imaginary part. The integers
722
    in list_concat are 2*width_in_bits wide.
723
    Real part is extracted from the LSB. Imaginary part is extracted the MSB.
724
    Example:
725
      >>> unconcat_complex(concat_complex([complex(1,2), complex(3,4)], 16), 16)
726
      [(1+2j), (3+4j)]
727
    """
728
    result = []
729
    for i in range(len(list_concat)):
730
        real =  list_concat[i]                   & (2**width_in_bits-1)
731
        imag = (list_concat[i] >> width_in_bits) & (2**width_in_bits-1)
732
        result.append(complex(real, imag))
733
    return result
734
 
735
def split_complex(list_complex):
736
    """
737
    Returns the real and imaginary part in two separate lists.
738
    [list_re, list_im] = split_complex(list_complex)
739
    """
740
    list_real = []
741
    list_imag = []
742
    for i in range(len(list_complex)):
743
        list_real.append(list_complex[i].real)
744
        list_imag.append(list_complex[i].imag)
745
    return (list_real, list_imag)
746
 
747
 
748
def mac_str(n):
749
    """
750
    Converts MAC address integer to the hexadecimal string representation,
751
    separated by ':'.
752
    """
753
    hexstr = "%012x" % n
754
    return ':'.join([hexstr[i:i+2] for i in range(0, len(hexstr), 2)])
755
 
756
def ip_str(n):
757
    """
758
    Converts IP address integer to the decimal string representation,
759
    separated by '.'.
760
    """
761
    ip_bytes = CommonBytes(n, 4)
762
    return str(ip_bytes[3])+'.'+str(ip_bytes[2])+'.'+str(ip_bytes[1])+'.'+str(ip_bytes[0])
763
 
764
def mkdir(path):
765
    """Recursively create leave directory and intermediate directories if they do not already exist."""
766
    expandPath = os.path.expandvars(path)        # support using environment variables in the file path
767
    expandPath = os.path.expanduser(expandPath)  # support using ~ in the file path
768
    if not os.path.exists(expandPath):
769
        os.makedirs(expandPath)
770
 
771
def expand_file_path_name(fpn, dir_path=''):
772
    """ Expand environment variables in fpn to get filePathName.
773
    - if it is an absolute path return filePathName else
774
    - if it still has a local file path prepend dir_path to the filePathName and return dir_path + filePathName.
775
    """
776
    filePathName = os.path.expandvars(fpn)           # support using environment variables in the file path
777
    filePathName = os.path.expanduser(filePathName)  # support using ~ in the file path
778
    if os.path.isabs(filePathName):
779
        return filePathName                          # use absolute path to file
780
    else:
781
        return os.path.join(os.path.expandvars(dir_path), filePathName)  # derive path to file from the directory path and a directory path to the file
782
 
783
def find_string_in_file(fpn, find_str):
784
    """Return index >= 0 if find_str is found in file fpn, returns -1 if find_str is not found in file fpn.
785
 
786
       Can also find '\n'.
787
    """
788
    return open(fpn, 'r').read().find(find_str)
789
 
790
def remove_from_list_string(list_str, item_str, sep=' '):
791
    """Treat the string list_str as a list of items that are separated by sep and then
792
       remove the specified item_str string from the list and return the list as a
793
       string of items separated by sep. Also remove any duplicate items.
794
    """
795
    ls = list_str.split(sep)
796
    ls = unique(ls)
797
    ls.remove(item_str)
798
    ls = sep.join(ls)
799
    return ls
800
 
801
def find_all_file_paths(rootDir, fileName):
802
    """
803
    Recursively search the rootDir tree to find the paths to all fileName files.
804
    """
805
    paths = []
806
    for root, _, files in os.walk(rootDir):
807
        if fileName in files:
808
             paths.append(root)
809
    return paths
810
 
811
 
812
################################################################################
813
# Classes
814
 
815
class CommonBits:
816
    """
817
    The purpose of this class is to allow the user to:
818
    1) create a CommonBits object with some data, e.g:
819
       >> my_bits = CommonBits(0xDEADBEEF)
820
    2) Use the bracket notation [] to extract bit ranges from that data:
821
       >> print(hex(my_bits[31:0]))
822
       0xdeadbeef
823
       >> print(hex(my_bits[31:4]))
824
       0xdeadbee
825
       >> print(hex(my_bits[31:16]))
826
       0xdead
827
       >> print(hex(my_bits[31]))
828
       0x1
829
       >> print(hex(my_bits[0]))
830
       0x1
831
    3) If a (optional) data width is passed, leading zeroes are added.
832
       >> my_bits = CommonBits(0xDEADBEEF, 16)
833
       >> print(hex(my_bits))
834
       0xbeef
835
       >> my_bits = CommonBits(0xDEADBEEF, 64)
836
       >> print(hex(my_bits[63:32]))
837
       0x0
838
    4) Besides getting bit slices, setting bitslices is also possible:
839
       >> my_bits = CommonBits(0xdeadbeef)
840
       >> print(my_bits)
841
       0xdeadbeef
842
       >> my_bits[15:0] = 0xbabe
843
       >> print(my_bits)
844
       0xdeadbabe
845
    5) Use -1 to set a range of bits to all ones.
846
    6) Use VHDL-style & operator to concatenate CommonBits types.
847
       >> MyBitsHi = 0xDEAD
848
       >> MyBitsLo = 0xBEEF
849
       >> print(MyBitsHi & MyBitsLo & CommonBits(0xCAFEBABE))
850
       0xdeadbeefcafebabe
851
    """
852
    def __init__(self, data, bits=0):
853
 
854
        if data>=0:
855
            self.data = data
856
        else:
857
            print("CommonBits: Error: Input data = %d. Only unsigned integers are supported, use to_unsigned(data, bits)." %data)
858
 
859
        if bits>0:
860
            # Set data width to passed 'bits'
861
            self.data_bin_len = bits
862
 
863
            # Check if data fits in passed nof bits
864
            if self.get_bin_len(data) > self.data_bin_len:
865
                print("CommonBits: Error: input data %d does not fit in passed number of bits (%d)" %(data, bits))
866
 
867
        else:
868
            # Use the minimum required data width            
869
            self.data_bin_len = self.get_bin_len(self.data)
870
 
871
    def __getitem__(self, bitslice):
872
        if self.check_slice(bitslice)==0:
873
            if type(bitslice)==type(slice(1,2,3)):
874
                # Get a bitmask for the bit range passed via the bitslice
875
                bitmask = self.bitmask(bitslice.start - bitslice.stop +1)
876
                return int((self.data >> bitslice.stop) & bitmask)
877
            if type(bitslice)==type(0):
878
                # We only want one bit
879
                bitmask = self.bitmask(1)
880
                return int((self.data >> bitslice) & bitmask)
881
            print(bitmask)
882
        else:
883
            print('CommonBits: Error: invalid slice range')
884
 
885
    def __setitem__(self, bitslice, value):
886
        if self.check_slice(bitslice)==0:
887
            if type(bitslice)==type(slice(1,2,3)):
888
                # Get a bitmask for the bit range passed via the bitslice
889
                bitmask = self.bitmask(bitslice.start - bitslice.stop +1)
890
 
891
                if value==-1:
892
                    # Allow -1 to set range to all ones. Simply use the bitmask as data.
893
                    data=bitmask
894
                elif value>=0:
895
                    data = value
896
                else:
897
                    print("CommonBits: Error: Input data = %d. Only unsigned integers are supported, use to_unsigned(data, bits)." %value)
898
 
899
                # Make sure bit length of passed data does not exceed bitmask length
900
                if self.get_bin_len(data) <= self.get_bin_len(bitmask):
901
                    self.data = (self.data & ~(bitmask << bitslice.stop)) | (data << bitslice.stop)
902
                else:
903
                    print('CommonBits: Error: passed value (%d) does not fit in bits [%d..%d].' %(value, bitslice.start, bitslice.stop))
904
 
905
            if type(bitslice)==type(0):
906
                # We only want to set one bit
907
                bitmask = self.bitmask(1)
908
                data=value
909
                # Make sure bit length of passed data does not exceed bitmask length
910
                if self.get_bin_len(data) <= self.get_bin_len(bitmask):
911
                    self.data = (self.data & ~(bitmask << bitslice)) | (data << bitslice)
912
                else:
913
                    print('CommonBits: Error: passed value (%d) does not fit in bit [%d].' %(value, bitslice))
914
 
915
        else:
916
            print('CommonBits: Error: invalid slice range')
917
 
918
    def __repr__(self):
919
        if self.data_bin_len>1:
920
            bitslice = slice(self.data_bin_len-1, 0, None)
921
        else:
922
            bitslice = 0
923
        return str(self.__getitem__(bitslice))
924
 
925
    def __len__(self):
926
        return self.data_bin_len
927
 
928
    def __str__(self):
929
        return hex(int(self.__repr__()))
930
 
931
    def __hex__(self):
932
        return hex(int(self.__repr__()))
933
 
934
    def __trunc__(self):
935
        return int(self.data).__trunc__()
936
 
937
    def __and__(self, other):
938
        # To concatenate two CommonBits types, first create a new one with the combined length
939
        ret = CommonBits(0, self.data_bin_len + other.data_bin_len )
940
 
941
        # Now fill in the values. Self is interpreted as the MS part, other as the LS part.
942
        ms_hi = ret.data_bin_len-1
943
        ms_lo = other.data_bin_len
944
        ls_hi = other.data_bin_len-1
945
        ls_lo = 0
946
        ret[ms_hi:ms_lo] = self.data
947
        ret[ls_hi:ls_lo] = other.data
948
        return ret
949
 
950
    def hi(self):
951
        data_bits = CommonBits(self.data)
952
        result = []
953
        for bit in range(0, self.data_bin_len):
954
            if data_bits[bit]==1:
955
                result.append(bit)
956
        return result
957
 
958
    def lo(self):
959
        data_bits = CommonBits(self.data)
960
        result = []
961
        for bit in range(0, self.data_bin_len):
962
            if data_bits[bit]==0:
963
                result.append(bit)
964
        return result
965
 
966
    def bitmask(self, nof_bits):
967
        # return a bitmask of nof_bits, e.g. 7 is a bitmask for 3 bits
968
        return pow(2, nof_bits)-1
969
 
970
    def check_slice(self, bitslice):
971
        # Check that the user passed a valid slice e.g. [31:24], or 1 integer e.g. [31]
972
        result = 0
973
        if type(bitslice)==type(slice(1,2,3)):
974
            # Slice type passed. Don't allow user to pass step
975
            if bitslice.step!=None:
976
                result+=1
977
                print('CommonBits: Error: no step size allowed')
978
            # We want user to pass range in [MS:LS] notation
979
            if bitslice.stop > bitslice.start:
980
                result+=1
981
                print('CommonBits: Error: slice range should be [ms:ls]')
982
            # Do not exceed MSb index
983
            if bitslice.start>=self.data_bin_len:
984
                result+=1
985
                print('CommonBits: Error: Passed MSbit does not exist in data')
986
        if type(bitslice)==type(0):
987
            # One integer passed. Only check if the passed bit exists.
988
            if bitslice>=self.data_bin_len:
989
                result+=1
990
                print('CommonBits: Error: Passed MSbit does not exist in data')
991
        return result
992
 
993
    def get_bin_len(self, value):
994
        value_bin_str = bin(value)
995
        # Cut the '0b' from the binary string:
996
        value_bin = value_bin_str[2:len(value_bin_str)]
997
        return len(value_bin)
998
 
999
    def reversed(self):
1000
        format_str = '{:0%db}'%self.data_bin_len
1001
        res = int(format_str.format(self.data)[::-1], 2)
1002
        return res
1003
 
1004
class CommonSymbols(CommonBits):
1005
    """
1006
    CommonBits operating on symbol boundaries.
1007
    """
1008
    def __init__(self, data, symbol_w, datasymbols=1):
1009
        if datasymbols>0:
1010
            CommonBits.__init__(self, data, datasymbols*symbol_w)
1011
        else:
1012
            CommonBits.__init__(self, data)
1013
 
1014
        self.symbol_w = symbol_w
1015
        self.data_symbol_len = ceil_div(self.data_bin_len, symbol_w)
1016
 
1017
    def __getitem__(self, symbolslice):
1018
        # Convert symbol range to bit range, let CommonBits do the rest
1019
        return CommonBits.__getitem__(self, self.symbolslice_to_bitslice(symbolslice))
1020
 
1021
    def __setitem__(self, symbolslice, value):
1022
        # Convert symbol range to bit range, let CommonBits do the rest
1023
         return CommonBits.__setitem__(self, self.symbolslice_to_bitslice(symbolslice), value)
1024
 
1025
    def __repr__(self):
1026
        if self.data_symbol_len>1:
1027
            symbolslice = slice(self.data_symbol_len-1, 0, None)
1028
        else:
1029
            symbolslice = 0
1030
        return self.__getitem__(symbolslice)
1031
 
1032
    def __len__(self):
1033
        return self.data_symbol_len
1034
 
1035
    def symbolslice_to_bitslice(self, symbolslice):
1036
        if type(symbolslice)==type(slice(1,2,3)):
1037
            MSS = symbolslice.start
1038
            LSS = symbolslice.stop
1039
            bitslice = slice((1+MSS)*self.symbol_w-1, LSS*self.symbol_w, None)
1040
        if type(symbolslice)==type(0):
1041
            MSb = (1+symbolslice)*self.symbol_w
1042
            LSb = (1+symbolslice)*self.symbol_w-self.symbol_w
1043
            bitslice = slice(MSb-1, LSb, None)
1044
        return bitslice
1045
 
1046
 
1047
class CommonBytes(CommonSymbols):
1048
    def __init__(self, data, datasymbols=1):
1049
        CommonSymbols.__init__(self, data, 8, datasymbols)
1050
 
1051
class CommonShorts(CommonSymbols):
1052
    def __init__(self, data, datasymbols=1):
1053
        CommonSymbols.__init__(self, data, 16, datasymbols)
1054
 
1055
class CommonWords(CommonSymbols):
1056
    def __init__(self, data, datasymbols=1):
1057
        CommonSymbols.__init__(self, data, 32, datasymbols)
1058
 
1059
class CommonWords64(CommonSymbols):
1060
    def __init__(self, data, datasymbols=1):
1061
        CommonSymbols.__init__(self, data, 64, datasymbols)
1062
 
1063
 

powered by: WebSVN 2.1.0

© copyright 1999-2019 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.