-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
826 additions
and
163 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// Define a package named Adder | ||
package Adder | ||
|
||
// Import necessary libraries | ||
import chisel3._ | ||
import chisel3.util._ | ||
|
||
/** A module that performs addition of two 64-bit unsigned integers. | ||
* | ||
* @param in_a The first input operand. | ||
* @param in_b The second input operand. | ||
* @param out_c The output sum of the two input operands. | ||
*/ | ||
|
||
//define Uint64_Adder class by extend Module from chisel3 library\ | ||
class Uint64_Adder extends Module { | ||
|
||
// define IO object as bundle (a collection of hardware elements) | ||
val io = IO(new Bundle { // val is the way to define varaible in scala | ||
val in_a = Input(UInt(64.W)) // input, data type is UInt, width is 64 | ||
val in_b = Input(UInt(64.W)) | ||
val out_c = Output(UInt(64.W)) | ||
}) | ||
|
||
// call attributes of io object to perform addition | ||
io.out_c := io.in_a + io.in_b // := is the way to assign value in scala | ||
} | ||
|
||
class Uint32_Adder extends Module { | ||
val io = IO(new Bundle { | ||
val in_a = Input(UInt(32.W)) | ||
val in_b = Input(UInt(32.W)) | ||
val out_c = Output(UInt(32.W)) | ||
}) | ||
io.out_c := io.in_a + io.in_b | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
/** | ||
* This file contains the definition of the VecDotProductModule class, which implements a vector dot product module. | ||
* The module takes two input vectors, A and B, and calculates their dot product by multiplying corresponding elements | ||
* and summing the results. The module supports configurable vector and result data widths, vector length, and selection | ||
* between vectors A and B. It also provides an enable signal for loading data into the vectors. | ||
* | ||
* @param cfg The configuration parameters for the module. | ||
*/ | ||
|
||
package Lab2 | ||
|
||
import chisel3._ | ||
import chisel3.util._ | ||
|
||
case class ModuleConfigs( | ||
vecDWidth: Int = 8, // vector data bit width | ||
resDWidth: Int = 32, // result data bit width | ||
vecLen: Int = 16, // vector length | ||
SEL_A:Bool=true.B, // select vector A | ||
SEL_B:Bool=false.B // select vector B | ||
) | ||
|
||
class VecDotProductModule(cfg:ModuleConfigs) extends Module // take the ModuleConfigs as a parameter | ||
{ | ||
val io = IO(new Bundle | ||
{ | ||
val dataIn = Input(UInt(cfg.vecDWidth.W)) // data input wire | ||
val ld_en = Input(Bool()) // load enable wire | ||
val buf_sel =Input(Bool()) // buffer select wire | ||
val dataIn_ptr =Input(UInt(log2Ceil(cfg.vecLen).W)) // data input pointer wire (address) | ||
val dataOut =Output(UInt(cfg.resDWidth.W)) | ||
}) | ||
|
||
// 向量A的寄存器组 | ||
val vec_A = RegInit(VecInit(Seq.fill(cfg.vecLen)(0.U(cfg.vecDWidth.W)))) | ||
|
||
// 向量B的寄存器组 | ||
val vec_B = RegInit(VecInit(Seq.fill(cfg.vecLen)(0.U(cfg.vecDWidth.W)))) | ||
|
||
// 加载向量A | ||
for(i <- 0 until cfg.vecLen) | ||
{ vec_A(i):=Mux(io.ld_en && io.buf_sel===cfg.SEL_A && io.dataIn_ptr===i.U,io.dataIn,vec_A(i)) } | ||
|
||
// 加载向量B | ||
for(i <- 0 until cfg.vecLen) | ||
{ vec_B(i):=Mux(io.ld_en && io.buf_sel===cfg.SEL_B && io.dataIn_ptr===i.U,io.dataIn,vec_B(i)) } | ||
|
||
// 乘 | ||
val productRes=WireInit(VecInit(Seq.fill(cfg.vecLen)(0.U(cfg.resDWidth.W)))) | ||
productRes.zipWithIndex.map{case(product_res,index)=> | ||
product_res:=vec_A(index)*vec_B(index) | ||
} | ||
|
||
// 加 | ||
val adderTree=Module(new AdderTree(width=cfg.resDWidth,numInputs=cfg.vecLen)) | ||
adderTree.io.inputs:=productRes | ||
|
||
// result | ||
io.dataOut:=adderTree.io.output | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
package Lab2 | ||
|
||
import chisel3._ | ||
import chisel3.util._ | ||
|
||
case class vecDotFSM_Configs( | ||
vecDWidth: Int = 8, | ||
resDWidth: Int = 32, | ||
vecLen: Int = 16, | ||
vecDepth: Int = 4, | ||
SEL_A: Int=0, | ||
SEL_B: Int=1, | ||
SEL_D: Int=2 | ||
) | ||
|
||
class FSM_VecDotProductModule(cfg:vecDotFSM_Configs) extends Module | ||
{ | ||
val io = IO(new Bundle | ||
{ | ||
// ******** Input ********** | ||
val dataIn = Input(UInt(cfg.vecDWidth.W)) | ||
val ld_en = Input(Bool()) // 加载 | ||
val buf_sel =Input(UInt(log2Ceil(3).W)) // 加载哪个向量 A or B or d , 3个选项,宽度为log2Ceil(3) 向上取整 | ||
val dept_ptr =Input(UInt(log2Ceil(cfg.vecDepth).W)) // 加载由buf_sel选定的buf(A/B)中的哪个向量; 该信号同时也用于指定加载d中的哪个元素 | ||
val elem_ptr =Input(UInt(log2Ceil(cfg.vecLen).W)) // 加载由buf_sel选定的buf(A/B)中,并由dept_ptr确定的向量中的哪个元素; | ||
val start = Input(Bool()) // 加载完成后,给信号开始计算(启动状态机) | ||
|
||
// ******** Output ********** | ||
val dataOut =Output(UInt(cfg.resDWidth.W)) | ||
val finish=Output(Bool()) // 状态机计算完后给出结束信号表示算完了 | ||
}) | ||
// Implementation todo | ||
//寄存器组定义 | ||
val vec_A_groups = Reg(Vec(cfg.vecDepth, Vec(cfg.vecLen, UInt(cfg.vecDWidth.W)))) | ||
val vec_B_groups = Reg(Vec(cfg.vecDepth, Vec(cfg.vecLen, UInt(cfg.vecDWidth.W)))) | ||
val c_buffer = Reg(Vec(cfg.vecDepth, UInt(cfg.resDWidth.W))) | ||
// 加载 注意这里的循环并非执行顺序,只是开了这些硬件窗口,只有等到某个元素对应的信号到来时,才会Load,所以一定要加上io.dept_ptr===depth.U | ||
for(depth <- 0 until cfg.vecDepth){ | ||
for(elem <- 0 until cfg.vecLen) | ||
{ | ||
vec_A_groups(depth)(elem):=Mux(io.ld_en && io.buf_sel===cfg.SEL_A.U && io.elem_ptr===elem.U && io.dept_ptr === depth.U,io.dataIn,vec_A_groups(depth)(elem)) | ||
} | ||
for(elem <- 0 until cfg.vecLen) | ||
{ | ||
vec_B_groups(depth)(elem):=Mux(io.ld_en && io.buf_sel===cfg.SEL_B.U && io.elem_ptr===elem.U && io.dept_ptr === depth.U,io.dataIn,vec_B_groups(depth)(elem)) | ||
} | ||
c_buffer(depth):=Mux(io.ld_en && io.buf_sel===cfg.SEL_D.U && io.dept_ptr===depth.U,io.dataIn,c_buffer(depth)) | ||
} | ||
|
||
//状态机定义 | ||
val depthReg = RegInit(0.U(log2Ceil(cfg.vecDepth).W)) | ||
val state = RegInit(0.U(2.W)) | ||
|
||
val temp = RegInit(0.U(cfg.resDWidth.W)) | ||
|
||
io.finish := false.B | ||
io.dataOut := 0.U | ||
//逻辑实现 | ||
when(io.start) { | ||
// 状态机开始 | ||
state := 1.U | ||
} | ||
|
||
switch(state) { | ||
is(0.U) { | ||
// 等待开始信号 | ||
when(io.start) { | ||
//io.dataOut := 0.U | ||
state := 1.U | ||
} | ||
} | ||
is(1.U) { | ||
// 乘 | ||
val productRes = WireInit(VecInit(Seq.fill(cfg.vecLen)(0.U(cfg.resDWidth.W)))) | ||
for (index <- 0 until cfg.vecLen) { | ||
productRes(index) := (vec_A_groups(depthReg)(index)) * (vec_B_groups(depthReg)(index)) | ||
} | ||
// 加 | ||
val adderTree=Module(new AdderTree(width=cfg.resDWidth,numInputs=cfg.vecLen)) | ||
adderTree.io.inputs.zip(productRes).foreach { case (input, product) => | ||
input := product | ||
} | ||
// 加上偏置,将当前所要计算的深度的结果保存到结果寄存器 | ||
printf(p"depthReg = $depthReg, c_buffer = ${c_buffer(depthReg)}\n") | ||
printf(p"adderTree.io.output = ${adderTree.io.output}\n") | ||
printf(p"c_buffer(depthReg) = ${c_buffer(depthReg)}\n") | ||
temp := adderTree.io.output + c_buffer(depthReg) | ||
printf(p"io.dataOut = ${io.dataOut}\n") | ||
// 跳转到下一个状态 | ||
state := 2.U | ||
} | ||
is(2.U) { | ||
// 返回一个计算完成信号 | ||
io.dataOut := temp | ||
io.finish := true.B | ||
// 检查是否是最后一个深度 | ||
when(depthReg === (cfg.vecDepth - 1).U) { | ||
// 如果是最后一个深度,回到状态0 | ||
depthReg := 0.U | ||
state := 0.U | ||
} otherwise { | ||
// 如果不是最后一个深度,继续计算下一个深度 | ||
depthReg := depthReg + 1.U | ||
state := 1.U | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package Lab2 | ||
|
||
import chisel3._ | ||
import chisel3.util._ | ||
|
||
class AdderTree(width: Int, numInputs: Int) extends Module { | ||
require(numInputs > 1, "AdderTree must have more than one input") | ||
|
||
val io = IO(new Bundle { | ||
val inputs = Input(Vec(numInputs, UInt(width.W))) | ||
val output = Output(UInt((width+log2Ceil(numInputs)).W)) | ||
}) | ||
|
||
// +&表示保留进位 | ||
io.output := io.inputs.reduce(_ +& _) | ||
} |
Oops, something went wrong.