优化与防止被优化
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
注册登录
•论坛
•搜索
•帮助
•导航
SoC Vista -- IC/FPGA设计家园» 30分钟必答 - 无限制提问专区» 设计未完成阶段进行面积评估如何防止被优化
12下一页
返回列表回复发帖
mentor00
超级通吃
版主
1#
打印
字体大小: t T
发表于 2009-11-8 09:48 | 只看该作者
设计未完成阶段进行面积评估如何防止被优化
(本文来自anthonyyi的来信。
请大家一起来解答。
)
为了对整个设计进行性能和面积的评估
在模块尚未全部完成的阶段进入FPGA综合阶段
在顶层设计中instance了所有已完成的模块
但这些模块中有的由于后续模块没有完成,其输出悬空,即没有load
在Synplify下使用Syn_noprune属性
发现在compile阶段能保留上述模块,其RTL view显示模块存在
在map之后观测Technology view发现上述模块已经被优化掉
只剩下输入端口,且无drive
故综合报告无实际意义和参考价值
想请教在如何不改变顶层模块的输出管脚而使综合保留上述无输出的模块
个人想到一种,用syn_probe将输出net probe出来,但这样会有风险因为综合工具似乎只会保留这些与该输出有关的逻辑而优化掉其他的部分
而且该步骤没有进行实战确认:(
本主题由 admin 于 2009-12-2 07:56 加入精华
收藏分享评分
回复引用
订阅 TOP
mentor00超级通吃
版主
2#
发表于 2009-11-8 10:04 | 只看该作者
我想可以参考一下下面的转载内容
提问:
我使用的是synplify pro综合verilog语言,例化了一个BUF,在综合结果里也看到了这个BUF,但是在MAP是这个BUF还是被优化掉了,请问用什么方法将这个BUF保留下来?
解答:
在这个BUF两端的信号线上加上下面的属性——
wire bufin /* synthesis syn_keep=1 xc_props="X" */;
wire bufout /* synthesis syn_keep=1 xc_props="X" */;
解释下:
1、syn_keep=1就是保留这个信号线,是它成为一个instance(synplify的),然后就可以
对它添加XILINX的约束属性;
2、xc_props=“”是synplify为XILINX保留留的约束属性,可以透传到ISE的实现中去,
从而约束实现过程。
3、“X”属性是在MAP时识别的KEEP属性,如果用XST综合就只需要在信号线的两端加上X 属性就可以透传到MAP中去。
但是synplify并不能识别,因此需要通过以上的方法将X属性
透传到MAP中去。
回复引用
TOP
mentor00超级通吃
版主
3#
发表于 2009-11-8 10:04 | 只看该作者
如果是VHDL可以这样来解决
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
library synplify;
USE synplify.attributes.all;
ENTITY delay_cell IS
PORT (
dly_in : IN STD_LOGIC;
dly_out : OUT STD_LOGIC
);
END delay_cell;
ARCHITECTURE archi OF delay_cell IS
--attribute syn_keep : boolean;
SIGNAL temp01, temp02, temp03, temp04, temp05, temp06, temp07, temp08, temp09, temp10, temp11, temp12, temp13 : STD_LOGIC;
attribute syn_keep of temp01, temp02, temp03, temp04, temp05, temp06, temp07, temp08, temp09, temp10, temp11, temp12, temp13 : signal is true;
attribute xc_props of temp01, temp02, temp03, temp04, temp05, temp06, temp07, temp08, temp09, temp10, temp11, temp12, temp13 : signal is "X";
BEGIN
temp01 <=NOT dly_in;
temp02 <=NOT temp01;
temp03 <=NOT temp02;
temp04 <=NOT temp03; temp05 <=NOT temp04; temp06 <=NOT temp05; temp07 <=NOT temp06; temp08 <=NOT temp07; temp09 <=NOT temp08; temp10 <=NOT temp09; temp11 <=NOT temp10; temp12 <=NOT temp11; temp13 <=NOT temp12; dly_out <=NOT temp13;
END archi;
回复引用
TOP
vimicro 通吃版主
4#
发表于 2009-11-8 20:38 | 只看该作者
对一些buffer设置set dont touch
回复引用
TOP
anthonyyi 通吃版
主
5#
发表于 2009-11-8 21:42 | 只看该作者以下是我根据mentor00老师的帖子进行实验的一个小例子
module test(clk,rst_n);
input clk;
input rst_n;
counter u_counter /*synthesis syn_noprune =1 */(
.clk (clk ),
.rst_n(rst_n ),
.p0 (p0 ),
.p1 (p1 )
);
endmodule
module counter(
clk,
rst_n,
p0,
p1
);
input clk;
input rst_n;
output p0;
output p1;
wire p0 /* synthesis syn_keep=1 xc_props="X" */;
wire p1;
reg [3:0] counter;
assign p0 = counter[2];
assign p1 = counter[3];
always @ (posedge clk or negedge rst_n)
if(!rst_n)
counter <= 4'h0;
else
counter <= counter + 1'b1;
endmodule
从综合的结果来看,发现添加syn_keep和xc_props的P0端口在mapping之后保留其technology view可以看到综合结果包括三个寄存器counter[0:2]
未添加约束的counter[3] 被优化掉了
按照这种方法需要将所有需要保存模块输出加上syn_keep属性
此外根据synplify最新版本的提示
@W: FX350 |xc_props attribute is obsolete and will not be supported in a future
release. Please use the attributes inside the xc_props string directly or generics/parameters if they are available
这个属性要改成个什么样子呢
回复引用
TOP
anthonyyi 通吃版
主
6#
发表于 2009-11-8 21:43 | 只看该作者
原帖由vimicro于 2009-11-8 20:38 发表
对一些buffer设置set dont touch
How can I do it, where is the key position for me to find the buffer
回复引用
TOP
anthonyyi 通吃版主
7#
发表于 2009-11-8 22:03 | 只看该作者
此外由于希望在整个评估过程中尽量不改动模块级的RTL代码
顶层的syn_noprone属性一定需要添加
否则compile都过不了,直接就被优化掉了
而且syn_keep的属性必须放在wire定义的那行,放在assign的位置也会被优化掉并且由于syn_keep属性只能针对wire类型
必须从rtlview中找到对应的线添加到sdc文件中才行:)
请大家一起试试,看看有没有别的方法
回复引用
TOP
mentor00
超级通吃版主
8#
发表于 2009-11-9 07:45 | 只看该作者
谢谢anthony的及时反馈与共享。
回复引用
TOP
ineedpower9#
管理员
发表于 2009-11-9 09:46 | 只看该作者
原帖由
anthonyyi于 2009-11-8 22:03 发表
而且syn_keep的属性必须放在wire定义的那行,放在assign的位置也会被优化掉
...
一直以来都以为对于wire和reg类型都可以使用的~~
回复引用
TOP
anthonyyi 通吃版主
10#
发表于 2009-11-9 10:20 | 只看该作者
寄存器用syn_preserve
syn_preserve ensures that registers are not optimized away 回复发帖
ineedpower
管理员
11#
发表于 2009-11-9 10:37 | 只看该作者
4 - Verilog开发仿真 » Synplify SCOPE 属性——高手的秘密
可惜好像还是to be continued~~~
回复引用
TOP
vimicro 通吃版主
12#
发表于 2009-11-11 09:57 | 只看该作者
回复 6# 的帖子
不太明白你的意思我的意思是直接在例化的module name上面设对了我是说DC 是ASIC流程,FPGA上面我不知道能否这样做
shared]Verilog综合时wire与reg如何防止被优化(1)
2009-11-29 14:14
Abstract
撰寫Verilog時,雖然每個module都會先用ModelSim或Quartus II自帶的simulator仿真過,但真的將每個module合併時,一些不可預期的『run-time』
問題可能才一一浮現,這時得靠SignalTap II來幫忙debug。
Introduction
使用環境:Quartus II 8.0 + DE2-70 (Cyclone II EP2C70F896C6N)
實際使用SignalTap II時,會發現有些reg與wire可以觀察,有些又無法觀察,在(原創) 如何使用SignalTap II觀察reg值? (IC Design) (Quartus II) (SignalTap II) (Verilog)中,我利用將reg接到top module的方式來觀察reg,雖然可行,但老實說並不是很好的方式。
當初有網友發表評論,說這是因為reg 被Quartus II優化掉不見了,導致無法使用SignalTap II觀察,本文整理出完整的reg與wire觀察方法。
觀察reg
如同(原創) 如何使用SignalTap II觀察reg值? (IC Design) (Quartus II) (SignalTap II) (Verilog)的範例,我再重複一次。
SSignalTapII_register_not_preserve.v / Verilog
1/*
2(C) OOMusou 2008
3
4Filename : SignalTapII_register_not_preserve.v
5Compiler : Quartus II 8.0
6Description : Demo how to preserve register with SingalTap II
7Release : 10/17/2008 1.0
8*/
9
10module SignalTapII_register_not_preserve (
11input iCLK,
12input iRST_N
13 );
14
15reg [3:0] cnt;
16
17always@(posedge iCLK, negedge iRST_N) begin
18if (!iRST_N)
19cnt <= 4'h0;
20else
21cnt <= cnt + 4'h1;
22end
23
24endmodule
這是個很簡單的計數器,我故意讓cnt不做output,而想用SignalTap II去觀
察cnt這個reg的值。
cnt都是0,顯然不合理,表示SignalTap II無法capture cnt這個reg的值。
為什麼會這樣呢?
若我們將SignalTap II拿掉,重新用Quartus II編譯,觀察其compilation report,顯示register為0。
觀察RTL Viewer的合成結果,真的沒有register!!
這證明了一件事情,Quartus II在合成時,發現cnt並沒有需要output,而自動最佳化不合成cnt,導致SignalTap II無法觀察reg,不過有時為了debug
方便,我們就是想觀察這種reg,有辦法讓Quartus II暫時不要啟動最佳化嗎? 使用Synthesis Attribute避免最佳化
SignalTapII_register_preserve.v / Verilog
1/*
2(C) OOMusou 2008
3
4Filename : SignalTapII_register_preserve.v
5Compiler : Quartus II 8.0
6Description : Demo how to preserve register in SignalTap II
7Release : 10/17/2008 1.0
8*/
9
10module SignalTapII_register_preserve (
11input iCLK,
12input iRST_N
13 )
14
15reg [3:0] cnt /*synthesis noprune*/;
16
17always@(posedge iCLK, negedge iRST_N) begin
18if (!iRST_N)
19cnt <= 4'h0;
20else
21cnt <= cnt + 4'h1;
22end
23
24endmodule
15行
reg [3:0] cnt /*synthesis noprune*/;
多了/*synthesis noprune*/這個synthesis attribute,指示Quartus II不要對cnt做最佳化,保留此register以供SignalTap II觀察,注意必須寫在分號前面,不能如下寫在分號後面。
reg [3:0] cnt;/*synthesis noprune*/ //錯!!
編譯後,SignalTap II就能順利的觀察到cnt的值!!重點是不需改top module 的interface,只需對想觀察的reg加上synthesis attribute即可。
Quartus II也支援Verilog 2001的語法
1/*
2(C) OOMusou 2008
3
4Filename : SignalTapII_register_preserve.v
5Compiler : Quartus II 8.0
6Description : Demo how to preserve register in SignalTap II 7Release : 10/17/2008 1.0
8*/
9
10module SignalTapII_register_preserve (
11input iCLK,
12input iRST_N
13 );
14
15// Verilog 2001
16//(*noprune*) reg [3:0] cnt;
17
18always@(posedge iCLK, negedge iRST_N) begin
19if (!iRST_N)
20cnt <= 4'h0;
21else
22cnt <= cnt + 4'h1;
23end
24
25endmodule
16行
(*noprune*) reg [3:0] cnt;
這是Verilog 2001的語法,Quartus II 8.0也能看得懂。
若希望整個module的reg都不被最佳化,可將synthesis attribute放在module。
1/*
2(C) OOMusou 2008
3
4Filename : SignalTapII_register_preserve.v
5Compiler : Quartus II 8.0
6Description : Demo how to preserve register in SignalTap II
7Release : 10/17/2008 1.0
8*/
9
10module SignalTapII_register_preserve (
11input iCLK,
12input iRST_N
13 ) /*synthesis noprune*/;
14
15reg [3:0] cnt;
16
17always@(posedge iCLK, negedge iRST_N) begin
18if (!iRST_N)
19cnt <= 4'h0;
20else
21cnt <= cnt + 4'h1;
22end
23
24endmodule
13行
module SignalTapII_register_preserve (
input iCLK,
input iRST_N
//);
) /*synthesis noprune*/;
將/*synthesis noprune*/放在module,這樣整個module的reg將不被最佳化,不用再一一指定。
另外一個與reg相關的Synthesis Attribute:/*synthesis preserve*/
跟reg相關的attribute,除了/*synthesis noprune*/可用,還有一個
/*synthesis preserve*/可用,兩者的差異在於:
/*synthesis noprune*/ 避免Quartus II優化掉沒output的reg。
/*synthesis preserve*/ 避免Quartus II將reg優化為常數,或者合併重複的reg。
也可以使用Verilog 2001的寫法
//(*preserve*) reg [3:0] cnt;
或者整個module的寫法
module SignalTapII_register_preserve (
input iCLK,
input iRST_N
) /*synthesis preserve*/;
类别:Ic | | 添加到搜藏| 分享到i贴吧| 浏览(329) | 评论 (0)
上一篇:[shared]Ubuntu下安装Cadence 51... 下一篇:[shared]Verilog综合时wire与reg... 最近读者:
kimi169coffindidi jadekung盖塔Q peipeihan1gywan94p
基于Verilog HDL的模型优化
周信坚李德兵
(江南计算技术研究所,江苏无锡214000)
摘要本文基于模型优化的必要性,对使用Verilog HDL建模时可以运用的优化手段作了详细的阐述,对设计者具有一定的指导意义。
关键词模型优化;综合;表达式
1 引言
每个设计者在进行Verilog建模时都会形成自己的设计风格,同一个电路设计,用Verilog描述可以写出许多逻辑上等价的模型,而大多数设计者考虑的主要是代码书写上的方便和功能上是否正确,对设计的模型是否最优化结构却考虑甚少,这样不仅加重了逻辑综合的负担,影响综合效率,而且很可能会导致设计出的芯片未达到最优的面积和速度。
因此,在Verilog建模时,很有必要进行模型优化。
2 模型优化概述
影响一个芯片性能的指标主要有两个:面积和速度。
模型优化就是通过一定的手段对模型的结构进行调整、组合和精简,从而使设计出的芯片达到更小的面积和更快的速度。
综合所生成的逻辑易受模型描述方式的影响。
把语句从一个位置移到另一个位置,或者拆分表达式都会对所生成的逻辑产生重大影响,这可能会造成综合出的逻辑门数有所增减,也可能改变其定时特性。
因此,采取一定的手段可以实现对逻辑的优化。
但是由于优化终点包含的两个方面面积和速度是互相矛盾的,优化一个方面必定影响另一个方面,而无法实现面积和速度都达到最优,这就需要设计者对两者进行权衡,看设计偏重于哪个方面,而采取不同的优化起点。
下面分别从面积和速度两个方面对模型优化的手段进行介绍。
3 面积的优化
3.1 提取公共子表达式
如果条件语句的互斥分支中有公共子表达式,可以提取该公共子表达式。
如下面的模型可以提取公共子表达式:
P = A&(B+C);
else
Q = (B+C)|D;
此模型中条件语句的互斥分支中都计算了表达式B+C,因此,应将该表达式提取出来放在条件语句之前进行赋值,新模型如下所示:Tmp = B+C;//引入一个临时变量
if(enable)
P = A&Tmp;
else
Q = Tmp |D;
这样,综合工具就会综合出一个加法器,而原来的模型则会综合出两个加法器。
引申到一般情况,若在逻辑中找到有公共子表达式,就可以将该公共子表达式赋值给一个临时变量,然后用该临时变量来表示该公共子表达式,这样就可以减少综合出的ALU单元的数量,以实现面积的优化。
3.2 代码移位
如果在循环语句内某个表达式的值在每次循环中都不变化,可以将该表达式移至循环之外。
如下面的模型可以进行代码移位:
P = …
…
for(i=1;i<=5;i++)
begin
…
Q = P+5;//假设循环中未对P赋新值
…
end
赋值语句“Q = P+5;”右端的表达式不随循环变量而变,因此,应将该表达式移至循环之外,新模型如下所示:
P = …
…
Tmp = P+5;//引入一个临时变量
for(i=1;i<=5;i++)
begin
…
Q = Tmp;
…
end
这样,综合工具对“P+5”只会综合出一个加法器,而原来的模型会产生5个加法器,每循环一次就产生一个,造成了代码冗余。
优化后的新模型不仅减少了综合出的ALU单元的数量,而且提高了仿真效率。
3.3 资源共享
资源共享是指在互斥条件下共享算术逻辑单元(ALU)的过程。
如下面的模型:
if(num>5)
P = A+B;
else
如果不采用资源分配,算符“+”和“-”就会被综合成两个单独的ALU。
而如果采用了资源分配,仅需一个ALU就可以实现“+”和“-”这两种运算。
这是因为这两种算符总是互斥地使用。
此外还生成了一个多路选择器,用来从B和C中选择合适的量接到ALU的第二个输入端上。
实际上,资源分配就是共享算符的过程。
共享算符有以下几种可能的情况:
(1)算符相同,运算量相同。
如:A+B和A+B,这种情况同“提取公共子表达式”,显然必须共享。
(2)算符相同,有一个运算量不同。
如:A+B和A+C,这时需引入一个多路选择器,要进行面积与速度之间的权衡。
(3)算符相同,运算量都不同。
如:A+B和C+D,这时需引入两个多路选择器,要进行面积与速度之间的权衡。
(4)算符不同,运算量相同。
如:A+B和A-B,可以将“+”和“—”合成一个ALU单元,要共享。
(5)算符不同,有一个运算量不同。
如:A+B和A-C,这时需引入一个多路选择器,要进行面积与速度之间的权衡。
(6)算符和运算量都不同。
如:A+B和C-D,这时需引入两个多路选择器,要进行面积与速度之间的权衡。
在共享ALU的时候,要在ALU的某个输入端引入多路选择器,这样会增加路径的延迟。
因此,设计者应根据实际情况权衡是优化面积重要还是优化速度重要,如果是在“定时至上”的设计中,最好不要采用资源共享。
此外,对于复杂的运算单元,可以采用函数和任务来定义这些共享的数据处理模块,以减少器件资源的消耗,降低成本。
3.4 消除触发器
有些设计者为了图编写代码的方便,喜欢将同一条件控制下的赋值语句写在一个时序控制语句中,如下面的模型:
always @(posedge CLK)
begin
case(State)
0:
begin
preState <= 1;
Dout <= 16’h56;
end
1:
begin
preState <= 0;
Dout <= 16’h29;
end
endcase
end
设计者的本意仅是要把preState的值保存在上升沿触发的触发器中,而Dout的值只是受State影响的组合逻辑,原本只需要1个触发器即可,而上述模型综合后的网表会生成17个触发器,浪费了资源,优化后的模型如下所示:
always @(posedge CLK) //推导出触发器
begin
case(State)
0:preState <= 1;
1:preState <= 0;
endcase
end
always @(State) //组合逻辑
begin
0:Dout <= 16’h56;
1:Dout <= 16’h29;
endcase
end
3.5 消除锁存器
推导锁存器的规则是:
(1)变量在条件语句(if或case语句)中被赋值。
(2)变量未在条件语句的所有分支中都被赋值。
(3)在always语句的多次调用之间需要保存变量值。
同时满足以上3个条件,就会将变量推导成锁存器。
有的设计者可能会图省事没有在所有的条件分支中对变量进行赋值,这样就导致原本不需要产生锁存器的变量产生了锁存器,而浪费了资源。
消除锁存器的最好方法是在设计时明确哪些变量需要锁存器,哪些则不需要。
对不需要推导出锁存器的变量,在其所有条件分支中都对其赋值,或者是在条件语句之前对其进行初始化赋值。
4 速度的优化
4.1 使用括号
在表达式中使用括号,可以控制所综合出的逻辑电路的结构,缩短电路的关键路径,从而实现速度的优化。
例如对语句P = A+B-C+D,综合工具在综合右端表达式时遵循从左至右进行演算,就会构造出如图1所示的电路。
使用括号后的语句为:P = (A+B)-(C-D),综合后的电路如图2所示。
图1未使用括号综合出的电路图2使用括号综合出的电路
很显然,未使用括号时关键路径的深度为3,而使用括号后的关键路径深度为2,优化了速度。
4.2 提取关键路径
在电路设计中,有些信号的路径比较长,或者信号本身就来得比较晚,从而造成电路的建立时间不够。
这种引起电路建立时间不够的信号路径称为关键路径。
这种关键信号路径大多要提取出来特别对待,以尽量减少它的延时。
4.2.1提取重复变量
如语句P = (a&b&c)|(b&d&e)中的信号b的路径就是关键路径,可以提取出来单独处理,提取关键路径前后的电路模型如图3所示。
图3 电路模型比较
由图中可以看出,信号b的路径由2级变成了1级,增加了其建立时间,缩短了延迟,而且还减少了一个与门,既提高了速度又减少了面积。
4.2.2提取先行关键路径
如下面的模型所示:
always @(a or b or c or d or e or current_out)
begin
next_out = current_out;
if(!a)begin
if(b & !(d & !e)) next_out = !c;
else next_out = c;
end
else if(d & !e) next_out = c;
end
其中,输入信号e在always语句块中是个时间非常紧的关键信号,需要进行特殊处理。
处理后的模型如下所示:always @(a or b or c or d or e or current_out)
begin
next_out = current_out;
if(e)begin
if(!a) begin
if(b) next_out = !c;
else next_out = c;
end
end
else begin
if(!a) begin
if(b&!d) next_out = !c;
else next_out = c;
end
else if(d) next_out = c;
end
end
上述模型描述了关键信号e的分步提取方法,改写后的描述都与原always块逻辑等效。
5 其它优化手段
5.1 引用工艺库中预定义的宏结构
设计者可以根据需要使用模块实例化语句来实现预定义功能块,就好像对待元件那样,在模型中对其进行实例化,然后再综合此实例模型。
例如,要建立一个加法器,根据面积约束,可以调用一个面积高效的行波加法器,而根据延时约束,可以调用一个快速但面积较大的先行结构加法器。
5.2 使用小型设计
实验研究表明逻辑电路规模在2000门至5000门时逻辑优化器的优化效果最佳,因此,设计时应尽量组织成多个模块或多个always语句段。
综合过程的运行时间主要用于逻辑优化,它与设计规模呈指数关系,因此将各个子功能块的规模保持在可处理的设计范围内很关键。
5.3 传播常量
使用常量传播技术可以增加电路模型修改的灵活性和可移植性。
如果有一个确定意义的常量并且在模型中的多处地方都引用到,则可以将该常量值定义为一个常量符号,然后直接引用该常量符号即可,如下所示:
parameter COUNT = 16;
…
P = COUNT*2;
for(i=0;i<COUNT-1;i++)
…
其中,COUNT表示的是循环次数,根据需要可以在语句“parameter COUNT = 16;”中修改其值。
由于它是一个常量,在综合时不会为表达式“COUNT*2”和“COUNT-1”生成任何硬件,而是在编译时直接计算出表达式的值并将其赋给变量。
6 结束语
一般情况下,综合工具会自动对Verilog模型进行优化,但如果设计者在电路设计时直接就编写出结构优化的电路模型,就会大大减少综合工具的运行时间,甚至有时候综合工具无法优化的结构经过手工调整后实现了优化的目的。
因此,养成良好的设计风格是很重要的,在设计时不仅要保证设计的正确性,还要注重设计的高效性,避免不必要的反复修正,这样才能提高设计效率,缩短开发周期。
参考文献。