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

Subversion Repositories ion

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

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

powered by: WebSVN 2.1.0

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