YosysHQ / yosys

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

Yosys subcommand "hierarchy" fails for "hardcoded FPGA blocks" #3013

Open 71GA opened 2 years ago

71GA commented 2 years ago

I have this design where I use SPI block that is "hardcoded inside the FPGA". I don't have the design of this element, but I am able to use it successfully once my bitstream file is uploaded to the FPGA.

This is my design (in Verilog):

// A:
module
    top(
        input pcb_oscilator,
        output pcb_rgb_led0,
        output pcb_rgb_led1,
        output pcb_rgb_led2,
        output pcb_led1,
        output pcb_led2,
        output pcb_led3,
        output pcb_led4,
        output pcb_led5,
        input pcb_spi_sck,
        input pcb_spi_csn,
        input pcb_spi_si,
        output pcb_spi_so
);

    // B:
    parameter
        NOP = 0,
        INIT = 1,
        WR_INVERTED = 2,
        WR_LEDS = 4,
        WR_VEC = 6,
        RD_VEC = 7;

    // C:
    parameter
        INIT_SPICR0 = 0,
        INIT_SPICR1 = 1,
        INIT_SPICR2 = 2,
        INIT_SPIBR = 3,
        INIT_SPICSR = 4,
        SPI_WAIT_RECEPTION = 5,
        SPI_READ_OPCODE = 6,
        SPI_READ_LED_VALUE = 7,
        SPI_READ_INIT = 8,
        SPI_SEND_DATA = 9,
        SPI_WAIT_TRANSMIT_READY = 10,
        SPI_TRANSMIT = 11,
        STATEA = 12,
        LOOPSTATE = 13;

    // D:
    parameter
        SPI_ADDR_SPICR0 = 8'b00001000,
        SPI_ADDR_SPICR1 = 8'b00001001,
        SPI_ADDR_SPICR2 = 8'b00001010,
        SPI_ADDR_SPIBR = 8'b00001011,
        SPI_ADDR_SPITXDR = 8'b00001101,
        SPI_ADDR_SPIRXDR = 8'b00001110,
        SPI_ADDR_SPICSR = 8'b00001111,
        SPI_ADDR_SPISR = 8'b00001100;
        /// SPI_ADDR_SPIINTSR = 8'b00000110,
        /// SPI_ADDR_SPIINTCR = 8'b00000111;

    // E:
    ///parameter COMMAND_SIZE = 4;

    // F:
    wire sb_clki;
    reg sb_rwi;
    reg sb_stbi;
    reg [7:0] sb_adri;
    reg [7:0] sb_dati;
    ///reg [7:0] sb_dato;
    wire [7:0] sb_dato;
    wire sb_acko;
    wire so;
    wire si;
    wire scki;
    wire scsni;
    reg [2:0] rgb_led;
    wire led1;
    wire led2;
    wire led3;
    wire led4;
    wire led5;

    // G:
    SB_SPI SB_SPI_inst(
        .SBCLKI(sb_clki),      // System bus: clock (i)
        .SBRWI(sb_rwi),        // System bus: read/write (i)
        .SBSTBI(sb_stbi),      // System bus: strobe (i)
        .SBADRI0(sb_adri[0]),  // System bus: address to target control registers (i)
        .SBADRI1(sb_adri[1]),
        .SBADRI2(sb_adri[2]),
        .SBADRI3(sb_adri[3]),
        .SBADRI4(sb_adri[4]),
        .SBADRI5(sb_adri[5]),
        .SBADRI6(sb_adri[6]),
        .SBADRI7(sb_adri[7]),
        .SBDATI0(sb_dati[0]),
        .SBDATI1(sb_dati[1]),  // System bus: data input (i)
        .SBDATI2(sb_dati[2]),
        .SBDATI3(sb_dati[3]),
        .SBDATI4(sb_dati[4]),
        .SBDATI5(sb_dati[5]),
        .SBDATI6(sb_dati[6]),
        .SBDATI7(sb_dati[7]),
        .SBDATO0(sb_dato[0]),  // System bus: data output (o)
        .SBDATO1(sb_dato[1]),
        .SBDATO2(sb_dato[2]),
        .SBDATO3(sb_dato[3]),
        .SBDATO4(sb_dato[4]),
        .SBDATO5(sb_dato[5]),
        .SBDATO6(sb_dato[6]),
        .SBDATO7(sb_dato[7]),
        //.SPIIRQ(),           // SPI: interrupt output (o)
        //.SPIWKUP(),          // SPI: wakeup from standby (o)
        .SBACKO(sb_acko),      // System bus: acknowledge (o)
        //.MI(),               // SPI: master input (i)
        .SO(so),               // SPI: slave out (o)
        //.SOE(),              // SPI: slave out enable - active high (o)
        .SI(si),               // SPI: slave in (i)
        //.MO(),               // SPI: master out (o)
        //.MOE(),              // SPI: master out enable - active high (o)
        .SCKI(scki),           // SPI: slave clock in (i)
        //.SCKO(),             // SPI: slave clock out (o)
        //.SCKOE(),            // SPI: slave clock out enable - active high (o)
        .SCSNI(scsni)          // SPI: slave chip select (i)
        //.MCSNO0(),           // SPI: master chip select (o)
        //.MCSNO1(),
        //.MCSNO2(),
        //.MCSNO3(),
        //.MCSNOE0(),          // SPI: master chip select enable - active high (o)
        //.MCSNOE1(),
        //.MCSNOE2(),
        //.MCSNOE3()
    );

    // H:
    assign pcb_spi_sck = sb_clki;
    assign pcb_spi_sck = scki;
    assign pcb_spi_csn = scsni;
    assign pcb_spi_si = si;
    assign pcb_spi_so = so;
    assign pcb_rgb_led2 = ~rgb_led[0];
    assign pcb_rgb_led1 = ~rgb_led[1];
    assign pcb_rgb_led0 = ~rgb_led[2];
    assign pcb_led1 = led1;
    assign pcb_led2 = led2;
    assign pcb_led3 = led3;
    assign pcb_led4 = led4;
    assign pcb_led5 = led5;

