/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

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