Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/src/common/Pc.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,13 @@ class Pc(
val pcReg = RegInit(spec.Pc.init)
io.pc := pcReg

val canIncReg = RegInit(true.B)

pcReg := pcReg
when(io.newPc.en) {
pcReg := io.newPc.pcAddr
}.elsewhen(io.isNext) {
pcReg := io.newPc.pcAddr
canIncReg := !io.newPc.isIdle
}.elsewhen(io.isNext && canIncReg) {
// pcReg := pcReg + (4 * issueNum).U
pcReg := pcReg + 4.U
}
Expand Down
4 changes: 3 additions & 1 deletion src/src/common/bundles/PcSetPort.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ import spec._
import chisel3.experimental.BundleLiterals._

class PcSetPort extends Bundle {
val isIdle = Bool()
val en = Bool()
val pcAddr = UInt(Width.Reg.data)
}

object PcSetPort {
val default = (new PcSetPort).Lit(
_.en -> false.B,
_.pcAddr -> zeroWord
_.pcAddr -> zeroWord,
_.isIdle -> false.B
)
}
7 changes: 2 additions & 5 deletions src/src/control/Cu.scala
Original file line number Diff line number Diff line change
Expand Up @@ -229,12 +229,9 @@ class Cu(
}

// select new pc
// when(ertnFlush) {
// io.newPc.en := true.B
// io.newPc.pcAddr := io.csrValues.era.asUInt
// }.else
when(exceptionFlush) {
io.newPc.en := true.B
io.newPc.en := true.B
io.newPc.isIdle := false.B
when(isTlbRefillException) {
io.newPc.pcAddr := io.csrValues.tlbrentry.asUInt
}.otherwise {
Expand Down
2 changes: 2 additions & 0 deletions src/src/frontend/InstFetchStage.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ class InstFetchStage extends Module {
val instEnqueuePort = Decoupled(new InstInfoBundle)
})

io.instEnqueuePort.bits := InstInfoBundle.default

io.instEnqueuePort.bits.pcAddr := io.pc
io.instEnqueuePort.bits.inst := io.accessPort.res.read.data

Expand Down
77 changes: 56 additions & 21 deletions src/src/pipeline/common/MultiQueue.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,33 @@ import spec._
import utils.MultiCounter

class MultiQueue[ElemT <: Data](
queueLength: Int,
enqMaxNum: Int,
deqMaxNum: Int,
elemNdFactory: => ElemT,
blankElem: => ElemT,
writeFirst: Boolean = true)
queueLength: Int,
enqMaxNum: Int,
deqMaxNum: Int,
elemNdFactory: => ElemT,
blankElem: => ElemT,
needValidPorts: Boolean = false,
isRelativePosition: Boolean = false,
writeFirst: Boolean = true)
extends Module {

val io = IO(new Bundle {
val isFlush = Input(Bool())
val enqueuePorts = Vec(enqMaxNum, Flipped(Decoupled(elemNdFactory)))
val dequeuePorts = Vec(deqMaxNum, Decoupled(elemNdFactory))

val setPorts = Input(Vec(queueLength, ValidIO(elemNdFactory)))
val elems = Output(Vec(queueLength, elemNdFactory))
// deq_ptr -> enq_ptr
val setPorts = Input(Vec(queueLength, ValidIO(elemNdFactory)))
val elems = Output(Vec(queueLength, elemNdFactory))
val elemValids = if (needValidPorts) Some(Output(Vec(queueLength, Bool()))) else None
})

require(queueLength > enqMaxNum)
require(queueLength > deqMaxNum)

val ram = RegInit(VecInit(Seq.fill(queueLength)(blankElem)))
io.elems.zip(ram).foreach {
case (dst, src) =>
dst := src
}
val ram = RegInit(VecInit(Seq.fill(queueLength)(blankElem)))
val ramValids = RegInit(VecInit(Seq.fill(queueLength)(false.B)))

val enq_ptr = Module(new MultiCounter(queueLength, enqMaxNum))
val deq_ptr = Module(new MultiCounter(queueLength, deqMaxNum))

Expand Down Expand Up @@ -79,10 +81,14 @@ class MultiQueue[ElemT <: Data](
val dequeueNum = deqEn.map(_.asUInt).reduce(_ +& _)

if (!writeFirst) {
ram.zip(io.setPorts).foreach {
case (r, s) =>
io.setPorts.zipWithIndex.foreach {
case (s, idx) =>
when(s.valid) {
r := s.bits
if (isRelativePosition) {
ram(deq_ptr.io.incResults(idx)) := s.bits
} else {
ram(idx) := s.bits
}
}
}
}
Expand All @@ -97,25 +103,54 @@ class MultiQueue[ElemT <: Data](
io.enqueuePorts.lazyZip(enqEn).zipWithIndex.foreach {
case ((enqPort, en), idx) =>
when(idx.U < enqueueNum) {
ram(enq_ptr.io.incResults(idx)) := enqPort.bits
ram(enq_ptr.io.incResults(idx)) := enqPort.bits
ramValids(enq_ptr.io.incResults(idx)) := true.B
}
}

deq_ptr.io.inc := dequeueNum
io.dequeuePorts.zipWithIndex.foreach {
case (deq, idx) =>
deq.bits := ram(deq_ptr.io.incResults(idx))
deq.bits := ram(deq_ptr.io.incResults(idx))
ramValids(deq_ptr.io.incResults(idx)) := false.B
}

if (writeFirst) {
ram.zip(io.setPorts).foreach {
case (r, s) =>
io.setPorts.zipWithIndex.foreach {
case (s, idx) =>
when(s.valid) {
r := s.bits
if (isRelativePosition) {
ram(deq_ptr.io.incResults(idx)) := s.bits
} else {
ram(idx) := s.bits
}
}
}
}

io.elems.zipWithIndex.foreach {
case (dst, idx) =>
if (isRelativePosition) {
dst := ram(deq_ptr.io.incResults(idx))
} else {
dst := ram(idx)
}

}

io.elemValids match {
case Some(elemValids) =>
io.elemValids.zipWithIndex.foreach {
case (dst, idx) =>
if (isRelativePosition) {
dst := ramValids(deq_ptr.io.incResults(idx))
} else {
dst := ramValids(idx)
}
}
case None =>
}

when(io.isFlush) {
ram.foreach(_ := blankElem)
maybeFull := false.B
Expand Down
150 changes: 143 additions & 7 deletions src/src/pipeline/dispatch/IssueStage.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ import pipeline.common.MultiBaseStage
import pipeline.execution.ExeNdPort
import pipeline.dispatch.FetchInstDecodeNdPort
import pipeline.rob.bundles.InstWbNdPort
import pipeline.common.MultiQueue
import pipeline.dispatch.bundles.ReservationStationBundle
import pipeline.rob.enums.RobDistributeSel

// class FetchInstDecodeNdPort extends Bundle {
// val decode = new DecodeOutNdPort
Expand All @@ -29,14 +32,14 @@ import pipeline.rob.bundles.InstWbNdPort
// }

class IssueStagePeerPort(
issueNum: Int = Param.issueInstInfoMaxNum,
pipelineNum: Int = Param.pipelineNum,
scoreChangeNum: Int = Param.regFileWriteNum)
issueNum: Int = Param.issueInstInfoMaxNum,
pipelineNum: Int = Param.pipelineNum)
extends Bundle {

// `IssueStage` <-> `Rob`
val requests = Output(Vec(issueNum, new RobReadRequestNdPort))
val results = Input(Vec(issueNum, new RobReadResultNdPort))
val robEmptyNum = Input(UInt(Param.Width.Rob.addr))
val requests = Output(Vec(issueNum, new RobReadRequestNdPort))
val results = Input(Vec(issueNum, new RobReadResultNdPort))

// `LSU / ALU` -> `IssueStage
val writebacks = Input(Vec(pipelineNum, new InstWbNdPort))
Expand All @@ -47,17 +50,150 @@ class IssueStagePeerPort(
}

// dispatch & Reservation Stations
class IssueStage
class IssueStage(
issueNum: Int = Param.issueInstInfoMaxNum,
pipelineNum: Int = Param.pipelineNum,
reservationLength: Int = spec.Param.reservationStationDeep)
extends MultiBaseStage(
new FetchInstDecodeNdPort,
new ExeNdPort,
FetchInstDecodeNdPort.default,
Some(new IssueStagePeerPort)
Some(new IssueStagePeerPort),
issueNum,
pipelineNum
) {

// Fallback
resultOutsReg.foreach(_.bits := 0.U.asTypeOf(resultOutsReg(0).bits))
io.peer.get.csrOccupyPort := ScoreboardChangeNdPort.default
io.peer.get.requests.foreach(_ := RobReadRequestNdPort.default)

val reservationStations = Seq.fill(pipelineNum)(
Module(new MultiQueue(reservationLength, 1, 1, new ReservationStationBundle, ReservationStationBundle.default))
)

// fall back
reservationStations.foreach { port =>
port.io.enqueuePorts(0).valid := false.B
port.io.enqueuePorts(0).bits := DontCare
}
reservationStations.foreach(_.io.dequeuePorts(0).ready := false.B)
// TODO: BRANCH CONDITION
reservationStations.foreach(_.io.isFlush := io.isFlush)
reservationStations.foreach(_.io.setPorts.foreach { port =>
port.valid := false.B
port.bits := DontCare
})

/** fetch -> reservation stations
*/

val readyReservations = WireDefault(VecInit(reservationStations.map(_.io.enqueuePorts(0).ready)))

val dispatchMap = WireDefault(VecInit(Seq.fill(issueNum)(VecInit(Seq.fill(pipelineNum)(false.B)))))
val canDispatchs = WireDefault(VecInit(dispatchMap.map(_.reduceTree(_ || _))))
isComputeds.lazyZip(canDispatchs).lazyZip(selectedIns).foreach {
case (isComputed, canDispatch, in) =>
isComputed := canDispatch || !in.instInfo.isValid
}
io.ins.zip(isLastComputeds).foreach {
case (in, isLastComputed) =>
in.ready := isLastComputed
}

selectedIns.lazyZip(dispatchMap).zipWithIndex.foreach {
case ((in, dispatchSel), src_idx) =>
when(in.instInfo.isValid) {
// select all dsts to dispatch
val dstReady = Wire(Vec(pipelineNum, Bool()))
dstReady.lazyZip(readyReservations).zipWithIndex.foreach {
case ((dispatchEn, ready), dst_idx) =>
// Map condition src -> dst
// 1. dst ready
// 2. dst isn't occupied by previous srcs
// 3. previous srcs dispatch success
// 4. rob has empty position
// 5. in the right pipeline index
dispatchEn := ready &&
!dispatchMap.take(src_idx).map(_(dst_idx)).foldLeft(false.B)(_ || _) &&
canDispatchs.take(src_idx).foldLeft(true.B)(_ && _) &&
src_idx.U < io.peer.get.robEmptyNum
if (dst_idx != loadStoreIssuePipelineIndex) {
when(in.decode.info.exeSel === ExeInst.Sel.loadStore) {
dispatchEn := false.B
}
}
if (dst_idx != csrIssuePipelineIndex) {
when(in.instInfo.needCsr) {
dispatchEn := false.B
}
}
}
// select one
dispatchSel.zip(PriorityEncoderOH(dstReady)).foreach {
case (dst, src) =>
dst := src
}
}
}

// -> reservation stations
for (src_idx <- Seq.range(issueNum - 1, -1, -1)) {
for (dst_idx <- 0 to pipelineNum) {
when(dispatchMap(src_idx)(dst_idx)) {
// decode info
reservationStations(dst_idx).io.enqueuePorts(0).valid := true.B
reservationStations(dst_idx).io.enqueuePorts(0).bits.regReadPort.preExeInstInfo := selectedIns(
src_idx
).decode.info
reservationStations(dst_idx).io.enqueuePorts(0).bits.regReadPort.instInfo := selectedIns(src_idx).instInfo

// rob result
io.peer.get.requests(src_idx).readRequests.zip(selectedIns(src_idx).decode.info.gprReadPorts).foreach {
case (req, decodeRead) =>
req := decodeRead
}
io.peer.get.requests(src_idx).writeRequest := selectedIns(src_idx).decode.info.gprWritePort
reservationStations(dst_idx).io.enqueuePorts(0).bits.robResult := io.peer.get.results(src_idx)

// commit result
io.peer.get.writebacks.foreach { writeback =>
selectedIns(src_idx).decode.info.gprReadPorts
.lazyZip(io.peer.get.results(src_idx).readResults)
.lazyZip(reservationStations(dst_idx).io.enqueuePorts(0).bits.robResult.readResults)
.foreach {
case (readPort, robResult, rs) =>
// may be error
when(writeback.en && readPort.en && writeback.robId === robResult.result) {
rs.sel := RobDistributeSel.realData
rs.result := writeback.data
}
}
}

// imm
when(selectedIns(src_idx).decode.info.isHasImm) {
reservationStations(dst_idx).io.enqueuePorts(0).bits.robResult.readResults(1).sel := RobDistributeSel.realData
reservationStations(dst_idx).io.enqueuePorts(0).bits.robResult.readResults(1).result := selectedIns(
src_idx
).decode.info.imm
}

// csr score board
io.peer.get.csrOccupyPort.en := selectedIns(src_idx).decode.info.needCsr
io.peer.get.csrOccupyPort.addr := DontCare
}
}
}

/** commit --fill--> reservation stations
*/

reservationStations.foreach { reservationStation =>
reservationStation.io.elems.zip(reservationStation.io.elemValids)
}

/** output
*/

}
10 changes: 9 additions & 1 deletion src/src/pipeline/dispatch/bundles/InstInfoBundle.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,19 @@ import spec._
class InstInfoBundle extends Bundle {
val pcAddr = UInt(Width.Reg.data)
val inst = UInt(Width.inst)
val isAdef = Bool()
val isPpi = Bool()
val isPif = Bool()
val isTlbr = Bool()
}

object InstInfoBundle {
val default = (new InstInfoBundle).Lit(
_.pcAddr -> zeroWord,
_.inst -> zeroWord
_.inst -> zeroWord,
_.isAdef -> false.B,
_.isPif -> false.B,
_.isPpi -> false.B,
_.isTlbr -> false.B
)
}
Loading