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

Subversion Repositories ion

[/] [ion/] [trunk/] [src/] [bin2hdl.py] - Blame information for rev 124

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

Line No. Rev Author Line
1 124 ja_rd
"""
2
Builds VHDL file from a template by replacing tags with parameter values.
3
See the makefiles of the code samples included in project ION for usage
4
examples.
5 2 ja_rd
"""
6
import sys
7
import getopt
8
import math
9
 
10
 
11
def usage():
12 77 ja_rd
    print ""
13 2 ja_rd
    print "usage:"
14
    print "python bin2hdl.py [arguments]\n"
15
    print "Inserts data in VHDL template\n"
16
    print "ALL of the following arguments should be given, in any order:"
17
    print "{c|code} <filename>        Code binary image file name"
18
    print "{v|vhdl} <filename>        VHDL template"
19
    print "{a|architecture} <name>    Name of target VHDL architecture"
20
    print "{e|entity} <name>          Name of target VHDL entity"
21
    print "{o|output} <filename>      Target VHDL file name"
22 77 ja_rd
    print "code_size <number>         Size of bram memory in words (decimal)"
23 2 ja_rd
    print "data_size <number>         Size of data memory in words (decimal)"
24 77 ja_rd
    print "flash_size <number>        Size of flash memory in words (decimal)"
25
    print "(note the flash and xram info are used in simulation only)"
26 2 ja_rd
    print ""
27
    print "Additionally, any of these arguments can be given:"
28 84 ja_rd
    print "{t|log_trigger} <number>   Fetch address that triggers file logging"
29 24 ja_rd
    print "{s|sim_len} <number>       Length of simulation in clock cycles"
30 33 ja_rd
    print "{d|data} <filename>        Data binary image file name or 'empty'"
31 2 ja_rd
    print "{h|help}                   Display some help text and exit"
32
    print "{i|indent} <number>        Indentation in VHDL tables (decimal)"
33
 
34
def help():
35
    print "\nPurpose:\n"
36
    print "Reads the code and data binary files and 'slices' them in byte"
37
    print "columns."
38
    print "The data columns are converted to VHDL strings and then inserted"
39
    print "into the vhdl template, in place of tags @code0@ .. @code3@ and "
40
    print "@data0@ .. @data3@. Column 0 is LSB and column3 is MSB.\n"
41 33 ja_rd
    print "Tags like @data31@ and @data20@ etc. can be used to initialize"
42
    print "memories in 16-bit buses, also split in byte columns.\n"
43 2 ja_rd
    print "Other template tags are replaced as follows:"
44
    print "@entity_name@         : Name of entity in target vhdl file"
45
    print "@arch_name@           : Name of architecture in target vhdl file"
46 24 ja_rd
    print "@sim_len@             : Length of simulation in clock cycles"
47 2 ja_rd
    print "@code_table_size@     : Size of code RAM block, in words"
48
    print "@code_addr_size@      : ceil(Log2(@code_table_size@))"
49
    print "@data_table_size@     : Size of data RAM block, in words"
50
    print "@data_addr_size@      : ceil(Log2(@data_table_size@))"
51
 
52
 
53 77 ja_rd
def build_vhdl_flash_table(flash, table_size, indent_size):
54
    # Build vhdl table for flash data
55
 
56
    # fill up empty table space with zeros
57
    if len(flash) < table_size*4:
58
        flash = flash + '\0'*4*(table_size-len(flash)/4)
59
 
60
    num_words = len(flash)/4
61
    remaining = num_words;
62
    col = 0
63
    vhdl_flash_string = "\n" + " "*indent_size
64
    for w in range(num_words):
65
        b0 = ord(flash[w*4+0]);
66
        b1 = ord(flash[w*4+1]);
67
        b2 = ord(flash[w*4+2]);
68
        b3 = ord(flash[w*4+3]);
69
 
70
        if remaining > 1:
71
            item = "X\"%02X%02X%02X%02X\"," % (b0, b1, b2, b3)
72
        else:
73
            item = "X\"%02X%02X%02X%02X\"" % (b0, b1, b2, b3)
74
 
75
        remaining = remaining - 1
76
        col = col + 1
77
        if col == 4:
78
           col = 0
79
           item = item + "\n" + " "*indent_size
80
 
81
        vhdl_flash_string = vhdl_flash_string + item
82
 
83
    return vhdl_flash_string
84
 
85
 
86
 
