154 lines
6.7 KiB
Python
154 lines
6.7 KiB
Python
import argparse
|
||
import sys
|
||
import xlrd
|
||
import os
|
||
|
||
def parse_args():
|
||
"""解析命令行参数"""
|
||
parser = argparse.ArgumentParser(description='Generate SRAM wrapper verilog files')
|
||
parser.add_argument('xls_file', help='Excel configuration file path')
|
||
parser.add_argument('-name', help='Specify sheet name to process')
|
||
return parser.parse_args()
|
||
|
||
def validate_sheet(rb, sheet_name):
|
||
"""验证Sheet是否存在"""
|
||
try:
|
||
return rb.sheet_by_name(sheet_name)
|
||
except xlrd.biffh.XLRDError:
|
||
print(f"[Error] Sheet '{sheet_name}' not found in {rb}")
|
||
sys.exit(1)
|
||
|
||
def generate_files(xls_path, sheet_name=None):
|
||
"""主生成函数"""
|
||
rb = xlrd.open_workbook(xls_path)
|
||
|
||
# 处理Sheet选择逻辑
|
||
sheets = [rb.sheet_by_name(sheet_name)] if sheet_name else rb.sheets()
|
||
|
||
for sheet in sheets:
|
||
# 获取列索引(根据模板参数)
|
||
headers = sheet.row_values(1)
|
||
col_map = {
|
||
'name' : headers.index('SramWrapName'),
|
||
'width': headers.index('Width'),
|
||
'depth': headers.index('Depth'),
|
||
'ref' : headers.index('ReferenceName'),
|
||
'port' : headers.index('PortType'),
|
||
'CompilerName' : headers.index('CompilerName'),
|
||
'AssemblyDepth' : headers.index('AssemblyDepth'),
|
||
'AssemblyWidth' : headers.index('AssemblyWidth'),
|
||
'CompileDepth' : headers.index('CompileDepth'),
|
||
'CompileWidth' : headers.index('CompileWidth'),
|
||
'ASYNC' : headers.index('Async')
|
||
}
|
||
|
||
# 新增列存在性检查
|
||
required_columns = ['SramWrapName', 'Width', 'Depth', 'ReferenceName',
|
||
'PortType', 'AssemblyDepth', 'AssemblyWidth']
|
||
missing_cols = [col for col in required_columns if col not in headers]
|
||
if missing_cols:
|
||
error_msg = f"[Error] Sheet '{sheet.name}' missing columns: {', '.join(missing_cols)}"
|
||
if sheet_name: # 指定特定sheet时直接退出
|
||
print(error_msg)
|
||
sys.exit(1)
|
||
print(error_msg + ", skipping...")
|
||
continue
|
||
|
||
print(f"Processing sheet: {sheet.name} with columns: {col_map}")
|
||
# 创建输出目录
|
||
# output_dir = f"output_{sheet.name}"
|
||
output_dir = f"sram_wrap_{sheet.name}"
|
||
os.makedirs(output_dir, exist_ok=True)
|
||
|
||
sram_port = ""
|
||
template_file = ""
|
||
# 处理每行数据
|
||
for row_idx in range(2, sheet.nrows):
|
||
row = sheet.row_values(row_idx)
|
||
# 检查必要列是否有值
|
||
if not row[col_map['name']] or not row[col_map['AssemblyWidth']] or not row[col_map['AssemblyDepth']]:
|
||
print(f"[Warning] Missing required data in row {row_idx}, skipping.")
|
||
continue
|
||
# generate sram wrap
|
||
if int(row[col_map['AssemblyDepth']]) + int(row[col_map['AssemblyWidth']]) == 2:
|
||
if row[col_map['port']] == 'SP':
|
||
sram_port = 'SRAM_SP'
|
||
template_file = "template_sram_sp_wrap.v"
|
||
elif row[col_map['port']] == 'TP':
|
||
sram_port = 'SRAM_SYNC_TP' if (row[col_map['ASYNC']] == 'No') else 'SRAM_ASYNC_TP'
|
||
template_file = "template_sram_tp_wrap.v" if (row[col_map['ASYNC']] == 'No') \
|
||
else "template_sram_tp_async_wrap.v"
|
||
else: # Assembly
|
||
if row[col_map['port']] == 'SP':
|
||
sram_port = 'SRAM_SP'
|
||
template_file = "templake_sram_sp_wrap_asmbly.v"
|
||
elif row[col_map['port']] == 'TP':
|
||
sram_port = 'SRAM_SYNC_TP_ASMBLY' if (row[col_map['ASYNC']] == 'No') else 'SRAM_ASYNC_TP_ASMBLY'
|
||
template_file = "template_sram_tp_wrap_asmbly.v" if (row[col_map['ASYNC']] == 'No') \
|
||
else "template_sram_tp_async_wrap_asmbly.v"
|
||
|
||
print(f"Generated {sram_port} wrapper for: {row[col_map['name']]}")
|
||
# 调用生成函数
|
||
generate_sram_wrapper(
|
||
# input file_path
|
||
template_file = template_file,
|
||
sram_name = row[col_map['name']],
|
||
width = int(row[col_map['width']]),
|
||
depth = int(row[col_map['depth']]),
|
||
ref_name = row[col_map['ref']],
|
||
asmbly_depth_nums = int(row[col_map['AssemblyDepth']]),
|
||
asmbly_width_nums = int(row[col_map['AssemblyWidth']]),
|
||
compile_depth = int(row[col_map['CompileDepth']]),
|
||
compile_width = int(row[col_map['CompileWidth']]),
|
||
output_dir = output_dir
|
||
)
|
||
|
||
# scan the all files of the directory/ to be inclued into xxx.lst
|
||
lst_path = os.path.join(output_dir, f"{output_dir}.lst")
|
||
# # 获取目录中所有.v文件k按字母顺序排序)
|
||
# v_files = [f for f in os.listdir(output_dir) if f.endswith('.v')]
|
||
# 获取目录中所有.v文件并添加路径前缀
|
||
v_files = [f"$PROJ_ROOT/rtl/common/mem/{output_dir}/{f}"
|
||
for f in os.listdir(output_dir)
|
||
if f.endswith('.v')]
|
||
with open(lst_path, 'w') as f:
|
||
f.write('\n'.join(sorted(v_files)))
|
||
# TODO generate .sh
|
||
sh_path = os.path.join(output_dir,f"run_{sheet.name}.sh")
|
||
#commands = [
|
||
# f"../{}"
|
||
#]
|
||
|
||
|
||
|
||
def generate_sram_wrapper(template_file, sram_name, width, depth, ref_name,\
|
||
asmbly_depth_nums,asmbly_width_nums,compile_depth,compile_width,\
|
||
output_dir):
|
||
"""生成单个SRAM包装文件"""
|
||
with open(template_file, 'r') as f:
|
||
template = f.read()
|
||
|
||
# 执行模板替换(根据您提供的模板结构)
|
||
replaced = template.replace('${SramWrapName}', sram_name)\
|
||
.replace('${Width}', str(width))\
|
||
.replace('${Depth}', str(depth))\
|
||
.replace('${AssemblyDepth}',str(asmbly_depth_nums))\
|
||
.replace('${AssemblyWidth}',str(asmbly_width_nums))\
|
||
.replace('${CompileDepth}',str(compile_depth))\
|
||
.replace('${CompileWidth}',str(compile_width))\
|
||
.replace('${ReferenceName}', ref_name)
|
||
|
||
# 写入输出文件
|
||
output_path = f"{output_dir}/{sram_name}.v"
|
||
with open(output_path, 'w') as f:
|
||
f.write(replaced)
|
||
|
||
if __name__ == "__main__":
|
||
args = parse_args()
|
||
|
||
# 必须参数检查
|
||
if not os.path.exists(args.xls_file):
|
||
print(f"[Error] File not found: {args.xls_file}")
|
||
sys.exit(1)
|
||
|
||
generate_files(args.xls_file, args.name) |