前言
本篇文章旨在对Chisel的书写提供一个风格指南,帮助读者写出更高质量的代码。
本篇会从几个角度出发,讲解几个常见的规范。
#chisel #verilog #vhdl
优点:
- 可读性增强,利于自己与他人阅读代码
- 提高调试效率,更容易找到问题所在
接下来就从命名开始,讲解如何写出高质量的Chisel代码吧。
命名
驼峰命名法(CamelCase)
分类:
- 高驼峰命名法(UpperCamelCase)
- 首单词的首字母大写
- 低驼峰命名法(lowerCamelCase)
- 首单词的首字母小写
正常书写 | UpperCamelCase | lowerCamelCase | 错误示范 |
---|---|---|---|
find GCD | FindGcd | findGcd | |
state for FSM | StateForFsm | stateForFsm | |
mock dut | MockDut | mockDut | |
FIFO Generator | FifoGenerator | fifoGenerator |
用于调试的变量命名
用于调试的变量加上前缀debug
,例如debugSomeValue
常数的命名
常数名一般用高驼峰命名法(UpperCamelCase),其余情况用低驼峰命名法
// 常数
object Constants {
val Number = 5
val Names = "Ed" :: "Ann" :: Nil
val Ages = Map("Ed" -> 35, "Ann" -> 32)
}
// 不是常数
class NonConstantsInClass {
val inClass: String = "in-class"
}
定义寄存器
//定义寄存器的同时初始化为0.U,并定义了位宽为15.W
//有效防止未定义时间的发生
RegInit(0.U(15.W))
Bundle的细分
将同类的变量,或者IO端口分到同一个端口,方便管理
//定义一个Fetch 和 Decode 模块共有的IO端口
class fetchDecodeIO extends Bundle {
val instr = Output(UInt(32.W))
val pc = Output(UInt(32.W))
}
//定义Fetch模块
class Fetch extends Module {
//定义io口
val io = IO(new Bundle {
//定义两个模块共有的部分
val fetchdecodeIO = new FetchDecodeIO()
val a = Input(UInt(32.W))
val b = Input(UInt(32.W))
})
// fetch阶段的实现省略
io.fetchdecodeIO.instr := io.a
io.fetchdecodeIO.pc := io.b
}
显式传参
当实例化模块或者使用函数时,可以显式地传参,可读性更强
//实例化模块
val example = Module(new Example(arg1 = 8, arg2 = 24, arg3 = 11, arg4 = 53))
//使用函数
val counter = genCounter(n=8)
包(package)
包的命名
//正确示范:全部用小写字母命名
package hardware.chips.topsecret.masterplan
//错误示范:不能使用下划线
package hardware.chips.veryObvious.bad_style
导入包
import chisel3._ //只建议对chisel3这个包这样使用
//其他包建议这样使用,可以更清楚地看到导入了什么内容
import rocket.{UseFPU, XLen}
import cde.{Parameters, Field}
//调用时也显式地写上来源的包,可读性更强
val tlb = Module(new rocket.TLB())
间距
使用空格,而不是Tab。
英文版参考资料: