提交 4142e72c 编写于 作者: W William Wang

Merge remote-tracking branch 'origin/master' into opt-roq-timing

......@@ -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)"
......
......@@ -4,7 +4,7 @@ import chisel3._
import chisel3.util._
import xiangshan._
import xiangshan.backend.decode.{DecodeBuffer, DecodeStage}
import xiangshan.backend.rename.Rename
import xiangshan.backend.rename.{Rename, BusyTable}
import xiangshan.backend.brq.Brq
import xiangshan.backend.dispatch.Dispatch
import xiangshan.backend.exu._
......@@ -59,9 +59,8 @@ class CtrlBlock extends XSModule {
val decBuf = Module(new DecodeBuffer)
val rename = Module(new Rename)
val dispatch = Module(new Dispatch)
// TODO: move busyTable to dispatch1
// val fpBusyTable = Module(new BusyTable(NRFpReadPorts, NRFpWritePorts))
// val intBusyTable = Module(new BusyTable(NRIntReadPorts, NRIntWritePorts))
val intBusyTable = Module(new BusyTable(NRIntReadPorts, NRIntWritePorts))
val fpBusyTable = Module(new BusyTable(NRFpReadPorts, NRFpWritePorts))
val roqWbSize = NRIntWritePorts + NRFpWritePorts + exuParameters.StuCnt + 1
......@@ -99,14 +98,6 @@ class CtrlBlock extends XSModule {
rename.io.redirect <> redirect
rename.io.roqCommits <> roq.io.commits
// they should be moved to busytables
rename.io.wbIntResults <> io.fromIntBlock.wbRegs
rename.io.wbFpResults <> io.fromFpBlock.wbRegs
rename.io.intRfReadAddr <> dispatch.io.readIntRf.map(_.addr)
rename.io.fpRfReadAddr <> dispatch.io.readFpRf.map(_.addr)
rename.io.intPregRdy <> dispatch.io.intPregRdy
rename.io.fpPregRdy <> dispatch.io.fpPregRdy
rename.io.replayPregReq <> dispatch.io.replayPregReq
rename.io.out <> dispatch.io.fromRename
dispatch.io.redirect <> redirect
......@@ -121,11 +112,39 @@ class CtrlBlock extends XSModule {
)
dispatch.io.readIntRf <> io.toIntBlock.readRf
dispatch.io.readFpRf <> io.toFpBlock.readRf
dispatch.io.allocPregs.zipWithIndex.foreach { case (preg, i) =>
intBusyTable.io.allocPregs(i).valid := preg.isInt
fpBusyTable.io.allocPregs(i).valid := preg.isFp
intBusyTable.io.allocPregs(i).bits := preg.preg
fpBusyTable.io.allocPregs(i).bits := preg.preg
}
dispatch.io.numExist <> io.fromIntBlock.numExist ++ io.fromFpBlock.numExist ++ io.fromLsBlock.numExist
dispatch.io.enqIQCtrl <> io.toIntBlock.enqIqCtrl ++ io.toFpBlock.enqIqCtrl ++ io.toLsBlock.enqIqCtrl
dispatch.io.enqIQData <> io.toIntBlock.enqIqData ++ io.toFpBlock.enqIqData ++ io.toLsBlock.enqIqData
val flush = redirect.valid && (redirect.bits.isException || redirect.bits.isFlushPipe)
fpBusyTable.io.flush := flush
intBusyTable.io.flush := flush
for((wb, setPhyRegRdy) <- io.fromIntBlock.wbRegs.zip(intBusyTable.io.wbPregs)){
setPhyRegRdy.valid := wb.valid && wb.bits.uop.ctrl.rfWen && (wb.bits.uop.ctrl.ldest =/= 0.U)
setPhyRegRdy.bits := wb.bits.uop.pdest
}
for((wb, setPhyRegRdy) <- io.fromFpBlock.wbRegs.zip(fpBusyTable.io.wbPregs)){
setPhyRegRdy.valid := wb.valid && wb.bits.uop.ctrl.fpWen
setPhyRegRdy.bits := wb.bits.uop.pdest
}
intBusyTable.io.rfReadAddr <> dispatch.io.readIntRf.map(_.addr)
intBusyTable.io.pregRdy <> dispatch.io.intPregRdy
fpBusyTable.io.rfReadAddr <> dispatch.io.readFpRf.map(_.addr)
fpBusyTable.io.pregRdy <> dispatch.io.fpPregRdy
for(i <- 0 until ReplayWidth){
intBusyTable.io.replayPregs(i).valid := dispatch.io.replayPregReq(i).isInt
fpBusyTable.io.replayPregs(i).valid := dispatch.io.replayPregReq(i).isFp
intBusyTable.io.replayPregs(i).bits := dispatch.io.replayPregReq(i).preg
fpBusyTable.io.replayPregs(i).bits := dispatch.io.replayPregReq(i).preg
}
roq.io.memRedirect <> io.fromLsBlock.replay
roq.io.brqRedirect <> brq.io.redirect
roq.io.dp1Req <> dispatch.io.toRoq
......
......@@ -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
......@@ -45,6 +45,7 @@ class Dispatch extends XSModule {
val fpPregRdy = Vec(NRFpReadPorts, Input(Bool()))
// replay: set preg status to not ready
val replayPregReq = Output(Vec(ReplayWidth, new ReplayPregReq))
val allocPregs = Vec(RenameWidth, Output(new ReplayPregReq))
// to reservation stations
val numExist = Input(Vec(exuParameters.ExuCnt, UInt(log2Ceil(IssQueSize).W)))
val enqIQCtrl = Vec(exuParameters.ExuCnt, DecoupledIO(new MicroOp))
......@@ -71,6 +72,7 @@ class Dispatch extends XSModule {
dispatch1.io.toIntDq <> intDq.io.enq
dispatch1.io.toFpDq <> fpDq.io.enq
dispatch1.io.toLsDq <> lsDq.io.enq
dispatch1.io.allocPregs <> io.allocPregs
// dispatch queue: queue uops and dispatch them to different reservation stations or issue queues
// it may cancel the uops
......
......@@ -22,6 +22,7 @@ class Dispatch1 extends XSModule {
val toLsq = Vec(RenameWidth, DecoupledIO(new MicroOp))
// get LsIdx
val lsIdx = Input(Vec(RenameWidth, new LSIdx))
val allocPregs = Vec(RenameWidth, Output(new ReplayPregReq))
// to dispatch queue
val toIntDq = Vec(dpParams.DqEnqWidth, DecoupledIO(new MicroOp))
val toFpDq = Vec(dpParams.DqEnqWidth, DecoupledIO(new MicroOp))
......@@ -147,6 +148,10 @@ class Dispatch1 extends XSModule {
*/
val readyVector = (0 until RenameWidth).map(i => !io.fromRename(i).valid || io.recv(i))
for (i <- 0 until RenameWidth) {
io.allocPregs(i).isInt := io.fromRename(i).valid && io.fromRename(i).bits.ctrl.rfWen && (io.fromRename(i).bits.ctrl.ldest =/= 0.U)
io.allocPregs(i).isFp := io.fromRename(i).valid && io.fromRename(i).bits.ctrl.fpWen
io.allocPregs(i).preg := io.fromRename(i).bits.pdest
val enqFire = (io.toIntDq(intIndex.io.reverseMapping(i).bits).fire() && intIndex.io.reverseMapping(i).valid) ||
(io.toFpDq(fpIndex.io.reverseMapping(i).bits).fire() && fpIndex.io.reverseMapping(i).valid) ||
(io.toLsDq(lsIndex.io.reverseMapping(i).bits).fire() && lsIndex.io.reverseMapping(i).valid)
......
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(
......
......@@ -9,14 +9,6 @@ class Rename extends XSModule {
val io = IO(new Bundle() {
val redirect = Flipped(ValidIO(new Redirect))
val roqCommits = Vec(CommitWidth, Flipped(ValidIO(new RoqCommit)))
val wbIntResults = Vec(NRIntWritePorts, Flipped(ValidIO(new ExuOutput)))
val wbFpResults = Vec(NRFpWritePorts, Flipped(ValidIO(new ExuOutput)))
val intRfReadAddr = Vec(NRIntReadPorts, Input(UInt(PhyRegIdxWidth.W)))
val fpRfReadAddr = Vec(NRFpReadPorts, Input(UInt(PhyRegIdxWidth.W)))
val intPregRdy = Vec(NRIntReadPorts, Output(Bool()))
val fpPregRdy = Vec(NRFpReadPorts, Output(Bool()))
// set preg to busy when replay
val replayPregReq = Vec(ReplayWidth, Input(new ReplayPregReq))
// from decode buffer
val in = Vec(RenameWidth, Flipped(DecoupledIO(new CfCtrl)))
// to dispatch1
......@@ -43,8 +35,6 @@ class Rename extends XSModule {
val fpFreeList, intFreeList = Module(new FreeList).io
val fpRat = Module(new RenameTable(float = true)).io
val intRat = Module(new RenameTable(float = false)).io
val fpBusyTable = Module(new BusyTable(NRFpReadPorts, NRFpWritePorts)).io
val intBusyTable = Module(new BusyTable(NRIntReadPorts, NRIntWritePorts)).io
fpFreeList.redirect := io.redirect
intFreeList.redirect := io.redirect
......@@ -52,8 +42,6 @@ class Rename extends XSModule {
val flush = io.redirect.valid && (io.redirect.bits.isException || io.redirect.bits.isFlushPipe) // TODO: need check by JiaWei
fpRat.flush := flush
intRat.flush := flush
fpBusyTable.flush := flush
intBusyTable.flush := flush
def needDestReg[T <: CfCtrl](fp: Boolean, x: T): Bool = {
{if(fp) x.ctrl.fpWen else x.ctrl.rfWen && (x.ctrl.ldest =/= 0.U)}
......@@ -125,7 +113,6 @@ class Rename extends XSModule {
def writeRat(fp: Boolean) = {
val rat = if(fp) fpRat else intRat
val freeList = if(fp) fpFreeList else intFreeList
val busyTable = if(fp) fpBusyTable else intBusyTable
// speculative inst write
val specWen = freeList.allocReqs(i) && freeList.canAlloc(i)
// walk back write
......@@ -153,9 +140,6 @@ class Rename extends XSModule {
freeList.deallocReqs(i) := rat.archWritePorts(i).wen
freeList.deallocPregs(i) := io.roqCommits(i).bits.uop.old_pdest
// set phy reg status to busy
busyTable.allocPregs(i).valid := specWen
busyTable.allocPregs(i).bits := freeList.pdests(i)
}
writeRat(fp = false)
......@@ -190,26 +174,5 @@ class Rename extends XSModule {
}
def updateBusyTable(fp: Boolean) = {
val wbResults = if(fp) io.wbFpResults else io.wbIntResults
val busyTable = if(fp) fpBusyTable else intBusyTable
for((wb, setPhyRegRdy) <- wbResults.zip(busyTable.wbPregs)){
setPhyRegRdy.valid := wb.valid && needDestReg(fp, wb.bits.uop)
setPhyRegRdy.bits := wb.bits.uop.pdest
}
}
updateBusyTable(false)
updateBusyTable(true)
intBusyTable.rfReadAddr <> io.intRfReadAddr
intBusyTable.pregRdy <> io.intPregRdy
for(i <- io.replayPregReq.indices){
intBusyTable.replayPregs(i).valid := io.replayPregReq(i).isInt
fpBusyTable.replayPregs(i).valid := io.replayPregReq(i).isFp
intBusyTable.replayPregs(i).bits := io.replayPregReq(i).preg
fpBusyTable.replayPregs(i).bits := io.replayPregReq(i).preg
}
fpBusyTable.rfReadAddr <> io.fpRfReadAddr
fpBusyTable.pregRdy <> io.fpPregRdy
}
......@@ -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,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
......@@ -309,4 +310,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
......@@ -138,4 +138,4 @@ class StoreUnit extends XSModule {
printPipeLine(store_s0.io.out.bits, store_s0.io.out.valid, "S0")
printPipeLine(store_s1.io.out.bits, store_s1.io.out.valid, "S1")
}
}
\ 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.
先完成此消息的编辑!
想要评论请 注册