https://mp.weixin.qq.com/s/rgCRorjPYyyD6i7moIzbZgnode
介紹LazyModule和Node構造方法的執行過程,即實例化過程。
1. NullIntSource
以NullIntSource爲例,將其做爲頂層的LazyModule考慮:
2. LazyModule實例化過程
1) 執行NullIntSource的構造方法,首先要逐層向上找到各個父類,而後逐層向下執行各個父類的構造方法;
a. 最開始執行LazyModule類的構造方法:用於構造LazyModule層級結構的是:LazyModule.scope = Some(this)。以後再添加的LazyModule都會加入到這個scope中。
b. 把本LazyModule加入到父LazyModule中:
由於這裏把NullIntSource做爲頂層LazyModule,因此parent爲None,不執行實際添加。
c. 執行NullIntSource的構造方法,建立intnode節點;
其中首先執行BaseNode的構造方法,把當前節點加入到LazyModule.scope中:
d. 定義lazy val module:
intnode是一個source節點,沒有輸入只有輸出。module的實現中默認讓intnode.out輸出0。由於是lazy變量,因此定義時並不執行,而是在引用時執行。
2) 從上可知,在NullIntSource實例化以後,構建了基於LazyModule的層次結構。每一個LazyModule內部的LazyModule和Node也都填充完畢,可是彼此之間的尚未鏈接。
3. LazyModuleImp實例化
lazy val module是LazyModuleImp匿名子類的實例,引用這個module時會對其進行實例化。
在引用的時候,會對這個匿名子類進行實例化。首先逐層向上找到其父類,而後逐層向下執行每一個父類的構造方法。
a. 首先執行LazyModuleImpLike和MultiIOMultiIOModule的構造方法;
b. 而後執行LazyModuleImp的父類的構造方法:
這裏會調用instantiate()方法,把內部的全部LazyModule和Node成對的鏈接連在一塊兒。
c. 執行匿名子類的構造方法,實現NullIntSource的內部邏輯:
主要是鏈接內部的LazyModule和Node,及賦初始值等。
4. 總結
a. LazyModule提供一個框架,以容納內部LazyModule和節點,即實現模塊層次結構(hierarchy);
b. LazyModuleImp實現LazyModule的邏輯(其中爲內部模塊提供鏈接);
c. Node爲LazyModule提供參數協商支持,然後提供輸入輸出鏈接;不能嵌套,也沒有內部邏輯;
5. 附錄
NullIntSource.scala:
// See LICENSE.SiFive for license details.
package freechips.rocketchip.interrupts
import Chisel._
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
/** Useful for stubbing out parts of an interrupt interface where certain devices might be missing */
class NullIntSource(num: Int = 1, ports: Int = 1, sources: Int = 1)(implicit p: Parameters) extends LazyModule
{
val intnode = IntSourceNode(IntSourcePortSimple(num, ports, sources))
lazy val module = new LazyModuleImp(this) {
intnode.out.foreach { case (o, _) => o.foreach { _ := false.B } }
}
}
object NullIntSource {
def apply(num: Int = 1, ports: Int = 1, sources: Int = 1)(implicit p: Parameters): IntNode = {
val null_int_source = LazyModule(new NullIntSource(num, ports, sources))
null_int_source.intnode
}
}