87 2 ja_rd
def build_vhdl_tables(code,table_size, indent_size):
88
    # Build the four byte column tables. [0] is LSB, [3] is MSB
89 77 ja_rd
    # Useful only for BRAM and SRAM tables
90 2 ja_rd
    tables = [[0 for i in range(table_size)] for i in range(4)]
91
 
92
    # Separate binary data into byte columns
93
    # (here's where data endianess matters, we're assuming big endian)
94
    byte = 0    # byte 0 is LSB, 3 is MSB
95
    index = 0   # index into column table    
96
    for c in code:
97
        #print str(ord(c)) + " " +  str(byte) + " " + str(index)
98
        tables[3-byte][index] = ord(c)
99
        #for k in tables:
100
        #    print k[0:4]
101
        byte = byte + 1
102
        if byte == 4:
103
            byte = 0
104
            index = index + 1
105
 
106
    # Write the data for each of the four column tables as a VHDL byte
107
    # constant table.
108 56 ja_rd
    vhdl_data_strings = [" "*indent_size]*7
109 2 ja_rd
 
110
    for j in range(4):
111
        col = 0
112
        word = len(tables[j])
113
        for c in tables[j]:
114
            word = word - 1
115
            if word > 0:
116
                item = "X\"%02X\"," % c
117
            else:
118
                item = "X\"%02X\"" % c
119
            col = col + 1
120
            if col == 8:
121
                col = 0
122
                item = item + "\n" + " "*indent_size
123
            vhdl_data_strings[j] = vhdl_data_strings[j] + item
124 33 ja_rd
        vhdl_data_strings[j] = "\n" + vhdl_data_strings[j]
125
 
126 56 ja_rd
    # ok, now build init strings for 16-bit wide memories, split in 2 byte 
127 33 ja_rd
    # columns: an odd column with bytes 3:1 and an even column with bytes 2:0
128
    byte_order = [3,1,2,0]
129
    for j in range(2):
130
        col = 0
131
        word_count = len(tables[j*2])
132
        for i in range(word_count):
133
            w_high = tables[byte_order[j*2+0]][i]
134
            w_low  = tables[byte_order[j*2+1]][i]
135
            word_count = word_count - 1
136
            if word_count > 0:
137
                item_h = "X\"%02X\"," % w_high
138
                item_l = "X\"%02X\"," % w_low
139
            else:
140
                item_h = "X\"%02X\"," % w_high
141
                item_l = "X\"%02X\"" % w_low
142
            item = item_h + item_l
143
            col = col + 1
144
            if col == 4:
145
                col = 0
146
                item = item + "\n" + " "*indent_size
147
            vhdl_data_strings[4+j] = vhdl_data_strings[4+j] + item
148
        vhdl_data_strings[4+j] = "\n" + vhdl_data_strings[4+j]
149
 
150 56 ja_rd
    # finally, build init strings for 32-bit wide memories not split into 
151
    # byte columns; useful for read-only 32-bit wide BRAMs
152
    byte_order = [3,2,1,0]
153
    col = 0
154
    word_count = len(tables[0])
155
    for i in range(word_count):
156
        w3 = tables[byte_order[0]][i]
157
        w2 = tables[byte_order[1]][i]
158
        w1 = tables[byte_order[2]][i]
159
        w0 = tables[byte_order[3]][i]
160
 
161
        word_count = word_count - 1
162
        if word_count > 0:
163
            item = "X\"%02X%02X%02X%02X\"," % (w3, w2, w1, w0)
164
        else:
165
            item = "X\"%02X%02X%02X%02X\"" % (w3, w2, w1, w0)
166
 
167
        col = col + 1
168
        if col == 4:
169
            col = 0
170
            item = item + "\n" + " "*indent_size
171
        vhdl_data_strings[6] = vhdl_data_strings[6] + item
172
    vhdl_data_strings[6] = "\n" + vhdl_data_strings[6]
173
 
174
 
175
 
176 2 ja_rd
    return vhdl_data_strings
177
 
178
def main(argv):
179 77 ja_rd
    code_filename = ""          # file with bram contents ('code')
180
    data_filename = ""          # file with xram contents ('data')
181
    flash_filename = ""         # file with flash contents ('flash')
182 2 ja_rd
    vhdl_filename = ""          # name of vhdl template file
183
    entity_name = "mips_tb"     # name of vhdl entity to be generated
184
    arch_name = "testbench"     # name of vhdl architecture to be generated
185
    target_filename = "tb.vhdl" # name of target vhdl file
