介绍如何构建由模块组成的硬件模型。
1. 子模块
一个模块可以有一个或多个子模块,创建子模块时,需要使用Module(...)包裹:
Module()实现如下:
bc是一个call-by-name参数,在第一次引用时调用。
1) 在调用bc创建模块之前,先保存Builder的状态。
a. Module()只能用于包裹一个模块的实例化操作:
Builder.readyForModuleConstr在实例化模块之前被置为false:
这个要求模块的实例化必须在Module()以内。子模块在父模块中以Module()包裹实例化,顶层模块如何实例化呢?也需要以Module()包裹,后续再讲。
b. 记录当前Builder的状态信息,如当前的val parent = Builder.currentModule为将要实例化的模块的父模块:
2) 调用bc,创建子模块
子模块创建之初,会先要设置Builder的状态,如下注释中所言:
实际代码在BaseModule类体中:
3) 恢复Builder的状态
4) 把创建的模块,转换成为一个component
如果父模块不为空,则使用pushCommand把新创建的模块以DefInstance命令添加到硬件模型中。
2. generateComponent
a. 处理各模块名字;
b. 定义ModuleIO;
c. 将模块输入输出端口转换为component所需的Port;
d. 定义component:val component = DefModule(this, name, firrtlPorts, invalidateCommands ++ getCommands)
3. 顶层模块
顶层模块也需要使用Module()包裹着创建。
如顶层模块Adder4的创建。其创建函数被传给chisel3.Driver.execute方法:
可以看到,这里调用gen()的时候,也包裹在Module()之中。
只是这里的Module(gen())也是一个call-by-name参数,并不是直接调用:
这里的Builder即为之前多次提到的Builder。build方法返回顶层模块Circuit。