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
00023 class vmm_opts_info;
00024 typedef enum {NO_ARGS, STR_ARGS, INT_ARGS} arg_type_e;
00025
00026 arg_type_e arg_type = NO_ARGS;
00027 string opt;
00028 string sarg;
00029 string doc;
00030 string fname;
00031 int val;
00032
00033 bit opt_specified;
00034 bit arg_specified;
00035 bit expected;
00036
00037 int line_num;
00038 static int width = 1;
00039
00040 function new(string opt,
00041 string sarg = "");
00042 this.opt = opt;
00043 this.sarg = sarg;
00044 if (opt.len() > width) width = opt.len();
00045 endfunction
00046
00047 function string help(bit [12:0] id);
00048 static string spaces = " ";
00049 string fmt;
00050 string pad = spaces.substr(0, width-opt.len()-1);
00051
00052 case (arg_type)
00053 NO_ARGS: $sformat(fmt, "%d) %s%s (%b) : %s",
00054 id, opt, pad, (this.opt_specified) ? 1'b1 : 1'b0,
00055 doc);
00056 STR_ARGS: $sformat(fmt, "%d) %s%s=<str> (%s) : %s",
00057 id, opt, pad,
00058 (this.opt_specified) ? this.sarg : "Unspec'd",
00059 doc);
00060 INT_ARGS: $sformat(fmt, "%d) %s%s=<int> (%s) : %s",
00061 id, opt, pad,
00062 (this.opt_specified) ? this.sarg : "Unspec'd",
00063 doc);
00064 endcase
00065 return fmt;
00066 endfunction
00067 endclass
00068
00069
00070 function bit vmm_opts::extract_opts_info();
00071 if (opts_extracted) return 1;
00072 opts_extracted = 1;
00073
00074 log = new("vmm_opts", "class");
00075
00076 // Option files first
00077 if ($test$plusargs("vmm_opts_file")) begin
00078 string format;
00079 if ($value$plusargs("vmm_opts_file+%s", format)) begin
00080 string opts_file[$];
00081 void'(split(format, opts_file));
00082 foreach (opts_file[i]) begin
00083 parse_opts_file(opts_file[i]);
00084 end
00085 end
00086 end
00087
00088 // Command-line overrides option file options
00089 if ($test$plusargs("vmm_opts+")) begin
00090 string format;
00091 if ($value$plusargs("vmm_opts+%s", format)) begin
00092 string opts[$];
00093 void'(split(format, opts));
00094 foreach (opts[i]) begin
00095 add_specified_option(opts[i]);
00096 end
00097 end
00098 end
00099 endfunction
00100
00101
00102 function void vmm_opts::parse_opts_file(string filename);
00103 string t_str;
00104 int fp;
00105
00106 fp = $fopen(filename, "r");
00107 if (!fp) begin
00108 `vmm_fatal(log, `vmm_sformatf("Unable to open options file %s for reading", filename));
00109 return;
00110 end
00111
00112 while ($fscanf(fp, "%s", t_str) == 1) begin
00113 string str;
00114 if (`vmm_str_match(t_str, "[+]")) begin
00115 str = `vmm_str_postmatch(t_str);
00116 add_specified_option(str, filename);
00117 end
00118 end
00119 $fclose(fp);
00120 endfunction
00121
00122
00123 function void vmm_opts::add_specified_option(string frmt,
00124 string fname = "Command Line");
00125 bit arg_specified;
00126 int val;
00127 int idx[$];
00128 string s_arg;
00129 string name;
00130 vmm_opts_info oinfo;
00131
00132 arg_specified = 0;
00133 if (`vmm_str_match(frmt, "=")) begin
00134 s_arg = `vmm_str_postmatch(frmt);
00135 frmt = `vmm_str_prematch(frmt);
00136 arg_specified = 1;
00137 end
00138
00139 if (opts_info.exists(frmt)) begin
00140 oinfo = opts_info[frmt];
00141 if (arg_specified) oinfo.sarg = s_arg;
00142 end
00143 else begin
00144 oinfo = new(frmt, s_arg);
00145 opts_info[frmt] = oinfo;
00146 end
00147
00148 oinfo.opt_specified = 1;
00149 oinfo.arg_specified = arg_specified;
00150 oinfo.fname = fname;
00151 endfunction
00152
00153
00154 function vmm_opts_info vmm_opts::get_opts_by_name(string name);
00155 string vname = {"vmm_", name};
00156 string format;
00157 vmm_opts_info oinfo;
00158 int idx[$];
00159
00160 if (!opts_extracted)
00161 void'(extract_opts_info());
00162
00163 if (opts_info.exists(name)) begin
00164 oinfo = opts_info[name];
00165 end
00166 else begin
00167 oinfo = new(name);
00168 opts_info[name] = oinfo;
00169 end
00170
00171 if (!oinfo.expected && $test$plusargs(vname)) begin
00172 string sarg, format;
00173 oinfo.opt_specified = 1;
00174 format = `vmm_sformatf("vmm_%s=%%s", name);
00175 if ($value$plusargs(format, sarg)) begin
00176 oinfo.sarg = sarg;
00177 oinfo.arg_specified = 1;
00178 end
00179 end
00180 oinfo.expected = 1;
00181
00182 return oinfo;
00183 endfunction
00184
00185
00186 function bit vmm_opts::get_bit(string name,
00187 string doc = "");
00188 vmm_opts_info oinfo;
00189
00190 oinfo = get_opts_by_name(name);
00191 oinfo.arg_type = vmm_opts_info::NO_ARGS;
00192 if (oinfo.doc == "") oinfo.doc = doc;
00193 if (oinfo.doc == "") begin
00194 `vmm_warning(log, `vmm_sformatf("No documentation specified for option \"%s\".",
00195 name));
00196 end
00197 return oinfo.opt_specified;
00198 endfunction
00199
00200
00201 function string vmm_opts::get_string(string name,
00202 string dflt,
00203 string doc = "");
00204 vmm_opts_info oinfo;
00205
00206 oinfo = get_opts_by_name(name);
00207 oinfo.arg_type = vmm_opts_info::STR_ARGS;
00208 if (oinfo.doc == "") oinfo.doc = doc;
00209 if (oinfo.doc == "") begin
00210 `vmm_warning(log, `vmm_sformatf("No documentation specified for option \"%s\".",
00211 name));
00212 end
00213 if (oinfo.arg_specified) return oinfo.sarg;
00214
00215 return dflt;
00216 endfunction
00217
00218
00219 function int vmm_opts::get_int(string name,
00220 int dflt = 0,
00221 string doc = "");
00222 vmm_opts_info oinfo;
00223
00224 oinfo = get_opts_by_name(name);
00225 oinfo.arg_type = vmm_opts_info::INT_ARGS;
00226 if (oinfo.doc == "") oinfo.doc = doc;
00227 if (oinfo.doc == "") begin
00228 `vmm_warning(log, `vmm_sformatf("No documentation specified for option \"%s\".",
00229 name));
00230 end
00231 oinfo.val = oinfo.sarg.atoi();
00232 if (oinfo.arg_specified) return oinfo.val;
00233
00234 return dflt;
00235 endfunction
00236
00237
00238 function void vmm_opts::get_help();
00239 string usage[$];
00240 vmm_opts_info unknown[$];
00241 int p;
00242
00243 usage.push_back("VMM run-time options can be specified in the following formats:");
00244 usage.push_back(" 1) +vmm_opts+<option1>+<option2>+<option3>+...");
00245 usage.push_back(" 2) +vmm_<option1> +vmm_<option2> +vmm_<option3> ...");
00246 usage.push_back(" 3) +<option1> +<option2> +<option3> ... in file(s)");
00247 usage.push_back(" specified using +vmm_opts_file=<fname1>+<fname2>+...");
00248 usage.push_back(" where <optionN> is <name>, <name>=<int> or <name>=<str>");
00249 usage.push_back(" ");
00250 usage.push_back("VMM run-time options defined by this simulation are:");
00251 foreach (opts_info[name]) begin
00252 vmm_opts_info opt = opts_info[name];
00253 if (opt.expected) usage.push_back(opt.help(++p));
00254 if (opt.opt_specified && !opt.expected) begin
00255 unknown.push_back(opt);
00256 end
00257 end
00258 if (log.start_msg(vmm_log::NOTE_TYP, vmm_log::NORMAL_SEV)) begin
00259 foreach (usage[i]) void'(log.text(usage[i]));
00260 log.end_msg();
00261 end
00262
00263 if (unknown.size() > 0) begin
00264 string woops[$];
00265 woops.push_back("Following unknown VMM run-time options were specified:");
00266 foreach (unknown[i]) begin
00267 string txt;
00268 $sformat(txt, " %0d) %s (specified via %s)", i, unknown[i].opt,
00269 unknown[i].fname);
00270 woops.push_back(txt);
00271 end
00272 if (log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin
00273 foreach (woops[i]) void'(log.text(woops[i]));
00274 log.end_msg();
00275 end
00276 end
00277 endfunction
00278
00279
00280 function bit vmm_opts::split(string line, output string argv[$]);
00281 string pre;
00282 string post;
00283 string tok[$];
00284
00285 split = 1;
00286
00287 if (line.len() == 0) return 0;
00288 post = line;
00289 forever begin
00290 if (`vmm_str_match(post, "[+]")) begin
00291 pre = `vmm_str_prematch(post);
00292 post = `vmm_str_postmatch(post);
00293 if (pre.len() != 0) begin
00294 // Only add the token if non-empty to strip leading blanks
00295 argv.push_back(pre);
00296 end
00297 end else begin
00298 //if no further matches, put in the last match if it's non-zero len
00299 if (post.len() > 0) begin
00300 argv.push_back(post);
00301 end
00302 break;
00303 end
00304 end
00305 endfunction