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