使用Python脚本生成.ralf文件生成寄存器模型

使用软件及版本

  1. 脚本部分
    1. Python3
    2. openpyxl
  2. VCS版本2018的ralgen
  3. EXCEL

一,使用EXCEL做好寄存器描述表格

简单的示例如下

二,编写脚本生成.ralf文件(以Python为例)

(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'

(3)读取到寄存器名(regname)不为空(None)时先处理寄存器的部分再处理寄存器的域,因为写入.ralf文件的顺序就是先写reg再是field。
(4)按照寄存器名(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的个数
(5)根据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

最终生成的.ralf文件效果:
在这里插入图片描述

三, 通过ralgen的命令生成寄存器模型

文件格式随手一搜就有,注意access后的操作类型如 rw 不能大写,所以在Python中用lower()函数将字符串全部变为小写
以下是本次实验用到的
(1)需要使用-l 指明语言

-l sv

(2)指明最顶层的block

-t uart_reg_block

(3)使用64位操作系统

-full64

(4)uvm使用

-uvm

(5)生成对应的html

-gen_html 

(6)需要的ralf文件

mgc_uart_reg.ralf

(7)输出文件名

-o mgc_rm

(8)整个命令

ralgen -l sv -t uart_reg_block -full64 -uvm  -gen_html  mgc_uart_reg.ralf -o mgc_rm

四,生成的文件

(1)HTML文件
在这里插入图片描述
(2)寄存器模型的sv文件
有几个地方我们需要注意一下:
在这里插入图片描述

  1. 寄存器类名都为ral__( 所属block名 )_寄存器名
  2. 操作类型RO变成大写了
    在这里插入图片描述
  3. 会在block里将所有field也表示出来
  4. UVM_REG_ADDR_WIDTH需要自己写
  5. 上面ralf文件中寄存器地址是@+0x?? 但生成的文件中已经变成’h??了。证明ralgen可以识别0x?? 并转换成需要的格式。并不用像大多数博客写的@'h??
2023.7.16 更

以上脚本仍然有些小问题:(1)无法应对有一个寄存器中有多个reserve域(2)configure函数中的0X??会报错

解决方法:
(1): 开辟一个数组,存放该寄存器内已知的域,在写之前读出已知域,如有重名加后缀 ( _1 _2)
(2): 通过字符截位,将读出的复位值去掉0x前缀

    field_reset_num_str = sheet[reset_value_column + str(i+field_num)].value# 复位值
    field_reset_num =  str(field_reset_num_str)[2:]  
  • 3
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值