Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] Riviera-PRO component binding not working between libraries #1073

Open
SzymonHitachi opened this issue Nov 20, 2024 · 27 comments · May be fixed by #1087
Open

[Bug] Riviera-PRO component binding not working between libraries #1073

SzymonHitachi opened this issue Nov 20, 2024 · 27 comments · May be fixed by #1087

Comments

@SzymonHitachi
Copy link

Using tsfpga assume that I have 1 VHDL file myfile.vhd and 1 IP TCL file with mycomponent.

  • During simulation IP file is being compiled in a separate project and by default it ends in xil_defaultlib library
  • VHDL file has a component instantiation of that IP

During the simulation now, In Riviera-PRO, simulator does not bind the generated IP properly to the component:

# ELBREAD: Warning: ELBREAD_0037 myfile.vhd (505): Instance "/mycomponent_inst" of component "mycomponent" not bound.

Solution discussion:
This seems to be easily fixed by updating vunit/sim_if/rivierapro.py -> _create_load_function by adding:

        for library in self._libraries:
            vsim_flags += ["-L", library.name]

which is added in modelsim also.

This however results in significant increase of simulation time (increasing with the amount of tcl IPs) on start of elaboration with warnings for each of the IPs:

# ELBREAD: Warning: Entity "xil_defaultlib.mycomponent" has been compiled after architecture "work.myfile(rtl)" that instantiates and binds this entity at simulation initialization. Recompile the source files in the correct order to perform the binding operation during compilation and simultaneously reduce the time required to initialize the simulation.

Note: Same warning does not show up for modelsim.

What would be the actual good way of solving this issue?

@LarsAsplund
Copy link
Collaborator

Generally speaking we recommend that all third-party IPs are compiled according to the vendor instructions. They are typically encrypted so VUnit can't analyze them for compile order anyway. Even if you can, there is no point for VUnit to spend time analyzing a possible large set of file that rarely change. Once you have the library compiled you can add it to the project with add_external_library. Is that what you do already?

@SzymonHitachi
Copy link
Author

The problem happens due to xil_defaultlib. It seems to be added automatically to the project as its the ip_cores from tsfpga that are compiled there but their dependencies do not seem to be resolved properly. Not sure if there is a way to force xil_defaultlib to be compiled before my project lib.

@SzymonHitachi
Copy link
Author

On further digging it seems that if something is instantiated through component and then compiled in different library, the dependency isn't resolved properly.

@LarsAsplund
Copy link
Collaborator

Since VUnit + TSFPGA is a common approach, I'm sure there is a solution. I've not been working with Xilinx for quite some time but maybe @LukasVik knows what's going on

@SzymonHitachi
Copy link
Author

I did some printing and I see that the order here is like

34 mylib C:\work\fpga_dev\projects\mylib\source\abcd_cdc.vhd
72 xil_defaultlib C:\work\fpga_dev\out\vunit_out\mylib\mylib\vivado_ip_project\vivado_ip_project.gen\sources_1\ip\abcd_cdc_fifo\sim\abcd_cdc_fifo.v

And in the actual abcd_cdc.vhd is just (+ entity)

architecture rtl of abcd_cdc is
    
    component abcd_cdc_fifo
    port (
        rst : in std_logic;
        wr_clk : in std_logic;
        rd_clk : in std_logic;
        din : in std_logic_vector(31 downto 0);
        wr_en : in std_logic;
        rd_en : in std_logic;
        dout : out std_logic_vector(31 downto 0);
        full : out std_logic;
        empty : out std_logic 
    );
    end component;

    signal empty, full : std_logic;

begin
    
cdc_fifo_i : abcd_cdc_fifo
    port map (
        rst     => not source_reset_n,
        -- Ingress
        wr_clk  => source_clk,
        din     => source_data,
        wr_en   => source_valid and source_ready,
        full    => full,
        -- Egress
        rd_clk  => target_clk,
        dout    => target_data,
        rd_en   => target_valid and target_ready,
        empty   => empty
    );

source_ready <= source_reset_n and not full;
target_valid <= target_reset_n and not empty;

end architecture rtl;

@LarsAsplund
Copy link
Collaborator

Since binding happens at elaboration the important thing is that the library has been compiled before the simulation starts. Unfortunately, I haven't used TSFPGA enough to guide you. The tool adds an abstraction layer on-top of VUnit so I think you should validate your setup with that project first.

@LukasVik
Copy link
Contributor

Well I use Xilinx daily but I haven't used IP cores for the last five years. So the knowledge of how to do these things is not really top of mind. But let's see.

@SzymonHitachi Could you share the content of the file C:\work\fpga_dev\out\vunit_out\mylib\mylib\vivado_ip_project\vivado_ip_project.gen\sources_1\ip\abcd_cdc_fifo\sim\abcd_cdc_fifo.v? I'm mainly interested in if the component within that file matches exactly your component declaration in VHDL.

@LukasVik
Copy link
Contributor

Also, if you could add trace printouts of the with_dependency_scan and no_dependency_scan variables here: external/vunit/vunit/vunit/vivado/vivado.py

@SzymonHitachi
Copy link
Author

Since this is a bigger project, I have filtered out all of the unrelated files and kept abcd_cdc related ones only.

sim/abcd_cdc_fifo.v

