vmm_scenario_gen.sv

Go to the documentation of this file.
00001 // 
00002 // -------------------------------------------------------------
00003 //    Copyright 2004-2008 Synopsys, Inc.
00004 //    All Rights Reserved Worldwide
00005 // 
00006 //    Licensed under the Apache License, Version 2.0 (the
00007 //    "License"); you may not use this file except in
00008 //    compliance with the License.  You may obtain a copy of
00009 //    the License at
00010 // 
00011 //        http://www.apache.org/licenses/LICENSE-2.0
00012 // 
00013 //    Unless required by applicable law or agreed to in
00014 //    writing, software distributed under the License is
00015 //    distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
00016 //    CONDITIONS OF ANY KIND, either express or implied.  See
00017 //    the License for the specific language governing
00018 //    permissions and limitations under the License.
00019 // -------------------------------------------------------------
00020 // 
00021 
00022 `ifdef VCS
00023    `ifndef VMM_SOLVE_BEFORE_OPT
00024       `define VMM_SOLVE_BEFORE_OPT hard
00025    `endif
00026 `endif
00027 `ifndef VMM_SOLVE_BEFORE_OPT
00028    `define VMM_SOLVE_BEFORE_OPT
00029 `endif
00030 
00031 
00032 `define vmm_scenario_(class)                class``_scenario
00033 `define vmm_scenario_valid_(class)          class``_scenario_valid
00034 `define vmm_inject_item_scenario_(class)    class``_inject_item_scenario
00035 `define vmm_atomic_scenario_(class)         class``_atomic_scenario
00036 `define vmm_scenario_election_(class)       class``_scenario_election
00037 `define vmm_scenario_election_valid_(class) class``_scenario_election_valid
00038 `define vmm_scenario_gen_(class)            class``_scenario_gen
00039 `define vmm_scenario_gen_callbacks_(class)  class``_scenario_gen_callbacks
00040 
00041 `define vmm_scenario_gen(class_name, text) \
00042 `vmm_scenario_gen_using(class_name, class_name``_channel, text)
00043 
00044 `define vmm_scenario_gen_using(class_name, channel_name, text) \
00045  \
00046 class `vmm_scenario_(class_name) extends `VMM_DATA; \
00047  \
00048    static vmm_log log; \
00049  \
00050    local int    next_scenario_kind = 0; \
00051    local int    max_length         = 0; \
00052    local string scenario_names[*]; \
00053  \
00054    int stream_id; \
00055    int scenario_id; \
00056  \
00057    rand int unsigned scenario_kind; \
00058    rand int unsigned length; \
00059    rand class_name items[]; \
00060         class_name using; \
00061    rand int unsigned  repeated       = 0; \
00062    static int unsigned repeat_thresh = 100; \
00063  \
00064    constraint `vmm_scenario_valid_(class_name) { \
00065       scenario_kind >= 0; \
00066       scenario_kind < next_scenario_kind; \
00067  \
00068       length >= 0; \
00069       length <= max_length; \
00070  \
00071       items.size() == length; \
00072  \
00073       repeated >= 0; \
00074  \
00075       solve scenario_kind before length `VMM_SOLVE_BEFORE_OPT; \
00076       solve length before items.size() `VMM_SOLVE_BEFORE_OPT; \
00077    } \
00078  \
00079    constraint repetition { \
00080       repeated == 0; \
00081    } \
00082  \
00083    function new(`VMM_DATA_NEW_ARGS); \
00084       super.new(this.log `VMM_DATA_NEW_CALL); \
00085       if (this.log == null) begin \
00086          this.log = new({text, " Scenario"}, "Class"); \
00087          this.notify.log = this.log; \
00088       end \
00089  \
00090       using = null; \
00091    endfunction: new \
00092  \
00093    virtual function void display(string prefix = ""); \
00094       $display(this.psdisplay(prefix)); \
00095    endfunction: display \
00096  \
00097    virtual function string psdisplay(string prefix = ""); \
00098       int i; \
00099  \
00100       $sformat(psdisplay, "%sScenario \"%s\": kind=%0d, length=%0d (max=%0d), repeated=%0d\n", \
00101                prefix, this.scenario_name(this.scenario_kind), this.scenario_kind, this.length, this.max_length, \
00102                this.repeated); \
00103       foreach (this.items[i]) begin \
00104           psdisplay = {psdisplay, this.items[i].psdisplay(`vmm_sformatf("%s   Item #%0d: ", prefix, i))}; \
00105       end \
00106    endfunction: psdisplay \
00107  \
00108    function int unsigned define_scenario(string name, \
00109                                          int unsigned max_len); \
00110       define_scenario = this.next_scenario_kind++; \
00111       this.scenario_names[define_scenario] = name; \
00112  \
00113       if (max_len > this.max_length) this.max_length = max_len; \
00114    endfunction: define_scenario \
00115  \
00116    function void redefine_scenario(int unsigned scenario_kind, \
00117                                    string       name, \
00118                                    int unsigned max_len); \
00119       this.scenario_names[scenario_kind] = name; \
00120  \
00121       if (max_len > this.max_length) this.max_length = max_len; \
00122    endfunction: redefine_scenario \
00123  \
00124    function string scenario_name(int unsigned scenario_kind); \
00125       if (!this.scenario_names.exists(scenario_kind)) begin \
00126          `vmm_error(this.log, `vmm_sformatf("Cannot find scenario name: undefined scenario kind %0d", \
00127                                             scenario_kind)); \
00128          return "?"; \
00129       end \
00130  \
00131       scenario_name = this.scenario_names[scenario_kind]; \
00132    endfunction: scenario_name \
00133  \
00134    function void allocate_scenario(class_name using = null); \
00135       this.items = new [this.max_length]; \
00136       foreach (this.items[i]) begin \
00137          if (using == null) this.items[i] = new; \
00138          else $cast(this.items[i], using.copy()); \
00139  \
00140          this.items[i].stream_id   = this.stream_id; \
00141          this.items[i].scenario_id = this.scenario_id; \
00142          this.items[i].data_id     = i; \
00143       end \
00144    endfunction: allocate_scenario \
00145  \
00146    function void fill_scenario(class_name using = null); \
00147       int i; \
00148  \
00149       if (this.items.size() < this.max_length) begin \
00150          this.items = new [this.max_length] (this.items); \
00151       end \
00152       foreach (this.items[i]) begin \
00153          if (this.items[i] != null) continue; \
00154  \
00155          if (using == null) this.items[i] = new; \
00156          else $cast(this.items[i], using.copy()); \
00157  \
00158          this.items[i].stream_id   = this.stream_id; \
00159          this.items[i].scenario_id = this.scenario_id; \
00160          this.items[i].data_id     = i; \
00161       end \
00162    endfunction: fill_scenario \
00163  \
00164    function void pre_randomize(); \
00165       this.fill_scenario(this.using); \
00166    endfunction: pre_randomize \
00167  \
00168    virtual task apply(channel_name     channel, \
00169                       ref int unsigned n_insts); \
00170       int i; \
00171  \
00172       for (i = 0; i < this.length; i++) begin \
00173          class_name item; \
00174          $cast(item, this.items[i].copy()); \
00175          channel.put(item); \
00176       end \
00177  \
00178       n_insts = this.length; \
00179    endtask: apply \
00180 endclass \
00181  \
00182  \
00183 class `vmm_inject_item_scenario_(class_name) extends `vmm_scenario_(class_name); \
00184  \
00185    function new(class_name obj `VMM_DATA_NEW_ARGS); \
00186       super.new(`VMM_DATA_NEW_CALL); \
00187  \
00188       this.items    = new [1]; \
00189       this.items[0] = obj; \
00190       this.length   = 1; \
00191       this.repeated = 0; \
00192    endfunction: new \
00193  \
00194    virtual task apply(channel_name     channel, \
00195                       ref int unsigned n_insts); \
00196       channel.put(this.items[0]); \
00197       n_insts = 1; \
00198    endtask: apply \
00199  \
00200 endclass \
00201  \
00202  \
00203 class `vmm_atomic_scenario_(class_name) extends `vmm_scenario_(class_name); \
00204  \
00205    int unsigned ATOMIC; \
00206  \
00207    constraint atomic_scenario { \
00208       if (scenario_kind == ATOMIC) { \
00209          length == 1; \
00210          repeated == 0; \
00211       } \
00212    } \
00213  \
00214    function new(`VMM_DATA_NEW_ARGS); \
00215       super.new(`VMM_DATA_NEW_CALL); \
00216  \
00217       this.ATOMIC = this.define_scenario("Atomic", 1); \
00218  \
00219       this.scenario_kind   = this.ATOMIC; \
00220       this.length = 1; \
00221    endfunction: new \
00222  \
00223    virtual function string psdisplay(string prefix = ""); \
00224       psdisplay = super.psdisplay(prefix); \
00225    endfunction:psdisplay \
00226  \
00227    function void pre_randomize(); \
00228       super.pre_randomize(); \
00229    endfunction \
00230  \
00231    virtual task apply(channel_name     channel, \
00232                       ref int unsigned n_insts); \
00233       super.apply(channel, n_insts); \
00234    endtask: apply \
00235  \
00236 endclass \
00237  \
00238  \
00239 class `vmm_scenario_election_(class_name); \
00240    int stream_id; \
00241    int scenario_id; \
00242    int unsigned n_scenarios; \
00243    int unsigned last_selected[$]; \
00244    int unsigned next_in_set; \
00245  \
00246    `vmm_scenario_(class_name) scenario_set[$]; \
00247  \
00248    rand int select; \
00249  \
00250    constraint `vmm_scenario_election_valid_(class_name) { \
00251       select >= 0; \
00252       select < n_scenarios; \
00253    } \
00254  \
00255    constraint round_robin { \
00256       select == next_in_set; \
00257    } \
00258  \
00259 endclass \
00260  \
00261 typedef class `vmm_scenario_gen_(class_name); \
00262  \
00263 class `vmm_scenario_gen_callbacks_(class_name) extends vmm_xactor_callbacks; \
00264    virtual task pre_scenario_randomize(`vmm_scenario_gen_(class_name) gen, \
00265                                        ref `vmm_scenario_(class_name) scenario); \
00266    endtask \
00267  \
00268    virtual task post_scenario_gen(`vmm_scenario_gen_(class_name) gen, \
00269                                   `vmm_scenario_(class_name)     scenario, \
00270                                   ref bit                        dropped); \
00271    endtask \
00272 endclass \
00273  \
00274  \
00275 class `vmm_scenario_gen_(class_name) extends `VMM_XACTOR; \
00276  \
00277    int unsigned stop_after_n_insts; \
00278    int unsigned stop_after_n_scenarios; \
00279  \
00280    typedef enum int {GENERATED, \
00281                      DONE} symbols_e; \
00282  \
00283    `vmm_scenario_election_(class_name) select_scenario; \
00284  \
00285    `vmm_scenario_(class_name) scenario_set[$]; \
00286  \
00287    channel_name out_chan; \
00288  \
00289    protected int scenario_count; \
00290    protected int inst_count; \
00291  \
00292    function new(string       inst, \
00293                 int          stream_id = -1, \
00294                 channel_name out_chan  = null \
00295                 `VMM_XACTOR_NEW_ARGS); \
00296       super.new({text, " Scenario Generator"}, inst, stream_id \
00297                 `VMM_XACTOR_NEW_CALL); \
00298  \
00299       if (out_chan == null) begin \
00300          out_chan = new({text, " Scenario Generator output channel"}, \
00301                         inst); \
00302       end \
00303       this.out_chan = out_chan; \
00304       this.log.is_above(this.out_chan.log); \
00305  \
00306       this.scenario_count = 0; \
00307       this.inst_count = 0; \
00308       this.stop_after_n_insts     = 0; \
00309       this.stop_after_n_scenarios = 0; \
00310  \
00311       this.select_scenario = new; \
00312       begin \
00313          `vmm_atomic_scenario_(class_name) sc = new; \
00314          this.scenario_set.push_back(sc); \
00315       end \
00316  \
00317       this.notify.configure(GENERATED); \
00318       this.notify.configure(DONE, vmm_notify::ON_OFF); \
00319    endfunction: new \
00320  \
00321    function int unsigned get_n_insts(); \
00322       get_n_insts = this.inst_count; \
00323    endfunction: get_n_insts \
00324  \
00325    function int unsigned get_n_scenarios(); \
00326       get_n_scenarios = this.scenario_count; \
00327    endfunction: get_n_scenarios \
00328  \
00329    virtual task inject_obj(class_name obj); \
00330       `vmm_inject_item_scenario_(class_name) scenario = new(obj); \
00331       this.inject(scenario); \
00332    endtask: inject_obj \
00333  \
00334    virtual task inject(`vmm_scenario_(class_name) scenario); \
00335       bit drop = 0; \
00336  \
00337       scenario.stream_id   = this.stream_id; \
00338       scenario.scenario_id = this.scenario_count; \
00339       foreach (scenario.items[i]) begin \
00340          scenario.items[i].stream_id   = scenario.stream_id; \
00341          scenario.items[i].scenario_id = scenario.scenario_id; \
00342          scenario.items[i].data_id     = i; \
00343       end \
00344  \
00345       `vmm_callback(`vmm_scenario_gen_callbacks_(class_name), \
00346                     post_scenario_gen(this, scenario, drop)); \
00347  \
00348       if (!drop) begin \
00349          this.scenario_count++; \
00350          this.notify.indicate(GENERATED, scenario); \
00351  \
00352          if (scenario.repeated > scenario.repeat_thresh) begin \
00353             `vmm_warning(this.log, `vmm_sformatf("A scenario will be repeated %0d times...", \
00354                                                  scenario.repeated)); \
00355          end \
00356          repeat (scenario.repeated + 1) begin \
00357             int unsigned n_insts = 0; \
00358             scenario.apply(this.out_chan, n_insts); \
00359             this.inst_count += n_insts; \
00360          end \
00361       end \
00362    endtask: inject \
00363  \
00364    virtual function void reset_xactor(reset_e rst_type = SOFT_RST); \
00365       super.reset_xactor(rst_type); \
00366       this.scenario_count = 0; \
00367       this.inst_count     = 0; \
00368       this.out_chan.flush(); \
00369       this.select_scenario.last_selected.delete(); \
00370  \
00371       if (rst_type >= FIRM_RST) begin \
00372          this.notify.reset( , vmm_notify::HARD); \
00373       end \
00374  \
00375       if (rst_type >= HARD_RST) begin \
00376          `vmm_atomic_scenario_(class_name) sc = new; \
00377  \
00378          this.stop_after_n_insts     = 0; \
00379          this.stop_after_n_scenarios = 0; \
00380          this.select_scenario = new; \
00381          this.scenario_set.push_back(sc); \
00382       end \
00383  \
00384    endfunction: reset_xactor \
00385  \
00386    virtual protected task main(); \
00387       `vmm_scenario_(class_name) the_scenario; \
00388  \
00389       fork \
00390          super.main(); \
00391       join_none \
00392  \
00393       while ((this.stop_after_n_insts <= 0 \
00394               || this.inst_count < this.stop_after_n_insts) \
00395              && (this.stop_after_n_scenarios <= 0 \
00396                  || this.scenario_count < this.stop_after_n_scenarios)) begin \
00397  \
00398          this.wait_if_stopped(); \
00399  \
00400          this.select_scenario.stream_id    = this.stream_id; \
00401          this.select_scenario.scenario_id  = this.scenario_count; \
00402          this.select_scenario.n_scenarios  = this.scenario_set.size(); \
00403          this.select_scenario.scenario_set = this.scenario_set; \
00404          if (this.select_scenario.last_selected.size() == 0) \
00405             this.select_scenario.next_in_set = 0; \
00406          else \
00407             this.select_scenario.next_in_set = ((this.select_scenario.last_selected[$] + 1) % this.scenario_set.size()); \
00408  \
00409          if (!this.select_scenario.randomize()) begin \
00410             `vmm_fatal(this.log, "Cannot select scenario descriptor"); \
00411             continue; \
00412          end \
00413  \
00414          if (this.select_scenario.select < 0 || \
00415              this.select_scenario.select >= this.scenario_set.size()) begin \
00416             `vmm_fatal(this.log, `vmm_sformatf("Select scenario #%0d is not within available set (0-%0d)", \
00417                                                this.select_scenario.select, \
00418                                                this.scenario_set.size()-1)); \
00419             continue; \
00420          end \
00421  \
00422          this.select_scenario.last_selected.push_back(this.select_scenario.select); \
00423          while (this.select_scenario.last_selected.size() > 10) begin \
00424             void'(this.select_scenario.last_selected.pop_front()); \
00425          end \
00426  \
00427          the_scenario = this.scenario_set[this.select_scenario.select]; \
00428          if (the_scenario == null) begin \
00429             `vmm_fatal(this.log, `vmm_sformatf("Selected scenario #%0d does not exist", \
00430                                                this.select_scenario.select)); \
00431             continue; \
00432          end \
00433  \
00434          the_scenario.stream_id   = this.stream_id; \
00435          the_scenario.scenario_id = this.scenario_count; \
00436          foreach (the_scenario.items[i]) begin \
00437             if (the_scenario.items[i] == null) continue; \
00438  \
00439             the_scenario.items[i].stream_id   = the_scenario.stream_id; \
00440             the_scenario.items[i].scenario_id = the_scenario.scenario_id; \
00441             the_scenario.items[i].data_id     = i; \
00442          end \
00443  \
00444          `vmm_callback(`vmm_scenario_gen_callbacks_(class_name), \
00445                        pre_scenario_randomize(this, the_scenario)); \
00446          if (the_scenario == null) continue; \
00447  \
00448          if (!the_scenario.randomize()) begin \
00449             `vmm_fatal(this.log, $psprintf("Cannot randomize scenario descriptor #%0d", \
00450                                            this.select_scenario.select)); \
00451             continue; \
00452          end \
00453  \
00454          this.inject(the_scenario); \
00455       end \
00456  \
00457       this.notify.indicate(DONE); \
00458       this.notify.indicate(XACTOR_STOPPED); \
00459       this.notify.indicate(XACTOR_IDLE); \
00460       this.notify.reset(XACTOR_BUSY); \
00461       this.scenario_count++; \
00462    endtask: main \
00463   \
00464 endclass

Intelligent Design Verification
Intelligent Design Verification
Project: VMM, Revision: 1.0.0
Copyright (c) 2008 Intelligent Design Verification.
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
A copy of the license is included here:
http://www.intelligentdv.com/licenses/fdl.txt
doxygen
Doxygen Version: 1.5.6
Sat Oct 18 11:38:21 2008
Find a documentation bug? Report bugs to: bugs.intelligentdv.com Project: DoxygenFilterSV