diff --git a/src/src/CoreCpuTop.scala b/src/src/CoreCpuTop.scala index 51114b1e..9db34e27 100644 --- a/src/src/CoreCpuTop.scala +++ b/src/src/CoreCpuTop.scala @@ -280,6 +280,7 @@ class CoreCpuTop extends Module { case (dst, src) => dst <> src } + commitStage.io.hasInterrupt := csr.io.hasInterrupt // Register file (GPR file) regFile.io.writePorts <> cu.io.gprWritePassThroughPorts.out diff --git a/src/src/control/Cu.scala b/src/src/control/Cu.scala index 07ed7379..216d815b 100644 --- a/src/src/control/Cu.scala +++ b/src/src/control/Cu.scala @@ -220,19 +220,25 @@ class Cu( io.csrMessage.ertnFlush := isExceptionReturn // TODO: Make ERTN jump gracefully like branch instruction io.frontendFlush := - isException || io.branchExe.en || isTlbMaintenance || io.csrFlushRequest || cacopFlush || idleFlush || isExceptionReturn + RegNext( + isException || io.branchExe.en || isTlbMaintenance || io.csrFlushRequest || cacopFlush || idleFlush || isExceptionReturn, + false.B + ) io.backendFlush := RegNext( isException || io.branchCommit || isTlbMaintenance || io.csrFlushRequest || cacopFlush || idleFlush || isExceptionReturn, false.B ) - io.idleFlush := idleFlush + io.idleFlush := RegNext(idleFlush) // Select new pc - io.newPc := PcSetNdPort.default - io.newPc.en := + val newPc = RegInit(PcSetNdPort.default) + io.newPc := newPc + + newPc := PcSetNdPort.default + newPc.en := isTlbMaintenance || io.csrFlushRequest || isException || io.branchExe.en || cacopFlush || idleFlush || isExceptionReturn - io.newPc.isTlb := isTlbMaintenance - io.newPc.pcAddr := Mux( + newPc.isTlb := isTlbMaintenance + newPc.pcAddr := Mux( isException, Mux( majorInstInfo.exceptionRecord === Csr.ExceptionIndex.tlbr, @@ -250,11 +256,6 @@ class Cu( ) ) - val is_softwareInt = io.instInfoPorts(0).isValid && - io.instInfoPorts(0).csrWritePort.en && - (io.instInfoPorts(0).csrWritePort.addr === Csr.Index.estat) && - io.instInfoPorts(0).csrWritePort.data(1, 0).orR - io.difftest match { case Some(dt) => dt.cmt_ertn := RegNext(isExceptionReturn) diff --git a/src/src/pipeline/commit/CommitStage.scala b/src/src/pipeline/commit/CommitStage.scala index 53d32db9..b13f1369 100644 --- a/src/src/pipeline/commit/CommitStage.scala +++ b/src/src/pipeline/commit/CommitStage.scala @@ -40,14 +40,16 @@ class CommitStage( // `CommitStage` -> `Cu` NO delay val isExceptionValid = Output(Bool()) + val hasInterrupt = Input(Bool()) + val difftest = if (isDiffTest) Some(Output(new Bundle { val valid = Bool() val pc = UInt(Width.Reg.data) val instr = UInt(Width.Reg.data) - val is_TLBFILL = Bool() // TODO - val TLBFILL_index = UInt(Width.Reg.addr) // TODO + val is_TLBFILL = Bool() + val TLBFILL_index = UInt(Width.Reg.addr) val wen = Bool() val wdest = UInt(Width.Reg.addr) val wdata = UInt(Width.Reg.data) @@ -73,7 +75,7 @@ class CommitStage( else None }) - io.ins.foreach(_.ready := true.B) + io.ins.foreach(_.ready := !io.hasInterrupt) val inBits = WireDefault(VecInit(io.ins.map(_.bits))) diff --git a/src/src/pipeline/common/DistributedQueue.scala b/src/src/pipeline/common/DistributedQueue.scala index e520db3a..cdcf5164 100644 --- a/src/src/pipeline/common/DistributedQueue.scala +++ b/src/src/pipeline/common/DistributedQueue.scala @@ -20,12 +20,6 @@ class DistributedQueue[ElemT <: Data]( val isFlush = Input(Bool()) val enqueuePorts = Vec(enqMaxNum, Flipped(Decoupled(elemNdFactory))) val dequeuePorts = Vec(deqMaxNum, Decoupled(elemNdFactory)) - - // deq_ptr -> enq_ptr - val enqIncResults = Output(Vec(enqMaxNum + 1, UInt(log2Ceil(channelNum).W))) - val deqIncResults = Output(Vec(deqMaxNum + 1, UInt(log2Ceil(channelNum).W))) - val enq_ptr = Output(UInt(log2Ceil(channelNum).W)) - val deq_ptr = Output(UInt(log2Ceil(channelNum).W)) }) // Fallback @@ -53,22 +47,14 @@ class DistributedQueue[ElemT <: Data]( storeOuts.foreach(_.ready := false.B) if (channelNum == 1) { - storeOuts(0) <> storeIns(0) + // storeOuts(0) <> storeIns(0) + io.enqueuePorts(0) <> storeIns(0) + io.dequeuePorts(0) <> storeOuts(0) } else { val enq_ptr = Module(new MultiCounter(channelNum, enqMaxNum)) val deq_ptr = Module(new MultiCounter(channelNum, deqMaxNum)) enq_ptr.io.flush := io.isFlush deq_ptr.io.flush := io.isFlush - io.enq_ptr := enq_ptr.io.value - io.deq_ptr := deq_ptr.io.value - io.enqIncResults.zip(enq_ptr.io.incResults).foreach { - case (dst, src) => - dst := src - } - io.deqIncResults.zip(deq_ptr.io.incResults).foreach { - case (dst, src) => - dst := src - } enq_ptr.io.inc := io.enqueuePorts.zipWithIndex.map { case (enqPort, idx) => diff --git a/src/src/pipeline/common/DistributedQueuePlus.scala b/src/src/pipeline/common/DistributedQueuePlus.scala new file mode 100644 index 00000000..895e069c --- /dev/null +++ b/src/src/pipeline/common/DistributedQueuePlus.scala @@ -0,0 +1,121 @@ +package pipeline.common + +import chisel3._ +import chisel3.util._ +import utils.MultiCounter +import spec.Param + +class DistributedQueuePlus[ElemT <: Data]( + enqMaxNum: Int, + deqMaxNum: Int, + channelNum: Int, + channelLength: Int, + elemNdFactory: => ElemT, + blankElem: => ElemT, + useSyncReadMem: Boolean = true) + extends Module { + + require(channelNum >= enqMaxNum) + require(channelNum >= deqMaxNum) + require(log2Ceil(channelNum) == log2Floor(channelNum)) + val channelNumWidth = log2Ceil(channelNum) + + val io = IO(new Bundle { + val isFlush = Input(Bool()) + val enqueuePorts = Vec(enqMaxNum, Flipped(Decoupled(elemNdFactory))) + val dequeuePorts = Vec(deqMaxNum, Decoupled(elemNdFactory)) + + // deq_ptr -> enq_ptr + val enqIncResults = Output(Vec(enqMaxNum + 1, UInt(log2Ceil(channelLength * channelNum).W))) + val deqIncResults = Output(Vec(deqMaxNum + 1, UInt(log2Ceil(channelLength * channelNum).W))) + // val deqIncResults = Output(Vec(deqMaxNum + 1, UInt(log2Ceil(channelLength * channelNum).W))) + // val enq_ptr = Output(UInt(log2Ceil(channelLength * channelNum).W)) + // val deq_ptr = Output(UInt(log2Ceil(channelLength * channelNum).W)) + + val elems = Output(Vec(channelLength * channelNum, elemNdFactory)) + val setPorts = Input(Vec(channelLength * channelNum, Valid(elemNdFactory))) + }) + + // Fallback + io.dequeuePorts.foreach(_ <> DontCare) + io.enqueuePorts.foreach(_.ready := false.B) + io.dequeuePorts.foreach(_.valid := false.B) + + // val storeIns = Wire(Vec(channelNum, (DecoupledIO(elemNdFactory)))) + + val queues = Seq.fill(channelNum)( + Module( + new MultiQueue( + channelLength, + 1, + 1, + elemNdFactory, + blankElem, + writeFirst = false + ) + ) + ) + queues.foreach(_.io.isFlush := io.isFlush) + + val storeIns = VecInit(queues.map(_.io.enqueuePorts(0))) + val storeOuts = VecInit(queues.map(_.io.dequeuePorts(0))) + + for (i <- 0 until channelLength) { + for (j <- 0 until channelNum) { + val idx = i * channelLength + j + io.elems(idx) := queues(j).io.elems(i) + queues(j).io.setPorts(i) := io.setPorts(idx) + } + } + + storeIns.foreach { in => + in.valid := false.B + in.bits := DontCare + } + + storeOuts.foreach(_.ready := false.B) + if (channelNum == 1) { + io.enqueuePorts(0) <> storeIns(0) + io.dequeuePorts(0) <> storeOuts(0) + } else { + val enq_ptr = Module(new MultiCounter(channelLength * channelNum, enqMaxNum)) + val deq_ptr = Module(new MultiCounter(channelLength * channelNum, deqMaxNum)) + + enq_ptr.io.flush := io.isFlush + deq_ptr.io.flush := io.isFlush + // io.enq_ptr := enq_ptr.io.value + // io.deq_ptr := deq_ptr.io.value + // io.enqIncResults.zip(enq_ptr.io.incResults).foreach { + // case (dst, src) => + // dst := src + // } + // io.deqIncResults.zip(deq_ptr.io.incResults).foreach { + // case (dst, src) => + // dst := src + // } + io.enqIncResults.zipWithIndex.foreach { + case (dst, idx) => + dst := enq_ptr.io.incResults(idx) + } + io.deqIncResults.zipWithIndex.foreach { + case (dst, idx) => + dst := deq_ptr.io.incResults(idx) + } + + enq_ptr.io.inc := io.enqueuePorts.zipWithIndex.map { + case (enqPort, idx) => + // connect + enqPort <> storeIns(enq_ptr.io.incResults(idx)(channelNumWidth - 1, 0)) + // return + enqPort.valid && storeIns(enq_ptr.io.incResults(idx)(channelNumWidth - 1, 0)).ready + }.map(_.asUInt).reduce(_ +& _) + + deq_ptr.io.inc := io.dequeuePorts.zipWithIndex.map { + case (deqPort, idx) => + // connect + deqPort <> storeOuts(deq_ptr.io.incResults(idx)(channelNumWidth - 1, 0)) + // return + deqPort.valid && storeOuts(deq_ptr.io.incResults(idx)(channelNumWidth - 1, 0)).ready + }.map(_.asUInt).reduce(_ +& _) + } +} diff --git a/src/src/pipeline/dispatch/RenameStage.scala b/src/src/pipeline/dispatch/RenameStage.scala index 839713b1..9258c4e4 100644 --- a/src/src/pipeline/dispatch/RenameStage.scala +++ b/src/src/pipeline/dispatch/RenameStage.scala @@ -246,13 +246,13 @@ class RenameStage( } when(peer.branchFlush) { - peer.requests.foreach(_.en := false.B) + // peer.requests.foreach(_.en := false.B) io.ins.foreach(_.ready := false.B) fetchEnableFlag := false.B } when(io.isFlush) { - peer.requests.foreach(_.en := false.B) + // peer.requests.foreach(_.en := false.B) io.ins.foreach(_.ready := false.B) fetchEnableFlag := true.B } diff --git a/src/src/pipeline/rob/Rob.scala b/src/src/pipeline/rob/Rob.scala index ace226d3..70e26de8 100644 --- a/src/src/pipeline/rob/Rob.scala +++ b/src/src/pipeline/rob/Rob.scala @@ -9,6 +9,7 @@ import pipeline.common.MultiQueue import pipeline.rob.bundles._ import pipeline.rob.enums.{RegDataLocateSel, RobDistributeSel, RobInstState => State} import spec._ +import pipeline.common.DistributedQueuePlus // assert: commits cannot ready 1 but not 0 class Rob( @@ -57,15 +58,28 @@ class Rob( val matchTable = RegInit(VecInit(Seq.fill(spec.Count.reg)(RobMatchBundle.default))) + // val queue = Module( + // new MultiQueue( + // robLength, + // issueNum, + // commitNum, + // new RobInstStoreBundle, + // RobInstStoreBundle.default + // ) + // ) + val queue = Module( - new MultiQueue( - robLength, + new DistributedQueuePlus( issueNum, commitNum, + Param.Width.Rob._channelNum, + Param.Width.Rob._channelLength, new RobInstStoreBundle, - RobInstStoreBundle.default + RobInstStoreBundle.default, + useSyncReadMem = false ) ) + queue.io.enqueuePorts.foreach { port => port.valid := false.B port.bits := DontCare @@ -77,7 +91,7 @@ class Rob( } queue.io.dequeuePorts.foreach(_.ready := false.B) queue.io.isFlush := io.isFlush - io.emptyNum := queue.io.emptyNum + io.emptyNum := VecInit(queue.io.enqueuePorts.map(_.ready.asUInt)).reduceTree(_ +& _) io.instWbBroadCasts.zip(io.finishInsts).foreach { case (dst, src) => dst.en := src.valid // && io.robInstValids(src.bits.instInfo.robId) @@ -91,9 +105,9 @@ class Rob( io.finishInsts.foreach { finishInst => finishInst.ready := true.B when(finishInst.valid && finishInst.bits.instInfo.isValid) { - queue.io.elemValids.lazyZip(queue.io.elems).lazyZip(queue.io.setPorts).zipWithIndex.foreach { - case ((elemValid, elem, set), idx) => - when(elemValid && elem.state === State.busy && idx.U === finishInst.bits.instInfo.robId) { + queue.io.elems.lazyZip(queue.io.setPorts).zipWithIndex.foreach { + case ((elem, set), idx) => + when(elem.state === State.busy && idx.U === finishInst.bits.instInfo.robId) { set.valid := true.B set.bits.isValid := elem.isValid set.bits.state := State.ready @@ -138,8 +152,9 @@ class Rob( !deqPort.bits.wbPort.instInfo.forbidParallelCommit && queue.io.dequeuePorts(idx - 1).valid && queue.io.dequeuePorts(idx - 1).ready && // promise commit in order - !hasInterruptReg && - !io.hasInterrupt + !hasInterruptReg + // && + // !io.hasInterrupt } commit.valid := deqPort.ready @@ -159,12 +174,12 @@ class Rob( } when(io.hasInterrupt) { - when(io.commits(0).valid && io.commits(0).ready) { - io.commits(0).bits.instInfo.exceptionRecord := Csr.ExceptionIndex.int - io.commits(0).bits.instInfo.exceptionPos := ExceptionPos.backend - }.otherwise { - hasInterruptReg := true.B - } + // when(io.commits(0).valid && io.commits(0).ready) { + // io.commits(0).bits.instInfo.exceptionRecord := Csr.ExceptionIndex.int + // io.commits(0).bits.instInfo.exceptionPos := ExceptionPos.backend + // }.otherwise { + hasInterruptReg := true.B + // } }.elsewhen(hasInterruptReg && io.commits(0).valid && io.commits(0).ready) { hasInterruptReg := false.B io.commits(0).bits.instInfo.exceptionRecord := Csr.ExceptionIndex.int @@ -241,8 +256,8 @@ class Rob( */ when(io.isFlush) { - queue.io.enqueuePorts.foreach(_.valid := false.B) - io.commits.foreach(_.valid := false.B) + // queue.io.enqueuePorts.foreach(_.valid := false.B) + // io.commits.foreach(_.valid := false.B) matchTable.foreach(_.locate := RegDataLocateSel.regfile) } } diff --git a/src/src/spec/Param.scala b/src/src/spec/Param.scala index fddcaed7..862dab2e 100644 --- a/src/src/spec/Param.scala +++ b/src/src/spec/Param.scala @@ -36,8 +36,10 @@ object Param { val exeOp = log2Ceil(ExeInst.Op.count + 1).W object Rob { - val _length = 16 - val id = log2Ceil(_length).W + val _length = 16 + val _channelNum = 4 + val _channelLength = _length / _channelNum + val id = log2Ceil(_length).W } object Axi { diff --git a/verilog/fifo.v b/verilog/fifo.v deleted file mode 100644 index 558dee8e..00000000 --- a/verilog/fifo.v +++ /dev/null @@ -1,58 +0,0 @@ -// fifo is a module to encapsule a lutram based FIFO - -module fifo #( - parameter DATA_WIDTH = 128, - parameter DEPTH = 8 -) ( - input clk, - input rst, - - // Input - input push, - input [DATA_WIDTH-1:0] push_data, - - // Output - input pop, - output [DATA_WIDTH-1:0] pop_data, - - // Controll signals - input reset, // Have reset - output full, - output empty -); - - // Parameters - localparam PTR_WIDTH = $clog2(DEPTH); - - // Data structure - (* ram_style = "distributed" *) reg [DATA_WIDTH-1:0] ram[DEPTH]; - - reg [PTR_WIDTH-1:0] write_index; - reg [PTR_WIDTH-1:0] read_index; - - - // RAM operation - always_ff @(posedge clk) begin - // if (rst | reset) ram <= '{default: '0}; - // else - if (push) ram[write_index] <= push_data; - end - - // PTR operation - always_ff @(posedge clk) begin - if (rst | reset) read_index <= 0; - else if (pop & ~empty) read_index <= read_index + 1; - end - always_ff @(posedge clk) begin - if (rst | reset) write_index <= 0; - else if (push & ~full) write_index <= write_index + 1; - end - - // Output - assign pop_data = ram[read_index]; - - // Controll signals - assign full = read_index == PTR_WIDTH'(write_index + 1); - assign empty = read_index == write_index; - -endmodule