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