endmodule

This synthesizes well by calling make, but when I try to create an svg using make svg it fails because it can't find the "hardcoded SPI block" i.e. SB_SPI_inst. This is the compilation output:

┌───┐
│ $ │ ziga > ziga--workstation > spi_slave
└─┬─┘ /dev/pts/2
  └─> make svg 
yosys \
        -p "read_verilog -sv -formal top.v" \
        -p "hierarchy -generate SB_SPI_inst" \
        -p "hierarchy -check -top top" \
        -p "proc" \
        -p "write_json top.json"

 /----------------------------------------------------------------------------\
 |                                                                            |
 |  yosys -- Yosys Open SYnthesis Suite                                       |
 |                                                                            |
 |  Copyright (C) 2012 - 2020  Claire Xenia Wolf <claire@yosyshq.com>         |
 |                                                                            |
 |  Permission to use, copy, modify, and/or distribute this software for any  |
 |  purpose with or without fee is hereby granted, provided that the above    |
 |  copyright notice and this permission notice appear in all copies.         |
 |                                                                            |
 |  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES  |
 |  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF          |
 |  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR   |
 |  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES    |
 |  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN     |
 |  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF   |
 |  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.            |
 |                                                                            |
 \----------------------------------------------------------------------------/

 Yosys 0.9+4276 (git sha1 UNKNOWN, clang  -fPIC -Os)

-- Running command `read_verilog -sv -formal top.v' --

1. Executing Verilog-2005 frontend: top.v
Parsing formal SystemVerilog input from `top.v' to AST representation.
Generating RTLIL representation for module `\top'.
Successfully finished Verilog frontend.

-- Running command `hierarchy -generate SB_SPI_inst' --

2. Executing HIERARCHY pass (managing design hierarchy).
Entering generate mode.
Celltype: SB_SPI_inst