// (c) Copyright 1986-2022 Xilinx, Inc. All Rights Reserved.
// (c) Copyright 2022-2024 Advanced Micro Devices, Inc. All rights reserved.
// 
// This file contains confidential and proprietary information
// of AMD and is protected under U.S. and international copyright
// and other intellectual property laws.
// 
// DISCLAIMER
// This disclaimer is not a license and does not grant any
// rights to the materials distributed herewith. Except as
// otherwise provided in a valid license issued to you by
// AMD, and to the maximum extent permitted by applicable
// law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
// WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
// AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
// BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
// INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
// (2) AMD shall not be liable (whether in contract or tort,
// including negligence, or under any other theory of
// liability) for any loss or damage of any kind or nature
// related to, arising under or in connection with these
// materials, including for any direct, or any indirect,
// special, incidental, or consequential loss or damage
// (including loss of data, profits, goodwill, or any type of
// loss or damage suffered as a result of any action brought
// by a third party) even if such damage or loss was
// reasonably foreseeable or AMD had been advised of the
// possibility of the same.
// 
// CRITICAL APPLICATIONS
// AMD products are not designed or intended to be fail-
// safe, or for use in any application requiring fail-safe
// performance, such as life-support or safety devices or
// systems, Class III medical devices, nuclear facilities,
// applications related to the deployment of airbags, or any
// other applications that could lead to death, personal
// injury, or severe property or environmental damage
// (individually and collectively, "Critical
// Applications"). Customer assumes the sole risk and
// liability of any use of AMD products in Critical
// Applications, subject only to applicable laws and
// regulations governing limitations on product liability.
// 
// THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
// PART OF THIS FILE AT ALL TIMES.
// 
// DO NOT MODIFY THIS FILE.


// IP VLNV: xilinx.com:ip:fifo_generator:13.2
// IP Revision: 8

