defmax(a: Int, b: Int): Int = { if (a > b) a else b }
函數裡面可以有其他子函數
1 2 3 4
defmax(a: Int, b: Int): Int = { defmin(a: Int, b: Int): Int = if (a < b) a else b min(a, b) }
List
1 2 3 4 5 6 7 8 9
val list1 = List(1, 2, 3, 4, 5) val list2 = 1 :: 2 :: 3 :: 4 :: 5 :: Nil// Nil: 代表 List 的結尾
var list3 = list1 ++ list2 // 合併 list var m = list1.length // 長度 var n = list1.size // 長度 var x = list1.head // 取第一個元素 var z = list1(2) // 取第三個元素
for loop
1 2 3 4 5 6 7 8 9 10 11 12
for (i <- 1 to 10) { // 包含 10 println(i) } for (i <- 1 until 10) { // 不包含 10 println(i) } for (i <- 1 to 10 by 2) { // 間隔 2 println(i) } for (i <- list1) { // iterator println(i) }
class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
classPoint(xc: Int, yc: Int) { var x: Int = xc var y: Int = yc
defmove(dx: Int, dy: Int): Unit = { x = x + dx y = y + dy }
overridedeftoString: String = "(" + x + ", " + y + ")" println("Point x: " + x + ", y: " + y) // 每次 new 一個 Point 就會執行 }
val pt = newPoint(10, 20) val pt2 = newPoint(xc = 10, yc = 20) pt.move(10, 10)
Chisel 語法
Signal Types and Constants
有三種主要的資料型態:Bits、UInt、SInt
Bits: 用來表示固定長度的二進位數字
UInt: 用來表示無號整數
SInt: 用來表示有號整數
1 2 3
val x = Bits(8.W) // 8-bit val y = UInt(8.W) // unsigned 8-bit val z = SInt(8.W) // signed 8-bit (two's complement)
"hff".U// 255 in hex "o377".U// 255 in octal "b1111_1111".U// 255 in binary
Boolean 型態
1 2
val a = true.B val b = false.B
Combinational Circuits
可以宣告一個空的 Wire,他的寬度會在之後自動推論
1 2
val w = Wire(UInt()) w := a & b
提取 Single Bit
1
val sign = x(31)
提取 Bit Range
1
val sign = x(31, 30)
Concatenation
1 2
val y = Cat(x, z) val z = x ## y // same as Cat(x, y)
Mux Chisel 提供 Mux 函數,用來實現多路選擇器,第一個參數是 Bool 型態
1
val result = Mux(sel, a, b)
Registers
在 Chisel 中,register 默認是連到一個 global clock 上的,且是 rising edge-triggered,還會連到一個同步的 reset signal 上。
RegInit: 用來初始化 register 的值
1
val reg = RegInit(0.U(8.W)) // 8-bit register with initial value 0
更新 register 的值,有多種方法
1 2 3 4 5 6
reg := d // d is the new value of reg val q = reg // q is the value of reg
val nextReg = RegNext(d) // nextReg is the value of d in the next cycle
val bothReg = RegNext(d, 0.U) // 0.U is the reset value
Structure with Bundle and Vec
Bundle: 用來封裝多個訊號,繼承 Bundle Class,定義自己的結構
1 2 3 4 5 6 7 8 9 10
classMyBundleextendsBundle{ val a = UInt(32.W) val b = Bool() }
val bundle = Wire(newMyBundle) bundle.a := 1.U bundle.b := true.B val a = bundle.a val anotherBundle = bundle // anotherBundle is a reference to bundle
val regVec = RegInit(VecInit(Seq.fill(4)(0.U(8.W))))
Vec 不支援範圍 Assignment,可以用 Bundle 自己拆,最後再合併
1 2 3 4 5 6 7 8 9
val assignWord = Wire(UInt(16.W)) classSplitextendsBundle{ val high = UInt(8.W) val low = UInt(8.W) } val split = Wire(newSplit()) split.low := lowByte split.high := highByte assignWord := split.asUInt() // asUInt() is used to convert a Bundle to a UInt
//FullAdder ports: A B Cin Sum Cout valFA_Array = Array.fill(n)(Module(newFullAdder()).io) val carry = Wire(Vec(n+1, UInt(1.W))) val sum = Wire(Vec(n, Bool()))
carry(0) := io.Cin
for (i <- 0 until n) { FA_Array(i).A := io.In1(i) FA_Array(i).B := io.In2(i) FA_Array(i).Cin := carry(i) carry(i+1) := FA_Array(i).Cout sum(i) := FA_Array(i).Sum }
//Method Two defmyMux[T <: Data](sel:Bool,in1:T,in2:T):T={ val x = WireDefault(in1) when(sel){x := in2} x } io.out := myMux(io.sel,io.in1,io.in2)
//Method Three io.out := Mux(io.sel,io.in1,io.in2) }
32xINT32 Register File (2R1W)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
classRegisterFile (readPorts: Int) extendsModule{ val io = IO(newBundle{ val wen = Input(Bool()) val waddr = Input(UInt(5.W)) val wdata = Input(UInt(32.W)) val raddr = Input(Vec(readPorts, UInt(5.W))) val rdata = Output(Vec(readPorts, UInt(32.W))) }) val regs = RegInit(VecInit(Seq.fill(32)(0.U(32.W))))