data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/rtl/test_pe_comp.svp
 line:39: before: "parameter"
1: b"%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/rtl/test_pe_comp.svp:38: Define or directive not defined: '`mname'\nmodule   `mname`  #(\n         ^~~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/rtl/test_pe_comp.svp:38: syntax error, unexpected $undefined, expecting IDENTIFIER or PACKAGE-IDENTIFIER or TYPE-IDENTIFIER\nmodule   `mname`  #(\n               ^\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/rtl/test_pe_comp.svp:40: syntax error, unexpected ')', expecting ';'\n) (\n^\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/rtl/test_pe_comp.svp:55: Unsupported or unknown PLI call: $use_add\n  input [`$use_add -1`:0]              carry_in,\n          ^~~~~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/rtl/test_pe_comp.svp:63: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n  output logic [`$use_add -1`:0]             carry_out,\n  ^~~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/rtl/test_pe_comp.svp:63: Unsupported or unknown PLI call: $use_add\n  output logic [`$use_add -1`:0]             carry_out,\n                 ^~~~~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/rtl/test_pe_comp.svp:71: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input        [DataWidth-1:0]   div_oper,\n  ^~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/rtl/test_pe_comp.svp:80: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n  output logic [DataWidth-1:0]   res,\n  ^~~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/rtl/test_pe_comp.svp:82: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n  output logic [2*DataWidth-1:0] mult_res,\n  ^~~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/rtl/test_pe_comp.svp:85: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n  output logic                   ovfl,\n  ^~~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/rtl/test_pe_comp.svp:87: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n  output logic                   res_p\n  ^~~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/rtl/test_pe_comp.svp:237: syntax error, unexpected assign\nassign             nc_op_code = op_code;\n^~~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/rtl/test_pe_comp.svp:256: syntax error, unexpected $undefined, expecting TYPE-IDENTIFIER\nlocalparam NUM_ADDERS = `$use_add`;\n                        ^\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/rtl/test_pe_comp.svp:256: Unsupported or unknown PLI call: $use_add\nlocalparam NUM_ADDERS = `$use_add`;\n                         ^~~~~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/rtl/test_pe_comp.svp:267: syntax error, unexpected genvar\ngenvar ggg;\n^~~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/rtl/test_pe_comp.svp:272: Unsupported or unknown PLI call: $full_add\n  `$full_add->mname()` #(.DataWidth(DataWidth)) `$full_add->iname()`\n   ^~~~~~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/rtl/test_pe_comp.svp:272: Unsupported or unknown PLI call: $full_add\n  `$full_add->mname()` #(.DataWidth(DataWidth)) `$full_add->iname()`\n                                                 ^~~~~~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/rtl/test_pe_comp.svp:300: Unsupported or unknown PLI call: $compare\n`$compare->instantiate()`\n ^~~~~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/rtl/test_pe_comp.svp:319: syntax error, unexpected $undefined\n`$mult->mname()` #(.DataWidth(DataWidth)) `$mult->iname()`\n^\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/rtl/test_pe_comp.svp:319: Unsupported or unknown PLI call: $mult\n`$mult->mname()` #(.DataWidth(DataWidth)) `$mult->iname()`\n ^~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/rtl/test_pe_comp.svp:319: Unsupported or unknown PLI call: $mult\n`$mult->mname()` #(.DataWidth(DataWidth)) `$mult->iname()`\n                                           ^~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/rtl/test_pe_comp.svp:345: syntax error, unexpected always_comb\nalways_comb begin\n^~~~~~~~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/rtl/test_pe_comp.svp:388: syntax error, unexpected $undefined\n`$shft->mname()` #(.DataWidth(DataWidth)) `$shft->iname()`\n^\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/rtl/test_pe_comp.svp:388: Unsupported or unknown PLI call: $shft\n`$shft->mname()` #(.DataWidth(DataWidth)) `$shft->iname()`\n ^~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/rtl/test_pe_comp.svp:388: Unsupported or unknown PLI call: $shft\n`$shft->mname()` #(.DataWidth(DataWidth)) `$shft->iname()`\n                                           ^~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/rtl/test_pe_comp.svp:400: Unsupported or unknown PLI call: $en_double\n  .b   (op_b[$clog2(DataWidth)-1+`$en_double`:0]),\n                                  ^~~~~~~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/rtl/test_pe_comp.svp:420: syntax error, unexpected assign\nassign diff_sign = add_res[0][DATA_MSB];\n^~~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/rtl/test_pe_comp.svp:433: syntax error, unexpected assign\nassign ovfl_add_signed[0] = (op_a[DataMSB] == op_b[DataMSB]) &\n^~~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/rtl/test_pe_comp.svp:441: syntax error, unexpected always_comb\nalways_comb begin\n^~~~~~~~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/rtl/test_pe_comp.svp:454: syntax error, unexpected IDENTIFIER\n  CW_fp_mult #(.sig_width(10), .exp_width(8), .ieee_compliance(0)) mul1 (.a({op_a,3'd0}),.b({op_b,3'd0}),.rnd(3'd0),.z({fmul_res,fmul_res_x}),.status());\n  ^~~~~~~~~~\n%Error: Exiting due to 30 error(s)\n"
module   `mname`  #(
  parameter DataWidth = 16
) (
  input [7:0]                    op_code,

  input  [DataWidth-1:0]         op_a,

  input  [DataWidth-1:0]         op_a_shift,

  input  [DataWidth-1:0]         op_b,

  input  [DataWidth-1:0]         op_c,

  input                          op_d_p,



  input [`$use_add -1`:0]              carry_in,
  input                         cmpr_eq_in,

  input                          res_p_msb,
  output logic                   cmpr_eq_out,



  output logic [`$use_add -1`:0]             carry_out,




  output logic                   cntr_en,


  input        [DataWidth-1:0]   div_oper,

  input                          res_p_msb,


  output logic [DataWidth-1:0]   div_co,



  output logic [DataWidth-1:0]   res,

  output logic [2*DataWidth-1:0] mult_res,


  output logic                   ovfl,

  output logic                   res_p
);

