Source code for vsc.model.coverpoint_cross_model

# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#  http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.

# Created on Aug 3, 2019
#
# @author: ballance


import random
from typing import Set, Tuple, List

from vsc.model.coveritem_base import CoverItemBase
from vsc.model.expr_model import ExprModel
from vsc.model.rand_if import RandIF
from vsc.model.expr_bin_model import ExprBinModel
from vsc.model.bin_expr_type import BinExprType


[docs]class CoverpointCrossModel(CoverItemBase): def __init__(self, name, options, iff=None): super().__init__() self.parent = None self.name = name self.iff = iff self.iff_val_cache = True self.iff_val_cache_valid = False self.coverpoint_model_l = [] self.finalized = False self.n_bins = 0 # Need to map (tuple)->bin_idx (for coverage recording) # Need to map bin_idx->(tuple) (for constraint driving) # Need to track unhit bin indexes self.hit_l : List[int] = [] self.tuple2idx_m : Dict[Tuple,int] = {} self.idx2tuple_m : Dict[int,Tuple] = {} self.unhit_s : Set[Tuple] = set() self.srcinfo_decl = None self.coverage = 0.0 self.coverage_calc_valid = False self.options = options
[docs] def set_target_value_cache(self, iff): self.iff_val_cache = iff self.iff_val_cache_valid = True
[docs] def reset(self): self.iff_val_cache_valid = False
[docs] def coverpoints(self): return self.coverpoint_model_l
[docs] def get_coverage(self): if not self.coverage_calc_valid: self.coverage = (len(self.hit_l)-len(self.unhit_s))/len(self.hit_l) * 100.0 self.coverage_calc_valid = True return self.coverage
[docs] def get_n_bins(self): return self.n_bins
[docs] def get_bin_expr(self, bin_idx:int)->ExprModel: ret = None key_t = self.idx2tuple_m[bin_idx] for i in range(len(self.coverpoint_model_l)): cp_expr = self.coverpoint_model_l[i].get_bin_expr(key_t[i]) ret = cp_expr if ret is None else ExprBinModel( ret, BinExprType.And, cp_expr) return ret
[docs] def select_unhit_bin(self, r:RandIF)->int: if len(self.unhit_s) > 0: return random.sample(sorted(self.unhit_s), 1)[0] else: return -1
[docs] def get_bin_hits(self, bin_idx): return self.hit_l[bin_idx]
[docs] def get_bin_name(self, bin_idx)->str: t = self.idx2tuple_m[bin_idx] ret = "<" for i in range(len(t)): idx = t[i] if i > 0: ret += "," ret += self.coverpoint_model_l[i].get_bin_name(idx) ret += ">" return ret
[docs] def add_coverpoint(self, cp_m): self.coverpoint_model_l.append(cp_m)
[docs] def finalize(self): if not self.finalized: self._build_hit_map(0, []) self.hit_l = [0]*self.n_bins self.finalized = True
[docs] def accept(self, v): v.visit_coverpoint_cross(self)
def _build_hit_map(self, i, key_m): for bin_i in range(self.coverpoint_model_l[i].get_n_bins()): key_m.append(bin_i) if i+1 >= len(self.coverpoint_model_l): key = tuple(key_m) # Reached the bottom of the list # print("Tuple: " + str(key)) self.tuple2idx_m[key] = self.n_bins self.idx2tuple_m[self.n_bins] = key self.unhit_s.add(self.n_bins) self.n_bins += 1 else: self._build_hit_map(i+1, key_m) key_m.pop()
[docs] def sample(self): if not self.finalized: raise Exception("Cross sampled before finalization") if self.iff is not None and not self.iff_val_cache_valid: self.iff_val_cache = bool(self.iff.val()) self.iff_val_cache_valid = True have_cp_hit = self.iff_val_cache key_m = [] if have_cp_hit: for cp in self.coverpoint_model_l: have_bin_hit = False if cp.iff_val_cache: idx = 0 for b in cp.bin_model_l: if b.hit_idx() != -1: key_m.append(b.hit_idx() + idx) have_bin_hit = True break else: idx += b.get_n_bins() if have_bin_hit: have_cp_hit = True else: have_cp_hit = False break else: have_cp_hit = False break if have_cp_hit: key = tuple(key_m) bin_idx = self.tuple2idx_m[key] self.hit_l[bin_idx] += 1 if bin_idx in self.unhit_s: # New bin hit self.parent.coverage_ev(self, bin_idx) self.unhit_s.remove(bin_idx) self.coverage_calc_valid = False
[docs] def dump(self, ind=""): print(ind + "Cross: " + self.name) for i,count in enumerate(self.hit_l): print(ind + " " + str(i) + "=" + str(count))
[docs] def equals(self, oth : 'CoverpointCrossModel')->bool: eq = True if len(self.coverpoint_model_l) == len(oth.coverpoint_model_l): for i in range(len(self.coverpoint_model_l)): eq &= self.coverpoint_model_l[i].equals(oth.coverpoint_model_l[i]) else: eq = False return eq
[docs] def clone(self, coverpoint_m)->'CoverpointCrossModel': ret = CoverpointCrossModel(self.name, self.options.clone()) ret.srcinfo_decl = None if self.srcinfo_decl is None else self.srcinfo_decl.clone() for cp in self.coverpoint_model_l: ret.add_coverpoint(coverpoint_m[cp]) return ret