fnob_rand.sv (615 lines of code) (raw):

//################################################################################### // Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. // The following information is considered proprietary and confidential to Facebook, // and may not be disclosed to any third party nor be used for any purpose other // than to full fill service obligations to Facebook //################################################################################### `ifndef __FNOB_RAND_SV__ `define __FNOB_RAND_SV__ //================================================================================ //Abstract class, must implement below functions in child class //1. init //2. gen virtual class fnob_rand#(type T=bit[63:0]) extends uvm_object; T m_fnob_gen; //-------------------------------------------------------------------------------- function new(string name=""); super.new(); endfunction // new //-------------------------------------------------------------------------------- static function fnob_rand#(T) init(string name); //fnob_rand#(T) fr = new(name); //return fr; endfunction // init //-------------------------------------------------------------------------------- pure virtual function T gen(); endclass // fnob_rand //================================================================================ //Gaussian disribution class fnob_rand_norm#(type T=bit[63:0]) extends fnob_rand#(T); T m_norm,m_range, m_gen; //-------------------------------------------------------------------------------- covergroup fnob_cg; option.per_instance = 1; option.goal = 100; option.comment = "fnob_cg"; fnob_rand_cg:coverpoint m_gen{ bins val_norm = {m_norm}; } endgroup // fnob_cg //-------------------------------------------------------------------------------- function new(string name="", T params[$]); super.new(name); m_norm = params[0]; m_range = params[1]; fnob_cg = new; fnob_cg.option.name = name; endfunction // new //-------------------------------------------------------------------------------- static function fnob_rand#(T) init(string name, T params[$]); fnob_rand_norm#(T) fr = new(name, params); return fr; endfunction // init //-------------------------------------------------------------------------------- virtual function T gen(); int pos; $display("norm=%0d, range=%0d", m_norm, m_range); pos = $dist_normal($urandom, 50, 10); if (pos > 100) pos = 100; else if (pos < 0) pos = 0; //scale pos to actual value if(pos > 50) m_gen = ((pos-50) * 1.0 / 50) * m_range + m_norm; else m_gen = m_norm - ((50 - pos) * 1.0 / 50) * m_range; fnob_cg.sample(); m_fnob_gen = m_gen; return m_gen; endfunction // gen endclass // fnob_rand_norm //================================================================================ //inverted Gaussian disribution //{val:mean,range} -> generate a number in [mean-range:mean+range] class fnob_rand_inv_norm#(type T=bit[63:0]) extends fnob_rand#(T); T m_norm,m_range, m_gen; //-------------------------------------------------------------------------------- covergroup fnob_cg; option.per_instance = 1; option.goal = 100; option.comment = "fnob_cg"; fnob_rand_cg:coverpoint m_gen{ bins val_norm = {m_norm}; } endgroup // fnob_cg //-------------------------------------------------------------------------------- function new(string name="", T params[$]); super.new(name); m_norm = params[0]; m_range = params[1]; fnob_cg = new; fnob_cg.option.name = name; endfunction // new //-------------------------------------------------------------------------------- static function fnob_rand#(T) init(string name, T params[$]); fnob_rand_inv_norm#(T) fr = new(name, params); return fr; endfunction // init //-------------------------------------------------------------------------------- virtual function T gen(); int pos; $display("norm=%0d, range=%0d", m_norm, m_range); pos = $dist_normal($urandom, 50, 10); if (pos > 100) pos = 100; else if (pos < 0) pos = 0; //scale pos to actual value if(pos > 50) m_gen = ((100 - pos) * 1.0 / 50) * m_range + m_norm; else m_gen = m_norm - (pos * 1.0 / 50) * m_range; fnob_cg.sample(); m_fnob_gen = m_gen; return m_gen; endfunction // gen endclass // fnob_rand_inv_norm //================================================================================ class fnob_rand_unif#(type T=bit[63:0]) extends fnob_rand#(T); T m_unif_min, m_unif_max, m_unif_mid, m_gen; //-------------------------------------------------------------------------------- covergroup fnob_cg; option.per_instance = 1; option.goal = 100; option.comment = "fnob_cg"; fnob_rand_cg:coverpoint m_gen{ bins val_min = {m_unif_min}; bins val_max = {m_unif_max}; bins val_mid = {m_unif_mid}; } endgroup // fnob_cg //-------------------------------------------------------------------------------- function new(string name="", T params[$]); super.new(name); m_unif_min = params[0]; m_unif_max = params[1]; m_unif_mid = (m_unif_min + m_unif_max) / 2; assert(m_unif_min <= m_unif_max); fnob_cg = new; fnob_cg.option.name = name; endfunction // new //-------------------------------------------------------------------------------- static function fnob_rand#(T) init(string name, T params[$]); fnob_rand_unif#(T) fr = new(name, params); return fr; endfunction // init //-------------------------------------------------------------------------------- virtual function T gen(); //$display("min=%0d max=%0d", m_unif_min, m_unif_max); m_gen = $urandom_range(m_unif_min, m_unif_max); fnob_cg.sample(); m_fnob_gen = m_gen; return m_gen; endfunction // gen endclass // fnob_rand_unif //================================================================================ class fnob_randc_unif#(type T=bit[63:0]) extends fnob_rand#(T); T m_unif_min, m_unif_max, m_gen; T m_vals[$]; //-------------------------------------------------------------------------------- covergroup fnob_cg; option.per_instance = 1; option.goal = 100; option.comment = "fnob_cg"; fnob_rand_cg:coverpoint m_gen{ bins val_all[] = {[m_unif_min : m_unif_max]}; } endgroup // fnob_cg //-------------------------------------------------------------------------------- function new(string name="", T params[$]); super.new(name); m_unif_min = params[0]; m_unif_max = params[1]; assert(m_unif_min <= m_unif_max); fnob_cg = new; fnob_cg.option.name = name; //create m_vals queue init_queue(); endfunction // new //-------------------------------------------------------------------------------- static function fnob_rand#(T) init(string name, T params[$]); fnob_randc_unif#(T) fr = new(name, params); return fr; endfunction //-------------------------------------------------------------------------------- virtual function T gen(); if(m_vals.size() == 0) init_queue(); m_gen = m_vals.pop_front(); //$display("%p", m_vals); fnob_cg.sample(); m_fnob_gen = m_gen; return m_gen; endfunction // gen virtual function void init_queue(); for(int i=m_unif_min; i<=m_unif_max; i=i+1) begin m_vals.push_back(i); end m_vals.shuffle(); endfunction: init_queue endclass // fnob_randc_unif //================================================================================ class fnob_rand_profile#(type T=bit[63:0]) extends fnob_rand#(T); T m_vals[$], m_probs[$]; int m_delay_prof_q[$]; int m_burst_cnt = 0; int m_sel; //-------------------------------------------------------------------------------- covergroup fnob_cg(int max_sel); option.per_instance = 1; option.goal = 100; option.comment = "fnob_cg"; fnob_rand_cg:coverpoint m_sel{ bins val_all[] = {[0 : max_sel]}; } endgroup // fnob_cg //-------------------------------------------------------------------------------- function new(string name="", T params[string][$]); super.new(name); split_val_prob(params, m_vals, m_probs); fnob_cg = new(m_probs.size()-1); endfunction // new //-------------------------------------------------------------------------------- static function fnob_rand#(T) init(string name, T params[string][$]); fnob_rand_profile#(T) fr = new(name, params); return fr; endfunction //-------------------------------------------------------------------------------- function void split_val_prob(ref T params[string][$], ref T vals[$], ref T probs[$]); vals = params["val"]; probs = params["prob"]; assert(vals.size() == 2*probs.size()) else `uvm_fatal(get_name(), $psprintf("params.size=%0d vals.size=%0d probs.size=%.2f", params.size(), vals.size(), probs.size())); `uvm_info(get_name(), $psprintf("vals=%p probs=%p", vals, probs), UVM_MEDIUM) endfunction // split_val_prob //-------------------------------------------------------------------------------- virtual function T gen(); if (m_burst_cnt == 0) begin if (m_delay_prof_q.size() == 0) begin init_delay_prof_q(m_probs, m_delay_prof_q); end m_sel = m_delay_prof_q.pop_front(); m_burst_cnt = get_profile_delay(m_sel, m_vals); gen = get_profile_delay(m_sel, m_vals); fnob_cg.sample(); m_fnob_gen = gen; //`uvm_info(get_name(), $psprintf("gen=%0d m_burst_cnt=%0d", gen, m_burst_cnt), UVM_MEDIUM) end else begin m_burst_cnt--; m_fnob_gen = 0; return 0; end // else: !if(m_burst_cnt == 0) endfunction // gen //-------------------------------------------------------------------------------- function void init_delay_prof_q(ref T probs[$], ref int delay_prof_q[$]); for (int ii=0; ii<probs.size(); ii++) begin //`uvm_info(get_name(), $psprintf("probs[%0d]=%0d", ii, probs[ii]), UVM_MEDIUM) repeat(int'(probs[ii])) begin delay_prof_q.push_back(ii); end end delay_prof_q.shuffle(); endfunction // init_delay_profile_q //-------------------------------------------------------------------------------- function int get_profile_delay(int sel, ref T vals[$]); int min_val = vals[sel*2]; int max_val = vals[sel*2 + 1]; get_profile_delay = $urandom_range(min_val, max_val); endfunction // get_profile_delay endclass // fnob_rand_unif //================================================================================ class fnob_rand_const#(type T=bit[63:0]) extends fnob_rand#(T); T m_const, m_gen; //-------------------------------------------------------------------------------- covergroup fnob_cg; option.per_instance = 1; option.goal = 100; option.comment = "fnob_cg"; fnob_rand_cg:coverpoint m_gen{ bins val_all = {m_const}; } endgroup // fnob_cg //-------------------------------------------------------------------------------- function new(string name="", T params[$]); super.new(name); m_const = params[0]; fnob_cg = new; endfunction // new //-------------------------------------------------------------------------------- static function fnob_rand#(T) init(string name, T params[$]); fnob_rand_const#(T) fr = new(name, params); return fr; endfunction //-------------------------------------------------------------------------------- virtual function T gen(); m_gen = m_const; fnob_cg.sample(); m_fnob_gen = m_gen; return m_gen; endfunction // gen endclass //-------------------------------------------------------------------------------- /* You cannot declare an array of an embedded covergroup this is an LRM restriction because the covergroup declared in a class is an anonymous type and the covergroup name becomes the instance variable. (See 19.4 Using covergroup in classes in the 1800-2012 LRM) You need define the covergroup outside the class Define sam cg with diff name for better verdi viewing */ covergroup fnob_pattern_cg(int val) with function sample(int cp); option.per_instance = 1; option.goal = 100; option.comment = "fnob_cg"; fnob_rand_cg:coverpoint cp{ bins val_all = {val}; } endgroup covergroup fnob_randc_pattern_cg(int val) with function sample(int cp); option.per_instance = 1; option.goal = 100; option.comment = "fnob_cg"; fnob_rand_cg:coverpoint cp{ bins val_all = {val}; } endgroup covergroup fnob_in_list_cg(int val) with function sample(int cp); option.per_instance = 1; option.goal = 100; option.comment = "fnob_cg"; fnob_rand_cg:coverpoint cp{ bins val_all = {val}; } endgroup //================================================================================ class fnob_rand_pattern#(type T=bit[63:0]) extends fnob_rand#(T); T m_vals[$]; int m_idx = 0; fnob_pattern_cg cg[]; //-------------------------------------------------------------------------------- function new(string name="", T params[$]); super.new(name); m_vals = params; cg = new[m_vals.size()]; for (int ii=0; ii<m_vals.size(); ii++) begin cg[ii] = new(m_vals[ii]); end endfunction // new //-------------------------------------------------------------------------------- static function fnob_rand#(T) init(string name, T params[$]); fnob_rand_pattern#(T) fr = new(name, params); return fr; endfunction //-------------------------------------------------------------------------------- virtual function T gen(); if (m_idx >= m_vals.size()) begin m_idx = 0; end gen = m_vals[m_idx]; cg[m_idx].sample(gen); m_idx++; m_fnob_gen = gen; endfunction // gen endclass //================================================================================ class fnob_rand_dist#(type T=bit[63:0]) extends fnob_rand#(T); T m_vals[$], m_probs[$]; int m_probs_sum, m_sel; //-------------------------------------------------------------------------------- covergroup fnob_cg(int max_sel); option.per_instance = 1; option.goal = 100; option.comment = "fnob_cg"; fnob_rand_cg:coverpoint m_sel{ bins val_all[] = {[0 : max_sel]}; } endgroup // fnob_cg //-------------------------------------------------------------------------------- function new(string name="", T params[string][$]); super.new(name); split_val_prob(params, m_vals, m_probs); m_probs_sum = m_probs.sum(); fnob_cg = new(m_probs.size()-1); endfunction // new //-------------------------------------------------------------------------------- static function fnob_rand#(T) init(string name, T params[string][$]); fnob_rand_dist#(T) fr = new(name, params); return fr; endfunction // init //-------------------------------------------------------------------------------- function void split_val_prob(ref T params[string][$], ref T vals[$], ref T probs[$]); vals = params["val"]; probs = params["prob"]; assert(vals.size() == 2*probs.size()) else `uvm_fatal(get_name(), $psprintf("params.size=%0d vals.size=%0d probs.size=%.2f", params.size(), vals.size(), probs.size())); `uvm_info(get_name(), $psprintf("vals=%p probs=%p", vals, probs), UVM_MEDIUM) endfunction // split_val_prob //-------------------------------------------------------------------------------- virtual function T gen(); int idx = 0; int dice = $urandom_range(0, m_probs_sum-1) + 1;//offset delta 1 while(dice > m_probs[idx]) begin dice -= m_probs[idx]; idx++; end gen = $urandom_range(m_vals[idx*2], m_vals[idx*2+1]); m_sel = idx; fnob_cg.sample(); m_fnob_gen = gen; endfunction // gen endclass // fnob_rand_unif //================================================================================ class fnob_rand_log#(type T=bit[63:0]) extends fnob_rand#(T); real m_min_real, m_max_real, m_min_log, m_max_log; int m_min_int, m_max_int, m_gen; //-------------------------------------------------------------------------------- covergroup fnob_cg; option.per_instance = 1; option.goal = 100; option.comment = "fnob_cg"; fnob_rand_cg:coverpoint m_gen{ bins val_all[] = {[m_min_int : m_max_int]}; } endgroup // fnob_cg //-------------------------------------------------------------------------------- function new(string name="", T params[$]); super.new(name); m_min_real = params[0]; m_max_real = params[1]; m_min_int = params[0]; m_max_int = params[1]; assert(m_min_real <= m_max_real); m_min_log = $ln(m_min_real); m_max_log = $ln(m_max_real); fnob_cg = new; fnob_cg.option.name = name; endfunction // new //-------------------------------------------------------------------------------- static function fnob_rand#(T) init(string name, T params[$]); fnob_rand_log#(T) fr = new(name, params); return fr; endfunction //-------------------------------------------------------------------------------- virtual function T gen(); real frac = $itor($urandom) / $itor('hFFFFFFFF); real gen_log = m_min_log + (m_max_log - m_min_log) * frac; m_gen = $rtoi( $exp(gen_log) ); fnob_cg.sample(); m_fnob_gen = m_gen; return m_gen; endfunction // gen endclass // fnob_rand_log //================================================================================ class fnob_rand_sfs#(type T=bit[63:0]) extends fnob_rand#(T); T m_slow_min, m_slow_max, m_fast_min, m_fast_max; T m_slow_cmin, m_slow_cmax, m_fast_cmin, m_fast_cmax; T m_vals[$]; bit m_is_sfs; int m_cov_idx; //-------------------------------------------------------------------------------- covergroup fnob_cg; option.per_instance = 1; option.goal = 100; option.comment = "fnob_cg"; fnob_rand_cg:coverpoint m_cov_idx{ bins val_all[] = {[1 : 2]}; } endgroup // fnob_cg //-------------------------------------------------------------------------------- function new(string name="", T params[string][$], bit is_sfs=1); super.new(name); m_slow_min = params["val"][0]; m_slow_max = params["val"][1]; m_fast_min = params["val"][2]; m_fast_max = params["val"][3]; m_slow_cmin = params["prob"][0]; m_slow_cmax = params["prob"][1]; m_fast_cmin = params["prob"][2]; m_fast_cmax = params["prob"][3]; m_vals = {}; m_is_sfs = is_sfs; fnob_cg = new; `uvm_info(get_name(), $psprintf("m_slow_min=%0d m_slow_max=%0d m_fast_min=%0d m_fast_max=%0d m_slow_cmin=%0d m_slow_cmax=%0d m_fast_cmin=%0d m_fast_cmax=%0d", m_slow_min, m_slow_max, m_fast_min, m_fast_max, m_slow_cmin, m_slow_cmax, m_fast_cmin, m_fast_cmax), UVM_MEDIUM) endfunction // new //-------------------------------------------------------------------------------- static function fnob_rand#(T) init(string name, T params[string][$], bit is_sfs=1); fnob_rand_sfs#(T) fr = new(name, params, is_sfs); return fr; endfunction //-------------------------------------------------------------------------------- virtual function T gen(); if (m_vals.size() == 0) begin fill_arr(); end gen = m_vals.pop_front(); if ((gen>=m_slow_min) && (gen<=m_slow_max)) begin m_cov_idx = 1; end else if ((gen>=m_fast_min) && (gen<=m_fast_max)) begin m_cov_idx = 2; end fnob_cg.sample(); m_fnob_gen = gen; endfunction // gen //-------------------------------------------------------------------------------- virtual function void fill_arr(); int m_slow_cnt, m_fast_cnt; m_slow_cnt = $urandom_range(m_slow_cmin, m_slow_cmax); m_fast_cnt = $urandom_range(m_fast_cmin, m_fast_cmax); if (m_is_sfs == 1) begin repeat (m_slow_cnt) begin m_vals.push_back($urandom_range(m_slow_min, m_slow_max)); end repeat (m_fast_cnt) begin m_vals.push_back($urandom_range(m_fast_min, m_fast_max)); end end else begin repeat (m_fast_cnt) begin m_vals.push_back($urandom_range(m_fast_min, m_fast_max)); end repeat (m_slow_cnt) begin m_vals.push_back($urandom_range(m_slow_min, m_slow_max)); end end endfunction // fill_arr endclass //================================================================================ class fnob_randc_pattern#(type T=bit[63:0]) extends fnob_rand#(T); T m_vals[$]; T m_vals_gen[$]; fnob_randc_pattern_cg cg[]; int m_val2idx[int]; int m_idx = 0; //-------------------------------------------------------------------------------- function new(string name="", T params[$]); super.new(name); m_vals = params; m_vals_gen = params; cg = new[m_vals.size()]; for (int ii=0; ii<m_vals.size(); ii++) begin cg[ii] = new(m_vals[ii]); m_val2idx[m_vals[ii]] = ii; end endfunction // new //-------------------------------------------------------------------------------- static function fnob_rand#(T) init(string name, T params[$]); fnob_randc_pattern#(T) fr = new(name, params); return fr; endfunction //-------------------------------------------------------------------------------- virtual function T gen(); //pick m_idx m_idx = $urandom_range(0, m_vals_gen.size()-1); //cut queue into two queues gen = m_vals_gen[m_idx]; //update queue m_vals_gen.delete(m_idx); if(m_vals_gen.size() == 0) m_vals_gen = m_vals; cg[m_val2idx[gen]].sample(gen); m_fnob_gen = gen; endfunction // gen endclass // fnob_randc_pattern //-------------------------------------------------------------------------------- class fnob_rand_inside_list#(type T=bit[63:0]) extends fnob_rand#(T); T m_vals[$]; fnob_in_list_cg cg[]; int m_val2idx[int]; int m_idx = 0; //-------------------------------------------------------------------------------- function new(string name="", T params[$]); super.new(name); m_vals = params; cg = new[m_vals.size()]; for (int ii=0; ii<m_vals.size(); ii++) begin cg[ii] = new(m_vals[ii]); m_val2idx[m_vals[ii]] = ii; end endfunction // new //-------------------------------------------------------------------------------- static function fnob_rand#(T) init(string name, T params[$]); fnob_rand_inside_list#(T) fr = new(name, params); return fr; endfunction //-------------------------------------------------------------------------------- virtual function T gen(); //pick m_idx m_idx = $urandom_range(0, m_vals.size()-1); gen = m_vals[m_idx]; cg[m_val2idx[gen]].sample(gen); m_fnob_gen = gen; endfunction // gen endclass // fnob_inside_list //-------------------------------------------------------------------------------- class fnob_rand_intvl#(type T=bit[63:0]) extends fnob_rand#(T); T m_min, m_max, m_intvl; //-------------------------------------------------------------------------------- function new(string name="", T params[$]); super.new(name); m_min = params[0]; m_max = params[1]; m_intvl = params[2]; endfunction // new //-------------------------------------------------------------------------------- static function fnob_rand#(T) init(string name, T params[$]); fnob_rand_intvl#(T) fr = new(name, params); return fr; endfunction //-------------------------------------------------------------------------------- virtual function T gen(); int intvl_tot = (m_max - m_min) / m_intvl; int intvl_sel = $urandom_range(0, intvl_tot); gen = m_min + intvl_sel*m_intvl; endfunction // gen endclass `endif