Giter VIP home page Giter VIP logo

Comments (6)

cliffordwolf avatar cliffordwolf commented on August 17, 2024

There is a couple of things going on here.

First the Yosys Verilog parser did not support functions returning "integer". This is fixed now.

Second, the Yosys Verilog frontend does yet not support constant evaluation of functions for parameters. This is a bit tricky to add. I will look into it later and write another comment regarding this issue then. So this is why it sill fails case with ICARUS not set.

Regarding the case with ICARUS set: This would generally work with Yosys (the $clog2 function is supported). But this module is not synthesizable with this default parameters. With PRECISION=32 this module tries to access bits 4:0 of in2, but in2 is only 1 bit wide. This also creates an error when trying to synthesize the module with Xilinx XST, for example.

When you define ICARUS and set BITSIZE_in2 at least to $clog2(PRECISION), which is 5 in this case, then this module synthesizes fine with Yosys.

I'll keep this issue open until I have figured out how to do const evaluation of functions.

PS: When quoting code in markdown you should indent it with 4 spaces. Just for future reference, here is the code again, but quoted correctly (and with additional indenting for readability):

module lshift_expr_FU(in1, in2, out1);

    parameter BITSIZE_in1=1, BITSIZE_in2=1, BITSIZE_out1=1, PRECISION=32;

    // IN
    input signed [BITSIZE_in1-1:0] in1;
    input [BITSIZE_in2-1:0] in2;

    // OUT
    output signed [BITSIZE_out1-1:0] out1;

`ifndef __ICARUS__
    function integer log2;
        input integer value;
        integer temp_value;
        begin
            temp_value = value-1;
            for (log2=0; temp_value>0; log2=log2+1)
                temp_value = temp_value>>1;
        end
    endfunction
`endif

`ifdef __ICARUS__
    parameter arg2_bitsize = $clog2(PRECISION);
`else
    parameter arg2_bitsize = log2(PRECISION);
`endif

    assign out1 = in1 <<< in2[arg2_bitsize-1:0];

endmodule

from yosys.

fabrizioferrandi avatar fabrizioferrandi commented on August 17, 2024

First of all, thanks for the answer. You are right if you consider the module alone. What it is strange is the yosys behavior during the parsing of a more bigger example.
Here attached the large example that passes the xst/iverilog compilation:

// File automatically generated by: PandA framework version=0.9.2-dev
// Send any bug to: [email protected]
// ************************************************************************
// The following text holds for all the components tagged with PANDA_GPLv3.
// 
// This hardware description is free; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3, or (at your option)
// any later version.
// 
// This hardware description is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE.    See the GNU General Public License
// for more details.
// 
// You should have received a copy of the GNU General Public License
// along with the PandA framework; see the files COPYING
// If not, see <http://www.gnu.org/licenses/>.
// ************************************************************************

// This component is part of the BAMBU/PANDA IP LIBRARY
// Copyright (C) 2004-2014 Politecnico di Milano
// Author(s): Fabrizio Ferrandi <fabrizio.ferrandi@xxxx>, Christian Pilato <christian.pilato@xxxx>
// License: PANDA_GPLv3
`timescale 1ns / 1ps
module constant_value(out1);
    parameter BITSIZE_out1=1, value=0;
    // OUT
    output [BITSIZE_out1-1:0] out1;
    assign out1 = value;
endmodule

// This component is part of the BAMBU/PANDA IP LIBRARY
// Copyright (C) 2004-2014 Politecnico di Milano
// Author(s): Fabrizio Ferrandi <fabrizio.ferrandi@xxxx>
// License: PANDA_GPLv3
`timescale 1ns / 1ps
module register_SE(clock, reset, in1, wenable, out1);
    parameter BITSIZE_in1=1, BITSIZE_out1=1;
    // IN
    input clock;
    input reset;
    input [BITSIZE_in1-1:0] in1;
    input wenable;
    // OUT
    output [BITSIZE_out1-1:0] out1;
    reg [BITSIZE_out1-1:0] reg_out1;
    assign out1 = reg_out1;
    always @(posedge clock)
        if (wenable)
            reg_out1 <= in1;
endmodule

// This component is part of the BAMBU/PANDA IP LIBRARY
// Copyright (C) 2004-2014 Politecnico di Milano
// Author(s): Fabrizio Ferrandi <fabrizio.ferrandi@xxxx>
// License: PANDA_GPLv3
`timescale 1ns / 1ps
module register_STD(clock, reset, in1, wenable, out1);
    parameter BITSIZE_in1=1, BITSIZE_out1=1;
    // IN
    input clock;
    input reset;
    input [BITSIZE_in1-1:0] in1;
    input wenable;
    // OUT
    output [BITSIZE_out1-1:0] out1;
    reg [BITSIZE_out1-1:0] reg_out1;
    assign out1 = reg_out1;
    always @(posedge clock)
        reg_out1 <= in1;
endmodule

