当前位置:   article > 正文

设计模式在芯片验证中的应用——迭代器

设计模式在芯片验证中的应用——迭代器

一、迭代器设计模式

迭代器设计模式(iterator)是一种行为设计模式, 让你能在不暴露集合底层表现形式 (列表、 栈和树等数据结构) 的情况下遍历集合中所有的元素。

在验证环境中的checker会收集各个monitor上送过来的transactions,如果有一个专用配置寄存器用于开启或关闭ECC计算,那么在其发生更改时,需要遍历checker中的transactions并修改所预测的数据值,以实现正确的预测。任何在对象集合上执行遍历的场景,无论其内部结构如何,都适合使用iterator设计模式进行建模。该解决方案的主要优点是存储数据的内部结构不需要对外可见,因此可以在不影响环境其余部分的情况下进行修改。Iterator设计模式的使用增加了环境的灵活性,且通常没有任何主要缺点,还是比较推荐大家有机会可以试试。

迭代器设计模式主要包含以下几个组件:

  • 抽象迭代器(Abstract Iterator接口:声明了遍历集合所需的操作: 获取下一个元素、 获取当前位置和重新开始迭代等。
  • 具体迭代器 (Concrete Iterators :继承自抽象迭代器,实现遍历集合的一种特定算法。 迭代器对象必须跟踪自身遍历的进度。 这使得多个迭代器可以相互独立地遍历同一集合。
  • 抽象集合 (Abstract Container接口:声明一个或多个方法来获取与集合兼容的迭代器。 请注意, 返回方法的类型必须被声明为迭代器接口, 因此具体集合可以返回各种不同种类的迭代器。
  • 具体集合 (Concrete Container:继承自抽象集合, 会在客户端请求迭代器时返回一个特定的具体迭代器类实体。

下图为迭代器设计模式在ECC中应用的UML类图。

二、参考代码

迭代器设计模式的参考代码如下:

  1. class base_item extends uvm_object;
  2. `uvm_object_utils (base_item)
  3. function new (string name = "base_item");
  4. super.new(name);
  5. endfunction : new
  6. function void re_generate(bit ecc_en);
  7. if ( ecc_en ) $display("%s No ECC", get_name());
  8. else $display("%s Has ECC", get_name());
  9. endfunction : re_generate
  10. endclass : base_item
  11. virtual class iterator extends uvm_object;
  12. function new (string name = "iterator");
  13. super.new(name);
  14. endfunction : new
  15. pure virtual function bit has_next();
  16. pure virtual function base_item next();
  17. endclass : iterator
  18. virtual class container extends uvm_object;
  19. function new (string name = "container");
  20. super.new(name);
  21. endfunction : new
  22. pure virtual function iterator get_iterator();
  23. endclass : container
  24. class data_container extends container;
  25. `uvm_object_utils (data_container)
  26. static base_item item_q[$];
  27. class queue_iterator extends iterator;
  28. `uvm_object_utils (queue_iterator)
  29. int index;
  30. function new (string name = "queue_iterator");
  31. super.new(name);
  32. endfunction : new
  33. virtual function bit has_next();
  34. if ( index < item_q.size() ) begin
  35. return 1;
  36. end
  37. return 0;
  38. endfunction : has_next
  39. virtual function base_item next();
  40. if ( this.has_next() ) begin
  41. return item_q[index++];
  42. end
  43. return null;
  44. endfunction : next
  45. endclass : queue_iterator
  46. function new (string name = "data_container");
  47. super.new(name);
  48. endfunction : new
  49. virtual function iterator get_iterator();
  50. queue_iterator it_q = queue_iterator::type_id::create("iteratora");
  51. return it_q;
  52. endfunction : get_iterator
  53. function void add(base_item _item);
  54. item_q.push_back(_item);
  55. endfunction : add
  56. endclass : data_container

模拟测试代码如下:

  1. data_container data_cont;
  2. base_item item;
  3. base_item item1 = base_item::type_id::create("item1");
  4. base_item item2 = base_item::type_id::create("item2");
  5. base_item item3 = base_item::type_id::create("item3");
  6. data_cont = data_container::type_id::create("data_cont");
  7. data_cont.add(item1);
  8. data_cont.add(item2);
  9. data_cont.add(item3);
  10. for (iterator it = data_cont.get_iterator(); it.has_next(); ) begin
  11. item = it.next();
  12. item.re_generate(1);
  13. end
  14. for (iterator it = data_cont.get_iterator(); it.has_next(); ) begin
  15. item = it.next();
  16. item.re_generate(0);
  17. end

输出仿真日志如下:

  1. | item1 No ECC
  2. | item2 No ECC
  3. | item3 No ECC
  4. | item1 Has ECC
  5. | item2 Has ECC
  6. | item3 Has ECC

从仿真结果可以看出,添加到container中的三个base_item,在第一次迭代中没有打开ECC,所以都打印出“No ECC”字符串,在第二次迭代中打开了ECC,所以都打印出“Has ECC”字符串。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/677437
推荐阅读
相关标签
  

闽ICP备14008679号