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