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 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 Version: 1.5.6 Sat Oct 18 11:38:21 2008 |