PyHDI / Pyverilog

Python-based Hardware Design Processing Toolkit for Verilog HDL
Apache License 2.0
598 stars 168 forks source link

PyVerilog does not handle genvar and generate blocks #43

Open anandh1791 opened 5 years ago

anandh1791 commented 5 years ago

Hi Anandh,

Thank you! Now I successfully compiled your code by Icarus verilog. I found that some additional features must be implemented in Pyverilog. For instance, Pyverilog does not support automatic attribute of function definition.

Give me a little time to modify it ...

Thanks,

Shinya

On 2019/03/06 1:51, anandh krishnan wrote:

Hello Shinya san,

I am very sorry, but please add these two lines in your header file:

parameter P_FLOP_STRUCT_PARITY_ENB = 1'b0; parameter integer P_FLOP_STRUCT_PARITY_GRAN = 8;

Arrigato.

Thank you, Anandh

On Monday, March 4, 2019, 8:49:59 PM PST, Shinya TAKAMAEDA-YAMAZAKI <takamaeda@ist.hokudai.ac.jp mailto:takamaeda@ist.hokudai.ac.jp> wrote:

Hi Anandh,

Thanks for sharing your codes.

I still have a complication error on Icarus Verilog. Can you tell me the definitions of P_FLOP_STRUCT_PARITY_GRAN andP_FLOP_STRUCT_PARITY_ENB ? I could not find the definitions in your main code and header.

$ iverilog -tnull -Wall tmp.v tmp.v:29: error: Unable to bind parameter P_FLOP_STRUCT_PARITY_GRAN' inns_s_fifo' tmp.v:30: error: Unable to bind parameter P_FLOP_STRUCT_PARITY_GRAN' inns_s_fifo' tmp.v:32: error: Unable to bind parameter P_FLOP_STRUCT_PARITY_ENB' inns_s_fifo' tmp.v:34: error: Unable to bind parameter P_FLOP_STRUCT_PARITY_ENB' inns_s_fifo' tmp.v:268: error: Unable to bind parameter P_FLOP_STRUCT_PARITY_ENB' inns_s_fifo' tmp.v:268: error: Cannot evaluate genvar conditional expression: P_FLOP_STRUCT_PARITY_ENB tmp.v:268: error: Unable to bind parameter P_FLOP_STRUCT_PARITY_ENB' inns_s_fifo' tmp.v:268: error: Cannot evaluate genvar conditional expression: P_FLOP_STRUCT_PARITY_ENB 8 error(s) during elaboration.

Thanks,

Shinya

On 2019/03/05 13:32, anandh krishnan wrote:

Hello Shinya san,

Please find the header attached.

Thanks, Anandh

On Monday, March 4, 2019, 7:03:59 PM PST, Shinya TAKAMAEDA-YAMAZAKI <takamaeda@ist.hokudai.ac.jp mailto:takamaeda@ist.hokudai.ac.jp <mailto:takamaeda@ist.hokudai.ac.jp mailto:takamaeda@ist.hokudai.ac.jp>> wrote:

Hi Anandh,

I'm sorry for the very late response, again.

I tried to read your code by Veriloggen, but I could not do that because I don't have "ns_common_func.vh". Can you share your header file?

Best regards,

Shinya

On 2019/02/09 5:22, anandh krishnan wrote:

Shinya Sama,

Arrigato Gozaimasu!

I have a fatal error from veriloggen's veriloggen/verilog/from_verilog.py in the routine visit_GenerateStatement:

"Only generate-for and generate-if statements are supported."

This is because of a "genvar" within my generate block. Please advise what I need to do. My testcase is:

module ns_s_fifo( // Outputs rd_data, rd_data_valid, occupancy_cnt, fifo_full, perr, // Inputs clk, clk_g, reset, wr_enb, wr_data, wr_parity, rd_enb, perr_inj );

`include "ns_common_func.vh"

localparam P_FPGA_INFER_RAM        = 1'b0;
parameter P_FIFO_D_WIDTH           = 32;
parameter P_FIFO_DEPTH             = 4;
parameter P_REG_OUT                = 1'b0;
parameter P_OCCUPANCY_CNT          = 1'b0;

parameter P_EXT_PARITY_GEN = 1'b1;
localparam P_DATA_WIDTH_REMAINDER   = P_FIFO_D_WIDTH % P_FLOP_STRUCT_PARITY_GRAN ;
localparam P_DATA_PAD_BITS          = (P_DATA_WIDTH_REMAINDER==0) ? 0 : P_FLOP_STRUCT_PARITY_GRAN - P_DATA_WIDTH_REMAINDER;
localparam P_DATA_PLUS_PAD_WIDTH    = P_FIFO_D_WIDTH + P_DATA_PAD_BITS ;
localparam P_EXT_PARITY_BITS        = ((P_EXT_PARITY_GEN == 1'b0) | (P_FLOP_STRUCT_PARITY_ENB == 1'b0)) ? 1 :
                                       P_DATA_PLUS_PAD_WIDTH / P_FLOP_STRUCT_PARITY_GRAN ;
localparam P_NUM_PARITY_BITS        = P_FLOP_STRUCT_PARITY_ENB ? P_DATA_PLUS_PAD_WIDTH / P_FLOP_STRUCT_PARITY_GRAN : 1 ;

localparam LP_ONE = 1;
localparam P_FIFO_DEPTH_MOD = ((P_FIFO_DEPTH <= 2) & P_REG_OUT) ? 2 :
                              ((P_FIFO_DEPTH >= 3) & P_REG_OUT) ?    (P_FIFO_DEPTH-1) :
                               (P_FIFO_DEPTH <= 1)              ? 2 : P_FIFO_DEPTH ;

localparam P_FIFO_A_WIDTH = (P_FIFO_DEPTH_MOD == 1) ? 1 : clogb2(P_FIFO_DEPTH_MOD) ;
localparam P_OCCU_CNTR_WIDTH = clog2(P_FIFO_DEPTH+1);
localparam [P_FIFO_A_WIDTH-1:0] P_FIFO_DEPTH_MIN_1 = P_FIFO_DEPTH_MOD-1 ;

input                          clk;
input                          clk_g;
input                          reset;

input                          wr_enb;
input [P_FIFO_D_WIDTH-1:0]     wr_data;
input [P_EXT_PARITY_BITS-1:0]  wr_parity;

input                          rd_enb;
output [P_FIFO_D_WIDTH-1:0]    rd_data;
output                         rd_data_valid;

output [P_OCCU_CNTR_WIDTH-1:0] occupancy_cnt;
output                         fifo_full;
// NS_C: Flop Structure Parity I/O
// lint_checking USEPRT off
input                          perr_inj;
// lint_checking USEPRT on
output                         perr;

// Signal Declarations reg [P_FIFO_D_WIDTH-1:0] reg_array [P_FIFO_DEPTH_MOD-1:0] / altera ramstyle = "MLAB, no_rw_check" / ; wire [P_FIFO_A_WIDTH-1:0] wr_addrs ; wire [P_FIFO_A_WIDTH-1:0] rd_addrs ; wire [P_FIFO_D_WIDTH-1:0] arr_rd_data_d ; wire [P_FIFO_A_WIDTH:0] wr_pntr_plus1_d ; wire [P_FIFO_A_WIDTH:0] wr_pntr_bin_d ; reg [P_FIFO_A_WIDTH:0] wr_pntr_bin_q ; wire [P_FIFO_A_WIDTH:0] rd_pntr_plus1_d ; wire [P_FIFO_A_WIDTH:0] rd_pntr_bin_d ; reg [P_FIFO_A_WIDTH:0] rd_pntr_bin_q ; wire arr_wen_d ; wire arr_ren_d ; wire [P_FIFO_A_WIDTH-1:0] wr_pntr_plusone; wire [P_FIFO_A_WIDTH-1:0] rd_pntr_plusone;

// synopsys sync_set_reset "reset"

//**** assign wr_pntr_plusone = (wr_pntr_bin_q[P_FIFO_A_WIDTH-1:0] + LP_ONE[P_FIFO_A_WIDTH-1:0]); assign wr_pntr_plus1_d = (wr_pntr_bin_q[P_FIFO_A_WIDTH-1:0] == P_FIFO_DEPTH_MIN_1) ? {~(wr_pntr_bin_q[P_FIFO_A_WIDTH]), {(P_FIFO_A_WIDTH){1'b0}}} : {wr_pntr_bin_q[P_FIFO_A_WIDTH], wr_pntr_plusone[P_FIFO_A_WIDTH-1:0]}; assign wr_pntr_bin_d = arr_wen_d ? wr_pntr_plus1_d : wr_pntr_bin_q ;

always @(posedge clk) begin if (reset) wr_pntr_bin_q <= {(P_FIFO_A_WIDTH+1){1'b0}} ; else wr_pntr_bin_q <= wr_pntr_bin_d ; end

assign wr_addrs = wr_pntr_bin_q[P_FIFO_A_WIDTH-1:0] ;

generate if (P_FPGA_INFER_RAM) begin : G_FPGA always @(posedge clk) begin if (arr_wen_d) reg_array[wr_addrs] <= wr_data ; end end else begin : G_ASIC genvar k; for (k=0; k<P_FIFO_DEPTH_MOD; k=k+1) begin : G_ARR wire reg_wr_en ; reg [P_FIFO_D_WIDTH-1:0] reg_q ;

   assign reg_wr_en = arr_wen_d &
                      (wr_addrs == k[P_FIFO_A_WIDTH-1:0]);

   always @(posedge clk_g)
   begin
      if (reg_wr_en)
         reg_q <= wr_data ;
   end

   always @* reg_array[k] = reg_q ;

end

end endgenerate

assign rd_pntr_plusone = (rd_pntr_bin_q[P_FIFO_A_WIDTH-1:0] + LP_ONE[P_FIFO_A_WIDTH-1:0]);

assign rd_pntr_plus1_d = (rd_pntr_bin_q[P_FIFO_A_WIDTH-1:0] == P_FIFO_DEPTH_MIN_1) ? {~(rd_pntr_bin_q[P_FIFO_A_WIDTH]), {(P_FIFO_A_WIDTH){1'b0}}} : {rd_pntr_bin_q[P_FIFO_A_WIDTH], rd_pntr_plusone[P_FIFO_A_WIDTH-1:0]} ;

assign rd_pntr_bin_d = arr_ren_d ? rd_pntr_plus1_d : rd_pntr_bin_q ; always @(posedge clk) begin if (reset) rd_pntr_bin_q <= {(P_FIFO_A_WIDTH+1){1'b0}} ; else rd_pntr_bin_q <= rd_pntr_bin_d ; end

assign rd_addrs = rd_pntr_bin_q[P_FIFO_A_WIDTH-1:0] ; //lint_checking POOBID OFF assign arr_rd_data_d = reg_array[rd_addrs] ; //lint_checking POOBID ON reg array_empty_q; reg array_full_q;

always @(posedge clk) begin if (reset) begin array_empty_q <= 1'b1; array_full_q <= 1'b0; end else begin array_empty_q <= (rd_pntr_bin_d == wr_pntr_bin_d) ; array_full_q <= (rd_pntr_bin_d[P_FIFO_A_WIDTH] ^ wr_pntr_bin_d[P_FIFO_A_WIDTH]) & (rd_pntr_bin_d[P_FIFO_A_WIDTH-1:0] == wr_pntr_bin_d[P_FIFO_A_WIDTH-1:0]) ; end end

assign fifo_full = array_full_q ;

//**** //Registered output stage //**** //lint_checking URDWIR OFF wire pref_stage_wen_d ; wire pref_from_wr_data; //lint_checking URDWIR ON generate if (P_REG_OUT) begin : G_OREG

   reg                        pref_stage_valid_q ;
   reg [P_FIFO_D_WIDTH -1:0]  pref_stage_data_q ;
   wire [P_FIFO_D_WIDTH -1:0] pref_stage_data_d ;
   assign arr_wen_d = wr_enb & (~array_empty_q | (pref_stage_valid_q & ~rd_enb)) ;
   assign arr_ren_d = rd_enb & ~array_empty_q ;
   assign pref_from_wr_data = (array_empty_q & ~pref_stage_valid_q) |
                              (array_empty_q & pref_stage_valid_q & rd_enb);

   assign pref_stage_data_d = pref_from_wr_data ? wr_data :
                              rd_enb ? arr_rd_data_d :
                              pref_stage_data_q;
   always @(posedge clk) begin
      if (reset)
        pref_stage_data_q <= {(P_FIFO_D_WIDTH){1'b0}} ;
      else
        pref_stage_data_q <= pref_stage_data_d;
   end
   assign pref_stage_wen_d = (wr_enb & array_empty_q & ~pref_stage_valid_q) |
                             (wr_enb & array_empty_q & pref_stage_valid_q & rd_enb) |
                             arr_ren_d ;
   always @(posedge clk)
   begin
      if (reset)
         pref_stage_valid_q <= 1'b0 ;
      else
         if (pref_stage_wen_d)
            pref_stage_valid_q <= 1'b1 ;
         else if (rd_enb)
            pref_stage_valid_q <= 1'b0 ;
   end
   assign rd_data       = pref_stage_data_q ;
   assign rd_data_valid = pref_stage_valid_q ;

end
else begin : G_NO_OREG
   assign arr_wen_d = wr_enb ;
   assign arr_ren_d = rd_enb ;

   assign rd_data       = arr_rd_data_d ;
   assign rd_data_valid = ~array_empty_q ;

   // NS_C : needed for flop structure parity
   assign pref_stage_wen_d = 1'b0;
   assign pref_from_wr_data = 1'b0;
end

endgenerate

generate if (P_OCCUPANCY_CNT) begin: G_OCCUPANCY_CNT reg [P_OCCU_CNTR_WIDTH-1:0] occu_cntr; always @(posedge clk) begin if (reset) occu_cntr <= {P_OCCU_CNTR_WIDTH{1'b0}}; else if (wr_enb & ~rd_enb) occu_cntr <= occu_cntr + LP_ONE[P_OCCU_CNTR_WIDTH-1:0]; else if (~wr_enb & rd_enb) occu_cntr <= occu_cntr - LP_ONE[P_OCCU_CNTR_WIDTH-1:0]; end assign occupancy_cnt = occu_cntr; end else begin: G_NO_OCCUPANCY_CNT assign occupancy_cnt = {P_OCCU_CNTR_WIDTH{1'b0}}; end endgenerate

//**** // Flop Structure Parity //**** genvar i; generate if (P_FLOP_STRUCT_PARITY_ENB) begin : G_FLOP_STRUCT_PARITY

   // lint_checking URAWIR off
   wire [P_DATA_PLUS_PAD_WIDTH-1:0]    padded_wr_data ;
   // lint_checking URAWIR on
   wire [P_DATA_PLUS_PAD_WIDTH-1:0]    padded_rd_data ;
   wire [P_NUM_PARITY_BITS-1:0]        gen_parity;
   wire [P_NUM_PARITY_BITS-1:0]        raw_rd_parity;
   wire [P_NUM_PARITY_BITS-1:0]        rd_parity;
   reg  [P_NUM_PARITY_BITS-1:0]        parity_arr [P_FIFO_DEPTH_MOD-1:0] ;
   wire [P_NUM_PARITY_BITS-1:0]        perr_nxt;
   wire                                force_perr;
   reg                                 perr_q;
   // lint_checking URDREG off
   reg  [P_FIFO_A_WIDTH-1:0]           rd_addrs_q  ;
   // lint_checking URDREG on

   if (P_EXT_PARITY_GEN) begin: G_PARITY_EXT
      assign gen_parity = wr_parity;
   end
   else begin : G_PARITY_GEN
      // NS_C: generate parity
      // NS_C: adjust by pad bits to match the granularity exactly
      assign padded_wr_data = {{P_DATA_PAD_BITS{1'b0}}, wr_data} ;

      for (i=0; i<P_NUM_PARITY_BITS ; i=i+1) begin : G_PARITY_GEN
         assign gen_parity[i] = ^padded_wr_data[P_FLOP_STRUCT_PARITY_GRAN*i+:P_FLOP_STRUCT_PARITY_GRAN];
      end
   end

   always @(posedge clk) begin
      rd_addrs_q <= rd_addrs;
   end

   // NS_C: store parity into array if arr_wen_d = 1
   genvar k;
   for (k=0; k<P_FIFO_DEPTH_MOD; k=k+1) begin : G_PARITY_ARR
      wire parity_wr_en ;
      reg [P_NUM_PARITY_BITS-1:0] parity_q ;

      assign parity_wr_en = arr_wen_d & (wr_addrs == k[P_FIFO_A_WIDTH-1:0]);

      always @(posedge clk_g)
      begin
         if (parity_wr_en)
            parity_q <= gen_parity ;
      end

      always @* parity_arr[k] = parity_q ;
   end

   // NS_C: store/assign pref_stage parity
   if (P_REG_OUT) begin : G_OREG

      reg  [P_NUM_PARITY_BITS-1:0] pref_stage_parity;
      wire [P_NUM_PARITY_BITS-1:0] pref_stage_parity_d;
      // NS_C: Choose the correct parity based on the source of the prefetch load
      assign pref_stage_parity_d = pref_from_wr_data ? gen_parity :
                                   rd_enb ? parity_arr[rd_addrs] :
                                   pref_stage_parity;

      always @(posedge clk) begin
         if (pref_stage_wen_d)
            pref_stage_parity <= pref_stage_parity_d;
      end

      // lint_checking IDXTSM off
      assign raw_rd_parity = pref_stage_parity;
      // lint_checking IDXTSM on

   end // G_OREG

   else begin : G_NO_OREG

      assign raw_rd_parity = parity_arr[rd_addrs];

   end // G_NO_OREG

   // NS_C: force a parity error if programmed to do so
   assign force_perr = perr_inj & rd_enb & (rd_addrs=={P_FIFO_A_WIDTH{1'b0}});
   assign rd_parity = ~force_perr ? raw_rd_parity : ~raw_rd_parity;
   assign padded_rd_data = {{P_DATA_PAD_BITS{1'b0}},rd_data};

   // NS_C: check parity
   for (i=0; i<P_NUM_PARITY_BITS ; i=i+1) begin : G_PARITY_CHECK
         wire data_p_bit;

         assign data_p_bit =  ^padded_rd_data[P_FLOP_STRUCT_PARITY_GRAN*i+:P_FLOP_STRUCT_PARITY_GRAN] ;

         assign perr_nxt[i] = rd_data_valid &  ~(rd_parity[i] == data_p_bit);
   end

   always @(posedge clk) begin
      if (reset) begin
         perr_q <= 1'b0 ;
      end
      else begin
         perr_q <= |perr_nxt ;
      end
   end

   assign perr = perr_q;

end
else begin: G_NO_FLOP_STRUCT_PARITY
   assign perr = 1'b0;
end

endgenerate //****

`ifdef NS_FIFO_COVERAGE //lint_checking TPRUSD OFF // synthesis translate_off

reg done;
always @(posedge clk) begin
   if (~reset) begin
      if (!done && fifo_full===1'b1) begin
         done <= 1'b1;
         $display("%0d: FIFO_FULL_1ST_DETECTED: ns_s_fifo: %m", $time);
      end
   end
end
initial begin
   done <= 1'b0;
   $display("%0d: FIFO_INSTANTIATION: ns_s_fifo: %m", $time);
end

// synthesis translate_on
//lint_checking TPRUSD ON

`endif endmodule

On Thursday, February 7, 2019, 7:20:56 AM PST, Shinya TAKAMAEDA-YAMAZAKI <takamaeda@ist.hokudai.ac.jp mailto:takamaeda@ist.hokudai.ac.jp <mailto:takamaeda@ist.hokudai.ac.jp mailto:takamaeda@ist.hokudai.ac.jp> <mailto:takamaeda@ist.hokudai.ac.jp mailto:takamaeda@ist.hokudai.ac.jp <mailto:takamaeda@ist.hokudai.ac.jp mailto:takamaeda@ist.hokudai.ac.jp>>> wrote:

Hi Anandh,

I'm sorry for the very late response.

"Always" object of Veriloggen has the "self.sensitivity" field. (Please see veriloggen/core/vtypes.py) A list of Always objects for each Module can be found at "Module.always" field. (Please see veriloggen/core/module.py)

If the Always statement is realized as a sequential circuit, self.sensitivity must be "Posedge" or "Negedge" object. Otherwise, the field will be None or a list of some signals.

I think the software can predict whether the Always statement is realized as a sequential circuit or not

Thanks again!

Shinya

On 2019/01/25 6:40, anandh krishnan wrote:

Shinya san,

I was able to accomplish this task (computing registers/flip-flop count) in each module using veriloggen. Thank you Shinya San!. Arrigato.

I also would like to infer always blocks which could be realized as a flip-flop and wished to get your advice on how to proceed on this. As I need to know the total flipflop count of a module I need to also add up the costs due to the flipflops which can arise out of the always blocks such as this-

|module top (q, d, clk) output q; input d, clk; reg q; always @(posedge clk) q = d; endmodule|

On Saturday, January 19, 2019, 6:24:25 PM PST, Shinya TAKAMAEDA-YAMAZAKI <takamaeda@ist.hokudai.ac.jp mailto:takamaeda@ist.hokudai.ac.jp <mailto:takamaeda@ist.hokudai.ac.jp mailto:takamaeda@ist.hokudai.ac.jp> <mailto:takamaeda@ist.hokudai.ac.jp mailto:takamaeda@ist.hokudai.ac.jp <mailto:takamaeda@ist.hokudai.ac.jp mailto:takamaeda@ist.hokudai.ac.jp>> <mailto:takamaeda@ist.hokudai.ac.jp mailto:takamaeda@ist.hokudai.ac.jp <mailto:takamaeda@ist.hokudai.ac.jp mailto:takamaeda@ist.hokudai.ac.jp> <mailto:takamaeda@ist.hokudai.ac.jp mailto:takamaeda@ist.hokudai.ac.jp <mailto:takamaeda@ist.hokudai.ac.jp mailto:takamaeda@ist.hokudai.ac.jp>>>> wrote:

Hi Anandh,

Thank you for using Pyverilog.

I think you can figure out the number of register by using Veriloggen, not Pyverilog. Veriloggen is a hardware design framework based on Pyverilog. Veriloggen can import the existing Verilog HDL design.

Veriloggen: https://github.com/PyHDI/veriloggen

Please see the examples in veriloggen/tests/verilog/fromverilog/module

Module class has a "variable" member, which contains all "reg"s and "wire"s.

By using isinstance method like "if isinstance(obj, veriloggen.Reg): ...", you can gather only regs from all variables.

Thanks,

Shinya

On 2019/01/20 10:56, anandh krishnan wrote:

Hello Shinya san,

Konnichiwa.

I am trying to leverage PyVerilog AST to count the registers in each module in my Verilog design. The design is highly parameterized:

An example module from my Verilog design is listed below.

Please help me with pointers on how this can be done with the AST PyVerilog builds.

Arrigato, Anandh Krishnan * module ns_noc_data_ppln

(

 parameter        P_CLK_SYNCHRONIZER_DEPTH = 2,
 parameter        P_DATA_WIDTH      = 32,
 parameter        P_DATA_ERRCHK_WIDTH = 4,
 parameter        P_USRSB_ERRCHK_WIDTH = 4,
 parameter        P_WC_WIDTH        = 2,
 parameter        P_SB_WIDTH        = 15,
 parameter        P_OUTP_WIDTH      = 3,
 parameter        P_USRSB_WIDTH     = 1,
 parameter        P_NUM_OF_STAGES   = 1,
 parameter        P_VALID_WIDTH     = 4,
 parameter        P_COARSE_CLOCK_GATE = 1,
 parameter        P_FINE_CLOCK_GATE = 1

) (

 input                            clk,
 input                            reset_n,
 input                            reset_pd_n,
 input                            tst_rst,
 input                            tst_rst_bypass,

 input                            system_cg_or,
 input                            scan_mode,

 input  [P_VALID_WIDTH-1:0]       i_flit_valid,
 input  [P_DATA_WIDTH-1:0]        i_flit_data,
 input  [P_SB_WIDTH-1:0]          i_flit_sb,
 input  [P_USRSB_WIDTH-1:0]       i_flit_usrsb,
 input                            i_flit_type,
 input                            i_flit_mcpkt,
 input                            i_flit_sop,
 input                            i_flit_eop,
 input  [P_WC_WIDTH-1:0]          i_flit_bv,
 input  [P_OUTP_WIDTH-1:0]        i_flit_outp,
 input                            i_pktctl_parity,
 input                            i_rinfo_parity,
 input [P_DATA_ERRCHK_WIDTH-1:0]  i_data_parity,
 input [P_USRSB_ERRCHK_WIDTH-1:0] i_usrsb_parity,

 input                            i_cg_busy,
 output  [P_VALID_WIDTH-1:0]      o_flit_valid,
 output  [P_DATA_WIDTH-1:0]       o_flit_data,
 output  [P_SB_WIDTH-1:0]         o_flit_sb,
 output  [P_USRSB_WIDTH-1:0]      o_flit_usrsb,
 output                           o_flit_type,
 output                           o_flit_mcpkt,
 output                           o_flit_sop,
 output                           o_flit_eop,
 output  [P_WC_WIDTH-1:0]         o_flit_bv,
 output  [P_OUTP_WIDTH-1:0]       o_flit_outp,
 output                           o_pktctl_parity,
 output                           o_rinfo_parity,
 output [P_DATA_ERRCHK_WIDTH-1:0] o_data_parity,
 output [P_USRSB_ERRCHK_WIDTH-1:0]o_usrsb_parity,

 output                           o_cg_busy

) ;

localparam P_DATA_GROUP_WIDTH = P_DATA_WIDTH+P_WC_WIDTH+P_SB_WIDTH+P_USRSB_WIDTH+4+P_OUTP_WIDTH+2+P_DATA_ERRCHK_WIDTH+P_USRSB_ERRCHK_WIDTH ;

wire [P_DATA_GROUP_WIDTH-1:0] in_data_bundle ; wire [P_DATA_GROUP_WIDTH-1:0] data_ppln [P_NUM_OF_STAGES:0] ; wire [P_VALID_WIDTH-1:0] valid_ppln [P_NUM_OF_STAGES:0] ; wire busy_ppln [P_NUM_OF_STAGES:0] ;

assign in_data_bundle = {i_flit_data, i_flit_sb, i_flit_usrsb, i_flit_type, i_flit_mcpkt, i_flit_sop, i_flit_eop, i_flit_bv, i_flit_outp, i_pktctl_parity, i_rinfo_parity, i_data_parity, i_usrsb_parity} ;

assign data_ppln[0] = in_data_bundle ; assign valid_ppln[0] = i_flit_valid ; assign busy_ppln[0] = i_cg_busy ;

generate genvar i; for (i=1; i<=P_NUM_OF_STAGES; i=i+1) begin : G_DATA_PPLN / ns_data_ppln_stage AUTO_TEMPLATE ( .i_flit_valid (valid_ppln[i-1]), .i_flit_data_group (data_ppln[i-1]), .i_cg_busy (busy_ppln[i-1]), .o_flit_valid (valid_ppln[i]), .o_flit_data_group (data_ppln[i]), .o_cg_busy (busy_ppln[i]), ); / ns_data_ppln_stage #(/AUTOINSTPARAM/ // Parameters .P_CLK_SYNCHRONIZER_DEPTH(P_CLK_SYNCHRONIZER_DEPTH), .P_DATA_GROUP_WIDTH (P_DATA_GROUP_WIDTH), .P_VALID_WIDTH (P_VALID_WIDTH), .P_COARSE_CLOCK_GATE (P_COARSE_CLOCK_GATE), .P_FINE_CLOCK_GATE (P_FINE_CLOCK_GATE)) u_ns_data_ppln_stage (/AUTOINST/ // Outputs .o_flit_valid (valid_ppln[i]), // Templated .o_flit_data_group (data_ppln[i]), // Templated .o_cg_busy (busy_ppln[i]), // Templated // Inputs .clk (clk), .reset_n (reset_n), .tst_rst (tst_rst), .tst_rst_bypass (tst_rst_bypass), .reset_pd_n (reset_pd_n), .system_cg_or (system_cg_or), .scan_mode (scan_mode), .i_flit_valid (valid_ppln[i-1]), // Templated .i_flit_data_group (data_ppln[i-1]), // Templated .i_cg_busy (busy_ppln[i-1])); // Templated end endgenerate

wire [P_DATA_GROUP_WIDTH-1:0] data_ppln_exit; wire [P_DATA_GROUP_WIDTH-1:0] data_ppln_exit_clean;

assign data_ppln_exit = data_ppln[P_NUM_OF_STAGES];

ifdef NS_ECC_X_SQUASH_DEGREE2 genvar x; generate endgenerate for (x=0; x<P_DATA_GROUP_WIDTH; x=x+1) begin : G_DATA assign data_ppln_exit_clean[x] = (data_ppln_exit[x] === 1'bx) ? in_data_bundle[x]: data_ppln_exit[x]; end else assign data_ppln_exit_clean = data_ppln_exit; `endif

assign {o_flit_data, o_flit_sb, o_flit_usrsb, o_flit_type, o_flit_mcpkt, o_flit_sop, o_flit_eop, o_flit_bv, o_flit_outp, o_pktctl_parity, o_rinfo_parity, o_data_parity, o_usrsb_parity} = data_ppln_exit_clean; assign o_flit_valid = valid_ppln[P_NUM_OF_STAGES] ; assign o_cg_busy = busy_ppln[P_NUM_OF_STAGES] ;

endmodule

shtaxxx commented 5 years ago

ns_common.v

module ns_s_fifo(
   // Outputs
   rd_data,
   rd_data_valid,
   occupancy_cnt,
   fifo_full,
   perr,
   // Inputs
   clk,
   clk_g,
   reset,
   wr_enb,
   wr_data,
   wr_parity,
   rd_enb,
   perr_inj
   );

//`include "ns_common_func.vh"
parameter P_FLOP_STRUCT_PARITY_ENB    = 1'b0;
parameter integer  P_FLOP_STRUCT_PARITY_GRAN   = 8;

//lint_checking USEFTN OFF
// pragma coverage off
function automatic integer clogb2;
   input [31:0] value;
   integer     i;
   begin
   //lint_checking INPASN OFF
      clogb2 = 0;
      for(i = 0; 2**i < value; i = i + 1)
         clogb2 = i + 1;
   //lint_checking INPASN ON
   end
endfunction

// ceil() function
function automatic integer ceil;
  input integer value;
  input integer amt;
  integer floor;
  begin
    floor = (value/amt)*amt; 
    if (floor < value) 
        ceil = floor + amt;
    else
        ceil = value; 
  end
endfunction

// floor() function
function automatic integer floor;
  input integer value;
  input integer amt;
  begin
    floor = (value/amt)*amt; 
  end
endfunction

function automatic integer clog2;
   input [31:0] value;
   integer     i;
   begin
   //lint_checking INPASN OFF
      clog2 = 1;
      for(i = 0; 2**i < value; i = i + 1)
    clog2 = i + 1;
   //lint_checking INPASN ON
   end
endfunction

// NOTE: beware of unsigned/signed conversion
function automatic integer max_int;
   input integer a;
   input integer b;
   begin
      max_int = a >= b ? a : b;
   end
endfunction

// NOTE: beware of unsigned/signed conversion
function automatic integer min_int;
   input integer a;
   input integer b;
   begin
      min_int = a<=b ? a : b;
   end
endfunction

function automatic [5:0] nibble_count;
   input [31:0] value;
   begin
      if ((value % 4) == 0)
          nibble_count = value/4 ;
      else
          nibble_count = (value/4) + 1 ;
   end
endfunction

// pragma coverage on
//lint_checking USEFTN ON

   localparam P_FPGA_INFER_RAM        = 1'b0;
   parameter P_FIFO_D_WIDTH           = 32;
   parameter P_FIFO_DEPTH             = 4;
   parameter P_REG_OUT                = 1'b0;
   parameter P_OCCUPANCY_CNT          = 1'b0;

   parameter P_EXT_PARITY_GEN = 1'b1;
   localparam P_DATA_WIDTH_REMAINDER   = P_FIFO_D_WIDTH % P_FLOP_STRUCT_PARITY_GRAN ;
   localparam P_DATA_PAD_BITS          = (P_DATA_WIDTH_REMAINDER==0) ? 0 : P_FLOP_STRUCT_PARITY_GRAN - P_DATA_WIDTH_REMAINDER;
   localparam P_DATA_PLUS_PAD_WIDTH    = P_FIFO_D_WIDTH + P_DATA_PAD_BITS ;
   localparam P_EXT_PARITY_BITS        = ((P_EXT_PARITY_GEN == 1'b0) | (P_FLOP_STRUCT_PARITY_ENB == 1'b0)) ? 1 :
                                          P_DATA_PLUS_PAD_WIDTH / P_FLOP_STRUCT_PARITY_GRAN ;
   localparam P_NUM_PARITY_BITS        = P_FLOP_STRUCT_PARITY_ENB ? P_DATA_PLUS_PAD_WIDTH / P_FLOP_STRUCT_PARITY_GRAN : 1 ;

   localparam LP_ONE = 1;

   localparam P_FIFO_DEPTH_MOD = ((P_FIFO_DEPTH <= 2) & P_REG_OUT) ? 2 :
                                 ((P_FIFO_DEPTH >= 3) & P_REG_OUT) ?    (P_FIFO_DEPTH-1) : 
                                  (P_FIFO_DEPTH <= 1)              ? 2 : P_FIFO_DEPTH ;

   localparam P_FIFO_A_WIDTH = (P_FIFO_DEPTH_MOD == 1) ? 1 : clogb2(P_FIFO_DEPTH_MOD) ;
   localparam P_OCCU_CNTR_WIDTH = clog2(P_FIFO_DEPTH+1);

   localparam [P_FIFO_A_WIDTH-1:0] P_FIFO_DEPTH_MIN_1 = P_FIFO_DEPTH_MOD-1 ;

   input                          clk;
   input                          clk_g;
   input                          reset;

   input                          wr_enb;
   input [P_FIFO_D_WIDTH-1:0]     wr_data;
   input [P_EXT_PARITY_BITS-1:0]  wr_parity;

   input                          rd_enb;
   output [P_FIFO_D_WIDTH-1:0]    rd_data;
   output                         rd_data_valid;

   output [P_OCCU_CNTR_WIDTH-1:0] occupancy_cnt;

   output                         fifo_full;

   // NS_C: Flop Structure Parity I/O
   // lint_checking USEPRT off   
   input                          perr_inj;
   // lint_checking USEPRT on
   output                         perr;

//**** Signal Declarations ****

   reg [P_FIFO_D_WIDTH-1:0] reg_array [P_FIFO_DEPTH_MOD-1:0] /* altera ramstyle = "MLAB, no_rw_check" */ ;
   wire [P_FIFO_A_WIDTH-1:0] wr_addrs  ;
   wire [P_FIFO_A_WIDTH-1:0] rd_addrs  ;
   wire [P_FIFO_D_WIDTH-1:0] arr_rd_data_d  ;
   wire [P_FIFO_A_WIDTH:0] wr_pntr_plus1_d  ;
   wire [P_FIFO_A_WIDTH:0] wr_pntr_bin_d  ;
   reg [P_FIFO_A_WIDTH:0]  wr_pntr_bin_q  ;
   wire [P_FIFO_A_WIDTH:0] rd_pntr_plus1_d  ;
   wire [P_FIFO_A_WIDTH:0] rd_pntr_bin_d  ;
   reg [P_FIFO_A_WIDTH:0]  rd_pntr_bin_q  ;
   wire arr_wen_d ;
   wire arr_ren_d ;
   wire [P_FIFO_A_WIDTH-1:0] wr_pntr_plusone;
   wire [P_FIFO_A_WIDTH-1:0] rd_pntr_plusone;

// synopsys sync_set_reset "reset"

//********************************************************************************
assign wr_pntr_plusone = (wr_pntr_bin_q[P_FIFO_A_WIDTH-1:0] + LP_ONE[P_FIFO_A_WIDTH-1:0]);   
assign wr_pntr_plus1_d = (wr_pntr_bin_q[P_FIFO_A_WIDTH-1:0] == P_FIFO_DEPTH_MIN_1) ?
                            {~(wr_pntr_bin_q[P_FIFO_A_WIDTH]), {(P_FIFO_A_WIDTH){1'b0}}} :
                            {wr_pntr_bin_q[P_FIFO_A_WIDTH], wr_pntr_plusone[P_FIFO_A_WIDTH-1:0]};

assign wr_pntr_bin_d = arr_wen_d ?
                          wr_pntr_plus1_d :
                          wr_pntr_bin_q ;

always @(posedge clk)
begin
   if (reset)
      wr_pntr_bin_q <= {(P_FIFO_A_WIDTH+1){1'b0}} ;
   else
      wr_pntr_bin_q <= wr_pntr_bin_d ;
end

assign wr_addrs = wr_pntr_bin_q[P_FIFO_A_WIDTH-1:0] ;

generate
if (P_FPGA_INFER_RAM) begin : G_FPGA
   always @(posedge clk)
   begin
      if (arr_wen_d)
         reg_array[wr_addrs] <= wr_data ;
   end
end
else begin : G_ASIC
   genvar k;
   for (k=0; k<P_FIFO_DEPTH_MOD; k=k+1) begin : G_ARR
      wire reg_wr_en ;
      reg [P_FIFO_D_WIDTH-1:0] reg_q ;

      assign reg_wr_en = arr_wen_d &
                         (wr_addrs == k[P_FIFO_A_WIDTH-1:0]);

      always @(posedge clk_g)
      begin
         if (reg_wr_en)
            reg_q <= wr_data ;
      end

      always @* reg_array[k] = reg_q ;

   end
end
endgenerate

assign rd_pntr_plusone = (rd_pntr_bin_q[P_FIFO_A_WIDTH-1:0] + LP_ONE[P_FIFO_A_WIDTH-1:0]);

assign rd_pntr_plus1_d = (rd_pntr_bin_q[P_FIFO_A_WIDTH-1:0] == P_FIFO_DEPTH_MIN_1) ?
                            {~(rd_pntr_bin_q[P_FIFO_A_WIDTH]), {(P_FIFO_A_WIDTH){1'b0}}} :
                            {rd_pntr_bin_q[P_FIFO_A_WIDTH], rd_pntr_plusone[P_FIFO_A_WIDTH-1:0]} ;

assign rd_pntr_bin_d = arr_ren_d ?
                          rd_pntr_plus1_d :
                          rd_pntr_bin_q ;

always @(posedge clk)
begin
   if (reset)
      rd_pntr_bin_q  <= {(P_FIFO_A_WIDTH+1){1'b0}} ;
   else
      rd_pntr_bin_q  <= rd_pntr_bin_d ;
end

assign rd_addrs      = rd_pntr_bin_q[P_FIFO_A_WIDTH-1:0] ;
//lint_checking POOBID OFF
assign arr_rd_data_d = reg_array[rd_addrs] ;
//lint_checking POOBID ON

reg array_empty_q;
reg array_full_q;

always @(posedge clk)
begin
   if (reset) begin
      array_empty_q <= 1'b1;
      array_full_q <= 1'b0;
   end
   else begin
      array_empty_q <= (rd_pntr_bin_d == wr_pntr_bin_d) ;
      array_full_q <= (rd_pntr_bin_d[P_FIFO_A_WIDTH]     ^  wr_pntr_bin_d[P_FIFO_A_WIDTH]) &
                      (rd_pntr_bin_d[P_FIFO_A_WIDTH-1:0] == wr_pntr_bin_d[P_FIFO_A_WIDTH-1:0]) ;
   end
end

assign fifo_full = array_full_q ;

//********************************************************************************
//Registered output stage
//********************************************************************************
//lint_checking URDWIR OFF
wire                       pref_stage_wen_d ;
wire                       pref_from_wr_data;
//lint_checking URDWIR ON
generate
   if (P_REG_OUT) begin : G_OREG

      reg                        pref_stage_valid_q ;
      reg [P_FIFO_D_WIDTH -1:0]  pref_stage_data_q ;
      wire [P_FIFO_D_WIDTH -1:0] pref_stage_data_d ;

      assign arr_wen_d = wr_enb & (~array_empty_q | (pref_stage_valid_q & ~rd_enb)) ;
      assign arr_ren_d = rd_enb & ~array_empty_q ;
      assign pref_from_wr_data = (array_empty_q & ~pref_stage_valid_q) |
                                 (array_empty_q & pref_stage_valid_q & rd_enb);

      assign pref_stage_data_d = pref_from_wr_data ? wr_data :
                                 rd_enb ? arr_rd_data_d :
                                 pref_stage_data_q;

      always @(posedge clk) begin
         if (reset)
           pref_stage_data_q <= {(P_FIFO_D_WIDTH){1'b0}} ;
         else
           pref_stage_data_q <= pref_stage_data_d;
      end

      assign pref_stage_wen_d = (wr_enb & array_empty_q & ~pref_stage_valid_q) |
                                (wr_enb & array_empty_q & pref_stage_valid_q & rd_enb) |
                                arr_ren_d ;

      always @(posedge clk)
      begin
         if (reset)
            pref_stage_valid_q <= 1'b0 ;
         else
            if (pref_stage_wen_d)
               pref_stage_valid_q <= 1'b1 ;
            else if (rd_enb)
               pref_stage_valid_q <= 1'b0 ;
      end

      assign rd_data       = pref_stage_data_q ;
      assign rd_data_valid = pref_stage_valid_q ;

   end
   else begin : G_NO_OREG
      assign arr_wen_d = wr_enb ;
      assign arr_ren_d = rd_enb ;

      assign rd_data       = arr_rd_data_d ;
      assign rd_data_valid = ~array_empty_q ;

      // NS_C : needed for flop structure parity
      assign pref_stage_wen_d = 1'b0;
      assign pref_from_wr_data = 1'b0;
   end
endgenerate

generate 
   if (P_OCCUPANCY_CNT) begin: G_OCCUPANCY_CNT
      reg [P_OCCU_CNTR_WIDTH-1:0] occu_cntr;
      always @(posedge clk) begin
         if (reset) occu_cntr <= {P_OCCU_CNTR_WIDTH{1'b0}};
         else if (wr_enb & ~rd_enb) occu_cntr <= occu_cntr + LP_ONE[P_OCCU_CNTR_WIDTH-1:0];
         else if (~wr_enb & rd_enb) occu_cntr <= occu_cntr - LP_ONE[P_OCCU_CNTR_WIDTH-1:0];
      end
      assign occupancy_cnt = occu_cntr;
   end
   else begin: G_NO_OCCUPANCY_CNT
      assign occupancy_cnt = {P_OCCU_CNTR_WIDTH{1'b0}};
   end
endgenerate

//********************************************************************************
// Flop Structure Parity
//********************************************************************************
genvar i;
generate
   if (P_FLOP_STRUCT_PARITY_ENB) begin : G_FLOP_STRUCT_PARITY

      // lint_checking URAWIR off 
      wire [P_DATA_PLUS_PAD_WIDTH-1:0]    padded_wr_data ;
      // lint_checking URAWIR on 
      wire [P_DATA_PLUS_PAD_WIDTH-1:0]    padded_rd_data ;
      wire [P_NUM_PARITY_BITS-1:0]        gen_parity;
      wire [P_NUM_PARITY_BITS-1:0]        raw_rd_parity;
      wire [P_NUM_PARITY_BITS-1:0]        rd_parity;
      reg  [P_NUM_PARITY_BITS-1:0]        parity_arr [P_FIFO_DEPTH_MOD-1:0] ;
      wire [P_NUM_PARITY_BITS-1:0]        perr_nxt;
      wire                                force_perr;
      reg                                 perr_q;
      // lint_checking URDREG off
      reg  [P_FIFO_A_WIDTH-1:0]           rd_addrs_q  ;
      // lint_checking URDREG on

      if (P_EXT_PARITY_GEN) begin: G_PARITY_EXT
         assign gen_parity = wr_parity;
      end
      else begin : G_PARITY_GEN
         // NS_C: generate parity 
         // NS_C: adjust by pad bits to match the granularity exactly
         assign padded_wr_data = {{P_DATA_PAD_BITS{1'b0}}, wr_data} ;

         for (i=0; i<P_NUM_PARITY_BITS ; i=i+1) begin : G_PARITY_GEN
            assign gen_parity[i] = ^padded_wr_data[P_FLOP_STRUCT_PARITY_GRAN*i+:P_FLOP_STRUCT_PARITY_GRAN];
         end
      end

      always @(posedge clk) begin
         rd_addrs_q <= rd_addrs;
      end

      // NS_C: store parity into array if arr_wen_d = 1 
      genvar k;
      for (k=0; k<P_FIFO_DEPTH_MOD; k=k+1) begin : G_PARITY_ARR
         wire parity_wr_en ;
         reg [P_NUM_PARITY_BITS-1:0] parity_q ;

         assign parity_wr_en = arr_wen_d & (wr_addrs == k[P_FIFO_A_WIDTH-1:0]);

         always @(posedge clk_g)
         begin
            if (parity_wr_en)
               parity_q <= gen_parity ;
         end

         always @* parity_arr[k] = parity_q ;
      end

      // NS_C: store/assign pref_stage parity
      if (P_REG_OUT) begin : G_OREG

         reg  [P_NUM_PARITY_BITS-1:0] pref_stage_parity;
         wire [P_NUM_PARITY_BITS-1:0] pref_stage_parity_d;

         // NS_C: Choose the correct parity based on the source of the prefetch load
         assign pref_stage_parity_d = pref_from_wr_data ? gen_parity :
                                      rd_enb ? parity_arr[rd_addrs] :
                                      pref_stage_parity;

         always @(posedge clk) begin
            if (pref_stage_wen_d)
               pref_stage_parity <= pref_stage_parity_d;
         end

         // lint_checking IDXTSM off
         assign raw_rd_parity = pref_stage_parity;
         // lint_checking IDXTSM on

      end // G_OREG

      else begin : G_NO_OREG

         assign raw_rd_parity = parity_arr[rd_addrs];

      end // G_NO_OREG

      // NS_C: force a parity error if programmed to do so 
      assign force_perr = perr_inj & rd_enb & (rd_addrs=={P_FIFO_A_WIDTH{1'b0}});
      assign rd_parity = ~force_perr ? raw_rd_parity : ~raw_rd_parity;                                

      assign padded_rd_data = {{P_DATA_PAD_BITS{1'b0}},rd_data};

      // NS_C: check parity 
      for (i=0; i<P_NUM_PARITY_BITS ; i=i+1) begin : G_PARITY_CHECK
            wire data_p_bit;

            assign data_p_bit =  ^padded_rd_data[P_FLOP_STRUCT_PARITY_GRAN*i+:P_FLOP_STRUCT_PARITY_GRAN] ;

            assign perr_nxt[i] = rd_data_valid &  ~(rd_parity[i] == data_p_bit);
      end

      always @(posedge clk) begin
         if (reset) begin
            perr_q <= 1'b0 ;
         end
         else begin
            perr_q <= |perr_nxt ;
         end
      end

      assign perr = perr_q;

   end
   else begin: G_NO_FLOP_STRUCT_PARITY
      assign perr = 1'b0;
   end
endgenerate

//********************************************************************************

`ifdef NS_FIFO_COVERAGE
   //lint_checking TPRUSD OFF
   // synthesis translate_off

   reg done;
   always @(posedge clk) begin
      if (~reset) begin
         if (!done && fifo_full===1'b1) begin
            done <= 1'b1;
            $display("%0d: FIFO_FULL_1ST_DETECTED: ns_s_fifo: %m", $time);
         end
      end
   end
   initial begin
      done <= 1'b0;
      $display("%0d: FIFO_INSTANTIATION: ns_s_fifo: %m", $time);
   end

   // synthesis translate_on
   //lint_checking TPRUSD ON

`endif

endmodule
shtaxxx commented 5 years ago
 python3 example_parser.py ~/work/tmp/pyverilog_bug/ns_common.v -I ~/work/tmp/pyverilog_bug/

results

Syntax error
Traceback (most recent call last):
  File "example_parser.py", line 52, in <module>
    main()
  File "example_parser.py", line 45, in main
    preprocess_define=options.define)
  File "/Users/shinya/work/pyverilog/pyverilog/vparser/parser.py", line 2248, in parse
    ast = codeparser.parse()
  File "/Users/shinya/work/pyverilog/pyverilog/vparser/parser.py", line 2234, in parse
    ast = self.parser.parse(text, debug=debug)
  File "/Users/shinya/work/pyverilog/pyverilog/vparser/parser.py", line 64, in parse
    return self.parser.parse(text, lexer=self.lexer, debug=debug)
  File "/Users/shinya/work/pyverilog/pyverilog/vparser/ply/yacc.py", line 265, in parse
    return self.parseopt_notrack(input,lexer,debug,tracking,tokenfunc)
  File "/Users/shinya/work/pyverilog/pyverilog/vparser/ply/yacc.py", line 1047, in parseopt_notrack
    tok = self.errorfunc(errtoken)
  File "/Users/shinya/work/pyverilog/pyverilog/vparser/parser.py", line 2207, in p_error
    self._coord(p.lineno))
  File "/Users/shinya/work/pyverilog/pyverilog/vparser/plyparser.py", line 54, in _parse_error
    raise ParseError("%s: %s" % (coord, msg))
pyverilog.vparser.plyparser.ParseError: :25: before: integer
shtaxxx commented 5 years ago

At first, pyverilog does not support "automatic".

shtaxxx commented 5 years ago

I made another issue for "automatic" support.