186
    indent = 4                  # indentation for table data, in spaces
187
    code_table_size = -1        # size of VHDL table
188
    data_table_size = -1        # size of VHDL table
189 77 ja_rd
    flash_table_size = 32;      # default size of flash table in 32-bit words
190 84 ja_rd
    log_trigger_addr = "X\"FFFFFFFF\"" # default log trigger address
191 77 ja_rd
    flash = ['\0']*4*flash_table_size # default simulated flash
192 2 ja_rd
    bin_words = 0               # size of binary file in 32-bit words 
193 24 ja_rd
    simulation_length = 22000   # length of logic simulation in clock cycles
194 2 ja_rd
 
195
    #
196
 
197
    try:
198 84 ja_rd
        opts, args = getopt.getopt(argv, "hc:d:v:a:e:o:i:s:f:t:",
199 2 ja_rd
        ["help", "code=", "data=", "vhdl=", "architecture=",
200 84 ja_rd
         "entity=", "output=", "indent=", "sim_len=", "flash=", "log_trigger=",
201 77 ja_rd
         "code_size=", "data_size=", "flash_size="])
202
    except getopt.GetoptError, err:
203
        print ""
204
        print err
205 2 ja_rd
        usage()
206
        sys.exit(2)
207
 
208
    # Parse coommand line parameters
209
    for opt, arg in opts:
210
        if opt in ("-h", "--help"):
211
            usage()
212
            help()
213
            exit(1)
214
        if opt in ("-v", "--vhdl"):
215
            vhdl_filename = arg
216
        elif opt in ("-o", "--output"):
217
            target_filename = arg
218
        elif opt in ("-c", "--code"):
219
            code_filename = arg
220
        elif opt in ("-d", "--data"):
221
            data_filename = arg
222 77 ja_rd
        elif opt in ("-f", "--flash"):
223
            flash_filename = arg
224 2 ja_rd
        elif opt in ("-a", "--architecture"):
225
            arch_name = arg
226
        elif opt in ("-e", "--entity"):
227
            entity_name = arg
228
        elif opt in ("-i", "--indent"):
229
            indent = int(arg)
230 84 ja_rd
        elif opt in ("-t", "--log_trigger"):
231
            log_trigger_addr = "X\"%08X\"" % (int(arg,16))
232 24 ja_rd
        elif opt in ("-s", "--sim_len"):
233
            simulation_length = int(arg)
234 2 ja_rd
        elif opt == "--code_size":
235
            code_table_size = int(arg)
236
        elif opt == "--data_size":
237
            data_table_size = int(arg)
238 77 ja_rd
        elif opt == "--flash_size":
239
            flash_table_size = int(arg)
240 2 ja_rd
 
241
    # See if all mandatory options are there
242
    if code_filename=="" or vhdl_filename=="" or \
243
       code_table_size < 0 or data_table_size<0:
244 33 ja_rd
        print "Some mandatory parameter is missing\n"
245 2 ja_rd
        usage()
246
        sys.exit(2)
247
 
248 84 ja_rd
    #---------------------------------------------------------------------------    
249
    # Read BRAM initialization file, if any
250 2 ja_rd
    try:
251
        fin = open(code_filename, "rb")
252
        code = fin.read()
253
        fin.close()
254
    except IOError:
255
        print "Binary File %s not found" % code_filename
256
 
257 84 ja_rd
    # Make sure the code and data will fit in the tables
258
    bin_words = len(code) / 4
259
    if bin_words > code_table_size:
260
        print "Code does not fit table: " + str(bin_words) + " words,",
261
        print str(code_table_size) + " table entries"
262
        sys.exit(1)
263
 
264
    # Build the VHDL strings for each slice of the BRAM tables
265
    vhdl_code_strings = build_vhdl_tables(code, code_table_size, indent)
266
 
267
 
268
    #---------------------------------------------------------------------------
269
    # Read XRAM initialization file, if any.
270 2 ja_rd
    if data_filename != "":
271 33 ja_rd
        if data_filename == "empty":
272
            data = []
273
        else:
274
            try:
275
                fin = open(data_filename, "rb")
276
                data = fin.read()
277
                fin.close()
278
            except IOError:
279
                print "Binary File %s not found" % data_filename
280 84 ja_rd
 
281
        # FIXME We're not checking for BSS size here, only .data (?)
282
        bin_words = len(data) / 4
283
        if bin_words > data_table_size:
284
            print "Data does not fit table: " + str(bin_words) + " words,",
