// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2007 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0

module t (/*AUTOARG*/
   // Inputs
   clk
   );

   input clk;
   reg   toggle;
   integer cyc; initial cyc=1;

   Test test (/*AUTOINST*/
              // Inputs
              .clk                      (clk),
              .toggle                   (toggle),
              .cyc                      (cyc[31:0]));

   Sub sub1 (.*);
   Sub sub2 (.*);

   always @ (posedge clk) begin
      if (cyc!=0) begin
         cyc <= cyc + 1;
         toggle <= !cyc[0];
         if (cyc==9) begin
         end
         if (cyc==10) begin
            $write("*-* All Finished *-*\n");
            $finish;
         end
      end
   end

endmodule

module Test
  (
   input clk,
   input toggle,
   input [31:0] cyc
   );

   // Simple cover
   cover property (@(posedge clk) cyc==3);

   // With statement, in generate
   generate if (1) begin
      cover property (@(posedge clk) cyc==4) $display("*COVER: Cyc==4");
   end
   endgenerate

   // Labeled cover
   cyc_eq_5:
     cover property (@(posedge clk) cyc==5) $display("*COVER: Cyc==5");

   // Using default clock
   default clocking @(posedge clk); endclocking
   cover property (cyc==6) $display("*COVER: Cyc==6");

   // Disable statement
   // Note () after disable are required
   cover property (@(posedge clk) disable iff (toggle) cyc==8)
     $display("*COVER: Cyc==8");
   cover property (@(posedge clk) disable iff (!toggle) cyc==8)
     $stop;

   always_ff @ (posedge clk) begin
      labeled_icov: cover (cyc==3 || cyc==4);
   end

   // Immediate cover
   labeled_imm0: cover #0 (cyc == 0);
   labeled_immf: cover final (cyc == 0);

   // Immediate assert
   labeled_imas: assert #0 (1);
   assert final (1);

   //============================================================
   // Using a macro and generate
   wire reset = (cyc < 2);

`define covclk(eqn) cover property (@(posedge clk) disable iff (reset) (eqn))

   genvar i;
   generate
      for (i=0; i<32; i=i+1)
        begin: cycval
           CycCover_i: `covclk( cyc[i] );
        end
   endgenerate

`ifndef verilator // Unsupported
   //============================================================
   // Using a more complicated property
   property C1;
      @(posedge clk)
        disable iff (!toggle)
        cyc==5;
   endproperty
   cover property (C1) $display("*COVER: Cyc==5");

   // Using covergroup
   // Note a covergroup is really inheritance of a special system "covergroup" class.
   covergroup counter1 @ (posedge cyc);
      // Automatic methods:  stop(), start(), sample(), set_inst_name()

      // Each bin value must be <= 32 bits.  Strange.
      cyc_value : coverpoint cyc {
        }

      cyc_bined : coverpoint cyc {
         bins zero    = {0};
         bins low    = {1,5};
         // Note 5 is also in the bin above.  Only the first bin matching is counted.
         bins mid   = {[5:$]};
         // illegal_bins        // Has precidence over "first matching bin", creates assertion
         // ignore_bins         // Not counted, and not part of total
      }
      toggle : coverpoint (toggle) {
         bins off  = {0};
         bins on   = {1};
      }
      cyc5 : coverpoint (cyc==5) {
         bins five  = {1};
      }

      // option.at_least = {number};    // Default 1 - Hits to be considered covered
      // option.auto_bin_max = {number}; // Default 64
      // option.comment = {string}
      // option.goal = {number};        // Default 90%
      // option.name = {string}
      // option.per_instance = 1;       // Default 0 - each instance separately counted (cadence default is 1)
      // option.weight = {number};      // Default 1

      // CROSS
      value_and_toggle:  // else default is __<firstlabel>_X_<secondlabel>_<n>
        cross cyc_value, toggle;
   endgroup
   counter1 c1 = new();
`endif

endmodule

module Sub
  (
   input clk,
   input integer cyc
   );

   // Simple cover, per-instance
   pi_sub:
     cover property (@(posedge clk) cyc == 3);
endmodule