localparam DATA_MSB      = DataWidth - 1;

localparam PE_ADD_OP     = 6'h0;






localparam PE_SUB_OP     = 6'h1;







localparam PE_ABS_OP     = 6'h3;







localparam PE_GTE_MAX_OP = 6'h4;





localparam PE_LTE_MIN_OP = 6'h5;







localparam PE_SEL_OP     = 6'h8;







localparam PE_RSHFT_OP   = 6'hF;





localparam PE_LSHFT_OP   = 6'h11;








localparam PE_MULT_0_OP  = 6'hB;





localparam PE_MULT_1_OP  = 6'hC;





localparam PE_MULT_2_OP  = 6'hD;






localparam PE_RELU       = 6'hE;









localparam PE_OR_OP      = 6'h12;





localparam PE_AND_OP     = 6'h13;





localparam PE_XOR_OP     = 6'h14;








localparam PE_CNTR_OP    = 6'h18;







localparam PE_DIV_OP     = 6'h19;







logic [2*DataWidth-1:0] mult_res;



localparam PE_FLOAT_ADD     = 6'h20;





localparam PE_FLOAT_MULT     = 6'h21;







logic [7:0]        nc_op_code;
assign             nc_op_code = op_code;


logic [DATA_MSB:0] res_w;
logic              res_p_w;

logic                 is_signed;


logic                 double_mode;





logic                 cmpr_lte;
logic                 cmpr_gte;
logic                 cmpr_eq;

localparam NUM_ADDERS = `$use_add`;
localparam ADD_MSB = NUM_ADDERS - 1;

logic [DATA_MSB:0]  add_a     [ADD_MSB:0];
logic [DATA_MSB:0]  add_b     [ADD_MSB:0];
logic               add_c_in  [ADD_MSB:0];

wire  [DATA_MSB:0]  add_res   [ADD_MSB:0];
wire                add_c_out [ADD_MSB:0];


genvar ggg;

generate
  for(ggg=0;ggg<NUM_ADDERS;ggg=ggg+1) begin : GEN_ADD

  `$full_add->mname()` #(.DataWidth(DataWidth)) `$full_add->iname()`
    (
      .a     (add_a[ggg]),
      .b     (add_b[ggg]),
      .c_in  (add_c_in[ggg]),



      .res   (add_res[ggg]),
      .c_out (add_c_out[ggg])
    );


  assign carry_out[ggg] = add_c_out[ggg];

  end

endgenerate


assign cmpr_eq   =  ~|(op_a ^ op_b) & (~double_mode | cmpr_eq_in);