285
            print str(data_table_size) + " table entries"
286
            sys.exit(1)
287
 
288
        vhdl_data_strings = build_vhdl_tables(data, data_table_size, indent)
289
    else:
290
        # In case we didn't get a data binary, we will initialize any XRAM in
291
        # the template with zeros
292
        vhdl_data_strings = (["(others => X\"00\")"]*4) + \
293
                            (["(others => X\"00\")"]*2) + \
294
                            (["(others => X\"00000000\")"])
295
 
296
 
297
    #---------------------------------------------------------------------------
298
    # Read FLASH initialization file, if any 
299
 
300 77 ja_rd
    if flash_filename != "":
301
        if flash_filename == "empty":
302
            flash = [0]*flash_table_size
303
        else:
304
            try:
305
                fin = open(flash_filename, "rb")
306
                flash = fin.read()
307
                fin.close()
308
            except IOError:
309
                print "Binary File %s not found" % flash_filename
310 84 ja_rd
 
311
        # make sure file will fit simulated FLASH size
312 77 ja_rd
        bin_words = len(flash) / 4
313
        if bin_words > flash_table_size:
314
            print "Flash data does not fit table: " + str(bin_words) + " words,",
315
            print str(flash_table_size) + " table entries"
316
            sys.exit(1)
317 2 ja_rd
 
318
 
319 84 ja_rd
        # Build the VHDL strings for the simulated FLASH
320 77 ja_rd
    vhdl_flash_string = build_vhdl_flash_table(flash, flash_table_size, indent)
321
 
322 2 ja_rd
 
323 84 ja_rd
    #===========================================================================
324
    # OK, we just read all binary files and built all VHDL memory initialization
325
    # strings. Now start scanning the VHDL template, inserting data where needed
326
 
327 2 ja_rd
    # Read template file...
328
    fin = open(vhdl_filename, "r")
329
    vhdl_lines = fin.readlines()
330
    fin.close()
331
 
332
    # ...and build the keyword and replacement tables
333
    keywords = ["@code0@","@code1@","@code2@","@code3@",
334 33 ja_rd
                "@code31@", "@code20@",
335 56 ja_rd
                "@code-32bit@",
336 2 ja_rd
                "@data0@","@data1@","@data2@","@data3@",
337 33 ja_rd
                "@data31@", "@data20@",
338 56 ja_rd
                "@data-32bit@",
339 77 ja_rd
                "@flash@",
340 2 ja_rd
                "@entity_name@","@arch_name@",
341 24 ja_rd
                "@sim_len@",
342 33 ja_rd
                "@xram_size@",
343 2 ja_rd
                "@code_table_size@","@code_addr_size@",
344 77 ja_rd
                "@data_table_size@","@data_addr_size@",
345 84 ja_rd
                "@prom_size@",
346
                "@log_trigger_addr@"];
347 2 ja_rd
    replacement = vhdl_code_strings + vhdl_data_strings + \
348 77 ja_rd
                 [vhdl_flash_string,
349
                  entity_name, arch_name,
350 24 ja_rd
                  str(simulation_length),
351 33 ja_rd
                  str(data_table_size),
352
                  str(code_table_size),
353 2 ja_rd
                  str(int(math.floor(math.log(code_table_size,2)))),
354
                  str(data_table_size),
355 77 ja_rd
                  str(int(math.floor(math.log(data_table_size,2)))),
356 84 ja_rd
                  str(flash_table_size),
357
                  log_trigger_addr]
358 2 ja_rd
 
359
    # Now traverse the template lines replacing any keywords with the proper 
360
    # vhdl stuff we just built above.
361
    output = ""
362
    for vhdl_line in vhdl_lines:
363
        temp = vhdl_line
364
        for i in range(len(keywords)):
365
            if temp.rfind(keywords[i]) >= 0:
366
                temp = temp.replace(keywords[i], replacement[i])
367
                # uncomment this break to check for ONE keyword per line only
368
                #break
369
        output = output + temp
370
 
371
    try:
372
        fout = open(target_filename, "w")
373
        fout.write(output)
374
        fout.close()
375
        print "Wrote VHDL file '%s'" % target_filename
376
    except IOError:
377
        print "Could not write to file %s" % target_filename
378
 
379
 
380
    sys.exit(0)
381
 
382
 
383
 
384
if __name__ == "__main__":
385
    main(sys.argv[1:])
386
 
387
    sys.exit(0)
388
 

powered by: WebSVN 2.1.0

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