相关阅读
Design Compiler
https://blog.csdn.net/weixin_45791458/category_12738116.html?spm=1001.2014.3001.5482
HDL Compiler
https://blog.csdn.net/weixin_45791458/category_12893238.html?spm=1001.2014.3001.5482
有一类组合逻辑是基于控制信号选择相应的数据,HDL Compiler将这种逻辑推断为可综合操作符SELECT_OP或MUX_OP。默认情况下,工具会推断出通常适合RTL逻辑需求的单元,但用户也可以自己控制推断过程。
可综合操作符SELECT_OP
SELECT_OP是一种通用的可综合操作符,它拥有N个控制信号,并根据控制信号从N个相应的数据信号中选择一个输出。由于在任意时刻有且只有一个控制信号被置为高电平,这些控制信号被称为独热(One-Hot)控制信号。图1展示了一个可综合操作符SELECT_OP,它从四个单比特数据输入中选择一个输出(数据位宽是任意的),其命名规则为*SELECT_OP_<A>.<B><C>.1<D>,其中A为输入数据个数,B为输入数据位宽,C为控制信号个数,D为输出数据位宽。

图1 四选一单比特可综合操作符SELECT_OP
由于控制信号是独热的,HDL Compiler在读取RTL代码时会根据功能使用GTECH单元构建逻辑以对控制信号进行独热译码,如图2所示。

图2 可综合操作符SELECT_OP及其控制逻辑
Design Compiler在综合时将用包括简单逻辑门(例如AND2、OR2)、复杂逻辑门(例如AOI21、OAI21)和多路选择器(MUX21、MUX41)在内的组合逻辑门实现可综合操作符SELECT_OP及其控制逻辑。
例1展示了一种可综合操作符SELECT_OP的推断情况。
// 例1
module mux(
input wire A,
input wire B,
input wire D1,
input wire D2,
input wire D3,
output reg Z
);
always @(*) begin
if (A && !B)
Z = D1;
else if (!A && B)
Z = D2;
else
Z = D3;
end
endmodule
图3展示了HDL Compiler读取例1后的结果,控制信号使用以信号A和B作为输入的逻辑锥进行独热译码。

图3 可综合操作符SELECT_OP的推断
图4展示了Design Compiler综合例1后的结果,可综合操作符SELECT_OP及其控制逻辑一起被映射为由简单逻辑门、复杂逻辑门和多路选择器组成的最优实现。

图4 可综合操作符SELECT_OP的综合
可综合操作符MUX_OP
MUX_OP是一种通用的可综合操作符,它拥有log₂(N)个控制信号(向上取整),并根据控制信号从N个相应的数据信号中选择一个输出(实际上对于可综合操作符MUX_OP,其输入数据个数是2的幂,未使用的输入在综合后将连接到地)。图5展示了一个可综合操作符MUX_OP,它从四个单比特数据输入中选择一个输出(数据位宽是任意的),其命名规则为*MUX_OP_<A>_<B>_1,其中A为输入数据位宽,B为控制信号个数。

图5 四选一单比特可综合操作符MUX_OP
由于控制信号是二进制编码的,HDL Compiler在读取RTL代码时会根据功能使用GTECH单元构建逻辑以对控制信号进行二进制译码。
Design Compiler在综合时将强烈优先使用多路选择器(MUX21、MUX41)及其树形结构实现可综合操作符MUX_OP及其控制逻辑,但简单逻辑门(例如AND2、OR2)和复杂逻辑门(例如AOI21、OAI21)依旧会在必要时使用(如果可综合操作符MUX_OP被设置size only属性,则其会被强制映射为多路选择器,这可能会导致QoR恶化)。
例2展示了一种可综合操作符MUX_OP的推断情况。
// 例2
module mux (
input wire [7:0] DAT,
input wire [2:0] SEL,
output wire Z
);
assign Z = DAT[SEL];
endmodule
下面为HDL Compiler读取例2时产生的MUX_OP推断报告,图6展示了HDL Compiler读取例2后的结果,控制信号本身就是二进制编码的。
Statistics for MUX_OPs
======================================================
| block name/line | Inputs | Outputs | # sel inputs |
======================================================
| mux/8 | 8 | 1 | 3 |
======================================================

