Update tb: 1. fix xrf retire condition in monitor 2. Fix vcpop/vfirst logic 3. Fix tail elements behavior of mask producing instructions. Now it will writeback calculation result for tail element.

Change-Id: I9629e3b80b92935b90368a179e432dd7c44e2393
diff --git a/hdl/verilog/rvv/sve/rvv_backend_tb/src/rvs_agent_rvs_monitor.sv b/hdl/verilog/rvv/sve/rvv_backend_tb/src/rvs_agent_rvs_monitor.sv
index cb8baa0..65c252c 100644
--- a/hdl/verilog/rvv/sve/rvv_backend_tb/src/rvs_agent_rvs_monitor.sv
+++ b/hdl/verilog/rvv/sve/rvv_backend_tb/src/rvs_agent_rvs_monitor.sv
@@ -107,7 +107,8 @@
       // `uvm_info(get_type_name(),$sformatf("rt_uop=0x%1x, rt_last_uop=0x%1x",rvs_if.rt_uop, rvs_if.rt_last_uop), UVM_HIGH)
       for(int rt_idx=0; rt_idx<`NUM_RT_UOP; rt_idx++) begin
         if(rvs_if.rt_uop[rt_idx]) begin
-          while(!(rvs_if.rt_vrf_valid_rob2rt[rt_idx] && (rvs_if.rt_vrf_data_rob2rt[rt_idx].uop_pc === tr.pc))) begin
+          while(!(rvs_if.rt_vrf_valid_rob2rt[rt_idx] && (rvs_if.rt_vrf_data_rob2rt[rt_idx].uop_pc === tr.pc)) && 
+                !(rvs_if.rt_xrf_valid_rvv2rvs[rt_idx] && rvs_if.rt_xrf_ready_rvs2rvv[rt_idx] && (rvs_if.rt_xrf_rvv2rvs[rt_idx].uop_pc === tr.pc))) begin
               `uvm_info(get_type_name(), $sformatf("Monitor rx_queue pc(0x%8x) mismatch with DUT pc(0x%8x), discarded.", tr.pc, rvs_if.rt_vrf_data_rob2rt[rt_idx].uop_pc), UVM_HIGH)
               `uvm_info(get_type_name(), tr.sprint(),UVM_HIGH)
               tr = inst_rx_queue.pop_front();
diff --git a/hdl/verilog/rvv/sve/rvv_backend_tb/src/rvs_agent_rvs_transaction.sv b/hdl/verilog/rvv/sve/rvv_backend_tb/src/rvs_agent_rvs_transaction.sv
index 7e2f95d..f028568 100644
--- a/hdl/verilog/rvv/sve/rvv_backend_tb/src/rvs_agent_rvs_transaction.sv
+++ b/hdl/verilog/rvv/sve/rvv_backend_tb/src/rvs_agent_rvs_transaction.sv
@@ -51,6 +51,8 @@
        lmul_e src2_emul;
        lmul_e src3_emul;
        vext_e src1_func_vext;
+       vwxunary0_e src1_func_vwxunary0;
+       vmunary0_e  src1_func_vmunary0;
    
   rand logic [`XLEN-1:0] rs_data;
 
@@ -243,17 +245,33 @@
 
     `uvm_field_enum(oprand_type_e,dest_type,UVM_ALL_ON)
     `uvm_field_int(dest_idx,UVM_ALL_ON)
-    `uvm_field_enum(oprand_type_e,src1_type,UVM_ALL_ON)
     if(src1_type == FUNC && inst_type == ALU && alu_inst == VXUNARY0) begin
+      `uvm_field_enum(oprand_type_e,src1_type,UVM_ALL_ON)
       `uvm_field_enum(vext_e,src1_func_vext,UVM_ALL_ON)
-    end else begin
+      `uvm_field_int(src1_idx,UVM_ALL_ON)
+    end else if(src1_type == FUNC && inst_type == ALU && alu_inst == VWXUNARY0) begin
+      `uvm_field_enum(oprand_type_e,src1_type,UVM_ALL_ON)
+      `uvm_field_enum(vwxunary0_e,src1_func_vwxunary0,UVM_ALL_ON)
+      `uvm_field_int(src1_idx,UVM_ALL_ON)
+    end else if(src1_type == FUNC && inst_type == ALU && alu_inst == VMUNARY0) begin
+      `uvm_field_enum(oprand_type_e,src1_type,UVM_ALL_ON)
+      `uvm_field_enum(vmunary0_e,src1_func_vmunary0,UVM_ALL_ON)
+      `uvm_field_int(src1_idx,UVM_ALL_ON)
+    end else if(src1_type != UNUSE) begin
+      `uvm_field_enum(oprand_type_e,src1_type,UVM_ALL_ON)
       `uvm_field_int(src1_idx,UVM_ALL_ON)
     end
