一种残膜回收机防缠绕挑膜装置的制 一种秧草收获机用电力驱动行走机构

一种基于C++的FPGA硬件构造语言实现系统

2022-07-16 17:05:06 来源:中国专利 TAG:

一种基于c 的fpga硬件构造语言实现系统
技术领域
1.本发明属于硬件设计领域,具体涉及一种基于c 的fpga硬件构造语言实现系统。


背景技术:

2.目前的硬件设计领域中存在如下几方面问题:
3.一是现有的硬件描述语言缺乏抽象能力,表达能力较弱,因而造成硬件设计难度大、重复性工作多、设计效率低下等问题,为硬件开发带来了很高的门槛。
4.二是硬件领域的社区生态相较软件社区来说并不完善,缺少可便捷重用、可扩展、可快速构建设计的库支持,这使得硬件设计的周期相对较长,效率较低。
5.三是硬件设计很大程度上受到开发工具的制约,而现有的硬件设计工具对于软件系统跨平台的支持较差,且其工具本身的版本兼容性也不能满足设计者的需求,不能给设计者带来良好的开发体验。
6.以上三方面问题的存在一方面阻碍了硬件设计领域本身的发展,另一方面也提高了硬件设计的学习成本,进而为软硬件协同相关领域工作的进展带来了巨大的困难。
7.为了解决上述问题,目前已有通过高级编程语言来快速映射硬件设计的设计方法hls(如vivado hls),能够为软件设计中既有的算法自动生成对应功能的硬件设计。但是这种设计方法通常适合需要在硬件上快速实现某些算法的场景,但其最终映射的硬件可控性低,难以对其进行细粒度的控制,且设计出错后难以进行问题的查找以及调试工作,因此对无法提供很高的定制性。
8.不同于高级综合语言,目前国外已有一些硬件构造语言也尝试解决了硬件设计中存在的问题,硬件构造语言一般都是嵌入某种软件编程语言实现的,最终转换成对应的硬件设计。现有的硬件构造语言相关的研究主要基于python与scala实现,如pyverilog是基于python的、chisel与spinalhdl是基于scala的,它们的目标语言都是verilog hdl。这些技术的实现思路都是利用软件编程的类或函数进行硬件结构的实现与转换。国内尚无类似技术。


技术实现要素:

9.鉴于上述,本发明的目的是提供一种基于c 的fpga硬件构造语言实现系统,将高级编程语言特性融入硬件设计,提高硬件开发效率与表达能力。
10.为实现上述发明目的,实施例提供了一种基于c 的fpga硬件构造语言实现系统,包括代码设计单元、代码编译单元、中间语言解析单元以及转换单元;
11.所述代码设计单元用于提供基于c 实现的语法设计模块,并将基于语法设计模块设计的类的构造函数传输至代码编译单元,其中构造函数记录了电路设计信息;
12.所述代码编译单元用于采用c 编译器对设计构造函数进行编译以形成中间语言;
13.所述中间语言解析单元用于对中间语言进行解析以得到中间语言语法树;
14.所述转换单元用于通过对中间语言语法树进行分析以生成硬件描述语言verilog hdl。
15.在一个实施例中,所述语法设计模块包括端口集合和模块设计部分,所述模块设计部分通过c 的构造函数实现,所述模块设计部分包括线网、寄存器、硬件原语模块、控制流以及子模块;
16.所述端口集合包括输入端口、输出端口,用于连接设计的电路节点,该输入端口和输出端口通过c 中的struct类实现;
17.所述线网用于记录设计电路节点之间的连接关系,通过c 中的类实现,通过定义线网对应类来记录线网名称、线网所属模块;
18.所述寄存器用于记录电路元件、硬件设计的中间值,通过c 中的类实现,通过定义线网对应类来记录寄存器名称、寄存器所属模块;
19.所述硬件原语模块作为内置函数,通过c 的函数实现,函数的参数对应端口列表被提供给设计者设计使用;
20.所述控制流采用c 中的类实现,避开了c 中内置的控制流关键字,支持if-else的控制流模式和switch-case的控制流模式进行设计;
21.所述子模块是指语法设计模块的子模块,与语法设计模块具有相同的功能。
22.在一个实施例中,所述寄存器支持多时钟域触发,即通过指定寄存器的触发信号,以更改寄存器的容纳数据。
23.在一个实施例中,寄存器对应的构造函数参数维护了敏感列表,敏感列表包含了多个时钟触发信号,时钟触发信号以不同的电平信号或时钟边沿表示。
24.在一个实施例中,所述语法设计模块支持线网、寄存器、输入端口、输出端口等硬件类型的相关操作符进行重载,记录操作符类型和参与运算的元素名称,并生成一个中间节点的硬件类型作为运算结果返回,以便能够进行多个硬件类型的连续运算过程。
25.在一个实施例的所述中间语言解析单元采用语法词法分析工具对中间语言进行词法解析与语法树生成,从而在内存中得到一棵完整描述硬件设计的中间语言语法树,中间语言语法树的每个节点都是电路设计中的某个组成部分。
26.在一个实施例中,所述转换单元中,对中间语言语法树进行分析以生成硬件描述语言verilog hdl的过程包括:
27.(1)构建元素引用映射图,即从元素引用名到元素引用类型ref类的映射,其中,ref类记录了元素的硬件名称、硬件类型、数据类型type节点,硬件类型包括线网、寄存器、端口、中间节点、实例化模块的端口;
28.(2)构建敏感列表映射图,即构建verilog hdl中的完整敏感列表字符串到对应触发的寄存器名称列表的映射;
29.(3)处理模块名及端口定义,即将模块名按照verilog hdl的语法进行输出,再对模块端口进行处理,其中,处理是指根据模块的方向、位宽、是否有符号、名称这四个信息进行对应的输出;
30.(4)依据元素引用映射图、敏感列表映射图逐句处理语法设计模块的语句块,包括展开控制流处理和合并相同敏感列表处理;
31.(5)整合步骤(3)和步骤(4)的输出流,生成verilog hdl代码。
32.在一个实施例的步骤(1)中,构建元素引用映射图包括:
33.针对端口,将语法设计模块的所有端口名字与对应数据类型插入元素引用映射图中;
34.针对线网和寄存器,如果是线网和寄存器定义则根据对应信息插入元素引用映射图中即可;
35.针对中间节点,需要先根据中间节点的操作符类型以及参与运算的数据类型来得到节点的数据类型,再记录引用信息;
36.针对模块实例化语句,则需要对已经实例化的模块端口一一进行记录;
37.针对控制流,则需要对控制流的两个分支分别进行构建元素引用映射图函数的递归调用,即重复整个构建元素引用映射图的流程。
38.在一个实施例的步骤(2)中,构建敏感列表映射图包括:
39.首先对对语法设计模块中所有寄存器定义类型的语句进行处理,得到定义寄存器时对应的敏感列表;再将敏感列表转换至最终verilog hdl对应的触发字符串,最后将敏感列表对应的触发字符串作为映射图的键,语句定义的寄存器名插入该键对应的寄存器名称列表中,从而完成敏感列表映射图的构建。
40.在一个实施例的步骤(4)中,所述展开控制流处理包括:将控制流语句的两个分支用一个mux选择表达式进行平铺展开,如果存在控制流嵌套的情况,则嵌套对应的mux表达式即可;
41.所述合并相同敏感列表处理包括:对于寄存器赋值语句,对有着相同敏感列表的寄存器赋值语句进行合并,即只需要有一个从字符串到字符串流的映射表即可,即对于不同的敏感列表字符串,对应不同的赋值语句流,在最终的转换时仅需遍历这一映射表即得到合并后的敏感列表赋值块。
42.与现有技术相比,本发明具有的有益效果至少包括:
43.基于c 的硬件构造语言,将高级编程语言特性融入硬件设计,提高硬件开发效率与表达能力;实现的硬件构造语言基于c ,转换过程消耗更少的系统资源与时长;实现的硬件构造语言较好地支持了多时钟域设计,在寄存器定义时可根据需要灵活方便地选择不同时钟信号作为敏感变量。
附图说明
44.为了更清楚地说明本发明实施例或现有技术中的技术方案,下面将对实施例或现有技术描述中所需要使用的附图做简单地介绍,显而易见地,下面描述中的附图仅仅是本发明的一些实施例,对于本领域普通技术人员来讲,在不付出创造性劳动前提下,还可以根据这些附图获得其他附图。
45.图1是实施例提供的基于c 的fpga硬件构造语言实现系统的结构示意图;
46.图2是实施例提供的基于c 的fpga硬件构造语言实现系统实现的方法流程图;
47.图3是实施例提供的语法设计模块的结构示意图;
48.图4是实施例提供的语法树的示例图;
49.图5是实施例提供的分析中间语言语法树生成硬件描述语言verilog hdl的流程图。
具体实施方式
50.为使本发明的目的、技术方案及优点更加清楚明白,以下结合附图及实施例对本发明进行进一步的详细说明。应当理解,此处所描述的具体实施方式仅仅用以解释本发明,并不限定本发明的保护范围。
51.针对传统的硬件描述语言缺乏抽象能力,表达能力较弱,导致硬件设计效率低的问题;还针对硬件高层综合hls最终映射的硬件可控性低,难以对其进行细粒度的控制的问题;还针对目前已有的硬件构造语言,主要是基于scala或python等软件编程语言,转换过程会消耗大量内存等资源,且耗时较久、性能较差的问题;还针对目前已有的硬件构造语言缺乏足够的对多时钟域设计的支持,使用较为复杂的问题。实施例提供了一种基于c 的fpga硬件构造语言实现系统和方法。
52.图1是实施例提供的基于c 的fpga硬件构造语言实现系统的结构示意图。图2是实施例提供的基于c 的fpga硬件构造语言实现系统实现的方法流程图。如图1和图2所示,实施例提供的基于c 的fpga硬件构造语言实现系统包括代码设计单元、代码编译单元、中间语言解析单元以及转换单元。其中,代码设计单元用于提供基于c 实现的语法设计模块,并将基于语法设计模块设计的代码传输至代码编译单元;代码编译单元用于采用c 编译器对设计代码进行编译以形成中间语言;中间语言解析单元用于对中间语言进行解析以得到中间语言语法树;转换单元用于通过对中间语言语法树进行分析以生成硬件描述语言verilog hdl。下面针对每个单元进行详细说明。
53.语法设计单元
54.实施例中,语法设计单元主要提供语法设计功能,用户通过提供的语法设计模块进行语法设计。其中,语法设计模块是基于c 中的module类实现的,包含一个特殊复合结构(struct类)的成员变量表示模型的端口集合,并在c 的构造函数中记录硬件设计相关信息,即进行硬件电路的设计与其他模块的连接,然后将构造函数用命令的形式导出作为设计代码输入至代码编译单元。
55.c 是一门类型安全的编程语言,所有变量在使用前都需要说明其类型。基于此,本实施例中,基于c 类实现语法设计模块时,也需要进行类型定义,具体地,将语法设计模块包含的所有内容分为两类,一类是硬件类型,另一类是数据类型。其中,硬件类型对应硬件设计中所有可能出现的元素,如模块、端口、寄存器和线网等等,而数据类型对应硬件设计中每个线网或寄存器中容纳的数据,包括其位宽、字面值、是否有符号等属性。
56.如图3所示,实施例提供的语法设计模块包括端口列表和模块设计部分。其中,端口集合port是指模块输入端口、输出端口的集合,在使用上比较类似c 的struct类,只能包含input、output和inoutput类型的端口对象。但由于c 本身没有反射机制,因此在实现过程中,端口集合port知识一个宏定义的语法,最终编译时会转换成一个自定义的类,继承自portvec类,包含当前的模块名及其实例化的名称,以供后续使用。
57.不同两个模块的端口集合之间采用connect()函数进行整体连接,connect()函数将两个端口集合里面所有同名的端口进行连接。同级模型之间的端口必须是输入连输出、输出连输入,父级模块和子级模块的端口连接方向则是输入连输入、输出连输出。对于名字不匹配的端口,connect()函数不进行端口集合级别的自动连接,但可使用connect()赋值符进行连接。
58.实施例中,为了保证生成的hdl代码能够拥有良好的代码规范,输入端口有与输出端口固定为线网类型,即其类继承自线网类,在构造时需要额外记录端口方向,所属模块名及模块对应实例化的名称。
59.如图3所示,模块设计部分包括多个线网、多个寄存器、硬件原语模块、控制流以及子模块。其中,线网和寄存器同样由c 中的类实现,分别在其构造时记录包括名称、所属模块等信息。
60.线网wire类型对应verilog中的wrie,是电路节点。在定义线网实例时需要传入其容纳的数据类型。如需要自定义线网的名称,需要将自定义的线网名称传入构造函数中;若不传入,则命名将随机生成。线网的赋值通过重载“=”赋值符实现,即在使用过程中,仅需要利用赋值符对线网进行赋值即可,也可以使用赋值符将某个线网连接到其他电路节点。
61.寄存器reg类型对应verilog中的reg,仅在给定的触发时机进行值的跳变,寄存器的使用方式、构造函数与线网类似,不同的是可指定寄存器的触发信号。默认触发信号为*,也就是说任意一个依赖的信号发生变化时,寄存器的值都可能会变化。若需要更改寄存器触发信号,从构造函数的第三参数起给出敏感列表,敏感列表包含了触发信号。实施例中,将敏感列表中不同的电平信号或者时钟边沿(表示触发信号)作为可变参数列表中的类型,并在寄存器定义时作为参数传入,从而记录完整的敏感列表。
62.为了保证生成的硬件描述代码能够拥有良好且统一的代码风格,实施例中未对寄存器作阻塞赋值的支持,而是将寄存器相关的赋值操作均理解为非阻塞赋值。这一限制使得设计者如需实现组合电路,仅可通过线网变量来进行设计,涉及到寄存器的电路最终将被综合为时序电路。
63.实施例中,可以对线网、寄存器、输入端口、输出端口的硬件类型的相关操作符进行重载,记录操作符类型和参与运算的元素名称,并生成一个中间节点的硬件类型作为运算结果返回,以便能够进行多个硬件类型的连续运算过程。实施中,线网和寄存器可以容纳一些数据,表示能够承载的数据位宽、字面值、重载运算符以及有无符号等属性。
64.硬件原语模块作为内置函数,通过c 的函数实现,函数的参数对应端口列表被提供给设计者设计使用。实施例中,支持以c 中函数的形式调用verilog hdl原语模块,如and、nand、or、xor等。同样,需要定义硬件原语模块名称,需要在构造函数的第一个参数中给出。
65.控制流是指在硬件设计中的若有条件判断导致的分支设计模式,支持if-else的控制流模式和switch-case的控制流模式进行设计。但是,控制流与c 语法中的关键字冲突,因此将控制流作为不同的类,其构造函数为控制流的判断节点,在判断节点记录控制流分支的信息。而后紧跟一个语法块作为控制流中该分支的设计。
66.具体地,由于c 本身自有if、else和switch、case这四类关键词,因此在实施例提供的控制流中,需要与c 区分开,因而使用if-elif-else、switch-case来达到控制流试实现的目的。此外,由于自身实现机制,在所有的控制流语句块之后需要加上表述结束的宏语法,如if-elif-else之后须声明endif,switch-case之后须声明endswitch。
67.子模块是指语法设计模块的子模块,与语法设计模块具有相同的功能。实施例中,利用语法设计模块进行电路设计时,需要满足以下4个条件:(1)继承fracpp命名空间下的模板类module类,自身为模板类的模板参数,且须为public继承;(2)模块内部需要定义
port类型的public成员变量;(3)在类的构造方式里进行内部电路连接,可包含多个构建方式,最终转换为verilog后生成的模块不同;(4)在构造函数末尾需要调用this-》endmodule()函数表示设计的完成。
68.代码编译单元
69.实施例中,代码编译单元的输入为代码设计单元设计的代码,不同的硬件元素由不同的c 类表示,其构造函数负责记录电路设计的具体信息,即每个模块的名称、输入输出信号、模块内部的组成、线网与寄存器的互相连接、运算等信息。使用一个全局对象存储不同模块的组成信息以及当前设计所有模块名。接着通过通用c 编译器的编译,将存储的每个模块的电路设计信息以字符串的形式导出至文件,得到对应的中间语言。
70.中间语言实际上是一种命令式的自定义语言,它以命令的形式描述了一个大型硬件设计从顶层模块到所有子模块的实现逻辑。这些命令包括模块内部的端口组成、硬件元素的定义、信号之间的连接、寄存器的赋值、所有计算过程中涉及到的中间节点、模块的调用以及控制流等,这些元素共同组成了一个完整的硬件设计。
71.中间语言解析单元
72.基于代码设计单元,硬件设计是以模块为单位,其中包含端口,并在构造函数中实现。设计的代码经过代码编译单元运行可以得到命令式的中间语言,模块对应的中间语言命令队列根据用户的实用方式,会保留在内存中或者转储到文件系统中后续再读入进行中间语言的解析,以及中间表达形式语言树的形成。
73.实施例中,采用语法词法分析工具(例如antlr4)对中间语言进行词法解析与语法树生成,从而在内存中得到一棵完整描述硬件设计的中间语言语法树,中间语言语法树的每个节点都是电路设计中的某个组成部分。如图4所示,实施例生成的语法树结构,图中实线方框表示语法树节点,虚线方框代表枚举类型。树的根节点是一个文件,即整体的硬件设计文件,一个文件下课包含多个语法设计模块,每个模块下又包含两个部分,一部分是多个模块端口,另一个是模块设计部分。
74.转换单元
75.转换单元主要是通过对中间语言语法树进行从根节点向下遍历,对不同的节点做不同的处理以生成对应的verilog hdl语句,最后以文件或字符串的形式进行输出。这些工作具体由codegenerator类和moduleemitter类共同完成。
76.图5是实施例提供的分析中间语言语法树生成硬件描述语言verilog hdl的流程图。如图5所示,中间语言语法树到verilog hdl的转换过程包括:
77.步骤1,构建元素引用映射图reference map
78.即从元素引用名到元素引用类型ref类的映射,其中ref类记录了元素的引用名称、引用类型(包括线网、寄存器、端口、中间节点、实例化模块的端口)、数据类型type节点等关键信息。构建元素引用映射图,需要先记录模块的所有输入输出端口,将其名字与对应数据类型插入元素引用映射图中。接着对模块设计部分中的每个语句逐句进行分析与判断:如果是线网和寄存器定义则直接根据对应信息插入元素引用映射图中即可;如果是中间节点则需要先根据中间节点的操作符类型以及参与运算的数据类型来得到节点的数据类型,再记录引用信息;如果是模块实例化语句,则需要对已经实例化的模块端口一一进行记录;如果是控制流,则需要对控制流的两个分支分别进行构建元素引用映射图函数的递
归调用,即重复整个构建引用映射图的流程。
79.步骤2,构建敏感列表映射图trigger map
80.trigger map是最终hdl中的完整敏感列表字符串到对应触发的寄存器名称列表的映射。为了完整这一映射图的构建,需要对模块中所有寄存器定义类型的语句进行处理,得到定义寄存器时对应的敏感列表,再将敏感列表转换至最终hdl对应的触发字符串,最后将该敏感列表字符串作为映射图的键,这一语句定义的寄存器名插入该键对应的寄存器名称列表中,从而完成敏感列表映射图的构建。
81.步骤3,处理模块名及端口定义
82.这一步相对来说较为简单,只需要将模块名先按照verilog hdl的语法进行输出,再对模块端口一一处理即可。模块端口的处理则需要根据模块的方向、位宽、是否有符号、名称这四个信息进行对应的输出。需要注意的是,这一步中所述的“输出”并非直接输出至命令行或字符串,而是输出至moduleemitter的一个字符串流类型的私有成员变量中。
83.步骤4,逐句处理模块语句块
84.对模块中的每一条语句逐一进行输出处理,不同类型的语句按照verilog hdl的语法进行不同的处理,同时根据其类型输入不同的字符串流,包括硬件元素定义字符串流、模块实例化字符串流、原生verilog hdl嵌入字符串流、线网连接字符串流、硬件原语模块字符串流、寄存器赋值字符串流。在这一流程中,值得一提的是控制流语句,对于控制流语句来说,无法直接将其转换至对应的hdl代码,而是需要将控制流语句的两个分支用一个mux选择表达式进行平铺展开,如果存在控制流嵌套的情况,则嵌套对应的mux表达式即可,这样一来可以得到控制流块里每个被赋值的元素对应的右值表达式,并用赋值表来记录。赋值表中的每一项是一个字符串和表达式的pair,即在控制流中被赋值的每个硬件元素,其赋值来源是怎样的表达式节点。在处理完模块之后,对赋值表中的每一项再逐一进行处理。
85.此外,对于寄存器赋值语句,也需要对有着相同敏感列表的寄存器赋值语句进行合并。但是,这一流程相对来说比较简单,只需要有一个从字符串到字符串流的映射表即可,即对于不同的敏感列表字符串,对应不同的赋值语句流,在最终的转换时仅需遍历这一映射表即可得到合并后的敏感列表赋值块。
86.步骤5,整合所有字符串流,输出verilog hdl代码
87.上述所有流程中得到的代码,均按照语句类型存储在不同的字符串流中。在这一步,仅需按照合理的顺序将流中的字符串合并输出,得到最终的hdl代码即可。输出字符串流的先后顺序依次是:端口定义流、硬件元素定义流、模块实例化流、原生verilog hdl流、线网连接流、硬件原语模块流、优化后的寄存器赋值流。所有字符串流输出结束后,根据verilog hdl语法输出endmodule来表示模块设计的结束,即可完成一个模块的hdl生成流程。
88.需要说明的是,存在不经过中间语言的分析过程,直接从电路设计信息翻译至verilog设计代码的方案。但这样的方案扩展性较差,无法完成具体的实现目标,如将相同触发列表对应的寄存器赋值语句整合等,因此这样的方案生成的verilog代码无法达到更高的可读性。
89.实验例
90.以实现时钟分频器clockdiv为实验,具体通过代码设计单元设计过程为:
[0091][0092]
其中,自定义的clockdiv类为时钟分频器模块,继承自module类。包含一个port结构体的成员变量表示模块的输入输出端口集合。其中,clk与rst为输入信号,位宽为1,分别表示时钟信号与复位信号;clkdiv为输出信号,位宽为32,表示时钟分配输出信号。
[0093]
在clockdiv的构造函数中进行电路的连接。首先定义clkdiv_reg为寄存器类型,位宽32,表示分频信号,在定义时指定了敏感变量为clk信号正边沿与rst信号负边沿。当rst信号为高电平时,重置clkdiv_reg为0,否则自增1。最后将clkdiv_reg连接到输出信号clkdiv上,完成模块设计。
[0094][0095]
如上述代码,在主函数中实例化定义的clockdiv类,并调用转换函数进行转换,最终得到如下的verilog代码:
[0096][0097]
以上所述的具体实施方式对本发明的技术方案和有益效果进行了详细说明,应理解的是以上所述仅为本发明的最优选实施例,并不用于限制本发明,凡在本发明的原则范围内所做的任何修改、补充和等同替换等,均应包含在本发明的保护范围之内。
再多了解一些

本文用于企业家、创业者技术爱好者查询,结果仅供参考。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

相关文献