Files
super6502/hw/efinix_fpga/ip/bram/efx_mem_init_script.py
2022-12-20 15:38:55 -05:00

420 lines
12 KiB
Python

"""
Copyright (C) 2022 Efinix Inc. All rights reserved.
No portion of this code may be reused, modified or
distributed in any way without the expressed written
consent of Efinix Inc.
Created on Dec 22, 2021
@author: Dragon Lai
"""
import sys
import os
import argparse
import math
import json
from enum import Enum
FAMILY = 0
in_addr_width_a = 0
in_data_width_a = 0
in_addr_width_b = 0
in_data_width_b = 0
actual_size_A = 0
actual_size_B = 0
byteen_width = 0
group_data_width = 0
group_columns = 0
bram_decompose_mode = 0
bram_feature_table = list()
group_columns = list()
bram_decompose_table = list()
bram_mapping_table = list()
rMux_mapping_table_A = list()
wen_sel_mapping_table_A = list()
rMux_mapping_table_B = list()
wen_sel_mapping_table_B = list()
data_mapping_table_A = list()
data_mapping_table_B = list()
address_mapping_table_A = list()
address_mapping_table_B = list()
mem_table = list()
def remove_comment(InString):
result = False
outString = InString
#find comment sytnax '//'
Index_start = InString.find('//')
#find end of line \n after //
if (Index_start != -1 ):
Index_end = InString.find('\n',Index_start)
if (Index_end == -1):
Index_end = len(InString)
if (Index_start == 0 ):
outString = InString[Index_end:]
else:
outString = InString[:Index_start] + InString[Index_end:]
result = True
return result, outString
def remove_comments(InString):
result = True
TempString = InString
while(result):
result, OutString = remove_comment(TempString)
TempString = OutString
return OutString
def dump2memTable(InString,in_format, port, in_data_width, in_addr_width):
ProcesseData = remove_comments(InString)
#print( in_format, in_data_width, in_addr_width)
#print(ProcesseData)
lines = ProcesseData.split()
#print(lines)
bit_count = 1
if (in_format == 'hex'):
bit_count = 4
line_ptr = 0
for line in lines:
if (line_ptr+1) > (2**in_addr_width):
break
bit_ptr = 0
for bits in reversed(line):
if (bit_ptr+1) > in_data_width:
break
value = int(bits, 16)
for x in range(0,bit_count):
# print ( line_ptr, bit_ptr)
if (bit_ptr+1) > in_data_width:
break
mem_table[line_ptr][bit_ptr] = (value % 2)
value = int(value / 2)
bit_ptr = bit_ptr + 1
#print(mem_table[line_ptr])
line_ptr = line_ptr+1
#print(mem_table)
create_memory_init_file(port,in_data_width, in_addr_width )
def create_prmitive_map(data_width, addr_width, primitive_addr_width, primiive_data_width, map_data_msb, map_data_lsb, repeat, interval, row_index):
#print(data_width, addr_width, primitive_addr_width, primiive_data_width, map_data_msb, map_data_lsb, repeat, row_index)
#print(data_width, addr_width, primitive_addr_width, primiive_data_width, map_data_msb, map_data_lsb, repeat, interval, row_index)
primitive_mem = list()
#initial primitive memory profile
for y in range(0,(2**primitive_addr_width)):
row = list()
for x in range(0,primiive_data_width):
row.append(int(0))
primitive_mem.append(row)
primitive_y = int(0)
primitive_x = int(0)
addr_start = row_index * (2**primitive_addr_width)
addr_End = (row_index+1)* (2**primitive_addr_width) -1
#print(addr_start, addr_End, primiive_data_width, map_data_lsb,map_data_msb )
if(addr_End > (2**addr_width)-1):
addr_End = (2**addr_width)-1
for y in range(addr_start, addr_End+1 ):
init_row = mem_table[y]
primitive_x = int(0)
if repeat == 0:
for x in range(map_data_lsb, map_data_msb +1 ) :
if (primitive_x+1) > primiive_data_width:
break
primitive_mem[primitive_y][primitive_x] = init_row[x]
primitive_x = primitive_x+1
#if (map_data_lsb == 10 ):
# print (y, primitive_y,primitive_x, primitive_mem[primitive_y], init_row, map_data_lsb,( map_data_msb-map_data_lsb) +1 )
else:
for r_x in range(0,repeat):
temp_data_lsb = map_data_lsb + (interval * r_x)
temp_data_msb = map_data_msb + (interval * r_x)
for x in range(temp_data_lsb, temp_data_msb +1 ) :
if (primitive_x+1) > primiive_data_width:
break
primitive_mem[primitive_y][primitive_x] = init_row[x]
primitive_x = primitive_x+1
primitive_y = primitive_y+1
#print(primitive_mem)
converted_init_mem = list()
#initial primitive init profile
for y in range(0,40):
row =list()
for x in range(0,32):
row.append(int(0))
converted_init_mem.append(row)
#initial primitive memory profile
primitive_bit_ptr = int(0)
primitive_byte = int(0)
primitive_x_ptr = int(31)
primitive_y_ptr = int(0)
for y in range(0,(2**primitive_addr_width)):
for x in range(0,primiive_data_width):
primitive_byte = primitive_byte + primitive_mem[y][x] * (2** primitive_bit_ptr)
primitive_bit_ptr = primitive_bit_ptr + 1
if primitive_bit_ptr >= 8:
converted_init_mem[primitive_y_ptr][primitive_x_ptr] = primitive_byte
primitive_bit_ptr = 0
primitive_byte = 0
primitive_x_ptr = primitive_x_ptr-1
if primitive_x_ptr < 0:
primitive_x_ptr = 31
primitive_y_ptr = primitive_y_ptr +1
if primitive_y_ptr >= 40:
break
return converted_init_mem
def create_memory_init_file(port, data_width, addr_width ):
f = open("bram_ini.vh", "w")
line = '\n'
line += 'function [255:0] bram_ini_table;\n'
line += 'input integer index;//Mode type \n'
line += 'input integer val_; //Port A index, Port B Index, Number of Items in Loop, Port A Start, Port B Start, reserved \n'
line += 'case (index)\n'
f.write (line)
y = 0
for row in bram_mapping_table:
line = ""
x = 0
line += '%4s: bram_ini_table=\n' %(y)
index_primitive_row = row[0]
index_primitive_column = row[1]
DataA_MSB = row[2]
DataA_LSB = row[3]
DataA_REPEAT = row[4]
DataA_RdMux = row[5]
DataB_MSB = row[9]
DataB_LSB = row[10]
DataB_REPEAT = row[11]
DataB_RdMux = row[12]
primitive_addrW_A = row[16]
primitive_dataW_A = row[17]
primitive_addrW_B = row[18]
primitive_dataW_B = row[19]
maptable = list()
if port == 'a':
maptable = create_prmitive_map(data_width, addr_width, primitive_addrW_A, primitive_dataW_A, DataA_MSB, DataA_LSB, DataA_REPEAT, in_data_width_b, DataA_RdMux)
elif port == 'b':
maptable = create_prmitive_map(data_width, addr_width, primitive_addrW_B, primitive_dataW_B, DataB_MSB, DataB_LSB, DataB_REPEAT, in_data_width_a, DataB_RdMux)
stringline = ""
for Values in maptable:
stringline ="256'h"
for value in Values:
stringline += '%02x' % (value)
line += '(val_==%2s)?' % (x)
line += stringline
line += ":\n"
x = x + 1
line += '0;\n'
f.write (line)
#stringline ="256'h"
#for hexChar in range(0,32):
# #stringline += '%02x' % (y)
# stringline += '%02x' % (0)
#
#
#for x in range(0, 40):
# #line += '(val_==' + str(x) + ')?' + str(feature) + ':'
# line += '(val_==%2s)?' % (x)
#
# line += stringline
# #line += "256'h0000000000000000000000000000000000000000000000000000000000000000"
#
# line += ":\n"
# x = x + 1
#line += '0;\n'
#f.write (line)
y = y +1
line = ""
line += " endcase\n"
line += "endfunction \n"
f.write (line)
f.close()
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Memory Decompose to BRAM')
parser.add_argument("format", choices=['hex', 'bin'], help="Memory file format")
parser.add_argument("init_file", help="Input file name")
parser.add_argument("--port", choices=['a', 'b'], default='b', help="inital data width based on port A(Write) , or port B(Read)")
# run parser
args = parser.parse_args()
text_file = open(args.init_file, "r")
try:
with open('mem_config.txt', 'r') as f:
mem_config = json.loads(f.read())
FAMILY = mem_config[0]
in_addr_width_a = mem_config[1]
in_data_width_a = mem_config[2]
in_addr_width_b = mem_config[3]
in_data_width_b = mem_config[4]
actual_size_A = mem_config[5]
actual_size_B = mem_config[6]
byteen_width = mem_config[7]
group_data_width = mem_config[8]
group_columns = mem_config[9]
bram_decompose_mode = mem_config[10]
bram_feature_table = mem_config[11]
group_columns = mem_config[12]
bram_decompose_table = mem_config[13]
bram_mapping_table = mem_config[14]
rMux_mapping_table_A = mem_config[15]
wen_sel_mapping_table_A = mem_config[16]
rMux_mapping_table_B = mem_config[17]
wen_sel_mapping_table_B = mem_config[18]
data_mapping_table_A = mem_config[19]
data_mapping_table_B = mem_config[20]
address_mapping_table_A = mem_config[21]
address_mapping_table_B = mem_config[22]
data_width = 0
addr_width = 0
if args.port == 'a':
data_width = in_data_width_a
addr_width = in_addr_width_a
elif args.port == 'b':
data_width = in_data_width_b
addr_width = in_addr_width_b
for y in range(0,2 ** addr_width):
column = list()
for x in range(0,data_width):
column.append(0)
mem_table.append(column)
#read whole file to a string
InString = text_file.read()
result = "Data width = " + str(data_width) + " Address width = " + str(addr_width)
print (result)
print ("Status : Memory Initialization has completed")
dump2memTable(InString,args.format,args.port, data_width, addr_width)
#close file
text_file.close()
except OSError as e:
print(f"{type(e)}: {e}")