`timescale 1ns/1ps

(* DowngradeIPIdentifiedWarnings = "yes" *)
module abcd_cdc_fifo (
  rst,
  wr_clk,
  rd_clk,
  din,
  wr_en,
  rd_en,
  dout,
  full,
  empty
);

input wire rst;
(* X_INTERFACE_PARAMETER = "XIL_INTERFACENAME write_clk, FREQ_HZ 100000000, FREQ_TOLERANCE_HZ 0, PHASE 0.0, INSERT_VIP 0" *)
(* X_INTERFACE_INFO = "xilinx.com:signal:clock:1.0 write_clk CLK" *)
input wire wr_clk;
(* X_INTERFACE_PARAMETER = "XIL_INTERFACENAME read_clk, FREQ_HZ 100000000, FREQ_TOLERANCE_HZ 0, PHASE 0.0, INSERT_VIP 0" *)
(* X_INTERFACE_INFO = "xilinx.com:signal:clock:1.0 read_clk CLK" *)
input wire rd_clk;
(* X_INTERFACE_INFO = "xilinx.com:interface:fifo_write:1.0 FIFO_WRITE WR_DATA" *)
input wire [31 : 0] din;
(* X_INTERFACE_INFO = "xilinx.com:interface:fifo_write:1.0 FIFO_WRITE WR_EN" *)
input wire wr_en;
(* X_INTERFACE_INFO = "xilinx.com:interface:fifo_read:1.0 FIFO_READ RD_EN" *)
input wire rd_en;
(* X_INTERFACE_INFO = "xilinx.com:interface:fifo_read:1.0 FIFO_READ RD_DATA" *)
output wire [31 : 0] dout;
(* X_INTERFACE_INFO = "xilinx.com:interface:fifo_write:1.0 FIFO_WRITE FULL" *)
output wire full;
(* X_INTERFACE_INFO = "xilinx.com:interface:fifo_read:1.0 FIFO_READ EMPTY" *)
output wire empty;

  fifo_generator_v13_2_8 #(
    .C_COMMON_CLOCK(0),
    .C_SELECT_XPM(0),
    .C_COUNT_TYPE(0),
    .C_DATA_COUNT_WIDTH(4),
    .C_DEFAULT_VALUE("BlankString"),
    .C_DIN_WIDTH(32),
    .C_DOUT_RST_VAL("0"),
    .C_DOUT_WIDTH(32),
    .C_ENABLE_RLOCS(0),
    .C_FAMILY("spartan7"),
    .C_FULL_FLAGS_RST_VAL(1),
    .C_HAS_ALMOST_EMPTY(0),
    .C_HAS_ALMOST_FULL(0),
    .C_HAS_BACKUP(0),
    .C_HAS_DATA_COUNT(0),
    .C_HAS_INT_CLK(0),
    .C_HAS_MEMINIT_FILE(0),
    .C_HAS_OVERFLOW(0),
    .C_HAS_RD_DATA_COUNT(0),
    .C_HAS_RD_RST(0),
    .C_HAS_RST(1),
    .C_HAS_SRST(0),
    .C_HAS_UNDERFLOW(0),
    .C_HAS_VALID(0),
    .C_HAS_WR_ACK(0),
    .C_HAS_WR_DATA_COUNT(0),
    .C_HAS_WR_RST(0),
    .C_IMPLEMENTATION_TYPE(2),
    .C_INIT_WR_PNTR_VAL(0),
    .C_MEMORY_TYPE(2),
    .C_MIF_FILE_NAME("BlankString"),
    .C_OPTIMIZATION_MODE(0),
    .C_OVERFLOW_LOW(0),
    .C_PRELOAD_LATENCY(0),
    .C_PRELOAD_REGS(1),
    .C_PRIM_FIFO_TYPE("512x36"),
    .C_PROG_EMPTY_THRESH_ASSERT_VAL(4),
    .C_PROG_EMPTY_THRESH_NEGATE_VAL(5),
    .C_PROG_EMPTY_TYPE(0),
    .C_PROG_FULL_THRESH_ASSERT_VAL(15),
    .C_PROG_FULL_THRESH_NEGATE_VAL(14),
    .C_PROG_FULL_TYPE(0),
    .C_RD_DATA_COUNT_WIDTH(4),
    .C_RD_DEPTH(16),
    .C_RD_FREQ(1),
    .C_RD_PNTR_WIDTH(4),
    .C_UNDERFLOW_LOW(0),
    .C_USE_DOUT_RST(1),
    .C_USE_ECC(0),
    .C_USE_EMBEDDED_REG(0),
    .C_USE_PIPELINE_REG(0),
    .C_POWER_SAVING_MODE(0),
    .C_USE_FIFO16_FLAGS(0),
    .C_USE_FWFT_DATA_COUNT(0),
    .C_VALID_LOW(0),
    .C_WR_ACK_LOW(0),
    .C_WR_DATA_COUNT_WIDTH(4),
    .C_WR_DEPTH(16),
    .C_WR_FREQ(1),
    .C_WR_PNTR_WIDTH(4),
    .C_WR_RESPONSE_LATENCY(1),
    .C_MSGON_VAL(1),
    .C_ENABLE_RST_SYNC(1),
    .C_EN_SAFETY_CKT(0),
    .C_ERROR_INJECTION_TYPE(0),
    .C_SYNCHRONIZER_STAGE(2),
    .C_INTERFACE_TYPE(0),
    .C_AXI_TYPE(1),
    .C_HAS_AXI_WR_CHANNEL(1),
    .C_HAS_AXI_RD_CHANNEL(1),
    .C_HAS_SLAVE_CE(0),
    .C_HAS_MASTER_CE(0),
    .C_ADD_NGC_CONSTRAINT(0),
    .C_USE_COMMON_OVERFLOW(0),
    .C_USE_COMMON_UNDERFLOW(0),
    .C_USE_DEFAULT_SETTINGS(0),
    .C_AXI_ID_WIDTH(1),
    .C_AXI_ADDR_WIDTH(32),
    .C_AXI_DATA_WIDTH(64),
    .C_AXI_LEN_WIDTH(8),
    .C_AXI_LOCK_WIDTH(1),
    .C_HAS_AXI_ID(0),
    .C_HAS_AXI_AWUSER(0),
    .C_HAS_AXI_WUSER(0),
    .C_HAS_AXI_BUSER(0),
    .C_HAS_AXI_ARUSER(0),
    .C_HAS_AXI_RUSER(0),
    .C_AXI_ARUSER_WIDTH(1),
    .C_AXI_AWUSER_WIDTH(1),
    .C_AXI_WUSER_WIDTH(1),
    .C_AXI_BUSER_WIDTH(1),
    .C_AXI_RUSER_WIDTH(1),
    .C_HAS_AXIS_TDATA(1),
    .C_HAS_AXIS_TID(0),
    .C_HAS_AXIS_TDEST(0),
    .C_HAS_AXIS_TUSER(1),
    .C_HAS_AXIS_TREADY(1),
    .C_HAS_AXIS_TLAST(0),
    .C_HAS_AXIS_TSTRB(0),
    .C_HAS_AXIS_TKEEP(0),
    .C_AXIS_TDATA_WIDTH(8),
    .C_AXIS_TID_WIDTH(1),
    .C_AXIS_TDEST_WIDTH(1),
    .C_AXIS_TUSER_WIDTH(4),
    .C_AXIS_TSTRB_WIDTH(1),
    .C_AXIS_TKEEP_WIDTH(1),
    .C_WACH_TYPE(0),
    .C_WDCH_TYPE(0),
    .C_WRCH_TYPE(0),
    .C_RACH_TYPE(0),
    .C_RDCH_TYPE(0),
    .C_AXIS_TYPE(0),
    .C_IMPLEMENTATION_TYPE_WACH(1),
    .C_IMPLEMENTATION_TYPE_WDCH(1),
    .C_IMPLEMENTATION_TYPE_WRCH(1),
    .C_IMPLEMENTATION_TYPE_RACH(1),
    .C_IMPLEMENTATION_TYPE_RDCH(1),
    .C_IMPLEMENTATION_TYPE_AXIS(1),
    .C_APPLICATION_TYPE_WACH(0),
    .C_APPLICATION_TYPE_WDCH(0),
    .C_APPLICATION_TYPE_WRCH(0),
    .C_APPLICATION_TYPE_RACH(0),
    .C_APPLICATION_TYPE_RDCH(0),
    .C_APPLICATION_TYPE_AXIS(0),
    .C_PRIM_FIFO_TYPE_WACH("512x36"),
    .C_PRIM_FIFO_TYPE_WDCH("1kx36"),
    .C_PRIM_FIFO_TYPE_WRCH("512x36"),
    .C_PRIM_FIFO_TYPE_RACH("512x36"),
    .C_PRIM_FIFO_TYPE_RDCH("1kx36"),
    .C_PRIM_FIFO_TYPE_AXIS("1kx18"),
    .C_USE_ECC_WACH(0),
    .C_USE_ECC_WDCH(0),
    .C_USE_ECC_WRCH(0),
    .C_USE_ECC_RACH(0),
    .C_USE_ECC_RDCH(0),
    .C_USE_ECC_AXIS(0),
    .C_ERROR_INJECTION_TYPE_WACH(0),
    .C_ERROR_INJECTION_TYPE_WDCH(0),
    .C_ERROR_INJECTION_TYPE_WRCH(0),
    .C_ERROR_INJECTION_TYPE_RACH(0),
    .C_ERROR_INJECTION_TYPE_RDCH(0),
    .C_ERROR_INJECTION_TYPE_AXIS(0),
    .C_DIN_WIDTH_WACH(1),
    .C_DIN_WIDTH_WDCH(64),
    .C_DIN_WIDTH_WRCH(2),
    .C_DIN_WIDTH_RACH(32),
    .C_DIN_WIDTH_RDCH(64),
    .C_DIN_WIDTH_AXIS(1),
    .C_WR_DEPTH_WACH(16),
    .C_WR_DEPTH_WDCH(1024),
    .C_WR_DEPTH_WRCH(16),
    .C_WR_DEPTH_RACH(16),
    .C_WR_DEPTH_RDCH(1024),
    .C_WR_DEPTH_AXIS(1024),
    .C_WR_PNTR_WIDTH_WACH(4),
    .C_WR_PNTR_WIDTH_WDCH(10),
    .C_WR_PNTR_WIDTH_WRCH(4),
    .C_WR_PNTR_WIDTH_RACH(4),
    .C_WR_PNTR_WIDTH_RDCH(10),
    .C_WR_PNTR_WIDTH_AXIS(10),
    .C_HAS_DATA_COUNTS_WACH(0),
    .C_HAS_DATA_COUNTS_WDCH(0),
    .C_HAS_DATA_COUNTS_WRCH(0),
    .C_HAS_DATA_COUNTS_RACH(0),
    .C_HAS_DATA_COUNTS_RDCH(0),
    .C_HAS_DATA_COUNTS_AXIS(0),
    .C_HAS_PROG_FLAGS_WACH(0),
    .C_HAS_PROG_FLAGS_WDCH(0),
    .C_HAS_PROG_FLAGS_WRCH(0),
    .C_HAS_PROG_FLAGS_RACH(0),
    .C_HAS_PROG_FLAGS_RDCH(0),
    .C_HAS_PROG_FLAGS_AXIS(0),
    .C_PROG_FULL_TYPE_WACH(0),
    .C_PROG_FULL_TYPE_WDCH(0),
    .C_PROG_FULL_TYPE_WRCH(0),
    .C_PROG_FULL_TYPE_RACH(0),
    .C_PROG_FULL_TYPE_RDCH(0),
    .C_PROG_FULL_TYPE_AXIS(0),
    .C_PROG_FULL_THRESH_ASSERT_VAL_WACH(1023),
    .C_PROG_FULL_THRESH_ASSERT_VAL_WDCH(1023),
    .C_PROG_FULL_THRESH_ASSERT_VAL_WRCH(1023),
    .C_PROG_FULL_THRESH_ASSERT_VAL_RACH(1023),
    .C_PROG_FULL_THRESH_ASSERT_VAL_RDCH(1023),
    .C_PROG_FULL_THRESH_ASSERT_VAL_AXIS(1023),
    .C_PROG_EMPTY_TYPE_WACH(0),
    .C_PROG_EMPTY_TYPE_WDCH(0),
    .C_PROG_EMPTY_TYPE_WRCH(0),
    .C_PROG_EMPTY_TYPE_RACH(0),
    .C_PROG_EMPTY_TYPE_RDCH(0),
    .C_PROG_EMPTY_TYPE_AXIS(0),
    .C_PROG_EMPTY_THRESH_ASSERT_VAL_WACH(1022),
    .C_PROG_EMPTY_THRESH_ASSERT_VAL_WDCH(1022),
    .C_PROG_EMPTY_THRESH_ASSERT_VAL_WRCH(1022),
    .C_PROG_EMPTY_THRESH_ASSERT_VAL_RACH(1022),
    .C_PROG_EMPTY_THRESH_ASSERT_VAL_RDCH(1022),
    .C_PROG_EMPTY_THRESH_ASSERT_VAL_AXIS(1022),
    .C_REG_SLICE_MODE_WACH(0),
    .C_REG_SLICE_MODE_WDCH(0),
    .C_REG_SLICE_MODE_WRCH(0),
    .C_REG_SLICE_MODE_RACH(0),
    .C_REG_SLICE_MODE_RDCH(0),
    .C_REG_SLICE_MODE_AXIS(0)
  ) inst (
    .backup(1'D0),
    .backup_marker(1'D0),
    .clk(1'D0),
    .rst(rst),
    .srst(1'D0),
    .wr_clk(wr_clk),
    .wr_rst(1'D0),
    .rd_clk(rd_clk),
    .rd_rst(1'D0),
    .din(din),
    .wr_en(wr_en),
    .rd_en(rd_en),
    .prog_empty_thresh(4'B0),
    .prog_empty_thresh_assert(4'B0),
    .prog_empty_thresh_negate(4'B0),
    .prog_full_thresh(4'B0),
    .prog_full_thresh_assert(4'B0),
    .prog_full_thresh_negate(4'B0),
    .int_clk(1'D0),
    .injectdbiterr(1'D0),
    .injectsbiterr(1'D0),
    .sleep(1'D0),
    .dout(dout),
    .full(full),
    .almost_full(),
    .wr_ack(),
    .overflow(),
    .empty(empty),
    .almost_empty(),
    .valid(),
    .underflow(),
    .data_count(),
    .rd_data_count(),
    .wr_data_count(),
    .prog_full(),
    .prog_empty(),
    .sbiterr(),
    .dbiterr(),
    .wr_rst_busy(),
    .rd_rst_busy(),
    .m_aclk(1'D0),
    .s_aclk(1'D0),
    .s_aresetn(1'D0),
    .m_aclk_en(1'D0),
    .s_aclk_en(1'D0),
    .s_axi_awid(1'B0),
    .s_axi_awaddr(32'B0),
    .s_axi_awlen(8'B0),
    .s_axi_awsize(3'B0),
    .s_axi_awburst(2'B0),
    .s_axi_awlock(1'B0),
    .s_axi_awcache(4'B0),
    .s_axi_awprot(3'B0),
    .s_axi_awqos(4'B0),
    .s_axi_awregion(4'B0),
    .s_axi_awuser(1'B0),
    .s_axi_awvalid(1'D0),
    .s_axi_awready(),
    .s_axi_wid(1'B0),
    .s_axi_wdata(64'B0),
    .s_axi_wstrb(8'B0),
    .s_axi_wlast(1'D0),
    .s_axi_wuser(1'B0),
    .s_axi_wvalid(1'D0),
    .s_axi_wready(),
    .s_axi_bid(),
    .s_axi_bresp(),
    .s_axi_buser(),
    .s_axi_bvalid(),
    .s_axi_bready(1'D0),
    .m_axi_awid(),
    .m_axi_awaddr(),
    .m_axi_awlen(),
    .m_axi_awsize(),
    .m_axi_awburst(),
    .m_axi_awlock(),
    .m_axi_awcache(),
    .m_axi_awprot(),
    .m_axi_awqos(),
    .m_axi_awregion(),
    .m_axi_awuser(),
    .m_axi_awvalid(),
    .m_axi_awready(1'D0),
    .m_axi_wid(),
    .m_axi_wdata(),
    .m_axi_wstrb(),
    .m_axi_wlast(),
    .m_axi_wuser(),
    .m_axi_wvalid(),
    .m_axi_wready(1'D0),
    .m_axi_bid(1'B0),
    .m_axi_bresp(2'B0),
    .m_axi_buser(1'B0),
    .m_axi_bvalid(1'D0),
    .m_axi_bready(),
    .s_axi_arid(1'B0),
    .s_axi_araddr(32'B0),
    .s_axi_arlen(8'B0),
    .s_axi_arsize(3'B0),
    .s_axi_arburst(2'B0),
    .s_axi_arlock(1'B0),
    .s_axi_arcache(4'B0),
    .s_axi_arprot(3'B0),
    .s_axi_arqos(4'B0),
    .s_axi_arregion(4'B0),
    .s_axi_aruser(1'B0),
    .s_axi_arvalid(1'D0),
    .s_axi_arready(),
    .s_axi_rid(),
    .s_axi_rdata(),
    .s_axi_rresp(),
    .s_axi_rlast(),
    .s_axi_ruser(),
    .s_axi_rvalid(),
    .s_axi_rready(1'D0),
    .m_axi_arid(),
    .m_axi_araddr(),
    .m_axi_arlen(),
    .m_axi_arsize(),
    .m_axi_arburst(),
    .m_axi_arlock(),
    .m_axi_arcache(),
    .m_axi_arprot(),
    .m_axi_arqos(),
    .m_axi_arregion(),
    .m_axi_aruser(),
    .m_axi_arvalid(),
    .m_axi_arready(1'D0),
    .m_axi_rid(1'B0),
    .m_axi_rdata(64'B0),
    .m_axi_rresp(2'B0),
    .m_axi_rlast(1'D0),
    .m_axi_ruser(1'B0),
    .m_axi_rvalid(1'D0),
    .m_axi_rready(),
    .s_axis_tvalid(1'D0),
    .s_axis_tready(),
    .s_axis_tdata(8'B0),
    .s_axis_tstrb(1'B0),
    .s_axis_tkeep(1'B0),
    .s_axis_tlast(1'D0),
    .s_axis_tid(1'B0),
    .s_axis_tdest(1'B0),
    .s_axis_tuser(4'B0),
    .m_axis_tvalid(),
    .m_axis_tready(1'D0),
    .m_axis_tdata(),
    .m_axis_tstrb(),
    .m_axis_tkeep(),
    .m_axis_tlast(),
    .m_axis_tid(),
    .m_axis_tdest(),
    .m_axis_tuser(),
    .axi_aw_injectsbiterr(1'D0),
    .axi_aw_injectdbiterr(1'D0),
    .axi_aw_prog_full_thresh(4'B0),
    .axi_aw_prog_empty_thresh(4'B0),
    .axi_aw_data_count(),
    .axi_aw_wr_data_count(),
    .axi_aw_rd_data_count(),
    .axi_aw_sbiterr(),
    .axi_aw_dbiterr(),
    .axi_aw_overflow(),
    .axi_aw_underflow(),
    .axi_aw_prog_full(),
    .axi_aw_prog_empty(),
    .axi_w_injectsbiterr(1'D0),
    .axi_w_injectdbiterr(1'D0),
    .axi_w_prog_full_thresh(10'B0),
    .axi_w_prog_empty_thresh(10'B0),
    .axi_w_data_count(),
    .axi_w_wr_data_count(),
    .axi_w_rd_data_count(),
    .axi_w_sbiterr(),
    .axi_w_dbiterr(),
    .axi_w_overflow(),
    .axi_w_underflow(),
    .axi_w_prog_full(),
    .axi_w_prog_empty(),
    .axi_b_injectsbiterr(1'D0),
    .axi_b_injectdbiterr(1'D0),
    .axi_b_prog_full_thresh(4'B0),
    .axi_b_prog_empty_thresh(4'B0),
    .axi_b_data_count(),
    .axi_b_wr_data_count(),
    .axi_b_rd_data_count(),
    .axi_b_sbiterr(),
    .axi_b_dbiterr(),
    .axi_b_overflow(),
    .axi_b_underflow(),
    .axi_b_prog_full(),
    .axi_b_prog_empty(),
    .axi_ar_injectsbiterr(1'D0),
    .axi_ar_injectdbiterr(1'D0),
    .axi_ar_prog_full_thresh(4'B0),
    .axi_ar_prog_empty_thresh(4'B0),
    .axi_ar_data_count(),
    .axi_ar_wr_data_count(),
    .axi_ar_rd_data_count(),
    .axi_ar_sbiterr(),
    .axi_ar_dbiterr(),
    .axi_ar_overflow(),
    .axi_ar_underflow(),
    .axi_ar_prog_full(),
    .axi_ar_prog_empty(),
    .axi_r_injectsbiterr(1'D0),
    .axi_r_injectdbiterr(1'D0),
    .axi_r_prog_full_thresh(10'B0),
    .axi_r_prog_empty_thresh(10'B0),
    .axi_r_data_count(),
    .axi_r_wr_data_count(),
    .axi_r_rd_data_count(),
    .axi_r_sbiterr(),
    .axi_r_dbiterr(),
    .axi_r_overflow(),
    .axi_r_underflow(),
    .axi_r_prog_full(),
    .axi_r_prog_empty(),
    .axis_injectsbiterr(1'D0),
    .axis_injectdbiterr(1'D0),
    .axis_prog_full_thresh(10'B0),
    .axis_prog_empty_thresh(10'B0),
    .axis_data_count(),
    .axis_wr_data_count(),
    .axis_rd_data_count(),
    .axis_sbiterr(),
    .axis_dbiterr(),
    .axis_overflow(),
    .axis_underflow(),
    .axis_prog_full(),
    .axis_prog_empty()
  );
endmodule

@SzymonHitachi
Copy link
Author

vivado.py

I have done below changes:

diff --git a/vunit/vivado/vivado.py b/vunit/vivado/vivado.py
index 8481880e..e7eb7001 100644
--- a/vunit/vivado/vivado.py
+++ b/vunit/vivado/vivado.py
@@ -36,6 +36,7 @@ def add_from_compile_order_file(
         # Optionally use VUnit dependency scanning for everything in xil_defaultlib, which
         # typically contains unencrypted top levels that instantiate encrypted implementations.
         scan_dependencies = dependency_scan_defaultlib and library_name == "xil_defaultlib"
+        print(scan_dependencies, library_name, file_name)
         source_file = vunit_obj.library(library_name).add_source_file(
             file_name,
             no_parse=not scan_dependencies,
@@ -52,11 +53,24 @@ def add_from_compile_order_file(
     # Use hardcoded dependency for everthing outside of xil_defaultlib
     for idx in range(1, len(no_dependency_scan)):
         no_dependency_scan[idx].add_dependency_on(no_dependency_scan[idx - 1])
+        print("add", no_dependency_scan[idx].name, " depends on ", no_dependency_scan[idx - 1].name)

     # Add dependency of last item in non-dependency scanned files to the each scanned file
     if no_dependency_scan:
         for source_file in with_dependency_scan:
             source_file.add_dependency_on(no_dependency_scan[-1])
+            print("add", source_file.name, " depends on ", no_dependency_scan[-1].name)
+
+    i = 0
+    print("<<< With dependency scan:")
+    for sf in with_dependency_scan:
+        i += 1
+        print(i, sf.name)
+    print("<<< No dependency scan:")
+    i = 0
+    for sf in no_dependency_scan:
+        i += 1
+        print(sf.name)

     return source_files

and the filtered output is:

True xil_defaultlib c:/work/fpga_dev/out/vunit_out/myproject/myproject/vivado_ip_project/vivado_ip_project.gen/sources_1/ip/abcd_cdc_fifo/sim/abcd_cdc_fifo.v
add out\vunit_out\myproject\myproject\vivado_ip_project\vivado_ip_project.gen\sources_1\ip\abcd_cdc_fifo\sim\abcd_cdc_fifo.v  depends on  out\vunit_out\myproject\myproject\vivado_ip_project\vivado_ip_project.gen\sources_1\bd\axi_interconnect_backbone\ipshared\8c02\hdl\axi_protocol_converter_v2_1_vl_rfs.v

<<< With dependency scan:
3 out\vunit_out\myproject\myproject\vivado_ip_project\vivado_ip_project.gen\sources_1\ip\abcd_cdc_fifo\sim\abcd_cdc_fifo.v

<<< No dependency scan:

(That dependency on axi interconnect is weird. Those modules aren't even related O_o )

@SzymonHitachi
Copy link
Author

I also have the final compile order from sim_if

$ git diff -- vunit/sim_if/__init__.py
diff --git a/vunit/sim_if/__init__.py b/vunit/sim_if/__init__.py
index a1d84d8e..2a336935 100644
--- a/vunit/sim_if/__init__.py
+++ b/vunit/sim_if/__init__.py
@@ -272,6 +272,12 @@ class SimulatorInterface(object):  # pylint: disable=too-many-public-methods

         source_files_to_skip = set()

+        print("<<< source_files to compile")
+        for sf in source_files:
+            print(sf.name)
+        print("<<< end")
+        exit(-5)
+
         max_library_name = 0
         max_source_file_name = 0
         if source_files:

and the filtered output is

<<< source_files to compile

C:\work\fpga_dev\projects\myproject\source\interfaces\abcd\abcd_cdc.vhd
C:\work\fpga_dev\out\vunit_out\myproject\myproject\vivado_ip_project\vivado_ip_project.gen\sources_1\ip\abcd_cdc_fifo\sim\abcd_cdc_fifo.v

<<< end

@SzymonHitachi
Copy link
Author

SzymonHitachi commented Dec 16, 2024

Somehow the dependencies between vivado_ip_project and normal component instantiation of those are not resolved

@SzymonHitachi
Copy link
Author

To add:
My simulation project is based on tsfpga/examples/simulation_utils.py:89 class SimulationProject

@SzymonHitachi
Copy link
Author

SzymonHitachi commented Dec 16, 2024

@LarsAsplund I have traced it back to vunit/sim_if.py:compile_source_files calling get_files_in_compile_order from vunit/project.py which then calls create_dependency_graph() with implementation_dependencies=False and components are resolved only when implementation_dependencies=True

        if implementation_dependencies:
            add_dependencies(self._find_component_design_unit_dependencies, vhdl_files)

I see the same later on in sim_if.py

When i set it to True then digging deeper it seems i get

DEBUG - failed to find a matching entity/module for component 'abcd_cdc_fifo' 

@SzymonHitachi SzymonHitachi linked a pull request Dec 18, 2024 that will close this issue
@LukasVik
Copy link
Contributor

@SzymonHitachi Thank you for all the info and your thorough investigation. To begin with, a quick fix that will most likely make it work is to set the dependency_scan_defaultlib flag to False here: https://github.com/tsfpga/tsfpga/blob/844397ef4ae01f9e3005df0028d57277bd3749f6/tsfpga/examples/simulation_utils.py#L260

@LukasVik
Copy link
Contributor

LukasVik commented Dec 29, 2024

This part of the code is a little under-documented. I am partially the author of it so I guess I am to blame. But, I'll try to explain.

def add_from_compile_order_file(

A typical (small) compile order might look like this:

fifo_generator_v13_2_10,Verilog,/home/lukas/work/repo/Sarcura/software/external/tsfpga/tsfpga/generated/vivado_ip_project/vivado_ip_project.gen/sources_1/ip/fifo_generator_0/simulation/fifo_generator_vlog_beh.v
fifo_generator_v13_2_10,VHDL,/home/lukas/work/repo/Sarcura/software/external/tsfpga/tsfpga/generated/vivado_ip_project/vivado_ip_project.gen/sources_1/ip/fifo_generator_0/hdl/fifo_generator_v13_2_rfs.vhd
fifo_generator_v13_2_10,Verilog,/home/lukas/work/repo/Sarcura/software/external/tsfpga/tsfpga/generated/vivado_ip_project/vivado_ip_project.gen/sources_1/ip/fifo_generator_0/hdl/fifo_generator_v13_2_rfs.v
xil_defaultlib,Verilog,/home/lukas/work/repo/Sarcura/software/external/tsfpga/tsfpga/generated/vivado_ip_project/vivado_ip_project.gen/sources_1/ip/fifo_generator_0/sim/fifo_generator_0.v
xbip_utils_v3_0_13,VHDL,/home/lukas/work/repo/Sarcura/software/external/tsfpga/tsfpga/generated/vivado_ip_project/vivado_ip_project.gen/sources_1/ip/mult_u12_u5/hdl/xbip_utils_v3_0_vh_rfs.vhd
xbip_pipe_v3_0_9,VHDL,/home/lukas/work/repo/Sarcura/software/external/tsfpga/tsfpga/generated/vivado_ip_project/vivado_ip_project.gen/sources_1/ip/mult_u12_u5/hdl/xbip_pipe_v3_0_vh_rfs.vhd
xbip_bram18k_v3_0_9,VHDL,/home/lukas/work/repo/Sarcura/software/external/tsfpga/tsfpga/generated/vivado_ip_project/vivado_ip_project.gen/sources_1/ip/mult_u12_u5/hdl/xbip_bram18k_v3_0_vh_rfs.vhd
mult_gen_v12_0_21,VHDL,/home/lukas/work/repo/Sarcura/software/external/tsfpga/tsfpga/generated/vivado_ip_project/vivado_ip_project.gen/sources_1/ip/mult_u12_u5/hdl/mult_gen_v12_0_vh_rfs.vhd
xil_defaultlib,VHDL,/home/lukas/work/repo/Sarcura/software/external/tsfpga/tsfpga/generated/vivado_ip_project/vivado_ip_project.gen/sources_1/ip/mult_u12_u5/sim/mult_u12_u5.vhd

This is compile_order.txt created by

def create_compile_order_file(project_file, compile_order_file, vivado_path=None):

If dependency_scan_defaultlib is False, the files will be added to VUnit with a linear dependency chain from the first to the last, and without any parsing of any file. Since no files are parsed, VUnit has to compile all these files first (before any other files) since it would be impossible to determine which other files might be possible to compile before.

This was the default behavior for quite a while. the dependency_scan_defaultlib flag was added to improve performance in the following scenario:

If we are running a --minimal simulation of code that depends only on the FIFO in the compile order above (not the multiplier), VUnit would still have to compile all of it. So the dependency_scan_defaultlib flag was added which, if set to True enables parsing of all files in the xil_defaultlib library (which is where the top level of each IP core will be).

So given the example above, if we simulate some code that instantiates the component/entity of the FIFO IP, VUnit parser would detect that the FIFO entity is in the file fifo_generator_0.v. That file and anything before it in the compile order would be compiled. VUnit would also parse mult_u12_u5.vhd and find that it has another entity/component that is not used anywhere. So that would not be compiled.

This can save some time in e.g. CI in large projects with a lot of IP cores.

HOWEVER: If the scenario is the reverse, the code we're simulating uses mult_u12_u5.vhd but not fifo_generator_0.v, the concept kinda falls apart. Since VUnit parses fifo_generator_0.v it will realize that we are not using that file. But all the other FIFO files, which are encrypted by Vivado, are not parsed and are still added to the linear compile order. I.e. they are compiled but unused, which wastes time.

So if the IP that we are --minimally simulating is early in the compile order, we can save some time. If it is late in the compile order, we save virtually nothing.

@LukasVik
Copy link
Contributor

LukasVik commented Dec 29, 2024

@SzymonHitachi If you confirm that dependency_scan_defaultlib=False here (https://github.com/tsfpga/tsfpga/blob/844397ef4ae01f9e3005df0028d57277bd3749f6/tsfpga/examples/simulation_utils.py#L260) fixes the issue I can add an argument to the method API in tsfpga.

@LukasVik
Copy link
Contributor

LukasVik commented Dec 29, 2024

But the actual root issue is still somewhere in VUnit. Disabling dependency_scan_defaultlib would be a workaround.

It seems that VUnit does not realize that this module in sim/abcd_cdc_fifo.v:

module abcd_cdc_fifo (
  rst,
  wr_clk,
  rd_clk,
  din,
  wr_en,
  rd_en,
  dout,
  full,
  empty
);

input wire rst;
(* X_INTERFACE_PARAMETER = "XIL_INTERFACENAME write_clk, FREQ_HZ 100000000, FREQ_TOLERANCE_HZ 0, PHASE 0.0, INSERT_VIP 0" *)
(* X_INTERFACE_INFO = "xilinx.com:signal:clock:1.0 write_clk CLK" *)
input wire wr_clk;
(* X_INTERFACE_PARAMETER = "XIL_INTERFACENAME read_clk, FREQ_HZ 100000000, FREQ_TOLERANCE_HZ 0, PHASE 0.0, INSERT_VIP 0" *)
(* X_INTERFACE_INFO = "xilinx.com:signal:clock:1.0 read_clk CLK" *)
input wire rd_clk;
(* X_INTERFACE_INFO = "xilinx.com:interface:fifo_write:1.0 FIFO_WRITE WR_DATA" *)
input wire [31 : 0] din;
(* X_INTERFACE_INFO = "xilinx.com:interface:fifo_write:1.0 FIFO_WRITE WR_EN" *)
input wire wr_en;
(* X_INTERFACE_INFO = "xilinx.com:interface:fifo_read:1.0 FIFO_READ RD_EN" *)
input wire rd_en;
(* X_INTERFACE_INFO = "xilinx.com:interface:fifo_read:1.0 FIFO_READ RD_DATA" *)
output wire [31 : 0] dout;
(* X_INTERFACE_INFO = "xilinx.com:interface:fifo_write:1.0 FIFO_WRITE FULL" *)
output wire full;
(* X_INTERFACE_INFO = "xilinx.com:interface:fifo_read:1.0 FIFO_READ EMPTY" *)
output wire empty;

is the same as this component in abcd_cdc.vhd:

architecture rtl of abcd_cdc is
    
    component abcd_cdc_fifo
    port (
        rst : in std_logic;
        wr_clk : in std_logic;
        rd_clk : in std_logic;
        din : in std_logic_vector(31 downto 0);
        wr_en : in std_logic;
        rd_en : in std_logic;
        dout : out std_logic_vector(31 downto 0);
        full : out std_logic;
        empty : out std_logic 
    );
    end component;

begin

I guess this is a bug/limitation in the Verilog parser. I don't write much Verilog personally, but the code looks a little weird. The module part lists only the names, no input/output or ranges. Maybe VUnit verilog parser can not handle this?

@LukasVik
Copy link
Contributor

LukasVik commented Dec 29, 2024

@SzymonHitachi PS; I thougth your company is using hdl-modules also? A FIFO in pure VHDL is a lot nicer than an IP core. Should use this:

https://hdl-modules.com/modules/fifo/fifo.html#asynchronous-fifo-vhd

@SzymonHitachi
Copy link
Author

SzymonHitachi commented Jan 17, 2025

Happy new year! I finally am back and did dive into the topic.
#1073 (comment) seems to affect the order but not fully. The component (fifo) is still compiled after its instantiating module. It suggests the dependency is not resolved properly for component?

After more debugging I can confirm that for my file abcd_cdc.vhd which is instantiating abcd_cdc_fifo as component, file containing abcd_cdc_fifo the dependency on abcd_cdc_fifo.v is not being added

DEBUG - Adding source file C:\work\source\interfaces\abcd\abcd_cdc.vhd to library myproject
DEBUG - Adding primary design unit (entity) abcd_cdc
DEBUG - Adding secondary design unit (architecture) rtl
DEBUG - The file 'C:\work\source\interfaces\abcd\abcd_cdc.vhd' has the following components:
DEBUG - abcd_cdc_fifo
...
DEBUG - Adding source file C:\work\out\vunit_out\myproject\myproject\vivado_ip_project\vivado_ip_project.gen\sources_1\ip\abcd_cdc_fifo\sim\abcd_cdc_fifo.v to library xil_defaultlib

so it might be around the lines of #1073 (comment)

@SzymonHitachi
Copy link
Author

SzymonHitachi commented Jan 17, 2025

The verilog IP file seems to be parsed properly. I guess the issue might come from the fact that abcd_cdc_fifo is added to xil_defaultlib and not myproject but is refferenced like it was in the same library as abcd_cdc (which is myproject) because Vivado doesn't put IPs in libraries it seems.

My guess here is that experimenting with

set_property default_lib myproject [current_project]

Could yield some improvements.

@LukasVik
Copy link
Contributor

#1073 (comment)

I might be wrong but I really don't think this is the issue. If you look into the generated compile_order.txt I'm pretty sure it will say xil_defaultlib on the IP top level.

@LukasVik
Copy link
Contributor

I don't think the concept of an IP core belonging to a library exists. And it should work either way since it is a component instantiation. If you use entity instantiation (which I would personally), the library is xil_defaultlib, per compile_order.txt.

@SzymonHitachi
Copy link
Author

Yeah they end up in xil_defaultlib. The depencency of abcd_cdc on abcd_cdc_fifo IP is not being automatically resolved by VUnit and I think this is because of the library difference.

Is there any way to force the IP project VUnit compilation before rest of VUnit? Any way to really control the order other that adding manual dependency on the specific generated files?

@LukasVik
Copy link
Contributor

Yeah they end up in xil_defaultlib. The depencency of abcd_cdc on abcd_cdc_fifo IP is not being automatically resolved by VUnit and I think this is because of the library difference.

Again, I really don't think this is the issue. If compile_order.txt, which comes directly from Vivado, says xil_defaultlib then that's what it is supposed to be. Anyway, you use component instantiation and components don't really care about libraries. And IP cores in Vivado do not belong to any library.

I still think the issue is this: #1073 (comment)

Is there any way to force the IP project VUnit compilation before rest of VUnit? Any way to really control the order other that adding manual dependency on the specific generated files?

Yes this is what I suggested here: #1073 (comment)
Did you try it? Did it work?

@SzymonHitachi
Copy link
Author

Yes I did try it. It did not work. While it changed the order of operations, the IPs (yes instantiated as components) are still not placed before the files instantiating them. Currently I'm trying to force a dependency of my whole main project library on xil_defaultlib.
This seems a bit of workaround to check if this solves Riviera elaboration problems.

@SzymonHitachi
Copy link
Author

Few additional notes:

  1. Forcing xil_defaultlib as dependency to current project seems to work for most of the code.
  2. Some of the dependencies within xil_defaultlib still are not ordered properly for block diagrams
  3. some cross-library component dependencies other than in xil_defaultlib (but exactly the same case) are not ordered properly.

So it seems we have 2 different overlapping issues here:

  1. VUnit order for components coming from different library is not resolved properly.
  2. Riviera-PRO requires supplying the libraries not only to vsim but also to vcom

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants