1.采用python脚本生成寄存器模型
首先用excel表格做好寄存器描述
然后编写脚本生成.ralf文件
(1)首先通过openpyxl读取EXCEL表格,
workbook = openpyxl.load_workbook('reg.xlsx') # 返回一个workbook数据类型的值
(2)获得有效表格的整体大小即最大行和列
sheet = workbook['Sheet1'] # 获取某一个表
print(sheet.dimensions) # 获取表格的尺寸大小
row_num = sheet.max_row # 行
line_num = sheet.max_column # 列
(3)写出寄存器的各部分所对应的列,字母是用于后方访问单元格
reg_column = 'A' # 各部分的所在列
address_column = 'B'
reg_access_column = 'C'
field_column = 'D'
field_access_column = 'E'
reset_value_column = 'F'
bit_end_column = 'G'
bit_start_column = 'H'
function_column = 'I'
(4)读取到寄存器名(regname)不为空(None)时先处理寄存器的部分再处理寄存器的域,因为写入.ralf文件的顺序就是先写reg再是field。
(5)按照寄存器名(regname)判断每一个寄存器有几个域(field)。通过regname之间空了多少个来判断。中间穿插了写.ralf的部分。
for i in range(2,row_num+1): # i < row_num 所以要加一 第一行是描述性的
j = i
cell_data = sheet[reg_column + str(i)]
if(cell_data.value!=None): # 处理寄存器
start_row = cell_data.row
# 寄存器的相关属性
reg_name = cell_data.value
reg_addr = sheet[address_column + str(i)].value
reg_access = sheet[reg_access_column + str(i)].value
file_obj.write(" register " + reg_name+ " @" +reg_addr+" {\n")
# file_obj.write("bytes " + str(1)) # byte 没有则自动计算
print("reg name is",reg_name,"reg addr is ",reg_addr,"reg access is ",reg_access)
while(1):
j += 1
if(j < row_num):
if(sheet[reg_column + str(j)].value!=None):
end_row = j
reg_filed = end_row - start_row
print(cell_data.value,"reg filed is" ,reg_filed )
break
else:
end_row = j
reg_filed = end_row - start_row
print(cell_data.value,"reg filed is" ,reg_filed )
break
判断逻辑:
当知道regname不为空(None)时,记录当前行数,开始寻找下一个不为空的名字。注意None的第一个字符是大写
在寻找的过程中要保证不能超出最大范围
找到下一个regname不为空的行数,并与之前记录的作差,并记录下field的个数
(6)根据field的个数依次向下x行,读取field的相关信息
for field_num in range(0,reg_filed) :
fiedl_name = sheet[field_column+str(i+field_num)].value # 域的名字
print("fiedl_name is ",fiedl_name)
field_access = sheet[field_access_column+str(i+field_num)].value # 域的access
print("field access is ",field_access)
field_reset_num = sheet[reset_value_column + str(i+field_num)].value # 复位值
print("field_reset_nume ",field_reset_num)
field_bit_start = sheet[bit_start_column+str(i+field_num)].value # 起始位数
field_bit_end = sheet[bit_end_column+str(i+field_num)].value # 最终位数
field_bits = field_bit_end - field_bit_start + 1 # 共计多少bit
print("bit start " , field_bit_start , "end " ,field_bit_end ,"bits " ,field_bits)
file_obj.write(" field " + str(fiedl_name)+" {\n")
file_obj.write(" bits " + str(field_bits)+";\n")
file_obj.write(" reset " + str(field_reset_num)+";\n")
file_obj.write(" access " + str(field_access).lower()+";\n") # ralgen 区分大小写
file_obj.write(" }\n")
file_obj.write(" }\n")
print("out for ",i)
中间穿插了大量的写文件操作,并且为了.ralf文件内的风格添加了大量空格
最后一行的out for是为了调试时查看是否跳出一次for循环
可以打印以下内容 方便调试。
完整代码如下:
import os
import openpyxl
dst_filename = 'mgc_uart_reg.ralf'
workbook = openpyxl.load_workbook('reg.xlsx') # 返回一个workbook数据类型的值
file_obj = open(dst_filename,'w') # 打开目标文件
print(workbook.sheetnames) # 打印Excel表中的所有表
sheet = workbook['Sheet1'] # 获取某一个表
print(sheet.dimensions) # 获取表格的尺寸大小
row_num = sheet.max_row # 行
line_num = sheet.max_column # 列
reg_column = 'A' # 各部分的所在列
address_column = 'B'
reg_access_column = 'C'
field_column = 'D'
field_access_column = 'E'
reset_value_column = 'F'
bit_end_column = 'G'
bit_start_column = 'H'
function_column = 'I'
# 这里只有一个block所在在循环外面写
file_obj.write("block uart_reg_block { \n")
file_obj.write(" bytes " + str(11)+';\n') # byte
for i in range(2,row_num+1): # i < row_num 所以要加一 第一行是描述性的
j = i
cell_data = sheet[reg_column + str(i)]
if(cell_data.value!=None): # 处理寄存器域
start_row = cell_data.row
# 寄存器的相关属性
reg_name = cell_data.value
reg_addr = sheet[address_column + str(i)].value
reg_access = sheet[reg_access_column + str(i)].value
file_obj.write(" register " + reg_name+ " @" +reg_addr+" {\n")
# file_obj.write("bytes " + str(1)) # byte 没有则自动计算
print("reg name is",reg_name,"reg addr is ",reg_addr,"reg access is ",reg_access)
while(1):
j += 1
if(j < row_num):
if(sheet[reg_column + str(j)].value!=None):
end_row = j
reg_filed = end_row - start_row
print(cell_data.value,"reg filed is" ,reg_filed )
break
else:
end_row = j
reg_filed = end_row - start_row
print(cell_data.value,"reg filed is" ,reg_filed )
break
for field_num in range(0,reg_filed) :
fiedl_name = sheet[field_column+str(i+field_num)].value # 域的名字
print("fiedl_name is ",fiedl_name)
field_access = sheet[field_access_column+str(i+field_num)].value # 域的access
print("field access is ",field_access)
field_reset_num = sheet[reset_value_column + str(i+field_num)].value # 复位值
print("field_reset_nume ",field_reset_num)
field_bit_start = sheet[bit_start_column+str(i+field_num)].value # 起始位数
field_bit_end = sheet[bit_end_column+str(i+field_num)].value # 最终位数
field_bits = field_bit_end - field_bit_start + 1 # 共计多少bit
print("bit start " , field_bit_start , "end " ,field_bit_end ,"bits " ,field_bits)
file_obj.write(" field " + str(fiedl_name)+" {\n")
file_obj.write(" bits " + str(field_bits)+";\n")
file_obj.write(" reset " + str(field_reset_num)+";\n")
file_obj.write(" access " + str(field_access).lower()+";\n") # ralgen 区分大小写
file_obj.write(" }\n")
file_obj.write(" }\n")
print("out for ",i)
file_obj.write("}")
file_obj.close()
print("clear")
SystemExit
2.通过ralgen的命令生成寄存器模型
要使用ralgen命令生成寄存器模型,需要以下步骤:
1. 安装ralgen工具。这个工具可以从Accellera官方网站的SystemRDL项目中获取。下载并安装适合你的操作系统的版本。
2. 编写一个SystemRDL描述文件。这个文件描述了寄存器及其字段的属性和行为。
3. 在终端或命令提示符下,使用ralgen命令来生成寄存器模型。命令语法如下:
```
ralgen -l <language> -t <template> -b <base_addr> -o <output_dir> <input_file.rdl>
```
其中,`<language>`是生成模型的目标语言,可以是Verilog、VHDL或SystemVerilog等;`<template>`是使用的模板类型,可以是uvm、sv等;`<base_addr>`是寄存器的基地址;`<output_dir>`是生成模型文件的输出目录;`<input_file.rdl>`是输入的SystemRDL描述文件。
例如,下面的命令将生成一个UVM的寄存器模型:
```
ralgen -l uvm -t uvm_reg -b 0x1000 -o output my_registers.rdl
```
4. 执行ralgen命令后,会生成相应的模型文件。根据你选择的模板类型和目标语言,生成的文件可能包括一个寄存器模型和一个测试模型。
5. 检查生成的模型文件,确保寄存器及其字段的属性和行为与你的SystemRDL描述文件一致。
这样,你就可以通过ralgen命令生成寄存器模型了。请注意根据你的具体需求调整命令参数。