00001 // $Id: ovm__object_8sv-source.html,v 1.1 2008/10/07 21:54:14 alex.marin Exp $ 00002 //---------------------------------------------------------------------- 00003 // Copyright 2007-2008 Mentor Graphics Corporation 00004 // Copyright 2007-2008 Cadence Design Systems, Inc. 00005 // All Rights Reserved Worldwide 00006 // 00007 // Licensed under the Apache License, Version 2.0 (the 00008 // "License"); you may not use this file except in 00009 // compliance with the License. You may obtain a copy of 00010 // the License at 00011 // 00012 // http://www.apache.org/licenses/LICENSE-2.0 00013 // 00014 // Unless required by applicable law or agreed to in 00015 // writing, software distributed under the License is 00016 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 00017 // CONDITIONS OF ANY KIND, either express or implied. See 00018 // the License for the specific language governing 00019 // permissions and limitations under the License. 00020 //---------------------------------------------------------------------- 00021 00022 `include "base/ovm_misc.svh" 00023 `include "base/ovm_object.svh" 00024 `include "base/ovm_object_globals.svh" 00025 `include "base/ovm_printer.svh" 00026 `include "base/ovm_packer.svh" 00027 typedef class ovm_component; 00028 00029 //---------------------------------------------------------------------------- 00030 // 00031 // CLASS: ovm_object 00032 // 00033 //---------------------------------------------------------------------------- 00034 00035 00036 // new 00037 // --- 00038 00039 function ovm_object::new (string name=""); 00040 00041 m_inst_id = m_inst_count++; 00042 m_leaf_name = name; 00043 m_field_automation (null, OVM_CHECK_FIELDS, ""); 00044 endfunction 00045 00046 00047 // reseed 00048 // ------ 00049 00050 function void ovm_object::reseed (); 00051 if(use_ovm_seeding) 00052 this.srandom(ovm_create_random_seed(get_type_name(), get_full_name())); 00053 endfunction 00054 00055 00056 // get type 00057 // -------- 00058 00059 function ovm_object_wrapper ovm_object::get_type(); 00060 ovm_report_error("NOTYPID", "get_type not implemented in derived class."); 00061 return null; 00062 endfunction 00063 00064 00065 // get inst_id 00066 // ----------- 00067 00068 function int ovm_object::get_inst_id(); 00069 return m_inst_id; 00070 endfunction 00071 00072 00073 // get inst_count 00074 // -------------- 00075 00076 function int ovm_object::get_inst_count(); 00077 return m_inst_count; 00078 endfunction 00079 00080 00081 // get_name 00082 // -------- 00083 00084 function string ovm_object::get_name (); 00085 return m_leaf_name; 00086 endfunction 00087 00088 00089 // get_full_name 00090 // ------------- 00091 00092 function string ovm_object::get_full_name (); 00093 return get_name(); 00094 endfunction 00095 00096 00097 // set_name 00098 // -------- 00099 00100 function void ovm_object::set_name (string name); 00101 m_leaf_name = name; 00102 endfunction 00103 00104 00105 // print 00106 // ----- 00107 00108 function void ovm_object::print(ovm_printer printer=null); 00109 if(printer==null) 00110 printer = ovm_default_printer; 00111 00112 if(printer.istop()) begin 00113 printer.print_object(get_name(), this); 00114 end 00115 else begin 00116 //do m_field_automation here so user doesn't need to call anything to get 00117 //automation. 00118 ovm_auto_options_object.printer = printer; 00119 m_field_automation(null, OVM_PRINT, ""); 00120 //call user override 00121 do_print(printer); 00122 end 00123 endfunction 00124 00125 00126 // sprint 00127 // ------ 00128 00129 function string ovm_object::sprint(ovm_printer printer=null); 00130 bit p; 00131 00132 if(printer==null) 00133 printer = ovm_default_printer; 00134 00135 p = printer.knobs.sprint; 00136 printer.knobs.sprint = 1; 00137 00138 print(printer); 00139 00140 printer.knobs.sprint = p; //revert back to regular printing 00141 return printer.m_string; 00142 endfunction 00143 00144 00145 // do_sprint (virtual) 00146 // --------- 00147 00148 function string ovm_object::do_sprint(ovm_printer printer); 00149 if(!printer.knobs.sprint) begin 00150 ovm_report_error("SPNSTR", "do_sprint called without string option set for printer"); 00151 return ""; 00152 end 00153 do_print(printer); 00154 return printer.m_string; 00155 endfunction 00156 00157 // print_field_match (static) 00158 // ----------------- 00159 00160 function void ovm_object::print_field_match(string fnc, string match); 00161 string scratch; 00162 00163 if(m_sc.save_last_field) 00164 m_sc.last_field = m_sc.get_full_scope_arg(); 00165 00166 if(print_matches) begin 00167 int style; 00168 scratch = { 00169 fnc, ": Matched string ", match, " to field ", m_sc.get_full_scope_arg() 00170 }; 00171 ovm_report_info("STRMTC", scratch, OVM_LOW); 00172 end 00173 endfunction 00174 00175 // set 00176 // --- 00177 00178 function void ovm_object::set_int_local (string field_name, 00179 ovm_bitstream_t value, 00180 bit recurse=1); 00181 if(m_sc.scope.in_hierarchy(this)) return; 00182 00183 this.m_sc.status = 0; 00184 this.m_sc.bitstream = value; 00185 00186 m_field_automation(null, OVM_SETINT, field_name); 00187 00188 if(m_sc.warning && !this.m_sc.status) begin 00189 ovm_report_error("NOMTC", $psprintf("did not find a match for field %s", field_name)); 00190 end 00191 00192 endfunction 00193 00194 00195 // set_object_local 00196 // ---------------- 00197 00198 function void ovm_object::set_object_local (string field_name, 00199 ovm_object value, 00200 bit clone=1, 00201 bit recurse=1); 00202 ovm_object cc; 00203 if(m_sc.scope.in_hierarchy(this)) return; 00204 00205 if(clone && (value!=null)) begin 00206 cc = value.clone(); 00207 if(cc != null) cc.set_name(field_name); 00208 value = cc; 00209 end 00210 00211 this.m_sc.status = 0; 00212 this.m_sc.object = value; 00213 ovm_auto_options_object.clone = clone; 00214 00215 m_field_automation(null, OVM_SETOBJ, field_name); 00216 00217 if(m_sc.warning && !this.m_sc.status) begin 00218 ovm_report_error("NOMTC", $psprintf("did not find a match for field %s", field_name)); 00219 end 00220 00221 endfunction 00222 00223 00224 // set_string_local 00225 // ---------------- 00226 function void ovm_object::set_string_local (string field_name, 00227 string value, 00228 bit recurse=1); 00229 if(m_sc.scope.in_hierarchy(this)) return; 00230 this.m_sc.status = 0; 00231 this.m_sc.stringv = value; 00232 00233 m_field_automation(null, OVM_SETSTR, field_name); 00234 00235 if(m_sc.warning && !this.m_sc.status) begin 00236 `ifdef INCA 00237 ovm_report_error("NOMTC", $psprintf("did not find a match for field %s (@%0d)", field_name, this)); 00238 `else 00239 ovm_report_error("NOMTC", $psprintf("did not find a match for field %s", field_name)); 00240 `endif 00241 end 00242 endfunction 00243 00244 00245 // m_do_set (static) 00246 // ------------ 00247 00248 // function m_do_set (match, arg, lhs, what, flag) 00249 // Precondition: 00250 // match -- a match string to test against arg to do the set 00251 // arg -- the name of the short name of the lhs object 00252 // lhs -- the lhs to do on (left hand side) 00253 // what -- integer, what to do 00254 // flag -- object flags 00255 // 00256 // ovm_object::m_sc.bitstream -- rhs object used for set/get 00257 // ovm_object::m_sc.status -- return status for set/get calls 00258 // 00259 00260 00261 function int ovm_object::m_do_set (string match, 00262 string arg, 00263 inout ovm_bitstream_t lhs, 00264 input int what, 00265 int flag); 00266 00267 bit matched; 00268 00269 if (what < OVM_START_FUNCS || what > OVM_END_FUNCS) 00270 return 0; 00271 00272 matched = ovm_is_match(match, m_sc.scope.get_arg()); 00273 00274 case (what) 00275 OVM_SETINT: 00276 begin 00277 if(matched) begin 00278 if(flag &OVM_READONLY) begin 00279 ovm_report_warning("RDONLY", $psprintf("Readonly argument match %s is ignored", 00280 m_sc.get_full_scope_arg())); 00281 return 0; 00282 end 00283 print_field_match("set_int()", match); 00284 lhs = ovm_object::m_sc.bitstream; 00285 ovm_object::m_sc.status = 1; 00286 return 1; 00287 end 00288 end 00289 default: 00290 begin 00291 if(matched) begin 00292 ovm_report_warning("MTCTYP", $psprintf("matched integral field %s, ", 00293 m_sc.get_full_scope_arg(), 00294 "but expected a non-integral type")); 00295 end 00296 end 00297 endcase 00298 return 0; 00299 endfunction 00300 00301 00302 // m_do_set_string (static) 00303 // ------------------- 00304 00305 // function m_do_set_string (match, arg, lhs, what, flag) 00306 // Precondition: 00307 // match -- a match string to test against arg to do the set 00308 // arg -- the name of the short name of the lhs object 00309 // lhs -- the lhs to do get or set on (left hand side) 00310 // what -- integer, what to do 00311 // flag -- object flags 00312 // 00313 // ovm_object::m_sc.stringv -- rhs object used for set/get 00314 // ovm_object::m_sc.status -- return status for set/get calls 00315 // 00316 00317 function int ovm_object::m_do_set_string(string match, 00318 string arg, 00319 inout string lhs, 00320 input int what, 00321 int flag); 00322 00323 bit matched; 00324 string s; 00325 00326 if (what < OVM_START_FUNCS || what > OVM_END_FUNCS) 00327 return 0; 00328 00329 matched = ovm_is_match(match, m_sc.scope.get_arg()); 00330 00331 case (what) 00332 OVM_SETSTR: 00333 begin 00334 if(matched) begin 00335 if(flag &OVM_READONLY) begin 00336 ovm_report_warning("RDONLY", $psprintf("Readonly argument match %s is ignored", 00337 m_sc.get_full_scope_arg())); 00338 return 0; 00339 end 00340 print_field_match("set_string()", match); 00341 lhs = ovm_object::m_sc.stringv; 00342 ovm_object::m_sc.status = 1; 00343 return 1; 00344 end 00345 end 00346 default: 00347 begin 00348 if(matched) begin 00349 ovm_report_warning("MTCTYP", $psprintf("matched string field %s, ", 00350 m_sc.get_full_scope_arg(), 00351 "but expected a non-string type")); 00352 end 00353 end 00354 endcase 00355 return 0; 00356 endfunction 00357 00358 00359 // m_do_set_object (static) 00360 // ----------------- 00361 00362 // function m_do_set_object (match, arg, lhsobj, what, flag) 00363 // Precondition: 00364 // match -- a match string to test against arg to do the set 00365 // arg -- the name of the short name of the lhs object 00366 // lhsobj -- the object to do set_object on (left hand side) 00367 // what -- integer, what to do 00368 // flag -- object flags 00369 // 00370 // ovm_object::m_sc.object -- rhs object used for set 00371 // ovm_object::m_sc.status -- return status for set/get calls. set 00372 // always returns 0. 00373 // 00374 // Postcondition: 00375 // Performs the set or get operation on an object. If the object doesn't 00376 // match then the object is recursed. The get* operations return true if 00377 // an index was returned. The set* always return 0. 00378 00379 function int ovm_object::m_do_set_object (string match, 00380 string arg, 00381 inout ovm_object lhsobj, 00382 input int what, 00383 int flag); 00384 00385 bit matched; 00386 bit prev; 00387 00388 if (what < OVM_START_FUNCS || what > OVM_END_FUNCS) 00389 return 0; 00390 00391 matched = ovm_is_match(match, m_sc.scope.get_arg()); 00392 00393 case (what) 00394 OVM_SETOBJ: 00395 begin 00396 if(matched) begin 00397 if(flag &OVM_READONLY) begin 00398 ovm_report_warning("RDONLY", $psprintf("Readonly argument match %s is ignored", 00399 m_sc.get_full_scope_arg())); 00400 return 0; 00401 end 00402 print_field_match("set_object()", match); 00403 lhsobj = ovm_object::m_sc.object; 00404 ovm_object::m_sc.status = 1; 00405 end 00406 else if(lhsobj==null) return 0; 00407 if(flag &OVM_READONLY) 00408 return 0; 00409 lhsobj.m_field_automation(null, OVM_SETOBJ, match); 00410 return ovm_object::m_sc.status; 00411 end 00412 endcase 00413 00414 if(matched) begin 00415 ovm_report_warning("MTCTYP", $psprintf("matched object field %s, ", 00416 m_sc.get_full_scope_arg(), 00417 "but expected a non-object type")); 00418 end 00419 if(lhsobj==null) return 0; 00420 lhsobj.m_field_automation(null, what, match); 00421 00422 return ovm_object::m_sc.status; 00423 00424 endfunction 00425 00426 // clone 00427 // ----- 00428 00429 function ovm_object ovm_object::clone(); 00430 ovm_object tmp; 00431 tmp = this.create(get_name()); 00432 if(tmp == null) begin 00433 // ovm_report_warning("CRFLD", $psprintf("The create method failed for %s, object will be copied using shallow copy", get_name())); 00434 // tmp = new this; 00435 ovm_report_warning("CRFLD", $psprintf("The create method failed for %s, object cannot be cloned", get_name())); 00436 end 00437 else begin 00438 tmp.copy(this); 00439 end 00440 00441 return(tmp); 00442 endfunction 00443 00444 00445 // copy 00446 // ---- 00447 00448 ovm_copy_map ovm_global_copy_map = new; 00449 function void ovm_object::copy (ovm_object rhs); 00450 //For cycle checking 00451 static int depth; 00452 if((rhs !=null) && (ovm_global_copy_map.get(rhs) != null)) begin 00453 return; 00454 end 00455 00456 if(rhs==null) begin 00457 ovm_report_warning("NULLCP", "A null object was supplied to copy; copy is ignored"); 00458 return; 00459 end 00460 00461 ovm_global_copy_map.set(rhs, this); 00462 ++depth; 00463 00464 do_copy(rhs); 00465 m_field_automation(rhs, OVM_COPY, ""); 00466 00467 --depth; 00468 if(depth==0) begin 00469 ovm_global_copy_map.clear(); 00470 end 00471 endfunction 00472 00473 00474 // do_copy 00475 // ------- 00476 00477 function void ovm_object::do_copy (ovm_object rhs); 00478 return; 00479 endfunction 00480 00481 00482 // compare 00483 // ------- 00484 00485 function void ovm_comparer::print_msg(string msg); 00486 result++; 00487 if(result <= show_max) begin 00488 msg = {"Miscompare for ", scope.get_arg(), ": ", msg}; 00489 ovm_report_info("MISCMP", msg, OVM_LOW); 00490 end 00491 miscompares = { miscompares, scope.get_arg(), ": ", msg, "\n" }; 00492 endfunction 00493 00494 //Need this funciton because sformat doesn't support objects 00495 function void ovm_comparer::print_rollup(ovm_object rhs, ovm_object lhs); 00496 string msg; 00497 if(scope.depth() == 0) begin 00498 if(result && (show_max || (sev != OVM_INFO))) begin 00499 if(show_max < result) 00500 $swrite(msg, "%0d Miscompare(s) (%0d shown) for object ", 00501 result, show_max); 00502 else 00503 $swrite(msg, "%0d Miscompare(s) for object ", result); 00504 00505 case (sev) 00506 `ifdef INCA 00507 OVM_WARNING: begin 00508 ovm_report_warning("MISCMP", $psprintf("%s%s@%0d vs. %s@%0d", msg, 00509 lhs.get_name(), lhs, rhs.get_name(), rhs)); 00510 end 00511 OVM_ERROR: begin 00512 ovm_report_error("MISCMP", $psprintf("%s%s@%0d vs. %s@%0d", msg, 00513 lhs.get_name(), lhs, rhs.get_name(), rhs)); 00514 end 00515 default: begin 00516 ovm_report_info("MISCMP", $psprintf("%s%s@%0d vs. %s@%0d", msg, 00517 lhs.get_name(), lhs, rhs.get_name(), rhs), OVM_LOW); 00518 end 00519 `else 00520 OVM_WARNING: begin 00521 ovm_report_warning("MISCMP", $psprintf("%s%s vs. %s", msg, 00522 lhs.get_name(), rhs.get_name())); 00523 end 00524 OVM_ERROR: begin 00525 ovm_report_error("MISCMP", $psprintf("%s%s vs. %s", msg, 00526 lhs.get_name(), rhs.get_name())); 00527 end 00528 default: begin 00529 ovm_report_info("MISCMP", $psprintf("%s%s vs. %s", msg, 00530 lhs.get_name(), rhs.get_name()), OVM_LOW); 00531 end 00532 `endif 00533 endcase 00534 end 00535 end 00536 endfunction 00537 00538 function void ovm_comparer::print_msg_object(ovm_object lhs, ovm_object rhs); 00539 result++; 00540 `ifdef INCA 00541 if(result <= show_max) begin 00542 ovm_report_info("MISCMP", 00543 $psprintf("Miscompare for %0s: lhs = @%0d : rhs = @%0d", 00544 scope.get_arg(), lhs, rhs), verbosity); 00545 end 00546 $swrite(miscompares, "%s%s: lhs = @%0d : rhs = @%0d", 00547 miscompares, scope.get_arg(), lhs, rhs); 00548 `else 00549 if(result <= show_max) begin 00550 ovm_report_info("MISCMP", 00551 $psprintf("Miscompare for %0s", 00552 scope.get_arg()), verbosity); 00553 end 00554 $swrite(miscompares, "%s%s:", 00555 miscompares, scope.get_arg()); 00556 `endif 00557 endfunction 00558 00559 function ovm_status_container ovm_object::init_status(); 00560 if(m_sc==null) m_sc=new; 00561 return m_sc; 00562 endfunction 00563 00564 function bit ovm_object::compare (ovm_object rhs, 00565 ovm_comparer comparer=null); 00566 bit t, dc; 00567 static int style; 00568 bit done; 00569 done = 0; 00570 if(comparer != null) 00571 ovm_auto_options_object.comparer = comparer; 00572 else 00573 ovm_auto_options_object.comparer = ovm_default_comparer; 00574 comparer = ovm_auto_options_object.comparer; 00575 00576 if(!m_sc.scope.depth()) begin 00577 comparer.compare_map.clear(); 00578 comparer.result = 0; 00579 comparer.miscompares = ""; 00580 comparer.scope = m_sc.scope; 00581 if(get_name() == "") begin 00582 m_sc.scope.down("<object>", this); 00583 end 00584 else 00585 m_sc.scope.down(this.get_name(), this); 00586 end 00587 if(!done && (rhs == null)) begin 00588 if(m_sc.scope.depth()) begin 00589 comparer.print_msg_object(this, rhs); 00590 end 00591 else begin 00592 comparer.print_msg_object(this, rhs); 00593 `ifdef INCA 00594 ovm_report_info("MISCMP", 00595 $psprintf("%0d Miscompare(s) for object %s@%0d vs. @%0d", 00596 comparer.result, get_name(), this, rhs), ovm_auto_options_object.comparer.verbosity); 00597 `else 00598 ovm_report_info("MISCMP", 00599 $psprintf("%0d Miscompare(s) for object %s", 00600 comparer.result, get_name()), ovm_auto_options_object.comparer.verbosity); 00601 `endif 00602 done = 1; 00603 end 00604 end 00605 00606 if(!done && (comparer.compare_map.get(rhs) != null)) begin 00607 if(comparer.compare_map.get(rhs) != this) begin 00608 comparer.print_msg_object(this, comparer.compare_map.get(rhs)); 00609 end 00610 done = 1; //don't do any more work after this case, but do cleanup 00611 end 00612 00613 if(!done && comparer.check_type && get_type_name() != rhs.get_type_name()) begin 00614 m_sc.stringv = { "lhs type = \"", get_type_name(), 00615 "\" : rhs type = \"", rhs.get_type_name(), "\""}; 00616 comparer.print_msg(m_sc.stringv); 00617 end 00618 00619 if(!done) begin 00620 comparer.compare_map.set(rhs, this); 00621 m_field_automation(rhs, OVM_COMPARE, ""); 00622 dc = do_compare(rhs, comparer); 00623 end 00624 00625 if(m_sc.scope.depth() == 1) begin 00626 m_sc.scope.up(this); 00627 end 00628 00629 comparer.print_rollup(this, rhs); 00630 return (comparer.result == 0 && dc == 1); 00631 endfunction 00632 00633 00634 // do_compare 00635 // ---------- 00636 00637 function bit ovm_object::do_compare (ovm_object rhs, 00638 ovm_comparer comparer); 00639 return 1; 00640 endfunction 00641 00642 00643 // m_field_automation 00644 // -------------- 00645 00646 function void ovm_object::m_field_automation ( ovm_object tmp_data__, 00647 int what__, 00648 string str__ ); 00649 return; 00650 endfunction 00651 00652 00653 // check_fields 00654 // ------------ 00655 00656 function void ovm_object::m_do_field_check(string field); 00657 if(m_field_array.exists(field) && (m_field_array[field] == 1)) begin 00658 ovm_report_error("MLTFLD", $psprintf("Field %s is defined multiple times in type %s", 00659 field, get_type_name())); 00660 end 00661 m_field_array[field]++; 00662 endfunction 00663 00664 00665 // do_print (virtual override) 00666 // ------------ 00667 00668 function void ovm_object::do_print(ovm_printer printer); 00669 return; 00670 endfunction 00671 00672 00673 // m_pack 00674 // ------ 00675 00676 function void ovm_object::m_pack (inout ovm_packer packer); 00677 00678 if(packer!=null) 00679 ovm_auto_options_object.packer = packer; 00680 else 00681 ovm_auto_options_object.packer = ovm_default_packer; 00682 packer = ovm_auto_options_object.packer; 00683 00684 packer.reset(); 00685 packer.scope.down(get_name(), this); 00686 00687 m_field_automation(null, OVM_PACK, ""); 00688 do_pack(packer); 00689 00690 packer.set_packed_size(); 00691 00692 packer.scope.up(this); 00693 00694 endfunction 00695 00696 00697 // pack 00698 // ---- 00699 00700 function int ovm_object::pack (ref bit bitstream [], 00701 input ovm_packer packer =null ); 00702 m_pack(packer); 00703 packer.get_bits(bitstream); 00704 return packer.get_packed_size(); 00705 endfunction 00706 00707 // pack_bytes 00708 // ---------- 00709 00710 function int ovm_object::pack_bytes (ref byte unsigned bytestream [], 00711 input ovm_packer packer=null ); 00712 m_pack(packer); 00713 packer.get_bytes(bytestream); 00714 return packer.get_packed_size(); 00715 endfunction 00716 00717 00718 // pack_ints 00719 // --------- 00720 00721 function int ovm_object::pack_ints (ref int unsigned intstream [], 00722 input ovm_packer packer=null ); 00723 m_pack(packer); 00724 packer.get_ints(intstream); 00725 return packer.get_packed_size(); 00726 endfunction 00727 00728 00729 // do_pack 00730 // ------- 00731 00732 function void ovm_object::do_pack (ovm_packer packer ); 00733 return; 00734 endfunction 00735 00736 00737 // m_unpack_pre 00738 // ------------ 00739 00740 function void ovm_object::m_unpack_pre (inout ovm_packer packer); 00741 if(packer!=null) 00742 ovm_auto_options_object.packer = packer; 00743 else 00744 ovm_auto_options_object.packer = ovm_default_packer; 00745 packer = ovm_auto_options_object.packer; 00746 packer.reset(); 00747 endfunction 00748 00749 00750 // m_unpack_post 00751 // ------------- 00752 00753 function void ovm_object::m_unpack_post (ovm_packer packer); 00754 00755 int provided_size; 00756 00757 provided_size = packer.get_packed_size(); 00758 00759 //Put this object into the hierarchy 00760 packer.scope.down(get_name(), this); 00761 00762 m_field_automation(null, OVM_UNPACK, ""); 00763 00764 do_unpack(packer); 00765 00766 //Scope back up before leaving 00767 packer.scope.up(this); 00768 00769 if(packer.get_packed_size() != provided_size) begin 00770 ovm_report_warning("BDUNPK", $psprintf("Unpack operation unsuccessful: unpacked %0d bits from a total of %0d bits", packer.get_packed_size(), provided_size)); 00771 end 00772 00773 endfunction 00774 00775 00776 // unpack 00777 // ------ 00778 00779 function int ovm_object::unpack (ref bit bitstream [], 00780 input ovm_packer packer=null); 00781 m_unpack_pre(packer); 00782 packer.put_bits(bitstream); 00783 m_unpack_post(packer); 00784 return packer.get_packed_size(); 00785 endfunction 00786 00787 // unpack_bytes 00788 // ------------ 00789 00790 function int ovm_object::unpack_bytes (ref byte unsigned bytestream [], 00791 input ovm_packer packer=null); 00792 m_unpack_pre(packer); 00793 packer.put_bytes(bytestream); 00794 m_unpack_post(packer); 00795 return packer.get_packed_size(); 00796 endfunction 00797 00798 00799 // unpack_ints 00800 // ----------- 00801 00802 function int ovm_object::unpack_ints (ref int unsigned intstream [], 00803 input ovm_packer packer=null); 00804 m_unpack_pre(packer); 00805 packer.put_ints(intstream); 00806 m_unpack_post(packer); 00807 return packer.get_packed_size(); 00808 endfunction 00809 00810 00811 // do_unpack 00812 // --------- 00813 00814 function void ovm_object::do_unpack (ovm_packer packer); 00815 return; 00816 endfunction 00817 00818 00819 // record 00820 // ------ 00821 00822 function void ovm_object::record (ovm_recorder recorder=null); 00823 //mxg if(!recorder) 00824 if(recorder == null) 00825 recorder = ovm_default_recorder; 00826 00827 if(!recorder.tr_handle) return; 00828 00829 ovm_auto_options_object.recorder = recorder; 00830 recorder.recording_depth++; 00831 00832 m_field_automation(null, OVM_RECORD, ""); 00833 do_record(recorder); 00834 00835 recorder.recording_depth--; 00836 00837 if(recorder.recording_depth==0) begin 00838 recorder.tr_handle = 0; 00839 end 00840 endfunction 00841 00842 00843 // do_record (virtual) 00844 // --------- 00845 00846 function void ovm_object::do_record (ovm_recorder recorder); 00847 return; 00848 endfunction 00849 00850 00851 // m_get_function_type (static) 00852 // ------------------- 00853 00854 function string ovm_object::m_get_function_type (int what); 00855 case (what) 00856 OVM_COPY: return "copy"; 00857 OVM_COMPARE: return "compare"; 00858 OVM_PRINT: return "print"; 00859 OVM_RECORD: return "record"; 00860 OVM_PACK: return "pack"; 00861 OVM_UNPACK: return "unpack"; 00862 OVM_FLAGS: return "get_flags"; 00863 OVM_SETINT: return "set"; 00864 OVM_SETOBJ: return "set_object"; 00865 OVM_SETSTR: return "set_string"; 00866 default: return "unknown"; 00867 endcase 00868 endfunction 00869 00870 00871 // m_get_report_object 00872 // ------------------- 00873 00874 function ovm_report_object ovm_object::m_get_report_object(); 00875 return null; 00876 endfunction 00877 00878 00879 // m_record_field_object (static) 00880 // --------------------- 00881 00882 function void ovm_object::m_record_field_object (string arg, 00883 ovm_object value, 00884 ovm_recorder recorder =null, 00885 int flag = OVM_DEFAULT); 00886 begin 00887 if(!recorder) 00888 recorder=ovm_auto_options_object.recorder; 00889 00890 if((flag&OVM_NORECORD) != 0) return; 00891 00892 recorder.record_object(arg, value); 00893 00894 end 00895 endfunction 00896 00897 00898 // m_do_data (static) 00899 // --------- 00900 00901 // function m_do_data (arg, lhs, rhs, what, flag) 00902 // Precondition: 00903 // arg -- the name of the short name of the lhs object 00904 // lhs -- the lhs to do work on (left hand side) 00905 // lhs -- the rhs to do work from (right hand side) 00906 // what -- integer, what to do 00907 // flag -- object flags 00908 00909 function int ovm_object::m_do_data (string arg, 00910 inout ovm_bitstream_t lhs, 00911 input ovm_bitstream_t rhs, 00912 int what, 00913 int bits, 00914 int flag); 00915 00916 00917 if (what > OVM_END_DATA_EXTRA) 00918 return 0; 00919 00920 if(bits > OVM_STREAMBITS) begin 00921 ovm_report_warning("FLDTNC",$psprintf("%s is %0d bits; maximum field size is %0d, truncating", 00922 arg, bits, OVM_STREAMBITS)); 00923 end 00924 case (what) 00925 OVM_COPY: 00926 begin 00927 if(((flag)&OVM_NOCOPY) == 0) begin 00928 ovm_bitstream_t mask; 00929 mask = -1; 00930 mask >>= (OVM_STREAMBITS-bits); 00931 lhs = rhs & mask; 00932 end 00933 return 0; 00934 end 00935 OVM_COMPARE: 00936 begin 00937 if(((flag)&OVM_NOCOMPARE) == 0) begin 00938 bit r; 00939 if(bits <= 64) 00940 r = ovm_auto_options_object.comparer.compare_field_int(arg, lhs, rhs, bits, ovm_radix_enum'(flag&OVM_RADIX)); 00941 else 00942 r = ovm_auto_options_object.comparer.compare_field(arg, lhs, rhs, bits, ovm_radix_enum'(flag&OVM_RADIX)); 00943 end 00944 return 0; 00945 end 00946 OVM_PACK: 00947 begin 00948 if(((flag)&OVM_NOPACK) == 0) begin 00949 if(bits<=64) 00950 ovm_auto_options_object.packer.pack_field_int(lhs, bits); 00951 else 00952 ovm_auto_options_object.packer.pack_field(lhs, bits); 00953 end 00954 return 0; 00955 end 00956 OVM_UNPACK: 00957 begin 00958 if(((flag)&OVM_NOPACK) == 0) begin 00959 if(bits<=64) 00960 lhs=ovm_auto_options_object.packer.unpack_field_int(bits); 00961 else 00962 lhs=ovm_auto_options_object.packer.unpack_field(bits); 00963 end 00964 return 0; 00965 end 00966 OVM_PRINT: 00967 begin 00968 if(((flag)&OVM_NOPRINT) == 0) 00969 begin 00970 ovm_printer printer; 00971 ovm_radix_enum radix; 00972 radix = ovm_radix_enum'(flag&OVM_RADIX); 00973 printer = ovm_auto_options_object.printer; 00974 printer.print_field(arg, lhs, bits, radix); 00975 end 00976 end 00977 OVM_RECORD: 00978 begin 00979 if(((flag)&OVM_NORECORD) == 0) 00980 begin 00981 integer h; 00982 ovm_radix_enum radix; 00983 00984 if(m_sc.scope.depth()) arg = m_sc.scope.get_arg(); 00985 radix = ovm_radix_enum'(flag&OVM_RADIX); 00986 ovm_auto_options_object.recorder.record_field(arg, lhs, bits, radix); 00987 end 00988 end 00989 endcase 00990 return 0; 00991 endfunction 00992 00993 00994 // m_do_data_object (static) 00995 // ---------------- 00996 00997 // function m_do_data_object (arg, lhs, rhs, what, flag) 00998 // Precondition: 00999 // arg -- the name of the short name of the lhs object 01000 // lhs -- the lhs to do work on (left hand side) 01001 // lhs -- the rhs to do work from (right hand side) 01002 // what -- integer, what to do 01003 // flag -- object flags 01004 01005 function int ovm_object::m_do_data_object (string arg, 01006 inout ovm_object lhs, 01007 input ovm_object rhs, 01008 int what, 01009 int flag); 01010 01011 ovm_object lhs_obj; 01012 01013 if (what > OVM_END_DATA_EXTRA) 01014 return 0; 01015 01016 case (what) 01017 OVM_COPY: 01018 begin 01019 int rval; 01020 if(((flag)&OVM_NOCOPY) != 0) begin 01021 return 0; 01022 end 01023 if(rhs == null) begin 01024 lhs = null; 01025 return OVM_REFERENCE; 01026 end 01027 01028 if(flag & OVM_SHALLOW) begin 01029 rval = OVM_SHALLOW; 01030 end 01031 else if(flag & OVM_REFERENCE) begin 01032 lhs = rhs; 01033 rval = OVM_REFERENCE; 01034 end 01035 else //deepcopy 01036 begin 01037 ovm_object v; 01038 v = ovm_global_copy_map.get(rhs); 01039 if(v) begin 01040 lhs = v; 01041 rval = OVM_REFERENCE; 01042 end 01043 else if(lhs==null) begin 01044 lhs = rhs.clone(); 01045 lhs.set_name(arg); 01046 rval = OVM_REFERENCE; 01047 end 01048 else if(rhs == null) begin 01049 rval = OVM_REFERENCE; 01050 end 01051 else begin 01052 //lhs doesn't change for this case, so don't need to copy back 01053 lhs.copy(rhs); 01054 rval = 0; 01055 end 01056 end 01057 return rval; 01058 end 01059 OVM_COMPARE: 01060 begin 01061 bit refcmp; 01062 01063 if(((flag)&OVM_NOCOMPARE) != 0) begin 01064 return 0; 01065 end 01066 01067 //if the object are the same then don't need to do a deep compare 01068 if(rhs == lhs) return 0; 01069 01070 refcmp = (flag & OVM_SHALLOW) && !(ovm_auto_options_object.comparer.policy == OVM_DEEP); 01071 01072 //do a deep compare here 01073 if(!refcmp && !(ovm_auto_options_object.comparer.policy == OVM_REFERENCE)) 01074 begin 01075 if(((rhs == null) && (lhs != null)) || ((lhs==null) && (rhs!=null))) begin 01076 ovm_auto_options_object.comparer.print_msg_object(lhs, rhs); 01077 return 1; //miscompare 01078 end 01079 if((rhs == null) && (lhs==null)) 01080 return 0; 01081 else begin 01082 bit r; 01083 r = lhs.compare(rhs, ovm_auto_options_object.comparer); 01084 if(r == 0) begin 01085 return 1; 01086 end 01087 else begin 01088 return 0; 01089 end 01090 end 01091 end 01092 else begin //reference compare 01093 if(lhs != rhs) begin 01094 ovm_auto_options_object.comparer.print_msg_object(lhs, rhs); 01095 return 1; 01096 end 01097 end 01098 end 01099 OVM_PACK: 01100 begin 01101 if(((flag&OVM_NOPACK) == 0) && ((flag&OVM_REFERENCE)==0)) begin 01102 ovm_auto_options_object.packer.pack_object(lhs); 01103 end 01104 return 0; 01105 end 01106 OVM_UNPACK: 01107 begin 01108 if(((flag&OVM_NOPACK) == 0) && ((flag&OVM_REFERENCE)==0)) begin 01109 ovm_auto_options_object.packer.unpack_object_ext(lhs); 01110 end 01111 return 0; 01112 end 01113 OVM_PRINT: 01114 begin 01115 if(((flag)&OVM_NOPRINT) == 0) 01116 begin 01117 if(((flag)&OVM_REFERENCE) || (lhs == null)) begin 01118 int d; 01119 d = ovm_auto_options_object.printer.knobs.depth; 01120 ovm_auto_options_object.printer.knobs.depth = 0; 01121 ovm_auto_options_object.printer.print_object(arg, lhs); 01122 ovm_auto_options_object.printer.knobs.depth = d; 01123 end 01124 else begin 01125 ovm_component obj; 01126 if(lhs != null) begin 01127 if($cast(obj,lhs)) begin 01128 if(ovm_auto_options_object.printer.m_scope.current() == obj.get_parent() ) 01129 ovm_auto_options_object.printer.print_object(arg, lhs); 01130 else 01131 ovm_auto_options_object.printer.print_object_header(arg, lhs); 01132 end 01133 else begin 01134 ovm_auto_options_object.printer.print_object(arg, lhs); 01135 end 01136 end 01137 end 01138 end 01139 end 01140 OVM_RECORD: 01141 begin 01142 if(((flag)&OVM_NORECORD) == 0) 01143 begin 01144 //If refernce is on then don't want to do cycle check since only 01145 //recording the reference. 01146 if((flag)&OVM_REFERENCE != 0) 01147 m_record_field_object(arg, lhs, ovm_auto_options_object.recorder,flag); 01148 else begin 01149 if(m_sc.scope.in_hierarchy(lhs)) return 0; 01150 m_record_field_object(arg, lhs, ovm_auto_options_object.recorder,flag); 01151 end 01152 end 01153 end 01154 endcase 01155 return 0; 01156 endfunction 01157 01158 01159 // m_do_data_string (static) 01160 // ---------------- 01161 01162 // function m_do_data_string (arg, lhs, rhs, what, flag) 01163 // Precondition: 01164 // arg -- the name of the short name of the lhs object 01165 // lhs -- the lhs to do work on (left hand side) 01166 // lhs -- the rhs to do work from (right hand side) 01167 // what -- integer, what to do 01168 // flag -- object flags 01169 // 01170 01171 function int ovm_object::m_do_data_string(string arg, 01172 inout string lhs, 01173 input string rhs, 01174 int what, 01175 int flag); 01176 01177 01178 if (what > OVM_END_DATA_EXTRA) 01179 return 0; 01180 01181 case (what) 01182 OVM_COPY: 01183 begin 01184 if(((flag)&OVM_NOCOPY) == 0) begin 01185 lhs = rhs; 01186 end 01187 return 0; 01188 end 01189 OVM_COMPARE: 01190 begin 01191 if(((flag)&OVM_NOCOMPARE) == 0) begin 01192 if(lhs != rhs) begin 01193 m_sc.stringv = { "lhs = \"", lhs, "\" : rhs = \"", rhs, "\""}; 01194 ovm_auto_options_object.comparer.print_msg(m_sc.stringv); 01195 return 1; 01196 end 01197 end 01198 return 0; 01199 end 01200 OVM_PACK: 01201 begin 01202 if(((flag)&OVM_NOPACK) == 0) begin 01203 ovm_auto_options_object.packer.pack_string(lhs); 01204 end 01205 return 0; 01206 end 01207 OVM_UNPACK: 01208 begin 01209 if(((flag)&OVM_NOPACK) == 0) begin 01210 lhs = ovm_auto_options_object.packer.unpack_string(); 01211 end 01212 return 0; 01213 end 01214 OVM_PRINT: 01215 begin 01216 if(((flag)&OVM_NOPRINT) == 0) 01217 begin 01218 ovm_auto_options_object.printer.print_string(arg, lhs); 01219 end 01220 end 01221 OVM_RECORD: 01222 begin 01223 if(((flag)&OVM_NORECORD) == 0) 01224 begin 01225 ovm_auto_options_object.recorder.record_string(arg, lhs); 01226 end 01227 end 01228 endcase 01229 return 0; 01230 01231 endfunction 01232 01233 01234 //----------------------------------------------------------------------------- 01235 // 01236 // ovm_status_container 01237 // 01238 //----------------------------------------------------------------------------- 01239 01240 function string ovm_status_container::get_full_scope_arg (); 01241 get_full_scope_arg = scope.get_arg(); 01242 endfunction 01243 01244 function ovm_scope_stack ovm_status_container::init_scope(); 01245 if(scope==null) scope=new; 01246 return scope; 01247 endfunction 01248 01249 //----------------------------------------------------------------------------- 01250 // 01251 // ovm_options_container 01252 // 01253 //----------------------------------------------------------------------------- 01254 01255 ovm_options_container ovm_auto_options_object = ovm_options_container::init(); 01256 01257 function ovm_options_container::new(); 01258 comparer = ovm_default_comparer; 01259 packer = ovm_default_packer; 01260 recorder = ovm_default_recorder; 01261 printer = ovm_default_printer; 01262 endfunction 01263 01264 function ovm_options_container ovm_options_container::init(); 01265 if(ovm_auto_options_object==null) ovm_auto_options_object=new; 01266 return ovm_auto_options_object; 01267 endfunction 01268 01269 //----------------------------------------------------------------------------- 01270 // 01271 // ovm_recorder 01272 // 01273 //----------------------------------------------------------------------------- 01274 01275 function void ovm_recorder::record_field (string name, 01276 ovm_bitstream_t value, 01277 int size, 01278 ovm_radix_enum radix=OVM_NORADIX); 01279 if(tr_handle==0) return; 01280 scope.set_arg(name); 01281 01282 if(!radix) 01283 radix = default_radix; 01284 01285 case(radix) 01286 OVM_BIN: ovm_set_attribute_by_name(tr_handle, scope.get_arg(), value, "'b",size); 01287 OVM_OCT: ovm_set_attribute_by_name(tr_handle, scope.get_arg(), value, "'o",size); 01288 OVM_DEC: ovm_set_attribute_by_name(tr_handle, scope.get_arg(), value, "'s",size); 01289 OVM_TIME: ovm_set_attribute_by_name(tr_handle, scope.get_arg(), value, "'u",size); 01290 OVM_STRING: ovm_set_attribute_by_name(tr_handle, scope.get_arg(), value, "'a",size); 01291 default: ovm_set_attribute_by_name(tr_handle, scope.get_arg(), value, "'x",size); 01292 endcase 01293 endfunction 01294 01295 function void ovm_recorder::record_object (string name, 01296 ovm_object value); 01297 int v; 01298 string str; 01299 01300 if(scope.in_hierarchy(value)) return; 01301 01302 if(identifier) begin 01303 `ifdef INCA 01304 $swrite(str, "%0d", value); 01305 `else 01306 str = ""; 01307 `endif 01308 v = str.atoi(); 01309 scope.set_arg(name); 01310 ovm_set_attribute_by_name(tr_handle, scope.get_arg(), v, "'s"); 01311 end 01312 01313 if(policy != OVM_REFERENCE) begin 01314 if(value!=null) begin 01315 scope.down(name, value); 01316 value.record(this); 01317 scope.up(value); 01318 end 01319 end 01320 endfunction 01321 01322 function void ovm_recorder::record_string (string name, 01323 string value); 01324 scope.set_arg(name); 01325 ovm_set_attribute_by_name(tr_handle, scope.get_arg(), ovm_string_to_bits(value), "'a"); 01326 endfunction 01327 01328 function void ovm_recorder::record_time (string name, 01329 time value); 01330 record_field(name, value, 64, OVM_TIME); 01331 endfunction 01332 01333 function void ovm_recorder::record_generic (string name, 01334 string value); 01335 record_string(name, value); 01336 endfunction 01337 01338 01339 //----------------------------------------------------------------------------- 01340 // 01341 // ovm_comparer 01342 // 01343 //----------------------------------------------------------------------------- 01344 01345 function bit ovm_comparer::compare_field (string name, 01346 ovm_bitstream_t lhs, 01347 ovm_bitstream_t rhs, 01348 int size, 01349 ovm_radix_enum radix=OVM_NORADIX); 01350 ovm_bitstream_t mask; 01351 string msg; 01352 01353 if(size <= 64) 01354 return compare_field_int(name, lhs, rhs, size, radix); 01355 01356 mask = -1; 01357 mask >>= (OVM_STREAMBITS-size); 01358 if((lhs & mask) !== (rhs & mask)) begin 01359 scope.set_arg(name); 01360 case (radix) 01361 OVM_BIN: begin 01362 $swrite(msg, "lhs = 'b%0b : rhs = 'b%0b", 01363 lhs&mask, rhs&mask); 01364 end 01365 OVM_OCT: begin 01366 $swrite(msg, "lhs = 'o%0o : rhs = 'o%0o", 01367 lhs&mask, rhs&mask); 01368 end 01369 OVM_DEC: begin 01370 $swrite(msg, "lhs = %0d : rhs = %0d", 01371 lhs&mask, rhs&mask); 01372 end 01373 OVM_TIME: begin 01374 $swrite(msg, "lhs = %0t : rhs = %0t", 01375 lhs&mask, rhs&mask); 01376 end 01377 OVM_STRING: begin 01378 $swrite(msg, "lhs = %0s : rhs = %0s", 01379 lhs&mask, rhs&mask); 01380 end 01381 OVM_ENUM: begin 01382 //Printed as decimal, user should cuse compare string for enum val 01383 $swrite(msg, "lhs = %0d : rhs = %0d", 01384 lhs&mask, rhs&mask); 01385 end 01386 default: begin 01387 $swrite(msg, "lhs = 'h%0x : rhs = 'h%0x", 01388 lhs&mask, rhs&mask); 01389 end 01390 endcase 01391 print_msg(msg); 01392 return 0; 01393 end 01394 return 1; 01395 endfunction 01396 01397 function bit ovm_comparer::compare_field_int (string name, 01398 logic [63:0] lhs, 01399 logic [63:0] rhs, 01400 int size, 01401 ovm_radix_enum radix=OVM_NORADIX); 01402 logic [63:0] mask; 01403 string msg; 01404 01405 mask = -1; 01406 mask >>= (64-size); 01407 if((lhs & mask) !== (rhs & mask)) begin 01408 scope.set_arg(name); 01409 case (radix) 01410 OVM_BIN: begin 01411 $swrite(msg, "lhs = 'b%0b : rhs = 'b%0b", 01412 lhs&mask, rhs&mask); 01413 end 01414 OVM_OCT: begin 01415 $swrite(msg, "lhs = 'o%0o : rhs = 'o%0o", 01416 lhs&mask, rhs&mask); 01417 end 01418 OVM_DEC: begin 01419 $swrite(msg, "lhs = %0d : rhs = %0d", 01420 lhs&mask, rhs&mask); 01421 end 01422 OVM_TIME: begin 01423 $swrite(msg, "lhs = %0t : rhs = %0t", 01424 lhs&mask, rhs&mask); 01425 end 01426 OVM_STRING: begin 01427 $swrite(msg, "lhs = %0s : rhs = %0s", 01428 lhs&mask, rhs&mask); 01429 end 01430 OVM_ENUM: begin 01431 //Printed as decimal, user should cuse compare string for enum val 01432 $swrite(msg, "lhs = %0d : rhs = %0d", 01433 lhs&mask, rhs&mask); 01434 end 01435 default: begin 01436 $swrite(msg, "lhs = 'h%0x : rhs = 'h%0x", 01437 lhs&mask, rhs&mask); 01438 end 01439 endcase 01440 print_msg(msg); 01441 return 0; 01442 end 01443 return 1; 01444 endfunction 01445 01446 01447 function bit ovm_comparer::compare_object (string name, 01448 ovm_object lhs, 01449 ovm_object rhs); 01450 01451 if (rhs == lhs) 01452 return 1; 01453 01454 if (policy == OVM_REFERENCE && lhs != rhs) begin 01455 scope.set_arg(name); 01456 print_msg_object(lhs, rhs); 01457 return 0; 01458 end 01459 01460 if (rhs == null || lhs == null) begin 01461 scope.set_arg(name); 01462 print_msg_object(lhs, rhs); 01463 return 0; //miscompare 01464 end 01465 01466 scope.down(name, null); 01467 compare_object = lhs.compare(rhs, this); 01468 scope.up(null); 01469 01470 endfunction 01471 01472 function bit ovm_comparer::compare_string (string name, 01473 string lhs, 01474 string rhs); 01475 string msg; 01476 if(lhs != rhs) begin 01477 scope.set_arg(name); 01478 msg = { "lhs = \"", lhs, "\" : rhs = \"", rhs, "\""}; 01479 print_msg(msg); 01480 return 0; 01481 end 01482 return 1; 01483 endfunction 01484 01485 function ovm_comparer ovm_comparer::init(); 01486 if(ovm_default_comparer==null) ovm_default_comparer=new; 01487 return ovm_default_comparer; 01488 endfunction
![]() Intelligent Design Verification Project: OVM, Revision: 1.1.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.4.6 Mon Sep 29 14:23:30 2008 |