/ovm-2.0.1/src/base/ovm_object.sv
SystemVerilog | 1506 lines | 1033 code | 261 blank | 212 comment | 223 complexity | dd228c80a1dfe5d1c3e7f79e952e0cdc MD5 | raw file
Possible License(s): Apache-2.0
1// $Id: //dvt/vtech/dev/main/ovm/src/base/ovm_object.sv#29 $ 2//---------------------------------------------------------------------- 3// Copyright 2007-2008 Mentor Graphics Corporation 4// Copyright 2007-2008 Cadence Design Systems, Inc. 5// All Rights Reserved Worldwide 6// 7// Licensed under the Apache License, Version 2.0 (the 8// "License"); you may not use this file except in 9// compliance with the License. You may obtain a copy of 10// the License at 11// 12// http://www.apache.org/licenses/LICENSE-2.0 13// 14// Unless required by applicable law or agreed to in 15// writing, software distributed under the License is 16// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 17// CONDITIONS OF ANY KIND, either express or implied. See 18// the License for the specific language governing 19// permissions and limitations under the License. 20//---------------------------------------------------------------------- 21 22`include "base/ovm_misc.svh" 23`include "base/ovm_object.svh" 24`include "base/ovm_object_globals.svh" 25`include "base/ovm_printer.svh" 26`include "base/ovm_packer.svh" 27typedef class ovm_component; 28 29//---------------------------------------------------------------------------- 30// 31// CLASS: ovm_object 32// 33//---------------------------------------------------------------------------- 34 35 36// new 37// --- 38 39function ovm_object::new (string name=""); 40 41 m_inst_id = m_inst_count++; 42 m_leaf_name = name; 43 m_field_automation (null, OVM_CHECK_FIELDS, ""); 44endfunction 45 46 47// reseed 48// ------ 49 50function void ovm_object::reseed (); 51 if(use_ovm_seeding) 52 this.srandom(ovm_create_random_seed(get_type_name(), get_full_name())); 53endfunction 54 55 56// get type 57// -------- 58 59function ovm_object_wrapper ovm_object::get_type(); 60 ovm_report_error("NOTYPID", "get_type not implemented in derived class."); 61 return null; 62endfunction 63 64 65// get inst_id 66// ----------- 67 68function int ovm_object::get_inst_id(); 69 return m_inst_id; 70endfunction 71 72 73// get inst_count 74// -------------- 75 76function int ovm_object::get_inst_count(); 77 return m_inst_count; 78endfunction 79 80 81// get_name 82// -------- 83 84function string ovm_object::get_name (); 85 return m_leaf_name; 86endfunction 87 88 89// get_full_name 90// ------------- 91 92function string ovm_object::get_full_name (); 93 return get_name(); 94endfunction 95 96 97// set_name 98// -------- 99 100function void ovm_object::set_name (string name); 101 m_leaf_name = name; 102endfunction 103 104 105// print 106// ----- 107 108function void ovm_object::print(ovm_printer printer=null); 109 if(printer==null) 110 printer = ovm_default_printer; 111 112 if(printer.istop()) begin 113 printer.print_object(get_name(), this); 114 end 115 else begin 116 //do m_field_automation here so user doesn't need to call anything to get 117 //automation. 118 ovm_auto_options_object.printer = printer; 119 m_field_automation(null, OVM_PRINT, ""); 120 //call user override 121 do_print(printer); 122 end 123endfunction 124 125 126// sprint 127// ------ 128 129function string ovm_object::sprint(ovm_printer printer=null); 130 bit p; 131 132 if(printer==null) 133 printer = ovm_default_printer; 134 135 p = printer.knobs.sprint; 136 printer.knobs.sprint = 1; 137 138 print(printer); 139 140 printer.knobs.sprint = p; //revert back to regular printing 141 return printer.m_string; 142endfunction 143 144 145// do_sprint (virtual) 146// --------- 147 148function string ovm_object::do_sprint(ovm_printer printer); 149 if(!printer.knobs.sprint) begin 150 ovm_report_error("SPNSTR", "do_sprint called without string option set for printer"); 151 return ""; 152 end 153 do_print(printer); 154 return printer.m_string; 155endfunction 156 157// print_field_match (static) 158// ----------------- 159 160function void ovm_object::print_field_match(string fnc, string match); 161 string scratch; 162 163 if(m_sc.save_last_field) 164 m_sc.last_field = m_sc.get_full_scope_arg(); 165 166 if(print_matches) begin 167 int style; 168 scratch = { 169 fnc, ": Matched string ", match, " to field ", m_sc.get_full_scope_arg() 170 }; 171 ovm_report_info("STRMTC", scratch, OVM_LOW); 172 end 173endfunction 174 175// set 176// --- 177 178function void ovm_object::set_int_local (string field_name, 179 ovm_bitstream_t value, 180 bit recurse=1); 181 if(m_sc.scope.in_hierarchy(this)) return; 182 183 this.m_sc.status = 0; 184 this.m_sc.bitstream = value; 185 186 m_field_automation(null, OVM_SETINT, field_name); 187 188 if(m_sc.warning && !this.m_sc.status) begin 189 ovm_report_error("NOMTC", $psprintf("did not find a match for field %s", field_name)); 190 end 191 192endfunction 193 194 195// set_object_local 196// ---------------- 197 198function void ovm_object::set_object_local (string field_name, 199 ovm_object value, 200 bit clone=1, 201 bit recurse=1); 202 ovm_object cc; 203 if(m_sc.scope.in_hierarchy(this)) return; 204 205 if(clone && (value!=null)) begin 206 cc = value.clone(); 207 if(cc != null) cc.set_name(field_name); 208 value = cc; 209 end 210 211 this.m_sc.status = 0; 212 this.m_sc.object = value; 213 ovm_auto_options_object.clone = clone; 214 215 m_field_automation(null, OVM_SETOBJ, field_name); 216 217 if(m_sc.warning && !this.m_sc.status) begin 218 ovm_report_error("NOMTC", $psprintf("did not find a match for field %s", field_name)); 219 end 220 221endfunction 222 223 224// set_string_local 225// ---------------- 226function void ovm_object::set_string_local (string field_name, 227 string value, 228 bit recurse=1); 229 if(m_sc.scope.in_hierarchy(this)) return; 230 this.m_sc.status = 0; 231 this.m_sc.stringv = value; 232 233 m_field_automation(null, OVM_SETSTR, field_name); 234 235 if(m_sc.warning && !this.m_sc.status) begin 236`ifdef INCA 237 ovm_report_error("NOMTC", $psprintf("did not find a match for field %s (@%0d)", field_name, this)); 238`else 239 ovm_report_error("NOMTC", $psprintf("did not find a match for field %s", field_name)); 240`endif 241 end 242endfunction 243 244 245// m_do_set (static) 246// ------------ 247 248// function m_do_set (match, arg, lhs, what, flag) 249// Precondition: 250// match -- a match string to test against arg to do the set 251// arg -- the name of the short name of the lhs object 252// lhs -- the lhs to do on (left hand side) 253// what -- integer, what to do 254// flag -- object flags 255// 256// ovm_object::m_sc.bitstream -- rhs object used for set/get 257// ovm_object::m_sc.status -- return status for set/get calls 258// 259 260 261function int ovm_object::m_do_set (string match, 262 string arg, 263 inout ovm_bitstream_t lhs, 264 input int what, 265 int flag); 266 267 bit matched; 268 269 if (what < OVM_START_FUNCS || what > OVM_END_FUNCS) 270 return 0; 271 272 matched = ovm_is_match(match, m_sc.scope.get_arg()); 273 274 case (what) 275 OVM_SETINT: 276 begin 277 if(matched) begin 278 if(flag &OVM_READONLY) begin 279 ovm_report_warning("RDONLY", $psprintf("Readonly argument match %s is ignored", 280 m_sc.get_full_scope_arg())); 281 return 0; 282 end 283 print_field_match("set_int()", match); 284 lhs = ovm_object::m_sc.bitstream; 285 ovm_object::m_sc.status = 1; 286 return 1; 287 end 288 end 289 default: 290 begin 291 if(matched) begin 292 ovm_report_warning("MTCTYP", $psprintf("matched integral field %s, ", 293 m_sc.get_full_scope_arg(), 294 "but expected a non-integral type")); 295 end 296 end 297 endcase 298 return 0; 299endfunction 300 301 302// m_do_set_string (static) 303// ------------------- 304 305// function m_do_set_string (match, arg, lhs, what, flag) 306// Precondition: 307// match -- a match string to test against arg to do the set 308// arg -- the name of the short name of the lhs object 309// lhs -- the lhs to do get or set on (left hand side) 310// what -- integer, what to do 311// flag -- object flags 312// 313// ovm_object::m_sc.stringv -- rhs object used for set/get 314// ovm_object::m_sc.status -- return status for set/get calls 315// 316 317function int ovm_object::m_do_set_string(string match, 318 string arg, 319 inout string lhs, 320 input int what, 321 int flag); 322 323 bit matched; 324 string s; 325 326 if (what < OVM_START_FUNCS || what > OVM_END_FUNCS) 327 return 0; 328 329 matched = ovm_is_match(match, m_sc.scope.get_arg()); 330 331 case (what) 332 OVM_SETSTR: 333 begin 334 if(matched) begin 335 if(flag &OVM_READONLY) begin 336 ovm_report_warning("RDONLY", $psprintf("Readonly argument match %s is ignored", 337 m_sc.get_full_scope_arg())); 338 return 0; 339 end 340 print_field_match("set_string()", match); 341 lhs = ovm_object::m_sc.stringv; 342 ovm_object::m_sc.status = 1; 343 return 1; 344 end 345 end 346 default: 347 begin 348 if(matched) begin 349 ovm_report_warning("MTCTYP", $psprintf("matched string field %s, ", 350 m_sc.get_full_scope_arg(), 351 "but expected a non-string type")); 352 end 353 end 354 endcase 355 return 0; 356endfunction 357 358 359// m_do_set_object (static) 360// ----------------- 361 362// function m_do_set_object (match, arg, lhsobj, what, flag) 363// Precondition: 364// match -- a match string to test against arg to do the set 365// arg -- the name of the short name of the lhs object 366// lhsobj -- the object to do set_object on (left hand side) 367// what -- integer, what to do 368// flag -- object flags 369// 370// ovm_object::m_sc.object -- rhs object used for set 371// ovm_object::m_sc.status -- return status for set/get calls. set 372// always returns 0. 373// 374// Postcondition: 375// Performs the set or get operation on an object. If the object doesn't 376// match then the object is recursed. The get* operations return true if 377// an index was returned. The set* always return 0. 378 379function int ovm_object::m_do_set_object (string match, 380 string arg, 381 inout ovm_object lhsobj, 382 input int what, 383 int flag); 384 385 bit matched; 386 bit prev; 387 388 if (what < OVM_START_FUNCS || what > OVM_END_FUNCS) 389 return 0; 390 391 matched = ovm_is_match(match, m_sc.scope.get_arg()); 392 393 case (what) 394 OVM_SETOBJ: 395 begin 396 if(matched) begin 397 if(flag &OVM_READONLY) begin 398 ovm_report_warning("RDONLY", $psprintf("Readonly argument match %s is ignored", 399 m_sc.get_full_scope_arg())); 400 return 0; 401 end 402 print_field_match("set_object()", match); 403 lhsobj = ovm_object::m_sc.object; 404 ovm_object::m_sc.status = 1; 405 end 406 else if(lhsobj==null) return 0; 407 if(flag &OVM_READONLY) 408 return 0; 409 lhsobj.m_field_automation(null, OVM_SETOBJ, match); 410 return ovm_object::m_sc.status; 411 end 412 endcase 413 414 if(matched) begin 415 ovm_report_warning("MTCTYP", $psprintf("matched object field %s, ", 416 m_sc.get_full_scope_arg(), 417 "but expected a non-object type")); 418 end 419 if(lhsobj==null) return 0; 420 lhsobj.m_field_automation(null, what, match); 421 422 return ovm_object::m_sc.status; 423 424endfunction 425 426// clone 427// ----- 428 429function ovm_object ovm_object::clone(); 430 ovm_object tmp; 431 tmp = this.create(get_name()); 432 if(tmp == null) begin 433// ovm_report_warning("CRFLD", $psprintf("The create method failed for %s, object will be copied using shallow copy", get_name())); 434// tmp = new this; 435 ovm_report_warning("CRFLD", $psprintf("The create method failed for %s, object cannot be cloned", get_name())); 436 end 437 else begin 438 tmp.copy(this); 439 end 440 441 return(tmp); 442endfunction 443 444 445// copy 446// ---- 447 448ovm_copy_map ovm_global_copy_map = new; 449function void ovm_object::copy (ovm_object rhs); 450 //For cycle checking 451 static int depth; 452 if((rhs !=null) && (ovm_global_copy_map.get(rhs) != null)) begin 453 return; 454 end 455 456 if(rhs==null) begin 457 ovm_report_warning("NULLCP", "A null object was supplied to copy; copy is ignored"); 458 return; 459 end 460 461 ovm_global_copy_map.set(rhs, this); 462 ++depth; 463 464 do_copy(rhs); 465 m_field_automation(rhs, OVM_COPY, ""); 466 467 --depth; 468 if(depth==0) begin 469 ovm_global_copy_map.clear(); 470 end 471endfunction 472 473 474// do_copy 475// ------- 476 477function void ovm_object::do_copy (ovm_object rhs); 478 return; 479endfunction 480 481 482// compare 483// ------- 484 485function void ovm_comparer::print_msg(string msg); 486 result++; 487 if(result <= show_max) begin 488 msg = {"Miscompare for ", scope.get_arg(), ": ", msg}; 489 ovm_report_info("MISCMP", msg, OVM_LOW); 490 end 491 miscompares = { miscompares, scope.get_arg(), ": ", msg, "\n" }; 492endfunction 493 494//Need this funciton because sformat doesn't support objects 495function void ovm_comparer::print_rollup(ovm_object rhs, ovm_object lhs); 496 string msg; 497 if(scope.depth() == 0) begin 498 if(result && (show_max || (sev != OVM_INFO))) begin 499 if(show_max < result) 500 $swrite(msg, "%0d Miscompare(s) (%0d shown) for object ", 501 result, show_max); 502 else 503 $swrite(msg, "%0d Miscompare(s) for object ", result); 504 505 case (sev) 506`ifdef INCA 507 OVM_WARNING: begin 508 ovm_report_warning("MISCMP", $psprintf("%s%s@%0d vs. %s@%0d", msg, 509 lhs.get_name(), lhs, rhs.get_name(), rhs)); 510 end 511 OVM_ERROR: begin 512 ovm_report_error("MISCMP", $psprintf("%s%s@%0d vs. %s@%0d", msg, 513 lhs.get_name(), lhs, rhs.get_name(), rhs)); 514 end 515 default: begin 516 ovm_report_info("MISCMP", $psprintf("%s%s@%0d vs. %s@%0d", msg, 517 lhs.get_name(), lhs, rhs.get_name(), rhs), OVM_LOW); 518 end 519`else 520 OVM_WARNING: begin 521 ovm_report_warning("MISCMP", $psprintf("%s%s vs. %s", msg, 522 lhs.get_name(), rhs.get_name())); 523 end 524 OVM_ERROR: begin 525 ovm_report_error("MISCMP", $psprintf("%s%s vs. %s", msg, 526 lhs.get_name(), rhs.get_name())); 527 end 528 default: begin 529 ovm_report_info("MISCMP", $psprintf("%s%s vs. %s", msg, 530 lhs.get_name(), rhs.get_name()), OVM_LOW); 531 end 532`endif 533 endcase 534 end 535 end 536endfunction 537 538function void ovm_comparer::print_msg_object(ovm_object lhs, ovm_object rhs); 539 result++; 540`ifdef INCA 541 if(result <= show_max) begin 542 ovm_report_info("MISCMP", 543 $psprintf("Miscompare for %0s: lhs = @%0d : rhs = @%0d", 544 scope.get_arg(), lhs, rhs), verbosity); 545 end 546 $swrite(miscompares, "%s%s: lhs = @%0d : rhs = @%0d", 547 miscompares, scope.get_arg(), lhs, rhs); 548`else 549 if(result <= show_max) begin 550 ovm_report_info("MISCMP", 551 $psprintf("Miscompare for %0s", 552 scope.get_arg()), verbosity); 553 end 554 $swrite(miscompares, "%s%s:", 555 miscompares, scope.get_arg()); 556`endif 557endfunction 558 559function ovm_status_container ovm_object::init_status(); 560 if(m_sc==null) m_sc=new; 561 return m_sc; 562endfunction 563 564function bit ovm_object::compare (ovm_object rhs, 565 ovm_comparer comparer=null); 566 bit t, dc; 567 static int style; 568 bit done; 569 done = 0; 570 if(comparer != null) 571 ovm_auto_options_object.comparer = comparer; 572 else 573 ovm_auto_options_object.comparer = ovm_default_comparer; 574 comparer = ovm_auto_options_object.comparer; 575 576 if(!m_sc.scope.depth()) begin 577 comparer.compare_map.clear(); 578 comparer.result = 0; 579 comparer.miscompares = ""; 580 comparer.scope = m_sc.scope; 581 if(get_name() == "") begin 582 m_sc.scope.down("<object>", this); 583 end 584 else 585 m_sc.scope.down(this.get_name(), this); 586 end 587 if(!done && (rhs == null)) begin 588 if(m_sc.scope.depth()) begin 589 comparer.print_msg_object(this, rhs); 590 end 591 else begin 592 comparer.print_msg_object(this, rhs); 593`ifdef INCA 594 ovm_report_info("MISCMP", 595 $psprintf("%0d Miscompare(s) for object %s@%0d vs. @%0d", 596 comparer.result, get_name(), this, rhs), ovm_auto_options_object.comparer.verbosity); 597`else 598 ovm_report_info("MISCMP", 599 $psprintf("%0d Miscompare(s) for object %s", 600 comparer.result, get_name()), ovm_auto_options_object.comparer.verbosity); 601`endif 602 done = 1; 603 end 604 end 605 606 if(!done && (comparer.compare_map.get(rhs) != null)) begin 607 if(comparer.compare_map.get(rhs) != this) begin 608 comparer.print_msg_object(this, comparer.compare_map.get(rhs)); 609 end 610 done = 1; //don't do any more work after this case, but do cleanup 611 end 612 613 if(!done && comparer.check_type && get_type_name() != rhs.get_type_name()) begin 614 m_sc.stringv = { "lhs type = \"", get_type_name(), 615 "\" : rhs type = \"", rhs.get_type_name(), "\""}; 616 comparer.print_msg(m_sc.stringv); 617 end 618 619 if(!done) begin 620 comparer.compare_map.set(rhs, this); 621 m_field_automation(rhs, OVM_COMPARE, ""); 622 dc = do_compare(rhs, comparer); 623 end 624 625 if(m_sc.scope.depth() == 1) begin 626 m_sc.scope.up(this); 627 end 628 629 comparer.print_rollup(this, rhs); 630 return (comparer.result == 0 && dc == 1); 631endfunction 632 633 634// do_compare 635// ---------- 636 637function bit ovm_object::do_compare (ovm_object rhs, 638 ovm_comparer comparer); 639 return 1; 640endfunction 641 642 643// m_field_automation 644// -------------- 645 646function void ovm_object::m_field_automation ( ovm_object tmp_data__, 647 int what__, 648 string str__ ); 649 return; 650endfunction 651 652 653// check_fields 654// ------------ 655 656function void ovm_object::m_do_field_check(string field); 657 if(m_field_array.exists(field) && (m_field_array[field] == 1)) begin 658 ovm_report_error("MLTFLD", $psprintf("Field %s is defined multiple times in type %s", 659 field, get_type_name())); 660 end 661 m_field_array[field]++; 662endfunction 663 664 665// do_print (virtual override) 666// ------------ 667 668function void ovm_object::do_print(ovm_printer printer); 669 return; 670endfunction 671 672 673// m_pack 674// ------ 675 676function void ovm_object::m_pack (inout ovm_packer packer); 677 678 if(packer!=null) 679 ovm_auto_options_object.packer = packer; 680 else 681 ovm_auto_options_object.packer = ovm_default_packer; 682 packer = ovm_auto_options_object.packer; 683 684 packer.reset(); 685 packer.scope.down(get_name(), this); 686 687 m_field_automation(null, OVM_PACK, ""); 688 do_pack(packer); 689 690 packer.set_packed_size(); 691 692 packer.scope.up(this); 693 694endfunction 695 696 697// pack 698// ---- 699 700function int ovm_object::pack (ref bit bitstream [], 701 input ovm_packer packer =null ); 702 m_pack(packer); 703 packer.get_bits(bitstream); 704 return packer.get_packed_size(); 705endfunction 706 707// pack_bytes 708// ---------- 709 710function int ovm_object::pack_bytes (ref byte unsigned bytestream [], 711 input ovm_packer packer=null ); 712 m_pack(packer); 713 packer.get_bytes(bytestream); 714 return packer.get_packed_size(); 715endfunction 716 717 718// pack_ints 719// --------- 720 721function int ovm_object::pack_ints (ref int unsigned intstream [], 722 input ovm_packer packer=null ); 723 m_pack(packer); 724 packer.get_ints(intstream); 725 return packer.get_packed_size(); 726endfunction 727 728 729// do_pack 730// ------- 731 732function void ovm_object::do_pack (ovm_packer packer ); 733 return; 734endfunction 735 736 737// m_unpack_pre 738// ------------ 739 740function void ovm_object::m_unpack_pre (inout ovm_packer packer); 741 if(packer!=null) 742 ovm_auto_options_object.packer = packer; 743 else 744 ovm_auto_options_object.packer = ovm_default_packer; 745 packer = ovm_auto_options_object.packer; 746 packer.reset(); 747endfunction 748 749 750// m_unpack_post 751// ------------- 752 753function void ovm_object::m_unpack_post (ovm_packer packer); 754 755 int provided_size; 756 757 provided_size = packer.get_packed_size(); 758 759 //Put this object into the hierarchy 760 packer.scope.down(get_name(), this); 761 762 m_field_automation(null, OVM_UNPACK, ""); 763 764 do_unpack(packer); 765 766 //Scope back up before leaving 767 packer.scope.up(this); 768 769 if(packer.get_packed_size() != provided_size) begin 770 ovm_report_warning("BDUNPK", $psprintf("Unpack operation unsuccessful: unpacked %0d bits from a total of %0d bits", packer.get_packed_size(), provided_size)); 771 end 772 773endfunction 774 775 776// unpack 777// ------ 778 779function int ovm_object::unpack (ref bit bitstream [], 780 input ovm_packer packer=null); 781 m_unpack_pre(packer); 782 packer.put_bits(bitstream); 783 m_unpack_post(packer); 784 return packer.get_packed_size(); 785endfunction 786 787// unpack_bytes 788// ------------ 789 790function int ovm_object::unpack_bytes (ref byte unsigned bytestream [], 791 input ovm_packer packer=null); 792 m_unpack_pre(packer); 793 packer.put_bytes(bytestream); 794 m_unpack_post(packer); 795 return packer.get_packed_size(); 796endfunction 797 798 799// unpack_ints 800// ----------- 801 802function int ovm_object::unpack_ints (ref int unsigned intstream [], 803 input ovm_packer packer=null); 804 m_unpack_pre(packer); 805 packer.put_ints(intstream); 806 m_unpack_post(packer); 807 return packer.get_packed_size(); 808endfunction 809 810 811// do_unpack 812// --------- 813 814function void ovm_object::do_unpack (ovm_packer packer); 815 return; 816endfunction 817 818 819// record 820// ------ 821 822function void ovm_object::record (ovm_recorder recorder=null); 823//mxg if(!recorder) 824 if(recorder == null) 825 recorder = ovm_default_recorder; 826 827 if(!recorder.tr_handle) return; 828 829 ovm_auto_options_object.recorder = recorder; 830 recorder.recording_depth++; 831 832 m_field_automation(null, OVM_RECORD, ""); 833 do_record(recorder); 834 835 recorder.recording_depth--; 836 837 if(recorder.recording_depth==0) begin 838 recorder.tr_handle = 0; 839 end 840endfunction 841 842 843// do_record (virtual) 844// --------- 845 846function void ovm_object::do_record (ovm_recorder recorder); 847 return; 848endfunction 849 850 851// m_get_function_type (static) 852// ------------------- 853 854function string ovm_object::m_get_function_type (int what); 855 case (what) 856 OVM_COPY: return "copy"; 857 OVM_COMPARE: return "compare"; 858 OVM_PRINT: return "print"; 859 OVM_RECORD: return "record"; 860 OVM_PACK: return "pack"; 861 OVM_UNPACK: return "unpack"; 862 OVM_FLAGS: return "get_flags"; 863 OVM_SETINT: return "set"; 864 OVM_SETOBJ: return "set_object"; 865 OVM_SETSTR: return "set_string"; 866 default: return "unknown"; 867 endcase 868endfunction 869 870 871// m_get_report_object 872// ------------------- 873 874function ovm_report_object ovm_object::m_get_report_object(); 875 return null; 876endfunction 877 878 879// m_record_field_object (static) 880// --------------------- 881 882function void ovm_object::m_record_field_object (string arg, 883 ovm_object value, 884 ovm_recorder recorder =null, 885 int flag = OVM_DEFAULT); 886 begin 887 if(!recorder) 888 recorder=ovm_auto_options_object.recorder; 889 890 if((flag&OVM_NORECORD) != 0) return; 891 892 recorder.record_object(arg, value); 893 894 end 895endfunction 896 897 898// m_do_data (static) 899// --------- 900 901// function m_do_data (arg, lhs, rhs, what, flag) 902// Precondition: 903// arg -- the name of the short name of the lhs object 904// lhs -- the lhs to do work on (left hand side) 905// lhs -- the rhs to do work from (right hand side) 906// what -- integer, what to do 907// flag -- object flags 908 909function int ovm_object::m_do_data (string arg, 910 inout ovm_bitstream_t lhs, 911 input ovm_bitstream_t rhs, 912 int what, 913 int bits, 914 int flag); 915 916 917 if (what > OVM_END_DATA_EXTRA) 918 return 0; 919 920 if(bits > OVM_STREAMBITS) begin 921 ovm_report_warning("FLDTNC",$psprintf("%s is %0d bits; maximum field size is %0d, truncating", 922 arg, bits, OVM_STREAMBITS)); 923 end 924 case (what) 925 OVM_COPY: 926 begin 927 if(((flag)&OVM_NOCOPY) == 0) begin 928 ovm_bitstream_t mask; 929 mask = -1; 930 mask >>= (OVM_STREAMBITS-bits); 931 lhs = rhs & mask; 932 end 933 return 0; 934 end 935 OVM_COMPARE: 936 begin 937 if(((flag)&OVM_NOCOMPARE) == 0) begin 938 bit r; 939 if(bits <= 64) 940 r = ovm_auto_options_object.comparer.compare_field_int(arg, lhs, rhs, bits, ovm_radix_enum'(flag&OVM_RADIX)); 941 else 942 r = ovm_auto_options_object.comparer.compare_field(arg, lhs, rhs, bits, ovm_radix_enum'(flag&OVM_RADIX)); 943 end 944 return 0; 945 end 946 OVM_PACK: 947 begin 948 if(((flag)&OVM_NOPACK) == 0) begin 949 if(((flag&OVM_ABSTRACT) && ovm_auto_options_object.packer.abstract) || 950 (!(flag&OVM_ABSTRACT) && ovm_auto_options_object.packer.physical)) begin 951 if(bits<=64) 952 ovm_auto_options_object.packer.pack_field_int(lhs, bits); 953 else 954 ovm_auto_options_object.packer.pack_field(lhs, bits); 955 end 956 end 957 return 0; 958 end 959 OVM_UNPACK: 960 begin 961 if(((flag)&OVM_NOPACK) == 0) begin 962 if(((flag&OVM_ABSTRACT) && ovm_auto_options_object.packer.abstract) || 963 (!(flag&OVM_ABSTRACT) && ovm_auto_options_object.packer.physical)) begin 964 if(bits<=64) 965 lhs=ovm_auto_options_object.packer.unpack_field_int(bits); 966 else 967 lhs=ovm_auto_options_object.packer.unpack_field(bits); 968 end 969 end 970 return 0; 971 end 972 OVM_PRINT: 973 begin 974 if(((flag)&OVM_NOPRINT) == 0) 975 begin 976 ovm_printer printer; 977 ovm_radix_enum radix; 978 radix = ovm_radix_enum'(flag&OVM_RADIX); 979 printer = ovm_auto_options_object.printer; 980 printer.print_field(arg, lhs, bits, radix); 981 end 982 end 983 OVM_RECORD: 984 begin 985 if(((flag)&OVM_NORECORD) == 0) 986 begin 987 integer h; 988 ovm_radix_enum radix; 989 990 if(m_sc.scope.depth()) arg = m_sc.scope.get_arg(); 991 radix = ovm_radix_enum'(flag&OVM_RADIX); 992 ovm_auto_options_object.recorder.record_field(arg, lhs, bits, radix); 993 end 994 end 995 endcase 996 return 0; 997endfunction 998 999 1000// m_do_data_object (static) 1001// ---------------- 1002 1003// function m_do_data_object (arg, lhs, rhs, what, flag) 1004// Precondition: 1005// arg -- the name of the short name of the lhs object 1006// lhs -- the lhs to do work on (left hand side) 1007// lhs -- the rhs to do work from (right hand side) 1008// what -- integer, what to do 1009// flag -- object flags 1010 1011function int ovm_object::m_do_data_object (string arg, 1012 inout ovm_object lhs, 1013 input ovm_object rhs, 1014 int what, 1015 int flag); 1016 1017 ovm_object lhs_obj; 1018 1019 if (what > OVM_END_DATA_EXTRA) 1020 return 0; 1021 1022 case (what) 1023 OVM_COPY: 1024 begin 1025 int rval; 1026 if(((flag)&OVM_NOCOPY) != 0) begin 1027 return 0; 1028 end 1029 if(rhs == null) begin 1030 lhs = null; 1031 return OVM_REFERENCE; 1032 end 1033 1034 if(flag & OVM_SHALLOW) begin 1035 rval = OVM_SHALLOW; 1036 end 1037 else if(flag & OVM_REFERENCE) begin 1038 lhs = rhs; 1039 rval = OVM_REFERENCE; 1040 end 1041 else //deepcopy 1042 begin 1043 ovm_object v; 1044 v = ovm_global_copy_map.get(rhs); 1045 if(v) begin 1046 lhs = v; 1047 rval = OVM_REFERENCE; 1048 end 1049 else if(lhs==null) begin 1050 lhs = rhs.clone(); 1051 lhs.set_name(arg); 1052 rval = OVM_REFERENCE; 1053 end 1054 else if(rhs == null) begin 1055 rval = OVM_REFERENCE; 1056 end 1057 else begin 1058 //lhs doesn't change for this case, so don't need to copy back 1059 lhs.copy(rhs); 1060 rval = 0; 1061 end 1062 end 1063 return rval; 1064 end 1065 OVM_COMPARE: 1066 begin 1067 bit refcmp; 1068 1069 if(((flag)&OVM_NOCOMPARE) != 0) begin 1070 return 0; 1071 end 1072 1073 //if the object are the same then don't need to do a deep compare 1074 if(rhs == lhs) return 0; 1075 1076 refcmp = (flag & OVM_SHALLOW) && !(ovm_auto_options_object.comparer.policy == OVM_DEEP); 1077 1078 //do a deep compare here 1079 if(!refcmp && !(ovm_auto_options_object.comparer.policy == OVM_REFERENCE)) 1080 begin 1081 if(((rhs == null) && (lhs != null)) || ((lhs==null) && (rhs!=null))) begin 1082 ovm_auto_options_object.comparer.print_msg_object(lhs, rhs); 1083 return 1; //miscompare 1084 end 1085 if((rhs == null) && (lhs==null)) 1086 return 0; 1087 else begin 1088 bit r; 1089 r = lhs.compare(rhs, ovm_auto_options_object.comparer); 1090 if(r == 0) begin 1091 return 1; 1092 end 1093 else begin 1094 return 0; 1095 end 1096 end 1097 end 1098 else begin //reference compare 1099 if(lhs != rhs) begin 1100 ovm_auto_options_object.comparer.print_msg_object(lhs, rhs); 1101 return 1; 1102 end 1103 end 1104 end 1105 OVM_PACK: 1106 begin 1107 if(((flag&OVM_NOPACK) == 0) && ((flag&OVM_REFERENCE)==0)) begin 1108 if(((flag&OVM_ABSTRACT) && ovm_auto_options_object.packer.abstract) || 1109 (!(flag&OVM_ABSTRACT) && ovm_auto_options_object.packer.physical)) begin 1110 ovm_auto_options_object.packer.pack_object(lhs); 1111 end 1112 end 1113 return 0; 1114 end 1115 OVM_UNPACK: 1116 begin 1117 if(((flag&OVM_NOPACK) == 0) && ((flag&OVM_REFERENCE)==0)) begin 1118 if(((flag&OVM_ABSTRACT) && ovm_auto_options_object.packer.abstract) || 1119 (!(flag&OVM_ABSTRACT) && ovm_auto_options_object.packer.physical)) begin 1120 ovm_auto_options_object.packer.unpack_object_ext(lhs); 1121 end 1122 end 1123 return 0; 1124 end 1125 OVM_PRINT: 1126 begin 1127 if(((flag)&OVM_NOPRINT) == 0) 1128 begin 1129 if(((flag)&OVM_REFERENCE) || (lhs == null)) begin 1130 int d; 1131 d = ovm_auto_options_object.printer.knobs.depth; 1132 ovm_auto_options_object.printer.knobs.depth = 0; 1133 ovm_auto_options_object.printer.print_object(arg, lhs); 1134 ovm_auto_options_object.printer.knobs.depth = d; 1135 end 1136 else begin 1137 ovm_component obj; 1138 if(lhs != null) begin 1139 if($cast(obj,lhs)) begin 1140 if(ovm_auto_options_object.printer.m_scope.current() == obj.get_parent() ) 1141 ovm_auto_options_object.printer.print_object(arg, lhs); 1142 else 1143 ovm_auto_options_object.printer.print_object_header(arg, lhs); 1144 end 1145 else begin 1146 ovm_auto_options_object.printer.print_object(arg, lhs); 1147 end 1148 end 1149 end 1150 end 1151 end 1152 OVM_RECORD: 1153 begin 1154 if(((flag)&OVM_NORECORD) == 0) 1155 begin 1156 //If refernce is on then don't want to do cycle check since only 1157 //recording the reference. 1158 if((flag)&OVM_REFERENCE != 0) 1159 m_record_field_object(arg, lhs, ovm_auto_options_object.recorder,flag); 1160 else begin 1161 if(m_sc.scope.in_hierarchy(lhs)) return 0; 1162 m_record_field_object(arg, lhs, ovm_auto_options_object.recorder,flag); 1163 end 1164 end 1165 end 1166 endcase 1167 return 0; 1168endfunction 1169 1170 1171// m_do_data_string (static) 1172// ---------------- 1173 1174// function m_do_data_string (arg, lhs, rhs, what, flag) 1175// Precondition: 1176// arg -- the name of the short name of the lhs object 1177// lhs -- the lhs to do work on (left hand side) 1178// lhs -- the rhs to do work from (right hand side) 1179// what -- integer, what to do 1180// flag -- object flags 1181// 1182 1183function int ovm_object::m_do_data_string(string arg, 1184 inout string lhs, 1185 input string rhs, 1186 int what, 1187 int flag); 1188 1189 1190 if (what > OVM_END_DATA_EXTRA) 1191 return 0; 1192 1193 case (what) 1194 OVM_COPY: 1195 begin 1196 if(((flag)&OVM_NOCOPY) == 0) begin 1197 lhs = rhs; 1198 end 1199 return 0; 1200 end 1201 OVM_COMPARE: 1202 begin 1203 if(((flag)&OVM_NOCOMPARE) == 0) begin 1204 if(lhs != rhs) begin 1205 m_sc.stringv = { "lhs = \"", lhs, "\" : rhs = \"", rhs, "\""}; 1206 ovm_auto_options_object.comparer.print_msg(m_sc.stringv); 1207 return 1; 1208 end 1209 end 1210 return 0; 1211 end 1212 OVM_PACK: 1213 begin 1214 if(((flag)&OVM_NOPACK) == 0) begin 1215 if(((flag&OVM_ABSTRACT) && ovm_auto_options_object.packer.abstract) || 1216 (!(flag&OVM_ABSTRACT) && ovm_auto_options_object.packer.physical)) begin 1217 ovm_auto_options_object.packer.pack_string(lhs); 1218 end 1219 end 1220 return 0; 1221 end 1222 OVM_UNPACK: 1223 begin 1224 if(((flag)&OVM_NOPACK) == 0) begin 1225 if(((flag&OVM_ABSTRACT) && ovm_auto_options_object.packer.abstract) || 1226 (!(flag&OVM_ABSTRACT) && ovm_auto_options_object.packer.physical)) begin 1227 lhs = ovm_auto_options_object.packer.unpack_string(); 1228 end 1229 end 1230 return 0; 1231 end 1232 OVM_PRINT: 1233 begin 1234 if(((flag)&OVM_NOPRINT) == 0) 1235 begin 1236 ovm_auto_options_object.printer.print_string(arg, lhs); 1237 end 1238 end 1239 OVM_RECORD: 1240 begin 1241 if(((flag)&OVM_NORECORD) == 0) 1242 begin 1243 ovm_auto_options_object.recorder.record_string(arg, lhs); 1244 end 1245 end 1246 endcase 1247 return 0; 1248 1249endfunction 1250 1251 1252//----------------------------------------------------------------------------- 1253// 1254// ovm_status_container 1255// 1256//----------------------------------------------------------------------------- 1257 1258function string ovm_status_container::get_full_scope_arg (); 1259 get_full_scope_arg = scope.get_arg(); 1260endfunction 1261 1262function ovm_scope_stack ovm_status_container::init_scope(); 1263 if(scope==null) scope=new; 1264 return scope; 1265endfunction 1266 1267//----------------------------------------------------------------------------- 1268// 1269// ovm_options_container 1270// 1271//----------------------------------------------------------------------------- 1272 1273ovm_options_container ovm_auto_options_object = ovm_options_container::init(); 1274 1275function ovm_options_container::new(); 1276 comparer = ovm_default_comparer; 1277 packer = ovm_default_packer; 1278 recorder = ovm_default_recorder; 1279 printer = ovm_default_printer; 1280endfunction 1281 1282function ovm_options_container ovm_options_container::init(); 1283 if(ovm_auto_options_object==null) ovm_auto_options_object=new; 1284 return ovm_auto_options_object; 1285endfunction 1286 1287//----------------------------------------------------------------------------- 1288// 1289// ovm_recorder 1290// 1291//----------------------------------------------------------------------------- 1292 1293function void ovm_recorder::record_field (string name, 1294 ovm_bitstream_t value, 1295 int size, 1296 ovm_radix_enum radix=OVM_NORADIX); 1297 if(tr_handle==0) return; 1298 scope.set_arg(name); 1299 1300 if(!radix) 1301 radix = default_radix; 1302 1303 case(radix) 1304 OVM_BIN: ovm_set_attribute_by_name(tr_handle, scope.get_arg(), value, "'b",size); 1305 OVM_OCT: ovm_set_attribute_by_name(tr_handle, scope.get_arg(), value, "'o",size); 1306 OVM_DEC: ovm_set_attribute_by_name(tr_handle, scope.get_arg(), value, "'s",size); 1307 OVM_TIME: ovm_set_attribute_by_name(tr_handle, scope.get_arg(), value, "'u",size); 1308 OVM_STRING: ovm_set_attribute_by_name(tr_handle, scope.get_arg(), value, "'a",size); 1309 default: ovm_set_attribute_by_name(tr_handle, scope.get_arg(), value, "'x",size); 1310 endcase 1311endfunction 1312 1313function void ovm_recorder::record_object (string name, 1314 ovm_object value); 1315 int v; 1316 string str; 1317 1318 if(scope.in_hierarchy(value)) return; 1319 1320 if(identifier) begin 1321`ifdef INCA 1322 $swrite(str, "%0d", value); 1323`else 1324 str = ""; 1325`endif 1326 v = str.atoi(); 1327 scope.set_arg(name); 1328 ovm_set_attribute_by_name(tr_handle, scope.get_arg(), v, "'s"); 1329 end 1330 1331 if(policy != OVM_REFERENCE) begin 1332 if(value!=null) begin 1333 scope.down(name, value); 1334 value.record(this); 1335 scope.up(value); 1336 end 1337 end 1338endfunction 1339 1340function void ovm_recorder::record_string (string name, 1341 string value); 1342 scope.set_arg(name); 1343 ovm_set_attribute_by_name(tr_handle, scope.get_arg(), ovm_string_to_bits(value), "'a"); 1344endfunction 1345 1346function void ovm_recorder::record_time (string name, 1347 time value); 1348 record_field(name, value, 64, OVM_TIME); 1349endfunction 1350 1351function void ovm_recorder::record_generic (string name, 1352 string value); 1353 record_string(name, value); 1354endfunction 1355 1356 1357//----------------------------------------------------------------------------- 1358// 1359// ovm_comparer 1360// 1361//----------------------------------------------------------------------------- 1362 1363function bit ovm_comparer::compare_field (string name, 1364 ovm_bitstream_t lhs, 1365 ovm_bitstream_t rhs, 1366 int size, 1367 ovm_radix_enum radix=OVM_NORADIX); 1368 ovm_bitstream_t mask; 1369 string msg; 1370 1371 if(size <= 64) 1372 return compare_field_int(name, lhs, rhs, size, radix); 1373 1374 mask = -1; 1375 mask >>= (OVM_STREAMBITS-size); 1376 if((lhs & mask) !== (rhs & mask)) begin 1377 scope.set_arg(name); 1378 case (radix) 1379 OVM_BIN: begin 1380 $swrite(msg, "lhs = 'b%0b : rhs = 'b%0b", 1381 lhs&mask, rhs&mask); 1382 end 1383 OVM_OCT: begin 1384 $swrite(msg, "lhs = 'o%0o : rhs = 'o%0o", 1385 lhs&mask, rhs&mask); 1386 end 1387 OVM_DEC: begin 1388 $swrite(msg, "lhs = %0d : rhs = %0d", 1389 lhs&mask, rhs&mask); 1390 end 1391 OVM_TIME: begin 1392 $swrite(msg, "lhs = %0t : rhs = %0t", 1393 lhs&mask, rhs&mask); 1394 end 1395 OVM_STRING: begin 1396 $swrite(msg, "lhs = %0s : rhs = %0s", 1397 lhs&mask, rhs&mask); 1398 end 1399 OVM_ENUM: begin 1400 //Printed as decimal, user should cuse compare string for enum val 1401 $swrite(msg, "lhs = %0d : rhs = %0d", 1402 lhs&mask, rhs&mask); 1403 end 1404 default: begin 1405 $swrite(msg, "lhs = 'h%0x : rhs = 'h%0x", 1406 lhs&mask, rhs&mask); 1407 end 1408 endcase 1409 print_msg(msg); 1410 return 0; 1411 end 1412 return 1; 1413endfunction 1414 1415function bit ovm_comparer::compare_field_int (string name, 1416 logic [63:0] lhs, 1417 logic [63:0] rhs, 1418 int size, 1419 ovm_radix_enum radix=OVM_NORADIX); 1420 logic [63:0] mask; 1421 string msg; 1422 1423 mask = -1; 1424 mask >>= (64-size); 1425 if((lhs & mask) !== (rhs & mask)) begin 1426 scope.set_arg(name); 1427 case (radix) 1428 OVM_BIN: begin 1429 $swrite(msg, "lhs = 'b%0b : rhs = 'b%0b", 1430 lhs&mask, rhs&mask); 1431 end 1432 OVM_OCT: begin 1433 $swrite(msg, "lhs = 'o%0o : rhs = 'o%0o", 1434 lhs&mask, rhs&mask); 1435 end 1436 OVM_DEC: begin 1437 $swrite(msg, "lhs = %0d : rhs = %0d", 1438 lhs&mask, rhs&mask); 1439 end 1440 OVM_TIME: begin 1441 $swrite(msg, "lhs = %0t : rhs = %0t", 1442 lhs&mask, rhs&mask); 1443 end 1444 OVM_STRING: begin 1445 $swrite(msg, "lhs = %0s : rhs = %0s", 1446 lhs&mask, rhs&mask); 1447 end 1448 OVM_ENUM: begin 1449 //Printed as decimal, user should cuse compare string for enum val 1450 $swrite(msg, "lhs = %0d : rhs = %0d", 1451 lhs&mask, rhs&mask); 1452 end 1453 default: begin 1454 $swrite(msg, "lhs = 'h%0x : rhs = 'h%0x", 1455 lhs&mask, rhs&mask); 1456 end 1457 endcase 1458 print_msg(msg); 1459 return 0; 1460 end 1461 return 1; 1462endfunction 1463 1464 1465function bit ovm_comparer::compare_object (string name, 1466 ovm_object lhs, 1467 ovm_object rhs); 1468 1469 if (rhs == lhs) 1470 return 1; 1471 1472 if (policy == OVM_REFERENCE && lhs != rhs) begin 1473 scope.set_arg(name); 1474 print_msg_object(lhs, rhs); 1475 return 0; 1476 end 1477 1478 if (rhs == null || lhs == null) begin 1479 scope.set_arg(name); 1480 print_msg_object(lhs, rhs); 1481 return 0; //miscompare 1482 end 1483 1484 scope.down(name, null); 1485 compare_object = lhs.compare(rhs, this); 1486 scope.up(null); 1487 1488endfunction 1489 1490function bit ovm_comparer::compare_string (string name, 1491 string lhs, 1492 string rhs); 1493 string msg; 1494 if(lhs != rhs) begin 1495 scope.set_arg(name); 1496 msg = { "lhs = \"", lhs, "\" : rhs = \"", rhs, "\""}; 1497 print_msg(msg); 1498 return 0; 1499 end 1500 return 1; 1501endfunction 1502 1503function ovm_comparer ovm_comparer::init(); 1504 if(ovm_default_comparer==null) ovm_default_comparer=new; 1505 return ovm_default_comparer; 1506endfunction