PageRenderTime 167ms CodeModel.GetById 75ms app.highlight 64ms RepoModel.GetById 0ms app.codeStats 2ms

/ovm-2.0.1/src/base/ovm_object.sv

http://camlet.googlecode.com/
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