assign cmpr_eq   =  ~|(op_a ^ op_b);





`$compare->instantiate()`
(
  .a_msb     (op_a[DATA_MSB]),
  .b_msb     (op_b[DATA_MSB]),
  .diff_msb  (add_res[0][DATA_MSB]),
  .is_signed (is_signed),
  .eq        (cmpr_eq),

  .lte       (cmpr_lte),
  .gte       (cmpr_gte)
);





logic                 mult_c_out;


`$mult->mname()` #(.DataWidth(DataWidth)) `$mult->iname()`
(
  .is_signed (is_signed),

  .a  (op_a),
  .b  (op_b),



  .c  (op_c),


  .res   (mult_res),
  .c_out (mult_c_out)
);





enum {
Add_Op, Sub_Op, Abs_Op, GteMax_Op, LteMin_Op, 
Sel_Op, Rshft_Op, Lshft_Op, Mult0_Op, Mult1_Op, Mult2_Op, Relu_Op, Or_Op,
And_Op, Xor_Op, Cntr_Op, Div_Op, Fadd, Fmul, InvalidOp
} pe_oper;

always_comb begin
  case (op_code[5:0])
    PE_ADD_OP     : pe_oper = Add_Op;
    PE_SUB_OP     : pe_oper = Sub_Op;
    PE_ABS_OP     : pe_oper = Abs_Op;
    PE_GTE_MAX_OP : pe_oper = GteMax_Op;
    PE_LTE_MIN_OP : pe_oper = LteMin_Op;
    PE_SEL_OP     : pe_oper = Sel_Op;
    PE_RSHFT_OP   : pe_oper = Rshft_Op;
    PE_LSHFT_OP   : pe_oper = Lshft_Op;
    PE_MULT_0_OP  : pe_oper = Mult0_Op;
    PE_MULT_1_OP  : pe_oper = Mult1_Op;
    PE_MULT_2_OP  : pe_oper = Mult2_Op;

    PE_RELU       : pe_oper = Relu_Op;

    PE_OR_OP      : pe_oper = Or_Op;
    PE_AND_OP     : pe_oper = And_Op;
    PE_XOR_OP     : pe_oper = Xor_Op;

    PE_CNTR_OP    : pe_oper = Cntr_Op;


    PE_DIV_OP     : pe_oper = Div_Op;


    PE_FLOAT_ADD  : pe_oper = Fadd;
    PE_FLOAT_MULT : pe_oper = Fmul;

    default       : pe_oper = InvalidOp;
  endcase
end



  assign cntr_en = (op_code[5:0] == PE_CNTR_OP);




logic [DATA_MSB:0] shift_res;


`$shft->mname()` #(.DataWidth(DataWidth)) `$shft->iname()`
(
  .is_signed (is_signed),

  .double_mode (double_mode),

  .dir_left(op_code[5:0]==PE_LSHFT_OP),

  .a  (op_a),

  .a_shift (op_a_shift),

  .b   (op_b[$clog2(DataWidth)-1+`$en_double`:0]),

  .res (shift_res)
);



assign is_signed   = op_code[6];

assign double_mode = op_code[7];




assign cmpr_eq_out = cmpr_eq;



logic diff_sign;

assign diff_sign = add_res[0][DATA_MSB];

assign diff_sign = double_mode ? res_p_msb : add_res[0][DATA_MSB];

assign diff_sign = add_res[0][DATA_MSB];





localparam DataMSB = DataWidth-1;
logic [ADD_MSB:0] ovfl_add_signed;

assign ovfl_add_signed[0] = (op_a[DataMSB] == op_b[DataMSB]) &
                            (op_a[DataMSB] != add_res[0][DataMSB]);

assign ovfl_add_signed[1] = (add_res[0][DataMSB] == op_c[DataMSB]) &
                            (op_c[DataMSB] != add_res[1][DataMSB]);


logic  ovfl_sub_signed;
always_comb begin
  ovfl_sub_signed = ((op_a[DataMSB] != op_b[DataMSB]) & (op_a[DataMSB] != add_res[0][DataMSB]));

  ovfl_sub_signed = ovfl_sub_signed | ovfl_add_signed[1];

end