// This component is part of the BAMBU/PANDA IP LIBRARY
// Copyright (C) 2004-2014 Politecnico di Milano
// Author(s): Fabrizio Ferrandi <fabrizio.ferrandi@xxxx>
// License: PANDA_GPLv3
`timescale 1ns / 1ps
module ASSIGN_SIGNED_FU(in1, out1);
    parameter BITSIZE_in1=1, BITSIZE_out1=1;
    // IN
    input signed [BITSIZE_in1-1:0] in1;
    // OUT
    output signed [BITSIZE_out1-1:0] out1;
    assign out1 = in1;
endmodule

// This component is part of the BAMBU/PANDA IP LIBRARY
// Copyright (C) 2004-2014 Politecnico di Milano
// Author(s): Fabrizio Ferrandi <fabrizio.ferrandi@xxxx>
// License: PANDA_GPLv3
`timescale 1ns / 1ps
module MEMORY_CTRL(clock, start_port, in1, in2, in3, sel_LOAD, sel_STORE, done_port, out1, Min_oe_ram, Mout_oe_ram, Min_we_ram, Mout_we_ram, Min_addr_ram, Mout_addr_ram, M_Rdata_ram, Min_Wdata_ram, Mout_Wdata_ram, Min_data_ram_size, Mout_data_ram_size, M_DataRdy);
    parameter BITSIZE_in1=1, BITSIZE_in2=1, BITSIZE_in3=1, BITSIZE_out1=1, BITSIZE_Min_addr_ram=1, BITSIZE_Mout_addr_ram=1, BITSIZE_M_Rdata_ram=8, BITSIZE_Min_Wdata_ram=8, BITSIZE_Mout_Wdata_ram=8, BITSIZE_Min_data_ram_size=1, BITSIZE_Mout_data_ram_size=1;
    // IN
    input clock;
    input start_port;
    input [BITSIZE_in1-1:0] in1;
    input [BITSIZE_in2-1:0] in2;
    input [BITSIZE_in3-1:0] in3;
    input sel_LOAD;
    input sel_STORE;
    input Min_oe_ram;
    input Min_we_ram;
    input [BITSIZE_Min_addr_ram-1:0] Min_addr_ram;
    input [BITSIZE_M_Rdata_ram-1:0] M_Rdata_ram;
    input [BITSIZE_Min_Wdata_ram-1:0] Min_Wdata_ram;
    input [BITSIZE_Min_data_ram_size-1:0] Min_data_ram_size;
    input M_DataRdy;
    // OUT
    output done_port;
    output [BITSIZE_out1-1:0] out1;
    output Mout_oe_ram;
    output Mout_we_ram;
    output [BITSIZE_Mout_addr_ram-1:0] Mout_addr_ram;
    output [BITSIZE_Mout_Wdata_ram-1:0] Mout_Wdata_ram;
    output [BITSIZE_Mout_data_ram_size-1:0] Mout_data_ram_size;
    wire    [BITSIZE_in2-1:0] tmp_addr;

    assign tmp_addr = in2;
    assign Mout_addr_ram = (sel_LOAD || sel_STORE) ? tmp_addr : Min_addr_ram;
    assign Mout_oe_ram = sel_LOAD ? 1'b1 : Min_oe_ram;
    assign Mout_we_ram = sel_STORE ? 1'b1 : Min_we_ram;
    assign out1 = M_Rdata_ram[BITSIZE_out1-1:0];
    assign Mout_Wdata_ram = sel_STORE ? in1 : Min_Wdata_ram;
    assign Mout_data_ram_size = sel_STORE || sel_LOAD ? in3[BITSIZE_in3-1:0] : Min_data_ram_size;
    assign done_port = M_DataRdy && (sel_STORE || sel_LOAD);
    // Add assertion here
    // psl default clock = (posedge clock);
    // psl ERROR_Min_we_ram_Min_oe_ram: assert never {Min_we_ram && Min_oe_ram};
    // psl ERROR_LOAD_Min_oe_ram: assert never {sel_LOAD && Min_oe_ram};
    // psl ERROR_STORE_Min_we_ram: assert never {sel_STORE && Min_we_ram};
    // psl ERROR_STORE_LOAD: assert never {sel_STORE && sel_LOAD};
    // psl ERROR_wrong_address: assert never {(sel_STORE || sel_LOAD) && tmp_addr == 0};
endmodule

// This component is part of the BAMBU/PANDA IP LIBRARY
// Copyright (C) 2004-2014 Politecnico di Milano
// Author(s): Fabrizio Ferrandi <fabrizio.ferrandi@xxxx>
// License: PANDA_GPLv3
`timescale 1ns / 1ps
module plus_expr_FU(in1, in2, out1);
    parameter BITSIZE_in1=1, BITSIZE_in2=1, BITSIZE_out1=1;
    // IN
    input signed [BITSIZE_in1-1:0] in1;
    input signed [BITSIZE_in2-1:0] in2;
    // OUT
    output signed [BITSIZE_out1-1:0] out1;
    assign out1 = in1 + in2;
endmodule

// This component is part of the BAMBU/PANDA IP LIBRARY
// Copyright (C) 2004-2014 Politecnico di Milano
// Author(s): Fabrizio Ferrandi <fabrizio.ferrandi@xxxx>
// License: PANDA_GPLv3
`timescale 1ns / 1ps
module lshift_expr_FU(in1, in2, out1);
    parameter BITSIZE_in1=1, BITSIZE_in2=1, BITSIZE_out1=1, PRECISION=32;
    // IN
    input signed [BITSIZE_in1-1:0] in1;
    input [BITSIZE_in2-1:0] in2;
    // OUT
    output signed [BITSIZE_out1-1:0] out1;
    `ifndef __ICARUS__
        function integer log2;
             input integer value;
             integer temp_value;
            begin
                temp_value = value-1;
                for (log2=0; temp_value>0; log2=log2+1)
                    temp_value = temp_value>>1;
            end
        endfunction
    `endif
    `ifdef __ICARUS__
        parameter arg2_bitsize = $clog2(PRECISION);
    `else
        parameter arg2_bitsize = log2(PRECISION);
    `endif
    assign out1 = in1 <<< in2[arg2_bitsize-1:0];
endmodule

// This component is part of the BAMBU/PANDA IP LIBRARY
// Copyright (C) 2004-2014 Politecnico di Milano
// Author(s): Fabrizio Ferrandi <fabrizio.ferrandi@xxxx>
// License: PANDA_GPLv3
`timescale 1ns / 1ps
module mult_expr_FU(clock, in1, in2, out1);
    parameter BITSIZE_in1=1, BITSIZE_in2=1, BITSIZE_out1=1, PIPE_PARAMETER=0;
    // IN
    input clock;
    input signed [BITSIZE_in1-1:0] in1;
    input signed [BITSIZE_in2-1:0] in2;
    // OUT
    output signed [BITSIZE_out1-1:0] out1;
    generate
        if(PIPE_PARAMETER==1)
        begin
            reg signed [BITSIZE_in1-1:0] in1_in;
            reg signed [BITSIZE_in2-1:0] in2_in;
            assign out1 = in1_in * in2_in;
            always @(posedge clock)
            begin
                in1_in <= in1;
                in2_in <= in2;
            end
        end
        else if(PIPE_PARAMETER>1)
        begin
            reg signed [BITSIZE_in1-1:0] in1_in;
            reg signed [BITSIZE_in2-1:0] in2_in;
            wire signed [BITSIZE_out1-1:0] mult_res;
            reg signed [BITSIZE_out1-1:0] mul [PIPE_PARAMETER-2:0];
            integer i;
            assign mult_res = in1_in * in2_in;
            always @(posedge clock)
            begin
                in1_in <= in1;
                in2_in <= in2;
                mul[PIPE_PARAMETER-2] <= mult_res;
                for (i=0; i<PIPE_PARAMETER-2; i=i+1)
                    mul[i] <= mul[i+1];
            end
            assign out1 = mul[0];
        end
        else
        begin
            assign out1 = in1 * in2;
        end
    endgenerate
