GSL的拓扑模型是线和节点连接的模型,值的传播,即是值在线和节点之间传播和转化的过程。
值的传播有两种方式:
如果值不变,则终止传播。这样可以破除触发器那样带环的拓扑结构导致的死循环。
一. 深度优先
优先传递给Port的downstream Port,如果downstream Port有下一级的Port,则优先传递给下一级的Port。
拓扑结构没有环时,可以使用这种传播方式。有环比如锁存器时则可能会导致锁存的值是错误的值;
对应到代码中的方法,如下:
- wireA.propagate(): 将wireA的值以深度优先的方法传播下去,直至结束。
- PropagateManager.propagate():把加入到propagate manager中的wires等propagatables的值以深度优先的方式传递下去;(需要先使用PropagateManage.add(wireA, wireB...)方法把需要传播的propagatables加进来)
二. 广度优先
有的结构比如锁存器对时间的有要求:只锁存某个时间窗口到来的值。所以为了使锁存器能够锁存到正确的值,提供了广度优先的传播方式。
广度优先方式,优先把Port所有的downstream ports都传播到,然后在进行下一步传播,即把所有downstream ports的downstream ports传播到。
对应到代码中的方法,如下:
- PropagateManager.propagateParallel(): 每个Port每次只传播一步,即只传播给Port的所有下级Port,而把下级Port加入到PropagateManager等待下一步传播。(需要先使用PropagateManage.add(wireA, wireB...)方法把需要传播的propagatables加进来)
- PropagateManager.propagateParallel(wireA, wireB, ...): 同1,区别在于,直接传播wireA, wireB等的值,不需要用PropagateManage.add()了。
三. 值不变终止传播
如果值不变,则终止传播。这样可以破除触发器那样带环的拓扑结构导致的死循环。
四. 线的传播
Wire本身为Propagatable, 需要也可以定义自身的传播逻辑。
当前的实现逻辑时直接把Input port的值,赋值给Output port。
五. 节点的传播
节点为Propagatable, 可以定义自身的传播逻辑。
如果节点为原子节点,则需要继承AtomicNode类覆盖atomic()方法,实现Input值到Output值的转换逻辑,比如与门、或门、非门等。
如果节点为复合节点,则可以直接使用Node类实现的传播方法:
1. 节点Input的值由上级Wire的Output确定,然后直接赋值给下级Wire的Input。
2. 节点Output的值,直接由上级Wire Output的值确定,然后传递给下级Wire的Input。
即复合节点的Input和Output接口直接传值,不做变化。
六. 举例:Mux
运行输出如下:
PS. 第一步因为sel没有赋值,初始值为x,所以算出来out的值为x。