提交 5844fcf0 编写于 作者: L LinJiawei

Initially completed the module interface design

上级 98d97dd3
package xiangshan
import chisel3._
import chisel3.util._
// Fetch FetchWidth x 32-bit insts from Icache
class FetchPacket extends XSBundle {
val instrs = Vec(FetchWidth, UInt(32.W))
val mask = UInt(FetchWidth.W)
val pc = UInt(VAddrBits.W) // the pc of first inst in the fetch group
}
// Dequeue DecodeWidth insts from Ibuffer
class CtrlFlow extends XSBundle {
val instr = UInt(32.W)
val pc = UInt(VAddrBits.W)
val exceptionVec = Vec(16, Bool())
val intrVec = Vec(12, Bool())
}
// Decode DecodeWidth insts at Decode Stage
class CtrlSignals extends XSBundle {
}
class CfCtrl extends XSBundle {
val cf = new CtrlFlow
val ctrl = new CtrlSignals
}
// CfCtrl -> MicroOp at Rename Stage
class MicroOp extends CfCtrl {
val psrc1, psrc2, psrc3, pdst, old_pdst = UInt(PhyRegIdxWidth.W)
val brMask = UInt(BrqSize.W)
val brTag = UInt(BrTagWidth.W)
val roqIdx = UInt(RoqIdxWidth.W)
}
class Redirect extends XSBundle {
val target = UInt(VAddrBits.W)
val brTag = UInt(BrTagWidth.W)
}
class Dp1ToDp2IO extends XSBundle {
val intDqToDp2 = Vec(IntDqDeqWidth, DecoupledIO(new MicroOp))
val fpDqToDp2 = Vec(FpDqDeqWidth, DecoupledIO(new MicroOp))
val lsDqToDp2 = Vec(LsDqDeqWidth, DecoupledIO(new MicroOp))
}
class ExuInput extends XSBundle {
val uop = new MicroOp
val src1, src2, src3 = UInt(XLEN.W)
val isRVF = Bool()
}
class ExuOutput extends XSBundle {
val uop = new MicroOp
val data = UInt(XLEN.W)
}
class ExuIO extends XSBundle {
val in = Flipped(DecoupledIO(new ExuInput))
val out = DecoupledIO(new ExuOutput)
}
class RoqCommit extends XSBundle {
val uop = new MicroOp
}
class FrontendToBackendIO extends XSBundle {
// to backend end
val cfVec = Vec(DecodeWidth, DecoupledIO(new CtrlFlow))
// from backend
val redirect = Flipped(ValidIO(new Redirect))
val commits = Vec(CommitWidth, Flipped(ValidIO(new RoqCommit))) // update branch pred
}
\ No newline at end of file
......@@ -4,9 +4,9 @@ import chisel3._
import chisel3.util._
import bus.simplebus._
import noop.{Cache, CacheConfig, HasExceptionNO, TLB, TLBConfig}
import utils.PipelineConnect
import xiangshan.backend._
import xiangshan.ifu.FakeIFU
import xiangshan.backend.exu.ExuConfig
import xiangshan.frontend.Frontend
trait HasXSParameter {
val XLEN = 64
......@@ -24,13 +24,45 @@ trait HasXSParameter {
val DataBytes = DataBits / 8
val HasFPU = true
val FetchWidth = 8
val IBufSize = 64
val DecodeWidth = 6
val CommitWidth = 6
val BrqSize = 16
val BrTagWidth = log2Up(BrqSize)
val NRPhyRegs = 96
val PhyRegIdxWidth = log2Up(NRPhyRegs)
val NRReadPorts = 14
val NRWritePorts = 8
val RoqSize = 128
val RoqIdxWidth = log2Up(RoqSize)
val IntDqDeqWidth = 4
val FpDqDeqWidth = 4
val LsDqDeqWidth = 4
val exuConfig = ExuConfig(
AluCnt = 4,
BruCnt = 1,
MulCnt = 1,
MduCnt = 1,
FmacCnt = 4,
FmiscCnt = 1,
FmiscDivSqrtCnt = 1,
LsuCnt = 1
)
}
abstract class XSModule extends Module
with HasXSParameter
with HasExceptionNO
//remove this trait after impl module logic
trait NeedImpl { this: Module =>
override protected def IO[T <: Data](iodef: T): T = {
val io = chisel3.experimental.IO(iodef)
io <> DontCare
io
}
}
abstract class XSBundle extends Bundle
with HasXSParameter
......@@ -52,11 +84,10 @@ class XSCore(implicit val p: XSConfig) extends XSModule {
val dmemXbar = Module(new SimpleBusCrossbarNto1(3))
val ifu = Module(new FakeIFU)
val front = Module(new Frontend)
val backend = Module(new Backend)
ifu.io.redirect := backend.io.redirect
PipelineConnect(ifu.io.fetchPacket, backend.io.fetchPacket, true.B, false.B)
front.io.backend <> backend.io.frontend
backend.io.memMMU.imem <> DontCare
......
......@@ -5,24 +5,102 @@ import chisel3._
import chisel3.util._
import chisel3.util.experimental.BoringUtils
import noop.MemMMUIO
import xiangshan.{FetchPacket, Redirect, XSConfig, XSModule}
import xiangshan._
import xiangshan.backend.decode.DecodeStage
import xiangshan.backend.rename.Rename
import xiangshan.backend.brq.Brq
import xiangshan.backend.dispatch.{Dispatch1, Dispatch2}
import xiangshan.backend.exu.{ExeUnits, HasExuHelper, WriteBackArbMtoN}
import xiangshan.backend.issue.IssueStage
import xiangshan.backend.regfile.Regfile
import xiangshan.backend.roq.Roq
class Backend(implicit val p: XSConfig) extends XSModule {
/** Backend Pipeline:
* Decode -> Rename -> Dispatch-1 -> Dispatch-2 -> Issue -> Exe
*/
class Backend(implicit val p: XSConfig) extends XSModule
with HasExuHelper
with NeedImpl
{
val io = IO(new Bundle {
val dmem = new SimpleBusUC(addrBits = VAddrBits)
val memMMU = Flipped(new MemMMUIO)
val fetchPacket = Flipped(DecoupledIO(new FetchPacket)) // from frontend
val redirect = ValidIO(new Redirect)
val frontend = Flipped(new FrontendToBackendIO)
})
io.dmem <> DontCare
io.memMMU <> DontCare
io.redirect.valid := false.B
io.redirect.bits <> DontCare
io.fetchPacket.ready := true.B
val decode = Module(new DecodeStage)
val rename = Module(new Rename)
val dispatch1 = Module(new Dispatch1)
val roq = Module(new Roq)
val brq = Module(new Brq)
val dispatch2 = Module(new Dispatch2)
val intRf = Module(new Regfile(
numReadPorts = NRReadPorts,
numWirtePorts = NRWritePorts,
hasZero = true
))
val fpRf = Module(new Regfile(
numReadPorts = NRReadPorts,
numWirtePorts = NRWritePorts,
hasZero = false
))
val issue = Module(new IssueStage)
val exeUnits = Module(new ExeUnits)
val exeWbReqs = exeUnits.io.wbReqs
val exeWbResults = exeUnits.io.wbResults
val redirect = Mux(roq.io.redirect.valid, roq.io.redirect, brq.io.redirect)
io.frontend.redirect <> redirect
io.frontend.commits <> roq.io.commits
decode.io.in <> io.frontend.cfVec
rename.io.redirect <> redirect
rename.io.roqCommits <> roq.io.commits
rename.io.in <> decode.io.out
dispatch1.io.redirect <> redirect
dispatch1.io.in <> rename.io.out
roq.io.brqRedirect <> brq.io.redirect
roq.io.dp1Req <> dispatch1.io.toRoq
dispatch1.io.roqIdxs <> roq.io.roqIdxs
brq.io.roqRedirect <> roq.io.redirect
brq.io.dp1Req <> dispatch1.io.toBrq
dispatch1.io.brTags <> brq.io.brTags
dispatch1.io.brMasks <> brq.io.brMasks
dispatch2.io.in <> dispatch1.io.out
intRf.io.readPorts <> dispatch2.io.readIntRf
fpRf.io.readPorts <> dispatch2.io.readFpRf
issue.io.redirect <> redirect
issue.io.in <> dispatch2.io.out
issue.io.exeWbResults <> exeWbResults
exeUnits.io.redirect <> redirect
exeUnits.io.roqCommits <> roq.io.commits
exeUnits.io.in <> issue.io.out
roq.io.exeWbResults <> exeWbResults
//TODO: filter fp/int write back req in lsResults
val wbIntReqs = exeWbReqs.getBru +:
(
exeWbReqs.getAluVec ++ exeWbReqs.getMulVec ++ exeWbReqs.getMduVec ++ exeWbReqs.getLsuVec
)
val intWbArb = Module(new WriteBackArbMtoN(wbIntReqs.size, NRWritePorts))
intWbArb.io.in <> wbIntReqs
intRf.io.writePorts <> intWbArb.io.out
val wbFpReqs = exeWbReqs.getFmacVec ++ exeWbReqs.getFmiscVec ++ exeWbReqs.getFmiscDivSqrtVec
val fpWbArb = Module(new WriteBackArbMtoN(wbFpReqs.size, NRWritePorts))
fpWbArb.io.in <> wbFpReqs
fpRf.io.writePorts <> fpWbArb.io.out
......@@ -46,9 +124,9 @@ class Backend(implicit val p: XSConfig) extends XSModule {
// A fake commit
// TODO: difftest 6 insts per cycle
val commit = io.fetchPacket.fire()
val pc = io.fetchPacket.bits.pc
val inst = io.fetchPacket.bits.instrs(0)
val commit = RegNext(RegNext(RegNext(true.B)))
val pc = WireInit("h80000000".U)
val inst = WireInit("h66666666".U)
if(!p.FPGAPlatform){
BoringUtils.addSource(commit, "difftestCommit")
......
package xiangshan.backend.brq
import chisel3._
import chisel3.util._
import xiangshan._
class Brq extends XSModule with NeedImpl {
val io = IO(new Bundle() {
val roqRedirect = Input(Valid(new Redirect))
val dp1Req = Vec(DecodeWidth, Flipped(DecoupledIO(new MicroOp)))
val brTags = Output(Vec(DecodeWidth, UInt(BrTagWidth.W)))
val brMasks = Output(Vec(DecodeWidth, UInt(BrqSize.W)))
val redirect = Output(Valid(new Redirect))
})
}
package xiangshan.backend.decode
import chisel3._
import chisel3.util._
import xiangshan._
class DecodeStage extends XSModule with NeedImpl {
val io = IO(new Bundle() {
val in = Vec(DecodeWidth, Flipped(DecoupledIO(new CtrlFlow)))
val out = Vec(DecodeWidth, DecoupledIO(new CfCtrl))
})
}
\ No newline at end of file
package xiangshan.backend.decode
import chisel3._
import chisel3.util._
import xiangshan._
class Decoder extends XSModule with NeedImpl {
val io = IO(new Bundle() {
val in = Input(new CtrlFlow)
val out = Output(new CfCtrl)
})
}
package xiangshan.backend.dispatch
import chisel3._
import chisel3.util._
import xiangshan._
class Dispatch1 extends XSModule with NeedImpl {
val io = IO(new Bundle() {
val redirect = Flipped(ValidIO(new Redirect))
// from rename
val in = Vec(DecodeWidth, Flipped(DecoupledIO(new MicroOp)))
// enq Roq
val toRoq = Vec(DecodeWidth, DecoupledIO(new MicroOp))
// get RoqIdx
val roqIdxs = Input(Vec(DecodeWidth, UInt(RoqIdxWidth.W)))
// enq Brq
val toBrq = Vec(DecodeWidth, DecoupledIO(new MicroOp))
// get brMask/brTag
val brTags = Input(Vec(DecodeWidth, UInt(BrTagWidth.W)))
val brMasks = Input(Vec(DecodeWidth, UInt(BrqSize.W)))
// to Dp2
val out = new Dp1ToDp2IO
})
}
package xiangshan.backend.dispatch
import chisel3._
import chisel3.util._
import xiangshan._
import xiangshan.backend.regfile.RfReadPort
class Dispatch2 extends XSModule with NeedImpl {
val io = IO(new Bundle() {
// from dispatch1
val in = Flipped(new Dp1ToDp2IO)
// read regfile
val readIntRf = Vec(NRReadPorts, Flipped(new RfReadPort))
val readFpRf = Vec(NRReadPorts, Flipped(new RfReadPort))
// enq Issue Queue
val out = Vec(exuConfig.ExuCnt, DecoupledIO(new ExuInput))
})
}
package xiangshan.backend.exu
import chisel3._
import chisel3.util._
import xiangshan._
import xiangshan.backend.regfile.RfWritePort
case class ExuConfig
(
AluCnt: Int,
BruCnt: Int,
MulCnt: Int,
MduCnt: Int,
FmacCnt: Int,
FmiscCnt: Int,
FmiscDivSqrtCnt: Int,
LsuCnt: Int
){
assert(BruCnt == 1, "Only support 1 Bru now!")
def IntExuCnt = AluCnt + MulCnt + MduCnt + BruCnt
def FpExuCnt = FmacCnt + FmiscCnt + FmiscDivSqrtCnt
def ExuCnt = IntExuCnt + FpExuCnt + LsuCnt
}
abstract class Exu extends Module {
val io = IO(new ExuIO)
}
class Alu extends Exu with NeedImpl
class Bru extends Exu with NeedImpl
class Mul extends Exu with NeedImpl
class Mdu extends Exu with NeedImpl
class Fmac extends Exu with NeedImpl
class Fmisc extends Exu with NeedImpl
class FmiscDivSqrt extends Exu with NeedImpl
class Lsu extends Exu with NeedImpl
class ExeUnits extends XSModule with NeedImpl {
val io = IO(new Bundle() {
val roqCommits = Vec(CommitWidth, Flipped(ValidIO(new RoqCommit)))
val redirect = Flipped(ValidIO(new Redirect))
val in = Vec(exuConfig.ExuCnt, Flipped(DecoupledIO(new ExuInput)))
val wbReqs = Vec(exuConfig.ExuCnt, DecoupledIO(new ExuOutput))
val wbResults = Vec(exuConfig.ExuCnt, ValidIO(new ExuOutput))
})
}
// TODO: refactor exu io logic, this is ugly...
trait HasExuHelper extends HasXSParameter {
implicit class ExuHelper[T <: Data](xs: Vec[T]){
private val bruIdx = 0
private val aluIdx = bruIdx + 1
private val mulIdx = aluIdx + exuConfig.AluCnt
private val mduIdx = mulIdx + exuConfig.MulCnt
private val fmacIdx = mduIdx + exuConfig.MduCnt
private val fmiscIdx = fmacIdx + exuConfig.FmacCnt
private val fmiscDivSqrtIdx = fmiscIdx + exuConfig.FmiscDivSqrtCnt
private val lsuIdx = fmiscDivSqrtIdx + exuConfig.LsuCnt
def getBru: T = {
xs(bruIdx)
}
def getAluVec: Vec[T] = {
VecInit(xs.slice(aluIdx, mulIdx))
}
def getMulVec: Vec[T] = {
VecInit(xs.slice(mulIdx, mduIdx))
}
def getMduVec: Vec[T] = {
VecInit(xs.slice(mduIdx, fmacIdx))
}
def getFmacVec: Vec[T] = {
VecInit(xs.slice(fmacIdx, fmiscIdx))
}
def getFmiscVec: Vec[T] = {
VecInit(xs.slice(fmiscIdx, fmiscDivSqrtIdx))
}
def getFmiscDivSqrtVec: Vec[T] = {
VecInit(xs.slice(fmiscDivSqrtIdx, lsuIdx))
}
def getLsuVec: Vec[T] = {
VecInit(xs.drop(lsuIdx))
}
}
}
class WriteBackArbMtoN(m: Int, n: Int) extends XSModule with NeedImpl {
val io = IO(new Bundle() {
val in = Vec(m, Flipped(DecoupledIO(new ExuOutput)))
val out = Vec(n, Flipped(new RfWritePort))
})
}
package xiangshan.backend.issue
import chisel3._
import chisel3.util._
import xiangshan._
import xiangshan.backend.exu.HasExuHelper
class IssueStage extends XSModule with HasExuHelper with NeedImpl{
val io = IO(new Bundle() {
val redirect = Flipped(ValidIO(new Redirect))
val in = Vec(exuConfig.ExuCnt, Flipped(DecoupledIO(new ExuInput)))
val out = Vec(exuConfig.ExuCnt, DecoupledIO(new ExuInput))
val exeWbResults = Vec(exuConfig.ExuCnt, Flipped(ValidIO(new ExuOutput)))
})
}
package xiangshan.backend.regfile
import chisel3._
import chisel3.util._
import xiangshan._
class RfReadPort extends XSBundle {
val addr = Input(UInt(PhyRegIdxWidth.W))
val data = Output(UInt(XLEN.W))
}
class RfWritePort extends XSBundle {
val wen = Input(Bool())
val addr = Input(UInt(PhyRegIdxWidth.W))
val data = Input(UInt(XLEN.W))
}
class Regfile
(
numReadPorts: Int,
numWirtePorts: Int,
hasZero: Boolean
) extends XSModule with NeedImpl {
val io = IO(new Bundle() {
val readPorts = Vec(numReadPorts, new RfReadPort)
val writePorts = Vec(numWirtePorts, new RfWritePort)
})
}
package xiangshan.backend.rename
import chisel3._
import chisel3.util._
import xiangshan._
class Rename extends XSModule with NeedImpl {
val io = IO(new Bundle() {
val redirect = Flipped(ValidIO(new Redirect))
val roqCommits = Vec(CommitWidth, Flipped(ValidIO(new RoqCommit)))
val in = Vec(DecodeWidth, Flipped(DecoupledIO(new CfCtrl)))
val out = Vec(DecodeWidth, DecoupledIO(new MicroOp))
})
}
package xiangshan.backend.roq
import chisel3._
import chisel3.util._
import xiangshan._
class Roq extends XSModule with NeedImpl {
val io = IO(new Bundle() {
val brqRedirect = Input(Valid(new Redirect))
val dp1Req = Vec(DecodeWidth, Flipped(DecoupledIO(new MicroOp)))
val roqIdxs = Output(Vec(DecodeWidth, UInt(RoqIdxWidth.W)))
val redirect = Output(Valid(new Redirect))
val exeWbResults = Vec(exuConfig.ExuCnt, Flipped(ValidIO(new ExuOutput)))
val commits = Vec(CommitWidth, Valid(new RoqCommit))
})
}
package xiangshan.ifu
package xiangshan.frontend
import chisel3._
import chisel3.util._
......@@ -46,13 +46,11 @@ class FakeCache extends XSModule with HasIFUConst {
}
}
class FakeIFUtoBackendIO extends Bundle {
val fetchPacket = DecoupledIO(new FetchPacket)
val redirect = Flipped(ValidIO(new Redirect))
}
class FakeIFU extends XSModule with HasIFUConst {
val io = IO(new FakeIFUtoBackendIO)
val io = IO(new Bundle() {
val fetchPacket = DecoupledIO(new FetchPacket)
val redirect = Flipped(ValidIO(new Redirect))
})
val pc = RegInit(resetVector.U(VAddrBits.W))
val pcUpdate = io.redirect.valid || io.fetchPacket.fire()
......
package xiangshan.frontend
import chisel3._
import chisel3.util._
import utils.PipelineConnect
import xiangshan._
class Frontend extends XSModule {
val io = IO(new Bundle() {
val backend = new FrontendToBackendIO
})
val fakeIFU = Module(new FakeIFU)
val ibuffer= Module(new Ibuffer)
fakeIFU.io.redirect := io.backend.redirect
ibuffer.io.in <> fakeIFU.io.fetchPacket
ibuffer.io.flush := io.backend.redirect.valid
io.backend.cfVec <> ibuffer.io.out
}
package xiangshan.frontend
import chisel3._
import chisel3.util._
import xiangshan._
import xiangshan.utils._
class Ibuffer extends XSModule with NeedImpl {
val io = IO(new Bundle() {
val flush = Input(Bool())
val in = Flipped(DecoupledIO(new FetchPacket))
val out = Vec(DecodeWidth, DecoupledIO(new CtrlFlow))
})
}
\ No newline at end of file
package xiangshan.utils
import chisel3._
import chisel3.util._
object ParallelOperation {
def apply(xs: Seq[UInt], func: (UInt, UInt) => UInt): UInt = {
xs match {
case Seq(a) => a
case Seq(a, b) => func(a, b)
case _ =>
apply(Seq(apply(xs take xs.size/2, func), apply(xs drop xs.size/2, func)), func)
}
}
}
object ParallelOR {
def apply(xs: Seq[UInt]): UInt = {
ParallelOperation(xs, (a, b) => a | b)
}
}
object ParallelAND {
def apply(xs: Seq[UInt]): UInt = {
ParallelOperation(xs, (a, b) => a & b)
}
}
object ParallelMux {
def apply[T<:Data](in: Seq[(Bool, T)]): T = {
val xs = in map { case (cond, x) => Fill(x.getWidth, cond) & x.asUInt() }
ParallelOR(xs).asInstanceOf[T]
}
}
object ParallelLookUp {
def apply[T<:Data](key: UInt, mapping:Seq[(UInt,T)]): T = {
ParallelMux(mapping.map(m => (m._1===key) -> m._2))
}
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册