-    `uvm_field_enum(oprand_type_e,src2_type,UVM_ALL_ON)
-    `uvm_field_int(src2_idx,UVM_ALL_ON)
-    `uvm_field_enum(oprand_type_e,src3_type,UVM_ALL_ON)
-    `uvm_field_int(src3_idx,UVM_ALL_ON)
-    `uvm_field_int(rs_data,UVM_ALL_ON)
+    if(src2_type != UNUSE) begin
+      `uvm_field_enum(oprand_type_e,src2_type,UVM_ALL_ON)
+      `uvm_field_int(src2_idx,UVM_ALL_ON)
+    end
+    if(src3_type != UNUSE) begin
+      `uvm_field_enum(oprand_type_e,src3_type,UVM_ALL_ON)
+      `uvm_field_int(src3_idx,UVM_ALL_ON)
+    end
+    if(src1_type == XRF || src2_type == XRF) begin
+      `uvm_field_int(rs_data,UVM_ALL_ON)
+    end
 
 
     if(is_rt) begin
@@ -296,6 +314,8 @@
     use_vm_to_cal = 0;
   
   if(src1_type == FUNC && inst_type == ALU && alu_inst == VXUNARY0) $cast(src1_func_vext,src1_idx);
+  if(src1_type == FUNC && inst_type == ALU && alu_inst == VWXUNARY0) $cast(src1_func_vwxunary0,src1_idx);
+  if(src1_type == FUNC && inst_type == ALU && alu_inst == VMUNARY0) $cast(src1_func_vmunary0,src1_idx);
   
   // rs random data
   if(src1_type != XRF && src2_type != XRF) rs_data = 'x;
@@ -363,6 +383,10 @@
           inst = "vmv.v";
         else
           inst = "vmerge";
+      end else if(alu_inst inside {VWXUNARY0}) begin
+        inst = src1_func_vwxunary0.name();
+      end else if(alu_inst inside {VMUNARY0}) begin
+        inst = src1_func_vmunary0.name();
       end else begin
         inst = this.alu_inst.name();
       end
@@ -377,9 +401,10 @@
     FUNC: begin
       if(inst_type == ALU && alu_inst == VXUNARY0 && src1_idx inside{VSEXT_VF4, VSEXT_VF4}) begin
         suf1 = "f4"; src1 = "";
-      end
-      if(inst_type == ALU && alu_inst == VXUNARY0 && src1_idx inside{VSEXT_VF2, VSEXT_VF2}) begin
+      end else if(inst_type == ALU && alu_inst == VXUNARY0 && src1_idx inside{VSEXT_VF2, VSEXT_VF2}) begin
         suf1 = "f2"; src1 = "";
+      end else if(inst_type == ALU && alu_inst inside {VMAND, VMOR, VMXOR, VMORN, VMNAND, VMNOR, VMANDN, VMXNOR}) begin
+        suf1 = "m"; src1 = $sformatf("v%0d",this.src1_idx); 
       end
     end
     default: begin suf1 = "?"; src1 = "?"; end
@@ -388,12 +413,16 @@
     VRF: begin 
       if(inst_type == ALU && alu_inst inside {VWADDU_W, VWADD_W, VWSUBU_W, VWSUB_W}) begin
         suf2 = "w"; src2 = $sformatf("v%0d",this.src2_idx); 