-- Running command `hierarchy -check -top top' --

3. Executing HIERARCHY pass (managing design hierarchy).

3.1. Analyzing design hierarchy..
Top module:  \top
ERROR: Module `\SB_SPI' referenced in module `\top' in cell `\SB_SPI_inst' is not part of the design.
make: *** [makefile:10: svg] Error 1

This is the makefile that I use:

filename = top
pcf_file = io.pcf

build:
    yosys -p "synth_ice40 -blif $(filename).blif" $(filename).v
    arachne-pnr -d 5k -P sg48 -p $(pcf_file) $(filename).blif -o $(filename).asc
    icepack $(filename).asc $(filename).bin

svg:
    yosys \
        -p "read_verilog -sv -formal $(filename).v" \
        -p "hierarchy -generate SB_SPI_inst" \
        -p "hierarchy -check -top $(filename)" \
        -p "proc" \
        -p "write_json $(filename).json"
    netlistsvg -o $(filename).svg $(filename).json

flash:
    iceprog $(filename).bin

flash_flash:
    iceprog -S $(filename).bin

clean:
    rm -rf $(filename).blif $(filename).asc $(filename).bin

If I check the help for yosys subcommand hierarchy, I get this:

┌───┐
│ $ │ ziga > ziga--workstation > spi_slave
└─┬─┘ /dev/pts/2
  └─> yosys

 /----------------------------------------------------------------------------\
 |                                                                            |
 |  yosys -- Yosys Open SYnthesis Suite                                       |
 |                                                                            |
 |  Copyright (C) 2012 - 2020  Claire Xenia Wolf <claire@yosyshq.com>         |
 |                                                                            |
 |  Permission to use, copy, modify, and/or distribute this software for any  |
 |  purpose with or without fee is hereby granted, provided that the above    |
 |  copyright notice and this permission notice appear in all copies.         |
 |                                                                            |
 |  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES  |
 |  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF          |
 |  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR   |
 |  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES    |
 |  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN     |
 |  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF   |
 |  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.            |
 |                                                                            |
 \----------------------------------------------------------------------------/

 Yosys 0.9+4276 (git sha1 UNKNOWN, clang  -fPIC -Os)

yosys> help netlistsvg
No such command or cell type: netlistsvg

yosys> help hierarchy

    hierarchy [-check] [-top <module>]
    hierarchy -generate <cell-types> <port-decls>

In parametric designs, a module might exists in several variations with
different parameter values. This pass looks at all modules in the current
design and re-runs the language frontends for the parametric modules as
needed. It also resolves assignments to wired logic data types (wand/wor),
resolves positional module parameters, unrolls array instances, and more.

    -check
        also check the design hierarchy. this generates an error when
        an unknown module is used as cell type.

    -simcheck
        like -check, but also throw an error if blackbox modules are
        instantiated, and throw an error if the design has no top module.

    -purge_lib
        by default the hierarchy command will not remove library (blackbox)
        modules. use this option to also remove unused blackbox modules.

    -libdir <directory>
        search for files named <module_name>.v in the specified directory
        for unknown modules and automatically run read_verilog for each
        unknown module.

    -keep_positionals
        per default this pass also converts positional arguments in cells
        to arguments using port names. This option disables this behavior.

    -keep_portwidths
        per default this pass adjusts the port width on cells that are
        module instances when the width does not match the module port. This
        option disables this behavior.

    -nodefaults
        do not resolve input port default values

    -nokeep_asserts
        per default this pass sets the "keep" attribute on all modules
        that directly or indirectly contain one or more formal properties.
        This option disables this behavior.

    -top <module>
        use the specified top module to build the design hierarchy. Modules
        outside this tree (unused modules) are removed.

        when the -top option is used, the 'top' attribute will be set on the
        specified top module. otherwise a module with the 'top' attribute set
        will implicitly be used as top module, if such a module exists.

    -auto-top
        automatically determine the top of the design hierarchy and mark it.

    -chparam name value 
       elaborate the top module using this parameter value. Modules on which
       this parameter does not exist may cause a warning message to be output.
       This option can be specified multiple times to override multiple
       parameters. String values must be passed in double quotes (").

In -generate mode this pass generates blackbox modules for the given cell
types (wildcards supported). For this the design is searched for cells that
match the given types and then the given port declarations are used to
determine the direction of the ports. The syntax for a port declaration is:

    {i|o|io}[@<num>]:<portname>

Input ports are specified with the 'i' prefix, output ports with the 'o'
prefix and inout ports with the 'io' prefix. The optional <num> specifies
the position of the port in the parameter list (needed when instantiated
using positional arguments). When <num> is not specified, the <portname> can
also contain wildcard characters.

This pass ignores the current selection and always operates on all modules
in the current design.

This problem is related to yosys and netlistsvg, so I posted it here.

gatecat commented 2 years ago

Try reading in the blackboxes for the iCE40 cells first using read_verilog -lib +/ice40/cells_sim.v before hierarchy

71GA commented 2 years ago

This worked! I just did changed the makefile target svg like this:

svg:
    yosys \
        -p "read_verilog -sv -formal $(filename).v" \
        -p "read_verilog -lib +/ice40/cells_sim.v" \
        -p "hierarchy -check -top $(filename)" \
        -p "proc" \
        -p "write_json $(filename).json"
    netlistsvg -o $(filename).svg $(filename).json

Where is this documented?