|
楼主 |
发表于 2023-2-20 10:30:40
|
显示全部楼层
根据新思的信息:
1) When HDL Compiler reads the design, it has the ability to remove some registers and not infer them. The tool does not issue a warning message when this optimization is done.
确实很存在一些不报告log的remove register动作。
When Does Design Compiler Remove Nonconstant Registers With an OPT-1207 Warning?
Question:
When does Design Compiler remove nonconstant registers? Sometimes Design Compiler
issues an OPT-1207 information message, as shown:
Information: The register 'X_reg' will be removed. (OPT-1207)
However, at other times it removes registers without any information message.
Answer:
There are two phases in which Design Compiler removes nonconstant registers: The first phase
is when HDL Compiler reads the design. The second phase is during compilation and optimization
when you run either the compile or compile_ultra command.
1) When HDL Compiler reads the design, it has the ability to remove some registers and not
infer them. The tool does not issue a warning message when this optimization is done.
HDL Compiler removes the following types of registers:
a) Registers that do not have any topological path to downstream logic within the scope of the
design being elaborated (unloaded registers).
b) Registers whose visibility is being blocked by a constant downstream (registers driving
redundant logic).
HDL Compiler controls this optimization with the hdlin_preserve_sequential variable. The default
is none. You must set this variable to all to infer all registers as described in the RTL.
In Example #0, HDL Compiler removes register "A" because it does not have any topological
path to downstream logic.
--------Example #0-------------
module test(a,b,c,clk,out);
input a,b,c,clk;
output out;
reg A,B,C;
always @ (posedge clk)
begin
A <= a;
B <= b;
C <= c;
end
assign out = B & C;
endmodule
------------------------------
HDL Compiler only looks for unloaded registers within the scope of the design being elaborated
or built internally. Therefore, HDL Compiler cannot remove any registers that are unloaded at a
higher level of hierarchy (see Example #1).
In addition, HDL Compiler cannot remove any registers that become unloaded after constant propagation
from surrounding blocks.
In Example #1, we know that register "A" is unloaded because it does not have a topological path to
downstream logic. HDL Compiler does not remove this register because register "A" is unloaded only
from the scope of the top level. You cannot consider the top level alone. In this case, the sublevel
register "A" is not unloaded because it is driving the subblock "a" input.
--------Example #1-------------
module test(a,b,c,clk,out);
input a,b,c,clk;
output out;
reg A,B,C;
always @ (posedge clk)
begin
A <= a;
B <= b;
C <= c;
end
sub U1(.a(A),.b(B),.c(C),.out(out));
endmodule
module sub(a,b,c,out);
input a,b,c;
output out;
assign out = b & c;
endmodule
------------------------------
2) During compilation and optimization when you run either the compile or compile_ultra command,
Design Compiler can remove most of the unloaded and redundant registers. It removes the following
registers and issues an OPT-1207 warning message:
a) Registers that do not have a topological path to downstream logic (unloaded registers).
b) Registers whose visibility is blocked by a constant from upstream or downstream logic
(registers driving redundant logic).
c) Registers that do not control any downstream logic even though they have a topological path
(registers driving redundant logic).
This optimization is controlled by the compile_delete_unloaded_sequential_cells variable. The
default is true. You must set this variable to false to stop the optimization. Unlike HDL Compiler,
Design Compiler looks at the overall design and generally identifies more registers as unloaded or
redundant and removes them when you run the compile or compile_ultra command. In Example #1,
register "A" will be removed during compilation.
The following sections describe unloaded registers and registers that drive redundant logic and
provide examples for each.
Unloaded Registers:
For Design Compiler, an unloaded register is a register that does not have a topological path to
downstream logic. In other words, the register does not drive any loads and is left "unloaded."
Example #2 shows that register "A" is unloaded because it does not have a topological path to
downstream logic.
----------Example #2 ----------
module test(a,b,c,clk,out);
input a,b,c,clk;
output out;
reg A,B,C;
always @ (posedge clk)
begin
A <= a;
B <= b;
C <= c;
end
assign out = B & C;
endmodule
------------------------------
Registers Driving Redundant Logic - Blocked by a Constant:
A redundant register is a register that has a topological path to downstream logic, but the
register does not impact the functionality of the design at its primary output. The first
possible reason for this is that the register's visibility for downstream logic is being
blocked by a constant from upstream or downstream logic.
For example, see Example #3:
------------Example #3---------
module test(a,b,c,clk,out);
input a,b,c,clk;
output out;
reg A,B,C;
always @ (posedge clk)
begin
A <= a;
B <= b;
C <= 1'b0;
end
assign out = C? B : A;
endmodule
------------------------------
In Example #3, the visibility of register "B" to downstream logic is being blocked by a constant
emerging from register "C" and propagating to the select line of a downstream MUX. Even though it
has a topological path for downstream logic, it does not impact the functionality of the overall
design at its primary output. Therefore, Design Compiler can safely remove register "B" and issue
an OPT-1207 information message during the compile or compile_ultra command run.
Registers Driving Redundant Logic - Truly Redundant:
Again, a redundant register is a register that has a topological path to downstream logic but
the register does not impact the functionality of the design at its primary output.
The second possible reason for this is that the combinational logic that the register is
driving is actually redundant. In other words, the register is not controlling any unique
downstream logic. See Example #4 and Example #5:
---------Example #4------------
module test(a,b,c,clk,out);
input a,b,c,clk;
output out;
reg A,B,C;
always @ (posedge clk)
begin
A <= a;
B <= b;
C <= c;
end
assign out = A & ( A | B | C);
endmodule
------------------------------
In Example #4, the register "B" and "C" are not controlling the primary output "out" and can safely
be removed. This is because if you analyze this design, you can infer:
1) If A=0, the primary output out=0.
2) If A=1, the primary output out=1.
The compile and compile_ultra logs show an OPT-1207 information message for register C_reg and B_reg
as shown, confirming that the registers are redundant:
Information: The register 'C_reg' will be removed. (OPT-1207)
Information: The register 'B_reg' will be removed. (OPT-1207)
---------Example #5------------
module test(a,b,c,clk,out);
input a,b,c,clk;
output [2:0] out;
reg A,B,C;
reg [2:0] out;
always @ (posedge clk)
begin
A <= a;
B <= b;
C <= c;
end
always @ (posedge clk)
begin
if(A)
begin
out <= out + 2;
end
else if(B)
begin
out <= out + 3;
if(C)
begin
out <= out + 1;
end
end
else
begin
out <= 'bx;
end
end
endmodule
------------------------------
Example #5 is more complicated and not as straightforward. There are three selectors driving the
output register "out":
1) Selector #1: Register "C" is the select signal. It will either add 1 to the "out" output or add
a value of 3 to "out" depending on whether "C" is 0 or 1.
2) Selector #2: Register "B" is the select signal. It will either select the output of Selector #1
or assign a dont_care to the output.
3) Selector #3: Register "A" is the select signal. It will either add a value of 2 to "out" or select
the output of Selector #2.
In this case, register "B" will be unloaded if Design Compiler chooses to map the dont_care to the
input of Selector #2 to make that selector redundant. In other words, if X (dont_care) in Selector #2
is mapped to the output of Selector #1, there is no need for Selector #2; it can be optimized away.
Depending on the optimization performed by Design Compiler, the register could become unloaded.
|
|