+      end else if(inst_type == ALU && alu_inst inside {VMAND, VMOR, VMXOR, VMORN, VMNAND, VMNOR, VMANDN, VMXNOR,
+                                                       VWXUNARY0, VMUNARY0}) begin
+        suf2 = "m"; src2 = $sformatf("v%0d",this.src2_idx); 
       end else begin
         suf2 = "v"; src2 = $sformatf("v%0d",this.src2_idx); 
       end
     end
     XRF: begin suf2 = "x"; src2 = $sformatf("x%0d",this.src2_idx); end
     IMM: begin suf2 = "i"; src2 = $sformatf("%0d",$signed(this.src2_idx)); end
+    default: begin suf1 = "?"; src1 = "?"; end
   endcase
   if(vm == 0) begin
     if(inst_type == ALU && use_vm_to_cal == 1) begin
diff --git a/hdl/verilog/rvv/sve/rvv_backend_tb/src/rvv_behavior_model.sv b/hdl/verilog/rvv/sve/rvv_backend_tb/src/rvv_behavior_model.sv
index 834f2a8..86a2df3 100644
--- a/hdl/verilog/rvv/sve/rvv_backend_tb/src/rvv_behavior_model.sv
+++ b/hdl/verilog/rvv/sve/rvv_backend_tb/src/rvv_behavior_model.sv
@@ -151,6 +151,7 @@
     bit is_widen_inst;
     bit is_widen_vs2_inst;
     bit is_narrow_inst;
+    bit is_mask_producing_inst;
     bit use_vm_to_cal;
 
     bit vm;
@@ -246,6 +247,10 @@
                                                                               VWMUL, VWMULU, VWMULSU, VWMACCU, VWMACC, VWMACCUS, VWMACCSU});
         is_widen_vs2_inst = inst_tr.inst_type == ALU && (inst_tr.alu_inst inside {VWADD_W, VWADDU_W, VWSUBU_W, VWSUB_W});
         is_narrow_inst = inst_tr.inst_type == ALU && (inst_tr.alu_inst inside {VNSRL, VNSRA, VNCLIPU, VNCLIP});
+        is_mask_producing_inst = inst_tr.inst_type == ALU && (inst_tr.alu_inst inside {VMAND, VMOR, VMXOR, VMORN, VMNAND, VMNOR, VMANDN, VMXNOR,
+                                                                                       VMADC, VMSBC, 
+                                                                                       VMSEQ, VMSNE, VMSLTU, VMSLT, VMSLEU, VMSLE, VMSGTU, VMSGT,
+                                                                                       VMUNARY0});
         use_vm_to_cal = inst_tr.use_vm_to_cal;
 
         // 1.0 illegal inst check
@@ -399,6 +404,8 @@
               src2_emul = src2_emul * src2_eew / eew;
               src1_eew = EEW1;
               src1_emul = src1_emul * src1_eew / eew;
+              // Special case: In this case, DUT will writeback all bits in dest.
+              elm_idx_max = `VLEN;
             end
             if(inst_tr.inst_type == ALU && inst_tr.alu_inst inside {VMADC, VMSBC, 
                 VMSEQ, VMSNE, VMSLTU, VMSLT, VMSLEU, VMSLE, VMSGTU, VMSGT}) begin
@@ -412,6 +419,8 @@
               src2_emul = src2_emul * src2_eew / eew;
               src1_eew = EEW1;
               src1_emul = src1_emul * src1_eew / eew;
+              // Special case: In this case, DUT will writeback all bits in dest.
+              elm_idx_max = `VLEN;
             end
             if(inst_tr.inst_type == ALU && inst_tr.alu_inst inside {VMUNARY0} && inst_tr.src1_idx inside {VIOTA, VID}) begin
               src2_eew = EEW1;
@@ -616,27 +625,45 @@
           endcase
 
           if(elm_idx < vstart) begin
