提交 3a1c7672 编写于 作者: G GouLingrui

Merge branch 'dev-frontend' of https://github.com/RISCVERS/XiangShan into dev-frontend

......@@ -3,7 +3,7 @@ NANOS_HOME ?= $(AM_HOME)/../nanos-lite
SINGLETEST = ALL=min3
B ?= 0
E ?= 0
E ?= -1
V ?= ALL
#V ?= OFF
EMU_ARGS = B=$(B) E=$(E) V=$(V)
......@@ -13,14 +13,14 @@ EMU_ARGS = B=$(B) E=$(E) V=$(V)
# ------------------------------------------------------------------
cpu:
$(MAKE) -C $(AM_HOME)/tests/cputest $(ARCH) ALL=dummy $(EMU_ARGS) run
$(MAKE) -C $(AM_HOME)/tests/cputest $(ARCH) ALL=shift $(EMU_ARGS) run 2>&1 | tee > ras_shift.log
# ------------------------------------------------------------------
# run different test sets
# ------------------------------------------------------------------
cputest:
$(MAKE) -C $(AM_HOME)/tests/cputest $(ARCH) $(EMU_ARGS) run
$(MAKE) -C $(AM_HOME)/tests/cputest $(ARCH) $(EMU_ARGS) run 2>&1 | tee > cpu.log
#2 > cpu.log
cat cpu.log | grep different
cat cpu.log | grep IPC
......
......@@ -58,6 +58,7 @@ class BranchInfo extends XSBundle {
val tageMeta = new TageMeta
val rasSp = UInt(log2Up(RasSize).W)
val rasTopCtr = UInt(8.W)
val rasToqAddr = UInt(VAddrBits.W)
def apply(histPtr: UInt, tageMeta: TageMeta, rasSp: UInt, rasTopCtr: UInt) = {
this.histPtr := histPtr
......
......@@ -106,6 +106,8 @@ abstract class BPUStage extends XSModule {
val pred = Decoupled(new BranchPrediction)
val out = Decoupled(new BPUStageIO)
val predecode = Flipped(ValidIO(new Predecode))
val recover = Flipped(ValidIO(new BranchUpdateInfo))
}
val io = IO(new DefaultIO)
......@@ -235,8 +237,8 @@ class BPUStage2 extends BPUStage {
class BPUStage3 extends BPUStage {
io.out.valid := predValid && io.predecode.valid && !io.flush
io.out.valid := predValid && io.predecode.valid && !io.flush
// TAGE has its own pipelines and the
// response comes directly from s3,
// so we do not use those from inLatch
......@@ -252,11 +254,12 @@ class BPUStage3 extends BPUStage {
val brs = pdMask & Reverse(Cat(pds.map(_.isBr)))
val jals = pdMask & Reverse(Cat(pds.map(_.isJal)))
val jalrs = pdMask & Reverse(Cat(pds.map(_.isJalr)))
// val calls = pdMask & Reverse(Cat(pds.map(_.isCall)))
// val rets = pdMask & Reverse(Cat(pds.map(_.isRet)))
val calls = pdMask & Reverse(Cat(pds.map(_.isCall)))
val rets = pdMask & Reverse(Cat(pds.map(_.isRet)))
val RVCs = pdMask & Reverse(Cat(pds.map(_.isRVC)))
// val callIdx = PriorityEncoder(calls)
// val retIdx = PriorityEncoder(rets)
val callIdx = PriorityEncoder(calls)
val retIdx = PriorityEncoder(rets)
val brTakens =
if (EnableBPD) {
......@@ -274,6 +277,27 @@ class BPUStage3 extends BPUStage {
else { VecInit((0 until PredictWidth).map(i => brs(i) && !bimTakens(i)))})
targetSrc := inLatch.resp.btb.targets
//RAS
if(EnableRAS){
val ras = Module(new RAS)
ras.io <> DontCare
ras.io.pc.bits := inLatch.pc
ras.io.pc.valid := io.out.fire()//predValid
ras.io.is_ret := rets.orR && (retIdx === jmpIdx) && io.predecode.valid
ras.io.callIdx.valid := calls.orR && (callIdx === jmpIdx) && io.predecode.valid
ras.io.callIdx.bits := callIdx
ras.io.isRVC := (calls & RVCs).orR //TODO: this is ugly
ras.io.recover := io.recover
for(i <- 0 until PredictWidth){
io.out.bits.brInfo(i).rasSp := ras.io.branchInfo.rasSp
io.out.bits.brInfo(i).rasTopCtr := ras.io.branchInfo.rasTopCtr
io.out.bits.brInfo(i).rasToqAddr := ras.io.branchInfo.rasToqAddr
}
takens := VecInit((0 until PredictWidth).map(i => (brTakens(i) || jalrs(i)) && btbHits(i) || jals(i)|| rets(i)))
when(ras.io.is_ret && ras.io.out.valid){targetSrc(retIdx) := ras.io.out.bits.target}
}
lastIsRVC := pds(lastValidPos).isRVC
when (lastValidPos === 1.U) {
lastHit := pdMask(1) |
......@@ -378,6 +402,11 @@ abstract class BaseBPU extends XSModule with BranchPredictorComponents{
io.branchInfo.bits := s3.io.out.bits.brInfo
s3.io.out.ready := io.branchInfo.ready
s1.io.recover <> DontCare
s2.io.recover <> DontCare
s3.io.recover.valid <> io.inOrderBrInfo.valid
s3.io.recover.bits <> io.inOrderBrInfo.bits.ui
XSDebug(io.branchInfo.fire(), "branchInfo sent!\n")
for (i <- 0 until PredictWidth) {
val b = io.branchInfo.bits(i)
......@@ -488,3 +517,16 @@ class BPU extends BaseBPU {
}
}
object BPU{
def apply(enableBPU: Boolean = true) = {
if(enableBPU) {
val BPU = Module(new BPU)
BPU
}
else {
val FakeBPU = Module(new FakeBPU)
FakeBPU
}
}
}
\ No newline at end of file
......@@ -30,7 +30,7 @@ class IFUIO extends XSBundle
class IFU extends XSModule with HasIFUConst
{
val io = IO(new IFUIO)
val bpu = if (EnableBPU) Module(new BPU) else Module(new FakeBPU)
val bpu = BPU(EnableBPU)
val pd = Module(new PreDecode)
val if2_redirect, if3_redirect, if4_redirect = WireInit(false.B)
......
package xiangshan.frontend
import chisel3._
import chisel3.util._
import xiangshan._
import xiangshan.backend.ALUOpType
import utils._
class RAS extends BasePredictor
{
class RASResp extends Resp
{
val target =UInt(VAddrBits.W)
}
class RASBranchInfo extends Meta
{
val rasSp = UInt(log2Up(RasSize).W)
val rasTopCtr = UInt(8.W)
val rasToqAddr = UInt(VAddrBits.W)
}
class RASIO extends DefaultBasePredictorIO
{
val is_ret = Input(Bool())
val callIdx = Flipped(ValidIO(UInt(log2Ceil(PredictWidth).W)))
val isRVC = Input(Bool())
val recover = Flipped(ValidIO(new BranchUpdateInfo))
val out = ValidIO(new RASResp)
val branchInfo = Output(new RASBranchInfo)
}
def rasEntry() = new Bundle {
val retAddr = UInt(VAddrBits.W)
val ctr = UInt(8.W) // layer of nested call functions
}
override val io = IO(new RASIO)
// val ras_0 = Reg(Vec(RasSize, rasEntry())) //RegInit(0.U)asTypeOf(Vec(RasSize,rasEntry)) cause comb loop
// val ras_1 = Reg(Vec(RasSize, rasEntry()))
// val sp_0 = RegInit(0.U(log2Up(RasSize).W))
// val sp_1 = RegInit(0.U(log2Up(RasSize).W))
// val choose_bit = RegInit(false.B) //start with 0
// val spec_ras = Mux(choose_bit, ras_1, ras_0)
// val spec_sp = Mux(choose_bit,sp_1,sp_0)
// val commit_ras = Mux(choose_bit, ras_0, ras_1)
// val commit_sp = Mux(choose_bit,sp_0,sp_1)
val spec_ras = Reg(Vec(RasSize, rasEntry()))
val spec_sp = RegInit(0.U(log2Up(RasSize).W))
val commit_ras = Reg(Vec(RasSize, rasEntry()))
val commit_sp = RegInit(0.U(log2Up(RasSize).W))
val spec_is_empty = spec_sp === 0.U
val spec_is_full = spec_sp === (RasSize - 1).U
val spec_ras_top_entry = spec_ras(spec_sp-1.U)
val spec_ras_top_addr = spec_ras_top_entry.retAddr
val spec_ras_top_ctr = spec_ras_top_entry.ctr
//no need to pass the ras branchInfo
io.branchInfo.rasSp := DontCare
io.branchInfo.rasTopCtr := DontCare
io.branchInfo.rasToqAddr := DontCare
io.out.valid := !spec_is_empty && io.is_ret
XSDebug("----------------RAS(spec)----------------\n")
XSDebug(" index addr ctr \n")
for(i <- 0 until RasSize){
XSDebug(" (%d) 0x%x %d",i.U,spec_ras(i).retAddr,spec_ras(i).ctr)
when(i.U === spec_sp){XSDebug(false,true.B," <----sp")}
XSDebug(false,true.B,"\n")
}
XSDebug("----------------RAS(commit)----------------\n")
XSDebug(" index addr ctr \n")
for(i <- 0 until RasSize){
XSDebug(" (%d) 0x%x %d",i.U,commit_ras(i).retAddr,commit_ras(i).ctr)
when(i.U === commit_sp){XSDebug(false,true.B," <----sp")}
XSDebug(false,true.B,"\n")
}
// update spec RAS
// speculative update RAS
val spec_push = !spec_is_full && io.callIdx.valid && io.pc.valid
val spec_pop = !spec_is_empty && io.is_ret && io.pc.valid
val spec_new_addr = io.pc.bits + (io.callIdx.bits << 1.U) + Mux(io.isRVC,2.U,4.U)
val spec_ras_write = WireInit(0.U.asTypeOf(rasEntry()))
val sepc_alloc_new = spec_new_addr =/= spec_ras_top_addr
when (spec_push) {
//push
spec_ras_write.ctr := 1.U
spec_ras_write.retAddr := spec_new_addr
when(sepc_alloc_new){
spec_sp := spec_sp + 1.U
spec_ras(spec_sp) := spec_ras_write
}.otherwise{
spec_ras_top_ctr := spec_ras_top_ctr + 1.U
}
XSDebug("(spec_ras)push inAddr: 0x%x inCtr: %d | allocNewEntry:%d | sp:%d \n",spec_ras_write.retAddr,spec_ras_write.ctr,sepc_alloc_new,spec_sp.asUInt)
}
when (spec_pop) {
//pop
when (spec_ras_top_ctr === 1.U) {
spec_sp := Mux(spec_sp === 0.U, 0.U, spec_sp - 1.U)
}.otherwise {
spec_ras_top_ctr := spec_ras_top_ctr - 1.U
}
XSDebug("(spec_ras)pop outValid:%d outAddr: 0x%x \n",io.out.valid,io.out.bits.target)
}
io.out.bits.target := spec_ras_top_addr
// TODO: back-up stack for ras
// use checkpoint to recover RAS
val commit_is_empty = commit_sp === 0.U
val commit_is_full = commit_sp === (RasSize - 1).U
val commit_ras_top_entry = commit_ras(commit_sp-1.U)
val commit_ras_top_addr = commit_ras_top_entry.retAddr
val commit_ras_top_ctr = commit_ras_top_entry.ctr
//update commit ras
val commit_push = !commit_is_full && io.recover.valid && io.recover.bits.pd.isCall
val commit_pop = !commit_is_empty && io.recover.valid && io.recover.bits.pd.isRet
val commit_new_addr = io.recover.bits.pc + 4.U //TODO: consider RVC
val commit_ras_write = WireInit(0.U.asTypeOf(rasEntry()))
val commit_alloc_new = commit_new_addr =/= commit_ras_top_addr
when (commit_push) {
//push
commit_ras_write.ctr := 1.U
commit_ras_write.retAddr := commit_new_addr
when(commit_alloc_new){
commit_sp := commit_sp + 1.U
commit_ras(commit_sp) := commit_ras_write
}.otherwise{
commit_ras_top_ctr := commit_ras_top_ctr + 1.U
}
XSDebug("(commit_ras)push inAddr: 0x%x inCtr: %d | allocNewEntry:%d | sp:%d \n",commit_ras_write.retAddr,commit_ras_write.ctr,sepc_alloc_new,commit_sp.asUInt)
}
when (commit_pop) {
//pop
when (commit_ras_top_ctr === 1.U) {
commit_sp := Mux(commit_sp === 0.U, 0.U, commit_sp - 1.U)
}.otherwise {
commit_ras_top_ctr := commit_ras_top_ctr - 1.U
}
XSDebug("(commit_ras)pop outValid:%d outAddr: 0x%x \n",io.out.valid,io.out.bits.target)
}
val copy_valid = io.recover.valid && io.recover.bits.isMisPred
val copy_next = RegNext(copy_valid)
XSDebug("copyValid:%d copyNext:%d \n",copy_valid,copy_next)
when(copy_next)
{
for(i <- 0 until RasSize)
{
spec_ras(i) := commit_ras(i)
spec_sp := commit_sp
}
}
// val recoverSp = io.recover.bits.brInfo.rasSp
// val recoverCtr = io.recover.bits.brInfo.rasTopCtr
// val recoverAddr = io.recover.bits.brInfo.rasToqAddr
// val recover_top = ras(recoverSp - 1.U)
// when (recover_valid) {
// sp := recoverSp
// recover_top.ctr := recoverCtr
// recover_top.retAddr := recoverAddr
// XSDebug("RAS update: SP:%d , Ctr:%d \n",recoverSp,recoverCtr)
// }
// val recover_and_push = recover_valid && push
// val recover_and_pop = recover_valid && pop
// val recover_alloc_new = new_addr =/= recoverAddr
// when(recover_and_push)
// {
// when(recover_alloc_new){
// sp := recoverSp + 1.U
// ras(recoverSp).retAddr := new_addr
// ras(recoverSp).ctr := 1.U
// recover_top.retAddr := recoverAddr
// recover_top.ctr := recoverCtr
// } .otherwise{
// sp := recoverSp
// recover_top.ctr := recoverCtr + 1.U
// recover_top.retAddr := recoverAddr
// }
// } .elsewhen(recover_and_pop)
// {
// io.out.bits.target := recoverAddr
// when ( recover_top.ctr === 1.U) {
// sp := recoverSp - 1.U
// }.otherwise {
// sp := recoverSp
// recover_top.ctr := recoverCtr - 1.U
// }
// }
}
\ No newline at end of file
package xiangshan.frontend
import chisel3._
import chiseltest._
import org.scalatest._
import xiangshan.testutils._
class RASTest extends FlatSpec
with ChiselScalatestTester
with Matchers
with ParallelTestExecution
with HasPartialDecoupledDriver {
it should "test RASTest" in {
test(new RAS) { c =>
def spec_push(pc: Long,callIdx: Int){
c.io.callIdx.valid.poke(true.B)
c.io.callIdx.bits.poke(callIdx.U)
c.io.pc.valid.poke(true.B)
c.io.pc.bits.poke(pc.U)
c.clock.step()
c.io.callIdx.valid.poke(false.B)
}
def spec_pop(){
c.io.is_ret.poke(true.B)
//c.io.out.bits.target.expect(rigth_target.U)
c.clock.step()
c.io.is_ret.poke(false.B)
}
def commit_push(pc: Long){
c.io.recover.valid.poke(true.B)
c.io.recover.bits.isMisPred.poke(false.B)
c.io.recover.bits.pd.isCall.poke(true.B)
c. io.recover.bits.pc.poke(pc.U)
c.clock.step()
c.io.recover.valid.poke(false.B)
c.io.recover.bits.pd.isCall.poke(false.B)
}
def commit_pop(){
c.io.recover.valid.poke(true.B)
c.io.recover.bits.pd.isRet.poke(true.B)
c.clock.step()
c.io.recover.valid.poke(false.B)
c.io.recover.bits.pd.isRet.poke(false.B)
}
// def update_pop(sp:Int,ctr:Int,addr:Long){
// c.io.recover.valid.poke(true.B)
// c.io.recover.bits.isMisPred.poke(true.B)
// c.io.recover.bits.brInfo.rasToqAddr.poke(addr.U)
// c.io.recover.bits.brInfo.rasTopCtr.poke(ctr.U)
// c.io.recover.bits.brInfo.rasSp.poke(sp.U)
// pop(right_target=addr)
// c.io.out.bits.target.expect(addr.U)
// }
// def update_push(sp:Int,ctr:Int,addr:Long,pc: Long,callIdx: Int){
// c.io.recover.valid.poke(true.B)
// c.io.recover.bits.isMisPred.poke(true.B)
// c.io.recover.bits.brInfo.rasToqAddr.poke(addr.U)
// c.io.recover.bits.brInfo.rasTopCtr.poke(ctr.U)
// c.io.recover.bits.brInfo.rasSp.poke(sp.U)
// push(pc,callIdx)
// }
//update_pop(sp=2,ctr=1,addr=0x60002020+5*2+4)
spec_push(pc=0x60000010,callIdx=2)
spec_push(pc=0x60000014,callIdx=3)
commit_push(pc=0x60000028)
commit_push(pc=0x60000030)
spec_pop()
spec_pop()
c.io.recover.valid.poke(true.B)
c.io.recover.bits.isMisPred.poke(true.B)
commit_pop()
commit_pop()
// pop(rigth_target=0x60002000+8*2+4)
// pop(rigth_target=0x60002000+8*2+4)
// pop(rigth_target=0x60002000+8*2+4)
}
}
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册