logic [15:0] fadd_res;
logic [15:0] fmul_res;
logic [2:0] fmul_res_x;
  CW_fp_mult #(.sig_width(10), .exp_width(8), .ieee_compliance(0)) mul1 (.a({op_a,3'd0}),.b({op_b,3'd0}),.rnd(3'd0),.z({fmul_res,fmul_res_x}),.status());
  CW_fp_add #(.sig_width(7), .exp_width(8), .ieee_compliance(0)) add1 (.a(op_a),.b(op_b),.rnd(3'd0),.z(fadd_res),.status());


always_comb begin : proc_alu

  add_a[0] = op_a;
  add_b[0] = op_b;
  add_c_in[0] = 1'b0;


  add_a[1] = add_res[0];
  add_b[1] = op_c;
  add_c_in[1] = 1'b0;


  res_w   = add_res[ADD_MSB];
  res_p_w = add_c_out[ADD_MSB];

  res_w   = 'hX;
  res_p_w = 'hX;






  div_co      = {DataWidth{1'b0}};


  ovfl = 1'b0;


  unique case (op_code[5:0])

    PE_FLOAT_ADD: begin
        res_w  = fadd_res;
        res_p_w     = 1'b0;
      end
    PE_FLOAT_MULT: begin
        res_w  = fmul_res;
        res_p_w     = 1'b0;
      end



    PE_ADD_OP: begin

        add_c_in[0] = double_mode ? carry_in[0] : op_d_p;

        add_c_in[1] = double_mode ? carry_in[1] : 1'b0;


        add_c_in[0] = op_d_p;

        res_p_w     = add_c_out[0];

        res_p_w     = add_c_out[0] | add_c_out[1];


        ovfl        = (is_signed) ? (|ovfl_add_signed) : res_p_w;

      end
    PE_SUB_OP: begin
        add_b[0]    = ~op_b;

        add_c_in[0] = double_mode ? carry_in[0] : 1'b1;

        add_c_in[1] = double_mode ? carry_in[1] : 1'b0;


        add_c_in[0] = 1'b1;


        ovfl        = (is_signed) ? ovfl_sub_signed : 1'b0;

      end

    PE_ABS_OP: begin

        add_b[0]    = ~op_b;

        add_a[1]    = diff_sign ? ~add_res[0]:add_res[0];

        add_c_in[0] = double_mode ? carry_in[0] : 1'b1;
        add_c_in[1] = double_mode ? carry_in[1] : diff_sign;

        add_c_in[0] = 1'b1;
        add_c_in[1] = diff_sign;



        ovfl        = (add_res[0][DATA_MSB] & (~|add_res[0][DATA_MSB-1:0])) |
                      res_w[DATA_MSB];


        res_p_w     = diff_sign;

        add_a[0]    = ~op_a;
        add_b[0]    = 0;

        add_c_in[0] = double_mode ? carry_in[0] : 1'b1;
        res_p_w     = op_a[DATA_MSB];

        add_c_in[0] = 1'b1;
        res_p_w     = double_mode ? res_p_msb : op_a[DATA_MSB];

        add_c_in[0] = 1'b1;
        res_p_w     = op_a[DATA_MSB];


        res_w       = (diff_sign | !is_signed) ? op_a : add_res[0];

        ovfl        = res_w[DATA_MSB];



    end


    PE_GTE_MAX_OP: begin
        add_b[0]    = ~op_b;

        add_c_in[0] = double_mode ? carry_in[0] : 1'b1;
        res_p_w     = cmpr_gte;

        add_c_in[0] = 1'b1;
        res_p_w     = double_mode ? res_p_msb : cmpr_gte;

        add_c_in[0] = 1'b1;
        res_p_w     = cmpr_gte;


        res_w       = res_p_w ? op_a : op_b;

      end
    PE_LTE_MIN_OP: begin
        add_b[0]    = ~op_b;

        add_c_in[0] = double_mode ? carry_in[0] : 1'b1;
        res_p_w     = cmpr_lte;

        add_c_in[0] = 1'b1;
        res_p_w     = double_mode ? res_p_msb : cmpr_lte;

        add_c_in[0] = 1'b1;
        res_p_w     = cmpr_lte;


        res_w       = res_p_w ? op_a : op_b;

      end
      PE_SEL_OP: begin
        res_w = op_d_p ? op_a : op_b;
      end


    PE_RSHFT_OP: begin
        res_w = shift_res;
      end
    PE_LSHFT_OP: begin
        res_w = shift_res;
      end


    PE_MULT_0_OP: begin
        res_w   = mult_res[DATA_MSB:0];
        res_p_w = mult_c_out;

        if (is_signed) begin
          ovfl = (op_a[DATA_MSB] == op_b[DATA_MSB]) ?
                                    mult_res[DATA_MSB] :
                                    ~mult_res[DATA_MSB] & |{op_a, op_b};
        end else begin
          ovfl = |mult_res[2*DataWidth-1:DataWidth];
        end

      end
    PE_MULT_1_OP: begin
        res_w   = mult_res[3*DataWidth/2-1:DataWidth/2];
        res_p_w = mult_c_out;

        if (is_signed) begin
          ovfl = (op_a[DATA_MSB] == op_b[DATA_MSB]) ?
                                    mult_res[DATA_MSB] :
                                    ~mult_res[DATA_MSB] & |{op_a, op_b};
        end else begin
          ovfl = |mult_res[2*DataWidth-1:3*DataWidth/2];
        end

      end
    PE_MULT_2_OP: begin
        res_w   = mult_res[2*DataWidth-1:DataWidth];
        res_p_w = mult_c_out;

        ovfl = 1'b0;

      end


    PE_RELU: begin
        res_w   = diff_sign ? mult_res[2*DataWidth-1:DataWidth] : op_a;
        res_p_w = op_a[DATA_MSB];
      end




    PE_OR_OP: begin
        res_w = op_a | op_b;
      end
    PE_AND_OP: begin
        res_w = op_a & op_b;
      end
    PE_XOR_OP: begin
        res_w = op_a ^ op_b;
      end


    PE_CNTR_OP: begin

        add_a[0]    = op_a;

        add_a[0]    = 'h1;

        add_b[0]    = op_b;
        add_c_in[0] = 1'b0;


	res_w       = add_res[0];


        res_p_w     = ~|(op_b ^ op_c);

        res_p_w     = ~|(op_b ^ op_a);

      end



    PE_DIV_OP: begin
      add_a[0]    = div_oper;
      add_b[0]    = ~op_b;
      add_c_in[0] = 1'b1;


      res_w       = ~add_res[0][DATA_MSB] ?  add_res[0] : div_oper;
      res_p_w     = add_res[0][DATA_MSB];

      div_co      = ~add_res[0][DATA_MSB] ? add_res[0] : div_oper;
      res_w       = {op_a[DataWidth-3:0], ~add_res[0][DATA_MSB] , ~res_p_msb} ;

      end


    default: begin
        res_w   = op_a;
        res_p_w = op_d_p;
      end
  endcase
end


assign res   = res_w;
assign res_p = res_p_w;













endmodule
module   `mname`  #(
  parameter DataWidth = 16
) (
  input [7:0]                    op_code,

  input  [DataWidth-1:0]         op_a,

  input  [DataWidth-1:0]         op_a_shift,

  input  [DataWidth-1:0]         op_b,

  input  [DataWidth-1:0]         op_c,

  input                          op_d_p,



  input [`$use_add -1`:0]              carry_in,
  input                         cmpr_eq_in,

  input                          res_p_msb,
  output logic                   cmpr_eq_out,



  output logic [`$use_add -1`:0]             carry_out,




  output logic                   cntr_en,


  input        [DataWidth-1:0]   div_oper,

  input                          res_p_msb,


  output logic [DataWidth-1:0]   div_co,



  output logic [DataWidth-1:0]   res,

  output logic [2*DataWidth-1:0] mult_res,


  output logic                   ovfl,

  output logic                   res_p
);


localparam DATA_MSB      = DataWidth - 1;

localparam PE_ADD_OP     = 6'h0;






localparam PE_SUB_OP     = 6'h1;







localparam PE_ABS_OP     = 6'h3;







localparam PE_GTE_MAX_OP = 6'h4;





localparam PE_LTE_MIN_OP = 6'h5;







localparam PE_SEL_OP     = 6'h8;







localparam PE_RSHFT_OP   = 6'hF;





localparam PE_LSHFT_OP   = 6'h11;








localparam PE_MULT_0_OP  = 6'hB;





localparam PE_MULT_1_OP  = 6'hC;





localparam PE_MULT_2_OP  = 6'hD;






localparam PE_RELU       = 6'hE;









localparam PE_OR_OP      = 6'h12;





localparam PE_AND_OP     = 6'h13;





localparam PE_XOR_OP     = 6'h14;








localparam PE_CNTR_OP    = 6'h18;







localparam PE_DIV_OP     = 6'h19;







logic [2*DataWidth-1:0] mult_res;



localparam PE_FLOAT_ADD     = 6'h20;





localparam PE_FLOAT_MULT     = 6'h21;







logic [7:0]        nc_op_code;
assign             nc_op_code = op_code;


logic [DATA_MSB:0] res_w;
logic              res_p_w;

logic                 is_signed;


logic                 double_mode;





logic                 cmpr_lte;
logic                 cmpr_gte;
logic                 cmpr_eq;

localparam NUM_ADDERS = `$use_add`;
localparam ADD_MSB = NUM_ADDERS - 1;

logic [DATA_MSB:0]  add_a     [ADD_MSB:0];
logic [DATA_MSB:0]  add_b     [ADD_MSB:0];
logic               add_c_in  [ADD_MSB:0];

wire  [DATA_MSB:0]  add_res   [ADD_MSB:0];
wire                add_c_out [ADD_MSB:0];


genvar ggg;

generate
  for(ggg=0;ggg<NUM_ADDERS;ggg=ggg+1) begin : GEN_ADD

  `$full_add->mname()` #(.DataWidth(DataWidth)) `$full_add->iname()`
    (
      .a     (add_a[ggg]),
      .b     (add_b[ggg]),
      .c_in  (add_c_in[ggg]),



      .res   (add_res[ggg]),
      .c_out (add_c_out[ggg])
    );


  assign carry_out[ggg] = add_c_out[ggg];

  end

endgenerate


assign cmpr_eq   =  ~|(op_a ^ op_b) & (~double_mode | cmpr_eq_in);

assign cmpr_eq   =  ~|(op_a ^ op_b);





`$compare->instantiate()`
(
  .a_msb     (op_a[DATA_MSB]),
  .b_msb     (op_b[DATA_MSB]),
  .diff_msb  (add_res[0][DATA_MSB]),
  .is_signed (is_signed),
  .eq        (cmpr_eq),

  .lte       (cmpr_lte),
  .gte       (cmpr_gte)
);





logic                 mult_c_out;


`$mult->mname()` #(.DataWidth(DataWidth)) `$mult->iname()`
(
  .is_signed (is_signed),

  .a  (op_a),
  .b  (op_b),



  .c  (op_c),


  .res   (mult_res),
  .c_out (mult_c_out)
);





enum {
Add_Op, Sub_Op, Abs_Op, GteMax_Op, LteMin_Op, 
Sel_Op, Rshft_Op, Lshft_Op, Mult0_Op, Mult1_Op, Mult2_Op, Relu_Op, Or_Op,
And_Op, Xor_Op, Cntr_Op, Div_Op, Fadd, Fmul, InvalidOp
} pe_oper;

always_comb begin
  case (op_code[5:0])
    PE_ADD_OP     : pe_oper = Add_Op;
    PE_SUB_OP     : pe_oper = Sub_Op;
    PE_ABS_OP     : pe_oper = Abs_Op;
    PE_GTE_MAX_OP : pe_oper = GteMax_Op;
    PE_LTE_MIN_OP : pe_oper = LteMin_Op;
    PE_SEL_OP     : pe_oper = Sel_Op;
    PE_RSHFT_OP   : pe_oper = Rshft_Op;
    PE_LSHFT_OP   : pe_oper = Lshft_Op;
    PE_MULT_0_OP  : pe_oper = Mult0_Op;
    PE_MULT_1_OP  : pe_oper = Mult1_Op;
    PE_MULT_2_OP  : pe_oper = Mult2_Op;

    PE_RELU       : pe_oper = Relu_Op;

    PE_OR_OP      : pe_oper = Or_Op;
    PE_AND_OP     : pe_oper = And_Op;
    PE_XOR_OP     : pe_oper = Xor_Op;

    PE_CNTR_OP    : pe_oper = Cntr_Op;


    PE_DIV_OP     : pe_oper = Div_Op;


    PE_FLOAT_ADD  : pe_oper = Fadd;
    PE_FLOAT_MULT : pe_oper = Fmul;

    default       : pe_oper = InvalidOp;
  endcase
end



  assign cntr_en = (op_code[5:0] == PE_CNTR_OP);




logic [DATA_MSB:0] shift_res;


`$shft->mname()` #(.DataWidth(DataWidth)) `$shft->iname()`
(
  .is_signed (is_signed),

  .double_mode (double_mode),

  .dir_left(op_code[5:0]==PE_LSHFT_OP),

  .a  (op_a),

  .a_shift (op_a_shift),

  .b   (op_b[$clog2(DataWidth)-1+`$en_double`:0]),

  .res (shift_res)
);



assign is_signed   = op_code[6];

assign double_mode = op_code[7];




assign cmpr_eq_out = cmpr_eq;



logic diff_sign;

assign diff_sign = add_res[0][DATA_MSB];

assign diff_sign = double_mode ? res_p_msb : add_res[0][DATA_MSB];

assign diff_sign = add_res[0][DATA_MSB];





localparam DataMSB = DataWidth-1;
logic [ADD_MSB:0] ovfl_add_signed;

assign ovfl_add_signed[0] = (op_a[DataMSB] == op_b[DataMSB]) &
                            (op_a[DataMSB] != add_res[0][DataMSB]);

assign ovfl_add_signed[1] = (add_res[0][DataMSB] == op_c[DataMSB]) &
                            (op_c[DataMSB] != add_res[1][DataMSB]);


logic  ovfl_sub_signed;
always_comb begin
  ovfl_sub_signed = ((op_a[DataMSB] != op_b[DataMSB]) & (op_a[DataMSB] != add_res[0][DataMSB]));

  ovfl_sub_signed = ovfl_sub_signed | ovfl_add_signed[1];

end




logic [15:0] fadd_res;
logic [15:0] fmul_res;
logic [2:0] fmul_res_x;
  CW_fp_mult #(.sig_width(10), .exp_width(8), .ieee_compliance(0)) mul1 (.a({op_a,3'd0}),.b({op_b,3'd0}),.rnd(3'd0),.z({fmul_res,fmul_res_x}),.status());
  CW_fp_add #(.sig_width(7), .exp_width(8), .ieee_compliance(0)) add1 (.a(op_a),.b(op_b),.rnd(3'd0),.z(fadd_res),.status());


always_comb begin : proc_alu

  add_a[0] = op_a;
  add_b[0] = op_b;
  add_c_in[0] = 1'b0;


  add_a[1] = add_res[0];
  add_b[1] = op_c;
  add_c_in[1] = 1'b0;


  res_w   = add_res[ADD_MSB];
  res_p_w = add_c_out[ADD_MSB];

  res_w   = 'hX;
  res_p_w = 'hX;






  div_co      = {DataWidth{1'b0}};


  ovfl = 1'b0;


  unique case (op_code[5:0])

    PE_FLOAT_ADD: begin
        res_w  = fadd_res;
        res_p_w     = 1'b0;
      end
    PE_FLOAT_MULT: begin
        res_w  = fmul_res;
        res_p_w     = 1'b0;
      end



    PE_ADD_OP: begin

        add_c_in[0] = double_mode ? carry_in[0] : op_d_p;

        add_c_in[1] = double_mode ? carry_in[1] : 1'b0;


        add_c_in[0] = op_d_p;

        res_p_w     = add_c_out[0];

        res_p_w     = add_c_out[0] | add_c_out[1];


        ovfl        = (is_signed) ? (|ovfl_add_signed) : res_p_w;

      end
    PE_SUB_OP: begin
        add_b[0]    = ~op_b;

        add_c_in[0] = double_mode ? carry_in[0] : 1'b1;

        add_c_in[1] = double_mode ? carry_in[1] : 1'b0;


        add_c_in[0] = 1'b1;


        ovfl        = (is_signed) ? ovfl_sub_signed : 1'b0;

      end

    PE_ABS_OP: begin

        add_b[0]    = ~op_b;

        add_a[1]    = diff_sign ? ~add_res[0]:add_res[0];

        add_c_in[0] = double_mode ? carry_in[0] : 1'b1;
        add_c_in[1] = double_mode ? carry_in[1] : diff_sign;

        add_c_in[0] = 1'b1;
        add_c_in[1] = diff_sign;



        ovfl        = (add_res[0][DATA_MSB] & (~|add_res[0][DATA_MSB-1:0])) |
                      res_w[DATA_MSB];


        res_p_w     = diff_sign;

        add_a[0]    = ~op_a;
        add_b[0]    = 0;

        add_c_in[0] = double_mode ? carry_in[0] : 1'b1;
        res_p_w     = op_a[DATA_MSB];

        add_c_in[0] = 1'b1;
        res_p_w     = double_mode ? res_p_msb : op_a[DATA_MSB];

        add_c_in[0] = 1'b1;
        res_p_w     = op_a[DATA_MSB];


        res_w       = (diff_sign | !is_signed) ? op_a : add_res[0];

        ovfl        = res_w[DATA_MSB];



    end


    PE_GTE_MAX_OP: begin
        add_b[0]    = ~op_b;

        add_c_in[0] = double_mode ? carry_in[0] : 1'b1;
        res_p_w     = cmpr_gte;

        add_c_in[0] = 1'b1;
        res_p_w     = double_mode ? res_p_msb : cmpr_gte;

        add_c_in[0] = 1'b1;
        res_p_w     = cmpr_gte;


        res_w       = res_p_w ? op_a : op_b;

      end
    PE_LTE_MIN_OP: begin
        add_b[0]    = ~op_b;

        add_c_in[0] = double_mode ? carry_in[0] : 1'b1;
        res_p_w     = cmpr_lte;

        add_c_in[0] = 1'b1;
        res_p_w     = double_mode ? res_p_msb : cmpr_lte;

        add_c_in[0] = 1'b1;
        res_p_w     = cmpr_lte;


        res_w       = res_p_w ? op_a : op_b;

      end
      PE_SEL_OP: begin
        res_w = op_d_p ? op_a : op_b;
      end


    PE_RSHFT_OP: begin
        res_w = shift_res;
      end
    PE_LSHFT_OP: begin
        res_w = shift_res;
      end


    PE_MULT_0_OP: begin
        res_w   = mult_res[DATA_MSB:0];
        res_p_w = mult_c_out;

        if (is_signed) begin
          ovfl = (op_a[DATA_MSB] == op_b[DATA_MSB]) ?
                                    mult_res[DATA_MSB] :
                                    ~mult_res[DATA_MSB] & |{op_a, op_b};
        end else begin
          ovfl = |mult_res[2*DataWidth-1:DataWidth];
        end

      end
    PE_MULT_1_OP: begin
        res_w   = mult_res[3*DataWidth/2-1:DataWidth/2];
        res_p_w = mult_c_out;

        if (is_signed) begin
          ovfl = (op_a[DATA_MSB] == op_b[DATA_MSB]) ?
                                    mult_res[DATA_MSB] :
                                    ~mult_res[DATA_MSB] & |{op_a, op_b};
        end else begin
          ovfl = |mult_res[2*DataWidth-1:3*DataWidth/2];
        end

      end
    PE_MULT_2_OP: begin
        res_w   = mult_res[2*DataWidth-1:DataWidth];
        res_p_w = mult_c_out;

        ovfl = 1'b0;

      end


    PE_RELU: begin
        res_w   = diff_sign ? mult_res[2*DataWidth-1:DataWidth] : op_a;
        res_p_w = op_a[DATA_MSB];
      end




    PE_OR_OP: begin
        res_w = op_a | op_b;
      end
    PE_AND_OP: begin
        res_w = op_a & op_b;
      end
    PE_XOR_OP: begin
        res_w = op_a ^ op_b;
      end


    PE_CNTR_OP: begin

        add_a[0]    = op_a;

        add_a[0]    = 'h1;

        add_b[0]    = op_b;
        add_c_in[0] = 1'b0;


	res_w       = add_res[0];


        res_p_w     = ~|(op_b ^ op_c);

        res_p_w     = ~|(op_b ^ op_a);

      end



    PE_DIV_OP: begin
      add_a[0]    = div_oper;
      add_b[0]    = ~op_b;
      add_c_in[0] = 1'b1;


      res_w       = ~add_res[0][DATA_MSB] ?  add_res[0] : div_oper;
      res_p_w     = add_res[0][DATA_MSB];

      div_co      = ~add_res[0][DATA_MSB] ? add_res[0] : div_oper;
      res_w       = {op_a[DataWidth-3:0], ~add_res[0][DATA_MSB] , ~res_p_msb} ;

      end


    default: begin
        res_w   = op_a;
        res_p_w = op_d_p;
      end
  endcase
end


assign res   = res_w;
assign res_p = res_p_w;













endmodule