-            `uvm_info("MDL", $sformatf("element[%2d]: pre-start", elm_idx), UVM_LOW)
             // pre-start: do nothing
+            if(is_mask_producing_inst) begin
+              //  If is mask producing operation, it will write with calculation results.
+              `uvm_info("MDL", $sformatf("element[%2d]: pre-start, mask producing operation", elm_idx), UVM_LOW)
+              elm_writeback(dest, inst_tr.dest_type, dest_reg_idx_base, elm_idx, dest_eew);
+            end else begin 
+              `uvm_info("MDL", $sformatf("element[%2d]: pre-start", elm_idx), UVM_LOW)
+            end
           end else if(elm_idx >= vl) begin
-            // tail
-            `uvm_info("MDL", $sformatf("element[%2d]: tail", elm_idx), UVM_LOW)
-            if(vtype.vta == AGNOSTIC) begin
-              if(all_one_for_agn) begin 
-                dest = '1;
-                elm_writeback(dest, inst_tr.dest_type, dest_reg_idx_base, elm_idx, dest_eew);
+            // tail 
+            if(is_mask_producing_inst) begin
+              //  If is mask producing operation, it will write with calculation results.
+              `uvm_info("MDL", $sformatf("element[%2d]: tail, mask producing operation", elm_idx), UVM_LOW)
+              dest = alu_handler.exe(inst_tr, dest, src2, src1, src0);
+              elm_writeback(dest, inst_tr.dest_type, dest_reg_idx_base, elm_idx, dest_eew);
+            end else begin 
+              `uvm_info("MDL", $sformatf("element[%2d]: tail", elm_idx), UVM_LOW)
+              if(vtype.vta == AGNOSTIC) begin
+                if(all_one_for_agn) begin 
+                  dest = '1;
+                  elm_writeback(dest, inst_tr.dest_type, dest_reg_idx_base, elm_idx, dest_eew);
+                end
+              end else begin
               end
-            end else begin
             end
           end else if(!(vm || this.vrf[0][elm_idx] || use_vm_to_cal)) begin
             // body-inactive
-            `uvm_info("MDL", $sformatf("element[%2d]: body-inactive", elm_idx), UVM_LOW)
-            if(vtype.vma == AGNOSTIC) begin
-              if(all_one_for_agn) begin 
-                dest = '1;
-                elm_writeback(dest, inst_tr.dest_type, dest_reg_idx_base, elm_idx, dest_eew);
-              end
+            if(is_mask_producing_inst) begin
+              `uvm_info("MDL", $sformatf("element[%2d]: body-inactive, mask producing operation", elm_idx), UVM_LOW)
+              elm_writeback(dest, inst_tr.dest_type, dest_reg_idx_base, elm_idx, dest_eew);
             end else begin
