// -------------------------------------------------------------------------------------
// CHECKS
// -------------------------------------------------------------------------------------
integer error_count;
integer warn_count;
integer pass_count;

initial begin
   error_count = 0;
   warn_count = 0;
   pass_count = 0;
end

// ----------------------------------------------------------------------------------------
// MISC
// ----------------------------------------------------------------------------------------
task END_SIM;
   begin

      #500;

      $display("\n\n");
      $display("%% -----------------------------------------");
      if (error_count > 0) begin
         $display("%% Simulation Completed with Errors!!"); 
         $display("%% %0d Error(s) and %0d Warning(s) Detected", error_count,warn_count);
      end
      else if (warn_count > 0) begin
         $display("%% Simulation Completed with Warnings!!");
         $display("%% %0d Warning(s) Detected",warn_count);
      end
      else begin
         $display("%% Simulation Completed Successfully");  
      end

      $display("%%");
      $display("%% END_SIM called @ Time = %0d", $time);
      $display("%% %0d Checks done", pass_count + error_count);
      $display("%% %0d Checks successful", pass_count);
      $display("%% %0d Checks failed", error_count);
      $display("%% -----------------------------------------");
      $display("\n\n");
      $finish(2);  // CPU time and memory used
   end
endtask // END_SIM


// ----------------------------------------------------------------------------------------
// DISPLAY
// ----------------------------------------------------------------------------------------
task COMMENT;
   input [128*8:1] comment_string;
   begin
      $write("\n%% INFO @ %0d ns: %0s", $time, comment_string); 
   end
endtask // COMMENT

task PRINT_WARN;
   input [128*8:1] warning_string;
   begin
      warn_count = warn_count + 1;
      $write("\n%% WARN #%3d @ %0d ns: %0s", warn_count, $time, warning_string);
   end
endtask // PRINT_WARN

task PRINT_ERROR;
   input [128*8:1] error_string;
   begin
      error_count = error_count + 1;
      $write("\n%% ERROR #%3d @ %0d ns: %0s", error_count, $time, error_string);
`ifdef END_ON_ERROR
      END_SIM;
`endif
   end
endtask // PRINT_ERROR

task PRINT_PASS;
   input [128*8:1] pass_string;
   begin
      pass_count = pass_count + 1;
      $write("\n%% PASS #%3d @ %0d ns: %0s", pass_count, $time, pass_string);
   end
endtask // PRINT_PASS

// ----------------------------------------------------------------------------------------
// check_digital_net_id
// ----------------------------------------------------------------------------------------
task check_digital_net_id;
  input [255:0] id;  // 32 characters (32x8=256)
  input signal;
  input expected;

integer        signal;
integer        expected;

begin

  if (expected !== signal)
    begin
      error_count = error_count + 1;
      $write("\n%% ERROR #%3d @ %0d ns: %0s : incorrect digital value", error_count, $time, id);
      $display("\n%% Measured digital value %h, Expected digital value %h\n", signal, expected);
`ifdef END_ON_ERROR
      END_SIM;
`endif
    end
  else
    begin
      pass_count = pass_count + 1;
      $write("\n%% PASS #%3d @ %0d ns: %0s : correct digital value", pass_count, $time, id);
      $display("\n%% Measured digital value %h, Expected digital value %h\n", signal, expected);
    end
end
endtask

// ----------------------------------------------------------------------------------------
// check_digital_net
// ----------------------------------------------------------------------------------------
task check_digital_net;
  input signal;
  input expected;

integer        signal;
integer        expected;

begin

  if (expected !== signal)
    begin
      error_count = error_count + 1;
      $write("\n%% ERROR #%3d @ %0d ns : incorrect digital value", error_count, $time);
      $display("\n%% Measured digital value %h, Expected digital value %h\n", signal, expected);
`ifdef END_ON_ERROR
      END_SIM;
`endif
    end
  else
    begin
      pass_count = pass_count + 1;
      $write("\n%% PASS #%3d @ %0d ns : correct digital value", pass_count, $time);
      $display("\n%% Measured digital value %h, Expected digital value %h\n", signal, expected);
    end
end
endtask

// ----------------------------------------------------------------------------------------
// i2c_write_fields
// ----------------------------------------------------------------------------------------
task i2c_write_fields;
input addr;
integer addr;

reg [7:0] this_reg;
integer j;
begin
    #0; // this is needed to make sure the wire update event is 
        // scheduled first
    for (j = 0; j < 8 ; j = j + 1)
    begin
        this_reg[j] = i2c_fields[8*addr+j];
    end
    i2c_master.i2cWrHS(addr, this_reg);
    COMMENT("");
    $display("I2C Reg. %3d Write: Data %s", addr, groupby4(this_reg, 0));
end
endtask // i2c_write_fields

// ----------------------------------------------------------------------------------------
// i2c_read_fields
// ----------------------------------------------------------------------------------------
task i2c_read_fields;
input addr;
input [7:0] mask_val;
reg   [7:0] expect_val;
reg   [7:0] return_val;
reg   [7:0] actual_val;

integer addr;
integer j;

begin
    #0; // this is needed to make sure the wire update event is 
        // scheduled first
        //the mask_val contains a 1 for the bits to compare against

    i2c_master.i2cRd( addr );
    return_val = i2c_master.i2c_rdback_val;
    for (j = 0; j < 8 ; j = j + 1)
    begin
        expect_val[j] = i2c_fields [8*addr+j] & mask_val [j]; 
        actual_val[j] = return_val [j]        & mask_val [j]; 
    end

    if (expect_val !== actual_val) begin
       PRINT_ERROR("");  
       $display("FAIL: I2C Reg. %3d Read Check ERROR.", addr);
       $display("%%\t\tBit #:    7654_3210");
       $display("%%\t\t          ---------");
       $display("%%\t\tMask:     %s,", groupby4(mask_val, 0));
       $display("%%\t\tRead:     %s,", groupby4(return_val, 0));
       $display("%%\t\tExpected: %s" , groupby4(expect_val, 0));
    end
    else begin
       PRINT_PASS(""); 
       $display("PASS: I2C Reg. %3d Read Check PASS.", addr);
       $display("%%\t\tMask:     %s,", groupby4(mask_val, 0));
       $display("%%\t\tRead:     %s,", groupby4(return_val, 0));
       $display("%%\t\tExpected: %s" , groupby4(expect_val, 0));
    end
end
endtask // i2c_read_fields

// ----------------------------------------------------------------------------------------
// groupby4
// ----------------------------------------------------------------------------------------
function [80 : 1] groupby4;
   input [8:1] regin;
   input changez;
   integer i;

   begin
      i = 8;
      groupby4 = 0;
      while (i >= 1)
        begin

           case (regin[i])
           1'b0 : groupby4[8:1] = "0";
           1'b1 : groupby4[8:1] = "1";
           1'bx : groupby4[8:1] = "x";
           1'bz : groupby4[8:1] = changez ? "?" : "z";
           default : groupby4[8:1] = "u";
           endcase


           groupby4 = groupby4 << 8;
           i = i - 1;
           if ( i !=0 &&  !(i % 4))
             begin
                groupby4[8:1] = "_";
                groupby4 = groupby4 << 8;
             end
        end
   end

endfunction // groupby4
