feat(npc): implement all riscv32i intructions (untested)

This commit is contained in:
xinyangli 2024-04-08 22:51:51 +08:00
parent 50f7d4d7b9
commit 8500df8a6e
Signed by: xin
SSH key fingerprint: SHA256:qZ/tzd8lYRtUFSrfBDBMcUqV4GHKxqeqRA3huItgvbk
7 changed files with 396 additions and 91 deletions

View file

@ -8,7 +8,9 @@ module RamDpi (
input [31:0] writeData, input [31:0] writeData,
input [3:0] writeMask, input [3:0] writeMask,
input reg [31:0] readAddr, input reg [31:0] readAddr,
output reg [31:0] readData output reg [31:0] readData,
input reg [31:0] pc,
output reg [31:0] inst
); );
always @(*) begin always @(*) begin
if (valid) begin // 有读写请求时 if (valid) begin // 有读写请求时
@ -20,5 +22,6 @@ module RamDpi (
else begin else begin
readData = 0; readData = 0;
end end
inst = pmem_read(pc);
end end
endmodule endmodule

View file

@ -6,41 +6,50 @@ import shapeless.{HNil, ::}
class ALUControlInterface extends Bundle { class ALUControlInterface extends Bundle {
object OpSelect extends ChiselEnum { object OpSelect extends ChiselEnum {
val aOpAdd, aOpSub, aOpNot, aOpAnd, aOpOr, aOpXor, aOpSlt, aOpEq, aOpNop = Value val aOpAdd, aOpSub, aOpNot, aOpAnd, aOpOr, aOpXor, aOpSlt, aOpSll, aOpSrl, aOpSra = Value
} }
object SrcSelect extends ChiselEnum { object SrcASelect extends ChiselEnum {
val aSrcRs2, aSrcImm = Value val aSrcARs1, aSrcAPc, aSrcAZero = Value
}
object SrcBSelect extends ChiselEnum {
val aSrcBRs2, aSrcBImmI, aSrcBImmJ, aSrcBImmB, aSrcBImmS = Value
} }
val op = Input(OpSelect()) val op = Input(OpSelect())
val src = Input(SrcSelect()) val srcASelect = Input(SrcASelect())
val srcBSelect = Input(SrcBSelect())
val signExt = Input(Bool())
type CtrlTypes = OpSelect.Type :: SrcSelect.Type :: HNil def ctrlBindPorts = {
def ctrlBindPorts: CtrlTypes = { op :: srcASelect :: srcBSelect :: signExt :: HNil
op :: src :: HNil
} }
} }
class ALU[T <: UInt](tpe: T) extends Module { class ALU[T <: UInt](tpe: T) extends Module {
val control = IO(new ALUControlInterface) val control = IO(new ALUControlInterface)
val in = IO(new Bundle { val in = IO(new Bundle {
val a = Input(Vec(control.SrcSelect.all.length, tpe)) val a = Input(Vec(control.SrcASelect.all.length, tpe))
val b = Input(tpe) val b = Input(Vec(control.SrcBSelect.all.length, tpe))
}) })
val out = IO(new Bundle { val out = IO(new Bundle {
val eq = Output(Bool())
val result = Output(tpe) val result = Output(tpe)
}) })
val a = in.a(control.src.asUInt) val a = in.a(control.srcASelect.asUInt)
val b = in.b(control.srcBSelect.asUInt)
// val adder_b = (Fill(tpe.getWidth, io.op(0)) ^ io.b) + io.op(0) // take (-b) if sub // val adder_b = (Fill(tpe.getWidth, io.op(0)) ^ io.b) + io.op(0) // take (-b) if sub
val add = a + in.b val add = a + b
val sub = a - in.b val sub = a - b
val and = a & in.b val and = a & b
val not = ~a val not = ~a
val or = a | in.b val or = a | b
val xor = a ^ in.b val xor = a ^ b
val slt = a < in.b val slt = a < b
val eq = a === in.b val sll = a << b(log2Ceil(tpe.getWidth), 0)
val srl = a >> b(log2Ceil(tpe.getWidth), 0)
val sra = a.asSInt >> b(log2Ceil(tpe.getWidth), 0)
out.eq := a === b
import control.OpSelect._ import control.OpSelect._
@ -52,7 +61,9 @@ class ALU[T <: UInt](tpe: T) extends Module {
aOpOr -> or, aOpOr -> or,
aOpXor -> xor, aOpXor -> xor,
aOpSlt -> slt, aOpSlt -> slt,
aOpEq -> eq aOpSll -> sll,
aOpSrl -> srl,
aOpSra -> sra.asUInt
)) ))
} }

