Closed mole99 closed 1 year ago
Hi @d-m-bailey, I have now tried the following:
\
in FP_PDN_MACRO_HOOKS
"FP_PDN_MACRO_HOOKS": [
"\\memory[0].sram vccd1 vssd1 vccd1 vssd1,",
"\\memory[1].sram vccd1 vssd1 vccd1 vssd1,",
"\\memory[2].sram vccd1 vssd1 vccd1 vssd1,",
"\\memory[3].sram vccd1 vssd1 vccd1 vssd1,",
"sram vccd1 vssd1 vccd1 vssd1"
],
Thanks for the tip with runs/tag/config.tcl
, that seems to be correct now at least:
set ::env(FP_PDN_MACRO_HOOKS) {\memory[0].sram vccd1 vssd1 vccd1 vssd1, \memory[1].sram vccd1 vssd1 vccd1 vssd1, \memory[2].sram vccd1 vssd1 vccd1 vssd1, \memory[3].sram vccd1 vssd1 vccd1 vssd1, sram vccd1 vssd1 vccd1 vssd1}
But the actual issue still persists, the SRAM macros instantiated inside the generate
do not have any power ports in the powered verilog (tmp/signoff/25-user_project_wrapper.pnl.v
) and thus are not connected to power.
For example one of the SRAMs with the generate
keyword:
sky130_sram_2kbyte_1rw1r_32x512_8 \memory[2].sram (.csb0(la_data_in[0]),
.csb1(la_data_in[47]),
.web0(la_data_in[1]),
.clk0(wb_clk_i),
.clk1(wb_clk_i),
.addr0({la_data_in[14],
la_data_in[13],
la_data_in[12],
la_data_in[11],
...
The SRAM instantiated in the normal way, on the other hand, has the power ports as expected:
sky130_sram_2kbyte_1rw1r_32x512_8 sram (.csb0(la_data_in[0]),
.csb1(la_data_in[47]),
.web0(la_data_in[1]),
.clk0(wb_clk_i),
.clk1(wb_clk_i),
.vccd1(vccd1),
.vssd1(vssd1),
.addr0({la_data_in[14],
la_data_in[13],
la_data_in[12],
la_data_in[11],
la_data_in[10],
...
The interesting thing is your manual instantiation uses the same preprocessor guard…
If I had to guess, this is probably the Verilog standard being the Verilog standard or a Yosys bug. Probably the former.
Hi @donn, yes exactly. The only difference is the generate
around it, that's why I expected it to just work.
I can't tell you by heart what the Verilog standard says, but it would be a very strange limitation.
I actually prototyped my design on an FPGA with Yosys for synthesis and there (if USE_POWER_PINS
was defined) it would connect the ports even inside the generate
statement.
I quickly created this example design, which also works as expected.
`define USE_POWER_PINS
module design (
`ifdef USE_POWER_PINS
inout vccd1, // User area 1 1.8V supply
inout vssd1, // User area 1 digital ground
`endif
input in,
output out
);
assign out = !in;
endmodule
module test(
input in
);
design design_manual(
`ifdef USE_POWER_PINS
.vccd1(vccd1), // User area 1 1.8V power
.vssd1(vssd1), // User area 1 digital ground
`endif
.in(in),
.out()
);
parameter NUM_INSTANCES = 4;
generate
genvar i;
for (i = 0; i < NUM_INSTANCES; i++) begin : gen
design design(
`ifdef USE_POWER_PINS
.vccd1(vccd1), // User area 1 1.8V power
.vssd1(vssd1), // User area 1 digital ground
`endif
.in(in),
.out()
);
end
endgenerate
endmodule
The command yosys -p 'read_verilog test.v; show test'
gives me this image with all ports connected:
The command yosys -p 'read_verilog test.v; write_verilog out.v'
gives me the following verilog code:
/* Generated by Yosys 0.23 (git sha1 7ce5011c24b) */
(* cells_not_processed = 1 *)
(* src = "test.v:3.1-15.10" *)
module \design (vccd1, vssd1, in, out);
(* src = "test.v:13.18-13.21" *)
wire _0_;
(* src = "test.v:9.11-9.13" *)
input in;
wire in;
(* src = "test.v:10.12-10.15" *)
output out;
wire out;
(* src = "test.v:5.11-5.16" *)
inout vccd1;
wire vccd1;
(* src = "test.v:6.11-6.16" *)
inout vssd1;
wire vssd1;
assign _0_ = ! (* src = "test.v:13.18-13.21" *) in;
assign out = _0_;
endmodule
(* cells_not_processed = 1 *)
(* src = "test.v:17.1-49.10" *)
module test(in);
(* src = "test.v:18.11-18.13" *)
input in;
wire in;
(* src = "test.v:23.16-23.21" *)
wire vccd1;
(* src = "test.v:24.16-24.21" *)
wire vssd1;
(* module_not_derived = 32'd1 *)
(* src = "test.v:21.12-28.6" *)
\design design_manual (
.in(in),
.vccd1(vccd1),
.vssd1(vssd1)
);
(* module_not_derived = 32'd1 *)
(* src = "test.v:37.20-44.14" *)
\design \gen[0].design (
.in(in),
.vccd1(vccd1),
.vssd1(vssd1)
);
(* module_not_derived = 32'd1 *)
(* src = "test.v:37.20-44.14" *)
\design \gen[1].design (
.in(in),
.vccd1(vccd1),
.vssd1(vssd1)
);
(* module_not_derived = 32'd1 *)
(* src = "test.v:37.20-44.14" *)
\design \gen[2].design (
.in(in),
.vccd1(vccd1),
.vssd1(vssd1)
);
(* module_not_derived = 32'd1 *)
(* src = "test.v:37.20-44.14" *)
\design \gen[3].design (
.in(in),
.vccd1(vccd1),
.vssd1(vssd1)
);
endmodule
Again, all ports are connected. The question is, does OpenLane use Yosys in a different configuration to generate the powered verilog? Or does it use a completely different parser to create the powered verilog which has these limitations?
Maybe someone has an idea what it could be. Thanks!
There are two issues here. The first is that if you look at logs/floorplan/6-pdn.log
you will notice the following:
[WARNING PDN-0189] Supply pin vccd1 of instance memory\[0\].sram is not connected to any net.
[WARNING PDN-0189] Supply pin vssd1 of instance memory\[0\].sram is not connected to any net.
[WARNING PDN-0189] Supply pin vccd1 of instance memory\[1\].sram is not connected to any net.
[WARNING PDN-0189] Supply pin vssd1 of instance memory\[1\].sram is not connected to any net.
[WARNING PDN-0189] Supply pin vccd1 of instance memory\[2\].sram is not connected to any net.
[WARNING PDN-0189] Supply pin vssd1 of instance memory\[2\].sram is not connected to any net.
[WARNING PDN-0189] Supply pin vccd1 of instance memory\[3\].sram is not connected to any net.
[WARNING PDN-0189] Supply pin vssd1 of instance memory\[3\].sram is not connected to any net.
FP_PDN_MACRO_HOOKS
uses add_global_connection
from openroad. The macro name that is passed to add_global_connection
is a regex. Since instance names are all similar to memory\[3\].sram
, the regex that matches such a name is memory\\\[3\\\]\.sram
and in order to have the regex in the string FP_PDN_MACRO_HOOKS
you need to escape the backslashes making the string look like this "memory\\\\\\[3\\\\\\]\\.sram
. Another way of defining the variable can be memory.*sram vccd1 vssd1 vccd1 vssd1
. But yeah this is a bit tricky. If you set the correct definitions for macro hooks you will find that the final netlist have the power connections you are looking for.
The second issue is that the power connections are missing from the netlist when openroad failed to establish that connection (due to a bad configuration) . I am still looking into that, but initially this looks like a bug.
Thanks for taking a look at it! Also, that's a lot of backslashes, but I will take what I get :smile:
Is this fixed by #1622, @kareefardi?
Sorry it took so long. I tested my design with the latest OpenLane version and now it works!
Thanks, from my side this issue can be closed.
Description
When instantiating multiple macros via the Verilog
generate
statement the power connections are lost somewhere in the flow and thus the macros are not connected to power.I had a look at the resulting file
tmp/signoff/25-user_project_wrapper.pnl.v
. The macro I had instantiated normally is connected tovccd1
/vssd1
, the other four instances via thegenerate
statement are not connected tovccd1
/vssd1
.Example code snippet:
Expected Behavior
The macros should be connected to power.
Environment report
Reproduction material
No reproducible was packaged because the flow did not fail.
I created a repository, ol-generate-bug, based on
caravel_user_project
to easily reproduce the issue. Please note that I installedsky130A
next to the project folder underdependencies/pdks
, so that the sram can be found.After
OPENLANE_ROOT
,PDK_ROOT
andPDK
are exported, you can run the flow viamake user_project_wrapper
.Relevant log output