【第二届集成电路EDA备赛】三、“时序模块驱动冲突的检查”赛题介绍及思路

举报
ReCclay 发表于 2022/02/22 00:34:22 2022/02/22
【摘要】 一、赛题描述 在RTL的设计中,有一部分是组合逻辑(combinational logic),一部分是时序逻辑(sequential logic)。一般而言,时序逻辑的每个输出只能有一个驱动(drive...

一、赛题描述

在RTL的设计中,有一部分是组合逻辑(combinational logic),一部分是时序逻辑(sequential logic)。一般而言,时序逻辑的每个输出只能有一个驱动(driver),该驱动可以是组合/时序逻辑的输出。如下图:

在这里插入图片描述

在实际RTL开发中,有一类比较常见的错误,就是一个时序电路的输出(如Q)会有多个驱动,如下图:

在这里插入图片描述

通常,这种错误往往在仿真结果出现问题的时候才能发现,就像刚才说的,验证工具读入verilog design,生成可执行程序,执行可执行程序,如果发现结果错误,这个时候用户需要调试。对于用户来说,调试起来周期非常长,尤其是RTL设计非常大的时候。

理想的情况是验证工具进行静态检查,让这类问题在编译阶段报出,从而节省用户的调试时间。这个需求最早是由INTEL公司提出来的。

本赛题就是要求参赛选手开发这样一种静态检查的功能。

二、驱动冲突的规则

1、驱动冲突的检查对象是变量(variable),而非 wire(net type) , 因为 IEEE 标准已经确保了 wire 是不能用被时序电路驱动的。变量的类型包括 reg, integer 等。

2、驱动冲突的检查模块是 always block,在其他 scope 下,多个驱动是允许的。如两个initial block 里驱动同一个变量是合法的。但是同一个变量同时被一个 initial block 和 always block 驱动就是有冲突的。

3、在同一个 always block 中的多次写操作不视为驱动冲突。

always @(posedge clk) begin
	if (sel)
		Q <= D1;
	else
		Q <= D2;
end

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

三、测例描述

RTL 设计以 Verilog 形式,如下图所示:

module dut (input a, b, c, e, output q);
wire a, b, c;
reg r;
reg clk;
reg q;
reg d;

always @(a, b, c)
	d = a & (b | c);

always @(e)
	q = e;

always @(posedge clk)
	q <= d;
endmodule

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

输出:屏幕上需要打出如下报错信息(至少两个)

The following drivers conflict:
Line 12
Line 15

  
 
  • 1
  • 2
  • 3

四、评分标准

评分标准包括功能的覆盖程度、代码质量、 测试,及性能等几部分。

4.1、功能覆盖及质量 ( 80 分)

1、基本功能(20 分)

支持 scalar【标量类型】(如:reg 等), 以各种 driver【驱动类型】。

没有范围规范的net或reg声明应该被认为是1位宽,被称为标量【scalar】

driver类型是指continue assign和procedure assign;要看的是variable类型的driver,例如reg类型。

2、支持 vector、memory、select ( 30 分)

多位net和reg数据类型必须通过指定一个范围来声明,这个范围称为向量【vector】。(类比C语言的一维数组)

memory是一个寄存器数组,如reg\[3:0\] memo\[255:0\]表示 256个4位存储器,该存储器地址范围是0-255。(类比C语言的二维数组)

select通常用来选择某几位,配合case一起使用

如:

reg [3:0] aa
always @(bb)
	aa[0] = bb;
always @(posedge clk)
	aa[1] = cc;

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

这个例子应该是没有冲突的,因为他们的 select 不同,而下面这个会在 a[1]有冲突:

always @(bb)
	aa[1:0] = bb;
always @(posedge clk)
	aa[3:1] = cc;

  
 
  • 1
  • 2
  • 3
  • 4

3、支持 for loop 分析 (30 分):

a)、支持单层的 for loop ( 15 分)

reg [0:7] aa;
reg [0:7] bb;
reg [0:7] cc;
always @(posedge clk)
	for (i = 0; i < 4; i++)
		aa[i] <= cc[i];
always @(posedge clk) begin
	for (i = 3; i < 8; i++)
		aa[i] <= bb[i];
end

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

这里, aa[3] 是有冲突的, 其他位没有冲突

b)、支持嵌套的 for loop (15 分)

reg [0:7] aa [0:15];
always @(posedge clk)
	for (i = 0; i < 7; i++)
		for (j = 0; j < i + 1; j++)
			aa[i][j] = cc;

always @(posedge clk)
	for (i = 0; i < 7; i++)
		for (j = i+1; j < 15; j++)
			aa[i][j] = bb;

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

以上两个是没有冲突的。

4.2、代码及测试 (10 分)