图6 可综合操作符MUX_OP的推断
图7展示了Design Compiler综合例2后的结果,可综合操作符MUX_OP及其控制逻辑一起被映射为由复杂逻辑门和多个多路选择器组成的最优实现。

图7 可综合操作符MUX_OP的综合
对于较大的选择逻辑,使用多路选择器实现通常会比使用组合逻辑门实现速度更快、拥塞更少,但面积可能更大。
默认的可综合操作符推断方式
默认情况下,HDL Compiler会使用一种启发式规则来推断可综合操作符SELECT_OP或MUX_OP,这些规则旨在适配大多数使用场景,表1给出了默认推断方式。
表1 默认推断方式
|-------------------|-----------------------------------------------------------------------------|
| RTL操作符 | 默认推断的可综合操作符 |
| if语句、case语句、三目运算符 | SELECT_OP |
| 向量位选、数组读取 | 若满足hdlin_mux_for_array_read_sparseness_limit变量控制的阈值,则推断为MUX_OP,否则为SELECT_OP |
控制if语句、case语句、三目运算符的推断方式
默认情况下,工具使用可综合操作符SELECT_OP来实现if语句、case语句、三目运算符,但用户可以让工具推断可综合操作符MUX_OP。
控制方式有两种:局部控制(使用综合指令)和全局控制(使用应用变量),这两种控制方式是相互依赖的,具体哪一种优先取决于使用的设置。
全局控制
可以通过hdlin_infer_mux变量(默认值为default)进行全局控制,如表2所示。
表2 hdlin_infer_mux变量的效果
|-------------------------|------------------------------------|-----------------------------------------|
| hdlin_infer_mux变量取值 | 默认推断的可综合操作符(if语句、case语句、三目运算符) | 局部控制 |
| default | SELECT_OP | 可使用infer_mux、infer_mux_override综合指令 |
| all | MUX_OP | 无需使用infer_mux、可使用infer_mux_override综合指令 |
| none | SELECT_OP | 可使用infer_mux_override综合指令 |
即使将hdlin_infer_mux变量设置为default且使用了infer_mux综合指令或将hdlin_infer_mux变量设置为all,还需要满足下面三个变量的条件才能推断出可综合操作符MUX_OP(使用infer_mux_override综合指令强制推断除外):hdlin_mux_size_limit变量(默认值为32)控制输入数据个数上限、hdlin_mux_size_min变量(默认值为2)控制输入数据个数下限、hdlin_mux_oversize_ratio变量(默认值为100)控制数据重复比例上限(稀疏度)。
局部控制
可以通过在RTL中使用以下综合指令进行局部控制:
- // synopsys infer_mux:在一系列应用变量设置允许的情况下推断可综合操作符MUX_OP。
- // synopsys infer_mux_override:强制推断可综合操作符MUX_OP并将其映射为多路选择器树,该综合指令于2013版本推出。
如果使用infer_mux_override综合指令,对应的可综合操作符MUX_OP会被设置size only属性,确保其不会在综合过程中被优化掉(需要注意的是,此时的size_only属性是隐式设置的,这与使用set_size_only命令显式设置不同,无法使用report_attribute命令或get_attribute命令直接查看,而只能使用report_cell命令或report_size_only命令间接查看,隐式size_only属性的优先级高于显式size_only属性),使用list_size_only_types命令可以列出叶单元被设置size_only属性的原因(显式或隐式)。
以下小节描述了每种RTL操作符类型的综合指令放置要求。
if语句
if语句的相关综合指令必须放置在第一个条件表达式的右括号后,如下所示:
// 有效的综合指令
always @(*) begin
if (SEL == 2'b00) // synopsys infer_mux_override/infer_mux
Z = D1;
else if (SEL == 2'b01)
Z = D2;
else
Z = D3;
end
使用综合指令对if语句的要求有:
1、每个条件表达式必须是一个简单变量与常量的等式比较,隐式的单比特布尔测试是支持的,例如if(var)。
// 无效的综合指令
always @(*)
if (SEL + 1 == 2'b01) // synopsys infer_mux_override/infer_mux
Z = D1;
else
Z = 8'h00;
2、条件表达式不能使用除等式比较以外任何其他运算符,包括取反、向量的位选/域选、数组的读取。
// 无效的综合指令
always @(*)
if (~SEL[0] !== 1'b1) // synopsys infer_mux_override/infer_mux
Z = D1;
else
Z = 8'h00;
3、条件表达式中的比较必须是同一个变量。
// 无效的综合指令
always @(*)
if (SEL == 2'b00) // synopsys infer_mux_override/infer_mux
Z = D1;
else if (VAR == 1'b1)
Z = D2;
else
Z = D3;
case语句
case语句的相关综合指令必须放置在条件表达式的右括号后,如下所示:
// 有效的综合指令
always @(*) begin
case (SEL1) // synopsys infer_mux_override/infer_mux
2'b00: PARITY = ^{DAT[7:0]};
2'b01: PARITY = ^{DAT[15:8]};
2'b10: PARITY = ^{DAT[23:16]};
2'b11: PARITY = ^{DAT[31:24]};
endcase
end
三目运算符
三目运算符的相关综合指令必须放置在问号后,如下所示:
// 有效的综合指令
assign ZCMP = (SEL == 1) ? /* synopsys infer_mux_override/infer_mux */ (V1 < V2) : (V3 > V4);
使用综合指令对三目运算符的要求有:
1、问号前的条件表达式必须是一个简单变量与常量的等式比较,隐式的单比特布尔测试是支持的,例如var?。
// 无效的综合指令
assign Z = (SEL > 4'd3) ? /* synopsys infer_mux_override/infer_mux */ A : B;
2、条件表达式不能使用除等式比较以外任何其他运算符,包括取反、向量的位选/域选、数组的读取。
// 无效的综合指令
assign Z = (~SEL[0] !== 1'b1) ? /* synopsys infer_mux_override/infer_mux */ A : B;
命名块
用户还可以将infer_mux综合指令应用于命名always块,相当于对该块内部所有if和case语句使用了infer_mux综合指令,如下所示:
// 有效的综合指令
// synopsys infer_mux "this_block_name"
always @(*) begin: this_block_name
...
end
需要注意的是,只有命名块内的infer_mux综合指令会应用于其中的if和case语句,infer_mux_override综合指令不支持,三目运算符不支持,且if语句依旧需要满足其要求。
设置size_only属性
在"可综合操作符MUX_OP"一节中提到,即使可综合操作符MUX_OP在读取RTL代码时已被推断出来,最终实现并不一定会映射为多路选择器。
如需强制映射为多路选择器(这可能会导致QoR恶化),可以使用set_size_only命令设置可综合操作符MUX_OP的size_only属性,或者让HDL Compiler在读取RTL代码时自动设置size_only属性,这可以通过2008版本引入的hdlin_mux_size_only变量进行控制(默认值为1)。
map_to_mux属性
拓扑模式的Design Compiler Graphical在2013版本引入了map_to_mux属性,用户可以通过拥塞热图的交叉探测功能找到导致拥塞的可综合操作符SELECT_OP或MUX_OP,将它们的map_to_mux属性设置为true,综合(需要使用compile_ultra -spg命令)时将强制映射为多路选择器,该方法与设置size_only属性相比,没有对优化进行过多限制。
compile_prefer_mux变量
拓扑模式的Design Compiler Graphical在2016版本引入了compile_prefer_mux变量(默认值为false),如果将该变量设置为true,综合(需要使用compile_ultra -spg命令)时会运行一种优化策略,用于改善包含选择逻辑的设计中的拥塞问题(可能引发拥塞的选择逻辑会在可行的情况下被转换为多路选择器),但可能会带来额外的运行时间和一定的面积开销。
与map_to_mux属性相比,更推荐使用compile_prefer_mux变量,因为无需用户寻找拥塞热点。
控制向量位选、数组读取的推断方式
默认情况下,工具使用可综合操作符MUX_OP来实现向量位选、数组读取,但用户可以让工具推断可综合操作符SELECT_OP。
控制方式有两种:局部控制(使用综合指令)和全局控制(使用应用变量),这两种控制方式是相互依赖的,具体哪一种优先取决于使用的设置。
全局控制
可以通过hdlin_infer_mux变量(默认值为default)进行全局控制,如表3所示。
表3 hdlin_infer_mux变量的效果
|-------------------------|----------------------------|---------------------------|
| hdlin_infer_mux变量取值 | 默认推断的可综合操作符(向量位选、数组读取) | 局部控制 |
| default | MUX_OP | 可使用infer_mux_override综合指令 |
| all | MUX_OP(忽略稀疏度限制) | 可使用infer_mux_override综合指令 |
| none | SELECT_OP | 可使用infer_mux_override综合指令 |
即使将hdlin_infer_mux变量设置为default,还需要满足下面的条件才能推断出可综合操作符MUX_OP(使用infer_mux_override综合指令强制推断除外):hdlin_mux_for_array_read_sparseness_limit变量(默认值为90)控制数据连接比例下限(稀疏度)。
局部控制
可以通过在RTL中使用以下综合指令进行局部控制(向量位选、数组读取不支持也无需使用infer_mux综合指令):
- // synopsys infer_mux_override:强制推断可综合操作符MUX_OP并将其映射为多路选择器树。
如果使用infer_mux_override综合指令,对应的可综合操作符MUX_OP会被设置size only属性,确保其不会在综合过程中被优化掉(需要注意的是,此时的size_only属性是隐式设置的,这与使用set_size_only命令显式设置不同,无法使用report_attribute命令或get_attribute命令直接查看,而只能使用report_cell命令或report_size_only命令间接查看,隐式size_only属性的优先级高于显式size_only属性),使用list_size_only_types命令可以列出叶单元被设置size_only属性的原因(显式或隐式)。
下面描述了向量位选、数组读取的综合指令放置要求。
整条语句
如果希望综合指令对整条语句生效,将其放置在语句末尾分号后,如下所示:
// 有效的综合指令
assign selected_bit = mem1[addr1][idx1] || mem2[addr2][idx2]; // synopsys infer_mux_override
对于例2,如果使用了infer_mux_override综合指令,则综合结果如图8所示。

图8 可综合操作符MUX_OP的综合
仅对特定维度生效
如果希望综合指令对特定维度生效,将其放置特定维度的右括号前,如下所示:
// 有效的综合指令
assign selected_bit = mem1[addr1 /*synopsys infer_mux_override*/][idx1] || mem2[addr2 /*synopsys infer_mux_override*/][idx2];
嵌套读取
综合指令会作用于该层级及其内部所有嵌套读取,如下所示:
// 有效的综合指令
// 综合指令同时作用于addr1以及嵌套的X
assign selected_bit =
mem1[addr1[X] /*synopsys infer_mux_override*/][idx1[Y]];
设置size_only属性
在"可综合操作符MUX_OP"一节中提到,即使可综合操作符MUX_OP在读取RTL代码时已被推断出来,最终实现并不一定会映射为多路选择器。
如需强制映射为多路选择器(这可能会导致QoR恶化),可以使用set_size_only命令设置可综合操作符MUX_OP的size_only属性,或者让HDL Compiler在读取RTL代码时自动设置size_only属性,这可以通过2008版本引入的hdlin_mux_size_only变量进行控制(默认值为1)。
map_to_mux属性
拓扑模式的Design Compiler Graphical在2013版本引入了map_to_mux属性,用户可以通过拥塞热图的交叉探测功能找到导致拥塞的可综合操作符SELECT_OP或MUX_OP,将它们的map_to_mux属性设置为true,综合(需要使用compile_ultra -spg命令)时将强制映射为多路选择器,该方法与设置size_only属性相比,没有对优化进行过多限制。
compile_prefer_mux变量
拓扑模式的Design Compiler Graphical在2016版本引入了compile_prefer_mux变量(默认值为false),如果将该变量设置为true,综合(需要使用compile_ultra -spg命令)时会运行一种优化策略,用于改善包含选择逻辑的设计中的拥塞问题(可能引发拥塞的选择逻辑会在可行的情况下被转换为多路选择器),但可能会带来额外的运行时间和一定的面积开销。
与map_to_mux属性相比,更推荐使用compile_prefer_mux变量,因为无需用户寻找拥塞热点。