endmodule

// This component is part of the BAMBU/PANDA IP LIBRARY
// Copyright (C) 2013-2014 Politecnico di Milano
// Author(s): Fabrizio Ferrandi <fabrizio.ferrandi@xxxx>
// License: PANDA_GPLv3
`timescale 1ns / 1ps
module bus_merger(in1, out1);
    parameter BITSIZE_in1=1, PORTSIZE_in1=2, BITSIZE_out1=1;
    // IN
    input [(PORTSIZE_in1*BITSIZE_in1)+(-1):0] in1;
    // OUT
    output [BITSIZE_out1-1:0] out1;
    function [BITSIZE_out1-1:0] merge;
        input [BITSIZE_in1*PORTSIZE_in1-1:0] m;
        reg [BITSIZE_out1-1:0] res;
        integer i1;
    begin
        res={BITSIZE_in1{1'b0}};
        for(i1 = 0; i1 < PORTSIZE_in1; i1 = i1 + 1)
        begin
            res = res | m[i1*BITSIZE_in1 +:BITSIZE_in1];
        end
        merge = res;
    end
    endfunction

    assign out1 = merge(in1);
endmodule

// This component is part of the BAMBU/PANDA IP LIBRARY
// Copyright (C) 2004-2014 Politecnico di Milano
// Author(s): Fabrizio Ferrandi <fabrizio.ferrandi@xxxx>
// License: PANDA_GPLv3
`timescale 1ns / 1ps
module IUdata_converter_FU(in1, out1);
    parameter BITSIZE_in1=1, BITSIZE_out1=1;
    // IN
    input signed [BITSIZE_in1-1:0] in1;
    // OUT
    output [BITSIZE_out1-1:0] out1;
    generate
    if (BITSIZE_out1 <= BITSIZE_in1)
    begin
        assign out1 = in1[BITSIZE_out1-1:0];
    end
    else
    begin
        assign out1 = {{(BITSIZE_out1-BITSIZE_in1){in1[BITSIZE_in1-1]}},in1};
    end
    endgenerate
endmodule

