YosysHQ / yosys

Yosys Open SYnthesis Suite
https://yosyshq.net/yosys/
ISC License
3.31k stars 860 forks source link

Broken OBUFT inference in submodules #1737

Open tmichalak opened 4 years ago

tmichalak commented 4 years ago

Steps to reproduce the issue

Testcase: obuft_inference_bug.zip make top.edif to generate the invalid EDIF.

Expected behavior

The final EDIF should contain OBUFT primitives instead of TBUF.

Actual behavior

When there is assign IO_UTX = (cio_uart_tx_en_d2p ? cio_uart_tx_d2p : 1'bz); in the top module the OBUFT is correctly inferred. However if I have the statement inside a submodule I end up with _TBUF_ cells which are obviously not recognized in Vivado.

=== design hierarchy ===

   top                               1
     padctl                          1

   Number of wires:                 12
   Number of wire bits:             12
   Number of public wires:          10
   Number of public wire bits:      10
   Number of memories:               0
   Number of memory bits:            0
   Number of processes:              0
   Number of cells:                  3
     $_TBUF_                         1
     IBUF                            1
rw1nkler commented 3 years ago

Recently, I encountered the same error and created some tests to investigate the problem. It turned out that the OBUFT inference in submodules works in some cases. The tests below use the synth_xilinx command for synthesis (I split the synth_xilinx command into few parts, to obtain the diagrams before the iopadmap call)

Test Case 1: OBUFT inference in place of $_TBUF_ in a top-level module:

 - before `iopadmap`:
   ![tbuf_case1_before_iopadmap](https://user-images.githubusercontent.com/52699314/94288200-70ec6680-ff57-11ea-8620-ac3b2a529821.png)

- after `iopadmap`:
  ![tbuf_case1_after_iopadmap](https://user-images.githubusercontent.com/52699314/94288036-41d5f500-ff57-11ea-8c7e-521aed2bdd7e.png)

- comment:
  This case is correctly resolved

### Test Case 2: OBUFT inference in place of `$_TBUF_` in a submodule:

- sources:

module top ( input wire sw_oe, input wire btn_iout, output wire led );

pad_wrapper wrap1 (sw_oe, btn_iout, led);

endmodule

module pad_wrapper ( input wire i_oe, input wire i_out, output wire o_out );

assign o_out = i_oe ? i_out : 1'bz;

endmodule

- before `iopadmap`:
  ![tbuf_case2_before_iopadmap](https://user-images.githubusercontent.com/52699314/94288451-b5780200-ff57-11ea-8524-fcd134c93619.png)

- after `iopadmap`:
  ![tbuf_case2_after_iopadmap](https://user-images.githubusercontent.com/52699314/94288475-ba3cb600-ff57-11ea-9558-3b76a7cd0567.png)

- comment:
  This case is correctly resolved

### Test Case 3: Mixed case

- sources:

module top ( input wire [1:0] sw_en, input wire [1:0] btn_led, output wire [1:0] leds );

assign leds[0] = sw_en[0] ? btn_led[0] : 1'bz;
pad_wrapper wrap1 (sw_en[1], btn_led[1], leds[1]);

endmodule

module pad_wrapper ( input wire i_oe, input wire i_out, output wire o_out );

assign o_out = i_oe ? i_out : 1'bz;

endmodule



- before `iopadmap`:
  ![tbuf_case3_before_iopadmap](https://user-images.githubusercontent.com/52699314/94288681-fa9c3400-ff57-11ea-9d33-fbf91e766d69.png)
- after `iopadmap`:
   ![tbuf_case3_after_iopadmap](https://user-images.githubusercontent.com/52699314/94288700-012aab80-ff58-11ea-9956-68fd288f074a.png)

- comment:
  It seems that the mixed case of the two previous scenarios causes problems. I noticed that the top-level module output is not directly connected to the `$_TBUF_` output in the last case. 
Maybe this is a source of the problems.

Here are all the tests with synthesis scripts:
[yosys_obuft.zip](https://github.com/YosysHQ/yosys/files/5283918/yosys_obuft.zip)

@mwkmwkmwk Do you have any thoughts, how this issue might be resolved?