提交 0393f8ed 编写于 作者: B BigWhiteDog

Merge branch 'master' into L1DTest

......@@ -3,20 +3,34 @@ name: EMU Test
on:
push:
branches: [ master, update-ci]
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build-emu:
generate-verilog:
runs-on: self-hosted
name: Make EMU
name: Generate Verilog
steps:
- uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: Check Wiring
run: bash .github/workflows/check-usage.sh "BoringUtils" $GITHUB_WORKSPACE
- name: set env
run: |
echo "NEMU_HOME=/home/ci-runner/xsenv/NEMU" >> $GITHUB_ENV
echo "NOOP_HOME=$GITHUB_WORKSPACE" >> $GITHUB_ENV
- name: generate verilog file
run:
make verilog SIM_ARGS=--dual-core
build-emu:
runs-on: self-hosted
name: Make EMU
steps:
- uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: Set env
run: |
echo "NEMU_HOME=/home/ci-runner/xsenv/NEMU" >> $GITHUB_ENV
......@@ -25,7 +39,7 @@ jobs:
echo "AM_HOME=/home/ci-runner/xsenv/nexus-am" >> $GITHUB_ENV
- name: Build EMU
run:
make ./build/emu SIM_ARGS=--disable-all NEMU_HOME=$NEMU_HOME NOOP_HOME=$NOOP_HOME -j60
make ./build/emu SIM_ARGS=--disable-all NEMU_HOME=$NEMU_HOME NOOP_HOME=$NOOP_HOME -j220
- name: Run cputest
run: |
CPU_TEST_DIR=$AM_HOME/tests/cputest
......
......@@ -29,7 +29,7 @@ trait CommonModule extends ScalaModule {
}
val chisel = Agg(
ivy"edu.berkeley.cs::chisel3:3.4.0"
ivy"edu.berkeley.cs::chisel3:3.4.1"
)
object `api-config-chipsalliance` extends CommonModule {
......@@ -103,4 +103,4 @@ object XiangShan extends CommonModule with SbtModule {
}
}
}
\ No newline at end of file
}
......@@ -3,7 +3,7 @@ package utils
import chisel3._
import chisel3.util._
class AsyncDataModuleTemplate[T <: Data](gen: T, numEntries: Int, numRead: Int, numWrite: Int) extends Module {
class DataModuleTemplate[T <: Data](gen: T, numEntries: Int, numRead: Int, numWrite: Int, isSync: Boolean) extends Module {
val io = IO(new Bundle {
val raddr = Vec(numRead, Input(UInt(log2Up(numEntries).W)))
val rdata = Vec(numRead, Output(gen))
......@@ -15,8 +15,9 @@ class AsyncDataModuleTemplate[T <: Data](gen: T, numEntries: Int, numRead: Int,
val data = Mem(numEntries, gen)
// read ports
val raddr = if (isSync) (RegNext(io.raddr)) else io.raddr
for (i <- 0 until numRead) {
io.rdata(i) := data(io.raddr(i))
io.rdata(i) := data(raddr(i))
}
// below is the write ports (with priorities)
......@@ -34,34 +35,5 @@ class AsyncDataModuleTemplate[T <: Data](gen: T, numEntries: Int, numRead: Int,
}
}
class SyncDataModuleTemplate[T <: Data](gen: T, numEntries: Int, numRead: Int, numWrite: Int) extends Module {
val io = IO(new Bundle {
val raddr = Vec(numRead, Input(UInt(log2Up(numEntries).W)))
val rdata = Vec(numRead, Output(gen))
val wen = Vec(numWrite, Input(Bool()))
val waddr = Vec(numWrite, Input(UInt(log2Up(numEntries).W)))
val wdata = Vec(numWrite, Input(gen))
})
val data = Mem(numEntries, gen)
// read ports
val raddr_reg = RegNext(io.raddr)
for (i <- 0 until numRead) {
io.rdata(i) := data(raddr_reg(i))
}
// below is the write ports (with priorities)
for (i <- 0 until numWrite) {
when (io.wen(i)) {
data(io.waddr(i)) := io.wdata(i)
}
}
// DataModuleTemplate should not be used when there're any write conflicts
for (i <- 0 until numWrite) {
for (j <- i+1 until numWrite) {
assert(!(io.wen(i) && io.wen(j) && io.waddr(i) === io.waddr(j)))
}
}
}
class SyncDataModuleTemplate[T <: Data](gen: T, numEntries: Int, numRead: Int, numWrite: Int) extends DataModuleTemplate(gen, numEntries, numRead, numWrite, true)
class AsyncDataModuleTemplate[T <: Data](gen: T, numEntries: Int, numRead: Int, numWrite: Int) extends DataModuleTemplate(gen, numEntries, numRead, numWrite, false)
......@@ -6,7 +6,7 @@ import xiangshan.backend.SelImm
import xiangshan.backend.brq.BrqPtr
import xiangshan.backend.rename.FreeListPtr
import xiangshan.backend.roq.RoqPtr
import xiangshan.backend.decode.XDecode
import xiangshan.backend.decode.{ImmUnion, XDecode}
import xiangshan.mem.{LqPtr, SqPtr}
import xiangshan.frontend.PreDecodeInfo
import xiangshan.frontend.HasBPUParameter
......@@ -14,6 +14,7 @@ import xiangshan.frontend.HasTageParameter
import xiangshan.frontend.HasIFUConst
import xiangshan.frontend.GlobalHistory
import utils._
import scala.math.max
import Chisel.experimental.chiselName
......@@ -219,7 +220,7 @@ class CtrlSignals extends XSBundle {
val flushPipe = Bool() // This inst will flush all the pipe when commit, like exception but can commit
val isRVF = Bool()
val selImm = SelImm()
val imm = UInt(XLEN.W)
val imm = UInt(ImmUnion.maxLen.W)
val commitType = CommitType()
val fpu = new FPUCtrlSignals
......@@ -283,6 +284,7 @@ class ReplayPregReq extends XSBundle {
class DebugBundle extends XSBundle{
val isMMIO = Bool()
val isPerfCnt = Bool()
}
class ExuInput extends XSBundle {
......
......@@ -425,6 +425,7 @@ class XSCoreImp(outer: XSCore) extends LazyModuleImp(outer)
integerBlock.io.csrio.memExceptionVAddr <> memBlock.io.lsqio.exceptionAddr.vaddr
integerBlock.io.csrio.externalInterrupt <> io.externalInterrupt
integerBlock.io.csrio.tlb <> memBlock.io.tlbCsr
integerBlock.io.csrio.perfinfo <> ctrlBlock.io.roqio.toCSR.perfinfo
integerBlock.io.fenceio.sfence <> memBlock.io.sfence
integerBlock.io.fenceio.sbuffer <> memBlock.io.fenceToSbuffer
......
......@@ -5,18 +5,19 @@ import chisel3.util._
import utils._
import xiangshan._
import xiangshan.backend.decode.DecodeStage
import xiangshan.backend.rename.{Rename, BusyTable}
import xiangshan.backend.brq.Brq
import xiangshan.backend.rename.{BusyTable, Rename}
import xiangshan.backend.brq.{Brq, BrqPcRead}
import xiangshan.backend.dispatch.Dispatch
import xiangshan.backend.exu._
import xiangshan.backend.exu.Exu.exuConfigs
import xiangshan.backend.regfile.RfReadPort
import xiangshan.backend.roq.{Roq, RoqPtr, RoqCSRIO}
import xiangshan.backend.roq.{Roq, RoqCSRIO, RoqPtr}
import xiangshan.mem.LsqEnqIO
class CtrlToIntBlockIO extends XSBundle {
val enqIqCtrl = Vec(exuParameters.IntExuCnt, DecoupledIO(new MicroOp))
val readRf = Vec(NRIntReadPorts, Flipped(new RfReadPort(XLEN)))
val jumpPc = Output(UInt(VAddrBits.W))
// int block only uses port 0~7
val readPortIndex = Vec(exuParameters.IntExuCnt, Output(UInt(log2Ceil(8 / 2).W))) // TODO parameterize 8 here
val redirect = ValidIO(new Redirect)
......@@ -87,6 +88,8 @@ class CtrlBlock extends XSModule with HasCircularQueuePtrHelper {
brq.io.redirect.bits <> redirect
brq.io.bcommit <> roq.io.bcommit
brq.io.exuRedirectWb <> io.fromIntBlock.exuRedirect
brq.io.pcReadReq.brqIdx := dispatch.io.enqIQCtrl(0).bits.brTag // jump
io.toIntBlock.jumpPc := brq.io.pcReadReq.pc
// pipeline between decode and dispatch
val lastCycleRedirect = RegNext(redirectValid)
......
......@@ -156,8 +156,9 @@ class FloatBlock
(0 until exuParameters.StuCnt).foreach(i => io.toMemBlock.readFpRf(i).data := fpRf.io.readPorts(i + 12).data)
// write fp rf arbiter
val fpWbArbiter = Module(new Wb(
(exeUnits.map(_.config) ++ fastWakeUpIn ++ slowWakeUpIn).map(_.wbFpPriority),
NRFpWritePorts
(exeUnits.map(_.config) ++ fastWakeUpIn ++ slowWakeUpIn),
NRFpWritePorts,
isFp = true
))
fpWbArbiter.io.in <> exeUnits.map(_.io.toFp) ++ io.wakeUpIn.fast ++ io.wakeUpIn.slow
......
......@@ -82,6 +82,9 @@ class IntegerBlock
val memExceptionVAddr = Input(UInt(VAddrBits.W)) // from lsq
val externalInterrupt = new ExternalInterruptIO // from outside
val tlb = Output(new TlbCsrBundle) // from tlb
val perfinfo = new Bundle {
val retiredInstr = Input(UInt(3.W))
}
}
val fenceio = new Bundle {
val sfence = Output(new SfenceBundle) // to front,mem
......@@ -99,11 +102,11 @@ class IntegerBlock
len = XLEN
))
val aluExeUnits = Array.tabulate(exuParameters.AluCnt)(_ => Module(new AluExeUnit))
val jmpExeUnit = Module(new JumpExeUnit)
val mduExeUnits = Array.tabulate(exuParameters.MduCnt)(_ => Module(new MulDivExeUnit))
val aluExeUnits = Array.tabulate(exuParameters.AluCnt)(_ => Module(new AluExeUnit))
val exeUnits = jmpExeUnit +: (aluExeUnits ++ mduExeUnits)
val exeUnits = jmpExeUnit +: (mduExeUnits ++ aluExeUnits)
def needWakeup(cfg: ExuConfig): Boolean =
(cfg.readIntRf && cfg.writeIntRf) || (cfg.readFpRf && cfg.writeFpRf)
......@@ -148,6 +151,7 @@ class IntegerBlock
val src2Value = VecInit((0 until 4).map(i => intRf.io.readPorts(i * 2 + 1).data))
rsData.io.srcRegValue(0) := src1Value(readPortIndex(i))
if (cfg.intSrcCnt > 1) rsData.io.srcRegValue(1) := src2Value(readPortIndex(i))
if (cfg == Exu.jumpExeUnitCfg) rsData.io.jumpPc := io.fromCtrlBlock.jumpPc
rsData.io.redirect <> redirect
rsData.io.writeBackedData <> writeBackData
......@@ -218,8 +222,9 @@ class IntegerBlock
(0 until NRMemReadPorts).foreach(i => io.toMemBlock.readIntRf(i).data := intRf.io.readPorts(i + 8).data)
// write int rf arbiter
val intWbArbiter = Module(new Wb(
(exeUnits.map(_.config) ++ fastWakeUpIn ++ slowWakeUpIn).map(_.wbIntPriority),
NRIntWritePorts
(exeUnits.map(_.config) ++ fastWakeUpIn ++ slowWakeUpIn),
NRIntWritePorts,
isFp = false
))
intWbArbiter.io.in <> exeUnits.map(_.io.toInt) ++ io.wakeUpIn.fast ++ io.wakeUpIn.slow
......
......@@ -5,6 +5,7 @@ import chisel3.util._
import xiangshan._
import utils._
import chisel3.ExcitingUtils._
import xiangshan.backend.decode.ImmUnion
class BrqPtr extends CircularQueuePtr(BrqPtr.BrqSize) with HasCircularQueuePtrHelper {
......@@ -44,6 +45,11 @@ class BrqEnqIO extends XSBundle {
val resp = Vec(RenameWidth, Output(new BrqPtr))
}
class BrqPcRead extends XSBundle {
val brqIdx = Input(new BrqPtr)
val pc = Output(UInt(VAddrBits.W))
}
class BrqIO extends XSBundle{
val redirect = Input(ValidIO(new Redirect))
// receive branch/jump calculated target
......@@ -57,6 +63,8 @@ class BrqIO extends XSBundle{
val cfiInfo = ValidIO(new CfiUpdateInfo)
// commit cnt of branch instr
val bcommit = Input(UInt(BrTagWidth.W))
// read pc for jump unit
val pcReadReq = new BrqPcRead
}
class Brq extends XSModule with HasCircularQueuePtrHelper {
......@@ -69,8 +77,14 @@ class Brq extends XSModule with HasCircularQueuePtrHelper {
val s_idle :: s_wb :: Nil = Enum(2)
class DecodeEnqBrqData extends Bundle {
val cfiUpdateInfo = new CfiUpdateInfo
// we use this to calculate branch target
val imm12 = UInt(12.W)
}
// data and state
val decodeData = Module(new SyncDataModuleTemplate(new ExuOutput, BrqSize, 2, DecodeWidth))
val decodeData = Module(new SyncDataModuleTemplate(new DecodeEnqBrqData, BrqSize, 3, DecodeWidth))
val writebackData = Module(new SyncDataModuleTemplate(new ExuOutput, BrqSize, 2, exuParameters.AluCnt + exuParameters.JmpCnt))
val ptrFlagVec = Reg(Vec(BrqSize, Bool()))
val stateQueue = RegInit(VecInit(Seq.fill(BrqSize)(s_idle)))
......@@ -109,9 +123,14 @@ class Brq extends XSModule with HasCircularQueuePtrHelper {
}
val brUpdateReadIdx = Mux(io.redirect.bits.flushItself(), io.redirect.bits.brTag - 1.U, io.redirect.bits.brTag)
val brUpdateReadEntry = Wire(new ExuOutput)
val brUpdateReadEntry = Wire(new CfiUpdateInfo)
io.cfiInfo.valid := RegNext(io.redirect.valid || wbValid)
io.cfiInfo.bits := brUpdateReadEntry.brUpdate
io.cfiInfo.bits := brUpdateReadEntry
io.cfiInfo.bits.target := RegNext(Mux(io.redirect.bits.flushItself(),
io.redirect.bits.target,
wbEntry.brUpdate.target
))
io.cfiInfo.bits.brTarget := io.cfiInfo.bits.target
io.cfiInfo.bits.brTag := RegNext(brUpdateReadIdx)
io.cfiInfo.bits.isReplay := RegNext(io.redirect.bits.flushItself())
io.cfiInfo.bits.isMisPred := RegNext(wbIsMisPred)
......@@ -183,31 +202,48 @@ class Brq extends XSModule with HasCircularQueuePtrHelper {
}
}
def mergeDecodeWbData(dec: ExuOutput, wb: ExuOutput) : ExuOutput = {
def mergeWbEntry(dec: DecodeEnqBrqData, wb: ExuOutput) : ExuOutput = {
val mergeData = Wire(new ExuOutput)
mergeData := dec
// only writeback necessary information
mergeData.uop := wb.uop
mergeData.data := wb.data
mergeData.fflags := wb.fflags
mergeData.redirectValid := wb.redirectValid
// calculate target pc
val pc = dec.cfiUpdateInfo.pc
val offset = SignExt(ImmUnion.B.toImm32(dec.imm12), VAddrBits)
val snpc = pc + Mux(dec.cfiUpdateInfo.pd.isRVC, 2.U, 4.U)
val bnpc = pc + offset
val branch_pc = Mux(wb.brUpdate.taken, bnpc, snpc)
val redirectTarget = Mux(dec.cfiUpdateInfo.pd.isBr, branch_pc, wb.redirect.target)
mergeData.redirect := wb.redirect
mergeData.redirect.target := redirectTarget
mergeData.debug := wb.debug
mergeData.brUpdate.target := wb.brUpdate.target
mergeData.brUpdate.brTarget := wb.brUpdate.brTarget
mergeData.brUpdate := dec.cfiUpdateInfo
mergeData.brUpdate.target := redirectTarget
mergeData.brUpdate.brTarget := redirectTarget
mergeData.brUpdate.taken := wb.brUpdate.taken
mergeData
}
def mergeBrUpdateEntry(dec: DecodeEnqBrqData, wb: ExuOutput): CfiUpdateInfo = {
val mergeData = WireInit(dec.cfiUpdateInfo)
mergeData.taken := wb.brUpdate.taken
mergeData
}
decodeData.io.raddr(0) := writebackPtr_next.value
decodeData.io.raddr(1) := brUpdateReadIdx.value
decodeData.io.raddr(2) := io.pcReadReq.brqIdx.value
decodeData.io.wen := VecInit(io.enq.req.map(_.fire()))
decodeData.io.waddr := VecInit(enqBrTag.map(_.value))
decodeData.io.wdata.zip(io.enq.req).map{ case (wdata, req) => {
wdata := DontCare
wdata.brUpdate := req.bits.brUpdate
wdata.brUpdate.pc := req.bits.pc
}}
decodeData.io.wdata.zip(io.enq.req).foreach{ case (wdata, req) =>
wdata.cfiUpdateInfo := req.bits.brUpdate
wdata.cfiUpdateInfo.pc := req.bits.pc
wdata.imm12 := ImmUnion.B.minBitsFromInstr(req.bits.instr)
}
writebackData.io.raddr(0) := writebackPtr_next.value
writebackData.io.raddr(1) := brUpdateReadIdx.value
......@@ -215,9 +251,10 @@ class Brq extends XSModule with HasCircularQueuePtrHelper {
writebackData.io.waddr := VecInit(io.exuRedirectWb.map(_.bits.redirect.brTag.value))
writebackData.io.wdata := VecInit(io.exuRedirectWb.map(_.bits))
wbEntry := mergeDecodeWbData(decodeData.io.rdata(0), writebackData.io.rdata(0))
brUpdateReadEntry := mergeDecodeWbData(decodeData.io.rdata(1), writebackData.io.rdata(1))
wbEntry := mergeWbEntry(decodeData.io.rdata(0), writebackData.io.rdata(0))
brUpdateReadEntry := mergeBrUpdateEntry(decodeData.io.rdata(1), writebackData.io.rdata(1))
io.pcReadReq.pc := decodeData.io.rdata(2).cfiUpdateInfo.pc
// Debug info
val debug_roq_redirect = io.redirect.valid && io.redirect.bits.isUnconditional()
......@@ -269,16 +306,16 @@ class Brq extends XSModule with HasCircularQueuePtrHelper {
val mbpRWrong = predWrong && isRType
if(!env.FPGAPlatform){
ExcitingUtils.addSource(mbpInstr, "perfCntCondMbpInstr", Perf)
ExcitingUtils.addSource(mbpRight, "perfCntCondMbpRight", Perf)
ExcitingUtils.addSource(mbpWrong, "perfCntCondMbpWrong", Perf)
ExcitingUtils.addSource(mbpBRight, "perfCntCondMbpBRight", Perf)
ExcitingUtils.addSource(mbpBWrong, "perfCntCondMbpBWrong", Perf)
ExcitingUtils.addSource(mbpJRight, "perfCntCondMbpJRight", Perf)
ExcitingUtils.addSource(mbpJWrong, "perfCntCondMbpJWrong", Perf)
ExcitingUtils.addSource(mbpIRight, "perfCntCondMbpIRight", Perf)
ExcitingUtils.addSource(mbpIWrong, "perfCntCondMbpIWrong", Perf)
ExcitingUtils.addSource(mbpRRight, "perfCntCondMbpRRight", Perf)
ExcitingUtils.addSource(mbpRWrong, "perfCntCondMbpRWrong", Perf)
ExcitingUtils.addSource(mbpInstr, "perfCntCondBpInstr", Perf)
ExcitingUtils.addSource(mbpRight, "perfCntCondBpRight", Perf)
ExcitingUtils.addSource(mbpWrong, "perfCntCondBpWrong", Perf)
ExcitingUtils.addSource(mbpBRight, "perfCntCondBpBRight", Perf)
ExcitingUtils.addSource(mbpBWrong, "perfCntCondBpBWrong", Perf)
ExcitingUtils.addSource(mbpJRight, "perfCntCondBpJRight", Perf)
ExcitingUtils.addSource(mbpJWrong, "perfCntCondBpJWrong", Perf)
ExcitingUtils.addSource(mbpIRight, "perfCntCondBpIRight", Perf)
ExcitingUtils.addSource(mbpIWrong, "perfCntCondBpIWrong", Perf)
ExcitingUtils.addSource(mbpRRight, "perfCntCondBpRRight", Perf)
ExcitingUtils.addSource(mbpRWrong, "perfCntCondBpRWrong", Perf)
}
}
......@@ -150,9 +150,9 @@ object XDecode extends DecodeConstants {
CSRRS -> List(SrcType.reg, SrcType.imm, SrcType.DC, FuType.csr, CSROpType.set, Y, N, N, Y, Y, N, N, SelImm.IMM_I),
CSRRC -> List(SrcType.reg, SrcType.imm, SrcType.DC, FuType.csr, CSROpType.clr, Y, N, N, Y, Y, N, N, SelImm.IMM_I),
CSRRWI -> List(SrcType.reg, SrcType.imm, SrcType.DC, FuType.csr, CSROpType.wrti, Y, N, N, Y, Y, N, N, SelImm.IMM_I),
CSRRSI -> List(SrcType.reg, SrcType.imm, SrcType.DC, FuType.csr, CSROpType.seti, Y, N, N, Y, Y, N, N, SelImm.IMM_I),
CSRRCI -> List(SrcType.reg, SrcType.imm, SrcType.DC, FuType.csr, CSROpType.clri, Y, N, N, Y, Y, N, N, SelImm.IMM_I),
CSRRWI -> List(SrcType.reg, SrcType.imm, SrcType.DC, FuType.csr, CSROpType.wrti, Y, N, N, Y, Y, N, N, SelImm.IMM_Z),
CSRRSI -> List(SrcType.reg, SrcType.imm, SrcType.DC, FuType.csr, CSROpType.seti, Y, N, N, Y, Y, N, N, SelImm.IMM_Z),
CSRRCI -> List(SrcType.reg, SrcType.imm, SrcType.DC, FuType.csr, CSROpType.clri, Y, N, N, Y, Y, N, N, SelImm.IMM_Z),
SFENCE_VMA->List(SrcType.reg, SrcType.imm, SrcType.DC, FuType.fence, FenceOpType.sfence, N, N, N, Y, Y, Y, N, SelImm.IMM_X),
ECALL -> List(SrcType.reg, SrcType.imm, SrcType.DC, FuType.csr, CSROpType.jmp, Y, N, N, Y, Y, N, N, SelImm.IMM_X),
......@@ -316,26 +316,98 @@ class RVCExpander extends XSModule {
}
}
object Imm32Gen {
def apply(sel: UInt, inst: UInt) = {
val sign = Mux(sel === SelImm.IMM_Z, 0.S, inst(31).asSInt)
val b30_20 = Mux(sel === SelImm.IMM_U, inst(30,20).asSInt, sign)
val b19_12 = Mux(sel =/= SelImm.IMM_U && sel =/= SelImm.IMM_UJ, sign, inst(19,12).asSInt)
val b11 = Mux(sel === SelImm.IMM_U || sel === SelImm.IMM_Z, 0.S,
Mux(sel === SelImm.IMM_UJ, inst(20).asSInt,
Mux(sel === SelImm.IMM_SB, inst(7).asSInt, sign)))
val b10_5 = Mux(sel === SelImm.IMM_U || sel === SelImm.IMM_Z, 0.U(1.W), inst(30,25))
val b4_1 = Mux(sel === SelImm.IMM_U, 0.U(1.W),
Mux(sel === SelImm.IMM_S || sel === SelImm.IMM_SB, inst(11,8),
Mux(sel === SelImm.IMM_Z, inst(19,16), inst(24,21))))
val b0 = Mux(sel === SelImm.IMM_S, inst(7),
Mux(sel === SelImm.IMM_I, inst(20),
Mux(sel === SelImm.IMM_Z, inst(15), 0.U(1.W))))
Cat(sign, b30_20, b19_12, b11, b10_5, b4_1, b0)
//object Imm32Gen {
// def apply(sel: UInt, inst: UInt) = {
// val sign = Mux(sel === SelImm.IMM_Z, 0.S, inst(31).asSInt)
// val b30_20 = Mux(sel === SelImm.IMM_U, inst(30,20).asSInt, sign)
// val b19_12 = Mux(sel =/= SelImm.IMM_U && sel =/= SelImm.IMM_UJ, sign, inst(19,12).asSInt)
// val b11 = Mux(sel === SelImm.IMM_U || sel === SelImm.IMM_Z, 0.S,
// Mux(sel === SelImm.IMM_UJ, inst(20).asSInt,
// Mux(sel === SelImm.IMM_SB, inst(7).asSInt, sign)))
// val b10_5 = Mux(sel === SelImm.IMM_U || sel === SelImm.IMM_Z, 0.U(1.W), inst(30,25))
// val b4_1 = Mux(sel === SelImm.IMM_U, 0.U(1.W),
// Mux(sel === SelImm.IMM_S || sel === SelImm.IMM_SB, inst(11,8),
// Mux(sel === SelImm.IMM_Z, inst(19,16), inst(24,21))))
// val b0 = Mux(sel === SelImm.IMM_S, inst(7),
// Mux(sel === SelImm.IMM_I, inst(20),
// Mux(sel === SelImm.IMM_Z, inst(15), 0.U(1.W))))
//
// Cat(sign, b30_20, b19_12, b11, b10_5, b4_1, b0)
// }
//}
abstract class Imm(val len: Int) extends Bundle {
def toImm32(minBits: UInt): UInt = do_toImm32(minBits(len - 1, 0))
def do_toImm32(minBits: UInt): UInt
def minBitsFromInstr(instr: UInt): UInt
}
case class Imm_I() extends Imm(12) {
override def do_toImm32(minBits: UInt): UInt = SignExt(minBits, 32)
override def minBitsFromInstr(instr: UInt): UInt =
Cat(instr(31, 20))
}
case class Imm_S() extends Imm(12) {
override def do_toImm32(minBits: UInt): UInt = SignExt(minBits, 32)
override def minBitsFromInstr(instr: UInt): UInt =
Cat(instr(31, 25), instr(11, 7))
}
case class Imm_B() extends Imm(12) {
override def do_toImm32(minBits: UInt): UInt = SignExt(Cat(minBits, 0.U(1.W)), 32)
override def minBitsFromInstr(instr: UInt): UInt =
Cat(instr(31), instr(7), instr(30, 25), instr(11, 8))
}
case class Imm_U() extends Imm(20){
override def do_toImm32(minBits: UInt): UInt = Cat(minBits, 0.U(12.W))
override def minBitsFromInstr(instr: UInt): UInt = {
instr(31, 12)
}
}
case class Imm_J() extends Imm(20){
override def do_toImm32(minBits: UInt): UInt = SignExt(Cat(minBits, 0.U(1.W)), 32)
override def minBitsFromInstr(instr: UInt): UInt = {
Cat(instr(31), instr(19, 12), instr(20), instr(30, 25), instr(24, 21))
}
}
case class Imm_Z() extends Imm(12 + 5){
override def do_toImm32(minBits: UInt): UInt = minBits
override def minBitsFromInstr(instr: UInt): UInt = {
Cat(instr(19, 15), instr(31, 20))
}
}
object ImmUnion {
val I = Imm_I()
val S = Imm_S()
val B = Imm_B()
val U = Imm_U()
val J = Imm_J()
val Z = Imm_Z()
val imms = Seq(I, S, B, U, J, Z)
val maxLen = imms.maxBy(_.len).len
val immSelMap = Seq(
SelImm.IMM_I,
SelImm.IMM_S,
SelImm.IMM_SB,
SelImm.IMM_U,
SelImm.IMM_UJ,
SelImm.IMM_Z
).zip(imms)
println(s"ImmUnion max len: $maxLen")
}
/**
* IO bundle for the Decode unit
*/
......@@ -403,19 +475,27 @@ class DecodeUnit extends XSModule with DecodeUnitConstants {
cs.lsrc1 := XSTrapDecode.lsrc1
}
cs.imm := SignExt(Imm32Gen(cs.selImm, ctrl_flow.instr), XLEN)
val instr = io.enq.ctrl_flow.instr
cs.imm := LookupTree(cs.selImm, ImmUnion.immSelMap.map(
x => {
val minBits = x._2.minBitsFromInstr(instr)
require(minBits.getWidth == x._2.len)
x._1 -> minBits
}
))
cf_ctrl.ctrl := cs
// TODO: do we still need this?
// fix ret and call
when (cs.fuType === FuType.jmp) {
def isLink(reg: UInt) = (reg === 1.U || reg === 5.U)
when (isLink(cs.ldest) && cs.fuOpType === JumpOpType.jal) { cf_ctrl.ctrl.fuOpType := JumpOpType.call }
when (cs.fuOpType === JumpOpType.jalr) {
when (isLink(cs.lsrc1)) { cf_ctrl.ctrl.fuOpType := JumpOpType.ret }
when (isLink(cs.ldest)) { cf_ctrl.ctrl.fuOpType := JumpOpType.call }
}
}
// when (cs.fuType === FuType.jmp) {
// def isLink(reg: UInt) = (reg === 1.U || reg === 5.U)
// when (isLink(cs.ldest) && cs.fuOpType === JumpOpType.jal) { cf_ctrl.ctrl.fuOpType := JumpOpType.call }
// when (cs.fuOpType === JumpOpType.jalr) {
// when (isLink(cs.lsrc1)) { cf_ctrl.ctrl.fuOpType := JumpOpType.ret }
// when (isLink(cs.ldest)) { cf_ctrl.ctrl.fuOpType := JumpOpType.call }
// }
// }
io.deq.cf_ctrl := cf_ctrl
......
......@@ -17,37 +17,40 @@ class Dispatch2Int extends XSModule {
val readPortIndex = Vec(exuParameters.IntExuCnt, Output(UInt(log2Ceil(8 / 2).W)))
})
val jmpCnt = exuParameters.JmpCnt
val mduCnt = exuParameters.MduCnt
val aluCnt = exuParameters.AluCnt
/**
* Part 1: generate indexes for reservation stations
*/
assert(jmpCnt == 1)
val jmpCanAccept = VecInit(io.fromDq.map(deq => deq.valid && jumpExeUnitCfg.canAccept(deq.bits.ctrl.fuType)))
val aluCanAccept = VecInit(io.fromDq.map(deq => deq.valid && aluExeUnitCfg.canAccept(deq.bits.ctrl.fuType)))
val mduCanAccept = VecInit(io.fromDq.map(deq => deq.valid && mulDivExeUnitCfg.canAccept(deq.bits.ctrl.fuType)))
assert(exuParameters.JmpCnt == 1)
val jmpIndexGen = Module(new IndexMapping(dpParams.IntDqDeqWidth, exuParameters.JmpCnt, false))
val aluIndexGen = Module(new IndexMapping(dpParams.IntDqDeqWidth, exuParameters.AluCnt, true))
val mduIndexGen = Module(new IndexMapping(dpParams.IntDqDeqWidth, exuParameters.MduCnt, true))
val aluPriority = PriorityGen((0 until exuParameters.AluCnt).map(i => io.numExist(i+exuParameters.JmpCnt)))
val mduPriority = PriorityGen((0 until exuParameters.MduCnt).map(i => io.numExist(i+exuParameters.JmpCnt+exuParameters.AluCnt)))
val aluCanAccept = VecInit(io.fromDq.map(deq => deq.valid && aluExeUnitCfg.canAccept(deq.bits.ctrl.fuType)))
val jmpIndexGen = Module(new IndexMapping(dpParams.IntDqDeqWidth, jmpCnt, false))
val mduIndexGen = Module(new IndexMapping(dpParams.IntDqDeqWidth, mduCnt, true))
val aluIndexGen = Module(new IndexMapping(dpParams.IntDqDeqWidth, aluCnt, true))
val mduPriority = PriorityGen(io.numExist.slice(jmpCnt, jmpCnt + mduCnt))
val aluPriority = PriorityGen(io.numExist.drop(jmpCnt + mduCnt))
jmpIndexGen.io.validBits := jmpCanAccept
aluIndexGen.io.validBits := aluCanAccept
mduIndexGen.io.validBits := mduCanAccept
aluIndexGen.io.validBits := aluCanAccept
jmpIndexGen.io.priority := DontCare
aluIndexGen.io.priority := aluPriority
mduIndexGen.io.priority := mduPriority
aluIndexGen.io.priority := aluPriority
val allIndexGen = Seq(jmpIndexGen, aluIndexGen, mduIndexGen)
val validVec = allIndexGen.map(_.io.mapping.map(_.valid)).reduceLeft(_ ++ _)
val indexVec = allIndexGen.map(_.io.mapping.map(_.bits)).reduceLeft(_ ++ _)
for (i <- validVec.indices) {
// XSDebug(p"mapping $i: valid ${validVec(i)} index ${indexVec(i)}\n")
}
val allIndexGen = Seq(jmpIndexGen, mduIndexGen, aluIndexGen)
val validVec = allIndexGen.flatMap(_.io.mapping.map(_.valid))
val indexVec = allIndexGen.flatMap(_.io.mapping.map(_.bits))
/**
* Part 2: assign regfile read ports
*/
val intStaticIndex = Seq(1, 2, 3, 4)
val intDynamicIndex = Seq(0, 5, 6)
val intStaticIndex = Seq(3, 4, 5, 6)
val intDynamicIndex = Seq(0, 1, 2)
val intStaticMappedValid = intStaticIndex.map(i => validVec(i))
val intDynamicMappedValid = intDynamicIndex.map(i => validVec(i))
val (intReadPortSrc, intDynamicExuSrc) = RegfileReadPortGen(intStaticMappedValid, intDynamicMappedValid)
......@@ -66,18 +69,18 @@ class Dispatch2Int extends XSModule {
* Part 3: dispatch to reservation stations
*/
val jmpReady = io.enqIQCtrl(0).ready
val aluReady = Cat(io.enqIQCtrl.take(exuParameters.JmpCnt + exuParameters.AluCnt).drop(exuParameters.JmpCnt).map(_.ready)).andR
val mduReady = Cat(io.enqIQCtrl.drop(exuParameters.JmpCnt + exuParameters.AluCnt).map(_.ready)).andR
val mduReady = Cat(io.enqIQCtrl.slice(jmpCnt, jmpCnt + mduCnt).map(_.ready)).andR
val aluReady = Cat(io.enqIQCtrl.drop(jmpCnt + mduCnt).map(_.ready)).andR
for (i <- 0 until exuParameters.IntExuCnt) {
val enq = io.enqIQCtrl(i)
if (i < exuParameters.JmpCnt) {
if (i < jmpCnt) {
enq.valid := jmpIndexGen.io.mapping(i).valid// && jmpReady
}
else if (i < exuParameters.JmpCnt + exuParameters.AluCnt) {
enq.valid := aluIndexGen.io.mapping(i - exuParameters.JmpCnt).valid && aluReady
else if (i < jmpCnt + mduCnt) {
enq.valid := mduIndexGen.io.mapping(i - jmpCnt).valid && mduReady
}
else {
enq.valid := mduIndexGen.io.mapping(i - (exuParameters.JmpCnt + exuParameters.AluCnt)).valid && mduReady
else { // alu
enq.valid := aluIndexGen.io.mapping(i - (jmpCnt + mduCnt)).valid && aluReady
}
enq.bits := io.fromDq(indexVec(i)).bits
......
......@@ -85,7 +85,7 @@ object RegfileReadPortGen {
val choiceCount = dynamicMappedValid.length + 1
val readPortSrc = Wire(Vec(staticMappedValid.length, UInt(log2Ceil(choiceCount).W)))
var hasAssigned = (0 until choiceCount).map(_ => false.B)
for (i <- 0 until staticMappedValid.length) {
for (i <- staticMappedValid.indices) {
val valid = staticMappedValid(i) +: dynamicMappedValid
val wantReadPort = (0 until choiceCount).map(j => valid(j) && ((j == 0).asBool() || !hasAssigned(j)))
readPortSrc(i) := PriorityEncoder(wantReadPort)
......@@ -93,8 +93,8 @@ object RegfileReadPortGen {
hasAssigned = (0 until choiceCount).map(i => hasAssigned(i) || onehot(i))
}
val dynamicExuSrc = Wire(Vec(dynamicMappedValid.length, UInt(log2Ceil(staticMappedValid.length).W)))
for (i <- 0 until dynamicMappedValid.length) {
val targetMatch = (0 until staticMappedValid.length).map(j => readPortSrc(j) === (i + 1).U)
for (i <- dynamicMappedValid.indices) {
val targetMatch = staticMappedValid.indices.map(j => readPortSrc(j) === (i + 1).U)
dynamicExuSrc(i) := PriorityEncoder(targetMatch)
}
(readPortSrc, dynamicExuSrc)
......
......@@ -183,6 +183,7 @@ abstract class Exu(val config: ExuConfig) extends XSModule {
out.fflags := DontCare
out.debug <> DontCare
out.debug.isMMIO := false.B
out.debug.isPerfCnt := false.B
out.redirect <> DontCare
out.redirectValid := false.B
}
......
......@@ -21,6 +21,9 @@ class JumpExeUnit extends Exu(jumpExeUnitCfg)
val memExceptionVAddr = Input(UInt(VAddrBits.W))
val externalInterrupt = new ExternalInterruptIO
val tlb = Output(new TlbCsrBundle)
val perfinfo = new Bundle {
val retiredInstr = Input(UInt(3.W))
}
})
val fenceio = IO(new Bundle {
val sfence = Output(new SfenceBundle)
......@@ -42,6 +45,7 @@ class JumpExeUnit extends Exu(jumpExeUnitCfg)
}.get
csr.csrio.perf <> DontCare
csr.csrio.perf.retiredInstr <> csrio.perfinfo.retiredInstr
csr.csrio.fpu.fflags <> csrio.fflags
csr.csrio.fpu.isIllegal := false.B
csr.csrio.fpu.dirty_fs <> csrio.dirty_fs
......@@ -73,6 +77,7 @@ class JumpExeUnit extends Exu(jumpExeUnitCfg)
io.toInt.bits.redirect.roqIdx := uop.roqIdx
io.toInt.bits.redirect.target := csr.csrio.redirectOut.bits
io.toInt.bits.redirect.pc := uop.cf.pc
io.toInt.bits.debug.isPerfCnt := csr.csrio.isPerfCnt
}.elsewhen(jmp.io.out.valid){
io.toInt.bits.redirectValid := jmp.redirectOutValid
io.toInt.bits.redirect := jmp.redirectOut
......
......@@ -6,9 +6,12 @@ import xiangshan._
import utils._
class Wb(priorities: Seq[Int], numOut: Int) extends XSModule {
class Wb(cfgs: Seq[ExuConfig], numOut: Int, isFp: Boolean) extends XSModule {
val priorities = cfgs.map(c => if(isFp) c.wbFpPriority else c.wbIntPriority)
val io = IO(new Bundle() {
val in = Vec(priorities.size, Flipped(DecoupledIO(new ExuOutput)))
val in = Vec(cfgs.size, Flipped(DecoupledIO(new ExuOutput)))
val out = Vec(numOut, ValidIO(new ExuOutput))
})
......@@ -35,7 +38,7 @@ class Wb(priorities: Seq[Int], numOut: Int) extends XSModule {
}
def splitN[T](in: Seq[T], n: Int): Seq[Option[Seq[T]]] = {
require(n > 0)
if(n == 0) return Seq()
if(n == 1){
Seq(Some(in))
} else {
......@@ -48,24 +51,38 @@ class Wb(priorities: Seq[Int], numOut: Int) extends XSModule {
}
}
if(mulReq.nonEmpty){
val arbReq = splitN(
otherReq,
mulReq.size
)
for(i <- mulReq.indices){
val other = arbReq(i).getOrElse(Seq())
val arb = Module(new Arbiter(new ExuOutput, 1+other.size))
arb.io.in <> mulReq(i) +: other
val out = io.out(directConnect.size + i)
out.valid := arb.io.out.valid
out.bits := arb.io.out.bits
arb.io.out.ready := true.B
}
val arbReq = splitN(
otherReq,
mulReq.size
)
val arbiters = for(i <- mulReq.indices) yield {
val other = arbReq(i).getOrElse(Seq())
val arb = Module(new Arbiter(new ExuOutput, 1+other.size))
arb.io.in <> mulReq(i) +: other
val out = io.out(directConnect.size + i)
out.valid := arb.io.out.valid
out.bits := arb.io.out.bits
arb.io.out.ready := true.B
arb
}
if(portUsed < numOut){
println(s"Warning: ${numOut - portUsed} ports are not used!")
io.out.drop(portUsed).foreach(_ <> DontCare)
}
val sb = new StringBuffer(s"\n${if(isFp) "fp" else "int"} wb arbiter:\n")
for((conn, i) <- directConnect.zipWithIndex){
sb.append(s"[ ${cfgs(io.in.indexOf(conn)).name} ] -> out #$i\n")
}
for(i <- mulReq.indices){
sb.append(s"[ ${cfgs(io.in.indexOf(mulReq(i))).name} ")
for(req <- arbReq(i).getOrElse(Nil)){
sb.append(s"${cfgs(io.in.indexOf(req)).name} ")
}
sb.append(s"] -> arb -> out #${directConnect.size + i}\n")
}
println(sb)
}
\ No newline at end of file
......@@ -8,15 +8,16 @@ import xiangshan.backend.ALUOpType
class Alu extends FunctionUnit with HasRedirectOut {
val (src1, src2, offset, func, pc, uop) = (
val (src1, src2, func, pc, uop) = (
io.in.bits.src(0),
io.in.bits.src(1),
io.in.bits.uop.ctrl.imm,
io.in.bits.uop.ctrl.fuOpType,
SignExt(io.in.bits.uop.cf.pc, AddrBits),
io.in.bits.uop
)
val offset = src2
val valid = io.in.valid
val isAdderSub = (func =/= ALUOpType.add) && (func =/= ALUOpType.addw)
......@@ -63,21 +64,30 @@ class Alu extends FunctionUnit with HasRedirectOut {
val snpc = Mux(isRVC, pc + 2.U, pc + 4.U)
redirectOutValid := io.out.valid && isBranch
redirectOut.pc := uop.cf.pc
redirectOut.target := Mux(!taken && isBranch, snpc, target)
// Only brTag, level, roqIdx are needed
// other infos are stored in brq
redirectOut := DontCare
redirectOut.brTag := uop.brTag
redirectOut.level := RedirectLevel.flushAfter
redirectOut.interrupt := DontCare
redirectOut.roqIdx := uop.roqIdx
brUpdate := uop.cf.brUpdate
// override brUpdate
brUpdate.pc := uop.cf.pc
brUpdate.target := Mux(!taken && isBranch, snpc, target)
brUpdate.brTarget := target
// redirectOut.pc := DontCare//uop.cf.pc
// redirectOut.target := DontCare//Mux(!taken && isBranch, snpc, target)
// redirectOut.interrupt := DontCare//DontCare
// Only taken really needed, do we need brTag ?
brUpdate := DontCare
brUpdate.taken := isBranch && taken
brUpdate.brTag := uop.brTag
// brUpdate := uop.cf.brUpdate
// // override brUpdate
// brUpdate.pc := uop.cf.pc
// brUpdate.target := Mux(!taken && isBranch, snpc, target)
// brUpdate.brTarget := target
// brUpdate.taken := isBranch && taken
// brUpdate.brTag := uop.brTag
io.in.ready := io.out.ready
io.out.valid := valid
io.out.bits.uop <> io.in.bits.uop
......
......@@ -29,7 +29,7 @@ case class FuConfig
writeIntRf: Boolean,
writeFpRf: Boolean,
hasRedirect: Boolean,
latency: HasFuLatency = CertainLatency(0)
latency: HasFuLatency = CertainLatency(0),
) {
def srcCnt: Int = math.max(numIntSrc, numFpSrc)
}
......@@ -159,7 +159,7 @@ object FunctionUnit extends HasXSParameter {
numFpSrc = 0,
writeIntRf = true,
writeFpRf = false,
hasRedirect = true
hasRedirect = true,
)
val jmpCfg = FuConfig(
......@@ -170,7 +170,7 @@ object FunctionUnit extends HasXSParameter {
numFpSrc = 0,
writeIntRf = true,
writeFpRf = false,
hasRedirect = true
hasRedirect = true,
)
val fenceCfg = FuConfig(
......
......@@ -5,6 +5,7 @@ import chisel3.util._
import xiangshan._
import utils._
import xiangshan.backend._
import xiangshan.backend.decode.ImmUnion
import xiangshan.backend.fu.FunctionUnit._
import xiangshan.backend.decode.isa._
......@@ -16,7 +17,7 @@ trait HasRedirectOut { this: RawModule =>
class Jump extends FunctionUnit with HasRedirectOut {
val (src1, offset, func, pc, uop) = (
val (src1, immMin, func, pc, uop) = (
io.in.bits.src(0),
io.in.bits.uop.ctrl.imm,
io.in.bits.uop.ctrl.fuOpType,
......@@ -24,6 +25,11 @@ class Jump extends FunctionUnit with HasRedirectOut {
io.in.bits.uop
)
val offset = SignExt(Mux(JumpOpType.jumpOpIsJal(func),
ImmUnion.J.toImm32(immMin),
ImmUnion.I.toImm32(immMin)
), XLEN)
val redirectHit = uop.roqIdx.needFlush(io.redirectIn)
val valid = io.in.valid
......@@ -32,15 +38,16 @@ class Jump extends FunctionUnit with HasRedirectOut {
val target = src1 + offset // NOTE: src1 is (pc/rf(rs1)), src2 is (offset)
redirectOutValid := valid
redirectOut.pc := uop.cf.pc
redirectOut := DontCare
// redirectOut.pc := uop.cf.pc
redirectOut.target := target
redirectOut.brTag := uop.brTag
redirectOut.level := RedirectLevel.flushAfter
redirectOut.interrupt := DontCare
// redirectOut.interrupt := DontCare
redirectOut.roqIdx := uop.roqIdx
brUpdate := uop.cf.brUpdate
brUpdate.pc := uop.cf.pc
brUpdate := DontCare //uop.cf.brUpdate
// brUpdate.pc := uop.cf.pc
brUpdate.target := target
brUpdate.brTarget := target
brUpdate.taken := true.B
......
package xiangshan.backend.fu.util
import chisel3._
import chisel3.ExcitingUtils.{ConnectionType, Debug}
import chisel3.util._
import utils._
import xiangshan._
import xiangshan.backend._
import utils.XSDebug
trait HasCSRConst {
// User Trap Setup
val Ustatus = 0x000
val Uie = 0x004
val Utvec = 0x005
// User Trap Handling
val Uscratch = 0x040
val Uepc = 0x041
val Ucause = 0x042
val Utval = 0x043
val Uip = 0x044
// User Floating-Point CSRs (not implemented)
val Fflags = 0x001
val Frm = 0x002
val Fcsr = 0x003
// User Counter/Timers
val Cycle = 0xC00
val Time = 0xC01
val Instret = 0xC02
// Supervisor Trap Setup
val Sstatus = 0x100
val Sedeleg = 0x102
val Sideleg = 0x103
val Sie = 0x104
val Stvec = 0x105
val Scounteren = 0x106
// Supervisor Trap Handling
val Sscratch = 0x140
val Sepc = 0x141
val Scause = 0x142
val Stval = 0x143
val Sip = 0x144
// Supervisor Protection and Translation
val Satp = 0x180
// Machine Information Registers
val Mvendorid = 0xF11
val Marchid = 0xF12
val Mimpid = 0xF13
val Mhartid = 0xF14
// Machine Trap Setup
val Mstatus = 0x300
val Misa = 0x301
val Medeleg = 0x302
val Mideleg = 0x303
val Mie = 0x304
val Mtvec = 0x305
val Mcounteren = 0x306
// Machine Trap Handling
val Mscratch = 0x340
val Mepc = 0x341
val Mcause = 0x342
val Mtval = 0x343
val Mip = 0x344
// Machine Memory Protection
// TBD
val Pmpcfg0 = 0x3A0
val Pmpcfg1 = 0x3A1
val Pmpcfg2 = 0x3A2
val Pmpcfg3 = 0x3A3
val PmpaddrBase = 0x3B0
// Machine Counter/Timers
// Currently, we uses perfcnt csr set instead of standard Machine Counter/Timers
// 0xB80 - 0x89F are also used as perfcnt csr
val Mcycle = 0xb00
val Minstret = 0xb02
val Mhpmcounter3 = 0xB03
val Mhpmcounter4 = 0xB04
val Mhpmcounter5 = 0xB05
val Mhpmcounter6 = 0xB06
val Mhpmcounter7 = 0xB07
val Mhpmcounter8 = 0xB08
val Mhpmcounter9 = 0xB09
val Mhpmcounter10 = 0xB0A
val Mhpmcounter11 = 0xB0B
val Mhpmcounter12 = 0xB0C
val Mhpmcounter13 = 0xB0D
val Mhpmcounter14 = 0xB0E
val Mhpmcounter15 = 0xB0F
val Mhpmcounter16 = 0xB10
val Mhpmcounter17 = 0xB11
val Mhpmcounter18 = 0xB12
val Mhpmcounter19 = 0xB13
val Mhpmcounter20 = 0xB14
val Mhpmcounter21 = 0xB15
val Mhpmcounter22 = 0xB16
val Mhpmcounter23 = 0xB17
val Mhpmcounter24 = 0xB18
val Mhpmcounter25 = 0xB19
val Mhpmcounter26 = 0xB1A
val Mhpmcounter27 = 0xB1B
val Mhpmcounter28 = 0xB1C
val Mhpmcounter29 = 0xB1D
val Mhpmcounter30 = 0xB1E
val Mhpmcounter31 = 0xB1F
// Machine Counter Setup (not implemented)
val Mcountinhibit = 0x320
val Mhpmevent3 = 0x323
val Mhpmevent4 = 0x324
val Mhpmevent5 = 0x325
val Mhpmevent6 = 0x326
val Mhpmevent7 = 0x327
val Mhpmevent8 = 0x328
val Mhpmevent9 = 0x329
val Mhpmevent10 = 0x32A
val Mhpmevent11 = 0x32B
val Mhpmevent12 = 0x32C
val Mhpmevent13 = 0x32D
val Mhpmevent14 = 0x32E
val Mhpmevent15 = 0x32F
val Mhpmevent16 = 0x330
val Mhpmevent17 = 0x331
val Mhpmevent18 = 0x332
val Mhpmevent19 = 0x333
val Mhpmevent20 = 0x334
val Mhpmevent21 = 0x335
val Mhpmevent22 = 0x336
val Mhpmevent23 = 0x337
val Mhpmevent24 = 0x338
val Mhpmevent25 = 0x339
val Mhpmevent26 = 0x33A
val Mhpmevent27 = 0x33B
val Mhpmevent28 = 0x33C
val Mhpmevent29 = 0x33D
val Mhpmevent30 = 0x33E
val Mhpmevent31 = 0x33F
// Debug/Trace Registers (shared with Debug Mode) (not implemented)
// Debug Mode Registers (not implemented)
def privEcall = 0x000.U
def privEbreak = 0x001.U
def privMret = 0x302.U
def privSret = 0x102.U
def privUret = 0x002.U
def ModeM = 0x3.U
def ModeH = 0x2.U
def ModeS = 0x1.U
def ModeU = 0x0.U
def IRQ_UEIP = 0
def IRQ_SEIP = 1
def IRQ_MEIP = 3
def IRQ_UTIP = 4
def IRQ_STIP = 5
def IRQ_MTIP = 7
def IRQ_USIP = 8
def IRQ_SSIP = 9
def IRQ_MSIP = 11
val IntPriority = Seq(
IRQ_MEIP, IRQ_MSIP, IRQ_MTIP,
IRQ_SEIP, IRQ_SSIP, IRQ_STIP,
IRQ_UEIP, IRQ_USIP, IRQ_UTIP
)
def csrAccessPermissionCheck(addr: UInt, wen: Bool, mode: UInt): Bool = {
val readOnly = addr(11,10) === "b11".U
val lowestAccessPrivilegeLevel = addr(9,8)
mode >= lowestAccessPrivilegeLevel && !(wen && readOnly)
}
}
\ No newline at end of file
......@@ -4,8 +4,10 @@ import chisel3._
import chisel3.util._
import xiangshan._
import utils._
import xiangshan.backend.decode.ImmUnion
import xiangshan.backend.exu.{Exu, ExuConfig}
import xiangshan.backend.regfile.RfReadPort
import scala.math.max
class BypassQueue(number: Int) extends XSModule {
......@@ -336,6 +338,7 @@ class ReservationStationData
// read src op value
val srcRegValue = Vec(srcNum, Input(UInt((XLEN + 1).W)))
val jumpPc = if(exuCfg == Exu.jumpExeUnitCfg) Input(UInt(VAddrBits.W)) else null
// broadcast selected uop to other issue queues
val selectedUop = ValidIO(new MicroOp)
......@@ -404,6 +407,7 @@ class ReservationStationData
val deq = RegEnable(sel.bits, sel.valid)
val enqCtrl = io.ctrl.enqCtrl
val enqUop = enqCtrl.bits
val enqUopReg = RegEnable(enqUop, enqCtrl.fire())
// enq
val enqPtr = enq(log2Up(IssQueSize)-1,0)
......@@ -418,7 +422,33 @@ class ReservationStationData
}
when (enqEnReg) {
(0 until srcNum).foreach(i => dataWrite(enqPtrReg, i, io.srcRegValue(i)))
exuCfg match {
case Exu.jumpExeUnitCfg =>
val src1Mux = Mux(enqUopReg.ctrl.src1Type === SrcType.pc,
SignExt(io.jumpPc, XLEN),
io.srcRegValue(0)
)
dataWrite(enqPtrReg, 0, src1Mux)
case Exu.aluExeUnitCfg =>
val src1Mux = Mux(enqUopReg.ctrl.src1Type === SrcType.pc,
SignExt(enqUopReg.cf.pc, XLEN),
io.srcRegValue(0)
)
dataWrite(enqPtrReg, 0, src1Mux)
// TODO: opt this, a full map is not necesscary here
val imm32 = LookupTree(
enqUopReg.ctrl.selImm,
ImmUnion.immSelMap.map(x => x._1 -> x._2.toImm32(enqUopReg.ctrl.imm))
)
val imm64 = SignExt(imm32, XLEN)
val src2Mux = Mux(enqUopReg.ctrl.src2Type === SrcType.imm,
imm64, io.srcRegValue(1)
)
dataWrite(enqPtrReg, 1, src2Mux)
case _ =>
(0 until srcNum).foreach(i => dataWrite(enqPtrReg, i, io.srcRegValue(i)))
}
XSDebug(p"${exuCfg.name}: enqPtrReg:${enqPtrReg} pc: ${Hexadecimal(uop(enqPtrReg).cf.pc)}\n")
XSDebug(p"[srcRegValue] " + List.tabulate(srcNum)(idx => p"src$idx: ${Hexadecimal(io.srcRegValue(idx))}").reduce((p1, p2) => p1 + " " + p2) + "\n")
}
......@@ -472,8 +502,8 @@ class ReservationStationData
exuInput.uop := uop(deq)
val regValues = List.tabulate(srcNum)(i => dataRead(Mux(sel.valid, sel.bits, deq), i))
XSDebug(io.deq.fire(), p"[regValues] " + List.tabulate(srcNum)(idx => p"reg$idx: ${Hexadecimal(regValues(idx))}").reduce((p1, p2) => p1 + " " + p2) + "\n")
exuInput.src1 := Mux(uop(deq).ctrl.src1Type === SrcType.pc, SignExt(uop(deq).cf.pc, XLEN + 1), regValues(0))
if (srcNum > 1) exuInput.src2 := Mux(uop(deq).ctrl.src2Type === SrcType.imm, uop(deq).ctrl.imm, regValues(1))
exuInput.src1 := regValues(0)
if (srcNum > 1) exuInput.src2 := regValues(1)
if (srcNum > 2) exuInput.src3 := regValues(2)
io.deq.valid := RegNext(sel.valid)
......@@ -496,7 +526,7 @@ class ReservationStationData
io.ctrl.feedback := DontCare
if (feedback) {
(0 until IssQueSize).map(i =>
(0 until IssQueSize).foreach(i =>
io.ctrl.feedback(i) := uop(i).roqIdx.asUInt === io.feedback.bits.roqIdx.asUInt && io.feedback.valid)
io.ctrl.feedback(IssQueSize) := io.feedback.bits.hit
}
......
......@@ -19,8 +19,10 @@ package object backend {
object JumpOpType {
def jal = "b11_000".U
def jalr = "b11_010".U
def call = "b11_011".U
def ret = "b11_100".U
// def call = "b11_011".U
// def ret = "b11_100".U
def jumpOpIsJal(op: UInt) = !op(1)
def jumpOpisJalr(op: UInt) = op(1)
}
object FenceOpType {
......
......@@ -38,6 +38,9 @@ class RoqCSRIO extends XSBundle {
val fflags = Output(Valid(UInt(5.W)))
val dirty_fs = Output(Bool())
val perfinfo = new Bundle {
val retiredInstr = Output(UInt(3.W))
}
}
class RoqEnqIO extends XSBundle {
......@@ -671,11 +674,10 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
if(i % 4 == 3) XSDebug(false, true.B, "\n")
}
val id = roqDebugId()
val difftestIntrNO = WireInit(0.U(XLEN.W))
val difftestCause = WireInit(0.U(XLEN.W))
ExcitingUtils.addSink(difftestIntrNO, s"difftestIntrNOfromCSR$id")
ExcitingUtils.addSink(difftestCause, s"difftestCausefromCSR$id")
val instrCnt = RegInit(0.U(64.W))
val retireCounter = Mux(state === s_idle, commitCnt, 0.U)
instrCnt := instrCnt + retireCounter
io.csr.perfinfo.retiredInstr := RegNext(retireCounter)
if(!env.FPGAPlatform) {
......@@ -696,10 +698,11 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
val uop = debug_microOp(idx)
val DifftestSkipSC = false
if(!DifftestSkipSC){
skip(i) := debug_exuDebug(idx).isMMIO && io.commits.valid(i)
skip(i) := (debug_exuDebug(idx).isMMIO || debug_exuDebug(idx).isPerfCnt) && io.commits.valid(i)
}else{
skip(i) := (
debug_exuDebug(idx).isMMIO ||
debug_exuDebug(idx).isPerfCnt ||
uop.ctrl.fuType === FuType.mou && uop.ctrl.fuOpType === LSUOpType.sc_d ||
uop.ctrl.fuType === FuType.mou && uop.ctrl.fuOpType === LSUOpType.sc_w
) && io.commits.valid(i)
......@@ -717,10 +720,10 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
debug_deqUop.ctrl.fuType === FuType.mou &&
(debug_deqUop.ctrl.fuOpType === LSUOpType.sc_d || debug_deqUop.ctrl.fuOpType === LSUOpType.sc_w)
val instrCnt = RegInit(0.U(64.W))
val retireCounter = Mux(state === s_idle, commitCnt, 0.U)
instrCnt := instrCnt + retireCounter
val difftestIntrNO = WireInit(0.U(XLEN.W))
val difftestCause = WireInit(0.U(XLEN.W))
ExcitingUtils.addSink(difftestIntrNO, "difftestIntrNOfromCSR")
ExcitingUtils.addSink(difftestCause, "difftestCausefromCSR")
XSDebug(difftestIntrNO =/= 0.U, "difftest intrNO set %x\n", difftestIntrNO)
val retireCounterFix = Mux(io.redirectOut.valid, 1.U, retireCounter)
val retirePCFix = SignExt(Mux(io.redirectOut.valid, debug_deqUop.cf.pc, debug_microOp(firstValidCommit).cf.pc), XLEN)
......
......@@ -398,7 +398,7 @@ class DCacheImp(outer: DCache) extends LazyModuleImp(outer) with HasDCacheParame
// sync with prober
missQueue.io.probe_wb_req.valid := prober.io.wb_req.fire()
missQueue.io.probe_wb_req.bits := prober.io.wb_req.bits
missQueue.io.probe_active := prober.io.inflight_req_block_addr
missQueue.io.probe_active := prober.io.inflight_req_idx
//----------------------------------------
// prober
......
......@@ -5,7 +5,7 @@ import chisel3.util._
import xiangshan._
import utils._
import xiangshan.backend.roq.RoqPtr
import xiangshan.backend.fu.HasCSRConst
import xiangshan.backend.fu.util.HasCSRConst
import chisel3.ExcitingUtils._
trait HasTlbConst extends HasXSParameter {
......
......@@ -306,7 +306,7 @@ class MissEntry(edge: TLEdgeOut) extends DCacheModule
// if it releases the block we are trying to acquire, we don't care, since we will get it back eventually
// but we need to know whether it releases the block we are trying to evict
val prober_writeback_our_block = (state === s_refill_req || state === s_refill_resp ||
state === s_mem_finish || state === s_wait_probe_exit || state === s_send_resp || state === s_wb_req) &&
state === s_mem_finish || state === s_wait_probe_exit) &&
io.probe_wb_req.valid && !io.probe_wb_req.bits.voluntary &&
io.probe_wb_req.bits.tag === req_old_meta.tag &&
io.probe_wb_req.bits.idx === req_idx &&
......
......@@ -126,14 +126,14 @@ class WritebackUnit(edge: TLEdgeOut) extends DCacheModule {
val id = cfg.nMissEntries
val probeResponse = edge.ProbeAck(
fromSource = id.U,
fromSource = req.source,
toAddress = r_address,
lgSize = log2Ceil(cfg.blockBytes).U,
reportPermissions = req.param
)
val probeResponseData = edge.ProbeAck(
fromSource = id.U,
fromSource = req.source,
toAddress = r_address,
lgSize = log2Ceil(cfg.blockBytes).U,
reportPermissions = req.param,
......
......@@ -403,7 +403,9 @@ class LoopPredictor extends BasePredictor with LTBParams {
io.meta.specCnts(i) := ltbResps(i).meta
}
ExcitingUtils.addSource(io.resp.exit.reduce(_||_), "perfCntLoopExit", Perf)
if (!env.FPGAPlatform) {
ExcitingUtils.addSource(io.resp.exit.reduce(_||_), "perfCntLoopExit", Perf)
}
if (BPUDebug && debug) {
// debug info
......@@ -422,4 +424,4 @@ class LoopPredictor extends BasePredictor with LTBParams {
XSDebug(false, out_fire && (i.U === 3.U || i.U === 7.U || i.U === 11.U || i.U === 15.U), "\n")
}
}
}
\ No newline at end of file
}
......@@ -362,6 +362,7 @@ class LoadQueue extends XSModule
io.ldout(i).bits.redirect := DontCare
io.ldout(i).bits.brUpdate := DontCare
io.ldout(i).bits.debug.isMMIO := debug_mmio(loadWbSel(i))
io.ldout(i).bits.debug.isPerfCnt := false.B
io.ldout(i).bits.fflags := DontCare
io.ldout(i).valid := loadWbSelV(i)
......
......@@ -264,6 +264,7 @@ class StoreQueue extends XSModule with HasDCacheParameters with HasCircularQueue
io.mmioStout.bits.redirect := DontCare
io.mmioStout.bits.brUpdate := DontCare
io.mmioStout.bits.debug.isMMIO := true.B
io.mmioStout.bits.debug.isPerfCnt := false.B
io.mmioStout.bits.fflags := DontCare
when (io.mmioStout.fire()) {
writebacked(deqPtr) := true.B
......
......@@ -4,6 +4,7 @@ import chisel3._
import chisel3.util._
import utils._
import xiangshan._
import xiangshan.backend.decode.ImmUnion
import xiangshan.cache._
// import xiangshan.cache.{DCacheWordIO, TlbRequestIO, TlbCmd, MemoryOpConstants, TlbReq, DCacheLoadReq, DCacheWordResp}
import xiangshan.backend.LSUOpType
......@@ -25,7 +26,7 @@ class LoadUnit_S0 extends XSModule {
})
val s0_uop = io.in.bits.uop
val s0_vaddr = io.in.bits.src1 + s0_uop.ctrl.imm
val s0_vaddr = io.in.bits.src1 + SignExt(ImmUnion.I.toImm32(s0_uop.ctrl.imm), XLEN)
val s0_mask = genWmask(s0_vaddr, s0_uop.ctrl.fuOpType(1,0))
// query DTLB
......@@ -280,6 +281,7 @@ class LoadUnit extends XSModule with HasLoadHelper {
intHitLoadOut.bits.redirect := DontCare
intHitLoadOut.bits.brUpdate := DontCare
intHitLoadOut.bits.debug.isMMIO := load_s2.io.out.bits.mmio
intHitLoadOut.bits.debug.isPerfCnt := false.B
intHitLoadOut.bits.fflags := DontCare
load_s2.io.out.ready := true.B
......
......@@ -4,6 +4,7 @@ import chisel3._
import chisel3.util._
import utils._
import xiangshan._
import xiangshan.backend.decode.ImmUnion
import xiangshan.cache._
// Store Pipeline Stage 0
......@@ -16,7 +17,7 @@ class StoreUnit_S0 extends XSModule {
})
// send req to dtlb
val saddr = io.in.bits.src1 + io.in.bits.uop.ctrl.imm
val saddr = io.in.bits.src1 + SignExt(ImmUnion.S.toImm32(io.in.bits.uop.ctrl.imm), XLEN)
io.dtlbReq.bits.vaddr := saddr
io.dtlbReq.valid := io.in.valid
......@@ -114,6 +115,7 @@ class StoreUnit_S2 extends XSModule {
io.stout.bits.redirect := DontCare
io.stout.bits.brUpdate := DontCare
io.stout.bits.debug.isMMIO := io.in.bits.mmio
io.stout.bits.debug.isPerfCnt := false.B
io.stout.bits.fflags := DontCare
}
......
......@@ -13,6 +13,10 @@ trait HasSbufferCst extends HasXSParameter {
def s_prepare = 2.U(2.W)
def s_inflight = 3.U(2.W)
val evictCycle = 8192
require(isPow2(evictCycle))
val countBits = 1 + log2Up(evictCycle)
val SbufferIndexWidth: Int = log2Up(StoreBufferSize)
// paddr = tag + offset
val CacheLineBytes: Int = CacheLineSize / 8
......@@ -37,7 +41,6 @@ class SbufferLine extends SbufferBundle {
class ChooseReplace(nWay: Int) extends XSModule {
val io = IO(new Bundle{
val mask = Vec(nWay, Input(Bool()))
val fire = Input(Bool())
val way = Output(UInt(nWay.W))
val flush = Input(Bool())
})
......@@ -49,12 +52,9 @@ class ChooseReplace(nWay: Int) extends XSModule {
val nextWay = PriorityEncoder(Cat(stateMask, loMask))(log2Up(nWay)-1, 0)
XSDebug(p"nextWay[${nextWay}]\n")
wayReg := nextWay
io.way := wayReg
when(io.fire){
wayReg := nextWay
}
when(io.flush){
wayReg := 0.U
}
......@@ -116,11 +116,11 @@ class NewSbuffer extends XSModule with HasSbufferCst {
val buffer = Mem(StoreBufferSize, new SbufferLine)
val stateVec = RegInit(VecInit(Seq.fill(StoreBufferSize)(s_invalid)))
val cohCount = Reg(Vec(StoreBufferSize, UInt(countBits.W)))
/*
idle --[flush]--> drian_sbuffer --[buf empty]--> idle
--[buf full]--> replace --[dcache resp]--> idle
*/
*/
val x_idle :: x_drain_sbuffer :: x_replace :: Nil = Enum(3)
val sbuffer_state = RegInit(x_idle)
......@@ -150,7 +150,6 @@ class NewSbuffer extends XSModule with HasSbufferCst {
val invalidCount = RegInit(StoreBufferSize.U((log2Up(StoreBufferSize) + 1).W))
val validCount = RegInit(0.U((log2Up(StoreBufferSize) + 1).W))
val full = invalidCount === 0.U
// val oneSpace = invalidCount === 1.U
val bufferRead = VecInit((0 until StoreBufferSize).map(i => buffer(i)))
val stateRead = VecInit((0 until StoreBufferSize).map(i => stateVec(i)))
......@@ -171,8 +170,7 @@ class NewSbuffer extends XSModule with HasSbufferCst {
val lru = Module(new ChooseReplace(StoreBufferSize))
val evictionIdx = lru.io.way
lru.io.fire := false.B
lru.io.mask := stateRead.map(_ === s_valid)
val tags = io.in.map(in => getTag(in.bits.addr))
......@@ -212,6 +210,7 @@ class NewSbuffer extends XSModule with HasSbufferCst {
def wordReqToBufLine(req: DCacheWordReq, tag: UInt, insertIdx: UInt, wordOffset: UInt, flushMask: Bool): Unit = {
stateUpdate(insertIdx) := s_valid
tagUpdate(insertIdx) := tag
cohCount(insertIdx) := 0.U
when(flushMask){
for(j <- 0 until CacheLineWords){
......@@ -230,6 +229,7 @@ class NewSbuffer extends XSModule with HasSbufferCst {
}
def mergeWordReq(req: DCacheWordReq, mergeIdx:UInt, wordOffset:UInt): Unit = {
cohCount(mergeIdx) := 0.U
for(i <- 0 until DataBytes){
when(req.mask(i)){
maskUpdate(mergeIdx)(wordOffset)(i) := true.B
......@@ -267,7 +267,7 @@ class NewSbuffer extends XSModule with HasSbufferCst {
for(i <- 0 until StoreBufferSize){
XSDebug(stateVec(i)=/=s_invalid,
p"[$i] state:${stateVec(i)} buf:${bufferRead(i)}\n"
p"[$i] timeout:${cohCount(i)(countBits-1)} state:${stateVec(i)} buf:${bufferRead(i)}\n"
)
}
......@@ -338,16 +338,14 @@ class NewSbuffer extends XSModule with HasSbufferCst {
//
// evictionEntry.bits := evictionIdx
val prepareValid = ((do_eviction && sbuffer_state === x_replace)|| (sbuffer_state === x_drain_sbuffer)) &&
val prepareValid = ((do_eviction && sbuffer_state === x_replace) || (sbuffer_state === x_drain_sbuffer)) &&
stateVec(evictionIdx)===s_valid &&
noSameBlockInflight(evictionIdx)
when(prepareValid){
stateVec(evictionIdx) := s_prepare
lru.io.fire := true.B
}
val prepareMask = stateVec.map(s => s === s_prepare)
val (prepareIdx, prepareEn) = PriorityEncoderWithFlag(prepareMask)
......@@ -383,6 +381,21 @@ class NewSbuffer extends XSModule with HasSbufferCst {
XSDebug(p"needSpace[$needSpace] invalidCount[$invalidCount] validCount[$validCount]\n")
//-------------------------cohCount-----------------------------
// insert and merge: cohCount=0
// every cycle cohCount+=1
// if cohCount(countBits-1)==1,evict
for(i <- 0 until StoreBufferSize){
when(stateVec(i) === s_valid){
when(cohCount(i)(countBits-1)){
assert(stateVec(i) === s_valid)
stateUpdate(i) := s_prepare
}
cohCount(i) := cohCount(i)+1.U
}
}
// ---------------------- Load Data Forward ---------------------
for ((forward, i) <- io.forward.zipWithIndex) {
......
......@@ -44,9 +44,87 @@ class SbufferTest extends AnyFlatSpec
top.Parameters.set(top.Parameters.debugParameters)
it should "random req" in {
// it should "random req" in {
// test(new SbufferWapper{AddSinks()}){ c =>
//
// def store_enq(addr: Seq[UInt], data: Seq[UInt], mask: Seq[UInt]) ={
// (0 until StorePipelineWidth).map { i =>
// c.io.in(i).valid.poke(true.B)
// c.io.in(i).bits.pokePartial(chiselTypeOf(c.io.in(i).bits).Lit(
// _.mask -> mask(i),
// _.addr -> addr(i),
// _.data -> data(i)
// ))
// }
// c.clock.step(1)
// for (in <- c.io.in){ in.valid.poke(false.B)}
// }
//
// def forward_req_and_resp(addr: Seq[UInt], data: Seq[UInt], mask:Seq[UInt]) = {
// (0 until LoadPipelineWidth).map{ i =>
// c.io.forward(i).paddr.poke(addr(i))
// c.io.forward(i).mask.poke(mask(i))
// if(c.io.in(i).ready.peek() == true.B) {
// (0 until 8).map { j =>
// c.io.forward(i).forwardData(j).expect(data(i)(j * 8 + 7, j * 8))
// }
// }
// }
// }
//
// val TEST_SIZE = 100
// for(i <- 0 until TEST_SIZE) {
// val addr = Seq.fill(StorePipelineWidth)((Random.nextLong() & 0x7ffffffff8L).U)// align to block size
// val data = Seq.fill(StorePipelineWidth)((Random.nextLong() & 0x7fffffffffffffffL).U)
// val mask = Seq.fill(StorePipelineWidth)(0xff.U)
// store_enq(addr, data, mask)
// forward_req_and_resp(addr, data, mask)
// }
// }
// }
//
// it should "sequence req" in {
// test(new SbufferWapper{AddSinks()}){ c =>
//
// def store_enq(addr: Seq[UInt], data: Seq[UInt], mask: Seq[UInt]) = {
// (0 until StorePipelineWidth).map { i =>
// c.io.in(i).valid.poke(true.B)
// c.io.in(i).bits.pokePartial(chiselTypeOf(c.io.in(i).bits).Lit(
// _.mask -> mask(i),
// _.addr -> addr(i),
// _.data -> data(i)
// ))
// }
// c.clock.step(1)
// for (in <- c.io.in){ in.valid.poke(false.B)}
// }
//
// def forward_req_and_resp(addr: Seq[UInt], data: Seq[UInt], mask:Seq[UInt]) = {
// (0 until LoadPipelineWidth).map{ i =>
// c.io.forward(i).paddr.poke(addr(i))
// c.io.forward(i).mask.poke(mask(i))
// if(c.io.in(i).ready.peek() == true.B) {
// (0 until 8).map { j =>
// c.io.forward(i).forwardData(j).expect(data(i)(j * 8 + 7, j * 8))
// }
// }
// }
// }
//
// val TEST_SIZE = 100
// val start_addr = Random.nextLong() & 0x7ffffffff8L
// for(i <- 0 until TEST_SIZE) {
// val addr = Seq(((i<<4) + start_addr).U,((i<<4)+8+start_addr).U)
// val data = Seq.fill(StorePipelineWidth)((Random.nextLong() & 0x7fffffffffffffffL).U)
// val mask = Seq.fill(StorePipelineWidth)(0xff.U)
// store_enq(addr, data, mask)
// forward_req_and_resp(addr, data, mask)
// }
// }
// }
it should "sbuffer coherence" in {
test(new SbufferWapper{AddSinks()}){ c =>
def store_enq(addr: Seq[UInt], data: Seq[UInt], mask: Seq[UInt]) ={
(0 until StorePipelineWidth).map { i =>
c.io.in(i).valid.poke(true.B)
......@@ -59,7 +137,6 @@ class SbufferTest extends AnyFlatSpec
c.clock.step(1)
for (in <- c.io.in){ in.valid.poke(false.B)}
}
def forward_req_and_resp(addr: Seq[UInt], data: Seq[UInt], mask:Seq[UInt]) = {
(0 until LoadPipelineWidth).map{ i =>
c.io.forward(i).paddr.poke(addr(i))
......@@ -71,55 +148,16 @@ class SbufferTest extends AnyFlatSpec
}
}
}
val TEST_SIZE = 100
val TEST_SIZE = 10
for(i <- 0 until TEST_SIZE) {
val addr = Seq.fill(StorePipelineWidth)((Random.nextLong() & 0x7ffffffff8L).U)// align to block size
val addr = Seq.fill(StorePipelineWidth)((Random.nextLong() & 0x7ffffffff8L).U)// align to
val data = Seq.fill(StorePipelineWidth)((Random.nextLong() & 0x7fffffffffffffffL).U)
val mask = Seq.fill(StorePipelineWidth)(0xff.U)
store_enq(addr, data, mask)
forward_req_and_resp(addr, data, mask)
}
}
}
it should "sequence req" in {
test(new SbufferWapper{AddSinks()}){ c =>
def store_enq(addr: Seq[UInt], data: Seq[UInt], mask: Seq[UInt]) = {
(0 until StorePipelineWidth).map { i =>
c.io.in(i).valid.poke(true.B)
c.io.in(i).bits.pokePartial(chiselTypeOf(c.io.in(i).bits).Lit(
_.mask -> mask(i),
_.addr -> addr(i),
_.data -> data(i)
))
}
c.clock.step(1)
for (in <- c.io.in){ in.valid.poke(false.B)}
}
def forward_req_and_resp(addr: Seq[UInt], data: Seq[UInt], mask:Seq[UInt]) = {
(0 until LoadPipelineWidth).map{ i =>
c.io.forward(i).paddr.poke(addr(i))
c.io.forward(i).mask.poke(mask(i))
if(c.io.in(i).ready.peek() == true.B) {
(0 until 8).map { j =>
c.io.forward(i).forwardData(j).expect(data(i)(j * 8 + 7, j * 8))
}
}
}
}
val TEST_SIZE = 100
val start_addr = Random.nextLong() & 0x7ffffffff8L
for(i <- 0 until TEST_SIZE) {
val addr = Seq(((i<<4) + start_addr).U,((i<<4)+8+start_addr).U)
val data = Seq.fill(StorePipelineWidth)((Random.nextLong() & 0x7fffffffffffffffL).U)
val mask = Seq.fill(StorePipelineWidth)(0xff.U)
store_enq(addr, data, mask)
forward_req_and_resp(addr, data, mask)
}
c.clock.step(512 + 10)
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册