// This component is part of the BAMBU/PANDA IP LIBRARY
// Copyright (C) 2004-2014 Politecnico di Milano
// Author(s): Fabrizio Ferrandi <fabrizio.ferrandi@xxxx>, Christian Pilato <christian.pilato@xxxx>
// License: PANDA_GPLv3
`timescale 1ns / 1ps
module MUX_GATE(sel, in1, in2, out1);
    parameter BITSIZE_in1=1, BITSIZE_in2=1, BITSIZE_out1=1;
    // IN
    input sel;
    input [BITSIZE_in1-1:0] in1;
    input [BITSIZE_in2-1:0] in2;
    // OUT
    output [BITSIZE_out1-1:0] out1;
    assign out1 = sel ? in1 : in2;
endmodule

// Datapath RTL descrition for simple_mult_test
// Copyright (C) 2004-2014 Politecnico di Milano
// Author(s): module automatically generated by bambu
// License: PANDA_GPLv3
`timescale 1ns / 1ps
module datapath_simple_mult_test(clock, reset, in_port_a, in_port_b, in_port_res, M_Rdata_ram, M_DataRdy, Min_oe_ram, Min_we_ram, Min_addr_ram, Min_Wdata_ram, Min_data_ram_size, Mout_oe_ram, Mout_we_ram, Mout_addr_ram, Mout_Wdata_ram, Mout_data_ram_size, wrenable_reg_1, wrenable_reg_2, wrenable_reg_3, fuselector_MEMORY_CTRL_4_i0_LOAD, fuselector_MEMORY_CTRL_4_i0_STORE, selector_MUX_12_mult_expr_FU_64_64_64_5_8_i1_0_0_0, selector_MUX_13_mult_expr_FU_64_64_64_5_8_i1_1_0_0, selector_IN_UNBOUNDED_simple_mult_test_90450_90479, wrenable_reg_0, OUT_UNBOUNDED_simple_mult_test_90450_90479);
    // IN
    input clock;
    input reset;
    input signed [63:0] in_port_a;
    input signed [63:0] in_port_b;
    input [31:0] in_port_res;
    input [63:0] M_Rdata_ram;
    input M_DataRdy;
    input Min_oe_ram;
    input Min_we_ram;
    input [31:0] Min_addr_ram;
    input [63:0] Min_Wdata_ram;
    input [6:0] Min_data_ram_size;
    input wrenable_reg_1;
    input wrenable_reg_2;
    input wrenable_reg_3;
    input fuselector_MEMORY_CTRL_4_i0_LOAD;
    input fuselector_MEMORY_CTRL_4_i0_STORE;
    input selector_MUX_12_mult_expr_FU_64_64_64_5_8_i1_0_0_0;
    input selector_MUX_13_mult_expr_FU_64_64_64_5_8_i1_1_0_0;
    input selector_IN_UNBOUNDED_simple_mult_test_90450_90479;
    input wrenable_reg_0;
    // OUT
    output Mout_oe_ram;
    output Mout_we_ram;
    output [31:0] Mout_addr_ram;
    output [63:0] Mout_Wdata_ram;
    output [6:0] Mout_data_ram_size;
    output OUT_UNBOUNDED_simple_mult_test_90450_90479;
    // Component and signal declarations
    wire signed [63:0] out_ASSIGN_SIGNED_FU_2_i0_fu_simple_mult_test_90450_90474;
    wire [63:0] out_MUX_12_mult_expr_FU_64_64_64_5_8_i1_0_0_0;
    wire [63:0] out_MUX_13_mult_expr_FU_64_64_64_5_8_i1_1_0_0;
    wire [63:0] out_const_0;
    wire [6:0] out_const_1;
    wire [63:0] out_iu_conv_conn_obj_0_IUdata_converter_FU_iu_conv_0;
    wire signed [63:0] out_lshift_expr_FU_64_0_64_6_i0_fu_simple_mult_test_90450_90512;
    wire signed [63:0] out_mult_expr_FU_64_64_64_5_8_i0_fu_simple_mult_test_90450_90475;
    wire signed [63:0] out_mult_expr_FU_64_64_64_5_8_i1_mult_expr_FU_64_64_64_5_8_i1;
    wire signed [63:0] out_plus_expr_FU_64_0_64_7_i0_fu_simple_mult_test_90450_90477;
    wire signed [63:0] out_plus_expr_FU_64_64_64_5_i0_fu_simple_mult_test_90450_90515;
    wire [63:0] out_reg_0_reg_0;
    wire [63:0] out_reg_1_reg_1;
    wire [63:0] out_reg_2_reg_2;
    wire [63:0] out_reg_3_reg_3;
    wire s_done_fu_simple_mult_test_90450_90479;
    wire [63:0] sig_in_bus_mergerMout_Wdata_ram10;
    wire [31:0] sig_in_bus_mergerMout_addr_ram20;
    wire [6:0] sig_in_bus_mergerMout_data_ram_size00;
    wire sig_in_bus_mergerMout_oe_ram40;
    wire sig_in_bus_mergerMout_we_ram30;
    wire [63:0] sig_out_bus_mergerMout_Wdata_ram1;
    wire [31:0] sig_out_bus_mergerMout_addr_ram2;
    wire [6:0] sig_out_bus_mergerMout_data_ram_size0;
    wire sig_out_bus_mergerMout_oe_ram4;
    wire sig_out_bus_mergerMout_we_ram3;

    IUdata_converter_FU #(.BITSIZE_in1(64), .BITSIZE_out1(64)) IUdata_converter_FU_iu_conv_0 (.out1(out_iu_conv_conn_obj_0_IUdata_converter_FU_iu_conv_0), .in1(out_reg_3_reg_3));
    MUX_GATE #(.BITSIZE_in1(64), .BITSIZE_in2(64), .BITSIZE_out1(64)) MUX_12_mult_expr_FU_64_64_64_5_8_i1_0_0_0 (.out1(out_MUX_12_mult_expr_FU_64_64_64_5_8_i1_0_0_0), .sel(selector_MUX_12_mult_expr_FU_64_64_64_5_8_i1_0_0_0), .in1(out_reg_3_reg_3), .in2(out_reg_2_reg_2));
    MUX_GATE #(.BITSIZE_in1(64), .BITSIZE_in2(64), .BITSIZE_out1(64)) MUX_13_mult_expr_FU_64_64_64_5_8_i1_1_0_0 (.out1(out_MUX_13_mult_expr_FU_64_64_64_5_8_i1_1_0_0), .sel(selector_MUX_13_mult_expr_FU_64_64_64_5_8_i1_1_0_0), .in1(out_reg_0_reg_0), .in2(out_reg_1_reg_1));
    bus_merger #(.BITSIZE_in1(64), .PORTSIZE_in1(1), .BITSIZE_out1(64)) bus_mergerMout_Wdata_ram1 (.out1(sig_out_bus_mergerMout_Wdata_ram1), .in1({sig_in_bus_mergerMout_Wdata_ram10}));
    bus_merger #(.BITSIZE_in1(32), .PORTSIZE_in1(1), .BITSIZE_out1(32)) bus_mergerMout_addr_ram2 (.out1(sig_out_bus_mergerMout_addr_ram2), .in1({sig_in_bus_mergerMout_addr_ram20}));
    bus_merger #(.BITSIZE_in1(7), .PORTSIZE_in1(1), .BITSIZE_out1(7)) bus_mergerMout_data_ram_size0 (.out1(sig_out_bus_mergerMout_data_ram_size0), .in1({sig_in_bus_mergerMout_data_ram_size00}));
    bus_merger #(.BITSIZE_in1(1), .PORTSIZE_in1(1), .BITSIZE_out1(1)) bus_mergerMout_oe_ram4 (.out1(sig_out_bus_mergerMout_oe_ram4), .in1({sig_in_bus_mergerMout_oe_ram40}));
    bus_merger #(.BITSIZE_in1(1), .PORTSIZE_in1(1), .BITSIZE_out1(1)) bus_mergerMout_we_ram3 (.out1(sig_out_bus_mergerMout_we_ram3), .in1({sig_in_bus_mergerMout_we_ram30}));
    constant_value #(.BITSIZE_out1(64), .value(64'b0000000000000000000000000000000000000000000000000000000000000001)) const_0 (.out1(out_const_0));
    constant_value #(.BITSIZE_out1(7), .value(7'b1000000)) const_1 (.out1(out_const_1));
    ASSIGN_SIGNED_FU #(.BITSIZE_in1(64), .BITSIZE_out1(64)) fu_simple_mult_test_90450_90474 (.out1(out_ASSIGN_SIGNED_FU_2_i0_fu_simple_mult_test_90450_90474), .in1(out_plus_expr_FU_64_64_64_5_i0_fu_simple_mult_test_90450_90515));
    mult_expr_FU #(.BITSIZE_in1(64), .BITSIZE_in2(64), .BITSIZE_out1(64), .PIPE_PARAMETER(5)) fu_simple_mult_test_90450_90475 (.out1(out_mult_expr_FU_64_64_64_5_8_i0_fu_simple_mult_test_90450_90475), .clock(clock), .in1(in_port_a), .in2(in_port_a));
    plus_expr_FU #(.BITSIZE_in1(64), .BITSIZE_in2(64), .BITSIZE_out1(64)) fu_simple_mult_test_90450_90477 (.out1(out_plus_expr_FU_64_0_64_7_i0_fu_simple_mult_test_90450_90477), .in1(in_port_b), .in2(out_const_0));
    MEMORY_CTRL #(.BITSIZE_in1(64), .BITSIZE_in2(32), .BITSIZE_in3(7), .BITSIZE_out1(1), .BITSIZE_Min_addr_ram(32), .BITSIZE_Mout_addr_ram(32), .BITSIZE_M_Rdata_ram(64), .BITSIZE_Min_Wdata_ram(64), .BITSIZE_Mout_Wdata_ram(64), .BITSIZE_Min_data_ram_size(7), .BITSIZE_Mout_data_ram_size(7)) fu_simple_mult_test_90450_90479 (.done_port(s_done_fu_simple_mult_test_90450_90479), .Mout_oe_ram(sig_in_bus_mergerMout_oe_ram40), .Mout_we_ram(sig_in_bus_mergerMout_we_ram30), .Mout_addr_ram(sig_in_bus_mergerMout_addr_ram20), .Mout_Wdata_ram(sig_in_bus_mergerMout_Wdata_ram10), .Mout_data_ram_size(sig_in_bus_mergerMout_data_ram_size00), .clock(clock), .start_port(selector_IN_UNBOUNDED_simple_mult_test_90450_90479), .in1(out_iu_conv_conn_obj_0_IUdata_converter_FU_iu_conv_0), .in2(in_port_res), .in3(out_const_1), .sel_LOAD(fuselector_MEMORY_CTRL_4_i0_LOAD), .sel_STORE(fuselector_MEMORY_CTRL_4_i0_STORE), .Min_oe_ram(Min_oe_ram), .Min_we_ram(Min_we_ram), .Min_addr_ram(Min_addr_ram), .M_Rdata_ram(M_Rdata_ram), .Min_Wdata_ram(Min_Wdata_ram), .Min_data_ram_size(Min_data_ram_size), .M_DataRdy(M_DataRdy));
    lshift_expr_FU #(.BITSIZE_in1(64), .BITSIZE_in2(64), .BITSIZE_out1(64), .PRECISION(64)) fu_simple_mult_test_90450_90512 (.out1(out_lshift_expr_FU_64_0_64_6_i0_fu_simple_mult_test_90450_90512), .in1(in_port_b), .in2(out_const_0));
    plus_expr_FU #(.BITSIZE_in1(64), .BITSIZE_in2(64), .BITSIZE_out1(64)) fu_simple_mult_test_90450_90515 (.out1(out_plus_expr_FU_64_64_64_5_i0_fu_simple_mult_test_90450_90515), .in1(out_lshift_expr_FU_64_0_64_6_i0_fu_simple_mult_test_90450_90512), .in2(in_port_b));
    mult_expr_FU #(.BITSIZE_in1(64), .BITSIZE_in2(64), .BITSIZE_out1(64), .PIPE_PARAMETER(5)) mult_expr_FU_64_64_64_5_8_i1 (.out1(out_mult_expr_FU_64_64_64_5_8_i1_mult_expr_FU_64_64_64_5_8_i1), .clock(clock), .in1(out_MUX_12_mult_expr_FU_64_64_64_5_8_i1_0_0_0), .in2(out_MUX_13_mult_expr_FU_64_64_64_5_8_i1_1_0_0));
    register_SE #(.BITSIZE_in1(64), .BITSIZE_out1(64)) reg_0 (.out1(out_reg_0_reg_0), .clock(clock), .reset(reset), .in1(out_ASSIGN_SIGNED_FU_2_i0_fu_simple_mult_test_90450_90474), .wenable(wrenable_reg_0));
    register_SE #(.BITSIZE_in1(64), .BITSIZE_out1(64)) reg_1 (.out1(out_reg_1_reg_1), .clock(clock), .reset(reset), .in1(out_plus_expr_FU_64_0_64_7_i0_fu_simple_mult_test_90450_90477), .wenable(wrenable_reg_1));
    register_STD #(.BITSIZE_in1(64), .BITSIZE_out1(64)) reg_2 (.out1(out_reg_2_reg_2), .clock(clock), .reset(reset), .in1(out_mult_expr_FU_64_64_64_5_8_i0_fu_simple_mult_test_90450_90475), .wenable(wrenable_reg_2));
    register_SE #(.BITSIZE_in1(64), .BITSIZE_out1(64)) reg_3 (.out1(out_reg_3_reg_3), .clock(clock), .reset(reset), .in1(out_mult_expr_FU_64_64_64_5_8_i1_mult_expr_FU_64_64_64_5_8_i1), .wenable(wrenable_reg_3));
    // io-signal post fix
    assign Mout_oe_ram = sig_out_bus_mergerMout_oe_ram4;
    assign Mout_we_ram = sig_out_bus_mergerMout_we_ram3;
    assign Mout_addr_ram = sig_out_bus_mergerMout_addr_ram2;
    assign Mout_Wdata_ram = sig_out_bus_mergerMout_Wdata_ram1;
    assign Mout_data_ram_size = sig_out_bus_mergerMout_data_ram_size0;
    assign OUT_UNBOUNDED_simple_mult_test_90450_90479 = s_done_fu_simple_mult_test_90450_90479;

