The-OpenROAD-Project / OpenLane

OpenLane is an automated RTL to GDSII flow based on several components including OpenROAD, Yosys, Magic, Netgen and custom methodology scripts for design exploration and optimization.
https://openlane.readthedocs.io/
Apache License 2.0
1.3k stars 369 forks source link

Verilog `generate` does not preserve power connections #1600

Closed mole99 closed 1 year ago

mole99 commented 1 year ago

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 to vccd1/vssd1, the other four instances via the generate statement are not connected to vccd1/vssd1.

Example code snippet:

generate
    genvar i;

    for (i = 0; i < NUM_INSTANCES; i++) begin : memory

        sky130_sram_2kbyte_1rw1r_32x512_8 sram (
            `ifdef USE_POWER_PINS
            .vccd1(vccd1),  // User area 1 1.8V power
            .vssd1(vssd1),  // User area 1 digital ground
            `endif
            // Port 0: RW
            .clk0  (wb_clk_i),
            .csb0  (la_data_in[0]),
            .web0  (la_data_in[1]),
            .wmask0(la_data_in[5:2]),
            .addr0 (la_data_in[14:6]),
            .din0  (la_data_in[46:15]),
            .dout0 (select_dout0[i*DATA_WIDTH+:DATA_WIDTH]),
            // Port 1: R
            .clk1 (wb_clk_i),
            .csb1 (la_data_in[47]),
            .addr1(la_data_in[79:48]),
            .dout1(select_dout1[i*DATA_WIDTH+:DATA_WIDTH])
        );

    end
endgenerate

Expected Behavior

The macros should be connected to power.

Environment report

$ python3 ./env.py issue-survey
Kernel: Linux v6.0.0-6-amd64
Distribution: debian 
Python: v3.10.9 (OK)
Container Engine: docker v20.10.21+dfsg1 (OK)
OpenLane Git Version: cb59d1f84deb5cedbb5b0a3e3f3b4129a967c988
pip: INSTALLED
python-venv: INSTALLED
---
PDK Version Verification Status: MISMATCH
The version of open_pdks used in building the PDK does not match the version OpenLane was tested on (installed: 0059588eebfc704681dc2368bd1d33d96281d10f, tested: 3af133706e554a740cfe60f21e773d9eaa41838c)
This may introduce some issues. You may want to re-install the PDK by invoking `make pdk`.
---
Git Log (Last 3 Commits)

