VMM OpenSource - sv/std_lib/vmm_opts.sv

sv/std_lib/vmm_opts.sv expanded 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 
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