feat(npc): implement all riscv32i intructions (untested)
This commit is contained in:
parent
50f7d4d7b9
commit
8500df8a6e
7 changed files with 396 additions and 91 deletions
|
@ -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
|
|
@ -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
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in a new issue