YosysHQ / yosys

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

Passing user defined attributes to Vivado via EDIF #655

Closed mithro closed 6 years ago

mithro commented 6 years ago

Steps to reproduce the issue

When creating code in migen for use with Vivado, the code is generated with custom attributes and then constraints applied in the XDC output.

The created Verilog code looks likes the following;

(* async_reg = "true", mr_ff = "true", dont_touch = "true" *) reg xilinxmultiregimpl0_regs0 = 1'd0;
(* async_reg = "true", dont_touch = "true" *) reg xilinxmultiregimpl0_regs1 = 1'd0;

You then use XDC to apply constraints like the following;

set_false_path -quiet -to [get_nets -filter {mr_ff == TRUE}]
set_false_path -quiet -to [get_pins -filter {REF_PIN_NAME == PRE} -of [get_cells -filter {ars_ff1 == TRUE || ars_ff2 == TRUE}]]
set_max_delay 2 -quiet -from [get_pins -filter {REF_PIN_NAME == Q} -of [get_cells -filter {ars_ff1 == TRUE}]] -to [get_pins -filter {REF_PIN_NAME == D} -of [get_cells -filter {ars_ff2 == TRUE}]]

When using the following Yosys script;

read_verilog -I./verilog/config ./verilog/submodule/rtl/lm32_dtlb.v
read_verilog -I./verilog/config top.v
# hierarchy -top top
# proc; memory; opt; fsm; opt
attrmap -tocase keep -imap keep="true" keep=1 \
    -imap keep="false" keep=0 -remove keep=0
synth_xilinx -top top -edif top.edif

and this Vivado script

create_project -force -name top -part xc7a35t-csg324-1
read_xdc top.xdc
read_edif top.edif
link_design -top top -part xc7a35t-csg324-1
opt_design
place_design
route_design
phys_opt_design
write_checkpoint -force top_route.dcp
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]
write_bitstream -force top.bit 
write_cfgmem -force -format bin -interface spix4 -size 16 -loadbit "up 0x0 top.bit" -file top.bin
quit

The Verilog attributes don't seem to end up in the EDIF file and Vivado outputs the following issues;

Parsing XDC File [/home/tansell/github/timvideos/HDMI2USB-litex-firmware/build/arty_base_lm32/gateware/top.xdc]
WARNING: [Vivado 12-1023] No nets matched for command 'get_nets -filter {mr_ff == TRUE}'. [/home/tansell/github/timvideos/HDMI2USB-litex-firmware/build/arty_base_lm32/gateware/top.xdc:282]
WARNING: [Vivado 12-180] No cells matched 'get_cells -filter {ars_ff1 == TRUE || ars_ff2 == TRUE}'. [/home/tansell/github/timvideos/HDMI2USB-litex-firmware/build/arty_base_lm32/gateware/top.xdc:284]
WARNING: [Vivado 12-508] No pins matched 'get_pins -filter {REF_PIN_NAME == PRE} -of [get_cells -filter {ars_ff1 == TRUE || ars_ff2 == TRUE}]'. [/home/tansell/github/timvideos/HDMI2USB-litex-firmware/build/arty_base_lm32/gateware/top.xdc:284]
WARNING: [Vivado 12-180] No cells matched 'get_cells -filter {ars_ff1 == TRUE}'. [/home/tansell/github/timvideos/HDMI2USB-litex-firmware/build/arty_base_lm32/gateware/top.xdc:286]
WARNING: [Vivado 12-508] No pins matched 'get_pins -filter {REF_PIN_NAME == Q} -of [get_cells -filter {ars_ff1 == TRUE}]'. [/home/tansell/github/timvideos/HDMI2USB-litex-firmware/build/arty_base_lm32/gateware/top.xdc:286]
WARNING: [Vivado 12-180] No cells matched 'get_cells -filter {ars_ff2 == TRUE}'. [/home/tansell/github/timvideos/HDMI2USB-litex-firmware/build/arty_base_lm32/gateware/top.xdc:286]
WARNING: [Vivado 12-508] No pins matched 'get_pins -filter {REF_PIN_NAME == D} -of [get_cells -filter {ars_ff2 == TRUE}]'. [/home/tansell/github/timvideos/HDMI2USB-litex-firmware/build/arty_base_lm32/gateware/top.xdc:286]
Finished Parsing XDC File [/home/tansell/github/timvideos/HDMI2USB-litex-firmware/build/arty_base_lm32/gateware/top.xdc]

A full example found here.

Expected behavior

This works in Vivado and it would be nice for it to work when using Yosys as a replacement synthesis tool.

FYI The custom properties that migen uses are the follow;

        # While custom attributes are supported in yosys, neither
        # arachne-pnr nor icetime currently can take advantage of them
        # to add fine-grained timing constraints.
        "mr_ff": None,  # user-defined attribute
        "mr_false_path": None,  # user-defined attribute
        "ars_ff1": None,  # user-defined attribute
        "ars_ff2": None,  # user-defined attribute
        "ars_false_path": None,  # user-defined attribute
