efabless / openlane2

The next generation of OpenLane, rewritten from scratch with a modular architecture
https://openlane2.readthedocs.io/
Apache License 2.0
175 stars 33 forks source link

Generating tristate buffers #123

Open Ashwin-Rajesh opened 1 year ago

Ashwin-Rajesh commented 1 year ago

How can tristate buffers be synthesized for the sky130 PDK? Even though yosys has only limited support for tristate logic, it is capable of synthesizing tristate buffers in the tribuf pass

I believe this is supported in openlane as can be seen in the yosys synthesize.tcl script Line no.241

# Infer tri-state buffers.
set tbuf_map false
if { [info exists ::env(TRISTATE_BUFFER_MAP)] } {
    set tbuf_map true
    tribuf
}

However, on synthesizing a verilog module like

module tristate (
    input wire in,
    input wire en,
    inout out 
);

    assign out = en ? in : 1'bz;

endmodule

Using the config file below

{
    "meta": {
        "version": 2,
        "flow": [
            "Yosys.Synthesis",
            "Misc.LoadBaseSDC",
            "OpenROAD.Floorplan",
            "OpenROAD.TapEndcapInsertion",
            "OpenROAD.GeneratePDN",
            "OpenROAD.IOPlacement",
            "OpenROAD.GlobalPlacement",
            "OpenROAD.RepairDesign",
            "OpenROAD.DetailedPlacement",
            "OpenROAD.GlobalRouting",
            "OpenROAD.DetailedRouting",
            "OpenROAD.FillInsertion",
            "Magic.StreamOut",
            "Magic.DRC",
            "Magic.SpiceExtraction",
            "Netgen.LVS"
        ]
    },
    "DESIGN_NAME": "tristate",
    "VERILOG_FILES": "dir::src/*.v",
    "CLOCK_PORT": null,
    "FP_SIZING": "absolute",
    "DIE_AREA": "0 0 25 50",
    "PL_TARGET_DENSITY": 0.5,
    "FP_PDN_VPITCH": 25,
    "FP_PDN_HPITCH": 25,
    "FP_PDN_VOFFSET": 5,
    "FP_PDN_HOFFSET": 5
}

The final output uses simple buffers, instead of a tristate buffer and ignores the en input.

Refer tristate.nl.v

module tristate (en,
    in,
    out);
 input en;
 input in;
 inout out;

 wire net1;

 sky130_fd_sc_hd__clkbuf_4 _0_ (.A(net1),
    .X(out));
 sky130_fd_sc_hd__decap_3 PHY_0 ();
 sky130_fd_sc_hd__decap_3 PHY_1 ();
 sky130_fd_sc_hd__decap_3 PHY_2 ();
 sky130_fd_sc_hd__decap_3 PHY_3 ();
 sky130_fd_sc_hd__decap_3 PHY_4 ();
 sky130_fd_sc_hd__decap_3 PHY_5 ();
 sky130_fd_sc_hd__decap_3 PHY_6 ();
 sky130_fd_sc_hd__decap_3 PHY_7 ();
 sky130_fd_sc_hd__decap_3 PHY_8 ();
 sky130_fd_sc_hd__decap_3 PHY_9 ();
 sky130_fd_sc_hd__decap_3 PHY_10 ();
 sky130_fd_sc_hd__decap_3 PHY_11 ();
 sky130_fd_sc_hd__decap_3 PHY_12 ();
 sky130_fd_sc_hd__decap_3 PHY_13 ();
 sky130_fd_sc_hd__decap_3 PHY_14 ();
 sky130_fd_sc_hd__decap_3 PHY_15 ();
 sky130_fd_sc_hd__decap_3 PHY_16 ();
 sky130_fd_sc_hd__decap_3 PHY_17 ();
 sky130_fd_sc_hd__decap_3 PHY_18 ();
 sky130_fd_sc_hd__decap_3 PHY_19 ();
 sky130_fd_sc_hd__clkbuf_1 input1 (.A(in),
    .X(net1));
 sky130_ef_sc_hd__decap_12 FILLER_0_3 ();
 sky130_ef_sc_hd__decap_12 FILLER_0_15 ();
 sky130_ef_sc_hd__decap_12 FILLER_1_3 ();
 sky130_ef_sc_hd__decap_12 FILLER_1_15 ();
 sky130_ef_sc_hd__decap_12 FILLER_2_3 ();
 sky130_ef_sc_hd__decap_12 FILLER_2_15 ();
 sky130_ef_sc_hd__decap_12 FILLER_3_3 ();
 sky130_ef_sc_hd__decap_12 FILLER_3_15 ();
 sky130_ef_sc_hd__decap_12 FILLER_4_3 ();
 sky130_ef_sc_hd__decap_12 FILLER_4_15 ();
 sky130_fd_sc_hd__decap_8 FILLER_5_3 ();
 sky130_fd_sc_hd__decap_8 FILLER_5_17 ();
 sky130_fd_sc_hd__fill_2 FILLER_5_25 ();
 sky130_ef_sc_hd__decap_12 FILLER_6_3 ();
 sky130_ef_sc_hd__decap_12 FILLER_6_15 ();
 sky130_ef_sc_hd__decap_12 FILLER_7_3 ();
 sky130_ef_sc_hd__decap_12 FILLER_7_15 ();
 sky130_ef_sc_hd__decap_12 FILLER_8_3 ();
 sky130_ef_sc_hd__decap_12 FILLER_8_15 ();
 sky130_ef_sc_hd__decap_12 FILLER_9_6 ();
 sky130_fd_sc_hd__decap_8 FILLER_9_18 ();
 sky130_fd_sc_hd__fill_1 FILLER_9_26 ();
endmodule

The output after yosys, in the load_techmap.dot file is as below tristate

How can i generate proper tristate logic? Are there any configuration parameters for this?

mo-hosni commented 5 months ago

Well, we never inferred tri-state buffers in the RTLs using

assign out = en ? in : 1'bz;

we usually specify the std cells in the RTL to avoid this issue such as this for sky130:

sky130_fd_sc_hd__ebufn_4 tri_buf_0 (.TE_B(en_n), .A(in), .Z(out));

I am not sure if the issue was fixed in Yosys or not but I will investigate that.