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

Subversion Repositories myblaze

[/] [myblaze/] [trunk/] [rtl/] [lut.py] - Blame information for rev 6

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 rockee
# -*- coding: utf-8 -*-
2
"""
3
    LUTs.py
4
    =============
5
 
6
    Lookup tables for sinus and division calculation
7
 
8 5 rockee
    :copyright: Copyright (c) 2010 Jian Luo
9
    :author-email: jian.luo.cn(at_)gmail.com
10
    :license: LGPL, see LICENSE for details
11 2 rockee
    :revision: $Id: lut.py 5 2010-11-21 10:59:30Z rockee $
12
"""
13
 
14
from numpy import *
15
from myhdl import *
16
from fixed_point import fxintbv,fxint
17
 
18
__all__ = ['ROM', 'LZD', 'GS_R0_Gen',
19
           'get_lzd_width', 'get_gs_entry_shape']
20
 
21
def my_bin(x, w=16):
22
    l = len(bin(x))
23
    return ''.join(['0'*(w-l), bin(x)])
24
 
25
 
26
###########
27
# General #
28
###########
29
 
30
def ROM(dout, addr, CONTENT):
31
    """
32
    General ROM implementation
33
    """
34
    @always_comb
35
    def read():
36
        dout.next = CONTENT[int(addr)]
37
    return instances()
38
 
39
 
40
##########################
41
# Leading Zero Detection #
42
##########################
43
 
44
def count_l_zeros(x, width=8):
45
    """
46
    Helper for count leading zeros
47
 
48
    x:      input digit
49
    width:  bitwidth of x
50
    """
51
    count = 0
52
    for i in downrange(width):
53
        y = (x>>i) & 1
54
        if y:
55
            break
56
        else:
57
            count += 1
58
    return count
59
 
60
def get_lzd_width(width):
61
    """
62
    Get word length of counter for leading zero detector
63
    """
64
    return int(ceil(log2(width)))
65
 
66
def LZD(dout, index, width=16, depth=1, top=None, offset=0):
67
    """
68
    Higher-half LUT of leading zeros for 16bit digits
69
    """
70
    if not top:
71
        top=width
72
    if depth == 0:  # Leaf LUT
73
        # Prepare contents
74
        LZeros = tuple([(count_l_zeros(x, width=width)+offset)%top for x in range(2**width)])
75
        lut = ROM(dout, index, LZeros)
76
    else:           # Recursive create 2 half LUTs
77
        half_width = width / 2
78
        assert half_width * 2 == width, (
79
            "Word length of %s can't be evenly divided into 2 parts." % width
80
        )
81
 
82
        # Glue signals
83
        index_h = Signal(intbv(0)[half_width:])
84
        index_l = Signal(intbv(0)[half_width:])
85
        dout_h = Signal(intbv(0)[len(dout):])
86
        dout_l = Signal(intbv(0)[len(dout):])
87
        high = LZD(dout_h, index_h, width=half_width,
88
                    offset=offset, depth=depth-1, top=top)
89
        low = LZD(dout_l, index_l, width=half_width, top=top,
90
                    offset=offset+half_width, depth=depth-1)
91
 
92
        @always_comb
93
        def input():
94
            index_h.next = index[:half_width]
95
            index_l.next = index[half_width:]
96
 
97
        @always_comb
98
        def output():
99
            if index_h == 0:
100
                dout.next = dout_l
101
            else:
102
                dout.next = dout_h
103
 
104
    return instances()
105
 
106
 
107
##############################
108
# R0 of Goldschmidt Division #
109
##############################
110
 
111
def get_gs_entry_shape(width, index_width):
112
    w = index_width
113
    ww = width
114
    r_wl = around(w*1.5)                # Word length of table entry
115
    r_iwl = ceil(log2(1.0*ww/w))        # Integer word length
116
    return (int(r_iwl), int(r_wl-r_iwl))
117
 
118
def gen_GSDiv_R0(width=16, index_width=8, debug=0, roundMode='round_even'):
119
    """
120
    Generates table of R0 for Goldschmidt division
121
 
122
    width -- Bitwidth of divisor
123
    index_width -- Number of leading bits for indexing lut.
124
                   While the first bit of divisor is always 1, so actually only
125
                   index_width - 1 bits will be used for indexing.
126
    R_Q -- Representation of entry in the table
127
    """
128
    R0=[]
129
    w = index_width
130
    ww = width
131
    r_Q = get_gs_entry_shape(ww, w) # Shape of entries
132
    for ii in range(2**(w-1), 2**w):
133
        try:
134
            val = (ii<<(w)) + (1<<(w-1))
135
            d0 = fxint(val/(2.0**(ww)), Q=(0,ww), roundMode=roundMode)
136
            #R0.append(fxint(2.0**(ww)/d0, Q=r_Q, roundMode='round'))
137
            r = fxint(1./d0.fValue, Q=r_Q, roundMode=roundMode)
138
            R0.append(r[r_Q[0]+r_Q[1]:])# roundMode='round'))
139
        except:
140
            print ii
141
            raise
142
 
143
    # Check if the table fulfills our requirements:
144
    #   generate "index_width" bits of leading '1's or '0's
145
    if debug:
146
        # Do tests
147
        for i in range(2**(w-1)):
148
            ii = (1<<(w-1)) | i
149
            if debug > 1:
150
                print '\ndh=%3d' % ii
151
            dh = ii<<w
152
            r0 = fxint(int(R0[i]), Q=r_Q, roundMode=roundMode)
153
            for dl in range(2**(w-1)):
154
                d = fxint((dh + dl)/2.0**(ww), Q=(0,ww), roundMode=roundMode)
155
                q = d*r0
156
                q.Q = (1,ww)
157
                bs = bin(q)
158
                if bs.startswith('10'):
159
                    c = bs[1:].find('1')
160
                else:
161
                    c = bs.find('0')
162
                if c<0:
163
                    c = q.fwl
164
                if debug > 1:
165
                    print '%s(%-8f) x %s(%-8f) = %s(%-14s):%s c=%2d' % (
166
                                d.Bit(), d.fValue, r0.Bit(), r0.fValue,
167
                                q.Bit(), q.fValue, q.rep, c
168
                            )
169
                if c < w:
170
                    raise
171
 
172
    return map(int, R0)
173
 
174
def GS_R0_Gen(dout, index, width=16, index_width=8, debug=0, roundMode='round_even'):
175
    """
176
    Generator of R0 for GoldSchmidt division, implemented as a lookup table
177
 
178
    width -- Word width
179
    index_width -- index width
180
    """
181
    addr_width = index_width - 1 # msb is always 1, while index >= 0.5
182
    msb = width - 1
183
    lsb = msb - addr_width
184
    R0 = tuple(gen_GSDiv_R0(width=width, index_width=index_width, debug=debug, roundMode=roundMode))
185
    # Only index_width - 1 bits are needed for indexing
186
    addr = Signal(intbv(0)[addr_width:])
187
    lut = ROM(dout, addr, R0)
188
 
189
    @always_comb
190
    def decode():
191
        #addr_i = intbv(0)[index_width-1:]
192
        #addr_i = index[:index_width]
193
        #addr.next = addr_i[addr_width:]
194
        addr.next = index[msb:lsb]
195
 
196
    return instances()
197
 
198
 
199
#############
200
# unit test #
201
#############
202
 
203
def tb_lzd():
204
    width = 16
205
    clk = Signal(False)
206
    d = Signal(intbv(0)[width:])
207
    lzeros = Signal(intbv(0)[get_lzd_width(width):])
208
    lzd = LZD(lzeros, d, width=width, depth=1)
209
 
210
    @always(delay(10))
211
    def clkgen():
212
        clk.next = not clk
213
 
214
    @instance
215
    def stim():
216
        yield delay(1)
217
        while 1:
218
            print 'd=%17s lzd=%d' % (my_bin(d,16), lzeros)
219
            if d >= 256:
220
                d.next = (d+(1 << 8)) % 65536
221
            else:
222
                d.next = d + 1
223
            yield clk.posedge
224
 
225
    #@always(clk.negedge)
226
    #def monitor():
227
        ## moniting on negedge 
228
 
229
    return instances()
230
 
231
def tb_gs_r0():
232
    width = 16
233
    iw = 8
234
    clk = Signal(False)
235
    d = Signal(fxintbv(0.5, Q=(0,width)))
236
    qt = get_gs_entry_shape(width, iw)
237
    r = Signal(fxintbv(0, Q=qt))
238
    q = Signal(fxintbv(0, Q=(qt[0],width)))
239
    gsr0 = GS_R0_Gen(r, d, index_width=iw)
240
    print qt
241
 
242
    @always(delay(10))
243
    def clkgen():
244
        clk.next = not clk
245
 
246
    @instance
247
    def stim():
248
        yield delay(1) # load r
249
        while d.fValue < 1:
250
            q.next = intbv(d.value*r.value)[:qt[0]+qt[1]-1].signed()
251
            yield delay(1)
252
            print 'd=%s(%f) * r=%s(%f) == q=%s(%f) %f' % (
253
                d.Bit(), d.fValue, r.Bit(), r.fValue,
254
                q.Bit(), q.fValue, 1.0/d.fValue)
255
            d.next = d.value + 1
256
            yield clk.posedge
257
 
258
    return instances()
259
 
260
def test_conv():
261
    rQ = get_gs_entry_shape(16, 8)
262
    addr = Signal(intbv(0)[16:])
263
    dout = Signal(intbv(0)[4:])
264
    rout = Signal(fxintbv(0, Q=rQ))
265
    toVHDL(LZD, dout, addr)
266
    toVHDL(GS_R0_Gen, rout, addr, debug=0)
267
    #gen_GSDiv_R0(debug=True)
268
 
269
if __name__ == '__main__':
270
    test_conv()
271
    tb = tb_gs_r0()
272
    #tb = tb_lzd()
273
    #gen_GSDiv_R0(debug=2)
274
    ##tb = traceSignals(tb_reciprocal)
275
    Simulation(tb).run()
276
 
277
### EOF ###
278
# vim:smarttab:sts=4:ts=4:sw=4:et:ai:
279
 

powered by: WebSVN 2.1.0

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