mithro commented 6 years ago

Looking at the EDIF Vivado itself produces;

From the following Verilog;

(* ars_ff1 = "true", async_reg = "true" *) FDPE #(
    .INIT(1'd1)
) FDPE (
    .C(sys_clk),
    .CE(1'd1),
    .D(1'd0),
    .PRE(xilinxasyncresetsynchronizerimpl0),
    .Q(xilinxasyncresetsynchronizerimpl0_rst_meta)
);

(* ars_ff2 = "true", async_reg = "true" *) FDPE #(
    .INIT(1'd1)
) FDPE_1 (
    .C(sys_clk),
    .CE(1'd1),
    .D(xilinxasyncresetsynchronizerimpl0_rst_meta),
    .PRE(xilinxasyncresetsynchronizerimpl0),
    .Q(sys_rst)
);

(* ars_ff1 = "true", async_reg = "true" *) FDPE #(
    .INIT(1'd1)
) FDPE_2 (
    .C(clk200_clk),
    .CE(1'd1),
    .D(1'd0),
    .PRE(xilinxasyncresetsynchronizerimpl1),
    .Q(xilinxasyncresetsynchronizerimpl1_rst_meta)
);

(* ars_ff2 = "true", async_reg = "true" *) FDPE #(
    .INIT(1'd1)
) FDPE_3 (
    .C(clk200_clk),
    .CE(1'd1),
    .D(xilinxasyncresetsynchronizerimpl1_rst_meta),
    .PRE(xilinxasyncresetsynchronizerimpl1),
    .Q(clk200_rst)
);

You get the following EDIF;

         (instance FDPE (viewref netlist (cellref FDPE (libraryref hdi_primitives)))
           (property BOX_TYPE (string "PRIMITIVE"))
           (property INIT (string "1'b1"))
           (property IS_C_INVERTED (string "1'b0"))
           (property IS_D_INVERTED (string "1'b0"))
           (property IS_PRE_INVERTED (string "1'b0"))
           (property ars_ff1 (string "true"))
           (property ASYNC_REG (boolean (true)))
         )
         (instance FDPE_1 (viewref netlist (cellref FDPE (libraryref hdi_primitives)))
           (property BOX_TYPE (string "PRIMITIVE"))
           (property INIT (string "1'b1"))
           (property IS_C_INVERTED (string "1'b0"))
           (property IS_D_INVERTED (string "1'b0"))
           (property IS_PRE_INVERTED (string "1'b0"))
           (property ars_ff2 (string "true"))
           (property ASYNC_REG (boolean (true)))
         )
         (instance FDPE_2 (viewref netlist (cellref FDPE (libraryref hdi_primitives)))
           (property BOX_TYPE (string "PRIMITIVE"))
           (property INIT (string "1'b1"))
           (property IS_C_INVERTED (string "1'b0"))
           (property IS_D_INVERTED (string "1'b0"))
           (property IS_PRE_INVERTED (string "1'b0"))
           (property ars_ff1 (string "true"))
           (property ASYNC_REG (boolean (true)))
         )
         (instance FDPE_3 (viewref netlist (cellref FDPE (libraryref hdi_primitives)))
           (property BOX_TYPE (string "PRIMITIVE"))
           (property INIT (string "1'b1"))
           (property IS_C_INVERTED (string "1'b0"))
           (property IS_D_INVERTED (string "1'b0"))
           (property IS_PRE_INVERTED (string "1'b0"))
           (property ars_ff2 (string "true"))
           (property ASYNC_REG (boolean (true)))
         )

If seems as simple as adding the following output to the EDIF; (property ars_ff2 (string "true")) or (property ars_ff1 (string "true")).

Yosys currently produces the following EDIF for the verilog;

          (instance FDPE
            (viewRef VIEW_NETLIST (cellRef FDPE (libraryRef LIB)))
            (property INIT (integer 1)))
          (instance FDPE_1
            (viewRef VIEW_NETLIST (cellRef FDPE (libraryRef LIB)))
            (property INIT (integer 1)))
          (instance FDPE_2
            (viewRef VIEW_NETLIST (cellRef FDPE (libraryRef LIB)))
            (property INIT (integer 1)))
          (instance FDPE_3
            (viewRef VIEW_NETLIST (cellRef FDPE (libraryRef LIB)))
            (property INIT (integer 1)))
cliffordwolf commented 6 years ago

Commit 115ca57 adds write_edif -attrprop with this functionality.

mithro commented 6 years ago

Just confirming this seems to work!

hierarchy -top top
# proc; memory; opt; fsm; opt
attrmap -tocase keep -imap keep="true" keep=1 \
    -imap keep="false" keep=0 -remove keep=0
synth_xilinx -top top
write_edif -attrprop top.edif

Vivado is now seeing the custom attributes and the xdc constraints seem to be successfully applied to them!