endmodule

// FSM based controller descrition for simple_mult_test
// Copyright (C) 2004-2014 Politecnico di Milano
// Author(s): module automatically generated by bambu
// License: PANDA_GPLv3
`timescale 1ns / 1ps
module controller_simple_mult_test(done_port, wrenable_reg_1, wrenable_reg_2, wrenable_reg_3, fuselector_MEMORY_CTRL_4_i0_LOAD, fuselector_MEMORY_CTRL_4_i0_STORE, selector_MUX_12_mult_expr_FU_64_64_64_5_8_i1_0_0_0, selector_MUX_13_mult_expr_FU_64_64_64_5_8_i1_1_0_0, selector_IN_UNBOUNDED_simple_mult_test_90450_90479, wrenable_reg_0, OUT_UNBOUNDED_simple_mult_test_90450_90479, clock, reset, start_port);
    // IN
    input OUT_UNBOUNDED_simple_mult_test_90450_90479;
    input clock;
    input reset;
    input start_port;
    // OUT
    output done_port;
    output wrenable_reg_1;
    output wrenable_reg_2;
    output wrenable_reg_3;
    output fuselector_MEMORY_CTRL_4_i0_LOAD;
    output fuselector_MEMORY_CTRL_4_i0_STORE;
    output selector_MUX_12_mult_expr_FU_64_64_64_5_8_i1_0_0_0;
    output selector_MUX_13_mult_expr_FU_64_64_64_5_8_i1_1_0_0;
    output selector_IN_UNBOUNDED_simple_mult_test_90450_90479;
    output wrenable_reg_0;
    parameter [4:0] S_0 = 5'd0,
        S_1 = 5'd1,
        S_2 = 5'd2,
        S_3 = 5'd3,
        S_4 = 5'd4,
        S_5 = 5'd5,
        S_6 = 5'd6,
        S_7 = 5'd7,
        S_8 = 5'd8,
        S_9 = 5'd9,
        S_10 = 5'd10,
        S_11 = 5'd11,
        S_12 = 5'd12,
        S_13 = 5'd13,
        S_14 = 5'd14,
        S_15 = 5'd15,
        S_16 = 5'd16,
        S_17 = 5'd17,
        S_18 = 5'd18,
        S_19 = 5'd19,
        S_20 = 5'd20;
    reg [4:0] _present_state, _next_state;
    reg done_port;
    reg wrenable_reg_1;
    reg wrenable_reg_2;
    reg wrenable_reg_3;
    reg fuselector_MEMORY_CTRL_4_i0_LOAD;
    reg fuselector_MEMORY_CTRL_4_i0_STORE;
    reg selector_MUX_12_mult_expr_FU_64_64_64_5_8_i1_0_0_0;
    reg selector_MUX_13_mult_expr_FU_64_64_64_5_8_i1_1_0_0;
    reg selector_IN_UNBOUNDED_simple_mult_test_90450_90479;
    reg wrenable_reg_0;

    always @(posedge clock)
        if (!reset) _present_state <= S_0;
        else _present_state <= _next_state;

    always @(_present_state or OUT_UNBOUNDED_simple_mult_test_90450_90479 or start_port)
    begin
        _next_state = S_0;
        done_port = 1'b0;
        wrenable_reg_1 = 1'b0;
        wrenable_reg_2 = 1'b0;
        wrenable_reg_3 = 1'b0;
        fuselector_MEMORY_CTRL_4_i0_LOAD = 1'b0;
        fuselector_MEMORY_CTRL_4_i0_STORE = 1'b0;
        selector_MUX_12_mult_expr_FU_64_64_64_5_8_i1_0_0_0 = 1'b0;
        selector_MUX_13_mult_expr_FU_64_64_64_5_8_i1_1_0_0 = 1'b0;
        selector_IN_UNBOUNDED_simple_mult_test_90450_90479 = 1'b0;
        wrenable_reg_0 = 1'b0;
        case (_present_state)
            S_0 :
                if(~start_port)
                begin
                    _next_state = S_0;
                end
                else
                begin
                    wrenable_reg_1 = 1'b1;
                    wrenable_reg_0 = 1'b1;
                    _next_state = S_1;
                end
            S_1 :
                begin
                    _next_state = S_2;
                end
            S_2 :
                begin
                    _next_state = S_3;
                end
            S_3 :
                begin
                    _next_state = S_4;
                end
            S_4 :
                begin
                    _next_state = S_5;
                end
            S_5 :
                begin
                    wrenable_reg_2 = 1'b1;
                    _next_state = S_6;
                end
            S_6 :
                begin
                    selector_MUX_13_mult_expr_FU_64_64_64_5_8_i1_1_0_0 = 1'b1;
                    _next_state = S_7;
                end
            S_7 :
                begin
                    _next_state = S_8;
                end
            S_8 :
                begin
                    _next_state = S_9;
                end
            S_9 :
                begin
                    _next_state = S_10;
                end
            S_10 :
                begin
                    _next_state = S_11;
                end
            S_11 :
                begin
                    wrenable_reg_3 = 1'b1;
                    _next_state = S_12;
                end
            S_12 :
                begin
                    selector_MUX_12_mult_expr_FU_64_64_64_5_8_i1_0_0_0 = 1'b1;
                    _next_state = S_13;
                end
            S_13 :
                begin
                    _next_state = S_14;
                end
            S_14 :
                begin
                    _next_state = S_15;
                end
            S_15 :
                begin
                    _next_state = S_16;
                end
            S_16 :
                begin
                    _next_state = S_17;
                end
            S_17 :
                begin
                    wrenable_reg_3 = 1'b1;
                    _next_state = S_18;
                end
            S_18 :
                begin
                    fuselector_MEMORY_CTRL_4_i0_STORE = 1'b1;
                    selector_IN_UNBOUNDED_simple_mult_test_90450_90479 = 1'b1;
                    if (OUT_UNBOUNDED_simple_mult_test_90450_90479 == 1'b0)
                        begin
                            _next_state = S_19;
                        end
                    else
                        begin
                            _next_state = S_20;
                        end
                end
            S_19 :
                begin
                    fuselector_MEMORY_CTRL_4_i0_STORE = 1'b1;
                    if (OUT_UNBOUNDED_simple_mult_test_90450_90479 == 1'b0)
                        begin
                            _next_state = S_19;
                        end
                    else
                        begin
                            _next_state = S_20;
                        end
                end
            S_20 :
                begin
                    _next_state = S_0;
                    done_port = 1'b1;
                end
            default :
                begin
                    done_port = 1'b0;
                    wrenable_reg_1 = 1'b0;
                    wrenable_reg_2 = 1'b0;
                    wrenable_reg_3 = 1'b0;
                    fuselector_MEMORY_CTRL_4_i0_LOAD = 1'b0;
                    fuselector_MEMORY_CTRL_4_i0_STORE = 1'b0;
                    selector_MUX_12_mult_expr_FU_64_64_64_5_8_i1_0_0_0 = 1'b0;
                    selector_MUX_13_mult_expr_FU_64_64_64_5_8_i1_1_0_0 = 1'b0;
                    selector_IN_UNBOUNDED_simple_mult_test_90450_90479 = 1'b0;
                    wrenable_reg_0 = 1'b0;
                end
        endcase
    end
endmodule

// Top circuit for simple_mult_test
// Copyright (C) 2004-2014 Politecnico di Milano
// Author(s): module automatically generated by bambu
// License: PANDA_GPLv3
`timescale 1ns / 1ps
module simple_mult_test(clock, reset, start_port, done_port, a, b, res, M_Rdata_ram, M_DataRdy, Min_oe_ram, Min_we_ram, Min_addr_ram, Min_Wdata_ram, Min_data_ram_size, Mout_oe_ram, Mout_we_ram, Mout_addr_ram, Mout_Wdata_ram, Mout_data_ram_size);
    // IN
    input clock;
    input reset;
    input start_port;
    input signed [63:0] a;
    input signed [63:0] b;
    input [31:0] res;
    input [63:0] M_Rdata_ram;
    input M_DataRdy;
    input Min_oe_ram;
    input Min_we_ram;
    input [31:0] Min_addr_ram;
    input [63:0] Min_Wdata_ram;
    input [6:0] Min_data_ram_size;
    // OUT
    output done_port;
    output Mout_oe_ram;
    output Mout_we_ram;
    output [31:0] Mout_addr_ram;
    output [63:0] Mout_Wdata_ram;
    output [6:0] Mout_data_ram_size;
    // Component and signal declarations
    wire OUT_UNBOUNDED_simple_mult_test_90450_90479;
    wire fuselector_MEMORY_CTRL_4_i0_LOAD;
    wire fuselector_MEMORY_CTRL_4_i0_STORE;
    wire selector_IN_UNBOUNDED_simple_mult_test_90450_90479;
    wire selector_MUX_12_mult_expr_FU_64_64_64_5_8_i1_0_0_0;
    wire selector_MUX_13_mult_expr_FU_64_64_64_5_8_i1_1_0_0;
    wire wrenable_reg_0;
    wire wrenable_reg_1;
    wire wrenable_reg_2;
    wire wrenable_reg_3;

    controller_simple_mult_test Controller_i (.done_port(done_port), .wrenable_reg_1(wrenable_reg_1), .wrenable_reg_2(wrenable_reg_2), .wrenable_reg_3(wrenable_reg_3), .fuselector_MEMORY_CTRL_4_i0_LOAD(fuselector_MEMORY_CTRL_4_i0_LOAD), .fuselector_MEMORY_CTRL_4_i0_STORE(fuselector_MEMORY_CTRL_4_i0_STORE), .selector_MUX_12_mult_expr_FU_64_64_64_5_8_i1_0_0_0(selector_MUX_12_mult_expr_FU_64_64_64_5_8_i1_0_0_0), .selector_MUX_13_mult_expr_FU_64_64_64_5_8_i1_1_0_0(selector_MUX_13_mult_expr_FU_64_64_64_5_8_i1_1_0_0), .selector_IN_UNBOUNDED_simple_mult_test_90450_90479(selector_IN_UNBOUNDED_simple_mult_test_90450_90479), .wrenable_reg_0(wrenable_reg_0), .OUT_UNBOUNDED_simple_mult_test_90450_90479(OUT_UNBOUNDED_simple_mult_test_90450_90479), .clock(clock), .reset(reset), .start_port(start_port));
    datapath_simple_mult_test Datapath_i (.Mout_oe_ram(Mout_oe_ram), .Mout_we_ram(Mout_we_ram), .Mout_addr_ram(Mout_addr_ram), .Mout_Wdata_ram(Mout_Wdata_ram), .Mout_data_ram_size(Mout_data_ram_size), .OUT_UNBOUNDED_simple_mult_test_90450_90479(OUT_UNBOUNDED_simple_mult_test_90450_90479), .clock(clock), .reset(reset), .in_port_a(a), .in_port_b(b), .in_port_res(res), .M_Rdata_ram(M_Rdata_ram), .M_DataRdy(M_DataRdy), .Min_oe_ram(Min_oe_ram), .Min_we_ram(Min_we_ram), .Min_addr_ram(Min_addr_ram), .Min_Wdata_ram(Min_Wdata_ram), .Min_data_ram_size(Min_data_ram_size), .wrenable_reg_1(wrenable_reg_1), .wrenable_reg_2(wrenable_reg_2), .wrenable_reg_3(wrenable_reg_3), .fuselector_MEMORY_CTRL_4_i0_LOAD(fuselector_MEMORY_CTRL_4_i0_LOAD), .fuselector_MEMORY_CTRL_4_i0_STORE(fuselector_MEMORY_CTRL_4_i0_STORE), .selector_MUX_12_mult_expr_FU_64_64_64_5_8_i1_0_0_0(selector_MUX_12_mult_expr_FU_64_64_64_5_8_i1_0_0_0), .selector_MUX_13_mult_expr_FU_64_64_64_5_8_i1_1_0_0(selector_MUX_13_mult_expr_FU_64_64_64_5_8_i1_1_0_0), .selector_IN_UNBOUNDED_simple_mult_test_90450_90479(selector_IN_UNBOUNDED_simple_mult_test_90450_90479), .wrenable_reg_0(wrenable_reg_0));

