提交 ada67687 编写于 作者: Y Yinan Xu

Merge remote-tracking branch 'origin/master' into debian-gogogo

......@@ -348,3 +348,4 @@ mill.rdiB
stale_outputs_checked
*.snapshot
......@@ -66,7 +66,7 @@ EMU_VFILES = $(shell find $(EMU_VSRC_DIR) -name "*.v" -or -name "*.sv")
EMU_CXXFLAGS += -std=c++11 -static -Wall -I$(EMU_CSRC_DIR)
EMU_CXXFLAGS += -DVERILATOR -Wno-maybe-uninitialized
EMU_LDFLAGS += -lpthread -lSDL2 -ldl
EMU_LDFLAGS += -lpthread -lSDL2 -ldl -lz
VEXTRA_FLAGS = -I$(abspath $(BUILD_DIR)) --x-assign unique -O3 -CFLAGS "$(EMU_CXXFLAGS)" -LDFLAGS "$(EMU_LDFLAGS)"
......
......@@ -5,7 +5,7 @@ import chisel3.util._
import xiangshan._
import xiangshan.backend.regfile.Regfile
import xiangshan.backend.exu._
import xiangshan.backend.issue.ReservationStationNew
import xiangshan.backend.issue.{ReservationStationCtrl, ReservationStationData}
class FpBlockToCtrlIO extends XSBundle {
......@@ -78,28 +78,30 @@ class FloatBlock
s"delay:${certainLatency}"
)
val rs = Module(new ReservationStationNew(
cfg, wakeupCnt, extraListenPortsCnt, fixedDelay = certainLatency, feedback = false
))
val rsCtrl = Module(new ReservationStationCtrl(cfg, wakeupCnt, extraListenPortsCnt, fixedDelay = certainLatency, feedback = false))
val rsData = Module(new ReservationStationData(cfg, wakeupCnt, extraListenPortsCnt, fixedDelay = certainLatency, feedback = false))
rs.io.redirect <> redirect
rs.io.numExist <> io.toCtrlBlock.numExist(i)
rs.io.enqCtrl <> io.fromCtrlBlock.enqIqCtrl(i)
rs.io.enqData <> io.fromCtrlBlock.enqIqData(i)
rsCtrl.io.data <> rsData.io.ctrl
rsCtrl.io.redirect <> redirect // TODO: remove it
rsCtrl.io.numExist <> io.toCtrlBlock.numExist(i)
rsCtrl.io.enqCtrl <> io.fromCtrlBlock.enqIqCtrl(i)
rsData.io.enqData <> io.fromCtrlBlock.enqIqData(i)
rsData.io.redirect <> redirect
rs.io.writeBackedData <> writeBackData
for ((x, y) <- rs.io.extraListenPorts.zip(extraListenPorts)) {
rsData.io.writeBackedData <> writeBackData
for ((x, y) <- rsData.io.extraListenPorts.zip(extraListenPorts)) {
x.valid := y.fire()
x.bits := y.bits
}
exeUnits(i).io.redirect <> redirect
exeUnits(i).io.fromFp <> rs.io.deq
rs.io.tlbFeedback := DontCare
exeUnits(i).io.fromFp <> rsData.io.deq
rsData.io.feedback := DontCare
rs.suggestName(s"rs_${cfg.name}")
rsCtrl.suggestName(s"rsc_${cfg.name}")
rsData.suggestName(s"rsd_${cfg.name}")
rs
rsData
})
for(rs <- reservedStations){
......@@ -157,4 +159,4 @@ class FloatBlock
rf.data := wb.bits.data
}
}
}
\ No newline at end of file
......@@ -6,7 +6,7 @@ import xiangshan._
import xiangshan.backend.exu.Exu.{jumpExeUnitCfg, ldExeUnitCfg, stExeUnitCfg}
import xiangshan.backend.exu.{AluExeUnit, ExuConfig, JumpExeUnit, MulDivExeUnit, Wb}
import xiangshan.backend.fu.FenceToSbuffer
import xiangshan.backend.issue.ReservationStationNew
import xiangshan.backend.issue.{ReservationStationCtrl, ReservationStationData}
import xiangshan.backend.regfile.Regfile
import xiangshan.backend.fu.fpu.Fflags
......@@ -131,28 +131,33 @@ class IntegerBlock
println(s"${i}: exu:${cfg.name} wakeupCnt: ${wakeupCnt} extraListenPorts: ${extraListenPortsCnt} delay:${certainLatency} feedback:${feedback}")
val rs = Module(new ReservationStationNew(
cfg, wakeupCnt, extraListenPortsCnt, fixedDelay = certainLatency, feedback = feedback
))
rs.io.redirect <> redirect
rs.io.numExist <> io.toCtrlBlock.numExist(i)
rs.io.enqCtrl <> io.fromCtrlBlock.enqIqCtrl(i)
rs.io.enqData <> io.fromCtrlBlock.enqIqData(i)
rs.io.writeBackedData <> writeBackData
for ((x, y) <- rs.io.extraListenPorts.zip(extraListenPorts)) {
// val rs = Module(new ReservationStationNew(
// cfg, wakeupCnt, extraListenPortsCnt, fixedDelay = certainLatency, feedback = feedback
// ))
val rsCtrl = Module(new ReservationStationCtrl(cfg, wakeupCnt, extraListenPortsCnt, fixedDelay = certainLatency, feedback = feedback))
val rsData = Module(new ReservationStationData(cfg, wakeupCnt, extraListenPortsCnt, fixedDelay = certainLatency, feedback = feedback))
rsCtrl.io.data <> rsData.io.ctrl
rsCtrl.io.redirect <> redirect // TODO: remove it
rsCtrl.io.numExist <> io.toCtrlBlock.numExist(i)
rsCtrl.io.enqCtrl <> io.fromCtrlBlock.enqIqCtrl(i)
rsData.io.enqData <> io.fromCtrlBlock.enqIqData(i)
rsData.io.redirect <> redirect
rsData.io.writeBackedData <> writeBackData
for ((x, y) <- rsData.io.extraListenPorts.zip(extraListenPorts)) {
x.valid := y.fire()
x.bits := y.bits
}
exeUnits(i).io.redirect <> redirect
exeUnits(i).io.fromInt <> rs.io.deq
rs.io.tlbFeedback := DontCare
exeUnits(i).io.fromInt <> rsData.io.deq
rsData.io.feedback := DontCare
rs.suggestName(s"rs_${cfg.name}")
rsCtrl.suggestName(s"rsc_${cfg.name}")
rsData.suggestName(s"rsd_${cfg.name}")
rs
rsData
})
for(rs <- reservationStations){
......@@ -220,4 +225,4 @@ class IntegerBlock
rf.addr := wb.bits.uop.pdest
rf.data := wb.bits.data
}
}
}
\ No newline at end of file
......@@ -9,7 +9,7 @@ import xiangshan.backend.exu._
import xiangshan.cache._
import xiangshan.mem._
import xiangshan.backend.fu.FenceToSbuffer
import xiangshan.backend.issue.ReservationStationNew
import xiangshan.backend.issue.{ReservationStationCtrl, ReservationStationData}
import xiangshan.backend.fu.FunctionUnit.{lduCfg, mouCfg, stuCfg}
class LsBlockToCtrlIO extends XSBundle {
......@@ -105,26 +105,30 @@ class MemBlock
println(s"${i}: exu:${cfg.name} wakeupCnt: ${wakeupCnt} extraListenPorts: ${extraListenPortsCnt} delay:${certainLatency} feedback:${feedback}")
val rs = Module(new ReservationStationNew(
cfg, wakeupCnt, extraListenPortsCnt, fixedDelay = certainLatency, feedback = feedback
))
val rsCtrl = Module(new ReservationStationCtrl(cfg, wakeupCnt, extraListenPortsCnt, fixedDelay = certainLatency, feedback = feedback))
val rsData = Module(new ReservationStationData(cfg, wakeupCnt, extraListenPortsCnt, fixedDelay = certainLatency, feedback = feedback))
rs.io.redirect <> redirect
rs.io.numExist <> io.toCtrlBlock.numExist(i)
rs.io.enqCtrl <> io.fromCtrlBlock.enqIqCtrl(i)
rs.io.enqData <> io.fromCtrlBlock.enqIqData(i)
rsCtrl.io.data <> rsData.io.ctrl
rsCtrl.io.redirect <> redirect // TODO: remove it
rsCtrl.io.numExist <> io.toCtrlBlock.numExist(i)
rsCtrl.io.enqCtrl <> io.fromCtrlBlock.enqIqCtrl(i)
rsData.io.enqData <> io.fromCtrlBlock.enqIqData(i)
rsData.io.redirect <> redirect
rs.io.writeBackedData <> writeBackData
for ((x, y) <- rs.io.extraListenPorts.zip(extraListenPorts)) {
rsData.io.writeBackedData <> writeBackData
for ((x, y) <- rsData.io.extraListenPorts.zip(extraListenPorts)) {
x.valid := y.fire()
x.bits := y.bits
}
rs.io.tlbFeedback := DontCare
// exeUnits(i).io.redirect <> redirect
// exeUnits(i).io.fromInt <> rsData.io.deq
rsData.io.feedback := DontCare
rs.suggestName(s"rs_${cfg.name}")
rsCtrl.suggestName(s"rsc_${cfg.name}")
rsData.suggestName(s"rsd_${cfg.name}")
rs
rsData
})
for(rs <- reservationStations){
......@@ -166,7 +170,7 @@ class MemBlock
// LoadUnit
for (i <- 0 until exuParameters.LduCnt) {
loadUnits(i).io.redirect <> io.fromCtrlBlock.redirect
loadUnits(i).io.tlbFeedback <> reservationStations(i).io.tlbFeedback
loadUnits(i).io.tlbFeedback <> reservationStations(i).io.feedback
loadUnits(i).io.dtlb <> dtlb.io.requestor(i)
// get input form dispatch
loadUnits(i).io.ldin <> reservationStations(i).io.deq
......@@ -184,7 +188,7 @@ class MemBlock
// StoreUnit
for (i <- 0 until exuParameters.StuCnt) {
storeUnits(i).io.redirect <> io.fromCtrlBlock.redirect
storeUnits(i).io.tlbFeedback <> reservationStations(exuParameters.LduCnt + i).io.tlbFeedback
storeUnits(i).io.tlbFeedback <> reservationStations(exuParameters.LduCnt + i).io.feedback
storeUnits(i).io.dtlb <> dtlb.io.requestor(exuParameters.LduCnt + i)
// get input form dispatch
storeUnits(i).io.stin <> reservationStations(exuParameters.LduCnt + i).io.deq
......@@ -232,6 +236,7 @@ class MemBlock
atomicsUnit.io.dtlb.resp.valid := false.B
atomicsUnit.io.dtlb.resp.bits := DontCare
atomicsUnit.io.dtlb.req.ready := dtlb.io.requestor(0).req.ready
// dispatch 0 takes priority
atomicsUnit.io.in.valid := st0_atomics
......@@ -251,7 +256,7 @@ class MemBlock
when(atomicsUnit.io.tlbFeedback.valid) {
assert(!storeUnits(0).io.tlbFeedback.valid)
atomicsUnit.io.tlbFeedback <> reservationStations(exuParameters.LduCnt + 0).io.tlbFeedback
atomicsUnit.io.tlbFeedback <> reservationStations(exuParameters.LduCnt + 0).io.feedback
}
atomicsUnit.io.dcache <> io.dcache.atomics
......@@ -269,4 +274,4 @@ class MemBlock
lsq.io.exceptionAddr.isStore := io.lsqio.exceptionAddr.isStore
io.lsqio.exceptionAddr.vaddr := Mux(atomicsUnit.io.exceptionAddr.valid, atomicsUnit.io.exceptionAddr.bits, lsq.io.exceptionAddr.vaddr)
}
}
\ No newline at end of file
package xiangshan.backend.exu
import chisel3._
......@@ -15,4 +16,17 @@ class AluExeUnit extends Exu(aluExeUnitCfg)
io.toInt.bits.redirectValid := alu.redirectOutValid
io.toInt.bits.redirect := alu.redirectOut
io.toInt.bits.brUpdate := alu.brUpdate
}
XSDebug(io.fromInt.valid || io.redirect.valid,
p"fromInt(${io.fromInt.valid} ${io.fromInt.ready}) toInt(${io.toInt.valid} ${io.toInt.ready})" +
p"Redirect:(${io.redirect.valid} ${io.redirect.bits.isException}${io.redirect.bits.isFlushPipe}${io.redirect.bits.isMisPred}${io.redirect.bits.isReplay}) roqIdx:${io.redirect.bits.roqIdx}\n",
)
XSDebug(io.fromInt.valid,
p"src1:${Hexadecimal(io.fromInt.bits.src1)} src2:${Hexadecimal(io.fromInt.bits.src2)} " +
p"src3:${Hexadecimal(io.fromInt.bits.src3)} func:${Binary(io.fromInt.bits.uop.ctrl.fuOpType)} " +
p"pc:${Hexadecimal(io.fromInt.bits.uop.cf.pc)} roqIdx:${io.fromInt.bits.uop.roqIdx}\n"
)
XSDebug(io.toInt.valid,
p"res:${Hexadecimal(io.toInt.bits.data)}\n"
)
}
\ No newline at end of file
......@@ -100,7 +100,7 @@ abstract class Exu(val config: ExuConfig) extends XSModule {
val src2 = in.bits.src2
val src3 = in.bits.src3
fu.io.in.valid := in.valid && sel
fu.io.in.valid := in.valid && sel && !in.bits.uop.roqIdx.needFlush(io.redirect)
fu.io.in.bits.uop := in.bits.uop
fu.io.in.bits.src.foreach(_ <> DontCare)
if (fuCfg.srcCnt > 0) {
......
......@@ -11,7 +11,10 @@ class FenceToSbuffer extends XSBundle {
val sbIsEmpty = Input(Bool())
}
class Fence extends FunctionUnit{
// class Fence extends FunctionUnit(FuConfig(
// /*FuType.fence, 1, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false,*/ latency = UncertainLatency()
// )){
class Fence extends FunctionUnit{ // TODO: check it
val sfence = IO(Output(new SfenceBundle))
val fencei = IO(Output(Bool()))
......@@ -43,7 +46,7 @@ class Fence extends FunctionUnit{
when (state === s_sb && valid && func === FenceOpType.fencei && !sbEmpty) { state := s_icache }
when (state === s_sb && valid && func === FenceOpType.sfence && !sbEmpty) { state := s_tlb }
when (state === s_sb && valid && func === FenceOpType.fence && !sbEmpty) { state := s_none }
when (state =/= s_sb && sbEmpty) { state := s_sb }
when (state =/= s_sb && sbEmpty) { state := s_sb }
assert(!(io.out.valid && io.out.bits.uop.ctrl.rfWen))
io.in.ready := state === s_sb
......@@ -54,4 +57,4 @@ class Fence extends FunctionUnit{
assert(!(valid || state =/= s_sb) || io.out.ready) // NOTE: fence instr must be the first(only one) instr, so io.out.ready must be true
XSDebug(valid || state=/=s_sb || io.out.valid, p"In(${io.in.valid} ${io.in.ready}) Out(${io.out.valid} ${io.out.ready}) state:${state} sbuffer(flush:${sbuffer} empty:${sbEmpty}) fencei:${fencei} sfence:${sfence} Inpc:0x${Hexadecimal(io.in.bits.uop.cf.pc)} InroqIdx:${io.in.bits.uop.roqIdx} Outpc:0x${Hexadecimal(io.out.bits.uop.cf.pc)} OutroqIdx:${io.out.bits.uop.roqIdx}\n")
}
}
\ No newline at end of file
......@@ -175,7 +175,8 @@ object FunctionUnit extends HasXSParameter {
val fenceCfg = FuConfig(
fuGen = fence _,
fuSel = (x: FunctionUnit) => x.io.in.bits.uop.ctrl.fuType === FuType.fence,
FuType.fence, 1, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false
FuType.fence, 1, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false,
UncertainLatency() // TODO: need rewrite latency structure, not just this value
)
val csrCfg = FuConfig(
......
......@@ -154,10 +154,8 @@ class TlbResp extends TlbBundle {
}
class TlbRequestIO() extends TlbBundle {
val req = Valid(new TlbReq)
val resp = Flipped(Valid(new TlbResp))
// override def cloneType: this.type = (new TlbRequestIO(Width)).asInstanceOf[this.type]
val req = DecoupledIO(new TlbReq)
val resp = Flipped(DecoupledIO(new TlbResp))
}
class BlockTlbRequestIO() extends TlbBundle {
......@@ -231,6 +229,7 @@ class TLB(Width: Int, isDtlb: Boolean) extends TlbModule with HasCSRConst{
2.U -> Cat(hitppn(i), reqAddr(i).off)
))
req(i).ready := resp(i).ready
resp(i).valid := valid(i)
resp(i).bits.paddr := Mux(vmEnable, paddr, SignExt(req(i).bits.vaddr, PAddrBits))
resp(i).bits.miss := miss(i)
......@@ -279,7 +278,7 @@ class TLB(Width: Int, isDtlb: Boolean) extends TlbModule with HasCSRConst{
}
// reset pf when pf hit
val pfHitReset = ParallelOR(widthMap{i => Mux(valid(i), VecInit(pfHitVec(i)).asUInt, 0.U) })
val pfHitReset = ParallelOR(widthMap{i => Mux(resp(i).fire(), VecInit(pfHitVec(i)).asUInt, 0.U) })
val pfHitRefill = ParallelOR(pfHitReset.asBools)
// refill
......@@ -356,8 +355,8 @@ class TLB(Width: Int, isDtlb: Boolean) extends TlbModule with HasCSRConst{
// Log
for(i <- 0 until Width) {
XSDebug(req(i).valid, p"req(${i.U}): ${req(i).bits}\n")
XSDebug(resp(i).valid, p"resp(${i.U}): ${resp(i).bits}\n")
XSDebug(req(i).valid, p"req(${i.U}): (${req(i).valid} ${req(i).ready}) ${req(i).bits}\n")
XSDebug(resp(i).valid, p"resp(${i.U}): (${resp(i).valid} ${resp(i).ready}) ${resp(i).bits}\n")
}
XSDebug(sfence.valid, p"Sfence: ${sfence}\n")
......@@ -412,27 +411,24 @@ object TLB {
if (!shouldBlock) { // dtlb
for (i <- 0 until width) {
tlb.io.requestor(i).req.valid := in(i).req.valid
tlb.io.requestor(i).req.bits := in(i).req.bits
in(i).req.ready := DontCare
in(i).resp.valid := tlb.io.requestor(i).resp.valid
in(i).resp.bits := tlb.io.requestor(i).resp.bits
tlb.io.requestor(i) <> in(i)
// tlb.io.requestor(i).req.valid := in(i).req.valid
// tlb.io.requestor(i).req.bits := in(i).req.bits
// in(i).req.ready := tlb.io.requestor(i).req.ready
// in(i).resp.valid := tlb.io.requestor(i).resp.valid
// in(i).resp.bits := tlb.io.requestor(i).resp.bits
// tlb.io.requestor(i).resp.ready := in(i).resp.ready
}
} else { // itlb
require(width == 1)
tlb.io.requestor(0).req.valid := in(0).req.valid
tlb.io.requestor(0).req.bits := in(0).req.bits
in(0).req.ready := !tlb.io.requestor(0).resp.bits.miss && in(0).resp.ready
// val pf = LookupTree(tlb.io.requestor(0).req.bits.cmd, List(
// TlbCmd.read -> tlb.io.requestor(0).resp.bits.excp.pf.ld,
// TlbCmd.write -> tlb.io.requestor(0).resp.bits.excp.pf.st,
// TlbCmd.exec -> tlb.io.requestor(0).resp.bits.excp.pf.instr
// ))
in(0).req.ready := !tlb.io.requestor(0).resp.bits.miss && in(0).resp.ready && tlb.io.requestor(0).req.ready
in(0).resp.valid := tlb.io.requestor(0).resp.valid && !tlb.io.requestor(0).resp.bits.miss
in(0).resp.bits := tlb.io.requestor(0).resp.bits
tlb.io.requestor(0).resp.ready := in(0).resp.ready
}
tlb.io.ptw
......
......@@ -459,4 +459,6 @@ class PTWImp(outer: PTW) extends PtwModule(outer){
XSDebug(memRespFire, p"mem resp fire rdata:0x${Hexadecimal(mem.d.bits.data)} Pte:${memPte}\n")
XSDebug(sfenceLatch, p"ptw has a flushed req waiting for resp... state:${state} mem.a(${mem.a.valid} ${mem.a.ready}) d($memValid} ${memRespReady})\n")
// TODO: add ptw perf cnt
}
......@@ -9,13 +9,17 @@ import scala.math.min
trait MicroBTBPatameter{
val nWays = 16
val offsetSize = 20
val lowerBitsSize = 20
val tagSize = 20
val extended_stat = false
}
class MicroBTB extends BasePredictor
with MicroBTBPatameter
{
val tagSize = VAddrBits - log2Ceil(PredictWidth) - 1
// val tagSize = VAddrBits - log2Ceil(PredictWidth) - 1
val untaggedBits = PredictWidth + 1
class MicroBTBResp extends Resp
{
......@@ -44,7 +48,7 @@ class MicroBTB extends BasePredictor
override val io = IO(new MicroBTBIO)
io.uBTBBranchInfo <> out_ubtb_br_info
def getTag(pc: UInt) = (pc >> (log2Ceil(PredictWidth) + 1)).asUInt()
def getTag(pc: UInt) = (pc >> untaggedBits)(tagSize-1, 0)
def getBank(pc: UInt) = pc(log2Ceil(PredictWidth) ,1)
class MicroBTBMeta extends XSBundle
......@@ -58,7 +62,7 @@ class MicroBTB extends BasePredictor
class MicroBTBEntry extends XSBundle
{
val offset = SInt(offsetSize.W)
val lower = UInt(lowerBitsSize.W)
}
// val uBTBMeta = RegInit((0.U).asTypeOf(Vec(nWays, Vec(PredictWidth, new MicroBTBMeta))))
......@@ -173,9 +177,9 @@ class MicroBTB extends BasePredictor
val read_resp = Wire(Vec(PredictWidth,new ReadRespEntry))
val read_bank_inOrder = VecInit((0 until PredictWidth).map(b => (read_req_basebank + b.U)(log2Up(PredictWidth)-1,0) ))
val isInNextRow = VecInit((0 until PredictWidth).map(_.U < read_req_basebank))
// val isInNextRow = VecInit((0 until PredictWidth).map(_.U < read_req_basebank))
(0 until PredictWidth).map{ b => metas(b).rtag := Mux(isInNextRow(b),read_req_tag + 1.U,read_req_tag) }
(0 until PredictWidth).map{ b => metas(b).rtag := read_req_tag }
val read_hit_ohs = read_bank_inOrder.map{ b => metas(b).hit_ohs }
val read_hit_vec = VecInit(read_hit_ohs.map{oh => ParallelOR(oh).asBool})
val read_hit_ways = VecInit(read_hit_ohs.map{oh => PriorityEncoder(oh)})
......@@ -193,7 +197,7 @@ class MicroBTB extends BasePredictor
read_resp(i).valid := read_hit_vec(i) && io.inMask(i)
read_resp(i).taken := read_resp(i).valid && uBTBMeta_resp(i).pred(1)
read_resp(i).is_Br := read_resp(i).valid && uBTBMeta_resp(i).is_Br
read_resp(i).target := ((io.pc.bits).asSInt + (i<<1).S + btb_resp(i).offset).asUInt
read_resp(i).target := Cat(io.pc.bits(VAddrBits-1, lowerBitsSize+1), btb_resp(i).asUInt, 0.U(1.W))
read_resp(i).is_RVC := read_resp(i).valid && uBTBMeta_resp(i).is_RVC
out_ubtb_br_info.hits(i) := read_hit_vec(i)
......@@ -250,7 +254,7 @@ class MicroBTB extends BasePredictor
val update_base_bank = getBank(update_fetch_pc)
val update_tag = getTag(update_br_pc)
val update_target = Mux(u.pd.isBr, u.brTarget, u.target)
val update_taget_offset = update_target.asSInt - update_br_pc.asSInt
val update_target_lower = update_target(lowerBitsSize, 1)
val update_is_BR_or_JAL = (u.pd.brType === BrType.branch) || (u.pd.brType === BrType.jal)
......@@ -260,12 +264,12 @@ class MicroBTB extends BasePredictor
//write btb target when miss prediction
// when(entry_write_valid)
// {
// uBTB(update_write_way)(update_bank).offset := update_taget_offset
// uBTB(update_write_way)(update_bank).offset := update_target_offset
// }
for (b <- 0 until PredictWidth) {
datas(b).wen := do_reset || (entry_write_valid && b.U === update_bank)
datas(b).wWay := Mux(do_reset, reset_way, update_write_way)
datas(b).wdata := Mux(do_reset, 0.U.asTypeOf(new MicroBTBEntry), update_taget_offset.asTypeOf(new MicroBTBEntry))
datas(b).wdata := Mux(do_reset, 0.U.asTypeOf(new MicroBTBEntry), update_target_lower.asTypeOf(new MicroBTBEntry))
}
......@@ -296,8 +300,8 @@ class MicroBTB extends BasePredictor
i.U,read_hit_vec(i),read_hit_ways(i),read_resp(i).valid,read_resp(i).is_RVC,read_resp(i).taken,read_resp(i).is_Br,read_resp(i).target,out_ubtb_br_info.writeWay(i))
}
XSDebug(meta_write_valid,"uBTB update: update | pc:0x%x | update hits:%b | | update_write_way:%d | update_bank: %d| update_br_index:%d | update_tag:%x | upadate_offset 0x%x\n "
,update_br_pc,update_hits,update_write_way,update_bank,update_br_idx,update_tag,update_taget_offset(offsetSize-1,0))
XSDebug(meta_write_valid,"uBTB update: update | pc:0x%x | update hits:%b | | update_write_way:%d | update_bank: %d| update_br_index:%d | update_tag:%x | update_lower 0x%x\n "
,update_br_pc,update_hits,update_write_way,update_bank,update_br_idx,update_tag,update_target_lower(lowerBitsSize-1,0))
XSDebug(meta_write_valid, "uBTB update: update_taken:%d | old_pred:%b | new_pred:%b\n",
update_taken, metas(update_bank).rpred,
Mux(!update_hits,
......@@ -306,6 +310,11 @@ class MicroBTB extends BasePredictor
))
}
if (extended_stat) {
val high_identical = update_target(VAddrBits-1, lowerBitsSize) =/= update_fetch_pc(VAddrBits-1, lowerBitsSize)
XSDebug(io.update.valid, "extended_stat: identical %d\n", high_identical)
}
//bypass:read-after-write
// for( b <- 0 until PredictWidth) {
......
......@@ -53,10 +53,10 @@ class LoadForwardQueryIO extends XSBundle {
val uop = Output(new MicroOp) // for replay
val pc = Output(UInt(VAddrBits.W)) //for debug
val valid = Output(Bool()) //for debug
val forwardMask = Input(Vec(8, Bool()))
val forwardData = Input(Vec(8, UInt(8.W)))
// val lqIdx = Output(UInt(LoadQueueIdxWidth.W))
val sqIdx = Output(new SqPtr)
}
}
\ No newline at end of file
......@@ -46,11 +46,9 @@ class StoreQueue extends XSModule with HasDCacheParameters with HasCircularQueue
val dataModule = Module(new LSQueueData(StoreQueueSize, StorePipelineWidth))
dataModule.io := DontCare
val allocated = RegInit(VecInit(List.fill(StoreQueueSize)(false.B))) // sq entry has been allocated
val valid = RegInit(VecInit(List.fill(StoreQueueSize)(false.B))) // data is valid
val datavalid = RegInit(VecInit(List.fill(StoreQueueSize)(false.B))) // non-mmio data is valid
val writebacked = RegInit(VecInit(List.fill(StoreQueueSize)(false.B))) // inst has been writebacked to CDB
val commited = Reg(Vec(StoreQueueSize, Bool())) // inst has been writebacked to CDB
val miss = Reg(Vec(StoreQueueSize, Bool())) // load inst missed, waiting for miss queue to accept miss request
val listening = Reg(Vec(StoreQueueSize, Bool())) // waiting for refill result
val commited = Reg(Vec(StoreQueueSize, Bool())) // inst has been commited by roq
val pending = Reg(Vec(StoreQueueSize, Bool())) // mmio pending: inst is an mmio inst, it will not be executed until it reachs the end of roq
val ringBufferHeadExtended = RegInit(0.U.asTypeOf(new SqPtr))
......@@ -70,8 +68,6 @@ class StoreQueue extends XSModule with HasDCacheParameters with HasCircularQueue
val enqDeqMask1 = tailMask ^ headMask
val enqDeqMask = Mux(ringBufferSameFlag, enqDeqMask1, ~enqDeqMask1)
// TODO: misc arbitor
// Enqueue at dispatch
val emptyEntries = StoreQueueSize.U - distanceBetween(ringBufferHeadExtended, ringBufferTailExtended)
XSDebug("(ready, valid): ")
......@@ -82,11 +78,9 @@ class StoreQueue extends XSModule with HasDCacheParameters with HasCircularQueue
when(io.dp1Req(i).fire()) {
uop(index) := io.dp1Req(i).bits
allocated(index) := true.B
valid(index) := false.B
datavalid(index) := false.B
writebacked(index) := false.B
commited(index) := false.B
miss(index) := false.B
listening(index) := false.B
pending(index) := false.B
}
val numTryEnqueue = offset +& io.dp1Req(i).valid
......@@ -108,9 +102,9 @@ class StoreQueue extends XSModule with HasDCacheParameters with HasCircularQueue
dataModule.io.wb(i).wen := false.B
when(io.storeIn(i).fire()) {
val stWbIndex = io.storeIn(i).bits.uop.sqIdx.value
valid(stWbIndex) := !io.storeIn(i).bits.mmio || io.storeIn(i).bits.uop.cf.exceptionVec.asUInt.orR
miss(stWbIndex) := io.storeIn(i).bits.miss
pending(stWbIndex) := io.storeIn(i).bits.mmio && !io.storeIn(i).bits.uop.cf.exceptionVec.asUInt.orR
val hasException = io.storeIn(i).bits.uop.cf.exceptionVec.asUInt.orR
datavalid(stWbIndex) := !io.storeIn(i).bits.mmio || hasException
pending(stWbIndex) := io.storeIn(i).bits.mmio && !hasException
val storeWbData = Wire(new LsqEntry)
storeWbData := DontCare
......@@ -124,13 +118,12 @@ class StoreQueue extends XSModule with HasDCacheParameters with HasCircularQueue
dataModule.io.wbWrite(i, stWbIndex, storeWbData)
dataModule.io.wb(i).wen := true.B
XSInfo("store write to sq idx %d pc 0x%x vaddr %x paddr %x data %x miss %x mmio %x roll %x exc %x\n",
XSInfo("store write to sq idx %d pc 0x%x vaddr %x paddr %x data %x mmio %x roll %x exc %x\n",
io.storeIn(i).bits.uop.sqIdx.value,
io.storeIn(i).bits.uop.cf.pc,
io.storeIn(i).bits.vaddr,
io.storeIn(i).bits.paddr,
io.storeIn(i).bits.data,
io.storeIn(i).bits.miss,
io.storeIn(i).bits.mmio,
io.storeIn(i).bits.rollback,
io.storeIn(i).bits.uop.cf.exceptionVec.asUInt
......@@ -185,15 +178,15 @@ class StoreQueue extends XSModule with HasDCacheParameters with HasCircularQueue
}
// select the last writebacked instruction
val validStoreVec = VecInit((0 until StoreQueueSize).map(i => !(allocated(i) && valid(i))))
val validStoreVec = VecInit((0 until StoreQueueSize).map(i => !(allocated(i) && datavalid(i))))
val storeNotValid = SqPtr(false.B, getFirstOne(validStoreVec, tailMask))
val storeValidIndex = (storeNotValid - 1.U).value
io.oldestStore.valid := allocated(ringBufferTailExtended.value) && valid(ringBufferTailExtended.value) && !commited(storeValidIndex)
io.oldestStore.valid := allocated(ringBufferTailExtended.value) && datavalid(ringBufferTailExtended.value) && !commited(storeValidIndex)
io.oldestStore.bits := uop(storeValidIndex).roqIdx
// writeback up to 2 store insts to CDB
// choose the first two valid store requests from deqPtr
val storeWbSelVec = VecInit((0 until StoreQueueSize).map(i => allocated(i) && valid(i) && !writebacked(i)))
val storeWbSelVec = VecInit((0 until StoreQueueSize).map(i => allocated(i) && datavalid(i) && !writebacked(i)))
val (storeWbValid, storeWbSel) = selectFirstTwo(storeWbSelVec, tailMask)
(0 until StorePipelineWidth).map(i => {
......@@ -215,6 +208,7 @@ class StoreQueue extends XSModule with HasDCacheParameters with HasCircularQueue
// remove retired insts from sq, add retired store to sbuffer
// move tailPtr
// TailPtr slow recovery: recycle bubbles in store queue
// allocatedMask: dequeuePtr can go to the next 1-bit
val allocatedMask = VecInit((0 until StoreQueueSize).map(i => allocated(i) || !enqDeqMask(i)))
// find the first one from deqPtr (ringBufferTail)
......@@ -222,6 +216,16 @@ class StoreQueue extends XSModule with HasDCacheParameters with HasCircularQueue
val nextTail = Mux(Cat(allocatedMask).orR, nextTail1, ringBufferHeadExtended)
ringBufferTailExtended := nextTail
// TailPtr fast recovery
val tailRecycle = VecInit(List(
io.uncache.resp.fire() || io.sbuffer(0).fire(),
io.sbuffer(1).fire()
))
when(tailRecycle.asUInt.orR){
ringBufferTailExtended := ringBufferTailExtended + PopCount(tailRecycle.asUInt)
}
// load forward query
// check over all lq entries and forward data from the first matched store
(0 until LoadPipelineWidth).map(i => {
......@@ -239,7 +243,7 @@ class StoreQueue extends XSModule with HasDCacheParameters with HasCircularQueue
val forwardMask = ((1.U((StoreQueueSize + 1).W)) << io.forward(i).sqIdx.value).asUInt - 1.U
val storeWritebackedVec = WireInit(VecInit(Seq.fill(StoreQueueSize)(false.B)))
for (j <- 0 until StoreQueueSize) {
storeWritebackedVec(j) := valid(j) && allocated(j) // all valid terms need to be checked
storeWritebackedVec(j) := datavalid(j) && allocated(j) // all datavalid terms need to be checked
}
val needForward1 = Mux(differentFlag, ~tailMask, tailMask ^ forwardMask) & storeWritebackedVec.asUInt
val needForward2 = Mux(differentFlag, forwardMask, 0.U(StoreQueueSize.W)) & storeWritebackedVec.asUInt
......@@ -258,80 +262,31 @@ class StoreQueue extends XSModule with HasDCacheParameters with HasCircularQueue
io.forward(i).forwardData := dataModule.io.forward(i).forwardData
})
// CommitedStoreQueue for timing opt
// send commited store inst to sbuffer
// select up to 2 writebacked store insts
val commitedStoreQueue = Module(new MIMOQueue(
UInt(log2Up(StoreQueueSize).W),
entries = 64, //FIXME
inCnt = 6,
outCnt = 2,
mem = false,
perf = true
))
commitedStoreQueue.io.flush := false.B
// When store commited, mark it as commited (will not be influenced by redirect),
// then add store's sq ptr into commitedStoreQueue
(0 until CommitWidth).map(i => {
when(storeCommit(i)) {
commited(mcommitIdx(i)) := true.B
XSDebug("store commit %d: idx %d %x\n", i.U, mcommitIdx(i), uop(mcommitIdx(i)).cf.pc)
}
commitedStoreQueue.io.enq(i).valid := storeCommit(i)
commitedStoreQueue.io.enq(i).bits := mcommitIdx(i)
// We assume commitedStoreQueue.io.enq(i).ready === true.B,
// for commitedStoreQueue.size = 64
})
class SbufferCandidateEntry extends XSBundle{
val sbuffer = new DCacheWordReq
val sqIdx = UInt(log2Up(StoreQueueSize).W)
}
val ensbufferCandidateQueue = Module(new MIMOQueue(
new SbufferCandidateEntry,
entries = 2,
inCnt = 2,
outCnt = 2,
mem = false,
perf = true
))
ensbufferCandidateQueue.io.flush := false.B
val sbufferCandidate = Wire(Vec(2, Decoupled(new SbufferCandidateEntry)))
(0 until 2).map(i => {
val ptr = commitedStoreQueue.io.deq(i).bits
val ptr = (ringBufferTailExtended + i.U).value
val mmio = dataModule.io.rdata(ptr).mmio
sbufferCandidate(i).valid := commitedStoreQueue.io.deq(i).valid && !mmio
sbufferCandidate(i).bits.sqIdx := ptr
sbufferCandidate(i).bits.sbuffer.cmd := MemoryOpConstants.M_XWR
sbufferCandidate(i).bits.sbuffer.addr := dataModule.io.rdata(ptr).paddr
sbufferCandidate(i).bits.sbuffer.data := dataModule.io.rdata(ptr).data
sbufferCandidate(i).bits.sbuffer.mask := dataModule.io.rdata(ptr).mask
sbufferCandidate(i).bits.sbuffer.meta := DontCare
sbufferCandidate(i).bits.sbuffer.meta.tlb_miss := false.B
sbufferCandidate(i).bits.sbuffer.meta.uop := DontCare
sbufferCandidate(i).bits.sbuffer.meta.mmio := mmio
sbufferCandidate(i).bits.sbuffer.meta.mask := dataModule.io.rdata(ptr).mask
when(mmio && commitedStoreQueue.io.deq(i).valid) {
io.sbuffer(i).valid := allocated(ptr) && commited(ptr) && !mmio
io.sbuffer(i).bits.cmd := MemoryOpConstants.M_XWR
io.sbuffer(i).bits.addr := dataModule.io.rdata(ptr).paddr
io.sbuffer(i).bits.data := dataModule.io.rdata(ptr).data
io.sbuffer(i).bits.mask := dataModule.io.rdata(ptr).mask
io.sbuffer(i).bits.meta := DontCare
io.sbuffer(i).bits.meta.tlb_miss := false.B
io.sbuffer(i).bits.meta.uop := DontCare
io.sbuffer(i).bits.meta.mmio := mmio
io.sbuffer(i).bits.meta.mask := dataModule.io.rdata(ptr).mask
when(io.sbuffer(i).fire()) {
allocated(ptr) := false.B
}
commitedStoreQueue.io.deq(i).ready := sbufferCandidate(i).fire() || mmio
sbufferCandidate(i).ready := ensbufferCandidateQueue.io.enq(i).ready
ensbufferCandidateQueue.io.enq(i).valid := sbufferCandidate(i).valid
ensbufferCandidateQueue.io.enq(i).bits.sqIdx := sbufferCandidate(i).bits.sqIdx
ensbufferCandidateQueue.io.enq(i).bits.sbuffer := sbufferCandidate(i).bits.sbuffer
ensbufferCandidateQueue.io.deq(i).ready := io.sbuffer(i).fire()
io.sbuffer(i).valid := ensbufferCandidateQueue.io.deq(i).valid
io.sbuffer(i).bits := ensbufferCandidateQueue.io.deq(i).bits.sbuffer
// update sq meta if store inst is send to sbuffer
when(ensbufferCandidateQueue.io.deq(i).valid && io.sbuffer(i).ready) {
allocated(ensbufferCandidateQueue.io.deq(i).bits.sqIdx) := false.B
XSDebug("sbuffer "+i+" fire: ptr %d\n", ptr)
}
})
......@@ -366,7 +321,7 @@ class StoreQueue extends XSModule with HasDCacheParameters with HasCircularQueue
}
when(io.uncache.resp.fire()){
valid(ringBufferTail) := true.B
datavalid(ringBufferTail) := true.B // will be writeback to CDB in the next cycle
// TODO: write back exception info
}
......@@ -390,10 +345,8 @@ class StoreQueue extends XSModule with HasDCacheParameters with HasCircularQueue
needCancel(i) := uop(i).roqIdx.needFlush(io.brqRedirect) && allocated(i) && !commited(i)
when(needCancel(i)) {
when(io.brqRedirect.bits.isReplay){
valid(i) := false.B
datavalid(i) := false.B
writebacked(i) := false.B
listening(i) := false.B
miss(i) := false.B
pending(i) := false.B
}.otherwise{
allocated(i) := false.B
......@@ -419,11 +372,9 @@ class StoreQueue extends XSModule with HasDCacheParameters with HasCircularQueue
if (i % 4 == 0) XSDebug("")
XSDebug(false, true.B, "%x [%x] ", uop(i).cf.pc, dataModule.io.rdata(i).paddr)
PrintFlag(allocated(i), "a")
PrintFlag(allocated(i) && valid(i), "v")
PrintFlag(allocated(i) && datavalid(i), "v")
PrintFlag(allocated(i) && writebacked(i), "w")
PrintFlag(allocated(i) && commited(i), "c")
PrintFlag(allocated(i) && miss(i), "m")
PrintFlag(allocated(i) && listening(i), "l")
PrintFlag(allocated(i) && pending(i), "p")
XSDebug(false, true.B, " ")
if (i % 4 == 3 || i == StoreQueueSize - 1) XSDebug(false, true.B, "\n")
......
......@@ -46,6 +46,7 @@ class AtomicsUnit extends XSModule with MemoryOpConstants{
io.dtlb.req.valid := false.B
io.dtlb.req.bits := DontCare
io.dtlb.resp.ready := false.B
io.flush_sbuffer.valid := false.B
......@@ -75,11 +76,12 @@ class AtomicsUnit extends XSModule with MemoryOpConstants{
io.dtlb.req.valid := true.B
io.dtlb.req.bits.vaddr := in.src1
io.dtlb.req.bits.roqIdx := in.uop.roqIdx
io.dtlb.resp.ready := true.B
val is_lr = in.uop.ctrl.fuOpType === LSUOpType.lr_w || in.uop.ctrl.fuOpType === LSUOpType.lr_d
io.dtlb.req.bits.cmd := Mux(is_lr, TlbCmd.read, TlbCmd.write)
io.dtlb.req.bits.debug.pc := in.uop.cf.pc
when(io.dtlb.resp.valid && !io.dtlb.resp.bits.miss){
when(io.dtlb.resp.fire && !io.dtlb.resp.bits.miss){
// exception handling
val addrAligned = LookupTree(in.uop.ctrl.fuOpType(1,0), List(
"b00".U -> true.B, //b
......@@ -143,7 +145,7 @@ class AtomicsUnit extends XSModule with MemoryOpConstants{
LSUOpType.amomaxu_d -> M_XA_MAXU
))
io.dcache.req.bits.addr := paddr
io.dcache.req.bits.addr := paddr
io.dcache.req.bits.data := genWdata(in.src2, in.uop.ctrl.fuOpType(1,0))
// TODO: atomics do need mask: fix mask
io.dcache.req.bits.mask := genWmask(paddr, in.uop.ctrl.fuOpType(1,0))
......@@ -221,4 +223,4 @@ class AtomicsUnit extends XSModule with MemoryOpConstants{
when(io.redirect.valid){
atom_override_xtval := false.B
}
}
}
\ No newline at end of file
......@@ -22,8 +22,8 @@ class LoadUnit_S0 extends XSModule {
val in = Flipped(Decoupled(new ExuInput))
val out = Decoupled(new LsPipelineBundle)
val redirect = Flipped(ValidIO(new Redirect))
val dtlbReq = Valid(new TlbReq)
val dtlbResp = Flipped(Valid(new TlbResp))
val dtlbReq = DecoupledIO(new TlbReq)
val dtlbResp = Flipped(DecoupledIO(new TlbResp))
val tlbFeedback = ValidIO(new TlbFeedback)
val dcacheReq = DecoupledIO(new DCacheLoadReq)
})
......@@ -40,6 +40,7 @@ class LoadUnit_S0 extends XSModule {
io.dtlbReq.bits.cmd := TlbCmd.read
io.dtlbReq.bits.roqIdx := s0_uop.roqIdx
io.dtlbReq.bits.debug.pc := s0_uop.cf.pc
io.dtlbResp.ready := io.out.ready // TODO: check it: io.out.fire()?
// feedback tlb result to RS
// Note: can be moved to s1
......@@ -104,7 +105,7 @@ class LoadUnit_S1 extends XSModule {
val s1_uop = io.in.bits.uop
val s1_paddr = io.in.bits.paddr
val s1_tlb_miss = io.in.bits.tlbMiss
val s1_mmio = !s1_tlb_miss && AddressSpace.isMMIO(s1_paddr)
val s1_mmio = !s1_tlb_miss && AddressSpace.isMMIO(s1_paddr) && !io.out.bits.uop.cf.exceptionVec.asUInt.orR
val s1_mask = io.in.bits.mask
io.out.bits := io.in.bits // forwardXX field will be updated in s1
......@@ -293,4 +294,4 @@ class LoadUnit extends XSModule {
when(io.ldout.fire()){
XSDebug("ldout %x iw %x fw %x\n", io.ldout.bits.uop.cf.pc, io.ldout.bits.uop.ctrl.rfWen, io.ldout.bits.uop.ctrl.fpWen)
}
}
}
\ No newline at end of file
......@@ -58,6 +58,7 @@ class StoreUnit extends XSModule {
io.dtlb.req.bits.cmd := TlbCmd.write
io.dtlb.req.bits.roqIdx := io.stin.bits.uop.roqIdx
io.dtlb.req.bits.debug.pc := io.stin.bits.uop.cf.pc
io.dtlb.resp.ready := s2_out.ready
s2_out.bits := DontCare
s2_out.bits.vaddr := saddr
......@@ -134,4 +135,4 @@ class StoreUnit extends XSModule {
// update store buffer according to store fill buffer
}
}
\ No newline at end of file
......@@ -15,6 +15,7 @@ static inline void print_help(const char *file) {
printf("\n");
printf(" -s, --seed=NUM use this seed\n");
printf(" -C, --max-cycles=NUM execute at most NUM cycles\n");
printf(" -I, --max-instr=NUM execute at most NUM instructions\n");
printf(" -i, --image=FILE run with this image file\n");
printf(" -b, --log-begin=NUM display log from NUM th cycle\n");
printf(" -e, --log-end=NUM stop display log at NUM th cycle\n");
......@@ -32,6 +33,7 @@ inline EmuArgs parse_args(int argc, const char *argv[]) {
{ "dump-wave", 0, NULL, 0 },
{ "seed", 1, NULL, 's' },
{ "max-cycles", 1, NULL, 'C' },
{ "max-instr", 1, NULL, 'I' },
{ "image", 1, NULL, 'i' },
{ "log-begin", 1, NULL, 'b' },
{ "log-end", 1, NULL, 'e' },
......@@ -41,7 +43,7 @@ inline EmuArgs parse_args(int argc, const char *argv[]) {
int o;
while ( (o = getopt_long(argc, const_cast<char *const*>(argv),
"-s:C:hi:m:b:e:", long_options, &long_index)) != -1) {
"-s:C:I:hi:m:b:e:", long_options, &long_index)) != -1) {
switch (o) {
case 0:
switch (long_index) {
......@@ -59,6 +61,7 @@ inline EmuArgs parse_args(int argc, const char *argv[]) {
}
break;
case 'C': args.max_cycles = atoll(optarg); break;
case 'I': args.max_instr = atoll(optarg); break;
case 'i': args.image = optarg; break;
case 'b': args.log_begin = atoll(optarg); break;
case 'e': args.log_end = atoll(optarg); break;
......@@ -122,9 +125,8 @@ Emulator::Emulator(int argc, const char *argv[]):
}
Emulator::~Emulator() {
#ifdef WITH_DRAMSIM3
dramsim3_finish();
#endif
ram_finish();
#ifdef VM_SAVABLE
snapshot_slot[0].save();
snapshot_slot[1].save();
......@@ -222,12 +224,13 @@ inline void Emulator::single_cycle() {
cycles ++;
}
uint64_t Emulator::execute(uint64_t n) {
uint64_t Emulator::execute(uint64_t max_cycle, uint64_t max_instr) {
extern void poll_event(void);
extern uint32_t uptime(void);
uint32_t lasttime_poll = 0;
uint32_t lasttime_snapshot = 0;
uint64_t lastcommit = n;
uint64_t lastcommit = max_cycle;
uint64_t instr_left_last_cycle = max_instr;
const int stuck_limit = 2000;
uint32_t wdst[DIFFTEST_WIDTH];
......@@ -240,14 +243,19 @@ uint64_t Emulator::execute(uint64_t n) {
diff.wdata = wdata;
diff.wdst = wdst;
while (trapCode == STATE_RUNNING && n > 0) {
while (trapCode == STATE_RUNNING) {
if (!(max_cycle > 0 && max_instr > 0 && instr_left_last_cycle >= max_instr /* handle overflow */)) {
trapCode = STATE_LIMIT_EXCEEDED;
break;
}
single_cycle();
n --;
max_cycle --;
if (dut_ptr->io_trap_valid) trapCode = dut_ptr->io_trap_code;
if (trapCode != STATE_RUNNING) break;
if (lastcommit - n > stuck_limit && hascommit) {
if (lastcommit - max_cycle > stuck_limit && hascommit) {
eprintf("No instruction commits for %d cycles, maybe get stuck\n"
"(please also check whether a fence.i instruction requires more than %d cycles to flush the icache)\n",
stuck_limit, stuck_limit);
......@@ -283,7 +291,11 @@ uint64_t Emulator::execute(uint64_t n) {
if (difftest_step(&diff)) {
trapCode = STATE_ABORT;
}
lastcommit = n;
lastcommit = max_cycle;
// update instr_cnt
instr_left_last_cycle = max_instr;
max_instr -= diff.commit;
}
uint32_t t = uptime();
......@@ -355,6 +367,9 @@ void Emulator::display_trapinfo() {
case STATE_ABORT:
eprintf(ANSI_COLOR_RED "ABORT at pc = 0x%" PRIx64 "\n" ANSI_COLOR_RESET, pc);
break;
case STATE_LIMIT_EXCEEDED:
eprintf(ANSI_COLOR_YELLOW "EXCEEDING CYCLE/INSTR LIMIT at pc = 0x%" PRIx64 "\n" ANSI_COLOR_RESET, pc);
break;
default:
eprintf(ANSI_COLOR_RED "Unknown trap code: %d\n", trapCode);
}
......
......@@ -9,6 +9,7 @@
struct EmuArgs {
uint32_t seed;
uint64_t max_cycles;
uint64_t max_instr;
uint64_t log_begin, log_end;
const char *image;
const char *snapshot_path;
......@@ -17,6 +18,7 @@ struct EmuArgs {
EmuArgs() {
seed = 0;
max_cycles = -1;
max_instr = -1;
log_begin = 1;
log_end = -1;
snapshot_path = NULL;
......@@ -38,6 +40,7 @@ class Emulator {
STATE_GOODTRAP = 0,
STATE_BADTRAP,
STATE_ABORT,
STATE_LIMIT_EXCEEDED,
STATE_RUNNING = -1
};
......@@ -60,7 +63,7 @@ class Emulator {
public:
Emulator(int argc, const char *argv[]);
~Emulator();
uint64_t execute(uint64_t n);
uint64_t execute(uint64_t max_cycle, uint64_t max_instr);
uint64_t get_cycles() const { return cycles; }
EmuArgs get_args() const { return args; }
bool is_good_trap() { return trapCode == STATE_GOODTRAP; };
......
......@@ -19,7 +19,7 @@ int main(int argc, const char** argv) {
};
auto args = emu->get_args();
uint64_t cycles = emu->execute(args.max_cycles);
uint64_t cycles = emu->execute(args.max_cycles, args.max_instr);
bool is_good_trap = emu->is_good_trap();
delete emu;
......
#include <sys/mman.h>
#include <zlib.h>
#include "common.h"
#include "ram.h"
#define RAMSIZE (128 * 1024 * 1024)
#define RAMSIZE (256 * 1024 * 1024UL)
#ifdef WITH_DRAMSIM3
#include "cosimulation.h"
CoDRAMsim3 *dram = NULL;
#endif
static uint64_t ram[RAMSIZE / sizeof(uint64_t)];
static uint64_t *ram;
static long img_size = 0;
void* get_img_start() { return &ram[0]; }
long get_img_size() { return img_size; }
void* get_ram_start() { return &ram[0]; }
long get_ram_size() { return RAMSIZE; }
#ifdef TLB_UNITTEST
void addpageSv39() {
//three layers
//addr range: 0x0000000080000000 - 0x0000000088000000 for 128MB from 2GB - 2GB128MB
......@@ -97,31 +101,100 @@ void addpageSv39() {
memcpy((char *)ram+(RAMSIZE-PAGESIZE*(PTENUM+PDENUM)), pde, PAGESIZE*PDENUM);
memcpy((char *)ram+(RAMSIZE-PAGESIZE*PTENUM), pte, PAGESIZE*PTENUM);
}
#endif
void init_ram(const char *img) {
assert(img != NULL);
FILE *fp = fopen(img, "rb");
if (fp == NULL) {
printf("Can not open '%s'\n", img);
// Return whether the file is a gz file
int isGzFile(const char *img) {
assert(img != NULL && strlen(img) >= 4);
return !strcmp(img + (strlen(img) - 3), ".gz");
}
// Read binary from .gz file
int readFromGz(void* ptr, const char *file_name) {
gzFile compressed_mem = gzopen(file_name, "rb");
if(compressed_mem == NULL) {
printf("Can't open compressed binary file '%s'", file_name);
return -1;
}
uint64_t curr_size = 0;
// read 16KB each time
const uint32_t chunk_size = 16384;
if ((RAMSIZE % chunk_size) != 0) {
printf("RAMSIZE must be divisible by chunk_size\n");
assert(0);
}
uint64_t *temp_page = new uint64_t[chunk_size];
uint64_t *pmem_current = (uint64_t *)ptr;
while (curr_size < RAMSIZE) {
uint32_t bytes_read = gzread(compressed_mem, temp_page, chunk_size);
if (bytes_read == 0) { break; }
assert(bytes_read % sizeof(uint64_t) == 0);
for (uint32_t x = 0; x < bytes_read / sizeof(uint64_t); x++) {
if (*(temp_page + x) != 0) {
pmem_current = (uint64_t*)((uint8_t*)ptr + curr_size + x * sizeof(uint64_t));
*pmem_current = *(temp_page + x);
}
}
curr_size += bytes_read;
}
// printf("Read 0x%lx bytes from gz stream in total.\n", curr_size);
delete [] temp_page;
if(gzclose(compressed_mem)) {
printf("Error closing '%s'\n", file_name);
return -1;
}
return curr_size;
}
void init_ram(const char *img) {
assert(img != NULL);
printf("The image is %s\n", img);
fseek(fp, 0, SEEK_END);
img_size = ftell(fp);
if (img_size > RAMSIZE) {
img_size = RAMSIZE;
// initialize memory using Linux mmap
printf("Using simulated %luMB RAM\n", RAMSIZE / (1024 * 1024));
ram = (uint64_t *)mmap(NULL, RAMSIZE, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
if (ram == (uint64_t *)MAP_FAILED) {
printf("Cound not mmap 0x%lx bytes\n", RAMSIZE);
assert(0);
}
int ret;
if (isGzFile(img)) {
printf("Gzip file detected and loading image from extracted gz file\n");
img_size = readFromGz(ram, img);
assert(img_size >= 0);
}
else {
FILE *fp = fopen(img, "rb");
if (fp == NULL) {
printf("Can not open '%s'\n", img);
assert(0);
}
fseek(fp, 0, SEEK_END);
img_size = ftell(fp);
if (img_size > RAMSIZE) {
img_size = RAMSIZE;
}
fseek(fp, 0, SEEK_SET);
ret = fread(ram, img_size, 1, fp);
fseek(fp, 0, SEEK_SET);
int ret = fread(ram, img_size, 1, fp);
assert(ret == 1);
fclose(fp);
assert(ret == 1);
fclose(fp);
}
#ifdef TLB_UNITTEST
//new add
addpageSv39();
//new end
#endif
#ifdef WITH_DRAMSIM3
#if !defined(DRAMSIM3_CONFIG) || !defined(DRAMSIM3_OUTDIR)
......@@ -133,6 +206,13 @@ void init_ram(const char *img) {
}
void ram_finish() {
munmap(ram, RAMSIZE);
#ifdef WITH_DRAMSIM3
dramsim3_finish();
#endif
}
extern "C" uint64_t ram_read_helper(uint8_t en, uint64_t rIdx) {
if (en && rIdx >= RAMSIZE / sizeof(uint64_t)) {
printf("ERROR: ram idx = 0x%lx out of bound!\n", rIdx);
......
......@@ -3,8 +3,8 @@
#include "common.h"
// #define WITH_DRAMSIM3
void init_ram(const char *img);
void ram_finish();
#ifdef WITH_DRAMSIM3
// 4*64 bits
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册