View file

@ -6,19 +6,32 @@ import chisel3.util.HasBlackBoxResource
import chisel3.util.log2Ceil import chisel3.util.log2Ceil
import chisel3.experimental.noPrefix import chisel3.experimental.noPrefix
import scala.collection.SeqMap import scala.collection.SeqMap
import javax.swing.plaf.synth.SynthRadioButtonMenuItemUI import flow.components
import shapeless.{HNil, ::}
class RamInterface[T <: Data](tpe: T, addrWidth: Int) extends Bundle { class RamControlInterface(addrWidth: Int) extends Bundle {
val valid = Input(Bool()) val valid = Input(Bool())
val writeMask = Input(UInt((addrWidth / 8).W))
val writeEnable = Input(Bool()) val writeEnable = Input(Bool())
def ctrlBindPorts = {
valid :: writeMask :: writeEnable :: HNil
}
}
/* FIXME: Extends here might not be the best solution.
* We need a way to merge two bundles together
*/
class RamInterface[T <: Data](tpe: T, addrWidth: Int) extends RamControlInterface(addrWidth) {
val writeAddr = Input(UInt(addrWidth.W)) val writeAddr = Input(UInt(addrWidth.W))
val writeData = Input(tpe) val writeData = Input(tpe)
val writeMask = Input(UInt((addrWidth / 8).W))
val readAddr = Input(UInt(addrWidth.W)) val readAddr = Input(UInt(addrWidth.W))
val readData = Output(tpe) val readData = Output(tpe)
val pc = Input(UInt(addrWidth.W))
val inst = Output(tpe)
} }
class RamDpi extends BlackBox with HasBlackBoxResource { class RamDpi extends BlackBox with HasBlackBoxResource {
val io = IO(new RamInterface(UInt(32.W), 32)) val io = IO((new RamInterface(UInt(32.W), 32)))
addResource("/RamDpi.v") addResource("/RamDpi.v")
} }

View file