endmodule

// Minimal interface for top component: simple_mult_test
// Copyright (C) 2004-2014 Politecnico di Milano
// Author(s): module automatically generated by bambu
// License: PANDA_GPLv3
`timescale 1ns / 1ps
module simple_mult_test_minimal_interface(clock, reset, start_port, a, b, res, M_Rdata_ram, M_DataRdy, done_port, Mout_oe_ram, Mout_we_ram, Mout_addr_ram, Mout_Wdata_ram, Mout_data_ram_size);
    // IN
    input clock;
    input reset;
    input start_port;
    input signed [63:0] a;
    input signed [63:0] b;
    input [31:0] res;
    input [63:0] M_Rdata_ram;
    input M_DataRdy;
    // OUT
    output done_port;
    output Mout_oe_ram;
    output Mout_we_ram;
    output [31:0] Mout_addr_ram;
    output [63:0] Mout_Wdata_ram;
    output [6:0] Mout_data_ram_size;
    // Component and signal declarations

    simple_mult_test simple_mult_test_i0 (.done_port(done_port), .Mout_oe_ram(Mout_oe_ram), .Mout_we_ram(Mout_we_ram), .Mout_addr_ram(Mout_addr_ram), .Mout_Wdata_ram(Mout_Wdata_ram), .Mout_data_ram_size(Mout_data_ram_size), .clock(clock), .reset(reset), .start_port(start_port), .a(a), .b(b), .res(res), .M_Rdata_ram(M_Rdata_ram), .M_DataRdy(M_DataRdy), .Min_oe_ram(1'b0), .Min_we_ram(1'b0), .Min_addr_ram(32'b00000000000000000000000000000000), .Min_Wdata_ram(64'b0000000000000000000000000000000000000000000000000000000000000000), .Min_data_ram_size(7'b0000000));

endmodule

from yosys.

cliffordwolf avatar cliffordwolf commented on August 17, 2024

First of all, thanks for the answer. You are right if you consider the module alone. What it is strange is the yosys behavior during the parsing of a more bigger example.

You are right. This is because yosys considers each module stand-alone before traversing the design hierarchy, while many other tools only consider the variations of the modules reachable from a given top module. I've now added this functionality to yosys. The following now works with the design you provided:

read_verilog -defer -D__ICARUS__ test.v
hierarchy -check -top simple_mult_test_minimal_interface

from yosys.

fabrizioferrandi avatar fabrizioferrandi commented on August 17, 2024

great it works!
Just few notes. Such kind of designs have been tested w.r.t. different simulators and RTL synthesis tools. So the impression is that the defer behavior should be the default one. Moreover, going in deep and checking the Verilog standard I've found this:

12.8 Elaboration
Elaboration
is the process that occurs between parsing and simulation. It binds modules to module
instances, builds the model hierarchy, computes parameter values, resolves hierarchical names, 
establishes net connectivity, and prepares all of this for simulation. With the addition of generate 
constructs, the order in which these tasks occur becomes significant.
...

So, my understanding is that parsing (read_verilog) should postpone parameter evaluation to the elaboration phase (hierarchy -check -top simple_mult_test_minimal_interface) as in the -defer case.
Anyway, thanks for adding the -defer option. In the next days I'll add a backend towards yosys to the PandA framework.

from yosys.

cliffordwolf avatar cliffordwolf commented on August 17, 2024

For "just synthesis" I fully agree. However, there are many things you can do with yosys where there is no dedicated top module (when you would use "hierarchy" without the -top option or even use "hierarchy" not at all, maybe even not operate on verilog input). Up until now it never was a problem that Yosys by default also creates an RTLIL representation of all modules with their default parameter values.

I have not found anything in the Verilog standard that would state explicitly that the default values of parameters would need to yield a valid module, but I honestly find it strange to choose default values that would yield an invalid module.. ;)

Just FYI:

From the way Yosys works it needs to evaluate the RTLIL of all modules to figure out what the "top-level modules" (12.1.1 of the standard) of the design are, creating a chicken-egg problem. The standard states:

Top-level modules are modules that are included in the source text, but do not appear in any module instantiation statement, as described in 12.1.2. This applies even if the module instantiation appears in a generate block that is not itself instantiated (see 12.4). A model shall contain at least one top-level module.

The "even if the module instantiation appears in a generate block that is not itself instantiated" part is here so that tools can figure out what the top modules are just by looking at the AST without evaluating it. Yosy does not do that. It evaluates the AST for the default parameters and looks at the RTLIL instead. The advantage of this behavior is that modules can come from different front-ends that do not share the same AST representation, thus better de-coupling the frontends.

The disadvantage is that the parameters need reasonable default values.

The thing here is that "read_verilog" does not only parse Verilog, it also creates the RTLIL representation. Such as read_ilang and future frontends such as read_blif do. In certain cases the use of "hierarchy" is optional (but it is recommended to always use it unless you really know what you are doing). As such it does more than "read_verilog" does in synopsys design compiler or xilinx vivado, where the command really only does the parsing.

I think the -defer option is an ok solution for implementing Verilog synthesis flows. I wont make it the default behavior, because the behavior deviates from the way Yosys frontends usually behave.

I'm looking forward to the PandA backend for Yosys.

from yosys.

cliffordwolf avatar cliffordwolf commented on August 17, 2024

I've now added very basic support for function calls in parameters. It is just enough to make your log2 function work. So now this also works without -D__ICARUS__:

read_verilog -defer test.v
hierarchy -check -top simple_mult_test_minimal_interface

At the moment I do not aim at complete support for constant functions in Yosys, so don't stress it with artificial test cases. But if you encounter a case of a constant function that you actually need do not hesitate to open a new issue with a test case and I will look into it.

PS: I've added a link to PandA on the "Links" page on the Yosys Website.

from yosys.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.