+              `uvm_info("MDL", $sformatf("element[%2d]: body-inactive", elm_idx), UVM_LOW)
+              if(vtype.vma == AGNOSTIC) begin
+                if(all_one_for_agn) begin 
+                  dest = '1;
+                  elm_writeback(dest, inst_tr.dest_type, dest_reg_idx_base, elm_idx, dest_eew);
+                end
+              end else begin
+              end
             end
           end else begin
             // body-active
@@ -797,7 +824,7 @@
   bit overflow;
   bit underflow;
   int mask_count;
-  bit first_mask_bit;
+  bit found_first_mask;
   int first_mask_idx;
   pure virtual function alu_unsigned_t exe (rvs_transaction inst_tr, alu_unsigned_t dest, alu_unsigned_t src2, alu_unsigned_t src1, alu_unsigned_t src0);
   pure virtual function alu_unsigned_t _roundoff_unsigned(alu_unsigned_t v, int unsigned d);
@@ -806,7 +833,7 @@
     this.overflow = 1'b0;
     this.underflow = 1'b0;
     this.mask_count = 'b0;
-    this.first_mask_bit = 1'b0;
+    this.found_first_mask = 1'b0;
     this.first_mask_idx =  'b0;
   endfunction: reset
   virtual function void set_vxrm(vxrm_e val);
@@ -1439,74 +1466,69 @@
   //---------------------------------------------------------------------- 
   // Ch31.15.1. Vector Mask-Register Logical Instructions
   function TD _vmand(T2 src2, T1 src1);
-    _vmand = src1 & src2;
+    _vmand = src2 & src1;
   endfunction : _vmand
   function TD _vmor(T2 src2, T1 src1);
-    _vmor = src1 | src2;
+    _vmor = src2 | src1;
   endfunction : _vmor
   function TD _vmxor(T2 src2, T1 src1);
-    _vmxor = src1 ^ src2;
+    _vmxor = src2 ^ src1;
   endfunction : _vmxor
   function TD _vmorn(T2 src2, T1 src1);
-    _vmorn = src1 | ~src2;
+    _vmorn = src2 | ~src1;
   endfunction : _vmorn
   function TD _vmnand(T2 src2, T1 src1);
-    _vmnand = ~(src1 & src2);
+    _vmnand = ~(src2 & src1);
   endfunction : _vmnand
   function TD _vmnor(T2 src2, T1 src1);
-    _vmnor = ~(src1 | src2);
+    _vmnor = ~(src2 | src1);
   endfunction : _vmnor
   function TD _vmandn(T2 src2, T1 src1);
-    _vmandn = src1 & ~src2;
+    _vmandn = src2 & ~src1;
   endfunction : _vmandn
   function TD _vmxnor(T2 src2, T1 src1);
-    _vmxnor = ~(src1 ^ src2);
+    _vmxnor = ~(src2 ^ src1);
   endfunction : _vmxnor
 
   //---------------------------------------------------------------------- 
   // 31.15.2. Vector count population in mask vcpop.m
   function TD _vcpop(T2 src2);
-    if(this.elm_idx == 0) begin
-      _vcpop = 0;
-      this.mask_count = 0;
-    end else begin
-      _vcpop = this.mask_count;
-      this.mask_count += src2;
-    end
+    this.mask_count += src2;
+    _vcpop = this.mask_count;
   endfunction: _vcpop
 
   //---------------------------------------------------------------------- 
   // 32.15.3. vfirst find-first-set mask bit
   function TD _vfirst(T2 src2);
-    if(!this.first_mask_bit) begin
-      this.first_mask_idx = '0;
-    end else if(src2 && !this.first_mask_bit) begin
-      this.first_mask_bit = 1'b1;
+    if(src2 && !this.found_first_mask) begin
+      this.found_first_mask = 1'b1;
       this.first_mask_idx = this.elm_idx;
     end else begin
       this.first_mask_idx = this.first_mask_idx;
     end
     _vfirst = this.first_mask_idx;
+    `uvm_info("MDL", $sformatf("found_first_mask=%0d, first_mask_idx=%0d, elm_idx=%0d", 
+                                found_first_mask, first_mask_idx, elm_idx),UVM_HIGH)
   endfunction: _vfirst
 
   //---------------------------------------------------------------------- 
   // 32.15.4. vmsbf.m set-before-first mask bit
   function TD _vmsbf(T2 src2);
-    if(!first_mask_bit) begin
+    if(!found_first_mask) begin
       _vmsbf = 1'b1;
     end else begin
       _vmsbf = 1'b0;
     end
-    if(src2 & ~first_mask_bit) begin
-      first_mask_bit = 1'b1; 
+    if(src2 & ~found_first_mask) begin
+      found_first_mask = 1'b1; 
     end
   endfunction: _vmsbf
 
   //---------------------------------------------------------------------- 
   // 32.15.5. vmsif.m set-including-first mask bit
   function TD _vmsof(T2 src2);
-    if(src2 & ~first_mask_bit) begin 
-      first_mask_bit = 1'b1; 
+    if(src2 & ~found_first_mask) begin 
+      found_first_mask = 1'b1; 
       _vmsof = 1'b1;
     end else begin
       _vmsof = 1'b0;
@@ -1516,10 +1538,10 @@
   //---------------------------------------------------------------------- 
   // 32.15.6. vmsof.m set-only-first mask bit
   function TD _vmsif(T2 src2);
-    if(src2 & ~first_mask_bit) begin 
-      first_mask_bit = 1'b1; 
+    if(src2 & ~found_first_mask) begin 
+      found_first_mask = 1'b1; 
     end
-    if(!first_mask_bit) begin
+    if(!found_first_mask) begin
       _vmsif = 1'b1;
     end else begin
       _vmsif = 1'b0;