cb59d1f 2022-11-18T18:42:38+02:00 fix return values in `equally_spaced_sequence` (#1503) - Kareem Farid -  (grafted, HEAD, tag: 2022.11.19)
---
Git Remotes

origin  https://github.com/The-OpenROAD-Project/OpenLane (fetch)
origin  https://github.com/The-OpenROAD-Project/OpenLane (push)

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 installed sky130A next to the project folder under dependencies/pdks, so that the sram can be found.

After OPENLANE_ROOT, PDK_ROOT and PDK are exported, you can run the flow via make user_project_wrapper.

Relevant log output

$ make user_project_wrapper 
make -C openlane user_project_wrapper
make[1]: Verzeichnis „/home/leo/Dokumente/workspace_test/caravel_user_project/openlane“ wird betreten
# user_project_wrapper
mkdir -p ./user_project_wrapper/runs/23_01_01_12_33 
rm -rf ./user_project_wrapper/runs/user_project_wrapper
ln -s $(realpath ./user_project_wrapper/runs/23_01_01_12_33) ./user_project_wrapper/runs/user_project_wrapper
docker run -it -v $(realpath /home/leo/Dokumente/workspace_test/caravel_user_project/..):$(realpath /home/leo/Dokumente/workspace_test/caravel_user_project/..) -v /home/leo/Dokumente/workspace_test/dependencies/pdks:/home/leo/Dokumente/workspace_test/dependencies/pdks -v /home/leo/Dokumente/workspace_test/caravel_user_project/caravel:/home/leo/Dokumente/workspace_test/caravel_user_project/caravel -v /home/leo/Dokumente/workspace_test/dependencies/openlane_src:/openlane -v /home/leo/Dokumente/workspace_test/caravel_user_project/mgmt_core_wrapper:/home/leo/Dokumente/workspace_test/caravel_user_project/mgmt_core_wrapper -e PDK_ROOT=/home/leo/Dokumente/workspace_test/dependencies/pdks -e PDK=sky130A -e MISMATCHES_OK=1 -e CARAVEL_ROOT=/home/leo/Dokumente/workspace_test/caravel_user_project/caravel -e OPENLANE_RUN_TAG=23_01_01_12_33 -e MCW_ROOT=/home/leo/Dokumente/workspace_test/caravel_user_project/mgmt_core_wrapper -u 1000:1000 \
    efabless/openlane:2022.11.19 sh -c "flow.tcl -design $(realpath ./user_project_wrapper) -save_path $(realpath ..) -save -tag 23_01_01_12_33 -overwrite -ignore_mismatches"
OpenLane cb59d1f84deb5cedbb5b0a3e3f3b4129a967c988
All rights reserved. (c) 2020-2022 Efabless Corporation and contributors.
Available under the Apache License, version 2.0. See the LICENSE file for more details.

[WARNING]: OpenLane may not function properly: The version of open_pdks used in building the PDK does not match the version OpenLane was tested on (installed: 0059588eebfc704681dc2368bd1d33d96281d10f, tested: 3af133706e554a740cfe60f21e773d9eaa41838c)
This may introduce some issues. You may want to re-install the PDK by invoking `make pdk`.
[INFO]: Using configuration in '../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/config.json'...
[INFO]: PDK Root: /home/leo/Dokumente/workspace_test/dependencies/pdks
[INFO]: Process Design Kit: sky130A
[INFO]: Standard Cell Library: sky130_fd_sc_hd
[INFO]: Optimization Standard Cell Library: sky130_fd_sc_hd
[INFO]: Run Directory: /home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33
[INFO]: Preparing LEF files for the nom corner...
[INFO]: Preparing LEF files for the min corner...
[INFO]: Preparing LEF files for the max corner...
[STEP 1]
[INFO]: Running Synthesis (log: ../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/logs/synthesis/1-synthesis.log)...
[STEP 2]
[INFO]: Running Single-Corner Static Timing Analysis (log: ../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/logs/synthesis/2-sta.log)...
[INFO]: Creating a netlist with power/ground pins.
[STEP 3]
[INFO]: Running Initial Floorplanning (log: ../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/logs/floorplan/3-initial_fp.log)...
[INFO]: Floorplanned with width 2908.58 and height 3497.92.
[STEP 4]
[INFO]: Running IO Placement...
[INFO]: Applying DEF template...
[STEP 5]
[INFO]: Performing Manual Macro Placement (log: ../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/logs/placement/5-macro_placement.log)...
[INFO]: Power planning with power {vccd1 vccd2 vdda1 vdda2} and ground {vssd1 vssd2 vssa1 vssa2}...
[STEP 6]
[INFO]: Generating PDN (log: ../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/logs/floorplan/6-pdn.log)...
[STEP 7]
[INFO]: Performing Random Global Placement (log: ../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/logs/placement/7-global.log)...
[INFO]: Skipping Placement Resizer Design Optimizations.
[STEP 8]
[INFO]: Running Detailed Placement (log: ../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/logs/placement/8-detailed.log)...
[INFO]: Skipping Placement Resizer Timing Optimizations.
[STEP 9]
[INFO]: Running Global Routing Resizer Timing Optimizations (log: ../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/logs/routing/9-resizer.log)...
[STEP 10]
[INFO]: Running Detailed Placement (log: ../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/logs/routing/10-diode_legalization.log)...
[STEP 11]
[INFO]: Running Global Routing (log: ../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/logs/routing/11-global.log)...
[STEP 12]
[INFO]: Writing Verilog (log: ../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/logs/routing/11-global_write_netlist.log)...
[STEP 13]
[INFO]: Running Detailed Routing (log: ../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/logs/routing/13-detailed.log)...
[INFO]: No DRC violations after detailed routing.
[STEP 14]
[INFO]: Checking Wire Lengths (log: ../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/logs/routing/14-wire_lengths.log)...
[STEP 15]
[INFO]: Running SPEF Extraction at the min process corner (log: ../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/logs/signoff/15-parasitics_extraction.min.log)...
[STEP 16]
[INFO]: Running Multi-Corner Static Timing Analysis at the min process corner (log: ../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/logs/signoff/16-rcx_mcsta.min.log)...
[STEP 17]
[INFO]: Running SPEF Extraction at the max process corner (log: ../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/logs/signoff/17-parasitics_extraction.max.log)...
[STEP 18]
[INFO]: Running Multi-Corner Static Timing Analysis at the max process corner (log: ../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/logs/signoff/18-rcx_mcsta.max.log)...
[STEP 19]
[INFO]: Running SPEF Extraction at the nom process corner (log: ../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/logs/signoff/19-parasitics_extraction.nom.log)...
[STEP 20]
[INFO]: Running Multi-Corner Static Timing Analysis at the nom process corner (log: ../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/logs/signoff/20-rcx_mcsta.nom.log)...
[STEP 21]
[INFO]: Running Single-Corner Static Timing Analysis at the nom process corner (log: ../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/logs/signoff/21-rcx_sta.log)...
[STEP 22]
[INFO]: Creating IR Drop Report (log: ../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/logs/signoff/22-irdrop.log)...
[STEP 23]
[INFO]: Running Magic to generate various views...
[INFO]: Streaming out GDSII with Magic (log: ../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/logs/signoff/23-gdsii.log)...
[INFO]: Generating MAGLEF views...
[STEP 24]
[INFO]: Streaming out GDSII with KLayout (log: ../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/logs/signoff/24-gdsii-klayout.log)...
[STEP 25]
[INFO]: Running Magic Spice Export from LEF (log: ../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/logs/signoff/25-spice.log)...
[STEP 26]
[INFO]: Writing Powered Verilog (logs: ../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/logs/signoff/26-write_powered_def.log, ../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/logs/signoff/26-write_powered_verilog.log)...
[STEP 27]
[INFO]: Writing Verilog (log: ../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/logs/signoff/26-write_powered_verilog.log)...
[STEP 28]
[INFO]: Running LVS (log: ../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/logs/signoff/28-lvs.lef.log)...
[STEP 29]
[INFO]: Running OpenROAD Antenna Rule Checker (log: ../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/logs/signoff/29-antenna.log)...
[INFO]: Saving current set of views in '../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/results/final'...
[INFO]: Saving current set of views in '../home/leo/Dokumente/workspace_test/caravel_user_project'...
[INFO]: Saving runtime environment...
[INFO]: Generating final set of reports...
[INFO]: Created manufacturability report at '../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/reports/manufacturability.rpt'.
[INFO]: Created metrics report at '../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/reports/metrics.csv'.
[WARNING]: There are max slew violations in the design at the typical corner. Please refer to '../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/reports/signoff/21-rcx_sta.slew.rpt'.
[WARNING]: There are max capacitance violations in the design at the typical corner. Please refer to '../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/reports/signoff/21-rcx_sta.slew.rpt'.
[INFO]: There are no hold violations in the design at the typical corner.
[INFO]: There are no setup violations in the design at the typical corner.
[SUCCESS]: Flow complete.
[INFO]: Note that the following warnings have been generated:
[WARNING]: There are max slew violations in the design at the typical corner. Please refer to '../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/reports/signoff/21-rcx_sta.slew.rpt'.
[WARNING]: There are max capacitance violations in the design at the typical corner. Please refer to '../home/leo/Dokumente/workspace_test/caravel_user_project/openlane/user_project_wrapper/runs/23_01_01_12_33/reports/signoff/21-rcx_sta.slew.rpt'.
mole99 commented 1 year ago

Hi @d-m-bailey, I have now tried the following:

"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],
    ...
donn commented 1 year ago

The interesting thing is your manual instantiation uses the same preprocessor guard…

https://github.com/mole99/ol-generate-bug/blob/20efc83d3d1297fa28ce877f647b3dc86975d221/verilog/rtl/user_project_wrapper.v#L119

If I had to guess, this is probably the Verilog standard being the Verilog standard or a Yosys bug. Probably the former.

mole99 commented 1 year ago

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:

Bildschirmfoto vom 2023-01-10 10-58-53

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!

kareefardi commented 1 year ago

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.

mole99 commented 1 year ago

Thanks for taking a look at it! Also, that's a lot of backslashes, but I will take what I get :smile:

donn commented 1 year ago

Is this fixed by #1622, @kareefardi?

mole99 commented 1 year ago

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.