Composite pattern
#背景
#场景:
验证平台中,各组件以一颗树的形式构成,每个组件都有自己的程序(demo_phase())。
#问题:
如何启动这些组件的程序?
#方案 - 朴素:
将各个组件的demo_phase()程序添加到traverse_demo_phase()中。
function traverse_demo_phase();
top.env.demo_phase();
top.env.reference_model.demo_phase();
top.env.scoreboard.demo_phase();
top.env.in_agent.demo_phase();
top.env.in_agent.driver.demo_phase();
top.env.in_agent.sequencer.demo_phase();
top.env.in_agent.monitor.demo_phase();
endfunction
缺点:
- 当平台中新增sequencer/monitor组件时,traverse_demo_phase()得跟着修改。
- 在平台增/删/改组件的路径/名称时,traverse_demo_phase()代码都得同步修改。
思考:can we do better?
- 能不能解除traverse_demo_phase()与组件的路径/名字之间的耦合?
- 平台组件的组成是一颗树的结构,能不能用树的遍历方法(递归DFS/BFS)遍历整个平台组件并启动demo_phase()?
- 各个组件/节点能不能归一化?
方案 - 组合模式
抽象:
归一化组件: 所有的组件都继承自uvm_component.
归一化指针: m_parent/m_children类型为基类类型uvm_component
归一化的获取指针的方法: get_parent()/get_child(…)
问题:
兄弟节点之间怎么连接?
说明:
完备的归一化指针:
- m_parent: 指向父节点;
- m_children[“driver”]指向子节点driver组件;
- m_children[string]字典中各key: ”sequencer,”driver”,”monitor”之间通过双链表连接。
说明:
平台组件使用组合模式后,可采用递归Deep First Search算法遍历平台。
Top-down phase:前序遍历
Bottom-up phase: 后续遍历
virtual function void traverse (uvm_component comp, uvm_phase phase, uvm_phase_state state);
string name;
comp.demo_phase(phase); // top-down phase place holder
if(comp.get_first_child(name))
do
traverse (comp.get_child(name), phase, state);
while(comp.get_next_child(name));
//comp.demo_phase(phase);// bottom-up phase place holder
endfunction
function void traverse_demo_phase();
top.env.demo_phase();
top.env.reference_model.demo_phase();
… …
top.env.in_agent.driver.demo_phase();
top.env.out_agent.demo_phase();
top.env.out_agent.monitor.demo_phase();
endfunction
缺点:
- 当平台中新增sequencer/monitor组件时,traverse_demo_phase()得跟着修改。
- 在平台增/删/改组件的路径/名称时,traverse_demo_phase()代码都得同步修改。
virtual function void traverse(uvm_component comp, uvm_phase phase, uvm_phase_state state);
string name;
comp.demo_phase(phase);
if(comp.get_first_child(name))
do
traverse(comp.get_child(name), phase, state);
while(comp.get_next_child(name));
endfunction
优点:
平台组件在增加/删除/修改时,traverse代码都无需修改,将组件名称/路径/数量与组件程序启动之间解耦。
#总结
模式说明:
描述了一组对象,这些对象的处理方式与相同类型对象的单个实例相同
应用场景:
树状结构的抽象
当客户忽略对象和单个对象之间的差异时,应使用Composite
UVM应用:
UVM Component Hierarchy – UVM Env
UVM Sequence Library – UVM Sequence
UVM Configuration