Spyglass是重要的CDC检测工具,主要功能是抽象SOC,生成sgdc文件,支持RTL分析、CDC分析、功耗分析等。 完整的SOC项目可能会生成几十个sgdc文件,每个文件的行数将达到数万行。 手动分析sgdc文件很麻烦,需要使用脚本来帮助分析。
python版本: python 3.7
使用的工具:正则表达式
任务目标:分析所有sdgc文件,生成同名的csv文件。 csv文件中的详细表述抽象端口的信息
预处理文件必须首先在只读模式中打开Spyglass生成的sgdc文件。 不能破坏原始的sgdc文件。 打开sgdc文件后,有大量的约束换行。 具体情况如下。
clock-name ' XXX '-tag XXX-domain D7-period 40000-edge '0' ' 20000 ' clock-name ' XXX '-tag XXX - domaind0- period 1666.666626-edge '0' ' 833.333313 ' clock-name ' XXX '-tag XXX- domain D1-period 1250-edge ' 0
defsgdc_func(path,file_name ) :file1=open ) path'/'file_name, ' r ' ) file1_ temp _ name=file _ name [ :-5 ] ' _ revised ' '.sgdc ' file1_ temp=open (file1_ temp _ namp ) ) )、replaceandnwith'fillace 0) relocatethefilepointertofileheadfile1_ lines=file1_ temp.read lines )
file1_lines是一个列表,元素是sgdc文件中每行的约束条件,元素类型为字符串。
关键字匹配最重要的部分是基于去掉约束换行后提取,csv文件的报头信息如下:
file2_ name=file _ name [ :-5 ] '.CSV ' file2=open (file2_ name,' w ' ) file2.write (,'.Join ) ) clock/domain/source ',' direction/period/divide/value ' ) 'n ' ) name是端口名称,有三种类型:端口、时钟和复位。
width/clk/reset标记端口的位宽,区分clk和generated_clk,并标记reset;
模块/标记端口所属的模块、标记时钟的标记;
clock/domain/source标记端口受哪些时钟约束,标记时钟所属的时钟字段,generated_clk的source;
direction/period/divide/value标记端口方向,标记时钟周期,标记分频系数,标记重置值
abstract_port默认sdgc文件中的所有端口属于同一模块;
关键字abstract_port表示此语句约束端口。 代码如下所示。
num=0if file1_lines 3360 # file1_ linesisalistforiteminrange (len ) file1_ lines ) (:if ) re.search ) Abstrach file1_lines[item] ) (: # key word abstract_port匹配模式为abstract_port -ports。 这是因为有些注释也跟在abstract_port,-ports之后
计算位宽很麻烦。 因为sgdc文件的端口位宽有以下几种写法。
abstract _ port-ports ' XXX '-clock ' XXX '-module ' XXX ' abstract _ port-ports ' XXX [0] '-clock ' XXX-mod
tract_port -ports "xxx[6:4]" -clock "xxx" -module "xxx" -related_ports xxx[0] xxx[1]总结规律: 多位宽一定会有[],但是有[]不一定是多位宽,因为-related_ports的参数 也可能包含[],不带[]一定是单位宽,带了[]也可能是单位宽;
python处理时将多位宽和单位宽分开处理,一个关键的匹配模式是:
这个匹配模式 将related_ports中的中括号忽略了,不识别单位宽,识别了多位宽的所有形式;
将带 : 的形式与 不带 : 的形式分开处理, 带 : 的形式 分别提取出 : 左右两边的 数字, 作差以后取绝对值再加1,作为此行语句的对应位宽, 不带 : 位宽直接加1;
同时需要提取出当前行 和下一行的端口名字, 如果端口名字是一样的, 表明当前的端口描述还未结束,需要继续分析下一行,如果不一样,表明当前端口描述结束,计算出端口的位宽即可,具体代码如下:
单位宽语句的处理,直接将位宽加1即可!
多余空格和引号的处理实际分析sgdc文件时,发现 -ports等所有关键词与后面的参数之间,未必是固定一个空格,可能存在若干个不定数量的空格,且参数有可能用引号包裹,也有可能没有引号包裹,所以匹配模式的通用形式是
(?<=(-module ))s*"?[^ "b]*-xxx表明关键字,但是 后面必须要有s*,否则会漏匹配一些语句,且python的正则表达式不支持将 不定长的内容用 ?<= 修饰,其实一般的正则表达式解释器是支持的,"?也很重要,因为参数可能用 " 包裹,也有可能没有引号!
匹配完成后一定要去掉多余的空格和引号,方法为:
这两个的处理方法与abstract_port接近,但是clock -name关键字会同时匹配到clock -name与generated_clock -name,所以还需要再次进行区分
多文件处理 import reimport osfrom sgdc_func import sgdc_funcpath = 'your_path'path_list = os.listdir(path)path_list_sgdc = []for item in path_list: if re.search(r'(.*.sgdc)[^ .swp]?',item): if re.search(r'(.*.sgdc)[^ .swp]?',item).group() == item: path_list_sgdc.append(item)print("There are %d sgdc files!n" %len(path_list_sgdc))path_list_sgdc.sort()首先使用os.listdir()函数获取指定路径下所有的 文件名列表,注意区别sgdc格式的文件和sgdc.swp格式的文件。