//+++++++++++++++++++++++++++++++++++++++++++++++++
//   DUT With Coverage
//+++++++++++++++++++++++++++++++++++++++++++++++++
module cvg_weight();

//    logic [7:0] addr=0;
//    logic [7:0] data, cache=0;
    int addr, data, cache;
    logic par=0;
    logic rw=0;
    logic en=1, clk=0;
    initial forever #10 clk=!clk;
    covergroup cg ( ref int x , ref int y, input int c);
        coverpoint x; // creates coverpoint "x" covering the formal "x"
        //x: coverpoint x; // INVALID: coverpoint label "x" already exists
        b: coverpoint y; // creates coverpoint "b" covering the formal "y"
        c: coverpoint x; // creates coverpoint "c" covering the formal "x"
        option.weight = c; // Line 18: set weight of "cg" to value of formal "c"
        d: coverpoint x {
            option.weight = 2; // set the weight of coverpoint "d"
        }
        //d.option.weight = 2; // INVALID use of "d", also syntax error
        cross x, y { // Creates implicit coverpoint "y" covering
            // the formal "y". Then creates a cross of
            // coverpoints "x", "y"
            option.weight = c; // LINE 26: set weight of cross to value of formal "c"
        }
        // b: cross y, x; // INVALID: coverpoint label "b" already exists
    endgroup
    
    cg cg_inst=new(addr, data, cache); 
    //=================================================
    // Coverage Group
    //=================================================
    covergroup memory (int per_inst=1, get_cvg=1) @ (posedge clk);
        type_option.merge_instances = 0;
        option.per_instance = per_inst;
        option.get_inst_coverage = get_cvg;
        address : coverpoint addr {
            bins low = {[0:50]}; // { [0:63] }; {0,50};
            bins med = {[51:150]};
            bins high = {[151:255]};
        }
        parity : coverpoint par {
            bins even = {0};
            bins odd = {1};
        }
        rdwr : coverpoint rw {
            bins read = {0};
            bins write = {1};
        }
        Xreadlow: cross rdwr, address
        { 
            bins rdlow = binsof(rdwr.read) && binsof(address.low);
            bins rdmed = binsof(rdwr.read) && binsof(address.med);
            bins rdhi = binsof(rdwr.read) && binsof(address.high);
        } 
    endgroup
    // ** Fatal: (vsim-8551) Found a Coverpoint 'rdwr' 
    // in select expression of Cross Bin 'rdlow' 
    //which does not exist in the Coverpoint list of Cross 'Xreadlow'. 
    // The Covergroup instance is '\/simple_coverage/mem '.
    //=================================================
    // Instance of covergroup memory
    //=================================================
    memory mem = new(.per_inst(1), .get_cvg(1));
    //=================================================
    // Task to drive values
    //=================================================
    task drive (input [7:0] a, input [7:0] d, input r);
        #5 en <= 1;
        addr <= a;
        rw <= r;
        data <= d;
        par <= ^d;
        $display ("@%2tns Address :%d data %x, rw %x, parity %x",
            $time,a,d,r, ^d);
        #5 en <= 0;
        //        rw <= 0;
        //        data <= 0;
        //        par <= 0;
        //        addr <= 0;
        //        rw <= 0;
    endtask
    //=================================================
    // Testvector generation
    //=================================================
    always @ (posedge clk) begin
        en = 0;
        ap1: assert(randomize(addr) with {addr < 100;}); 
        ap2: assert(randomize(data) with {data < 20;}); 
        ap4: assert(randomize(cache)); 
        //ap3: assert(randomize(par)); 
        ap3: assert(randomize(rw) with { rw dist {1'b1 :=80, 1'b0 :=20};}); 
        cg_inst.sample(); 
        drive (addr,data,rw);
        // #10 $finish;
    end

endmodule : cvg_weight
