Ubuntu上使用Mill的Chisel工程入门
开始
还记得劳资刚刚开始学chisel的时候,跟着github上的Bootcamp学习了一大堆chisel语法(然而不知道这些语法怎么用2333)
彼时彼刻,困扰老子的问题莫过于怎么在自己电脑的ubuntu上(其实是虚拟机辣)把那些chisel代码转化为verilog。
后来啊,老子突然就明白了,老子只要把开源的chisel项目clone下来,然后按照使用说明操作,模仿着他们的Makefile写几句自己的make命令不就行了吗?
于是老子就clone下来了Nutshell(果壳)处理器的开源项目,在该项目里写了自己的代码,Nutshell项目用的Mill作为编译工具,所以Mill也是本文要介绍的编译工具(模仿着开源项目编译对初学者来说实在太友好辣)。
NutShell项目介绍
该项目在这里哟!
这是一个chisel项目,使用Mill作为编译工具,使用verilator作为仿真工具(这次先不介绍Verilator辣)。Mill既可以在Win10上用(需自己下载2333),也可以在linux上用(但是,win10上没找着合适的编辑器插件,所以只好在ubuntu上写代码了555)。
话不多说,我们先clone下来。
删除原来的代码
哈哈,有一个开源项目作为样本,接下来就简单多了。
假设目前在这个项目的最外的文件夹里。
我们进入src/main/scala文件夹,
$ cd src/main/scala
发现里面有好多文件吖,可这跟我有什么关系呢?!
删!删!删!
让我们把这个文件夹里所有文件都删掉
然后新建两个文件夹:mycode,top
其实,mycode文件夹里就是我们的代码啦。(这里只是为了方便,其实不一定非得在一个文件夹里,我们的代码也可以分布在多个文件夹里,就像Nutshell项目原来那样)
top文件夹里是chisel代码执行的入口。(之所以用“执行”一词,是因为chisel是基于scala的,这个入口其实是scala执行的入口,所谓chisel的执行,其实就是chisel向verilog的翻译辣)
书写我们的代码
我们先在mycode文件夹里新建一个文件 Adder.scala,里面就写我们的代码就好辣。
package mycode
import chisel3._
import chisel3.util._
import chisel3.util.experimental.BoringUtils
class Adder extends Module {
val io = IO(new Bundle{
val src0 = Input(UInt(64.W))
val src1 = Input(UInt(64.W))
val result = Output(UInt(64.W))
})
io.result := io.src0 + io.src1
}
我们的目标:把这个chisel代码转换成verilog
但是记住一件事,这个“转换”也不是自动做的,而是通过scala代码做的!!!
天真的我一度以为这种翻译和“编译”一样,都是通过命令行做的,但是我错了。只有命令行还不够,还需要scala代码执行。这种执行翻译的scala代码,才是被命令行执行的东西。(两层套娃2333)
书写执行翻译的Scala代码
好了,我们进入top文件夹写执行翻译的Scala代码。。。
在top文件夹里新建topAdder.scala文件
里面写上:
package top
import mycode.Adder
import chisel3._
object topAdder extends App {
Driver.execute(args, () => new Adder)
}
这里面稍微解释一下下
package top
说明这个代码在top包里,跟Adder模块不在同一个包里
所以要把Adder模块从mycode包里导入进来,于是就有了
import mycode.Adder
这一行。
还要注意的是,这次我们extends了App,其实scala规定,一个scala项目要从extends App的类开始执行。这个extends App的东西就相当于scala的main函数啦。
而且,这时我们定义了object,其实定义了一个对象。(因为入口函数需唯一)
那么里面那一行
Driver.execute(args, () => new Adder)
就是把Adder转换成verilog代码的命令啦(虽然不懂原理,但这个语法记住就好啦,以后把Adder改成自己的顶层模块即可(是要有顶层模块的欧))。
运行整个工程
写了代码,不会运行,是坠致命滴。
不过好在,我们只要模仿着NutShell项目的运行命令就好啦。
安装Mill
首先安装NutShell项目的README里的指示安装Mill
就是这里
安装的时候可能要等一会儿,因为要外网555
安装好以后,就可以写命令行命令辣
使用Mill运行整个工程
我们输入
$ mkdir -p buildAdder
$ mill chiselModule.runMain top.topAdder -td buildAdder --output-file Adder.v
第二行里 top.topAdder 指明了入口函数是哪个包的哪个函数
-td后面跟着你要的输出文件(也就是verilog代码)所在的文件夹
–output-file 后面跟着你输出的verilog文件的名字。
运行这个命令,命令行的结果如下
然后我们进入我们指定的文件夹查看结果:
OK成功辣!!!
为啥要在项目里弄
因为chisel有很多依赖项,
如果你用的sbt运行scala,那么这些依赖项在build.sbt文件里规定
如果你用mill运行scala,那么这些依赖项在build.sc文件里规定
感受一下这玩意儿多恶心:
import mill._, scalalib._
import coursier.maven.MavenRepository
object CustomZincWorkerModule extends ZincWorkerModule {
def repositories() = super.repositories ++ Seq(
MavenRepository("https://oss.sonatype.org/content/repositories/releases"),
MavenRepository("https://oss.sonatype.org/content/repositories/snapshots")
)
}
/**
* Scala 2.12 module that is source-compatible with 2.11.
* This is due to Chisel's use of structural types. See
* https://github.com/freechipsproject/chisel3/issues/606
*/
trait HasXsource211 extends ScalaModule {
override def scalacOptions = T {
super.scalacOptions() ++ Seq(
"-deprecation",
"-unchecked",
"-Xsource:2.11"
)
}
}
trait HasChisel3 extends ScalaModule {
override def ivyDeps = Agg(
ivy"edu.berkeley.cs::chisel3:3.3.2"
)
}
trait HasChiselTests extends CrossSbtModule {
object test extends Tests {
override def ivyDeps = Agg(ivy"org.scalatest::scalatest:3.0.4", ivy"edu.berkeley.cs::chisel-iotesters:1.2+")
def testFrameworks = Seq("org.scalatest.tools.Framework")
}
}
trait HasMacroParadise extends ScalaModule {
// Enable macro paradise for @chiselName et al
val macroPlugins = Agg(ivy"org.scalamacros:::paradise:2.1.0")
def scalacPluginIvyDeps = macroPlugins
def compileIvyDeps = macroPlugins
}
object chiselModule extends CrossSbtModule with HasChisel3 with HasChiselTests with HasXsource211 with HasMacroParadise {
def zincWorker = CustomZincWorkerModule
def crossScalaVersion = "2.11.12"
}
头大大大大大大大大大大@@@@@
现在这个开源项目已经写好了build.sc文件,也就是我们不需要自己重新学习和书写chisel的依赖项辣
它不香嘛????