主要评估标准:

  • 1)选手代码的整洁程度,可读性,可调试性
  • 2)对原开源源代码的改动在满足性能/功能的前提下,要尽可能的小(避免重复开发而导致质量问题)
  • 3)是否有测试方案以确保软件的正确性

4.3、性能 (10 分)

根据一组提供的 benchmark(性能测试集), 以 compile time(CT)为衡量依据。性能超越 80%参赛选者得 10 分,性能超越 50%参赛选手者得 5 分。

4.4、附加题 (20 分)

Verilog 有一种概念是 hierarchical reference【层次参考】 , 即从一个 module 可以访问定义在另一个module 的 variable. 例如:

module top;
	sub s0();
	wire r;
endmodule

module sub;
	wire w;
	assign top.r = w; //hierarchical reference
endmodule

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

其对应的概念是:

在这里插入图片描述
如果 ‘sub’ module 在 ’top’ 下面有多个 instance , 会造成’r’ 有多个驱动。完整的例子如下:

module top;
	reg q;
	submod s1();
	submod s2();
endmodule

module submod();
	reg d, clk;
	always @(posedge clk)
		top.q <= d;
endmodule

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

由于这个驱动在源代码中只有一处,为了给用户更多信息,需要把这个驱动所在的 hierarchal path 打出来:

The following drivers conflict:
Line 8, in instance top.s1,
Line 8, in instance top.s2

  
 
  • 1
  • 2
  • 3

五、测试集

最后提交的是一个可执行程序。要求:速度快、内存小。【功能、性能】

比赛开始时,将提供 50 个左右单元测试供参赛选手使用。

验收时,将在另外一个测试集 (100-200 个 case)中测试选手的提交的软件,以通过率作为功能覆盖率(4.1)的打分标准。另外,会有一个性能测试集(20 个左右 benchmark),作为性能(4.3)的打分标准。

六、技术要点

6.1、技术要点1

本题用到的例子是一个RTL design。通常,RTL design由组合逻辑和时序逻辑构成。一个数字电路的网表抽象出来后就是一个图,每个变量是一个节点,变量之间的连线就是边。每个节点会有驱动(driver),和负载(load)【驱动和负载时相互的】。

要想实现本赛题的驱动检查,首先需要从表面的Verilog语言建立出一个这样的图,方便查询每个节点的驱动

在这里插入图片描述

6.2、技术要点2

RTL design的抽象程度要高于门级(gate level)。这意味着,会有vector, memory这样的word-level 的数据类型,以及 for loop 这样的控制类型语句。

always @(posedge clk) begin      
	if (reset)     
	    for (i = 3; i < 8; i++) 
	        aa[i] <= bb[i]; 
end

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

七、iverilog数据结构

Verilog 文件经过parse,elaboration以后,变成了netlist。Parsing 阶段会把Verilog 文件转换成中间格式pform。 elaborate阶段会把design展开,链接符号,生成一个完全展开的netlist。

在这里插入图片描述
其中,top的class名字叫scope【NetScope】,他有两个children,一个叫s1,一个叫s2。s1也是一个scope【NetScope】,他里面有自己的一些成员函数。

主要的数据结构都在文件netlist.h中,并且每种数据类型都有非常详细的注释。通过学习这个文件,我们需要了解Verilog的module,always, 赋值语句,continue,assign等分别对应于哪个数据结构,这是我们做题的前提条件。

在这里插入图片描述

上述右侧verilog代码第10行和第12行发生冲突。

类NetNet:verilog的wire、reg类型都在这个类里面,其中的type可以来表示其到底是wire还是reg。
类Netproc:定义了一个statement(整个赋值语句),可以是阻塞赋值q=e、非阻塞赋值q<=d、if语句、for语句。【是一个子类、继承了阻塞赋值和非阻塞赋值】
类NetExpr:表达式(赋值语句的右值)。比如a & (b | c)、e、d
类NetAssign_:赋值语句的左值。NetAssign_包含了NetNet,故上述的d也是一个NetAssign_
类NetScope:通过该类,可以找到每一个变量或者语句。
类NetProcTop:NetProcess代表了一个链表,由多个always或initial块组成,而NetProcTop表示的是该链表的Header(头)。

八、解题思路

本赛题要求参赛者在编译阶段检查驱动冲突,在做完 Elaboration后,整个design的hierarchy(层级结构)已经建立起来, 各节点的连接关系都可以遍历。函数入口在main.cc 里的elaborate(),参赛者可以在elaborate() 结束后检查驱动冲突。

遍历所有的gate,将其输出放到一个map里,如果它的个数大于1,那他就是一个multdriver,这种思路不是很高效!

把整个图都建立起来,遍历每个点,如果这个点有很多的driver,那么就把这个点报出来!


参考

文章来源: recclay.blog.csdn.net,作者:ReCclay,版权归原作者所有,如需转载,请联系作者。

原文链接:recclay.blog.csdn.net/article/details/108685354

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。