@ -6,33 +6,42 @@ import shapeless.{HNil, ::}
class PcControlInterface extends Bundle { class PcControlInterface extends Bundle {
object SrcSelect extends ChiselEnum { object SrcSelect extends ChiselEnum {
val pStaticNpc, pBranchResult = Value val pStaticNpc, pExeOut = Value
} }
val useImmB = Input(Bool())
val srcSelect = Input(SrcSelect()) val srcSelect = Input(SrcSelect())
type CtrlTypes = SrcSelect.Type :: HNil def ctrlBindPorts = {
def ctrlBindPorts: CtrlTypes = { useImmB :: srcSelect :: HNil
srcSelect :: HNil
} }
} }
class ProgramCounter[T <: Data](tpe: T) extends Module { class ProgramCounter[T <: UInt](tpe: T) extends Module {
val control = IO(new PcControlInterface) val control = IO(new PcControlInterface)
val in = IO(new Bundle { val in = IO(new Bundle {
val pcSrcs = Input(Vec(control.SrcSelect.all.length, tpe)) val immB = Input(tpe)
val exeOut = Input(tpe)
}) })
val out = IO(Output(tpe)) val out = IO(Output(tpe))
private val pc = RegInit(0x80000000L.U) private val pc_reg = RegInit(0x80000000L.U)
pc := in.pcSrcs(control.srcSelect.asUInt) // pc := in.pcSrcs(control.srcSelect.asUInt)
out := pc import control.SrcSelect._
when( control.useImmB === true.B ) {
pc_reg := pc_reg + in.immB
}. elsewhen( control.srcSelect === pStaticNpc) {
pc_reg := pc_reg + 4.U
}. elsewhen( control.srcSelect === pExeOut) {
pc_reg := in.exeOut
}
out := pc_reg
} }
object ProgramCounter { object ProgramCounter {
def apply[T <: Data](tpe: T): ProgramCounter[T] = { def apply[T <: UInt](tpe: T): ProgramCounter[T] = {
val pc = Module(new ProgramCounter(tpe)) val pc = Module(new ProgramCounter(tpe))
pc pc
} }

View file

@ -5,18 +5,17 @@ import chisel3.util.log2Ceil
import chisel3.util.UIntToOH import chisel3.util.UIntToOH
import chisel3.util.MuxLookup import chisel3.util.MuxLookup
import chisel3.experimental.Trace._ import chisel3.experimental.Trace._
import shapeless.{ HNil, :: } import shapeless.{ HList, HNil, :: }
class RegControl extends Bundle { class RegControl extends Bundle {
object WriteSelect extends ChiselEnum { object WriteSelect extends ChiselEnum {
val rAluOut, rMemOut = Value val rAluOut, rMemOut, rNpc = Value
} }
val writeEnable = Input(Bool()) val writeEnable = Input(Bool())
val writeSelect = Input(WriteSelect()) val writeSelect = Input(WriteSelect())
type CtrlTypes = Bool :: WriteSelect.Type :: HNil def ctrlBindPorts = {
def ctrlBindPorts: CtrlTypes = {
writeEnable :: writeSelect :: HNil writeEnable :: writeSelect :: HNil
} }
traceName(writeEnable) traceName(writeEnable)
@ -40,7 +39,8 @@ class RegisterFile[T <: Data](tpe: T, regCount: Int, numReadPorts: Int) extends
val writeAddrOH = UIntToOH(in.writeAddr) val writeAddrOH = UIntToOH(in.writeAddr)
for ((reg, i) <- regFile.zipWithIndex.tail) { for ((reg, i) <- regFile.zipWithIndex.tail) {
reg := Mux(writeAddrOH(i.U(log2Ceil(regCount).W)) && control.writeEnable, in.writeData(control.writeSelect.asUInt), reg) reg := Mux(
writeAddrOH(i.U(log2Ceil(regCount).W)) && control.writeEnable, in.writeData(control.writeSelect.asUInt), reg)
} }
regFile(0) := 0.U regFile(0) := 0.U

View file

@ -2,12 +2,8 @@ package flow
import scala.reflect.runtime.universe._ import scala.reflect.runtime.universe._
import chisel3._ import chisel3._
import chisel3.util.{MuxLookup, Fill, Decoupled, Counter, Queue, Reverse}
import chisel3.util.{SRAM}
import chisel3.util.experimental.decode.{decoder, TruthTable} import chisel3.util.experimental.decode.{decoder, TruthTable}
import chisel3.util.log2Ceil import chisel3.util._
import chisel3.util.BitPat
import chisel3.util.Enum
import chisel3.experimental.Trace._ import chisel3.experimental.Trace._
import shapeless.{HNil, ::} import shapeless.{HNil, ::}
import shapeless.HList import shapeless.HList
@ -15,68 +11,322 @@ import shapeless.ops.coproduct.Prepend
import chisel3.util.{ BinaryMemoryFile, HexMemoryFile } import chisel3.util.{ BinaryMemoryFile, HexMemoryFile }
import chisel3.experimental.Trace import chisel3.experimental.Trace
import scala.collection.IndexedSeqView
import shapeless.Poly1
import flow.components.RamControlInterface
object RV32Inst { object RV32Inst {
private val bp = BitPat private val bp = BitPat
val addi = this.bp("b???????_?????_?????_000_?????_00100_11")
val inv = this.bp("b???????_?????_?????_???_?????_?????_??")
}
class PcControl(width: Int) extends Bundle { val lui = this.bp("b???????_?????_?????_???_?????_01101_11")
object SrcSelect extends ChiselEnum { val auipc = this.bp("b???????_?????_?????_???_?????_00101_11")
val pPC, pExeResult = Value
} val jal = this.bp("b???????_?????_?????_???_?????_11011_11")
val srcSelect = Output(SrcSelect()) val jalr = this.bp("b???????_?????_?????_???_?????_11001_11")
val beq = this.bp("b???????_?????_?????_000_?????_11000_11")
val bne = this.bp("b???????_?????_?????_001_?????_11000_11")
val blt = this.bp("b???????_?????_?????_100_?????_11000_11")
val bge = this.bp("b???????_?????_?????_101_?????_11000_11")
val bltu = this.bp("b???????_?????_?????_110_?????_11000_11")
val bgeu = this.bp("b???????_?????_?????_111_?????_11000_11")
val lb = this.bp("b???????_?????_?????_000_?????_00000_11")
val lh = this.bp("b???????_?????_?????_001_?????_00000_11")
val lw = this.bp("b???????_?????_?????_010_?????_00000_11")
val lbu = this.bp("b???????_?????_?????_100_?????_00000_11")
val lhu = this.bp("b???????_?????_?????_101_?????_00000_11")
val sb = this.bp("b???????_?????_?????_000_?????_01000_11")
val sh = this.bp("b???????_?????_?????_001_?????_01000_11")
val sw = this.bp("b???????_?????_?????_010_?????_01000_11")
val addi = this.bp("b???????_?????_?????_000_?????_00100_11")
val slti = this.bp("b???????_?????_?????_010_?????_00100_11")
val sltiu = this.bp("b???????_?????_?????_011_?????_00100_11")
val xori = this.bp("b???????_?????_?????_100_?????_00100_11")
val ori = this.bp("b???????_?????_?????_110_?????_00100_11")
val andi = this.bp("b???????_?????_?????_111_?????_00100_11")
val slli = this.bp("b0000000_?????_?????_001_?????_00100_11")
val srli = this.bp("b0000000_?????_?????_101_?????_00100_11")
val srai = this.bp("b0100000_?????_?????_101_?????_00100_11")
val add = this.bp("b0000000_?????_?????_000_?????_01100_11")
val sub = this.bp("b0100000_?????_?????_000_?????_01100_11")
val sll = this.bp("b0000000_?????_?????_001_?????_01100_11")
val slt = this.bp("b0000000_?????_?????_010_?????_01100_11")
val sltu = this.bp("b0000000_?????_?????_011_?????_01100_11")
val xor = this.bp("b0000000_?????_?????_100_?????_01100_11")
val srl = this.bp("b0000000_?????_?????_101_?????_01100_11")
val sra = this.bp("b0100000_?????_?????_101_?????_01100_11")
val or = this.bp("b0000000_?????_?????_110_?????_01100_11")
val and = this.bp("b0000000_?????_?????_111_?????_01100_11")
val ebreak = this.bp("b0000000_00001_00000_000_00000_11100_11")
val mul = this.bp("b0000001_?????_?????_000_?????_01100_11")
val mulh = this.bp("b0000001_?????_?????_001_?????_01100_11")
val mulhsu = this.bp("b0000001_?????_?????_010_?????_01100_11")
val mulhu = this.bp("b0000001_?????_?????_011_?????_01100_11")
val div = this.bp("b0000001_?????_?????_100_?????_01100_11")
val divu = this.bp("b0000001_?????_?????_101_?????_01100_11")
val rem = this.bp("b0000001_?????_?????_110_?????_01100_11")
val remu = this.bp("b0000001_?????_?????_111_?????_01100_11")
val inv = this.bp("b???????_?????_?????_???_?????_?????_??")
} }
import flow.components.{RegControl, PcControlInterface, ALUControlInterface} import flow.components.{RegControl, PcControlInterface, ALUControlInterface}
class Control(width: Int) extends Module { class Control(width: Int) extends RawModule {
// Helpers
class WrapList[T](vl: T) { type Type = T; val v = vl}
object wrap extends Poly1 {
implicit def default[A] = at[A](Right(_).withLeft[Int])
}
def lit(x: Element) = { x.litValue.toInt }
def toBits(t: dst.Type): BitPat = {
val list = t.toList
list.map(e => e match {
case Right(x) => BitPat(lit(x).U(x.getWidth.W))
case Left(x) => BitPat.dontCare(x)
}).reduceLeft(_ ## _)
}
val r = Right
def l[T <: Any](x: T) = x match {
case x: ChiselEnum => Left(log2Ceil(x.all.length))
case x: Data => Left(x.getWidth)
case _ => throw new IllegalArgumentException
}
val inst = IO(Input(UInt(width.W))) val inst = IO(Input(UInt(width.W)))
val reg = IO(Flipped(new RegControl)) val reg = IO(Flipped(new RegControl))
val pc = IO(Flipped(new PcControlInterface)) val pc = IO(Flipped(new PcControlInterface))
val alu = IO(Flipped(new ALUControlInterface)) val alu = IO(Flipped(new ALUControlInterface))
val ram = IO(Flipped(new RamControlInterface(32)))
// TODO: Add .ctrlTypes together instead of writing them by hand. val dst = new WrapList((
type T = reg.ctrlBindPorts ++
Bool :: reg.WriteSelect.Type :: pc.SrcSelect.Type :: alu.OpSelect.Type :: alu.SrcSelect.Type :: HNil pc.ctrlBindPorts ++
val dst: T = reg.ctrlBindPorts ++ pc.ctrlBindPorts ++ alu.ctrlBindPorts alu.ctrlBindPorts ++
ram.ctrlBindPorts).map(wrap))
val dstList = dst.toList val dstList = dst.v.toList
val reversePrefixSum = dstList.scanLeft(0)(_ + _.getWidth).reverse val controlWidth = dstList.map(_.toOption.get.getWidth).reduce(_ + _)
val slices = reversePrefixSum.zip(reversePrefixSum.tail) val reversePrefixSum = dstList.scanLeft(0)(_ + _.toOption.get.getWidth)
val sliceIndex = reversePrefixSum.map(controlWidth - _)
val slices = sliceIndex.map(_ - 1).zip(sliceIndex.tail)
import reg.WriteSelect._ import reg.WriteSelect._
import reg._
import pc.SrcSelect._ import pc.SrcSelect._
import pc._
import alu.OpSelect._ import alu.OpSelect._
import alu.SrcSelect._ import alu.SrcASelect._
import alu.SrcBSelect._
import pc._
import RV32Inst._ import RV32Inst._
val ControlMapping: Array[(BitPat, T)] = Array( val ControlMapping: Array[(BitPat, dst.Type)] = Array(
// Regs :: PC :: Exe // Regs | writeEnable :: writeSelect :: HNil
// writeEnable :: writeSelect :: srcSelect :: // PC | useImmB :: srcSelect :: HNil
(addi, true.B :: rAluOut :: pStaticNpc :: aOpAdd :: aSrcImm :: HNil), // Exe | op :: srcASelect :: srcBSelect :: signExt :: HNil
) // Mem | valid :: writeMask :: writeEnable :: HNil
val default = BitPat.dontCare(dstList.map(_.getWidth).reduce(_ + _))
def toBits(t: T): BitPat = { // ---- Control Transfer Instructions ----
val list: List[Data] = t.toList (jal , (r(true.B) :: r(rNpc) ::
list.map(x => BitPat(x.litValue.toInt.U(x.getWidth.W))).reduceLeft(_ ## _) r(false.B) :: r(pExeOut) ::
} r(aOpAdd) :: r(aSrcAPc) :: r(aSrcBImmJ) :: r(false.B) ::
r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil)),
(jalr , (r(true.B) :: r(rNpc) ::
r(false.B) :: r(pExeOut) ::
r(aOpAdd) :: r(aSrcARs1) :: r(aSrcBImmJ) :: r(false.B) ::
r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil)),
(beq , (r(false.B) :: l(WriteSelect) ::
r(true.B) :: r(pExeOut) ::
r(aOpSlt) :: r(aSrcAPc) :: r(aSrcBImmB) :: l(Bool()) ::
r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil)),
(bne , (r(false.B) :: l(WriteSelect) ::
r(true.B) :: r(pExeOut) ::
r(aOpSlt) :: r(aSrcAPc) :: r(aSrcBImmB) :: l(Bool()) ::
r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil)),
(blt , (r(false.B) :: l(WriteSelect) ::
r(true.B) :: r(pExeOut) ::
r(aOpSlt) :: r(aSrcAPc) :: r(aSrcBImmB) :: r(true.B) ::
r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil)),
(bge , (r(false.B) :: l(WriteSelect) ::
r(true.B) :: r(pExeOut) ::
r(aOpSlt) :: r(aSrcAPc) :: r(aSrcBImmB) :: r(true.B) ::
r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil)),
(bltu , (r(false.B) :: l(WriteSelect)::
r(true.B) :: r(pExeOut) ::
r(aOpSlt) :: r(aSrcAPc) :: r(aSrcBImmB) :: r(false.B) ::
r(false.B) :: l(UInt(4.W)) :: r(false.B) :: HNil)),
(bgeu , (r(false.B) :: l(WriteSelect)::
r(true.B) :: r(pExeOut) ::
r(aOpSlt) :: r(aSrcAPc) :: r(aSrcBImmB) :: r(false.B) ::
r(false.B) :: l(UInt(4.W)) :: r(false.B) :: HNil)),
// ---- Memory Access Instructions ----
(lb , (r(true.B) :: r(rMemOut) ::
r(false.B) :: r(pStaticNpc) ::
r(aOpAdd) :: r(aSrcARs1) :: r(aSrcBImmI) :: l(Bool()) ::
r(true.B) :: l(UInt(4.W)) :: r(false.B) :: HNil)),
(lh , (r(true.B) :: r(rMemOut) ::
r(false.B) :: r(pStaticNpc) ::
r(aOpAdd) :: r(aSrcARs1) :: r(aSrcBImmI) :: l(Bool()) ::
r(true.B) :: l(UInt(4.W)) :: r(false.B) :: HNil)),
(lw , (r(true.B) :: r(rMemOut) ::
r(false.B) :: r(pStaticNpc) ::
r(aOpAdd) :: r(aSrcARs1) :: r(aSrcBImmI) :: l(Bool()) ::
r(true.B) :: l(UInt(4.W)) :: r(false.B) :: HNil)),
(sb , (r(false.B) :: l(WriteSelect)::
r(false.B) :: r(pStaticNpc) ::
r(aOpAdd) :: r(aSrcARs1) :: r(aSrcBImmI) :: l(Bool()) ::
r(true.B) :: r(1.U(4.W)) :: r(false.B) :: HNil)),
(sh , (r(false.B) :: l(WriteSelect)::
r(false.B) :: r(pStaticNpc) ::
r(aOpAdd) :: r(aSrcARs1) :: r(aSrcBImmI) :: l(Bool()) ::
r(true.B) :: r(3.U(4.W)) :: r(false.B) :: HNil)),
(sw , (r(false.B) :: l(WriteSelect)::
r(false.B) :: r(pStaticNpc) ::
r(aOpAdd) :: r(aSrcARs1) :: r(aSrcBImmI) :: l(Bool()) ::
r(true.B) :: r(15.U(4.W)) :: r(false.B) :: HNil)),
// ---- Integer Computational Instructions ---
(addi , (r(true.B) :: r(rAluOut) ::
r(false.B) :: r(pStaticNpc) ::
r(aOpAdd) :: r(aSrcARs1) :: r(aSrcBImmI) :: l(Bool()) ::
r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil)),
(slti , (r(true.B) :: r(rAluOut) ::
r(false.B) :: r(pStaticNpc) ::
r(aOpSlt) :: r(aSrcARs1) :: r(aSrcBImmI) :: r(true.B) ::
r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil)),
(sltiu , (r(true.B) :: r(rAluOut) ::
r(false.B) :: r(pStaticNpc) ::
r(aOpSlt) :: r(aSrcARs1) :: r(aSrcBImmI) :: r(false.B) ::
r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil)),
(xori , (r(true.B) :: r(rAluOut) ::
r(false.B) :: r(pStaticNpc) ::
r(aOpOr) :: r(aSrcARs1) :: r(aSrcBImmI) :: l(Bool()) ::
r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil)),
(ori , (r(true.B) :: r(rAluOut) ::
r(false.B) :: r(pStaticNpc) ::
r(aOpXor) :: r(aSrcARs1) :: r(aSrcBImmI) :: l(Bool()) ::
r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil)),
(andi , (r(true.B) :: r(rAluOut) ::
r(false.B) :: r(pStaticNpc) ::
r(aOpAnd) :: r(aSrcARs1) :: r(aSrcBImmI) :: l(Bool()) ::
r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil)),
(slli , (r(true.B) :: r(rAluOut) ::
r(false.B) :: r(pStaticNpc) ::
r(aOpSll) :: r(aSrcARs1) :: r(aSrcBImmI) :: l(Bool()) ::
r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil)),
(srli , (r(true.B) :: r(rAluOut) ::
r(false.B) :: r(pStaticNpc) ::
r(aOpSrl) :: r(aSrcARs1) :: r(aSrcBImmI) :: l(Bool()) ::
r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil)),
(srai , (r(true.B) :: r(rAluOut) ::
r(false.B) :: r(pStaticNpc) ::
r(aOpSra) :: r(aSrcARs1) :: r(aSrcBImmI) :: l(Bool()) ::
r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil)),
(add , (r(true.B) :: r(rAluOut) ::
r(false.B) :: r(pStaticNpc) ::
r(aOpAdd) :: r(aSrcARs1) :: r(aSrcBRs2) :: l(Bool()) ::
r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil)),
(sub , (r(true.B) :: r(rAluOut) ::
r(false.B) :: r(pStaticNpc) ::
r(aOpSub) :: r(aSrcARs1) :: r(aSrcBRs2) :: l(Bool()) ::
r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil)),
(sll , (r(true.B) :: r(rAluOut) ::
r(false.B) :: r(pStaticNpc) ::
r(aOpSll) :: r(aSrcARs1) :: r(aSrcBRs2) :: l(Bool()) ::
r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil)),
(slt , (r(true.B) :: r(rAluOut) ::
r(false.B) :: r(pStaticNpc) ::
r(aOpSlt) :: r(aSrcARs1) :: r(aSrcBRs2) :: r(true.B) ::
r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil)),
(sltu , (r(true.B) :: r(rAluOut) ::
r(false.B) :: r(pStaticNpc) ::
r(aOpSlt) :: r(aSrcARs1) :: r(aSrcBRs2) :: r(false.B) ::
r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil)),
(xor , (r(true.B) :: r(rAluOut) ::
r(false.B) :: r(pStaticNpc) ::
r(aOpXor) :: r(aSrcARs1) :: r(aSrcBRs2) :: l(Bool()) ::
r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil)),
(srl , (r(true.B) :: r(rAluOut) ::
r(false.B) :: r(pStaticNpc) ::
r(aOpSrl) :: r(aSrcARs1) :: r(aSrcBRs2) :: l(Bool()) ::
r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil)),
(sra , (r(true.B) :: r(rAluOut) ::
r(false.B) :: r(pStaticNpc) ::
r(aOpSra) :: r(aSrcARs1) :: r(aSrcBRs2) :: l(Bool()) ::
r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil)),
(or , (r(true.B) :: r(rAluOut) ::
r(false.B) :: r(pStaticNpc) ::
r(aOpOr) :: r(aSrcARs1) :: r(aSrcBRs2) :: l(Bool()) ::
r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil)),
(and , (r(true.B) :: r(rAluOut) ::
r(false.B) :: r(pStaticNpc) ::
r(aOpAnd) :: r(aSrcARs1) :: r(aSrcBRs2) :: l(Bool()) ::
r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil)),
)
val default = BitPat(0.U(controlWidth.W))
// println(s"ControlMapping = ${ControlMapping.map(it => (it._1 -> toBits(it._2))).foreach(x => println(x._2))}\n")
val out = decoder( val out = decoder(
inst, inst,
TruthTable(ControlMapping.map(it => (it._1 -> toBits(it._2))), default)) TruthTable(ControlMapping.map(it => (it._1 -> toBits(it._2))), default))
val srcList = slices.map(s => out(s._1 - 1, s._2)) val srcList = slices.map(s => out(s._1, s._2))
assert(out != default)
println(s"out = $out, default = $default\n")
println(s"dstList = ${dstList}\n")
println(s"srcList = ${srcList}\n")
srcList srcList
.zip(dstList.reverse) .zip(dstList)
.foreach({ case (src, dst) => .foreach({ case (src, dst) =>
dst := src.asTypeOf(dst) dst.toOption.get := src.asTypeOf(dst.toOption.get)
}) })
pc.useImmB := DontCare
} }
import flow.components.{RegisterFile, ProgramCounter, ALU, RamDpi} import flow.components.{RegisterFile, ProgramCounter, ALU, RamDpi}
import chisel3.util.experimental.loadMemoryFromFileInline import chisel3.util.experimental.loadMemoryFromFileInline
class Flow extends Module { class Flow extends Module {
def lit(x: Data) = { x.litValue.toInt }
val dataType = UInt(32.W) val dataType = UInt(32.W)
val ram = Module(new RamDpi) val ram = Module(new RamDpi)
val control = Module(new Control(32)) val control = Module(new Control(32))
@ -84,42 +334,61 @@ class Flow extends Module {
val pc = Module(new ProgramCounter(dataType)) val pc = Module(new ProgramCounter(dataType))
val alu = Module(new ALU(dataType)) val alu = Module(new ALU(dataType))
ram.io.readAddr := pc.out // TODO: Switch to Decoupled and Arbiter later
val inst = ram.io.readData ram.io.pc := pc.out
val inst = ram.io.inst
dontTouch(reg.control.writeEnable) dontTouch(reg.control.writeEnable)
import control.pc.SrcSelect._ import control.pc.SrcSelect._
pc.in.pcSrcs(pStaticNpc.litValue.toInt) := pc.out + 4.U val npc = Wire(dataType)
pc.in.pcSrcs(pBranchResult.litValue.toInt) := alu.out.result npc := pc.out + 4.U
pc.in.exeOut := alu.out.result
pc.in.immB := Cat(Fill(20, inst(31)), inst(7), inst(30, 25), inst(11, 8), inst(0))
control.inst := inst control.inst := inst
reg.control <> control.reg reg.control <> control.reg
// FIXME: Probably optimizable with bulk connection
pc.control <> control.pc pc.control <> control.pc
alu.control <> control.alu alu.control <> control.alu
val branchUseSlt = Wire(Bool())
val branchInvertResult = Wire(Bool())
branchUseSlt := inst(14)
branchInvertResult := inst(12)
val _branchResult = Mux(branchUseSlt, alu.out.result(0), alu.out.eq)
val branchResult = Mux(branchInvertResult, _branchResult, !_branchResult)
pc.control.useImmB := control.pc.useImmB && _branchResult
import control.reg.WriteSelect._ import control.reg.WriteSelect._
reg.in.writeData(rAluOut.litValue.toInt) := alu.out.result reg.in.writeData(lit(rAluOut)) := alu.out.result
// TODO: Read address in load command goes here // TODO: Read address in load command goes here
reg.in.writeData(rMemOut.litValue.toInt) := DontCare reg.in.writeData(lit(rMemOut)) := ram.io.readData
reg.in.writeData(lit(rNpc)) := npc
reg.in.writeAddr := inst(11, 7) reg.in.writeAddr := inst(11, 7)
reg.in.rs(0) := inst(19, 15) // rs1 reg.in.rs(0) := inst(19, 15) // rs1
reg.in.rs(1) := inst(24, 20) // rs2 reg.in.rs(1) := inst(24, 20) // rs2
// TODO: Memory write goes here // TODO: Memory write goes here
ram.io.writeAddr := DontCare ram.io.writeAddr := alu.out.result
ram.io.writeData := DontCare ram.io.writeData := reg.out.src(1)
ram.io.writeMask := DontCare ram.io.writeMask := control.ram.writeMask
ram.io.writeEnable := false.B ram.io.writeEnable := control.ram.writeEnable
ram.io.valid := true.B ram.io.valid := true.B
ram.io.readAddr := alu.out.result
import control.alu.SrcSelect._ import control.alu.SrcASelect._
alu.in.a(aSrcRs2.litValue.toInt) := reg.out.src(1) import control.alu.SrcBSelect._
alu.in.a(aSrcImm.litValue.toInt) := inst(31, 20) alu.in.a(lit(aSrcARs1)) := reg.out.src(0)
alu.in.b := reg.out.src(0) alu.in.a(lit(aSrcAPc)) := pc.out
alu.in.a(lit(aSrcAZero)) := 0.U
alu.in.b(lit(aSrcBRs2)) := reg.out.src(1)
alu.in.b(lit(aSrcBImmI)) := inst(31, 20).pad(aSrcBImmI.getWidth)
alu.in.b(lit(aSrcBImmJ)) := Cat(Fill(12, inst(31)), inst(19, 12), inst(20), inst(30, 25), inst(24, 21), 0.U(1.W))
alu.in.b(lit(aSrcBImmB)) := Cat(Fill(20, inst(31)), inst(7), inst(30, 25), inst(11, 8), inst(0))
alu.in.b(lit(aSrcBImmS)) := Cat(inst(31), inst(19, 12), inst(20), inst(30, 25), inst(24, 21), 0.U(1.W)).pad(aSrcBImmS.getWidth)
Trace.traceName(pc.out); Trace.traceName(pc.out);
dontTouch(control.out) dontTouch(control.out)

View file

@ -34,7 +34,7 @@ object VerilogMain extends App {
} }
val annos = (new ChiselStage).execute( val annos = (new ChiselStage).execute(
Array("--target-dir", opt.targetDir.toString, "--target", "systemverilog", "--split-verilog"), Array("--target-dir", opt.targetDir.toString, "--target", "systemverilog", "--split-verilog", "--full-stacktrace"),
Seq( Seq(
) ++ (if(config.traceConfig.enable) Seq(ChiselGeneratorAnnotation(() => new Flow)) else Seq()) ) ++ (if(config.traceConfig.enable) Seq(ChiselGeneratorAnnotation(() => new Flow)) else Seq())
@ -56,9 +56,9 @@ object VerilogMain extends App {
.foreach( .foreach(
ct => println(s"""TOP.${ct.circuit}.${ct.path.map { case (Instance(i), _) => i }.mkString(".")}.${ct.tokens.collectFirst { ct => println(s"""TOP.${ct.circuit}.${ct.path.map { case (Instance(i), _) => i }.mkString(".")}.${ct.tokens.collectFirst {
case Ref(r) => r case Ref(r) => r
}.get}""") }.get}""")
) )
val verilatorConfigWriter = new PrintWriter(new File(opt.targetDir, opt.verilatorConfigFileOut.toString())) val verilatorConfigWriter = new PrintWriter(new File(opt.targetDir, opt.verilatorConfigFileOut.toString()))
verilatorConfigWriter.write("`verilator_config\n") verilatorConfigWriter.write("`verilator_config\n")
try { try {