diff --git a/.gitmodules b/.gitmodules index cde2799a3..d72ad5a14 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,9 @@ [submodule "fudian"] path = fudian url = https://github.com/OpenXiangShan/fudian.git +[submodule "utility"] + path = utility + url = https://github.com/OpenXiangShan/utility +[submodule "yunsuan"] + path = yunsuan + url = https://github.com/OpenXiangShan/YunSuan.git diff --git a/build.sc b/build.sc index cfd846513..d153d8377 100644 --- a/build.sc +++ b/build.sc @@ -114,7 +114,8 @@ object huancun extends XSModule with SbtModule { override def millSourcePath = os.pwd / "huancun" override def moduleDeps = super.moduleDeps ++ Seq( - rocketchip + rocketchip, + utility ) } @@ -128,6 +129,15 @@ object yunsuan extends XSModule with SbtModule { object fudian extends XSModule with SbtModule +object utility extends XSModule with SbtModule { + + override def millSourcePath = os.pwd / "utility" + + override def moduleDeps = super.moduleDeps ++ Seq( + rocketchip + ) +} + // extends this trait to use XiangShan in other projects trait CommonXiangShan extends XSModule with SbtModule { m => @@ -137,6 +147,7 @@ trait CommonXiangShan extends XSModule with SbtModule { m => def huancunModule: PublishModule def yunsuanModule: PublishModule def fudianModule: PublishModule + def utilityModule: PublishModule override def millSourcePath = os.pwd @@ -149,7 +160,8 @@ trait CommonXiangShan extends XSModule with SbtModule { m => difftestModule, huancunModule, yunsuanModule, - fudianModule + fudianModule, + utilityModule ) object test extends Tests with TestModule.ScalaTest { @@ -170,4 +182,5 @@ object XiangShan extends CommonXiangShan { override def huancunModule = huancun override def yunsuanModule = yunsuan override def fudianModule = fudian + override def utilityModule = utility } diff --git a/huancun b/huancun index 57ccacbf0..f96ac2590 160000 --- a/huancun +++ b/huancun @@ -1 +1 @@ -Subproject commit 57ccacbf0c5b552a3d6dda5baeef3abc8bad033c +Subproject commit f96ac25904091ae7ab96b7f6f5bd7047d4129466 diff --git a/src/main/scala/device/AXI4DummySD.scala b/src/main/scala/device/AXI4DummySD.scala index 463135660..f733b12d4 100644 --- a/src/main/scala/device/AXI4DummySD.scala +++ b/src/main/scala/device/AXI4DummySD.scala @@ -21,7 +21,7 @@ import chisel3._ import chisel3.experimental.ExtModule import chisel3.util._ import freechips.rocketchip.diplomacy.AddressSet -import utils._ +import utility._ trait HasSDConst { def MemorySize = 4L * 1024 * 1024 * 1024 // 4GB diff --git a/src/main/scala/device/AXI4Flash.scala b/src/main/scala/device/AXI4Flash.scala index 7089eb62b..36474f7f4 100644 --- a/src/main/scala/device/AXI4Flash.scala +++ b/src/main/scala/device/AXI4Flash.scala @@ -22,6 +22,7 @@ import chipsalliance.rocketchip.config.Parameters import chisel3.experimental.ExtModule import freechips.rocketchip.diplomacy.AddressSet import utils._ +import utility._ class FlashHelper extends ExtModule with HasExtModuleInline { val clk = IO(Input(Clock())) diff --git a/src/main/scala/device/AXI4IntrGenerator.scala b/src/main/scala/device/AXI4IntrGenerator.scala index 4b5aa9db3..eb9c5f5df 100644 --- a/src/main/scala/device/AXI4IntrGenerator.scala +++ b/src/main/scala/device/AXI4IntrGenerator.scala @@ -21,6 +21,7 @@ import chisel3.util._ import chipsalliance.rocketchip.config.Parameters import freechips.rocketchip.diplomacy.AddressSet import utils._ +import utility._ // we support 256 interrupt bits by default class IntrGenIO extends Bundle { diff --git a/src/main/scala/device/AXI4Keyboard.scala b/src/main/scala/device/AXI4Keyboard.scala index 5569e271f..0b25e7017 100644 --- a/src/main/scala/device/AXI4Keyboard.scala +++ b/src/main/scala/device/AXI4Keyboard.scala @@ -21,6 +21,7 @@ import chisel3.util._ import chipsalliance.rocketchip.config.Parameters import freechips.rocketchip.diplomacy.AddressSet import utils._ +import utility._ class KeyboardIO extends Bundle { val ps2Clk = Input(Bool()) diff --git a/src/main/scala/device/AXI4Memory.scala b/src/main/scala/device/AXI4Memory.scala index 6a9ca7ecb..00491afb2 100644 --- a/src/main/scala/device/AXI4Memory.scala +++ b/src/main/scala/device/AXI4Memory.scala @@ -22,6 +22,7 @@ import chisel3.util._ import freechips.rocketchip.amba.axi4.{AXI4MasterNode, AXI4Parameters, AXI4SlaveNode} import freechips.rocketchip.diplomacy.{AddressSet, InModuleBody, LazyModule, LazyModuleImp} import utils._ +import utility._ class MemoryRWHelper extends ExtModule with HasExtModuleInline { val DataBits = 64 diff --git a/src/main/scala/device/AXI4Plic.scala b/src/main/scala/device/AXI4Plic.scala index b981d30f7..974f696fa 100644 --- a/src/main/scala/device/AXI4Plic.scala +++ b/src/main/scala/device/AXI4Plic.scala @@ -20,8 +20,8 @@ import chisel3._ import chisel3.util._ import chipsalliance.rocketchip.config._ import freechips.rocketchip.diplomacy._ -import utils.MaskExpand -import utils.{HasTLDump, XSDebug, RegMap} +import utils.{XSDebug, HasTLDump} +import utility.{RegMap, MaskExpand} /* base + 0x000000: Reserved (interrupt source 0 does not exist) base + 0x000004: Interrupt source 1 priority diff --git a/src/main/scala/device/AXI4RAM.scala b/src/main/scala/device/AXI4RAM.scala index b826668d9..6c667fc08 100644 --- a/src/main/scala/device/AXI4RAM.scala +++ b/src/main/scala/device/AXI4RAM.scala @@ -22,7 +22,7 @@ import chisel3.experimental.ExtModule import chisel3.util._ import freechips.rocketchip.amba.axi4.AXI4SlaveNode import freechips.rocketchip.diplomacy.{AddressSet, LazyModule} -import utils.MaskExpand +import utility.MaskExpand class RAMHelper(memByte: BigInt) extends ExtModule { val DataBits = 64 diff --git a/src/main/scala/device/AXI4SlaveModule.scala b/src/main/scala/device/AXI4SlaveModule.scala index 141a406b0..85d2e8d93 100644 --- a/src/main/scala/device/AXI4SlaveModule.scala +++ b/src/main/scala/device/AXI4SlaveModule.scala @@ -19,6 +19,7 @@ package device import chisel3._ import chisel3.util._ import utils._ +import utility._ import freechips.rocketchip.diplomacy.{AddressSet, LazyModule, LazyModuleImp, RegionType, TransferSizes} import chipsalliance.rocketchip.config.Parameters import freechips.rocketchip.amba.axi4.{AXI4Parameters, AXI4SlaveNode, AXI4SlaveParameters, AXI4SlavePortParameters} diff --git a/src/main/scala/device/AXI4Timer.scala b/src/main/scala/device/AXI4Timer.scala index a14aa44e9..d9e837279 100644 --- a/src/main/scala/device/AXI4Timer.scala +++ b/src/main/scala/device/AXI4Timer.scala @@ -20,6 +20,7 @@ import chisel3._ import chipsalliance.rocketchip.config.Parameters import freechips.rocketchip.diplomacy.AddressSet import utils._ +import utility._ class TimerIO extends Bundle { val mtip = Output(Bool()) diff --git a/src/main/scala/device/AXI4UART.scala b/src/main/scala/device/AXI4UART.scala index 71e64170b..843ace390 100644 --- a/src/main/scala/device/AXI4UART.scala +++ b/src/main/scala/device/AXI4UART.scala @@ -21,6 +21,7 @@ import chisel3.util._ import chipsalliance.rocketchip.config.Parameters import freechips.rocketchip.diplomacy.AddressSet import utils._ +import utility._ import difftest._ class AXI4UART diff --git a/src/main/scala/device/AXI4VGA.scala b/src/main/scala/device/AXI4VGA.scala index 2156dc390..3d790617a 100644 --- a/src/main/scala/device/AXI4VGA.scala +++ b/src/main/scala/device/AXI4VGA.scala @@ -23,6 +23,7 @@ import chisel3.experimental.ExtModule import freechips.rocketchip.amba.axi4.{AXI4AdapterNode, AXI4IdentityNode, AXI4Parameters, AXI4SlaveNode, AXI4SlaveParameters, AXI4SlavePortParameters, AXI4Xbar} import freechips.rocketchip.diplomacy.{AddressSet, LazyModule, LazyModuleImp, RegionType} import utils._ +import utility._ trait HasVGAConst { val ScreenW = 800 diff --git a/src/main/scala/device/TLPMA/TLPMA.scala b/src/main/scala/device/TLPMA/TLPMA.scala index 960d74200..3a410d007 100644 --- a/src/main/scala/device/TLPMA/TLPMA.scala +++ b/src/main/scala/device/TLPMA/TLPMA.scala @@ -6,6 +6,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ import freechips.rocketchip.regmapper.RegFieldGroup import freechips.rocketchip.tilelink.TLRegisterNode import xiangshan.backend.fu.{MMPMAMethod, PMAConst, PMPChecker, PMPReqBundle, PMPRespBundle} diff --git a/src/main/scala/gpu/GPU.scala b/src/main/scala/gpu/GPU.scala index 9b7df7707..f08501830 100644 --- a/src/main/scala/gpu/GPU.scala +++ b/src/main/scala/gpu/GPU.scala @@ -22,6 +22,7 @@ //import bus.axi4._ //import device.AXI4SlaveModule //import utils._ +import utility._ // //class PixelBundle extends Bundle { // val a = UInt(8.W) diff --git a/src/main/scala/system/SoC.scala b/src/main/scala/system/SoC.scala index b97964f28..63223a778 100644 --- a/src/main/scala/system/SoC.scala +++ b/src/main/scala/system/SoC.scala @@ -24,7 +24,7 @@ import freechips.rocketchip.devices.tilelink.{CLINT, CLINTParams, DevNullParams, import freechips.rocketchip.diplomacy.{AddressSet, IdRange, InModuleBody, LazyModule, LazyModuleImp, MemoryDevice, RegionType, SimpleDevice, TransferSizes} import freechips.rocketchip.interrupts.{IntSourceNode, IntSourcePortSimple} import freechips.rocketchip.regmapper.{RegField, RegFieldAccessType, RegFieldDesc, RegFieldGroup} -import utils.{BinaryArbiter, TLEdgeBuffer} +import utility.{BinaryArbiter, TLEdgeBuffer} import xiangshan.{DebugOptionsKey, HasXSParameter, XSBundle, XSCore, XSCoreParameters, XSTileKey} import freechips.rocketchip.amba.axi4._ import freechips.rocketchip.tilelink._ diff --git a/src/main/scala/top/Configs.scala b/src/main/scala/top/Configs.scala index 7432cc3a7..ef4be5bb2 100644 --- a/src/main/scala/top/Configs.scala +++ b/src/main/scala/top/Configs.scala @@ -20,6 +20,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ import system._ import chipsalliance.rocketchip.config._ import freechips.rocketchip.tile.{BusErrorUnit, BusErrorUnitParams, XLen} diff --git a/src/main/scala/top/Top.scala b/src/main/scala/top/Top.scala index ed5967f32..ed5c2f78a 100644 --- a/src/main/scala/top/Top.scala +++ b/src/main/scala/top/Top.scala @@ -20,6 +20,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ import system._ import device._ import chisel3.stage.ChiselGeneratorAnnotation diff --git a/src/main/scala/utils/BinaryArbiterNode.scala b/src/main/scala/utils/BinaryArbiterNode.scala deleted file mode 100644 index c9f89161a..000000000 --- a/src/main/scala/utils/BinaryArbiterNode.scala +++ /dev/null @@ -1,106 +0,0 @@ -package utils - - -import chisel3._ -import chisel3.util._ -import chipsalliance.rocketchip.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.util.BundleField -import huancun.XbarCircuit - - -case class BinaryArbiterNode -( - clientFn: Seq[TLMasterPortParameters] => TLMasterPortParameters, - managerFn: Seq[TLSlavePortParameters] => TLSlavePortParameters -)(implicit valName: ValName) extends TLCustomNode { - - override def resolveStar(iKnown: Int, oKnown: Int, iStars: Int, oStars: Int): (Int, Int) = { - require(iStars == 0 && oKnown == 0 && oStars == 1) - if(iKnown < 4) { - (0, 1) - } else { - require(2 * (iKnown / 2) == iKnown) - (0, 2) - } - } - - override def mapParamsD(n: Int, p: Seq[TLClientPortParameters]): Seq[TLClientPortParameters] = { - if(n == 1){ - Seq(clientFn(p)) - } else { - require(n == 2) - p.grouped(2).toList.transpose.map(grp => clientFn(grp)) - } - } - - override def mapParamsU(n: Int, p: Seq[TLManagerPortParameters]): Seq[TLManagerPortParameters] = { - Seq.fill(n)(p.head) - } -} - -class BinaryArbiter(policy: TLArbiter.Policy)(implicit p: Parameters) extends LazyModule { - - val node = BinaryArbiterNode( - clientFn = { seq => - seq.head.v1copy( - echoFields = BundleField.union(seq.flatMap(_.echoFields)), - requestFields = BundleField.union(seq.flatMap(_.requestFields)), - responseKeys = seq.flatMap(_.responseKeys).distinct, - minLatency = seq.map(_.minLatency).min, - clients = (TLXbar.mapInputIds(seq) zip seq) flatMap { case (range, port) => - port.clients map { client => - client.v1copy( - sourceId = client.sourceId.shift(range.start) - ) - } - } - ) - }, - managerFn = { seq => - val fifoIdFactory = TLXbar.relabeler() - seq.head.v1copy( - responseFields = BundleField.union(seq.flatMap(_.responseFields)), - requestKeys = seq.flatMap(_.requestKeys).distinct, - minLatency = seq.map(_.minLatency).min, - endSinkId = TLXbar.mapOutputIds(seq).map(_.end).max, - managers = seq.flatMap { port => - require(port.beatBytes == seq.head.beatBytes, - s"Xbar ($name with parent $parent) data widths don't match: ${port.managers.map(_.name)} has ${port.beatBytes}B vs ${seq(0).managers.map(_.name)} has ${seq(0).beatBytes}B") - val fifoIdMapper = fifoIdFactory() - port.managers map { manager => - manager.v1copy( - fifoId = manager.fifoId.map(fifoIdMapper(_)) - ) - } - } - )} - ) - - lazy val module = new LazyModuleImp(this){ - - if(node.out.size == 1){ - TLXbar.circuit(policy, node.in, node.out) - } else { - require(node.out.size == 2) - /* - 0, 1, 2, 3 => (0, 2) (1, 3) - */ - val grps = node.in.grouped(2).toList.transpose - require(grps.size == 2) - for((gp, out) <- grps.zip(node.out)){ - val xbar = Module(new XbarCircuit(policy, gp.map(_._2), Seq(out._2))) - xbar.io.in.zip(gp.map(_._1)).foreach(x => x._1 <> x._2) - out._1 <> xbar.io.out.head - } - } - } -} - -object BinaryArbiter { - def apply(policy: TLArbiter.Policy = TLArbiter.roundRobin)(implicit p: Parameters) = { - val arbiter = LazyModule(new BinaryArbiter(policy)) - arbiter.node - } -} diff --git a/src/main/scala/utils/BitUtils.scala b/src/main/scala/utils/BitUtils.scala deleted file mode 100644 index dd188151e..000000000 --- a/src/main/scala/utils/BitUtils.scala +++ /dev/null @@ -1,349 +0,0 @@ -/*************************************************************************************** -* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences -* Copyright (c) 2020-2021 Peng Cheng Laboratory -* -* XiangShan is licensed under Mulan PSL v2. -* You can use this software according to the terms and conditions of the Mulan PSL v2. -* You may obtain a copy of Mulan PSL v2 at: -* http://license.coscl.org.cn/MulanPSL2 -* -* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -* -* See the Mulan PSL v2 for more details. -***************************************************************************************/ - -package utils - -import chisel3._ -import chisel3.util._ - -import scala.math.min - -object RegNextWithEnable { - def apply[T <: Data](data: Valid[T], hasInit: Boolean = true): Valid[T] = { - val next = Wire(data.cloneType) - if (hasInit) { - next.valid := RegNext(data.valid, false.B) - } - else { - next.valid := RegNext(data.valid) - } - next.bits := RegEnable(data.bits, data.valid) - next - } -} - -class CircularShift(data: UInt) { - private def helper(step: Int, isLeft: Boolean): UInt = { - if (step == 0) { - data - } - else { - val splitIndex = if (isLeft) { - data.getWidth - (step % data.getWidth) - } else { - step % data.getWidth - } - Cat(data(splitIndex - 1, 0), data(data.getWidth - 1, splitIndex)) - } - } - def left(step: Int): UInt = helper(step, true) - def right(step: Int): UInt = helper(step, false) -} - -object CircularShift { - def apply(data: UInt): CircularShift = new CircularShift(data) -} - -object WordShift { - def apply(data: UInt, wordIndex: UInt, step: Int): UInt = (data << (wordIndex * step.U)).asUInt -} - -object MaskExpand { - def apply(m: UInt, maskWidth: Int = 8): UInt = Cat(m.asBools.map(Fill(maskWidth, _)).reverse) - def apply(m: Seq[Bool], maskWidth: Int): Vec[UInt] = VecInit(m.map(Fill(maskWidth, _))) -} - -object MaskData { - def apply(oldData: UInt, newData: UInt, fullmask: UInt): UInt = { - require(oldData.getWidth <= fullmask.getWidth, s"${oldData.getWidth} < ${fullmask.getWidth}") - require(newData.getWidth <= fullmask.getWidth, s"${newData.getWidth} < ${fullmask.getWidth}") - (newData & fullmask) | (oldData & (~fullmask).asUInt) - } -} - -object SignExt { - def apply(a: UInt, len: Int): UInt = { - val aLen = a.getWidth - val signBit = a(aLen-1) - if (aLen >= len) a(len-1,0) else Cat(Fill(len - aLen, signBit), a) - } -} - -object ZeroExt { - def apply(a: UInt, len: Int): UInt = { - val aLen = a.getWidth - if (aLen >= len) a(len-1,0) else Cat(0.U((len - aLen).W), a) - } -} - -object Or { - // Fill 1s from low bits to high bits - def leftOR(x: UInt): UInt = leftOR(x, x.getWidth, x.getWidth) - def leftOR(x: UInt, width: Integer, cap: Integer = 999999): UInt = { - val stop = min(width, cap) - def helper(s: Int, x: UInt): UInt = - if (s >= stop) x else helper(s+s, x | (x << s)(width-1,0)) - helper(1, x)(width-1, 0) - } - - // Fill 1s form high bits to low bits - def rightOR(x: UInt): UInt = rightOR(x, x.getWidth, x.getWidth) - def rightOR(x: UInt, width: Integer, cap: Integer = 999999): UInt = { - val stop = min(width, cap) - def helper(s: Int, x: UInt): UInt = - if (s >= stop) x else helper(s+s, x | (x >> s).asUInt) - helper(1, x)(width-1, 0) - } -} - -object OneHot { - def OH1ToOH(x: UInt): UInt = ((x << 1).asUInt | 1.U) & (~Cat(0.U(1.W), x)).asUInt - def OH1ToUInt(x: UInt): UInt = OHToUInt(OH1ToOH(x)) - def UIntToOH1(x: UInt, width: Int): UInt = (~((-1).S(width.W).asUInt << x)(width-1, 0)).asUInt - def UIntToOH1(x: UInt): UInt = UIntToOH1(x, (1 << x.getWidth) - 1) - def checkOneHot(in: Bits): Unit = assert(PopCount(in) <= 1.U) - def checkOneHot(in: Iterable[Bool]): Unit = assert(PopCount(in) <= 1.U) -} - -object LowerMask { - def apply(a: UInt, len: Int): UInt = { - ParallelOR((0 until len).map(i => (a >> i).asUInt)) - } - def apply(a: UInt): UInt = { - apply(a, a.getWidth) - } -} - -object HigherMask { - def apply(a: UInt, len: Int) = { - Reverse(LowerMask(Reverse(a), len)) - } - def apply(a: UInt): UInt = { - apply(a, a.getWidth) - } -} - -object LowerMaskFromLowest { - def apply(a: UInt) = { - LowerMask(PriorityEncoderOH(a)) - } -} - -object HigherMaskFromHighest { - def apply(a: UInt) = { - Reverse(LowerMask(PriorityEncoderOH(Reverse(a)))) - } -} - -object LowestBit { - def apply(a: UInt, len: Int) = { - Mux(a(0), 1.U(len.W), Reverse((ParallelOR((0 until len).map(i => Reverse(a(len - 1, 0)) >> i.U)) + 1.U) >> 1.U)) - } -} - -object HighestBit { - def apply(a: UInt, len: Int) = { - Reverse(LowestBit(Reverse(a), len)) - } -} - -object GenMask { - // generate w/r mask - def apply(high: Int, low: Int) = { - require(high > low) - (VecInit(List.fill(high+1)(true.B)).asUInt >> low << low).asUInt() - } - def apply(pos: Int) = { - (1.U << pos).asUInt() - } -} - -object UIntToMask { - def apply(ptr: UInt, length: Integer) = leftmask(ptr, length) - def reverseUInt(input: UInt): UInt = { - VecInit(input.asBools.reverse).asUInt - } - def leftmask(ptr: UInt, length: Integer) = UIntToOH(ptr)(length - 1, 0) - 1.U - def rightmask(ptr: UInt, length: Integer) = reverseUInt(reverseUInt(UIntToOH(ptr)(length - 1, 0)) - 1.U) -} - -object GetEvenBits { - def apply(input: UInt): UInt = { - VecInit((0 until input.getWidth/2).map(i => {input(2*i)})).asUInt - } - def reverse(input: UInt): UInt = { - VecInit((0 until input.getWidth * 2).map(i => { - if(i % 2 == 0) input(i/2) else false.B - })).asUInt - } -} - - -object GetOddBits { - def apply(input: UInt): UInt = { - VecInit((0 until input.getWidth/2).map(i => {input(2*i+1)})).asUInt - } - def reverse(input: UInt): UInt = { - VecInit((0 until input.getWidth * 2).map(i => { - if(i % 2 == 0) false.B else input(i/2) - })).asUInt - } -} - -object GetRemBits { - def apply(div: Int)(input: UInt): Seq[UInt] = { - (0 until div).map(rem => VecInit((0 until input.getWidth / div).map(i => input(div * i + rem))).asUInt) - } - def reverse(div: Int)(input: Seq[UInt]): Seq[UInt] = { - (0 until div).map(rem => VecInit((0 until input(rem).getWidth * div).map(i => { - if (i % div == rem) input(rem)(i / div) else 0.B - })).asUInt) - } -} - -object XORFold { - def apply(input: UInt, resWidth: Int): UInt = { - require(resWidth > 0) - val fold_range = (input.getWidth + resWidth - 1) / resWidth - val value = ZeroExt(input, fold_range * resWidth) - ParallelXOR((0 until fold_range).map(i => value(i*resWidth+resWidth-1, i*resWidth))) - } -} - -object OnesMoreThan { - def apply(input: Seq[Bool], thres: Int): Bool = { - if (thres == 0) { - true.B - } - else if (input.length < thres) { - false.B - } - else if (thres == 1) { - VecInit(input).asUInt.orR - } - else { - val tail = input.drop(1) - input(0) && OnesMoreThan(tail, thres - 1) || OnesMoreThan(tail, thres) - } - } -} - -abstract class SelectOne { - def getNthOH(n: Int): (Bool, Vec[Bool]) -} - -class NaiveSelectOne(bits: Seq[Bool], max_sel: Int = -1) extends SelectOne { - val n_bits = bits.length - val n_sel = if (max_sel > 0) max_sel else n_bits - require(n_bits > 0 && n_sel > 0 && n_bits >= n_sel) - private val matrix = Wire(Vec(n_bits, Vec(n_sel, Bool()))) - // matrix[i][j]: first i bits has j one's - for (i <- 0 until n_bits) { - for (j <- 0 until n_sel) { - if (j == 0) { - matrix(i)(j) := (if (i == 0) true.B else !Cat(bits.take(i)).orR) - } - // it's impossible to select j-th one from i elements - else if (i < j) { - matrix(i)(j) := false.B - } - else { - matrix(i)(j) := bits(i - 1) && matrix(i - 1)(j - 1) || !bits(i - 1) && matrix(i - 1)(j) - } - } - } - - def getNthOH(n: Int): (Bool, Vec[Bool]) = { - require(n > 0, s"$n should be positive to select the n-th one") - require(n <= n_sel, s"$n should not be larger than $n_sel") - // bits(i) is true.B and bits(i - 1, 0) has n - 1 - val selValid = OnesMoreThan(bits, n) - val sel = VecInit(bits.zip(matrix).map{ case (b, m) => b && m(n - 1) }) - (selValid, sel) - } -} - -class CircSelectOne(bits: Seq[Bool], max_sel: Int = -1) extends SelectOne { - val n_bits = bits.length - val n_sel = if (max_sel > 0) max_sel else n_bits - require(n_bits > 0 && n_sel > 0 && n_bits >= n_sel) - - val sel_forward = new NaiveSelectOne(bits, (n_sel + 1) / 2) - val sel_backward = new NaiveSelectOne(bits.reverse, n_sel / 2) - val moreThan = Seq(1, 2).map(i => OnesMoreThan(bits, i)) - - def getNthOH(n: Int): (Bool, Vec[Bool]) = { - val selValid = OnesMoreThan(bits, n) - val sel_index = (n + 1) / 2 - if (n % 2 == 1) { - (selValid, sel_forward.getNthOH(sel_index)._2) - } - else { - (selValid, VecInit(sel_backward.getNthOH(sel_index)._2.reverse)) - } - } -} - -class OddEvenSelectOne(bits: Seq[Bool], max_sel: Int = -1) extends SelectOne { - val n_bits = bits.length - val n_sel = if (max_sel > 0) max_sel else n_bits - require(n_bits > 0 && n_sel > 0 && n_bits >= n_sel) - require(n_sel > 1, "Select only one entry via OddEven causes odd entries to be ignored") - - val n_even = (n_bits + 1) / 2 - val sel_even = new CircSelectOne((0 until n_even).map(i => bits(2 * i)), n_sel / 2) - val n_odd = n_bits / 2 - val sel_odd = new CircSelectOne((0 until n_odd).map(i => bits(2 * i + 1)), (n_sel + 1) / 2) - - def getNthOH(n: Int): (Bool, Vec[Bool]) = { - val sel_index = (n + 1) / 2 - if (n % 2 == 1) { - val selected = sel_even.getNthOH(sel_index) - val sel = VecInit((0 until n_bits).map(i => if (i % 2 == 0) selected._2(i / 2) else false.B)) - (selected._1, sel) - } - else { - val selected = sel_odd.getNthOH(sel_index) - val sel = VecInit((0 until n_bits).map(i => if (i % 2 == 1) selected._2(i / 2) else false.B)) - (selected._1, sel) - } - } -} - -class CenterSelectOne(bits: Seq[Bool], max_sel: Int = -1) extends SelectOne { - require(max_sel == 2, "only 2 is supported!") - val n_bits = bits.length - val half_index = (bits.length + 1) / 2 - def centerReverse(data: Seq[Bool]): Seq[Bool] = data.take(half_index).reverse ++ data.drop(half_index).reverse - val select = new CircSelectOne(centerReverse(bits), max_sel) - - def getNthOH(n: Int): (Bool, Vec[Bool]) = { - val selected = select.getNthOH(n) - (selected._1, VecInit(centerReverse(selected._2))) - } -} - -object SelectOne { - def apply(policy: String, bits: Seq[Bool], max_sel: Int = -1): SelectOne = { - policy.toLowerCase match { - case "naive" => new NaiveSelectOne(bits, max_sel) - case "circ" => new CircSelectOne(bits, max_sel) - case "oddeven" => new OddEvenSelectOne(bits, max_sel) - case "center" => new CenterSelectOne(bits, max_sel) - case _ => throw new IllegalArgumentException(s"unknown select policy") - } - } -} diff --git a/src/main/scala/utils/CircularQueuePtr.scala b/src/main/scala/utils/CircularQueuePtr.scala deleted file mode 100644 index 64835576d..000000000 --- a/src/main/scala/utils/CircularQueuePtr.scala +++ /dev/null @@ -1,113 +0,0 @@ -/*************************************************************************************** -* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences -* Copyright (c) 2020-2021 Peng Cheng Laboratory -* -* XiangShan is licensed under Mulan PSL v2. -* You can use this software according to the terms and conditions of the Mulan PSL v2. -* You may obtain a copy of Mulan PSL v2 at: -* http://license.coscl.org.cn/MulanPSL2 -* -* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -* -* See the Mulan PSL v2 for more details. -***************************************************************************************/ - -package utils - -import chipsalliance.rocketchip.config.Parameters -import chisel3._ -import chisel3.util._ - -class CircularQueuePtr[T <: CircularQueuePtr[T]](val entries: Int) extends Bundle { - - def this(f: Parameters => Int)(implicit p: Parameters) = this(f(p)) - - val PTR_WIDTH = log2Up(entries) - val flag = Bool() - val value = UInt(PTR_WIDTH.W) - - override def toPrintable: Printable = { - p"$flag:$value" - } - - final def +(v: UInt): T = { - val entries = this.entries - val new_ptr = Wire(this.asInstanceOf[T].cloneType) - if(isPow2(entries)){ - new_ptr := (Cat(this.flag, this.value) + v).asTypeOf(new_ptr) - } else { - val new_value = this.value +& v - val diff = Cat(0.U(1.W), new_value).asSInt() - Cat(0.U(1.W), entries.U.asTypeOf(new_value)).asSInt() - val reverse_flag = diff >= 0.S - new_ptr.flag := Mux(reverse_flag, !this.flag, this.flag) - new_ptr.value := Mux(reverse_flag, - diff.asUInt(), - new_value - ) - } - new_ptr - } - - final def -(v: UInt): T = { - val flipped_new_ptr = this + (this.entries.U - v) - val new_ptr = Wire(this.asInstanceOf[T].cloneType) - new_ptr.flag := !flipped_new_ptr.flag - new_ptr.value := flipped_new_ptr.value - new_ptr - } - - final def === (that_ptr: T): Bool = this.asUInt()===that_ptr.asUInt() - - final def =/= (that_ptr: T): Bool = this.asUInt()=/=that_ptr.asUInt() - - def toOH: UInt = UIntToOH(value, entries) -} - -trait HasCircularQueuePtrHelper { - - def isEmpty[T <: CircularQueuePtr[T]](enq_ptr: T, deq_ptr: T): Bool = { - enq_ptr === deq_ptr - } - - def isFull[T <: CircularQueuePtr[T]](enq_ptr: T, deq_ptr: T): Bool = { - (enq_ptr.flag =/= deq_ptr.flag) && (enq_ptr.value === deq_ptr.value) - } - - def distanceBetween[T <: CircularQueuePtr[T]](enq_ptr: T, deq_ptr: T): UInt = { - assert(enq_ptr.entries == deq_ptr.entries) - Mux(enq_ptr.flag === deq_ptr.flag, - enq_ptr.value - deq_ptr.value, - enq_ptr.entries.U + enq_ptr.value - deq_ptr.value) - } - - def isAfter[T <: CircularQueuePtr[T]](left: T, right: T): Bool = { - val differentFlag = left.flag ^ right.flag - val compare = left.value > right.value - differentFlag ^ compare - } - - def isBefore[T <: CircularQueuePtr[T]](left: T, right: T): Bool = { - val differentFlag = left.flag ^ right.flag - val compare = left.value < right.value - differentFlag ^ compare - } -} - -// Should only be used when left and right are continuous pointers. -class QPtrMatchMatrix[T <: CircularQueuePtr[T]](left: Seq[T], right: Seq[T]) { - val matrix = left.map(l => right.map(_.value === l.value)) - - def apply(leftIndex: Int, rightIndex: Int): Bool = { - require(leftIndex < left.length && rightIndex < right.length) - if (leftIndex == 0 || rightIndex == 0) { - matrix(leftIndex)(rightIndex) - } - else { - apply(leftIndex - 1, rightIndex - 1) - } - } - def apply(leftIndex: Int): Seq[Bool] = right.indices.map(i => apply(leftIndex, i)) -} - diff --git a/src/main/scala/utils/DataModuleTemplate.scala b/src/main/scala/utils/DataModuleTemplate.scala deleted file mode 100644 index 4f6080fe2..000000000 --- a/src/main/scala/utils/DataModuleTemplate.scala +++ /dev/null @@ -1,238 +0,0 @@ -/*************************************************************************************** -* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences -* Copyright (c) 2020-2021 Peng Cheng Laboratory -* -* XiangShan is licensed under Mulan PSL v2. -* You can use this software according to the terms and conditions of the Mulan PSL v2. -* You may obtain a copy of Mulan PSL v2 at: -* http://license.coscl.org.cn/MulanPSL2 -* -* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -* -* See the Mulan PSL v2 for more details. -***************************************************************************************/ - -package utils - -import chisel3._ -import chisel3.util._ - -class RawDataModuleTemplate[T <: Data]( - gen: T, - numEntries: Int, - numRead: Int, - numWrite: Int, - isSync: Boolean, - optWrite: Seq[Int] = Seq() -) extends Module { - val io = IO(new Bundle { - val rvec = Vec(numRead, Input(UInt(numEntries.W))) - val rdata = Vec(numRead, Output(gen)) - val wen = Vec(numWrite, Input(Bool())) - val wvec = Vec(numWrite, Input(UInt(numEntries.W))) - val wdata = Vec(numWrite, Input(gen)) - }) - - val data = Reg(Vec(numEntries, gen)) - - val wen = io.wen.zipWithIndex.map{ case (en, i) => if (optWrite.contains(i)) RegNext(en) else en } - val wvec = io.wvec.zipWithIndex.map{ case (v, i) => if (optWrite.contains(i)) RegEnable(v, io.wen(i)) else v } - val wdata = io.wdata.zipWithIndex.map{ case (d, i) => if (optWrite.contains(i)) RegEnable(d, io.wen(i)) else d } - - // read ports - val rvec = if (isSync) RegNext(io.rvec) else io.rvec - for (i <- 0 until numRead) { - assert(PopCount(rvec(i)) <= 1.U) - io.rdata(i) := Mux1H(rvec(i), data) - } - - if (optWrite.nonEmpty) { - val data_next = WireInit(data) - val wbypass = io.wen.zip(io.wvec).zip(wdata).zipWithIndex.filter(x => optWrite.contains(x._2)).map(_._1) - for (i <- 0 until numEntries) { - val wbypass_en = wbypass.map(w => RegNext(w._1._1 && w._1._2(i))) - when (VecInit(wbypass_en).asUInt.orR) { - data_next(i) := Mux1H(wbypass_en, wbypass.map(_._2)) - } - } - for (i <- 0 until numRead) { - io.rdata(i) := Mux1H(rvec(i), data_next) - } - } - - // write ports - for (i <- 0 until numEntries) { - val w = VecInit((0 until numWrite).map(j => wen(j) && wvec(j)(i))) - assert(PopCount(w) <= 1.U, s"RawDatModule multi-write index:$i") - when (w.asUInt.orR) { - data(i) := Mux1H(w, wdata) - } - } -} - - -class SyncRawDataModuleTemplate[T <: Data]( - gen: T, numEntries: Int, numRead: Int, numWrite: Int, optWrite: Seq[Int] = Seq() -) extends RawDataModuleTemplate(gen, numEntries, numRead, numWrite, true, optWrite) -class AsyncRawDataModuleTemplate[T <: Data]( - gen: T, numEntries: Int, numRead: Int, numWrite: Int, optWrite: Seq[Int] = Seq() -) extends RawDataModuleTemplate(gen, numEntries, numRead, numWrite, false, optWrite) - -class SyncDataModuleTemplate[T <: Data]( - gen: T, - numEntries: Int, - numRead: Int, - numWrite: Int, - parentModule: String = "", - concatData: Boolean = false, - perReadPortBypassEnable: Option[Seq[Boolean]] = None -) extends Module { - val io = IO(new Bundle { - val raddr = Vec(numRead, Input(UInt(log2Ceil(numEntries).W))) - val rdata = Vec(numRead, Output(gen)) - val wen = Vec(numWrite, Input(Bool())) - val waddr = Vec(numWrite, Input(UInt(log2Ceil(numEntries).W))) - val wdata = Vec(numWrite, Input(gen)) - }) - - override def desiredName: String = s"SyncDataModuleTemplate_${parentModule}_${numEntries}entry" - val dataType = if (concatData) UInt(gen.getWidth.W) else gen - - val maxBankEntries = if (numEntries >= 2 * 64) 64 else 16 - val numBanks = (numEntries + maxBankEntries - 1) / maxBankEntries - def bankOffset(address: UInt): UInt = { - if (numBanks > 1) address(log2Ceil(maxBankEntries) - 1, 0) - else address - } - def bankIndex(address: UInt): UInt = { - if (numBanks > 1) address(log2Ceil(numEntries) - 1, log2Ceil(maxBankEntries)) - else 0.U - } - - // if use bypassEnable to control bypass of each port, - // then we should have a separate bit for each read port - perReadPortBypassEnable.map(en_vec => require(en_vec.length == numRead)) - - val dataBanks = Seq.tabulate(numBanks)(i => { - val bankEntries = if (i < numBanks - 1) maxBankEntries else numEntries - (i * maxBankEntries) - val dataBank = Module(new NegedgeDataModuleTemplate(dataType, bankEntries, numRead, numWrite, parentModule, perReadPortBypassEnable)) - - // delay one clock - val raddr_dup = RegNext(io.raddr) - val wen_dup = RegNext(io.wen) - val waddr_dup = io.wen.zip(io.waddr).map(w => RegEnable(w._2, w._1)) - - // input - dataBank.io.raddr := raddr_dup.map(bankOffset) - dataBank.io.wen := wen_dup.zip(waddr_dup).map{ case (en, addr) => en && bankIndex(addr) === i.U } - dataBank.io.waddr := waddr_dup.map(bankOffset) - if (concatData) { - val wdata_dup = io.wen.zip(io.wdata).map(w => RegEnable(w._2.asTypeOf(dataType), w._1)) - dataBank.io.wdata := wdata_dup - } - else { - dataBank.io.wdata := io.wen.zip(io.wdata).map(w => RegEnable(w._2, w._1)) - } - - dataBank - }) - - // output - val rdata = if (concatData) dataBanks.map(_.io.rdata.map(_.asTypeOf(gen))) else dataBanks.map(_.io.rdata) - for (j <- 0 until numRead) { - val raddr_dup = RegNext(io.raddr(j)) - val index_dec = UIntToOH(bankIndex(raddr_dup), numBanks) - io.rdata(j) := Mux1H(index_dec, rdata.map(_(j))) - } -} - -class NegedgeDataModuleTemplate[T <: Data]( - gen: T, - numEntries: Int, - numRead: Int, - numWrite: Int, - parentModule: String, - perReadPortBypassEnable: Option[Seq[Boolean]] = None -) extends Module { - val io = IO(new Bundle { - val raddr = Vec(numRead, Input(UInt(log2Ceil(numEntries).W))) - val rdata = Vec(numRead, Output(gen)) - val wen = Vec(numWrite, Input(Bool())) - val waddr = Vec(numWrite, Input(UInt(log2Ceil(numEntries).W))) - val wdata = Vec(numWrite, Input(gen)) - }) - - override def desiredName: String = s"NegedgeDataModule_${parentModule}_${numEntries}entry" - val data = Reg(Vec(numEntries, gen)) - - // if use bypassEnable to control bypass of each port, - // then we should have a separate bit for each read port - perReadPortBypassEnable.map(en_vec => require(en_vec.length == numRead)) - // read ports - for (i <- 0 until numRead) { - val bypass_en = perReadPortBypassEnable.map(_(i)).getOrElse(true) - val read_by = io.wen.zip(io.waddr).map(w => w._1 && w._2 === io.raddr(i) && bypass_en.B) - val addr_dec = UIntToOH(io.raddr(i), numEntries) - when (VecInit(read_by).asUInt.orR) { - io.rdata(i) := Mux1H(read_by, io.wdata) - } .otherwise { - io.rdata(i) := Mux1H(addr_dec, data) - } - } - - // write ports - val waddr_dec = io.waddr.map(a => UIntToOH(a)) - for (j <- 0 until numEntries) { - val write_wen = io.wen.zip(waddr_dec).map(w => w._1 && w._2(j)) - when (VecInit(write_wen).asUInt.orR) { - data(j) := Mux1H(write_wen, io.wdata) - } - } -} - -class Folded1WDataModuleTemplate[T <: Data](gen: T, numEntries: Int, numRead: Int, - isSync: Boolean, width: Int, hasResetEn: Boolean = true) extends Module { - val io = IO(new Bundle { - val raddr = Vec(numRead, Input(UInt(log2Up(numEntries).W))) - val rdata = Vec(numRead, Output(gen)) - val wen = Input(Bool()) - val waddr = Input(UInt(log2Up(numEntries).W)) - val wdata = Input(gen) - val resetEn = if (hasResetEn) Some(Input(Bool())) else None - }) - - require(width > 0 && isPow2(width)) - require(numEntries % width == 0) - - val nRows = numEntries / width - - val data = Mem(nRows, Vec(width, gen)) - - val doing_reset = RegInit(true.B) - if (hasResetEn) { - io.resetEn.map(en => when (en) { doing_reset := true.B }) - } - val resetRow = RegInit(0.U(log2Ceil(nRows).W)) - resetRow := resetRow + doing_reset - when (resetRow === (nRows-1).U) { doing_reset := false.B } - - val raddr = if (isSync) RegNext(io.raddr) else io.raddr - - for (i <- 0 until numRead) { - val addr = raddr(i) >> log2Ceil(width) - val idx = raddr(i)(log2Ceil(width)-1, 0) - io.rdata(i) := Mux(doing_reset, 0.U.asTypeOf(gen), data(addr)(idx)) - } - - val waddr = io.waddr >> log2Ceil(width) - val wmask = UIntToOH(io.waddr(log2Ceil(width)-1, 0)) - val wdata = VecInit(Seq.fill(width)(io.wdata)) - - when(doing_reset) { - data.write(resetRow, 0.U.asTypeOf(Vec(width, gen))) - }.elsewhen(io.wen) { - data.write(waddr, wdata, wmask.asBools) - } -} diff --git a/src/main/scala/utils/ECC.scala b/src/main/scala/utils/ECC.scala deleted file mode 100644 index ee5a38b51..000000000 --- a/src/main/scala/utils/ECC.scala +++ /dev/null @@ -1,230 +0,0 @@ -/*************************************************************************************** -* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences -* Copyright (c) 2020-2021 Peng Cheng Laboratory -* -* XiangShan is licensed under Mulan PSL v2. -* You can use this software according to the terms and conditions of the Mulan PSL v2. -* You may obtain a copy of Mulan PSL v2 at: -* http://license.coscl.org.cn/MulanPSL2 -* -* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -* -* See the Mulan PSL v2 for more details. -***************************************************************************************/ - -// See LICENSE.Berkeley for license details. - -package utils - -import chisel3._ -import chisel3.util._ -import chisel3.util.random.LFSR - -abstract class Decoding -{ - def uncorrected: UInt - def corrected: UInt - def correctable: Bool - def uncorrectable: Bool // If true, correctable should be ignored - def error = correctable || uncorrectable -} - -abstract class Code -{ - def canDetect: Boolean - def canCorrect: Boolean - - def width(w0: Int): Int - - /** Encode x to a codeword suitable for decode. - * If poison is true, the decoded value will report uncorrectable - * error despite uncorrected == corrected == x. - */ - def encode(x: UInt, poison: Bool = false.B): UInt - def decode(x: UInt): Decoding - - /** Copy the bits in x to the right bit positions in an encoded word, - * so that x === decode(swizzle(x)).uncorrected; but don't generate - * the other code bits, so decode(swizzle(x)).error might be true. - * For codes for which this operation is not trivial, throw an - * UnsupportedOperationException. */ - def swizzle(x: UInt): UInt -} - -class IdentityCode extends Code -{ - def canDetect = false - def canCorrect = false - - def width(w0: Int) = w0 - def encode(x: UInt, poison: Bool = false.B) = { - require (poison.isLit && poison.litValue == 0, "IdentityCode can not be poisoned") - x - } - def swizzle(x: UInt) = x - def decode(y: UInt) = new Decoding { - def uncorrected = y - def corrected = y - def correctable = false.B - def uncorrectable = false.B - } -} - -class ParityCode extends Code -{ - def canDetect = true - def canCorrect = false - - def width(w0: Int) = w0+1 - def encode(x: UInt, poison: Bool = false.B) = Cat(x.xorR ^ poison, x) - def swizzle(x: UInt) = Cat(false.B, x) - def decode(y: UInt) = new Decoding { - val uncorrected = y(y.getWidth-2,0) - val corrected = uncorrected - val correctable = false.B - val uncorrectable = y.xorR - } -} - -class SECCode extends Code -{ - def canDetect = true - def canCorrect = true - - // SEC codes may or may not be poisonous depending on the length - // If the code is perfect, every non-codeword is correctable - def poisonous(n: Int) = !isPow2(n+1) - - def width(k: Int) = { - val m = log2Floor(k) + 1 - k + m + (if((1 << m) < m+k+1) 1 else 0) - } - def swizzle(x: UInt) = { - val k = x.getWidth - val n = width(k) - Cat(0.U((n-k).W), x) - } - - // An (n=16, k=11) Hamming code is naturally encoded as: - // PPxPxxxPxxxxxxxP where P are parity bits and x are data - // Indexes typically start at 1, because then the P are on powers of two - // In systematic coding, you put all the data in the front: - // xxxxxxxxxxxPPPPP - // Indexes typically start at 0, because Computer Science - // For sanity when reading SRAMs, you want systematic form. - - private def impl(n: Int, k: Int) = { - require (n >= 3 && k >= 1 && !isPow2(n)) - val hamm2sys = IndexedSeq.tabulate(n+1) { i => - if (i == 0) { - n /* undefined */ - } else if (isPow2(i)) { - k + log2Ceil(i) - } else { - i - 1 - log2Ceil(i) - } - } - val sys2hamm = hamm2sys.zipWithIndex.sortBy(_._1).map(_._2).toIndexedSeq - def syndrome(j: Int) = { - val bit = 1 << j - ("b" + Seq.tabulate(n) { i => - if ((sys2hamm(i) & bit) != 0) "1" else "0" - }.reverse.mkString).U - } - (hamm2sys, sys2hamm, syndrome _) - } - - def encode(x: UInt, poison: Bool = false.B) = { - val k = x.getWidth - val n = width(k) - val (_, _, syndrome) = impl(n, k) - - require ((poison.isLit && poison.litValue == 0) || poisonous(n), s"SEC code of length ${n} cannot be poisoned") - - /* By setting the entire syndrome on poison, the corrected bit falls off the end of the code */ - val syndromeUInt = VecInit.tabulate(n-k) { j => (syndrome(j)(k-1, 0) & x).xorR ^ poison }.asUInt - Cat(syndromeUInt, x) - } - - def decode(y: UInt) = new Decoding { - val n = y.getWidth - val k = n - log2Ceil(n) - val (_, sys2hamm, syndrome) = impl(n, k) - - val syndromeUInt = VecInit.tabulate(n-k) { j => (syndrome(j) & y).xorR }.asUInt - - val hammBadBitOH = UIntToOH(syndromeUInt, n+1) - val sysBadBitOH = VecInit.tabulate(k) { i => hammBadBitOH(sys2hamm(i)) }.asUInt - - val uncorrected = y(k-1, 0) - val corrected = uncorrected ^ sysBadBitOH - val correctable = syndromeUInt.orR - val uncorrectable = if (poisonous(n)) { syndromeUInt > n.U } else { false.B } - } -} - -class SECDEDCode extends Code -{ - def canDetect = true - def canCorrect = true - - private val sec = new SECCode - private val par = new ParityCode - - def width(k: Int) = sec.width(k)+1 - def encode(x: UInt, poison: Bool = false.B) = { - // toggling two bits ensures the error is uncorrectable - // to ensure corrected == uncorrected, we pick one redundant - // bit from SEC (the highest); correcting it does not affect - // corrected == uncorrected. the second toggled bit is the - // parity bit, which also does not appear in the decoding - val toggle_lo = Cat(poison.asUInt, poison.asUInt) - val toggle_hi = toggle_lo << (sec.width(x.getWidth)-1) - par.encode(sec.encode(x)) ^ toggle_hi - } - def swizzle(x: UInt) = par.swizzle(sec.swizzle(x)) - def decode(x: UInt) = new Decoding { - val secdec = sec.decode(x(x.getWidth-2,0)) - val pardec = par.decode(x) - - val uncorrected = secdec.uncorrected - val corrected = secdec.corrected - val correctable = pardec.uncorrectable - val uncorrectable = !pardec.uncorrectable && secdec.correctable - } -} - -object ErrGen -{ - // generate a 1-bit error with approximate probability 2^-f - def apply(width: Int, f: Int): UInt = { - require(width > 0 && f >= 0 && log2Up(width) + f <= 16) - UIntToOH(LFSR(16)(log2Up(width)+f-1,0))(width-1,0) - } - def apply(x: UInt, f: Int): UInt = x ^ apply(x.getWidth, f) -} - -trait CanHaveErrors extends Bundle { - val correctable: Option[ValidIO[UInt]] - val uncorrectable: Option[ValidIO[UInt]] -} - -case class ECCParams( - bytes: Int = 1, - code: Code = new IdentityCode, - notifyErrors: Boolean = false -) - -object Code { - def fromString(s: Option[String]): Code = fromString(s.getOrElse("none")) - def fromString(s: String): Code = s.toLowerCase match { - case "none" => new IdentityCode - case "identity" => new IdentityCode - case "parity" => new ParityCode - case "sec" => new SECCode - case "secded" => new SECDEDCode - case _ => throw new IllegalArgumentException("Unknown ECC type") - } -} diff --git a/src/main/scala/utils/ExcitingUtils.scala b/src/main/scala/utils/ExcitingUtils.scala deleted file mode 100644 index 9f9ec4c43..000000000 --- a/src/main/scala/utils/ExcitingUtils.scala +++ /dev/null @@ -1,115 +0,0 @@ -/*************************************************************************************** -* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences -* Copyright (c) 2020-2021 Peng Cheng Laboratory -* -* XiangShan is licensed under Mulan PSL v2. -* You can use this software according to the terms and conditions of the Mulan PSL v2. -* You may obtain a copy of Mulan PSL v2 at: -* http://license.coscl.org.cn/MulanPSL2 -* -* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -* -* See the Mulan PSL v2 for more details. -***************************************************************************************/ - -package chisel3 - -import chisel3.internal.NamedComponent -import chisel3.util.experimental.BoringUtils -import scala.collection.mutable - -object ExcitingUtils { - - object ConnectionType extends Enumeration { - val Perf = Value("perf") - val Func = Value("func") - val Debug = Value("debug") - } - - type ConnectionType = ConnectionType.Value - val Perf = ConnectionType.Perf - val Func = ConnectionType.Func - val Debug = ConnectionType.Debug - - private def strToErrorMsg(str: String) = "\u001b[1m\u001b[;31m"+ str +"\u001b[0m" - - private class Connection - ( - var connType: ConnectionType, - var sourceModule: Option[String] = None, - var sinkModule: Option[String] = None, - var warned: Boolean = false - ){ - - override def toString: String = - s"type:[$connType] source location:[${sourceModule.getOrElse(strToErrorMsg("Not Found"))}]" + - s" sink location:[${sinkModule.getOrElse(strToErrorMsg("Not Found"))}]" - - def isLegalConnection: Boolean = sourceModule.nonEmpty && sinkModule.nonEmpty - } - - private val map = mutable.LinkedHashMap[String, Connection]() - - def addSource - ( - component: NamedComponent, - name: String, - connType: ConnectionType = Func, - disableDedup: Boolean = false, - uniqueName: Boolean = false - ): String = { - val conn = map.getOrElseUpdate(name, new Connection(connType)) - if (!conn.sourceModule.isEmpty && !conn.warned) { - println(s"[WARN] Signal |$name| has multiple sources") - conn.warned = true - } - require(conn.connType == connType) - conn.sourceModule = Some(component.parentModName) - BoringUtils.addSource(component, name, disableDedup, uniqueName) - } - - def addSink - ( - component: InstanceId, - name: String, - connType: ConnectionType = Func, - disableDedup: Boolean = false, - forceExists: Boolean = false - ): Unit = { - val conn = map.getOrElseUpdate(name, new Connection(connType)) - if (!conn.sinkModule.isEmpty && !conn.warned) { - println(s"[WARN] Signal |$name| has multiple sinks") - conn.warned = true - } - require(conn.connType == connType) - conn.sinkModule = Some(component.parentModName) - BoringUtils.addSink(component, name, disableDedup, forceExists) - } - - def fixConnections(): Unit ={ - val dontCare = WireInit(0.U) - for((name, conn) <- map){ - if(conn.sinkModule.isEmpty){ - addSink(dontCare, name, conn.connType) - } - if(conn.sourceModule.isEmpty){ - addSource(dontCare, name, conn.connType) - } - } - } - - - def checkAndDisplay(): Unit = { - var legal = true - val buf = new mutable.StringBuilder() - for((id, conn) <- map){ - buf ++= s"Connection:[$id] $conn\n" - if(!conn.isLegalConnection) legal = false - } - print(buf) - require(legal, strToErrorMsg("Error: Illegal connection found!")) - } - -} diff --git a/src/main/scala/utils/ExtractVerilogModules.scala b/src/main/scala/utils/ExtractVerilogModules.scala deleted file mode 100644 index a4bbc829e..000000000 --- a/src/main/scala/utils/ExtractVerilogModules.scala +++ /dev/null @@ -1,232 +0,0 @@ -/*************************************************************************************** -* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences -* Copyright (c) 2020-2021 Peng Cheng Laboratory -* -* XiangShan is licensed under Mulan PSL v2. -* You can use this software according to the terms and conditions of the Mulan PSL v2. -* You may obtain a copy of Mulan PSL v2 at: -* http://license.coscl.org.cn/MulanPSL2 -* -* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -* -* See the Mulan PSL v2 for more details. -***************************************************************************************/ - -package utils - -/* - https://github.com/Lingrui98/scalaTage/blob/vme/src/main/scala/getVerilogModules.scala - */ - -import scala.io.Source -import java.io._ -import scala.language.postfixOps -import sys.process._ -import sys._ - -class VerilogModuleExtractor { - // name - val modulePattern = "module ([\\w]+)\\(".r.unanchored - // type name - val subMoudlePattern = "([\\w]+) ([\\w]+) \\((?: //.*)*\\Z".r.unanchored - val endMoudleIOPattern = "\\);".r.unanchored - val endMoudlePattern = "endmodule".r.unanchored - - // (submoudle type, submoudle name) - type SubMoudleRecord = Tuple2[String, String] - - // (content, submodules) - type ModuleRecord = Tuple2[List[String], List[SubMoudleRecord]] - // name - type ModuleMap = Map[String, ModuleRecord] - - def getLines(s: scala.io.BufferedSource): Iterator[String] = s.getLines() - - def makeRecord(s: Iterator[String]): ModuleMap = { - val m: ModuleMap = Map() - // called before we see the first line of a module - def processModule(firstLine: String, it: Iterator[String]): ModuleRecord = { - val content: List[String] = List(firstLine) - val submodules: List[SubMoudleRecord] = List() - def iter(cont: List[String], subm: List[SubMoudleRecord]): ModuleRecord = - it.next() match { - case l: String => l match { - case endMoudlePattern() => (l :: cont, subm) - case subMoudlePattern(ty, name) => - // println(s"submoudle $ty $name") - iter(l :: cont, (ty, name) :: subm) - case _ => iter(l :: cont, subm) - } - case _ => println("Should not reach here"); (cont, subm) - } - val temp = iter(content, submodules) - (temp._1.reverse, temp._2) - } - def traverse(m: ModuleMap, it: Iterator[String]): ModuleMap = - if (it.hasNext) { - it.next() match { - case l: String => - // println(f"traversing $l") - l match { - case modulePattern(name) => - // println(f"get Module of name $name") - traverse(m ++ Map(name -> processModule(l, it)), it) - case _ => - println(f"line $l is not a module definition") - traverse(m, it) - } - case _ => traverse(m, it) - } - } - else m - - traverse(m, s) - } - - def makeRecordFromFile(file: String): ModuleMap = { - val bufSrc = Source.fromFile(file) - makeRecord(bufSrc.getLines()) - } - - def writeModuleToFile(name: String, record: ModuleRecord, dir: String) = { - val path = dir+name+".v" - val writer = new PrintWriter(new File(path)) - println(f"Writing module $name%20s to $path") - record._1.foreach(r => { - writer.write(f"$r\n") - }) - writer.close() - } - - // get moudle definition of specified name - def getModule(name: String, m: ModuleMap): ModuleRecord = { - m(name) - } - - def showModuleRecord(r: ModuleRecord) = { - val (content, submodules) = r - submodules.foreach { - case (t, n) => println(f"submoudle type: $t, submodule name: $n") - } - println("\nprinting module contents...") - content.foreach(println(_)) - } - - // We first get records of all the modules and its submodule record - // Then we choose a module as the root node to traverse its submodule - def processFromModule(name: String, map: ModuleMap, outPath: String, doneSet: Set[String] = Set(), top: Tuple2[String, Boolean]): Unit = { - def printSRAMs(sub: List[SubMoudleRecord]) = { - sub map { - case (ty, subn) if (ty contains "SRAM") => println(s"top module $name, sub module type $ty, name $subn") - case _ => - } - } - val (topName, isTop) = top - if (!map.contains(name)) { - println(s"${if (isTop) "chosen top" else s"submodule of ${topName},"} module $name does not exist!") - return - } - if (isTop) println(s"\nProcessing top module $name") - val r = map(name) - new File(outPath).mkdirs() // ensure the path exists - writeModuleToFile(name, r, outPath) - val submodules = r._2 - // printSRAMs(submodules) - // DFS - val subTypesSet = submodules map (m => m._1) toSet - val nowMap = map - name - val nowSet = doneSet ++ subTypesSet - subTypesSet.foreach { s => if (!doneSet.contains(s)) processFromModule(s, nowMap, outPath, nowSet, (if (isTop) name else topName, false)) } - } - - def getDate: String = { - val d = java.time.LocalDate.now - d.toString.toCharArray.filterNot(_ == '-').mkString - } - - def makePath(topModule: String, outDir: String , user: String = "glr"): String = { - (if (outDir.last == '/') - outDir - else - outDir+"/") + getDate + "-" + user + "-" + topModule + "/" - } - - - - def extract(src: String, topModule: String, outDir: String, user: String, mapp: Option[ModuleMap]): Unit = { - val useMap = mapp.getOrElse(makeRecordFromFile(src)) - val path = makePath(topModule, outDir, user) - processFromModule(topModule, useMap, path, top=(topModule, true)) - } - - def extract(src: String, topModules: List[String], outDir: String, user: String): Unit = { - // avoid repeat - val mapp = makeRecordFromFile(src) - topModules.foreach(n => extract(src, n, outDir, user, Some(mapp))) - } -} - -trait VMEArgParser { - type OptionMap = Map[String, Option[Any]] - - val usage = """ - Usage: sbt "run [OPTION...]" - -s, --source the verilog file generated by chisel, all in one file - default: $NOOP_HOME/build/XSSimTop.v - -h, --help print this help info - -o, --output the place you want to store your extracted verilog - default: $NOOP_HOME/build/extracted - -u, --usr your name, will be used to name the output folder - default: current user - -m, --modules the top modules you would like to extract verilog from - should always be the last argument - default: IFU - """ - - def parse(args: List[String]) = { - def nextOption(map: OptionMap, l: List[String]): OptionMap = { - def isSwitch(s : String)= (s(0) == '-') - l match { - case Nil => map - case ("--help" | "-h") :: tail => { - println(usage) - sys.exit() - map - } - case ("--source" | "-s") :: file :: tail => - nextOption(map ++ Map("source" -> Some(file)), tail) - case ("--output" | "-o") :: path :: tail => - nextOption(map ++ Map("output" -> Some(path)), tail) - case ("--usr" | "-u") :: name :: tail => - nextOption(map ++ Map("usr" -> Some(name)), tail) - // this should always be the last argument, since it is length variable - case ("--modules" | "-m") :: m :: tail => - map ++ Map("modules" -> Some(m :: tail)) - case s :: tail => { - if (isSwitch(s)) println(s"unexpected argument $s") - nextOption(map, tail) - } - } - } - nextOption(Map("source" -> None, "output" -> None, "usr" -> None, "modules" -> None), args) - } - - def wrapParams(args: Array[String]): (String, List[String], String, String) = { - val argL = args.toList - val paramMap = parse(argL) - (paramMap("source").map(_.asInstanceOf[String]).getOrElse(env("NOOP_HOME")+"/build/XSSimTop.v"), - paramMap("modules").map(_.asInstanceOf[List[String]]).getOrElse(List("IFU")), - paramMap("output").map(_.asInstanceOf[String]).getOrElse(env("NOOP_HOME")+"/build/extracted/"), - paramMap("usr").map(_.asInstanceOf[String]).getOrElse("whoami".!!.init)) - } -} - -object ExtractVerilogModules extends VMEArgParser { - def main(args: Array[String]): Unit = { - val vme = new VerilogModuleExtractor() - val (sourceFile, topModules, outTopDir, usr) = wrapParams(args) - vme.extract(sourceFile, topModules, outTopDir, usr) - } -} diff --git a/src/main/scala/utils/GTimer.scala b/src/main/scala/utils/GTimer.scala deleted file mode 100644 index a6cef8628..000000000 --- a/src/main/scala/utils/GTimer.scala +++ /dev/null @@ -1,27 +0,0 @@ -/*************************************************************************************** -* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences -* Copyright (c) 2020-2021 Peng Cheng Laboratory -* -* XiangShan is licensed under Mulan PSL v2. -* You can use this software according to the terms and conditions of the Mulan PSL v2. -* You may obtain a copy of Mulan PSL v2 at: -* http://license.coscl.org.cn/MulanPSL2 -* -* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -* -* See the Mulan PSL v2 for more details. -***************************************************************************************/ - -package utils - -import chisel3._ - -object GTimer { - def apply() = { - val c = RegInit(0.U(64.W)) - c := c + 1.U - c - } -} diff --git a/src/main/scala/utils/Hold.scala b/src/main/scala/utils/Hold.scala deleted file mode 100644 index 4c6a82bd8..000000000 --- a/src/main/scala/utils/Hold.scala +++ /dev/null @@ -1,98 +0,0 @@ -/*************************************************************************************** -* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences -* Copyright (c) 2020-2021 Peng Cheng Laboratory -* -* XiangShan is licensed under Mulan PSL v2. -* You can use this software according to the terms and conditions of the Mulan PSL v2. -* You may obtain a copy of Mulan PSL v2 at: -* http://license.coscl.org.cn/MulanPSL2 -* -* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -* -* See the Mulan PSL v2 for more details. -***************************************************************************************/ - -package utils - -import chisel3._ -import chisel3.util._ - -object HoldUnless { - def apply[T <: Data](x: T, en: Bool): T = Mux(en, x, RegEnable(x, 0.U.asTypeOf(x), en)) -} - -object ReadAndHold { - def apply[T <: Data](x: Mem[T], addr: UInt, en: Bool): T = HoldUnless(x.read(addr), en) - def apply[T <: Data](x: SyncReadMem[T], addr: UInt, en: Bool): T = HoldUnless(x.read(addr, en), RegNext(en)) -} - -/* - * Hold the in fire unless out fire or flush happens - * similar to BoolStopWatch - */ -object ValidHold { - def apply(infire: Bool, outfire: Bool, flush: Bool = false.B ) = { - val valid = RegInit(false.B) - when (outfire) { valid := false.B } - when (infire) { valid := true.B } - when (flush) { valid := false.B } // NOTE: the flush will flush in & out, is that ok? - valid - } -} - - -/* - * Hold the 'fire' for only one cycle unless new fire comes in - */ -object OneCycleValid { - def apply(fire: Bool, flush: Bool = false.B) = { - val valid = RegInit(false.B) - when (valid) { valid := false.B } - when (fire) { valid := true.B } - when (flush) { valid := false.B } - valid - } -} - -/* - * Hold the data when it is valid and bypass latest data - */ -object DataHoldBypass { - def apply[T <: Data](data: T, valid: Bool): T = { - Mux(valid, data, RegEnable(data, valid)) - } -} - -/* - * Data change or not - */ -object DataChanged { - def apply(data: UInt): UInt = { - data =/= RegNext(data) - } -} - -/** - * Delay the data for N cycles - */ -class DelayN[T <: Data](gen: T, n: Int) extends Module { - val io = IO(new Bundle() { - val in = Input(gen) - val out = Output(gen) - }) - var out = io.in - for (i <- 0 until n) { - out = RegNext(out) - } - io.out := out -} - -object DelayN { - def apply[T <: Data](in: T, n: Int): T = { - val delay = Module(new DelayN(in.cloneType, n)) - delay.io.in := in - delay.io.out - } -} diff --git a/src/main/scala/utils/IntBuffer.scala b/src/main/scala/utils/IntBuffer.scala deleted file mode 100644 index 06a13a084..000000000 --- a/src/main/scala/utils/IntBuffer.scala +++ /dev/null @@ -1,25 +0,0 @@ -package utils - -import chisel3._ -import chipsalliance.rocketchip.config.Parameters -import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} -import freechips.rocketchip.interrupts.IntAdapterNode - -class IntBuffer(implicit p: Parameters) extends LazyModule { - - val node = IntAdapterNode() - - lazy val module = new LazyModuleImp(this){ - for(((in, edgeIn), (out, edgeOut)) <- node.in.zip(node.out)){ - out := RegNext(in, 0.U.asTypeOf(in)) - } - } - -} - -object IntBuffer { - def apply()(implicit p: Parameters) = { - val intBuffer = LazyModule(new IntBuffer) - intBuffer.node - } -} diff --git a/src/main/scala/utils/LFSR64.scala b/src/main/scala/utils/LFSR64.scala deleted file mode 100644 index edc658590..000000000 --- a/src/main/scala/utils/LFSR64.scala +++ /dev/null @@ -1,32 +0,0 @@ -/*************************************************************************************** -* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences -* Copyright (c) 2020-2021 Peng Cheng Laboratory -* -* XiangShan is licensed under Mulan PSL v2. -* You can use this software according to the terms and conditions of the Mulan PSL v2. -* You may obtain a copy of Mulan PSL v2 at: -* http://license.coscl.org.cn/MulanPSL2 -* -* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -* -* See the Mulan PSL v2 for more details. -***************************************************************************************/ - -package utils - -import chisel3._ -import chisel3.util._ - -object LFSR64 { - def apply(increment: Bool = true.B): UInt = { - val wide = 64 - val lfsr = RegInit(0x1234567887654321L.U(wide.W)) // random initial value based on simulation seed - val xor = lfsr(0) ^ lfsr(1) ^ lfsr(3) ^ lfsr(4) - when (increment) { - lfsr := Mux(lfsr === 0.U, 1.U, Cat(xor, lfsr(wide-1,1))) - } - lfsr - } -} diff --git a/src/main/scala/utils/LatencyPipe.scala b/src/main/scala/utils/LatencyPipe.scala deleted file mode 100644 index d128ef16c..000000000 --- a/src/main/scala/utils/LatencyPipe.scala +++ /dev/null @@ -1,41 +0,0 @@ -/*************************************************************************************** -* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences -* Copyright (c) 2020-2021 Peng Cheng Laboratory -* -* XiangShan is licensed under Mulan PSL v2. -* You can use this software according to the terms and conditions of the Mulan PSL v2. -* You may obtain a copy of Mulan PSL v2 at: -* http://license.coscl.org.cn/MulanPSL2 -* -* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -* -* See the Mulan PSL v2 for more details. -***************************************************************************************/ - -// See LICENSE.Berkeley for license details. - -package utils - -import Chisel._ - -class LatencyPipe[T <: Data](typ: T, latency: Int) extends Module { - val io = new Bundle { - val in = Decoupled(typ).flip - val out = Decoupled(typ) - } - - def doN[T](n: Int, func: T => T, in: T): T = - (0 until n).foldLeft(in)((last, _) => func(last)) - - io.out <> doN(latency, (last: DecoupledIO[T]) => Queue(last, 1, pipe=true), io.in) -} - -object LatencyPipe { - def apply[T <: Data](in: DecoupledIO[T], latency: Int): DecoupledIO[T] = { - val pipe = Module(new LatencyPipe(in.bits, latency)) - pipe.io.in <> in - pipe.io.out - } -} diff --git a/src/main/scala/utils/LogUtils.scala b/src/main/scala/utils/LogUtils.scala index c216e176d..0797c06f6 100644 --- a/src/main/scala/utils/LogUtils.scala +++ b/src/main/scala/utils/LogUtils.scala @@ -20,6 +20,7 @@ import chipsalliance.rocketchip.config.Parameters import chisel3._ import xiangshan.DebugOptionsKey import utils.XSLogLevel.XSLogLevel +import utility.GTimer object XSLogLevel extends Enumeration { type XSLogLevel = Value diff --git a/src/main/scala/utils/LookupTree.scala b/src/main/scala/utils/LookupTree.scala deleted file mode 100644 index 550349cec..000000000 --- a/src/main/scala/utils/LookupTree.scala +++ /dev/null @@ -1,67 +0,0 @@ -/*************************************************************************************** -* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences -* Copyright (c) 2020-2021 Peng Cheng Laboratory -* -* XiangShan is licensed under Mulan PSL v2. -* You can use this software according to the terms and conditions of the Mulan PSL v2. -* You may obtain a copy of Mulan PSL v2 at: -* http://license.coscl.org.cn/MulanPSL2 -* -* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -* -* See the Mulan PSL v2 for more details. -***************************************************************************************/ - -package utils - -import chisel3._ -import chisel3.util._ - -object LookupTree { - def apply[T <: Data](key: UInt, mapping: Iterable[(UInt, T)]): T = - Mux1H(mapping.map(p => (p._1 === key, p._2))) -} - -object LookupTreeDefault { - def apply[T <: Data](key: UInt, default: T, mapping: Iterable[(UInt, T)]): T = - MuxLookup(key, default, mapping.toSeq) -} - - -object MuxT { - def apply[T <: Data, U <: Data](cond: Bool, con: (T, U), alt: (T, U)): (T, U) = - (Mux(cond, con._1, alt._1), Mux(cond, con._2, alt._2)) - - def apply[T <: Data, U <: Data, W <: Data](cond: Bool, con: (T, U, W), alt: (T, U, W)): (T, U, W) = - (Mux(cond, con._1, alt._1), Mux(cond, con._2, alt._2), Mux(cond, con._3, alt._3)) - - def apply[T <: Data, U <: Data, W <: Data, X <: Data](cond: Bool, con: (T, U, W, X), alt: (T, U, W, X)): (T, U, W, X) = - (Mux(cond, con._1, alt._1), Mux(cond, con._2, alt._2), Mux(cond, con._3, alt._3), Mux(cond, con._4, alt._4)) -} - -/** Creates a cascade of n MuxTs to search for a key value. */ -object MuxTLookup { - def apply[S <: UInt, T <: Data, U <: Data](key: S, default: (T, U), mapping: Seq[(S, (T, U))]): (T, U) = { - var res = default - for ((k, v) <- mapping.reverse) - res = MuxT(k === key, v, res) - res - } - - def apply[S <: UInt, T <: Data, U <: Data, W <: Data](key: S, default: (T, U, W), mapping: Seq[(S, (T, U, W))]): (T, U, W) = { - var res = default - for ((k, v) <- mapping.reverse) - res = MuxT(k === key, v, res) - res - } - - // in case you really need to search for a 4-tuple - def apply[S <: UInt, T <: Data, U <: Data, W <: Data, X <: Data](key: S, default: (T, U, W, X), mapping: Seq[(S, (T, U, W, X))]): (T, U, W, X) = { - var res = default - for ((k, v) <- mapping.reverse) - res = MuxT(k === key, v, res) - res - } -} diff --git a/src/main/scala/utils/MIMOQueue.scala b/src/main/scala/utils/MIMOQueue.scala deleted file mode 100644 index 1ca5a64a7..000000000 --- a/src/main/scala/utils/MIMOQueue.scala +++ /dev/null @@ -1,172 +0,0 @@ -/*************************************************************************************** -* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences -* Copyright (c) 2020-2021 Peng Cheng Laboratory -* -* XiangShan is licensed under Mulan PSL v2. -* You can use this software according to the terms and conditions of the Mulan PSL v2. -* You may obtain a copy of Mulan PSL v2 at: -* http://license.coscl.org.cn/MulanPSL2 -* -* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -* -* See the Mulan PSL v2 for more details. -***************************************************************************************/ - -package utils - -import chisel3._ -import chisel3.experimental.{DataMirror, requireIsChiselType} -import chisel3.util._ - -class IndexableMem[T <: Data] -( - entries: Int, - gen: T, - mem: Boolean, - init: Option[Seq[T]] -){ - require(!(init.nonEmpty && init.get.size!=entries)) - val ram = Mem(entries, gen) - val vec = Reg(Vec(entries, gen)) - val initializedVec = if(init.nonEmpty) RegInit(VecInit(init.get)) else null - def apply(idx: UInt): T = { - if(mem) ram(idx) - else if(init.nonEmpty) initializedVec(idx) - else vec(idx) - } -} - -object IndexableMem { - def apply[T <: Data] - ( - entries: Int, - gen: T, - mem: Boolean = false, - init: Option[Seq[T]] = None - ): IndexableMem[T] = { - new IndexableMem[T](entries, gen, mem, init) - } -} - -class MIMOQueueIO[T <: Data](gen: T, entries: Int, inCnt: Int, outCnt: Int) extends Bundle -{ - val flush = Input(Bool()) - val enq = Vec(inCnt, Flipped(DecoupledIO(gen))) - val deq = Vec(outCnt, DecoupledIO(gen)) - -} - -class MIMOQueue[T <: Data] -( - gen: T, - val entries: Int, - val inCnt: Int, - val outCnt: Int, - mem: Boolean = false, - perf: Boolean = false, - init: Option[Seq[T]] = None -) extends Module { - - require(isPow2(entries), "MIMOQueue: entries must be a power of 2!") - require(!(init.nonEmpty && mem), "MIMOQueue: Mem can't be init!") - require(!(init.nonEmpty && init.get.size!=entries)) - - def ptr_width = log2Up(entries) - - val io = IO(new MIMOQueueIO[T](gen, entries, inCnt, outCnt)) - - val genType = if (compileOptions.declaredTypeMustBeUnbound) { - requireIsChiselType(gen) - gen - } else { - if (DataMirror.internal.isSynthesizable(gen)) { - chiselTypeOf(gen) - } else { - gen - } - } - - val ram = IndexableMem(entries, genType, mem, init) - - val valids = if(perf){ - RegInit(VecInit((0 until entries).map(_ => if(init.nonEmpty) true.B else false.B))) - } else null - - val enqPtrInitVal = 0.U((ptr_width+1).W) - val deqPtrInitVal = (if(init.nonEmpty) 1< { - init + PopCount(vec.take(i).map(_.fire())) - }) - } else { - val ptrs = vec.map(_ => Wire(UInt((ptr_width+1).W))) - for(i <- vec.indices){ - ptrs(i) := {if(i==0) init else ptrs(i-1) + vec(i-1).fire()} - } - ptrs - } - } - - // dequeue - val deq_ptrs = genPtrs(deq_ptr, io.deq) - - for((deq, deq_ptr_wire) <- io.deq.zip(deq_ptrs)){ - val deq_idx = ptrToIdx(deq_ptr_wire) - deq.valid := { - if(perf) valids(deq_idx) - else !isEmpty(deq_ptr_wire, enq_ptr) - } - deq.bits := ram(deq_idx) - if(perf) when(deq.fire()){ valids(deq_idx) := false.B } - } - - deq_ptr := deq_ptrs.last + io.deq(outCnt-1).fire() - - // enqueue - val enq_ptrs = genPtrs(enq_ptr, io.enq) - - for((enq, enq_ptr_wire) <- io.enq.zip(enq_ptrs)){ - val enq_idx = ptrToIdx(enq_ptr_wire) - enq.ready := { - if(perf) !valids(enq_idx) - else !isFull(enq_ptr_wire, deq_ptr) - } - when(enq.fire()){ - ram(enq_idx) := enq.bits - if(perf){ - valids(enq_idx) := true.B - } - } - } - - enq_ptr := enq_ptrs.last + io.enq(inCnt-1).fire() - - when(io.flush){ - deq_ptr := 0.U - enq_ptr := 0.U - if(perf) valids.foreach(_ := false.B) - } - - // Debug(false){ - // val cnt = RegInit((if(init.nonEmpty) entries else 0).U(32.W)) - // val enqCnt = PopCount(io.enq.map(_.fire())) - // val deqCnt = PopCount(io.deq.map(_.fire())) - // cnt := cnt + enqCnt - deqCnt - // assert(cnt > deqCnt, "MIMOQueue underflow!") - // assert(cnt + enqCnt < entries.U(32.W), "MIMOQueue overflow!") - // printf(p"cnt: $cnt enqCnt:$enqCnt deqCnt:$deqCnt\n") - // } - -} diff --git a/src/main/scala/utils/Misc.scala b/src/main/scala/utils/Misc.scala deleted file mode 100644 index c45c06549..000000000 --- a/src/main/scala/utils/Misc.scala +++ /dev/null @@ -1,101 +0,0 @@ -/*************************************************************************************** -* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences -* Copyright (c) 2020-2021 Peng Cheng Laboratory -* -* XiangShan is licensed under Mulan PSL v2. -* You can use this software according to the terms and conditions of the Mulan PSL v2. -* You may obtain a copy of Mulan PSL v2 at: -* http://license.coscl.org.cn/MulanPSL2 -* -* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -* -* See the Mulan PSL v2 for more details. -***************************************************************************************/ - -package utils - -import chisel3._ -import chisel3.util._ -import chisel3.util.random.LFSR - -// This gets used everywhere, so make the smallest circuit possible ... -// Given an address and size, create a mask of beatBytes size -// eg: (0x3, 0, 4) => 0001, (0x3, 1, 4) => 0011, (0x3, 2, 4) => 1111 -// groupBy applies an interleaved OR reduction; groupBy=2 take 0010 => 01 -object MaskGen { - def apply(addr_lo: UInt, lgSize: UInt, beatBytes: Int, groupBy: Int = 1): UInt = { - require (groupBy >= 1 && beatBytes >= groupBy) - require (isPow2(beatBytes) && isPow2(groupBy)) - val lgBytes = log2Ceil(beatBytes) - val sizeOH = UIntToOH(lgSize | 0.U(log2Up(beatBytes).W), log2Up(beatBytes)) | (groupBy*2 - 1).U - - def helper(i: Int): Seq[(Bool, Bool)] = { - if (i == 0) { - Seq((lgSize >= lgBytes.U, true.B)) - } else { - val sub = helper(i-1) - val size = sizeOH(lgBytes - i) - val bit = addr_lo(lgBytes - i) - val nbit = !bit - Seq.tabulate (1 << i) { j => - val (sub_acc, sub_eq) = sub(j/2) - val eq = sub_eq && (if (j % 2 == 1) bit else nbit) - val acc = sub_acc || (size && eq) - (acc, eq) - } - } - } - - if (groupBy == beatBytes) 1.U else - Cat(helper(lgBytes-log2Ceil(groupBy)).map(_._1).reverse) - } -} - -object Random -{ - def apply(mod: Int, random: UInt): UInt = { - if (mod == 1) 0.U - else if (isPow2(mod)) random(log2Ceil(mod)-1,0) - else PriorityEncoder(partition(apply(1 << log2Up(mod*8), random), mod)) - } - def apply(mod: Int): UInt = apply(mod, randomizer) - def oneHot(mod: Int, random: UInt): UInt = { - if (mod == 1) 1.U(1.W) - else if (isPow2(mod)) UIntToOH(random(log2Up(mod)-1,0)) - else VecInit(PriorityEncoderOH(partition(apply(1 << log2Up(mod*8), random), mod))).asUInt - } - def oneHot(mod: Int): UInt = oneHot(mod, randomizer) - - private def randomizer = LFSR(16) - private def partition(value: UInt, slices: Int) = - Seq.tabulate(slices)(i => value < (((i + 1) << value.getWidth) / slices).U) -} - - -/** - * Transpose a matrix of Chisel Vecs. - */ -object Transpose -{ - def apply[T <: chisel3.Data](in: Vec[Vec[T]]) = { - val n = in(0).size - VecInit((0 until n).map(i => VecInit(in.map(row => row(i))))) - } -} - -/** - * assert when 'signal' is true for more than 'threshold' cycles - */ -object TimeOutAssert { - def apply(signal: Bool, threshold: Int, message: String): Unit = { - val counter = RegInit(0.U(32.W)) - when (signal) { - counter := counter + 1.U - }.otherwise { - counter := 0.U - } - assert(counter <= threshold.U, message) - } -} \ No newline at end of file diff --git a/src/main/scala/utils/ParallelMux.scala b/src/main/scala/utils/ParallelMux.scala deleted file mode 100644 index 602f19f54..000000000 --- a/src/main/scala/utils/ParallelMux.scala +++ /dev/null @@ -1,145 +0,0 @@ -/*************************************************************************************** -* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences -* Copyright (c) 2020-2021 Peng Cheng Laboratory -* -* XiangShan is licensed under Mulan PSL v2. -* You can use this software according to the terms and conditions of the Mulan PSL v2. -* You may obtain a copy of Mulan PSL v2 at: -* http://license.coscl.org.cn/MulanPSL2 -* -* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -* -* See the Mulan PSL v2 for more details. -***************************************************************************************/ - -package utils - -import chisel3._ -import chisel3.util._ - -object ParallelOperation { - def apply[T](xs: Seq[T], func: (T, T) => T): T = { - require(xs.nonEmpty) - xs match { - case Seq(a) => a - case Seq(a, b) => func(a, b) - case _ => - apply(Seq(apply(xs take xs.size/2, func), apply(xs drop xs.size/2, func)), func) - } - } -} - -object ParallelOR { - def apply[T <: Data](xs: Seq[T]): T = { - ParallelOperation(xs, (a: T, b: T) => (a.asUInt | b.asUInt).asTypeOf(xs.head)) - } -} - -object ParallelORR { - def apply(in: Seq[Bool]): Bool = ParallelOR(in) - def apply(in: Bits): Bool = apply(in.asBools) -} - -object ParallelAND { - def apply[T <: Data](xs: Seq[T]): T = { - ParallelOperation(xs, (a: T, b:T) => (a.asUInt & b.asUInt).asTypeOf(xs.head)) - } -} - -object ParallelANDR { - def apply(in: Seq[Bool]): Bool = ParallelAND(in) - def apply(in: Bits): Bool = apply(in.asBools) -} - -object ParallelXOR { - def apply[T <: Data](xs: Seq[T]): T = { - ParallelOperation(xs, (a: T, b:T) => (a.asUInt ^ b.asUInt).asTypeOf(xs.head)) - } -} - -object ParallelMux { - def apply[T<:Data](in: Seq[(Bool, T)]): T = { - val xs = in map { case (cond, x) => Mux(cond, x, 0.U.asTypeOf(x.cloneType)) } - ParallelOR(xs) - } - def apply[T <: Data](sel: Seq[Bool], in: Seq[T]): T = apply(sel.zip(in)) -} - -object ParallelLookUp { - def apply[T<:Data](key: UInt, mapping:Seq[(UInt,T)]): T = { - ParallelMux(mapping.map(m => (m._1===key) -> m._2)) - } -} - -object ParallelMax { - def apply[T <: Data](xs: Seq[T]): T = { - ParallelOperation(xs, (a: T, b:T) => Mux(a.asUInt > b.asUInt,a, b).asTypeOf(xs.head)) - } -} - -object ParallelMin { - def apply[T <: Data](xs: Seq[T]): T = { - ParallelOperation(xs, (a: T, b:T) => Mux(a.asUInt < b.asUInt,a, b).asTypeOf(xs.head)) - } -} - -object ParallelPriorityMux { - def apply[T <: Data](in: Seq[(Bool, T)]): T = { - ParallelOperation(in, (a: (Bool, T), b: (Bool, T)) => (a._1 || b._1, Mux(a._1, a._2, b._2)))._2 - } - def apply[T <: Data](sel: Bits, in: Seq[T]): T = apply((0 until in.size).map(sel(_)), in) - def apply[T <: Data](sel: Seq[Bool], in: Seq[T]): T = apply(sel zip in) -} - -object ParallelPriorityEncoder { - def apply(in: Seq[Bool]): UInt = ParallelPriorityMux(in, (0 until in.size).map(_.asUInt)) - def apply(in: Bits): UInt = apply(in.asBools) -} - -object ParallelSingedExpandingAdd { - def apply(in: Seq[SInt]): SInt = ParallelOperation(in, (a: SInt, b: SInt) => a +& b) -} - -class SelectTwoInterRes[T <: Data](gen: T) extends Bundle { - // val valid = Bool() - val hasOne = Bool() - val hasTwo = Bool() - val first = gen.cloneType - val second = gen.cloneType -} - -object SelectTwoInterRes { - def apply[T <: Data](hasOne: Bool, hasTwo: Bool, first: T, second: T): SelectTwoInterRes[T] = { - val res = Wire(new SelectTwoInterRes(first)) - res.hasOne := hasOne - res.hasTwo := hasTwo - res.first := first - res.second := second - res - } - def apply[T <: Data](valid: Bool, data: T): SelectTwoInterRes[T] = { - val res = apply(valid, false.B, data, data) - res - } -} - - -object ParallelSelectTwo { - def mergeSelectFirstTwo[T <: Data](a: SelectTwoInterRes[T], b: SelectTwoInterRes[T]): SelectTwoInterRes[T] = { - SelectTwoInterRes( - a.hasOne || b.hasOne, - a.hasTwo || b.hasTwo || a.hasOne && b.hasOne, - Mux(a.hasOne, a.first, b.first), - Mux1H(Seq( - (!a.hasOne, b.second), - (a.hasOne && !a.hasTwo, b.first), - (a.hasTwo, a.second) - )) - ) - } - def apply[T <: Data](xs: Seq[SelectTwoInterRes[T]]): SelectTwoInterRes[T] = { - ParallelOperation(xs, mergeSelectFirstTwo[T]) - } -} diff --git a/src/main/scala/utils/PipelineConnect.scala b/src/main/scala/utils/PipelineConnect.scala deleted file mode 100644 index 23a18b391..000000000 --- a/src/main/scala/utils/PipelineConnect.scala +++ /dev/null @@ -1,196 +0,0 @@ -/*************************************************************************************** -* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences -* Copyright (c) 2020-2021 Peng Cheng Laboratory -* -* XiangShan is licensed under Mulan PSL v2. -* You can use this software according to the terms and conditions of the Mulan PSL v2. -* You may obtain a copy of Mulan PSL v2 at: -* http://license.coscl.org.cn/MulanPSL2 -* -* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -* -* See the Mulan PSL v2 for more details. -***************************************************************************************/ - -package utils - -import chisel3._ -import chisel3.util._ - -class PipelineConnectPipe[T <: Data](gen: T) extends Module { - val io = IO(new Bundle() { - val in = Flipped(DecoupledIO(gen.cloneType)) - val out = DecoupledIO(gen.cloneType) - val rightOutFire = Input(Bool()) - val isFlush = Input(Bool()) - }) - - PipelineConnect.connect(io.in, io.out, io.rightOutFire, io.isFlush, false.B) -} - -class PipelineConnectBuffer[T <: Data, FlushT <: Data](gen: T, flushGen: FlushT, flushFunc: (T, FlushT) => Bool) - extends Module { - val io = IO(new Bundle() { - val in = Flipped(DecoupledIO(gen.cloneType)) - val out = DecoupledIO(gen.cloneType) - val flush = Input(flushGen.cloneType) - }) - - val valid = RegInit(VecInit.fill(2)(false.B)) - val data = Reg(Vec(2, gen.cloneType)) - val older = RegInit(false.B) - - // out - io.out.valid := valid.asUInt.orR - io.out.bits := data(older) - when (io.out.fire) { - valid(older) := false.B - older := !older - } - - // in - io.in.ready := !valid.asUInt.andR - val updateVec = WireInit(VecInit.fill(2)(false.B)) - when (io.in.valid && !flushFunc(io.in.bits, io.flush)) { - // how to choose: this_empty && (this_older || other_older && other_not_empty) - when (!valid(0) && (!older || older && valid(1))) { - valid(0) := true.B - data(0) := io.in.bits - updateVec(0) := true.B - }.elsewhen (!valid(1) && (older || !older && valid(0))) { - valid(1) := true.B - data(1) := io.in.bits - updateVec(1) := true.B - } - } - - // flush - val flushVec = data.zip(valid).map{ case (d, v) => flushFunc(d, io.flush) && v } - flushVec.zip(valid).foreach{ case (f, v) => - when (f) { - v := false.B - } - } -} - -class PipelineConnectBufferWithExtraData[T <: Data, FlushT <: Data, ExtraT <: Data]( - gen: T, flushGen: FlushT, flushFunc: (T, FlushT) => Bool, extraGen: ExtraT, extraLatency: Int -) extends PipelineConnectBuffer(gen, flushGen, flushFunc) { - require(extraLatency > 0, "why not use PipelineConnectBuffer?") - require(extraLatency == 1, "only 1 is supported now") - - val extra = IO(new Bundle { - val in = Input(extraGen.cloneType) - val out = Output(extraGen.cloneType) - }) - - val extraData = Reg(Vec(2, extraGen.cloneType)) - for (i <- 0 until 2) { - when (RegNext(updateVec(i) && !flushVec(i))) { - extraData(i) := extra.in - } - } - - // after out.fire, we assert(!older === RegNext(older)) - extra.out := extraData(!older) -} - -object PipelineConnect { - def connect[T <: Data]( - left: DecoupledIO[T], - right: DecoupledIO[T], - rightOutFire: Bool, - isFlush: Bool, - block: Bool - ): T = { - val valid = RegInit(false.B) - val leftFire = left.valid && right.ready && !block - when (rightOutFire) { valid := false.B } - when (leftFire) { valid := true.B } - when (isFlush) { valid := false.B } - - left.ready := right.ready && !block - val data = RegEnable(left.bits, leftFire) - right.bits := data - right.valid := valid - - data - } - - def apply[T <: Data]( - left: DecoupledIO[T], - right: DecoupledIO[T], - rightOutFire: Bool, - isFlush: Bool, - block: Bool = false.B, - moduleName: Option[String] = None - ): Option[T] = { - if (moduleName.isDefined) { - val pipeline = Module(new PipelineConnectPipe(left.bits)) - pipeline.suggestName(moduleName.get) - pipeline.io.in <> left - pipeline.io.rightOutFire := rightOutFire - pipeline.io.isFlush := isFlush - pipeline.io.out <> right - pipeline.io.out.ready := right.ready && !block - None - } - else { - // do not use module here to please DCE - Some(connect(left, right, rightOutFire, isFlush, block)) - } - } - - def apply[T <: Data, FlushT <: Data]( - left: DecoupledIO[T], - right: DecoupledIO[T], - flushFunc: (T, FlushT) => Bool, - flush: FlushT, - moduleName: Option[String] - ): Unit = { - val pipe_buffer = Module(new PipelineConnectBuffer(left.bits, flush, flushFunc)) - if(moduleName.nonEmpty) pipe_buffer.suggestName(moduleName.get) - pipe_buffer.io.in <> left - pipe_buffer.io.out <> right - pipe_buffer.io.flush := flush - } - - def apply[T <: Data, FlushT <: Data, ExtraT <: Data]( - left: DecoupledIO[T], - right: DecoupledIO[T], - flushFunc: (T, FlushT) => Bool, - flush: FlushT, - extraGen: ExtraT, - extraLatency: Int - ): PipelineConnectBufferWithExtraData[T, FlushT, ExtraT] = { - val pipe_buffer = Module(new PipelineConnectBufferWithExtraData(left.bits, flush, flushFunc, extraGen, extraLatency)) - pipe_buffer.io.in <> left - pipe_buffer.io.out <> right - pipe_buffer.io.flush := flush - pipe_buffer - } -} - -object PipelineNext { - def apply[T <: Data]( - left: DecoupledIO[T], - rightOutFire: Bool, - isFlush: Bool - ): DecoupledIO[T] = { - val right = Wire(Decoupled(left.bits.cloneType)) - PipelineConnect(left, right, rightOutFire, isFlush) - right - } - - def apply[T <: Data, FlushT <: Data]( - left: DecoupledIO[T], - flushFunc: (T, FlushT) => Bool, - flush: FlushT - ): DecoupledIO[T] = { - val right = Wire(Decoupled(left.bits.cloneType)) - PipelineConnect(left, right, flushFunc, flush, Some("buffer")) - right - } -} diff --git a/src/main/scala/utils/PriorityMuxDefault.scala b/src/main/scala/utils/PriorityMuxDefault.scala deleted file mode 100644 index 5629232c1..000000000 --- a/src/main/scala/utils/PriorityMuxDefault.scala +++ /dev/null @@ -1,59 +0,0 @@ -/*************************************************************************************** -* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences -* Copyright (c) 2020-2021 Peng Cheng Laboratory -* -* XiangShan is licensed under Mulan PSL v2. -* You can use this software according to the terms and conditions of the Mulan PSL v2. -* You may obtain a copy of Mulan PSL v2 at: -* http://license.coscl.org.cn/MulanPSL2 -* -* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -* -* See the Mulan PSL v2 for more details. -***************************************************************************************/ - -package utils - -import chisel3._ - -object PriorityMuxDefault { - def apply[T <: Data](in: Seq[(Bool, T)], default: T): T = { - in.size match { - case 1=> - Mux(in.head._1, in.head._2, default) - case _ => - Mux(in.head._1, in.head._2, PriorityMuxDefault(in.tail, default)) - } - } -} - -object PriorityEncoderDefault { - def apply(in: Seq[Bool], default: UInt): UInt = { - PriorityMuxDefault(in.zipWithIndex.map(x => x._1 -> x._2.U), default) - } -} - -object PriorityMuxWithFlag { - def apply[T <: Data](in: Seq[(Bool, T)]): (T, Bool) = { - in.size match { - case 1 => - (in.head._2, in.head._1) - case _ => - val (d_tail, f_tail) = PriorityMuxWithFlag(in.tail) - val d_head = in.head._2 - val f_head = in.head._1 - (Mux(f_head, d_head, d_tail), f_head || f_tail) - } - } -} - -object PriorityEncoderWithFlag { - def apply(in: Seq[Bool]): (UInt, Bool) = { - PriorityMuxWithFlag(in.zipWithIndex.map(x => x._1 -> x._2.U)) - } - def apply(in: Bits): (UInt, Bool) = { - PriorityEncoderWithFlag(in.asBools()) - } -} \ No newline at end of file diff --git a/src/main/scala/utils/PriorityMuxGen.scala b/src/main/scala/utils/PriorityMuxGen.scala deleted file mode 100644 index f4f8b8691..000000000 --- a/src/main/scala/utils/PriorityMuxGen.scala +++ /dev/null @@ -1,145 +0,0 @@ -/*************************************************************************************** -* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences -* Copyright (c) 2020-2021 Peng Cheng Laboratory -* -* XiangShan is licensed under Mulan PSL v2. -* You can use this software according to the terms and conditions of the Mulan PSL v2. -* You may obtain a copy of Mulan PSL v2 at: -* http://license.coscl.org.cn/MulanPSL2 -* -* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -* -* See the Mulan PSL v2 for more details. -***************************************************************************************/ - -package utils - -import chisel3._ -import chisel3.util._ -import Chisel.experimental.chiselName - -@chiselName -class PriorityMuxModule[T <: Data](val gen: T)(val names: Seq[String]) extends MultiIOModule { - class InBundle extends Bundle { - val sel = Bool() - val src = gen.cloneType - } - class OutBundle extends Bundle { - val res = gen.cloneType - } - val ins = names.map(s => { - IO(Input(new InBundle)).suggestName(s) - }) - val out = IO(Output(new OutBundle)) - out.res := PriorityMux(ins.map{i => (i.sel, i.src)}) -} - -// this could be used to handle the situation -// in which we have mux sources at multiple -// locations, and this is same to multiple -// when clauses as below, but collect them -// and put them into a ParallelPrioriyMux -// when (sel1) { x := in1 } -// when (sel2) { x := in2 } -class PriorityMuxGenerator[T <: Data] { - var src: List[(Bool, T, String)] = List() - var num: Int = 0 - def genPortName(n: Option[String]): String = { - num = num + 1 - n match { - case Some(name) => name - case None => { - "in" + num.toString() - } - } - } - - def register(sel: Bool, in: T, name: Option[String] = None) = { - src = (sel, in, genPortName(name)) :: src - } - def register(in: Seq[(Bool, T, Option[String])]) = { - src = in.toList.map{ case (b, t, n) => (b, t, genPortName(n)) } ::: src - } - def register(sel: Seq[Bool], in: Seq[T], name: Seq[Option[String]]) = { - src = (sel,in,name.map(genPortName)).zipped.toList ::: src - } - def apply(): T = { - val names = src.map(_._3) - val ins = src.map(s => (s._1, s._2)) - // we should use this sample data to get type and width - // ugly - val sample = ins(0)._2 - val ppm = Module(new PriorityMuxModule(sample)(names)) - (ppm.ins zip ins).foreach { - case (in, (b, t)) => { - in.sel := b - in.src := t - } - } - ppm.out.res - } -} - -// this module is like PhyPriorityMuxGenerator -// but you can specify the physical priority -// by passing in an Int, usually we give -// the hightest priority to the condition -// with the largest delay. -// but their logical priority is still -// arranged in the order specified in the code -class PhyPriorityMuxGenerator[T <: Data] { - var src: List[(Bool, T, String, Int)] = List() - var rev_src: List[(Bool, T, String, Int)] = List() - var sorted_src: List[(Bool, T, String, Int)] = List() - var num: Int = 0 - def genPortName(n: Option[String]): String = { - num = num + 1 - n match { - case Some(name) => name - case None => { - "in" + num.toString() - } - } - } - - def register(sel: Bool, in: T, name: Option[String] = None, phyPrio: Int = 0) = { - src = (sel, in, genPortName(name), phyPrio) :: src - } - def register(in: Seq[(Bool, T, Option[String], Int)]) = { - src = in.toList.map{ case (b, t, n, p) => (b, t, genPortName(n), p) } ::: src - } - def register(sel: Seq[Bool], in: Seq[T], name: Seq[Option[String]], phyPrio: Seq[Int]) = { - src = sel.zip(in.zip(name.map(genPortName).zip(phyPrio))).map { case (s, (i, (n, p))) => - (s, i, n, p) }.toList ::: src - } - def apply(): T = { - rev_src = src.reverse - for (i <- 0 until rev_src.length) { - // println(rev_src(i)._3) - sorted_src = (rev_src(i)._1 && (if (i == rev_src.length-1) true.B else (i+1 until rev_src.length).map(j => !rev_src(j)._1).reduce(_&&_)), - rev_src(i)._2, rev_src(i)._3, rev_src(i)._4) :: sorted_src - } - sorted_src = sorted_src.sortBy(_._4).reverse - // println(sorted_src) - val names = sorted_src.map(_._3) - val ins = sorted_src.map(s => (s._1, s._2)) - // we should use this sample data to get type and width - // ugly - val sample = ins(0)._2 - // println(src) - // println(sorted_src) - // println(ins) - // println(names) - - val ppm = Module(new PriorityMuxModule(sample)(names)) - (ppm.ins zip ins).foreach { - case (in, (b, t)) => { - in.sel := b - in.src := t - } - } - ppm.out.res - } -} \ No newline at end of file diff --git a/src/main/scala/utils/RegMap.scala b/src/main/scala/utils/RegMap.scala deleted file mode 100644 index 9f776cf42..000000000 --- a/src/main/scala/utils/RegMap.scala +++ /dev/null @@ -1,67 +0,0 @@ -/*************************************************************************************** -* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences -* Copyright (c) 2020-2021 Peng Cheng Laboratory -* -* XiangShan is licensed under Mulan PSL v2. -* You can use this software according to the terms and conditions of the Mulan PSL v2. -* You may obtain a copy of Mulan PSL v2 at: -* http://license.coscl.org.cn/MulanPSL2 -* -* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -* -* See the Mulan PSL v2 for more details. -***************************************************************************************/ - -package utils - -import chisel3._ -import chisel3.util._ - -object RegMap { - def Unwritable = null - def apply(addr: Int, reg: UInt, wfn: UInt => UInt = (x => x)) = (addr, (reg, wfn)) - def generate(mapping: Map[Int, (UInt, UInt => UInt)], raddr: UInt, rdata: UInt, - waddr: UInt, wen: Bool, wdata: UInt, wmask: UInt):Unit = { - val chiselMapping = mapping.map { case (a, (r, w)) => (a.U, r, w) } - rdata := LookupTree(raddr, chiselMapping.map { case (a, r, w) => (a, r) }) - chiselMapping.map { case (a, r, w) => - if (w != null) when (wen && waddr === a) { r := w(MaskData(r, wdata, wmask)) } - } - } - def generate(mapping: Map[Int, (UInt, UInt => UInt)], addr: UInt, rdata: UInt, - wen: Bool, wdata: UInt, wmask: UInt):Unit = generate(mapping, addr, rdata, addr, wen, wdata, wmask) -} - -object MaskedRegMap { // TODO: add read mask - def Unwritable = null - def NoSideEffect: UInt => UInt = (x=>x) - def WritableMask = Fill(64, true.B) - def UnwritableMask = 0.U(64.W) - def apply(addr: Int, reg: UInt, - wmask: UInt = WritableMask, wfn: UInt => UInt = (x => x), - rmask: UInt = WritableMask, rfn: UInt => UInt = x=>x - ): (Int, (UInt, UInt, UInt => UInt, UInt, UInt => UInt)) = (addr, (reg, wmask, wfn, rmask, rfn)) - def generate(mapping: Map[Int, (UInt, UInt, UInt => UInt, UInt, UInt => UInt)], raddr: UInt, rdata: UInt, - waddr: UInt, wen: Bool, wdata: UInt):Unit = { - val chiselMapping = mapping.map { case (a, (r, wm, w, rm, rfn)) => (a.U, r, wm, w, rm, rfn) } - rdata := LookupTree(raddr, chiselMapping.map { case (a, r, _, _, rm, rfn) => (a, rfn(r & rm)) }) - val wdata_reg = RegEnable(wdata, wen) - chiselMapping.foreach { case (a, r, wm, w, _, _) => - if (w != null && wm != UnwritableMask) { - // Warning: this RegMap adds a RegNext for write to reduce fanout - // the w must be pure function without side effects - val wen_reg = RegNext(wen && waddr === a) - when (wen_reg) { r := w(MaskData(r, wdata_reg, wm)) } - } - } - } - def isIllegalAddr(mapping: Map[Int, (UInt, UInt, UInt => UInt, UInt, UInt => UInt)], addr: UInt):Bool = { - val illegalAddr = Wire(Bool()) - illegalAddr := LookupTreeDefault(addr, true.B, mapping.toSeq.sortBy(_._1).map { case (a, _) => (a.U, false.B) }) - illegalAddr - } - def generate(mapping: Map[Int, (UInt, UInt, UInt => UInt, UInt, UInt => UInt)], addr: UInt, rdata: UInt, - wen: Bool, wdata: UInt):Unit = generate(mapping, addr, rdata, addr, wen, wdata) -} diff --git a/src/main/scala/utils/Replacement.scala b/src/main/scala/utils/Replacement.scala deleted file mode 100644 index 603985efb..000000000 --- a/src/main/scala/utils/Replacement.scala +++ /dev/null @@ -1,57 +0,0 @@ -/*************************************************************************************** -* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences -* Copyright (c) 2020-2021 Peng Cheng Laboratory -* -* XiangShan is licensed under Mulan PSL v2. -* You can use this software according to the terms and conditions of the Mulan PSL v2. -* You may obtain a copy of Mulan PSL v2 at: -* http://license.coscl.org.cn/MulanPSL2 -* -* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -* -* See the Mulan PSL v2 for more details. -***************************************************************************************/ - -// See LICENSE.Berkeley for license details. -// See LICENSE.SiFive for license details. - -package utils - -import chisel3._ -import chisel3.util._ -import chisel3.util.random.LFSR -import freechips.rocketchip.util._ -import freechips.rocketchip.util.property.cover -import xiangshan.{XSCoreParameters} - -object ReplacementPolicy { - //for fully associative mapping - def fromString(s: Option[String],n_ways: Int): ReplacementPolicy = fromString(s.getOrElse("none"),n_ways) - def fromString(s: String, n_ways: Int): ReplacementPolicy = s.toLowerCase match { - case "random" => new RandomReplacement(n_ways) - case "lru" => new TrueLRU(n_ways) - case "plru" => new PseudoLRU(n_ways) - case t => throw new IllegalArgumentException(s"unknown Replacement Policy type $t") - } - //for set associative mapping - def fromString(s: Option[String], n_ways: Int, n_sets: Int): SetAssocReplacementPolicy = fromString(s.getOrElse("none"),n_ways,n_sets ) - def fromString(s: String, n_ways: Int, n_sets: Int): SetAssocReplacementPolicy = s.toLowerCase match { - case "random" => new SetAssocRandom(n_sets, n_ways) - case "setlru" => new SetAssocLRU(n_sets, n_ways, "lru") - case "setplru" => new SetAssocLRU(n_sets, n_ways, "plru") - case t => throw new IllegalArgumentException(s"unknown Replacement Policy type $t") - } -} - -class SetAssocRandom(n_sets : Int, n_ways: Int) extends SetAssocReplacementPolicy { - val random = new RandomReplacement(n_ways) - - def miss(set: UInt) = random.miss - def way(set: UInt) = random.way - - def access(set: UInt, touch_way: UInt) = random.access(touch_way) - def access(sets: Seq[UInt], touch_ways: Seq[Valid[UInt]]) = random.access(touch_ways) - -} \ No newline at end of file diff --git a/src/main/scala/utils/ResetGen.scala b/src/main/scala/utils/ResetGen.scala deleted file mode 100644 index e80086240..000000000 --- a/src/main/scala/utils/ResetGen.scala +++ /dev/null @@ -1,68 +0,0 @@ -/*************************************************************************************** -* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences -* Copyright (c) 2020-2021 Peng Cheng Laboratory -* -* XiangShan is licensed under Mulan PSL v2. -* You can use this software according to the terms and conditions of the Mulan PSL v2. -* You may obtain a copy of Mulan PSL v2 at: -* http://license.coscl.org.cn/MulanPSL2 -* -* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -* -* See the Mulan PSL v2 for more details. -***************************************************************************************/ - -package utils - -import chisel3._ -import chisel3.util._ - -class ResetGen extends Module { - val io = IO(new Bundle() { - val out = Output(Bool()) - }) - - io.out := RegNext(RegNext(reset.asBool)) -} - -trait ResetNode - -case class ModuleNode(mod: MultiIOModule) extends ResetNode - -case class ResetGenNode(children: Seq[ResetNode]) extends ResetNode - -object ResetGen { - - def apply(resetTree: ResetNode, reset: Bool, sim: Boolean): Unit = { - if(!sim) { - resetTree match { - case ModuleNode(mod) => - mod.reset := reset - case ResetGenNode(children) => - val next_rst = Wire(Bool()) - withReset(reset){ - val resetGen = Module(new ResetGen) - next_rst := resetGen.io.out - } - children.foreach(child => apply(child, next_rst, sim)) - } - } - } - - def apply(resetChain: Seq[Seq[MultiIOModule]], reset: Bool, sim: Boolean): Seq[Bool] = { - val resetReg = Wire(Vec(resetChain.length + 1, Bool())) - resetReg.foreach(_ := reset) - for ((resetLevel, i) <- resetChain.zipWithIndex) { - if (!sim) { - withReset(resetReg(i)) { - val resetGen = Module(new ResetGen) - resetReg(i + 1) := resetGen.io.out - } - } - resetLevel.foreach(_.reset := resetReg(i + 1)) - } - resetReg.tail - } -} diff --git a/src/main/scala/utils/SRAMTemplate.scala b/src/main/scala/utils/SRAMTemplate.scala deleted file mode 100644 index 09208e700..000000000 --- a/src/main/scala/utils/SRAMTemplate.scala +++ /dev/null @@ -1,234 +0,0 @@ -/*************************************************************************************** -* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences -* Copyright (c) 2020-2021 Peng Cheng Laboratory -* -* XiangShan is licensed under Mulan PSL v2. -* You can use this software according to the terms and conditions of the Mulan PSL v2. -* You may obtain a copy of Mulan PSL v2 at: -* http://license.coscl.org.cn/MulanPSL2 -* -* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -* -* See the Mulan PSL v2 for more details. -***************************************************************************************/ - -/************************************************************************************** -* Copyright (c) 2020 Institute of Computing Technology, CAS -* Copyright (c) 2020 University of Chinese Academy of Sciences -* -* NutShell is licensed under Mulan PSL v2. -* You can use this software according to the terms and conditions of the Mulan PSL v2. -* You may obtain a copy of Mulan PSL v2 at: -* http://license.coscl.org.cn/MulanPSL2 -* -* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR -* FIT FOR A PARTICULAR PURPOSE. -* -* See the Mulan PSL v2 for more details. -***************************************************************************************/ - -package utils - -import chisel3._ -import chisel3.util._ - -class SRAMBundleA(val set: Int) extends Bundle { - val setIdx = Output(UInt(log2Up(set).W)) - - def apply(setIdx: UInt) = { - this.setIdx := setIdx - this - } -} - -class SRAMBundleAW[T <: Data](private val gen: T, set: Int, val way: Int = 1) extends SRAMBundleA(set) { - val data = Output(Vec(way, gen)) - val waymask = if (way > 1) Some(Output(UInt(way.W))) else None - - def apply(data: Vec[T], setIdx: UInt, waymask: UInt): SRAMBundleAW[T] = { - super.apply(setIdx) - this.data := data - this.waymask.map(_ := waymask) - this - } - // this could only be used when waymask is onehot or nway is 1 - def apply(data: T, setIdx: UInt, waymask: UInt): SRAMBundleAW[T] = { - apply(VecInit(Seq.fill(way)(data)), setIdx, waymask) - this - } -} - -class SRAMBundleR[T <: Data](private val gen: T, val way: Int = 1) extends Bundle { - val data = Output(Vec(way, gen)) -} - -class SRAMReadBus[T <: Data](private val gen: T, val set: Int, val way: Int = 1) extends Bundle { - val req = Decoupled(new SRAMBundleA(set)) - val resp = Flipped(new SRAMBundleR(gen, way)) - - def apply(valid: Bool, setIdx: UInt) = { - this.req.bits.apply(setIdx) - this.req.valid := valid - this - } -} - -class SRAMWriteBus[T <: Data](private val gen: T, val set: Int, val way: Int = 1) extends Bundle { - val req = Decoupled(new SRAMBundleAW(gen, set, way)) - - def apply(valid: Bool, data: Vec[T], setIdx: UInt, waymask: UInt): SRAMWriteBus[T] = { - this.req.bits.apply(data = data, setIdx = setIdx, waymask = waymask) - this.req.valid := valid - this - } - def apply(valid: Bool, data: T, setIdx: UInt, waymask: UInt): SRAMWriteBus[T] = { - apply(valid, VecInit(Seq.fill(way)(data)), setIdx, waymask) - this - } -} - -class SRAMTemplate[T <: Data]( - gen: T, set: Int, way: Int = 1, singlePort: Boolean = false, - shouldReset: Boolean = false, extraReset: Boolean = false, - holdRead: Boolean = false, bypassWrite: Boolean = false -) extends Module { - val io = IO(new Bundle { - val r = Flipped(new SRAMReadBus(gen, set, way)) - val w = Flipped(new SRAMWriteBus(gen, set, way)) - }) - val extra_reset = if (extraReset) Some(IO(Input(Bool()))) else None - - val wordType = UInt(gen.getWidth.W) - val array = SyncReadMem(set, Vec(way, wordType)) - val (resetState, resetSet) = (WireInit(false.B), WireInit(0.U)) - - if (shouldReset) { - val _resetState = RegInit(true.B) - val (_resetSet, resetFinish) = Counter(_resetState, set) - when (resetFinish) { _resetState := false.B } - if (extra_reset.isDefined) { - when (extra_reset.get) { - _resetState := true.B - } - } - - resetState := _resetState - resetSet := _resetSet - } - - val (ren, wen) = (io.r.req.valid, io.w.req.valid || resetState) - val realRen = (if (singlePort) ren && !wen else ren) - - val setIdx = Mux(resetState, resetSet, io.w.req.bits.setIdx) - val wdata = VecInit(Mux(resetState, 0.U.asTypeOf(Vec(way, gen)), io.w.req.bits.data).map(_.asTypeOf(wordType))) - val waymask = Mux(resetState, Fill(way, "b1".U), io.w.req.bits.waymask.getOrElse("b1".U)) - when (wen) { array.write(setIdx, wdata, waymask.asBools) } - - val raw_rdata = array.read(io.r.req.bits.setIdx, realRen) - - // bypass for dual-port SRAMs - require(!bypassWrite || bypassWrite && !singlePort) - def need_bypass(wen: Bool, waddr: UInt, wmask: UInt, ren: Bool, raddr: UInt) : UInt = { - val need_check = RegNext(ren && wen) - val waddr_reg = RegNext(waddr) - val raddr_reg = RegNext(raddr) - require(wmask.getWidth == way) - val bypass = Fill(way, need_check && waddr_reg === raddr_reg) & RegNext(wmask) - bypass.asTypeOf(UInt(way.W)) - } - val bypass_wdata = if (bypassWrite) VecInit(RegNext(io.w.req.bits.data).map(_.asTypeOf(wordType))) - else VecInit((0 until way).map(_ => LFSR64().asTypeOf(wordType))) - val bypass_mask = need_bypass(io.w.req.valid, io.w.req.bits.setIdx, io.w.req.bits.waymask.getOrElse("b1".U), io.r.req.valid, io.r.req.bits.setIdx) - val mem_rdata = { - if (singlePort) raw_rdata - else VecInit(bypass_mask.asBools.zip(raw_rdata).zip(bypass_wdata).map { - case ((m, r), w) => Mux(m, w, r) - }) - } - - // hold read data for SRAMs - val rdata = (if (holdRead) HoldUnless(mem_rdata, RegNext(realRen)) - else mem_rdata).map(_.asTypeOf(gen)) - - io.r.resp.data := VecInit(rdata) - io.r.req.ready := !resetState && (if (singlePort) !wen else true.B) - io.w.req.ready := true.B - -} - -class FoldedSRAMTemplate[T <: Data](gen: T, set: Int, width: Int = 4, way: Int = 1, - shouldReset: Boolean = false, extraReset: Boolean = false, - holdRead: Boolean = false, singlePort: Boolean = false, bypassWrite: Boolean = false) extends Module { - val io = IO(new Bundle { - val r = Flipped(new SRAMReadBus(gen, set, way)) - val w = Flipped(new SRAMWriteBus(gen, set, way)) - }) - val extra_reset = if (extraReset) Some(IO(Input(Bool()))) else None - // |<----- setIdx ----->| - // | ridx | width | way | - - require(width > 0 && isPow2(width)) - require(way > 0 && isPow2(way)) - require(set % width == 0) - - val nRows = set / width - - val array = Module(new SRAMTemplate(gen, set=nRows, way=width*way, - shouldReset=shouldReset, extraReset=extraReset, holdRead=holdRead, singlePort=singlePort)) - if (array.extra_reset.isDefined) { - array.extra_reset.get := extra_reset.get - } - - io.r.req.ready := array.io.r.req.ready - io.w.req.ready := array.io.w.req.ready - - val raddr = io.r.req.bits.setIdx >> log2Ceil(width) - val ridx = RegNext(if (width != 1) io.r.req.bits.setIdx(log2Ceil(width)-1, 0) else 0.U(1.W)) - val ren = io.r.req.valid - - array.io.r.req.valid := ren - array.io.r.req.bits.setIdx := raddr - - val rdata = array.io.r.resp.data - for (w <- 0 until way) { - val wayData = VecInit(rdata.indices.filter(_ % way == w).map(rdata(_))) - val holdRidx = HoldUnless(ridx, RegNext(io.r.req.valid)) - val realRidx = if (holdRead) holdRidx else ridx - io.r.resp.data(w) := Mux1H(UIntToOH(realRidx, width), wayData) - } - - val wen = io.w.req.valid - val wdata = VecInit(Seq.fill(width)(io.w.req.bits.data).flatten) - val waddr = io.w.req.bits.setIdx >> log2Ceil(width) - val widthIdx = if (width != 1) io.w.req.bits.setIdx(log2Ceil(width)-1, 0) else 0.U - val wmask = (width, way) match { - case (1, 1) => 1.U(1.W) - case (x, 1) => UIntToOH(widthIdx) - case _ => VecInit(Seq.tabulate(width*way)(n => (n / way).U === widthIdx && io.w.req.bits.waymask.get(n % way))).asUInt - } - require(wmask.getWidth == way*width) - - array.io.w.apply(wen, wdata, waddr, wmask) -} -class SRAMTemplateWithArbiter[T <: Data](nRead: Int, gen: T, set: Int, way: Int = 1, - shouldReset: Boolean = false) extends Module { - val io = IO(new Bundle { - val r = Flipped(Vec(nRead, new SRAMReadBus(gen, set, way))) - val w = Flipped(new SRAMWriteBus(gen, set, way)) - }) - - val ram = Module(new SRAMTemplate(gen, set, way, shouldReset = shouldReset, holdRead = false, singlePort = true)) - ram.io.w <> io.w - - val readArb = Module(new Arbiter(chiselTypeOf(io.r(0).req.bits), nRead)) - readArb.io.in <> io.r.map(_.req) - ram.io.r.req <> readArb.io.out - - // latch read results - io.r.map{ case r => { - r.resp.data := HoldUnless(ram.io.r.resp.data, RegNext(r.req.fire())) - }} -} diff --git a/src/main/scala/utils/StopWatch.scala b/src/main/scala/utils/StopWatch.scala deleted file mode 100644 index b405bdd18..000000000 --- a/src/main/scala/utils/StopWatch.scala +++ /dev/null @@ -1,35 +0,0 @@ -/*************************************************************************************** -* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences -* Copyright (c) 2020-2021 Peng Cheng Laboratory -* -* XiangShan is licensed under Mulan PSL v2. -* You can use this software according to the terms and conditions of the Mulan PSL v2. -* You may obtain a copy of Mulan PSL v2 at: -* http://license.coscl.org.cn/MulanPSL2 -* -* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -* -* See the Mulan PSL v2 for more details. -***************************************************************************************/ - -package utils - -import chisel3._ - -object BoolStopWatch { - def apply(start: Bool, stop: Bool, startHighPriority: Boolean = false, bypass: Boolean = false) = { - val r = RegInit(false.B) - if (startHighPriority) { - when (stop) { r := false.B } - when (start) { r := true.B } - } - else { - when (start) { r := true.B } - when (stop) { r := false.B } - } - (if (bypass) (start || r) else r) - } -} - diff --git a/src/main/scala/utils/TLClientsMerger.scala b/src/main/scala/utils/TLClientsMerger.scala deleted file mode 100644 index eefd95f29..000000000 --- a/src/main/scala/utils/TLClientsMerger.scala +++ /dev/null @@ -1,69 +0,0 @@ -package utils - -import chisel3._ -import chisel3.util._ -import chipsalliance.rocketchip.config.Parameters -import freechips.rocketchip.diplomacy.{IdRange, LazyModule, LazyModuleImp} -import freechips.rocketchip.tilelink.TLAdapterNode - -class TLClientsMerger(debug: Boolean)(implicit p: Parameters) extends LazyModule { - - val node = TLAdapterNode( - clientFn = s => { - val sourceIds = s.masters.map(_.sourceId) - val minId = sourceIds.map(_.start).min - val maxId = sourceIds.map(_.end).max - val merged = s.v1copy( - clients = Seq(s.masters.head.v1copy( - sourceId = IdRange(minId, maxId), - visibility = s.masters.flatMap(_.visibility) - )) - ) - if(debug){ - println("TLClientsMerger: Merging clients:") - for(c <- s.masters){ - println(c) - } - println("Merged params:") - println(merged.masters) - } - for(c <- s.masters.tail){ - // ensure all masters have same params except `sourceId` and `visiblity` - val head = s.masters.head - for(i <- (0 until head.productArity) - .filterNot(x => x == 1 || x == 3)) // skip `sourceId` and `visibility` - { - require(head.productElement(i) == c.productElement(i)) - } - } - merged - } - ) - - lazy val module = new LazyModuleImp(this){ - require(node.in.size == 1) - for((in, out) <- node.in.map(_._1).zip(node.out.map(_._1))){ - out <> in - } - for(((in, edgeIn), (out, edgeOut)) <- node.in.zip(node.out)){ - out <> in - // handle b channel carefully - val banks = edgeIn.master.masters.size - if(banks != 1){ - val blockBytes = edgeIn.master.masters.head.visibility.head.alignment - val bankBits = log2Up(banks) - val bankIdx = (out.b.bits.address >> log2Up(blockBytes))(bankBits - 1, 0) - val startIds = VecInit(edgeIn.master.masters.map(_.sourceId.start.U)) - in.b.bits.source := startIds(bankIdx) - } - } - } - -} - -object TLClientsMerger { - def apply(debug: Boolean = true)(implicit p: Parameters) = { - val merger = LazyModule(new TLClientsMerger(debug)) - merger.node - } -} diff --git a/src/main/scala/utils/TLEdgeBuffer.scala b/src/main/scala/utils/TLEdgeBuffer.scala deleted file mode 100644 index f4459d801..000000000 --- a/src/main/scala/utils/TLEdgeBuffer.scala +++ /dev/null @@ -1,98 +0,0 @@ -package utils - -import chisel3._ -import chipsalliance.rocketchip.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.tilelink._ - - -class TLEdgeBuffer -( - edgeFilter: Int => Boolean, - nameOpt: Option[String], - a: BufferParams = BufferParams.default, - b: BufferParams = BufferParams.default, - c: BufferParams = BufferParams.default, - d: BufferParams = BufferParams.default, - e: BufferParams = BufferParams.default, -)(implicit p: Parameters) extends LazyModule { - - val node = new TLBufferNode(a, b, c, d, e) - - lazy val module = new LazyModuleImp(this){ - for((((in, edgeIn), (out, edgeOut)), i) <- node.in.zip(node.out).zipWithIndex){ - val buffer = edgeFilter(i) - if(buffer){ - out <> TLBufferModule(edgeIn, edgeOut, in, name = nameOpt.map(s => s"${s}_edge_$i")) - } else { - out <> in - } - } - } - -} - -object TLEdgeBuffer { - def apply - ( - edgeFilter: Int => Boolean, - nameOpt: Option[String] = None - )(implicit p: Parameters) = { - val buffer = LazyModule(new TLEdgeBuffer(edgeFilter, nameOpt)) - buffer.suggestName(nameOpt) - buffer.node - } -} - -class TLBufferModule -( - edge: TLEdge, - bce: Boolean = true, - a: BufferParams = BufferParams.default, - b: BufferParams = BufferParams.default, - c: BufferParams = BufferParams.default, - d: BufferParams = BufferParams.default, - e: BufferParams = BufferParams.default -) extends Module { - val io = IO(new Bundle() { - val in = Flipped(TLBundle(edge.bundle)) - val out = TLBundle(edge.bundle) - }) - - io.out.a <> a(io.in.a) - io.in.d <> d(io.out.d) - if(bce){ - io.out.c <> c(io.in .c) - io.out.e <> e(io.in .e) - io.in.b <> b(io.out.b) - } else { - io.in.b.valid := false.B - io.in.c.ready := true.B - io.in.e.ready := true.B - io.out.b.ready := true.B - io.out.c.valid := false.B - io.out.e.valid := false.B - } - -} - -object TLBufferModule { - def apply - ( - edgeIn: TLEdgeIn, - edgeOut: TLEdgeOut, - in: TLBundle, - a: BufferParams = BufferParams.default, - b: BufferParams = BufferParams.default, - c: BufferParams = BufferParams.default, - d: BufferParams = BufferParams.default, - e: BufferParams = BufferParams.default, - name: Option[String] = None - ): TLBundle = { - val bce = edgeOut.manager.anySupportAcquireB && edgeOut.client.anySupportProbe - val mod = Module(new TLBufferModule(edgeIn, bce, a, b, c, d, e)) - name.map(mod.suggestName(_)) - mod.io.in <> in - mod.io.out - } -} diff --git a/src/main/scala/xiangshan/Bundle.scala b/src/main/scala/xiangshan/Bundle.scala index 8cf725676..fb70f471c 100644 --- a/src/main/scala/xiangshan/Bundle.scala +++ b/src/main/scala/xiangshan/Bundle.scala @@ -32,6 +32,7 @@ import xiangshan.frontend.CGHPtr import xiangshan.frontend.FtqRead import xiangshan.frontend.FtqToCtrlIO import utils._ +import utility._ import scala.math.max import Chisel.experimental.chiselName diff --git a/src/main/scala/xiangshan/Parameters.scala b/src/main/scala/xiangshan/Parameters.scala index fadcc8483..0ed7c05bd 100644 --- a/src/main/scala/xiangshan/Parameters.scala +++ b/src/main/scala/xiangshan/Parameters.scala @@ -244,7 +244,8 @@ case class XSCoreParameters )), L2NBanks: Int = 1, usePTWRepeater: Boolean = false, - softPTW: Boolean = false // dpi-c debug only + softPTW: Boolean = false, // dpi-c debug only + softPTWDelay: Int = 1 ){ val allHistLens = SCHistLens ++ ITTageTableInfos.map(_._2) ++ TageTableInfos.map(_._2) :+ UbtbGHRLength val HistoryLength = allHistLens.max + numBr * FtqSize + 9 // 256 for the predictor configs now diff --git a/src/main/scala/xiangshan/XSCore.scala b/src/main/scala/xiangshan/XSCore.scala index 54406c94e..48b4146ce 100644 --- a/src/main/scala/xiangshan/XSCore.scala +++ b/src/main/scala/xiangshan/XSCore.scala @@ -26,6 +26,7 @@ import freechips.rocketchip.tile.HasFPUParameters import freechips.rocketchip.tilelink.TLBuffer import system.HasSoCParameter import utils._ +import utility._ import xiangshan.backend._ import xiangshan.backend.exu.{ExuConfig, Wb2Ctrl, WbArbiterWrapper} import xiangshan.cache.mmu._ @@ -137,10 +138,12 @@ abstract class XSCoreBase()(implicit p: config.Parameters) extends LazyModule // outer facing nodes val frontend = LazyModule(new Frontend()) val ptw = LazyModule(new L2TLBWrapper()) - val ptw_to_l2_buffer = LazyModule(new TLBuffer) + val ptw_to_l2_buffer = if (!coreParams.softPTW) LazyModule(new TLBuffer) else null val csrOut = BundleBridgeSource(Some(() => new DistributedCSRIO())) - ptw_to_l2_buffer.node := ptw.node + if (!coreParams.softPTW) { + ptw_to_l2_buffer.node := ptw.node + } val wbArbiter = LazyModule(new WbArbiterWrapper(exuConfigs, NRIntWritePorts, NRFpWritePorts)) val intWbPorts: Seq[Seq[ExuConfig]] = wbArbiter.intWbPorts @@ -294,7 +297,7 @@ class XSCoreImp(outer: XSCoreBase) extends LazyModuleImp(outer) val wb2Ctrl = outer.wb2Ctrl.module val memBlock = outer.memBlock.module val ptw = outer.ptw.module - val ptw_to_l2_buffer = outer.ptw_to_l2_buffer.module + val ptw_to_l2_buffer = if (!coreParams.softPTW) outer.ptw_to_l2_buffer.module else null val exuBlocks = outer.exuBlocks.map(_.module) frontend.io.hartId := io.hartId @@ -400,7 +403,11 @@ class XSCoreImp(outer: XSCoreBase) extends LazyModuleImp(outer) ctrlBlock.perfinfo.perfEventsEu0 := exuBlocks(0).getPerf.dropRight(outer.exuBlocks(0).scheduler.numRs) ctrlBlock.perfinfo.perfEventsEu1 := exuBlocks(1).getPerf.dropRight(outer.exuBlocks(1).scheduler.numRs) - memBlock.io.perfEventsPTW := ptw.getPerf + if (!coreParams.softPTW) { + memBlock.io.perfEventsPTW := ptw.getPerf + } else { + memBlock.io.perfEventsPTW := DontCare + } ctrlBlock.perfinfo.perfEventsRs := outer.exuBlocks.flatMap(b => b.module.getPerf.takeRight(b.scheduler.numRs)) csrioIn.hartId <> io.hartId diff --git a/src/main/scala/xiangshan/XSTile.scala b/src/main/scala/xiangshan/XSTile.scala index 17c27f301..e72374567 100644 --- a/src/main/scala/xiangshan/XSTile.scala +++ b/src/main/scala/xiangshan/XSTile.scala @@ -11,7 +11,7 @@ import huancun.debug.TLLogger import huancun.{HCCacheParamsKey, HuanCun} import system.HasSoCParameter import top.BusPerfMonitor -import utils.{DelayN, ResetGen, TLClientsMerger, TLEdgeBuffer} +import utility.{DelayN, ResetGen, TLClientsMerger, TLEdgeBuffer} class L1BusErrorUnitInfo(implicit val p: Parameters) extends Bundle with HasSoCParameter { val ecc_error = Valid(UInt(soc.PAddrBits.W)) diff --git a/src/main/scala/xiangshan/backend/CtrlBlock.scala b/src/main/scala/xiangshan/backend/CtrlBlock.scala index a8dbafa19..994c4b39e 100644 --- a/src/main/scala/xiangshan/backend/CtrlBlock.scala +++ b/src/main/scala/xiangshan/backend/CtrlBlock.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} import utils._ +import utility._ import xiangshan._ import xiangshan.backend.decode.{DecodeStage, FusionDecoder, ImmUnion} import xiangshan.backend.dispatch.{Dispatch, Dispatch2Rs, DispatchQueue} diff --git a/src/main/scala/xiangshan/backend/ExuBlock.scala b/src/main/scala/xiangshan/backend/ExuBlock.scala index 87a8247e4..6522afadd 100644 --- a/src/main/scala/xiangshan/backend/ExuBlock.scala +++ b/src/main/scala/xiangshan/backend/ExuBlock.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} import utils._ +import utility._ import xiangshan._ import xiangshan.backend.exu._ diff --git a/src/main/scala/xiangshan/backend/FUBlock.scala b/src/main/scala/xiangshan/backend/FUBlock.scala index 70925103b..2e2d37ac1 100644 --- a/src/main/scala/xiangshan/backend/FUBlock.scala +++ b/src/main/scala/xiangshan/backend/FUBlock.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.experimental.hierarchy.Instance import chisel3.util._ import utils._ +import utility._ import xiangshan._ import xiangshan.backend.exu._ import xiangshan.backend.fu.CSRFileIO diff --git a/src/main/scala/xiangshan/backend/MemBlock.scala b/src/main/scala/xiangshan/backend/MemBlock.scala index efdb0fa5f..d241473b5 100644 --- a/src/main/scala/xiangshan/backend/MemBlock.scala +++ b/src/main/scala/xiangshan/backend/MemBlock.scala @@ -22,6 +22,7 @@ import chisel3.util._ import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} import freechips.rocketchip.tile.HasFPUParameters import utils._ +import utility._ import xiangshan._ import xiangshan.backend.exu.StdExeUnit import xiangshan.backend.fu._ @@ -269,6 +270,8 @@ class MemBlockImp(outer: MemBlock) extends LazyModuleImp(outer) // forward loadUnits(i).io.lsq.forward <> lsq.io.forward(i) loadUnits(i).io.sbuffer <> sbuffer.io.forward(i) + loadUnits(i).io.tlDchannel := dcache.io.lsu.forward_D(i) + loadUnits(i).io.forward_mshr <> dcache.io.lsu.forward_mshr(i) // ld-ld violation check loadUnits(i).io.lsq.loadViolationQuery <> lsq.io.loadViolationQuery(i) loadUnits(i).io.csrCtrl <> csrCtrl diff --git a/src/main/scala/xiangshan/backend/Scheduler.scala b/src/main/scala/xiangshan/backend/Scheduler.scala index 1e0a8ba80..1b2e353c0 100644 --- a/src/main/scala/xiangshan/backend/Scheduler.scala +++ b/src/main/scala/xiangshan/backend/Scheduler.scala @@ -22,6 +22,7 @@ import chisel3.util._ import difftest.{DifftestArchFpRegState, DifftestArchIntRegState, DifftestArchVecRegState} import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} import utils._ +import utility._ import xiangshan._ import xiangshan.backend.dispatch.Dispatch2Rs import xiangshan.backend.exu.ExuConfig diff --git a/src/main/scala/xiangshan/backend/decode/DecodeStage.scala b/src/main/scala/xiangshan/backend/decode/DecodeStage.scala index a443d6a29..239f9a889 100644 --- a/src/main/scala/xiangshan/backend/decode/DecodeStage.scala +++ b/src/main/scala/xiangshan/backend/decode/DecodeStage.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ import xiangshan.backend.rename.RatReadPort class DecodeStage(implicit p: Parameters) extends XSModule with HasPerfEvents { diff --git a/src/main/scala/xiangshan/backend/decode/DecodeUnit.scala b/src/main/scala/xiangshan/backend/decode/DecodeUnit.scala index e1c6e1ad7..260e2fe84 100644 --- a/src/main/scala/xiangshan/backend/decode/DecodeUnit.scala +++ b/src/main/scala/xiangshan/backend/decode/DecodeUnit.scala @@ -22,6 +22,7 @@ import chisel3.util._ import freechips.rocketchip.rocket.Instructions import freechips.rocketchip.util.uintToBitPat import utils._ +import utility._ import xiangshan.ExceptionNO.illegalInstr import xiangshan._ import freechips.rocketchip.rocket.Instructions._ diff --git a/src/main/scala/xiangshan/backend/decode/FusionDecoder.scala b/src/main/scala/xiangshan/backend/decode/FusionDecoder.scala index 4705b9eb7..79f329120 100644 --- a/src/main/scala/xiangshan/backend/decode/FusionDecoder.scala +++ b/src/main/scala/xiangshan/backend/decode/FusionDecoder.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import freechips.rocketchip.rocket.Instructions import utils._ +import utility._ import xiangshan._ abstract class BaseFusionCase(pair: Seq[Valid[UInt]])(implicit p: Parameters) diff --git a/src/main/scala/xiangshan/backend/dispatch/Dispatch.scala b/src/main/scala/xiangshan/backend/dispatch/Dispatch.scala index 69bf97e4a..bd3555fc2 100644 --- a/src/main/scala/xiangshan/backend/dispatch/Dispatch.scala +++ b/src/main/scala/xiangshan/backend/dispatch/Dispatch.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import difftest._ import utils._ +import utility._ import xiangshan.ExceptionNO._ import xiangshan._ import xiangshan.backend.rob.RobEnqIO diff --git a/src/main/scala/xiangshan/backend/dispatch/Dispatch2Rs.scala b/src/main/scala/xiangshan/backend/dispatch/Dispatch2Rs.scala index c49e0da2e..7d012747f 100644 --- a/src/main/scala/xiangshan/backend/dispatch/Dispatch2Rs.scala +++ b/src/main/scala/xiangshan/backend/dispatch/Dispatch2Rs.scala @@ -22,6 +22,7 @@ import chisel3.util._ import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} import xiangshan._ import utils._ +import utility._ import xiangshan.backend.exu.ExuConfig import xiangshan.backend.rename.BusyTableReadIO import xiangshan.mem.LsqEnqIO diff --git a/src/main/scala/xiangshan/backend/dispatch/DispatchQueue.scala b/src/main/scala/xiangshan/backend/dispatch/DispatchQueue.scala index 37c58064b..26a8bb2a4 100644 --- a/src/main/scala/xiangshan/backend/dispatch/DispatchQueue.scala +++ b/src/main/scala/xiangshan/backend/dispatch/DispatchQueue.scala @@ -20,6 +20,7 @@ import chipsalliance.rocketchip.config.Parameters import chisel3._ import chisel3.util._ import utils._ +import utility._ import xiangshan._ import xiangshan.backend.rob.RobPtr diff --git a/src/main/scala/xiangshan/backend/dispatch/IndexMapping.scala b/src/main/scala/xiangshan/backend/dispatch/IndexMapping.scala index d1d37eba9..b3f5a4763 100644 --- a/src/main/scala/xiangshan/backend/dispatch/IndexMapping.scala +++ b/src/main/scala/xiangshan/backend/dispatch/IndexMapping.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ class IndexMapping(inWidth: Int, outWidth: Int, withPriority: Boolean)(implicit p: Parameters) extends XSModule { val io = IO(new Bundle() { diff --git a/src/main/scala/xiangshan/backend/exu/ExeUnit.scala b/src/main/scala/xiangshan/backend/exu/ExeUnit.scala index 51e39b997..0a24010f1 100644 --- a/src/main/scala/xiangshan/backend/exu/ExeUnit.scala +++ b/src/main/scala/xiangshan/backend/exu/ExeUnit.scala @@ -22,6 +22,7 @@ import chisel3._ import chisel3.experimental.hierarchy.{Definition, instantiable, public} import chisel3.util._ import utils._ +import utility._ import xiangshan._ import xiangshan.backend.fu.fpu.{FMA, FPUSubModule} import xiangshan.backend.fu.{CSR, FUWithRedirect, Fence, FenceToSbuffer} diff --git a/src/main/scala/xiangshan/backend/exu/Exu.scala b/src/main/scala/xiangshan/backend/exu/Exu.scala index 50ccde289..4c440f0c2 100644 --- a/src/main/scala/xiangshan/backend/exu/Exu.scala +++ b/src/main/scala/xiangshan/backend/exu/Exu.scala @@ -20,7 +20,8 @@ import chipsalliance.rocketchip.config.Parameters import chisel3._ import chisel3.experimental.hierarchy.{IsLookupable, instantiable, public} import chisel3.util._ -import utils.{XSPerfAccumulate, ZeroExt} +import utils.XSPerfAccumulate +import utility.ZeroExt import xiangshan._ import xiangshan.backend.fu._ diff --git a/src/main/scala/xiangshan/backend/exu/MulDivExeUnit.scala b/src/main/scala/xiangshan/backend/exu/MulDivExeUnit.scala index 32b1b5c60..5efb45147 100644 --- a/src/main/scala/xiangshan/backend/exu/MulDivExeUnit.scala +++ b/src/main/scala/xiangshan/backend/exu/MulDivExeUnit.scala @@ -20,6 +20,7 @@ import chipsalliance.rocketchip.config.Parameters import chisel3._ import chisel3.util._ import utils._ +import utility._ import xiangshan._ import xiangshan.backend.fu._ diff --git a/src/main/scala/xiangshan/backend/exu/WbArbiter.scala b/src/main/scala/xiangshan/backend/exu/WbArbiter.scala index 5d3db8959..7074b0306 100644 --- a/src/main/scala/xiangshan/backend/exu/WbArbiter.scala +++ b/src/main/scala/xiangshan/backend/exu/WbArbiter.scala @@ -22,6 +22,7 @@ import chisel3.util._ import difftest.{DifftestFpWriteback, DifftestIntWriteback} import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} import utils._ +import utility._ import xiangshan._ import xiangshan.ExceptionNO._ import xiangshan.backend.HasExuWbHelper diff --git a/src/main/scala/xiangshan/backend/fu/Alu.scala b/src/main/scala/xiangshan/backend/fu/Alu.scala index 9ab325c93..ec02394bb 100644 --- a/src/main/scala/xiangshan/backend/fu/Alu.scala +++ b/src/main/scala/xiangshan/backend/fu/Alu.scala @@ -19,7 +19,7 @@ package xiangshan.backend.fu import chipsalliance.rocketchip.config.Parameters import chisel3._ import chisel3.util._ -import utils.{LookupTree, LookupTreeDefault, ParallelMux, SignExt, ZeroExt} +import utility.{LookupTree, LookupTreeDefault, ParallelMux, SignExt, ZeroExt} import xiangshan._ class AddModule(implicit p: Parameters) extends XSModule { diff --git a/src/main/scala/xiangshan/backend/fu/Bku.scala b/src/main/scala/xiangshan/backend/fu/Bku.scala index 62782ebde..51fc17df5 100644 --- a/src/main/scala/xiangshan/backend/fu/Bku.scala +++ b/src/main/scala/xiangshan/backend/fu/Bku.scala @@ -19,7 +19,8 @@ package xiangshan.backend.fu import chipsalliance.rocketchip.config.Parameters import chisel3._ import chisel3.util._ -import utils.{LookupTreeDefault, ParallelMux, ParallelXOR, SignExt, XSDebug, XSError, ZeroExt} +import utility.{LookupTreeDefault, ParallelMux, ParallelXOR, SignExt, ZeroExt} +import utils.{XSDebug, XSError} import xiangshan._ import xiangshan.backend.fu.util._ diff --git a/src/main/scala/xiangshan/backend/fu/CSR.scala b/src/main/scala/xiangshan/backend/fu/CSR.scala index b8f763749..64cd26f57 100644 --- a/src/main/scala/xiangshan/backend/fu/CSR.scala +++ b/src/main/scala/xiangshan/backend/fu/CSR.scala @@ -21,8 +21,9 @@ import chisel3._ import chisel3.util._ import difftest._ import freechips.rocketchip.util._ -import utils.MaskedRegMap.WritableMask +import utility.MaskedRegMap.WritableMask import utils._ +import utility._ import xiangshan.ExceptionNO._ import xiangshan._ import xiangshan.backend.fu.util._ diff --git a/src/main/scala/xiangshan/backend/fu/Fence.scala b/src/main/scala/xiangshan/backend/fu/Fence.scala index 5dba419d2..c13eb80d4 100644 --- a/src/main/scala/xiangshan/backend/fu/Fence.scala +++ b/src/main/scala/xiangshan/backend/fu/Fence.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ import xiangshan.ExceptionNO.illegalInstr class FenceToSbuffer extends Bundle { diff --git a/src/main/scala/xiangshan/backend/fu/InputBuffer.scala b/src/main/scala/xiangshan/backend/fu/InputBuffer.scala index 03e1c8181..2e2c78688 100644 --- a/src/main/scala/xiangshan/backend/fu/InputBuffer.scala +++ b/src/main/scala/xiangshan/backend/fu/InputBuffer.scala @@ -20,6 +20,7 @@ import chipsalliance.rocketchip.config.Parameters import chisel3._ import chisel3.util._ import utils._ +import utility._ import xiangshan._ import xiangshan.backend.issue.AgeDetector diff --git a/src/main/scala/xiangshan/backend/fu/Jump.scala b/src/main/scala/xiangshan/backend/fu/Jump.scala index 015dc0a5b..db127ebaf 100644 --- a/src/main/scala/xiangshan/backend/fu/Jump.scala +++ b/src/main/scala/xiangshan/backend/fu/Jump.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ import xiangshan.backend._ import xiangshan.backend.decode.ImmUnion import xiangshan.backend.decode.isa._ diff --git a/src/main/scala/xiangshan/backend/fu/Multiplier.scala b/src/main/scala/xiangshan/backend/fu/Multiplier.scala index 9b9aa6b2f..f9e5ce6f6 100644 --- a/src/main/scala/xiangshan/backend/fu/Multiplier.scala +++ b/src/main/scala/xiangshan/backend/fu/Multiplier.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ import xiangshan.backend.fu.util.{C22, C32, C53} class MulDivCtrl extends Bundle{ diff --git a/src/main/scala/xiangshan/backend/fu/PMA.scala b/src/main/scala/xiangshan/backend/fu/PMA.scala index 7ec94a387..d27279cd4 100644 --- a/src/main/scala/xiangshan/backend/fu/PMA.scala +++ b/src/main/scala/xiangshan/backend/fu/PMA.scala @@ -19,7 +19,7 @@ package xiangshan.backend.fu import chisel3._ import chisel3.util._ import freechips.rocketchip.regmapper.{RegField, RegFieldDesc, RegReadFn, RegWriteFn} -import utils.{ParallelPriorityMux, ZeroExt, ValidHold} +import utility.{ParallelPriorityMux, ZeroExt, ValidHold} import xiangshan.cache.mmu.TlbCmd /* Memory Mapped PMA */ diff --git a/src/main/scala/xiangshan/backend/fu/PMP.scala b/src/main/scala/xiangshan/backend/fu/PMP.scala index 0ae3acbba..70aaa2c86 100644 --- a/src/main/scala/xiangshan/backend/fu/PMP.scala +++ b/src/main/scala/xiangshan/backend/fu/PMP.scala @@ -22,10 +22,11 @@ import chipsalliance.rocketchip.config.Parameters import chisel3._ import chisel3.internal.naming.chiselName import chisel3.util._ -import utils.MaskedRegMap.WritableMask +import utility.MaskedRegMap.WritableMask import xiangshan._ import xiangshan.backend.fu.util.HasCSRConst import utils._ +import utility._ import xiangshan.cache.mmu.{TlbCmd, TlbExceptionBundle} trait PMPConst extends HasPMParameters { diff --git a/src/main/scala/xiangshan/backend/fu/Radix2Divider.scala b/src/main/scala/xiangshan/backend/fu/Radix2Divider.scala index 8e2098f50..64036c81e 100644 --- a/src/main/scala/xiangshan/backend/fu/Radix2Divider.scala +++ b/src/main/scala/xiangshan/backend/fu/Radix2Divider.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ abstract class AbstractDivider(len: Int)(implicit p: Parameters) extends FunctionUnit(len){ val ctrl = IO(Input(new MulDivCtrl)) diff --git a/src/main/scala/xiangshan/backend/fu/SRT16Divider.scala b/src/main/scala/xiangshan/backend/fu/SRT16Divider.scala index 475ebb997..46a37276c 100644 --- a/src/main/scala/xiangshan/backend/fu/SRT16Divider.scala +++ b/src/main/scala/xiangshan/backend/fu/SRT16Divider.scala @@ -24,6 +24,7 @@ import chipsalliance.rocketchip.config.Parameters import chisel3._ import chisel3.util._ import utils._ +import utility._ import xiangshan._ import xiangshan.backend.fu.util.CSA3_2 diff --git a/src/main/scala/xiangshan/backend/fu/SRT4Divider.scala b/src/main/scala/xiangshan/backend/fu/SRT4Divider.scala index 6f3ded733..e645493c1 100644 --- a/src/main/scala/xiangshan/backend/fu/SRT4Divider.scala +++ b/src/main/scala/xiangshan/backend/fu/SRT4Divider.scala @@ -23,7 +23,7 @@ package xiangshan.backend.fu import chipsalliance.rocketchip.config.Parameters import chisel3._ import chisel3.util._ -import utils.SignExt +import utility.SignExt import xiangshan.backend.fu.util.CSA3_2 /** A Radix-4 SRT Integer Divider diff --git a/src/main/scala/xiangshan/backend/fu/fpu/FDivSqrt.scala b/src/main/scala/xiangshan/backend/fu/fpu/FDivSqrt.scala index 1965f14ff..0cdab536f 100644 --- a/src/main/scala/xiangshan/backend/fu/fpu/FDivSqrt.scala +++ b/src/main/scala/xiangshan/backend/fu/fpu/FDivSqrt.scala @@ -21,7 +21,7 @@ import chisel3._ import chisel3.experimental.hierarchy.{Definition, Instance, instantiable, public} import chisel3.util._ import fudian.FDIV -import utils.MaskExpand +import utility.MaskExpand import scala.collection.mutable diff --git a/src/main/scala/xiangshan/backend/fu/fpu/FMA.scala b/src/main/scala/xiangshan/backend/fu/fpu/FMA.scala index 936dde36f..7f78511a9 100644 --- a/src/main/scala/xiangshan/backend/fu/fpu/FMA.scala +++ b/src/main/scala/xiangshan/backend/fu/fpu/FMA.scala @@ -23,6 +23,7 @@ import fudian.utils.Multiplier import fudian.{FCMA, FCMA_ADD, FCMA_ADD_s1, FCMA_ADD_s2, FMUL, FMULToFADD, FMUL_s1, FMUL_s2, FMUL_s3, RawFloat} import xiangshan._ import utils._ +import utility._ class MulToAddIO(val ftypes: Seq[FPU.FType])(implicit val p: Parameters) extends Bundle { diff --git a/src/main/scala/xiangshan/backend/fu/fpu/FPToInt.scala b/src/main/scala/xiangshan/backend/fu/fpu/FPToInt.scala index 032decc30..4910ae851 100644 --- a/src/main/scala/xiangshan/backend/fu/fpu/FPToInt.scala +++ b/src/main/scala/xiangshan/backend/fu/fpu/FPToInt.scala @@ -23,7 +23,7 @@ import chipsalliance.rocketchip.config.Parameters import chisel3._ import chisel3.util._ import fudian.FCMP -import utils.SignExt +import utility.SignExt import xiangshan._ diff --git a/src/main/scala/xiangshan/backend/fu/fpu/IntToFP.scala b/src/main/scala/xiangshan/backend/fu/fpu/IntToFP.scala index 51dfe7dfe..787aee5ea 100644 --- a/src/main/scala/xiangshan/backend/fu/fpu/IntToFP.scala +++ b/src/main/scala/xiangshan/backend/fu/fpu/IntToFP.scala @@ -22,7 +22,7 @@ package xiangshan.backend.fu.fpu import chipsalliance.rocketchip.config.Parameters import chisel3._ import chisel3.util._ -import utils.{SignExt, ZeroExt} +import utility.{SignExt, ZeroExt} import xiangshan.backend.fu.HasPipelineReg import xiangshan.i2fCfg diff --git a/src/main/scala/xiangshan/backend/fu/util/CSRConst.scala b/src/main/scala/xiangshan/backend/fu/util/CSRConst.scala index 16fe26ede..bedc7555e 100644 --- a/src/main/scala/xiangshan/backend/fu/util/CSRConst.scala +++ b/src/main/scala/xiangshan/backend/fu/util/CSRConst.scala @@ -19,9 +19,9 @@ package xiangshan.backend.fu.util import chisel3._ import chisel3.util._ import utils._ +import utility._ import xiangshan._ import xiangshan.backend._ -import utils.XSDebug trait HasCSRConst { diff --git a/src/main/scala/xiangshan/backend/issue/BypassNetwork.scala b/src/main/scala/xiangshan/backend/issue/BypassNetwork.scala index 02379a3dd..9c59a1266 100644 --- a/src/main/scala/xiangshan/backend/issue/BypassNetwork.scala +++ b/src/main/scala/xiangshan/backend/issue/BypassNetwork.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ class BypassInfo(numWays: Int, dataBits: Int) extends Bundle { diff --git a/src/main/scala/xiangshan/backend/issue/DataArray.scala b/src/main/scala/xiangshan/backend/issue/DataArray.scala index 6872eec91..ef8f76f3c 100644 --- a/src/main/scala/xiangshan/backend/issue/DataArray.scala +++ b/src/main/scala/xiangshan/backend/issue/DataArray.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ import xiangshan.backend.decode.{ImmUnion, Imm_LUI_LOAD, Imm_U} import xiangshan.backend.exu.ExuConfig diff --git a/src/main/scala/xiangshan/backend/issue/PayloadArray.scala b/src/main/scala/xiangshan/backend/issue/PayloadArray.scala index 3ba6c6af5..2f4553fbe 100644 --- a/src/main/scala/xiangshan/backend/issue/PayloadArray.scala +++ b/src/main/scala/xiangshan/backend/issue/PayloadArray.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ class PayloadArrayReadIO[T <: Data](gen: T, params: RSParams) extends Bundle { val addr = Input(UInt(params.numEntries.W)) diff --git a/src/main/scala/xiangshan/backend/issue/ReservationStationBase.scala b/src/main/scala/xiangshan/backend/issue/ReservationStationBase.scala index f4df80f40..07b5f5e3f 100644 --- a/src/main/scala/xiangshan/backend/issue/ReservationStationBase.scala +++ b/src/main/scala/xiangshan/backend/issue/ReservationStationBase.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} import utils._ +import utility._ import xiangshan._ import xiangshan.backend.exu.ExuConfig import xiangshan.backend.fu.FuConfig diff --git a/src/main/scala/xiangshan/backend/issue/SelectPolicy.scala b/src/main/scala/xiangshan/backend/issue/SelectPolicy.scala index 9e90190bf..5ae2fbfdc 100644 --- a/src/main/scala/xiangshan/backend/issue/SelectPolicy.scala +++ b/src/main/scala/xiangshan/backend/issue/SelectPolicy.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ class SelectPolicy(params: RSParams)(implicit p: Parameters) extends XSModule { val io = IO(new Bundle { diff --git a/src/main/scala/xiangshan/backend/issue/StatusArray.scala b/src/main/scala/xiangshan/backend/issue/StatusArray.scala index b5503f1b3..de114a4ff 100644 --- a/src/main/scala/xiangshan/backend/issue/StatusArray.scala +++ b/src/main/scala/xiangshan/backend/issue/StatusArray.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ import xiangshan.backend.rob.RobPtr import xiangshan.mem.{SqPtr, MemWaitUpdateReq} diff --git a/src/main/scala/xiangshan/backend/issue/WakeupQueue.scala b/src/main/scala/xiangshan/backend/issue/WakeupQueue.scala index 469972e8d..ff2f1d2f3 100644 --- a/src/main/scala/xiangshan/backend/issue/WakeupQueue.scala +++ b/src/main/scala/xiangshan/backend/issue/WakeupQueue.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ class WakeupQueue(number: Int)(implicit p: Parameters) extends XSModule { val io = IO(new Bundle { diff --git a/src/main/scala/xiangshan/backend/rename/BusyTable.scala b/src/main/scala/xiangshan/backend/rename/BusyTable.scala index c7948ceac..8d0eed4e2 100644 --- a/src/main/scala/xiangshan/backend/rename/BusyTable.scala +++ b/src/main/scala/xiangshan/backend/rename/BusyTable.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ class BusyTableReadIO(implicit p: Parameters) extends XSBundle { val req = Input(UInt(PhyRegIdxWidth.W)) diff --git a/src/main/scala/xiangshan/backend/rename/Rename.scala b/src/main/scala/xiangshan/backend/rename/Rename.scala index fd819a2ff..e7971e121 100644 --- a/src/main/scala/xiangshan/backend/rename/Rename.scala +++ b/src/main/scala/xiangshan/backend/rename/Rename.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ import xiangshan.backend.decode.{FusionDecodeInfo, Imm_I, Imm_LUI_LOAD, Imm_U} import xiangshan.backend.rob.RobPtr import xiangshan.backend.rename.freelist._ diff --git a/src/main/scala/xiangshan/backend/rename/RenameTable.scala b/src/main/scala/xiangshan/backend/rename/RenameTable.scala index d7f998672..31eec954b 100644 --- a/src/main/scala/xiangshan/backend/rename/RenameTable.scala +++ b/src/main/scala/xiangshan/backend/rename/RenameTable.scala @@ -19,7 +19,8 @@ package xiangshan.backend.rename import chipsalliance.rocketchip.config.Parameters import chisel3._ import chisel3.util._ -import utils.{ParallelPriorityMux, XSError} +import utility.ParallelPriorityMux +import utils.XSError import xiangshan._ abstract class RegType diff --git a/src/main/scala/xiangshan/backend/rename/freelist/BaseFreeList.scala b/src/main/scala/xiangshan/backend/rename/freelist/BaseFreeList.scala index 9995a3f85..0e4922a94 100644 --- a/src/main/scala/xiangshan/backend/rename/freelist/BaseFreeList.scala +++ b/src/main/scala/xiangshan/backend/rename/freelist/BaseFreeList.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ abstract class BaseFreeList(size: Int)(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelper { diff --git a/src/main/scala/xiangshan/backend/rename/freelist/MEFreeList.scala b/src/main/scala/xiangshan/backend/rename/freelist/MEFreeList.scala index 6ba783d3e..47bcfa31e 100644 --- a/src/main/scala/xiangshan/backend/rename/freelist/MEFreeList.scala +++ b/src/main/scala/xiangshan/backend/rename/freelist/MEFreeList.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ class MEFreeList(size: Int)(implicit p: Parameters) extends BaseFreeList(size) with HasPerfEvents { diff --git a/src/main/scala/xiangshan/backend/rename/freelist/RefCounter.scala b/src/main/scala/xiangshan/backend/rename/freelist/RefCounter.scala index 40f83920f..c329f9cd5 100644 --- a/src/main/scala/xiangshan/backend/rename/freelist/RefCounter.scala +++ b/src/main/scala/xiangshan/backend/rename/freelist/RefCounter.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ diff --git a/src/main/scala/xiangshan/backend/rename/freelist/StdFreeList.scala b/src/main/scala/xiangshan/backend/rename/freelist/StdFreeList.scala index e3ffb2653..3d1acf427 100644 --- a/src/main/scala/xiangshan/backend/rename/freelist/StdFreeList.scala +++ b/src/main/scala/xiangshan/backend/rename/freelist/StdFreeList.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ class StdFreeList(size: Int)(implicit p: Parameters) extends BaseFreeList(size) with HasPerfEvents { diff --git a/src/main/scala/xiangshan/backend/rob/Rob.scala b/src/main/scala/xiangshan/backend/rob/Rob.scala index 800e1a9a7..bce83dc26 100644 --- a/src/main/scala/xiangshan/backend/rob/Rob.scala +++ b/src/main/scala/xiangshan/backend/rob/Rob.scala @@ -22,6 +22,7 @@ import chisel3.util._ import difftest._ import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} import utils._ +import utility._ import xiangshan._ import xiangshan.backend.exu.ExuConfig import xiangshan.frontend.FtqPtr diff --git a/src/main/scala/xiangshan/cache/CacheInstruction.scala b/src/main/scala/xiangshan/cache/CacheInstruction.scala index 96cda4abd..9597bb182 100644 --- a/src/main/scala/xiangshan/cache/CacheInstruction.scala +++ b/src/main/scala/xiangshan/cache/CacheInstruction.scala @@ -5,6 +5,7 @@ import chisel3.util._ import xiangshan._ import xiangshan.frontend.icache._ import utils._ +import utility._ import chipsalliance.rocketchip.config.Parameters import xiangshan.backend.fu.util.HasCSRConst diff --git a/src/main/scala/xiangshan/cache/dcache/DCacheWrapper.scala b/src/main/scala/xiangshan/cache/dcache/DCacheWrapper.scala index bcd9e67e7..e4da3bcf7 100644 --- a/src/main/scala/xiangshan/cache/dcache/DCacheWrapper.scala +++ b/src/main/scala/xiangshan/cache/dcache/DCacheWrapper.scala @@ -22,12 +22,13 @@ import chisel3.experimental.ExtModule import chisel3.util._ import xiangshan._ import utils._ +import utility._ import freechips.rocketchip.diplomacy.{IdRange, LazyModule, LazyModuleImp, TransferSizes} import freechips.rocketchip.tilelink._ import freechips.rocketchip.util.{BundleFieldBase, UIntToOH1} import device.RAMHelper import huancun.{AliasField, AliasKey, DirtyField, PreferCacheField, PrefetchField} -import huancun.utils.FastArbiter +import utility.FastArbiter import mem.{AddPipelineReg} import scala.math.max @@ -335,6 +336,7 @@ class BankedDCacheWordResp(implicit p: Parameters) extends DCacheWordResp { val bank_data = Vec(DCacheBanks, Bits(DCacheSRAMRowBits.W)) val bank_oh = UInt(DCacheBanks.W) + val mshr_id = UInt(log2Up(cfg.nMissEntries).W) } class DCacheWordRespWithError(implicit p: Parameters) extends BaseDCacheWordResp @@ -368,6 +370,7 @@ class Refill(implicit p: Parameters) extends DCacheBundle def dump() = { XSDebug("Refill: addr: %x data: %x\n", addr, data) } + val id = UInt(log2Up(cfg.nMissEntries).W) } class Release(implicit p: Parameters) extends DCacheBundle @@ -478,12 +481,128 @@ class DCacheToSbufferIO(implicit p: Parameters) extends DCacheBundle { def hit_resps: Seq[ValidIO[DCacheLineResp]] = Seq(main_pipe_hit_resp, refill_hit_resp) } +// forward tilelink channel D's data to ldu +class DcacheToLduForwardIO(implicit p: Parameters) extends DCacheBundle { + val valid = Bool() + val data = UInt(l1BusDataWidth.W) + val mshrid = UInt(log2Up(cfg.nMissEntries).W) + val last = Bool() + + def apply(req_valid : Bool, req_data : UInt, req_mshrid : UInt, req_last : Bool) = { + valid := req_valid + data := req_data + mshrid := req_mshrid + last := req_last + } + + def dontCare() = { + valid := false.B + data := DontCare + mshrid := DontCare + last := DontCare + } + + def forward(req_valid : Bool, req_mshr_id : UInt, req_paddr : UInt) = { + val all_match = req_valid && valid && + req_mshr_id === mshrid && + req_paddr(log2Up(refillBytes)) === last + + val forward_D = RegInit(false.B) + val forwardData = RegInit(VecInit(List.fill(8)(0.U(8.W)))) + + val block_idx = req_paddr(log2Up(refillBytes) - 1, 3) + val block_data = Wire(Vec(l1BusDataWidth / 64, UInt(64.W))) + (0 until l1BusDataWidth / 64).map(i => { + block_data(i) := data(64 * i + 63, 64 * i) + }) + val selected_data = block_data(block_idx) + + forward_D := all_match + for (i <- 0 until 8) { + forwardData(i) := selected_data(8 * i + 7, 8 * i) + } + + (forward_D, forwardData) + } +} + +class MissEntryForwardIO(implicit p: Parameters) extends DCacheBundle { + val inflight = Bool() + val paddr = UInt(PAddrBits.W) + val raw_data = Vec(blockBytes/beatBytes, UInt(beatBits.W)) + val firstbeat_valid = Bool() + val lastbeat_valid = Bool() + + def apply(mshr_valid : Bool, mshr_paddr : UInt, mshr_rawdata : Vec[UInt], mshr_first_valid : Bool, mshr_last_valid : Bool) = { + inflight := mshr_valid + paddr := mshr_paddr + raw_data := mshr_rawdata + firstbeat_valid := mshr_first_valid + lastbeat_valid := mshr_last_valid + } + + // check if we can forward from mshr or D channel + def check(req_valid : Bool, req_paddr : UInt) = { + RegNext(req_valid && inflight && req_paddr(PAddrBits - 1, blockOffBits) === paddr(PAddrBits - 1, blockOffBits)) + } + + def forward(req_valid : Bool, req_paddr : UInt) = { + val all_match = (req_paddr(log2Up(refillBytes)) === 0.U && firstbeat_valid) || + (req_paddr(log2Up(refillBytes)) === 1.U && lastbeat_valid) + + val forward_mshr = RegInit(false.B) + val forwardData = RegInit(VecInit(List.fill(8)(0.U(8.W)))) + + val beat_data = raw_data(req_paddr(log2Up(refillBytes))) + val block_idx = req_paddr(log2Up(refillBytes) - 1, 3) + val block_data = Wire(Vec(l1BusDataWidth / 64, UInt(64.W))) + (0 until l1BusDataWidth / 64).map(i => { + block_data(i) := beat_data(64 * i + 63, 64 * i) + }) + val selected_data = block_data(block_idx) + + forward_mshr := all_match + for (i <- 0 until 8) { + forwardData(i) := selected_data(8 * i + 7, 8 * i) + } + + (forward_mshr, forwardData) + } +} + +// forward mshr's data to ldu +class LduToMissqueueForwardIO(implicit p: Parameters) extends DCacheBundle { + // req + val valid = Input(Bool()) + val mshrid = Input(UInt(log2Up(cfg.nMissEntries).W)) + val paddr = Input(UInt(PAddrBits.W)) + // resp + val forward_mshr = Output(Bool()) + val forwardData = Output(Vec(8, UInt(8.W))) + val forward_result_valid = Output(Bool()) + + def connect(sink: LduToMissqueueForwardIO) = { + sink.valid := valid + sink.mshrid := mshrid + sink.paddr := paddr + forward_mshr := sink.forward_mshr + forwardData := sink.forwardData + forward_result_valid := sink.forward_result_valid + } + + def forward() = { + (forward_result_valid, forward_mshr, forwardData) + } +} + class DCacheToLsuIO(implicit p: Parameters) extends DCacheBundle { val load = Vec(LoadPipelineWidth, Flipped(new DCacheLoadIO)) // for speculative load val lsq = ValidIO(new Refill) // refill to load queue, wake up load misses val store = new DCacheToSbufferIO // for sbuffer val atomics = Flipped(new AtomicWordIO) // atomics reqs val release = ValidIO(new Release) // cacheline release hint for ld-ld violation check + val forward_D = Output(Vec(LoadPipelineWidth, new DcacheToLduForwardIO)) + val forward_mshr = Vec(LoadPipelineWidth, new LduToMissqueueForwardIO) } class DCacheIO(implicit p: Parameters) extends DCacheBundle { @@ -516,7 +635,7 @@ class DCache()(implicit p: Parameters) extends LazyModule with HasDCacheParamete class DCacheImp(outer: DCache) extends LazyModuleImp(outer) with HasDCacheParameters with HasPerfEvents { val io = IO(new DCacheIO) - + val (bus, edge) = outer.clientNode.out.head require(bus.d.bits.data.getWidth == l1BusDataWidth, "DCache: tilelink width does not match") @@ -637,6 +756,15 @@ class DCacheImp(outer: DCache) extends LazyModuleImp(outer) with HasDCacheParame ldu(i).io.banked_data_resp := bankedDataArray.io.resp }) + (0 until LoadPipelineWidth).map(i => { + val (_, _, done, _) = edge.count(bus.d) + when(bus.d.bits.opcode === TLMessages.GrantData) { + io.lsu.forward_D(i).apply(bus.d.valid, bus.d.bits.data, bus.d.bits.source, done) + }.otherwise { + io.lsu.forward_D(i).dontCare() + } + }) + //---------------------------------------- // load pipe // the s1 kill signal @@ -672,6 +800,8 @@ class DCacheImp(outer: DCache) extends LazyModuleImp(outer) with HasDCacheParame missReqArb.io.in(MainPipeMissReqPort) <> mainPipe.io.miss_req for (w <- 0 until LoadPipelineWidth) { missReqArb.io.in(w + 1) <> ldu(w).io.miss_req } + for (w <- 0 until LoadPipelineWidth) { ldu(w).io.miss_resp.id := missQueue.io.resp.id } + wb.io.miss_req.valid := missReqArb.io.out.valid wb.io.miss_req.bits := missReqArb.io.out.bits.addr @@ -682,6 +812,9 @@ class DCacheImp(outer: DCache) extends LazyModuleImp(outer) with HasDCacheParame missReqArb.io.out.ready := false.B } + // forward missqueue + (0 until LoadPipelineWidth).map(i => io.lsu.forward_mshr(i).connect(missQueue.io.forward(i))) + // refill to load queue io.lsu.lsq <> missQueue.io.refill_to_ldq diff --git a/src/main/scala/xiangshan/cache/dcache/FakeDCache.scala b/src/main/scala/xiangshan/cache/dcache/FakeDCache.scala index 571f5eb39..997813341 100644 --- a/src/main/scala/xiangshan/cache/dcache/FakeDCache.scala +++ b/src/main/scala/xiangshan/cache/dcache/FakeDCache.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ import freechips.rocketchip.diplomacy.{IdRange, LazyModule, LazyModuleImp, TransferSizes} import freechips.rocketchip.tilelink._ import device.RAMHelper diff --git a/src/main/scala/xiangshan/cache/dcache/Uncache.scala b/src/main/scala/xiangshan/cache/dcache/Uncache.scala index 71306a6e2..3880c9f2e 100644 --- a/src/main/scala/xiangshan/cache/dcache/Uncache.scala +++ b/src/main/scala/xiangshan/cache/dcache/Uncache.scala @@ -20,6 +20,7 @@ import chisel3._ import chisel3.util._ import chipsalliance.rocketchip.config.Parameters import utils._ +import utility._ import xiangshan._ import freechips.rocketchip.diplomacy.{IdRange, LazyModule, LazyModuleImp, TransferSizes} import freechips.rocketchip.tilelink.{TLArbiter, TLBundleA, TLBundleD, TLClientNode, TLEdgeOut, TLMasterParameters, TLMasterPortParameters} diff --git a/src/main/scala/xiangshan/cache/dcache/data/AbstractDataArray.scala b/src/main/scala/xiangshan/cache/dcache/data/AbstractDataArray.scala index a3450611a..99d9f3a5e 100644 --- a/src/main/scala/xiangshan/cache/dcache/data/AbstractDataArray.scala +++ b/src/main/scala/xiangshan/cache/dcache/data/AbstractDataArray.scala @@ -20,7 +20,8 @@ import chipsalliance.rocketchip.config.Parameters import chisel3._ import chisel3.util._ import freechips.rocketchip.tilelink.{ClientMetadata, TLClientParameters, TLEdgeOut} -import utils.{Code, ParallelOR, ReplacementPolicy, SRAMTemplate, XSDebug} +import utility.{Code, ParallelOR, ReplacementPolicy, SRAMTemplate} +import utils.XSDebug import xiangshan.L1CacheErrorInfo import scala.math.max diff --git a/src/main/scala/xiangshan/cache/dcache/data/BankedDataArray.scala b/src/main/scala/xiangshan/cache/dcache/data/BankedDataArray.scala index 95a0ef175..1a053c0cf 100644 --- a/src/main/scala/xiangshan/cache/dcache/data/BankedDataArray.scala +++ b/src/main/scala/xiangshan/cache/dcache/data/BankedDataArray.scala @@ -19,9 +19,9 @@ package xiangshan.cache import chipsalliance.rocketchip.config.Parameters import chisel3._ import utils._ +import utility._ import chisel3.util._ import freechips.rocketchip.tilelink.{ClientMetadata, TLClientParameters, TLEdgeOut} -import utils.{Code, ParallelOR, ReplacementPolicy, SRAMTemplate, XSDebug, XSPerfAccumulate} import xiangshan.L1CacheErrorInfo import scala.math.max diff --git a/src/main/scala/xiangshan/cache/dcache/data/DuplicatedDataArray.scala b/src/main/scala/xiangshan/cache/dcache/data/DuplicatedDataArray.scala index a3e672a71..78a9b5a65 100644 --- a/src/main/scala/xiangshan/cache/dcache/data/DuplicatedDataArray.scala +++ b/src/main/scala/xiangshan/cache/dcache/data/DuplicatedDataArray.scala @@ -20,7 +20,8 @@ import chipsalliance.rocketchip.config.Parameters import chisel3._ import chisel3.util._ import freechips.rocketchip.tilelink.{ClientMetadata, TLClientParameters, TLEdgeOut} -import utils.{Code, ParallelOR, ReplacementPolicy, SRAMTemplate, XSDebug} +import utility.{Code, ParallelOR, ReplacementPolicy, SRAMTemplate} +import utils.XSDebug import scala.math.max diff --git a/src/main/scala/xiangshan/cache/dcache/loadpipe/LoadPipe.scala b/src/main/scala/xiangshan/cache/dcache/loadpipe/LoadPipe.scala index e5fb20a73..81b4d743f 100644 --- a/src/main/scala/xiangshan/cache/dcache/loadpipe/LoadPipe.scala +++ b/src/main/scala/xiangshan/cache/dcache/loadpipe/LoadPipe.scala @@ -48,6 +48,7 @@ class LoadPipe(id: Int)(implicit p: Parameters) extends DCacheModule with HasPer // send miss request to miss queue val miss_req = DecoupledIO(new MissReq) + val miss_resp = Input(new MissResp) // update state vec in replacement algo val replace_access = ValidIO(new ReplacementAccessBundle) @@ -276,6 +277,7 @@ class LoadPipe(id: Int)(implicit p: Parameters) extends DCacheModule with HasPer // load pipe need replay when there is a bank conflict resp.bits.replay := resp.bits.miss && (!io.miss_req.fire() || s2_nack) || io.bank_conflict_slow resp.bits.tag_error := s2_tag_error // report tag_error in load s2 + resp.bits.mshr_id := io.miss_resp.id XSPerfAccumulate("dcache_read_bank_conflict", io.bank_conflict_slow && s2_valid) diff --git a/src/main/scala/xiangshan/cache/dcache/mainpipe/MainPipe.scala b/src/main/scala/xiangshan/cache/dcache/mainpipe/MainPipe.scala index b40403750..c183c2840 100644 --- a/src/main/scala/xiangshan/cache/dcache/mainpipe/MainPipe.scala +++ b/src/main/scala/xiangshan/cache/dcache/mainpipe/MainPipe.scala @@ -24,6 +24,7 @@ import freechips.rocketchip.tilelink.MemoryOpCategories._ import freechips.rocketchip.tilelink.TLPermissions._ import freechips.rocketchip.tilelink.{ClientMetadata, ClientStates, TLPermissions} import utils._ +import utility._ import xiangshan.L1CacheErrorInfo class MainPipeReq(implicit p: Parameters) extends DCacheBundle { diff --git a/src/main/scala/xiangshan/cache/dcache/mainpipe/MissQueue.scala b/src/main/scala/xiangshan/cache/dcache/mainpipe/MissQueue.scala index 62578587d..d907b524d 100644 --- a/src/main/scala/xiangshan/cache/dcache/mainpipe/MissQueue.scala +++ b/src/main/scala/xiangshan/cache/dcache/mainpipe/MissQueue.scala @@ -21,13 +21,14 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ import freechips.rocketchip.tilelink._ import freechips.rocketchip.tilelink.ClientStates._ import freechips.rocketchip.tilelink.MemoryOpCategories._ import freechips.rocketchip.tilelink.TLPermissions._ import difftest._ import huancun.{AliasKey, DirtyKey, PreferCacheKey, PrefetchKey} -import huancun.utils.FastArbiter +import utility.FastArbiter import mem.{AddPipelineReg} class MissReqWoStoreData(implicit p: Parameters) extends DCacheBundle { @@ -106,8 +107,13 @@ class MissReq(implicit p: Parameters) extends MissReqWoStoreData { } } +class MissResp(implicit p: Parameters) extends DCacheBundle { + val id = UInt(log2Up(cfg.nMissEntries).W) +} + class MissEntry(edge: TLEdgeOut)(implicit p: Parameters) extends DCacheModule { val io = IO(new Bundle() { + val hartId = Input(UInt(8.W)) // MSHR ID val id = Input(UInt(log2Up(cfg.nMissEntries).W)) // client requests @@ -150,6 +156,10 @@ class MissEntry(edge: TLEdgeOut)(implicit p: Parameters) extends DCacheModule { val idx = UInt(idxBits.W) // vaddr val tag = UInt(tagBits.W) // paddr }) + + val req_handled_by_this_entry = Output(Bool()) + + val forwardInfo = Output(new MissEntryForwardIO) }) assert(!RegNext(io.primary_valid && !io.primary_ready)) @@ -200,6 +210,10 @@ class MissEntry(edge: TLEdgeOut)(implicit p: Parameters) extends DCacheModule { // merge miss req to current miss queue entry val secondary_fire = WireInit(io.req.valid && io.secondary_ready && !io.req.bits.cancel) + val req_handled_by_this_entry = primary_fire || secondary_fire + + io.req_handled_by_this_entry := req_handled_by_this_entry + when (release_entry && req_valid) { req_valid := false.B } @@ -395,6 +409,7 @@ class MissEntry(edge: TLEdgeOut)(implicit p: Parameters) extends DCacheModule { val data = refill_and_store_data.asUInt data((i + 1) * l1BusDataWidth - 1, i * l1BusDataWidth) }))) + // when granted data is all ready, wakeup lq's miss load io.refill_to_ldq.valid := RegNext(!w_grantlast && io.mem_grant.fire()) && should_refill_data_reg io.refill_to_ldq.bits.addr := RegNext(req.addr + (refill_count << refillOffBits)) io.refill_to_ldq.bits.data := refill_data_splited(RegNext(refill_count)) @@ -402,6 +417,7 @@ class MissEntry(edge: TLEdgeOut)(implicit p: Parameters) extends DCacheModule { io.refill_to_ldq.bits.refill_done := RegNext(refill_done && io.mem_grant.fire()) io.refill_to_ldq.bits.hasdata := hasData io.refill_to_ldq.bits.data_raw := refill_data_raw.asUInt + io.refill_to_ldq.bits.id := io.id io.mem_acquire.valid := !s_acquire val grow_param = req.req_coh.onAccess(req.cmd)._2 @@ -506,6 +522,8 @@ class MissEntry(edge: TLEdgeOut)(implicit p: Parameters) extends DCacheModule { io.debug_early_replace.bits.idx := addr_to_dcache_set(req.vaddr) io.debug_early_replace.bits.tag := req.replace_tag + io.forwardInfo.apply(req_valid, req.addr, refill_data_raw, w_grantfirst, w_grantlast) + XSPerfAccumulate("miss_req_primary", primary_fire) XSPerfAccumulate("miss_req_merged", secondary_fire) XSPerfAccumulate("load_miss_penalty_to_use", @@ -538,6 +556,7 @@ class MissQueue(edge: TLEdgeOut)(implicit p: Parameters) extends DCacheModule wi val io = IO(new Bundle { val hartId = Input(UInt(8.W)) val req = Flipped(DecoupledIO(new MissReq)) + val resp = Output(new MissResp) val refill_to_ldq = ValidIO(new Refill) val mem_acquire = DecoupledIO(new TLBundleA(edge.bundle)) @@ -568,6 +587,9 @@ class MissQueue(edge: TLEdgeOut)(implicit p: Parameters) extends DCacheModule wi val idx = UInt(idxBits.W) // vaddr val tag = UInt(tagBits.W) // paddr })) + + // forward missqueue + val forward = Vec(LoadPipelineWidth, new LduToMissqueueForwardIO) }) // 128KBL1: FIXME: provide vaddr for l2 @@ -587,6 +609,22 @@ class MissQueue(edge: TLEdgeOut)(implicit p: Parameters) extends DCacheModule wi val alloc = !reject && !merge && Cat(primary_ready_vec).orR val accept = alloc || merge + val req_handled_vec = entries.map(_.io.req_handled_by_this_entry) + assert(PopCount(req_handled_vec) <= 1.U, "Only one mshr can handle a req") + io.resp.id := OHToUInt(req_handled_vec) + + val forwardInfo_vec = VecInit(entries.map(_.io.forwardInfo)) + (0 until LoadPipelineWidth).map(i => { + val id = io.forward(i).mshrid + val req_valid = io.forward(i).valid + val paddr = io.forward(i).paddr + + val (forward_mshr, forwardData) = forwardInfo_vec(id).forward(req_valid, paddr) + io.forward(i).forward_result_valid := forwardInfo_vec(id).check(req_valid, paddr) + io.forward(i).forward_mshr := forward_mshr + io.forward(i).forwardData := forwardData + }) + assert(RegNext(PopCount(secondary_ready_vec) <= 1.U)) // assert(RegNext(PopCount(secondary_reject_vec) <= 1.U)) // It is possible that one mshr wants to merge a req, while another mshr wants to reject it. @@ -616,6 +654,7 @@ class MissQueue(edge: TLEdgeOut)(implicit p: Parameters) extends DCacheModule wi else Cat((0 until i).map(j => entries(j).io.primary_ready)).orR + e.io.hartId := io.hartId e.io.id := i.U e.io.req.valid := io.req.valid e.io.primary_valid := io.req.valid && diff --git a/src/main/scala/xiangshan/cache/dcache/meta/MetaArray.scala b/src/main/scala/xiangshan/cache/dcache/meta/MetaArray.scala index b15ea9bb0..9e4959a65 100644 --- a/src/main/scala/xiangshan/cache/dcache/meta/MetaArray.scala +++ b/src/main/scala/xiangshan/cache/dcache/meta/MetaArray.scala @@ -20,7 +20,8 @@ import chipsalliance.rocketchip.config.Parameters import chisel3._ import chisel3.util._ import freechips.rocketchip.tilelink.{ClientMetadata, TLClientParameters, TLEdgeOut} -import utils.{Code, ParallelOR, ReplacementPolicy, SRAMTemplate, XSDebug} +import utility.{Code, ParallelOR, ReplacementPolicy, SRAMTemplate} +import utils.XSDebug import xiangshan.L1CacheErrorInfo // basic building blocks for L1 DCache diff --git a/src/main/scala/xiangshan/cache/dcache/meta/TagArray.scala b/src/main/scala/xiangshan/cache/dcache/meta/TagArray.scala index 660fc8851..129414e43 100644 --- a/src/main/scala/xiangshan/cache/dcache/meta/TagArray.scala +++ b/src/main/scala/xiangshan/cache/dcache/meta/TagArray.scala @@ -19,7 +19,7 @@ package xiangshan.cache import chipsalliance.rocketchip.config.Parameters import chisel3._ import chisel3.util._ -import utils.SRAMTemplate +import utility.SRAMTemplate import xiangshan.cache.CacheInstrucion._ class TagReadReq(implicit p: Parameters) extends DCacheBundle { diff --git a/src/main/scala/xiangshan/cache/mmu/L2TLB.scala b/src/main/scala/xiangshan/cache/mmu/L2TLB.scala index c3baf68c3..66d3c6773 100644 --- a/src/main/scala/xiangshan/cache/mmu/L2TLB.scala +++ b/src/main/scala/xiangshan/cache/mmu/L2TLB.scala @@ -24,10 +24,12 @@ import chisel3.internal.naming.chiselName import xiangshan._ import xiangshan.cache.{HasDCacheParameters, MemoryOpConstants} import utils._ +import utility._ import freechips.rocketchip.diplomacy.{IdRange, LazyModule, LazyModuleImp} import freechips.rocketchip.tilelink._ import xiangshan.backend.fu.{PMP, PMPChecker, PMPReqBundle, PMPRespBundle} import xiangshan.backend.fu.util.HasCSRConst +import utility.ChiselDB class L2TLB()(implicit p: Parameters) extends LazyModule with HasPtwConst { @@ -131,6 +133,11 @@ class L2TLBImp(outer: L2TLB)(implicit p: Parameters) extends PtwModule(outer) wi prefetch.io.sfence := sfence_dup(0) prefetch.io.csr := csr_dup(0) arb2.io.in(InArbPrefetchPort) <> prefetch.io.out + + val L2TlbPrefetchTable = ChiselDB.createTable("L2TlbPrefetch_hart" + p(XSCoreParamsKey).HartId.toString, new L2TlbPrefetchDB) + val L2TlbPrefetchDB = Wire(new L2TlbPrefetchDB) + L2TlbPrefetchDB.vpn := prefetch.io.out.bits.vpn + L2TlbPrefetchTable.log(L2TlbPrefetchDB, prefetch.io.out.fire, "L2TlbPrefetch", clock, reset) } arb2.io.out.ready := cache.io.req.ready @@ -383,6 +390,52 @@ class L2TLBImp(outer: L2TLB)(implicit p: Parameters) extends PtwModule(outer) wi val perfEvents = Seq(llptw, cache, ptw).flatMap(_.getPerfEvents) generatePerfEvent() + + val L1TlbTable = ChiselDB.createTable("L1Tlb_hart" + p(XSCoreParamsKey).HartId.toString, new L1TlbDB) + val ITlbReqDB, DTlbReqDB, ITlbRespDB, DTlbRespDB = Wire(new L1TlbDB) + ITlbReqDB.vpn := io.tlb(0).req(0).bits.vpn + DTlbReqDB.vpn := io.tlb(1).req(0).bits.vpn + ITlbRespDB.vpn := io.tlb(0).resp.bits.entry.tag + DTlbRespDB.vpn := io.tlb(1).resp.bits.entry.tag + L1TlbTable.log(ITlbReqDB, io.tlb(0).req(0).fire, "ITlbReq", clock, reset) + L1TlbTable.log(DTlbReqDB, io.tlb(1).req(0).fire, "DTlbReq", clock, reset) + L1TlbTable.log(ITlbRespDB, io.tlb(0).resp.fire, "ITlbResp", clock, reset) + L1TlbTable.log(DTlbRespDB, io.tlb(1).resp.fire, "DTlbResp", clock, reset) + + val PageCacheTable = ChiselDB.createTable("PageCache_hart" + p(XSCoreParamsKey).HartId.toString, new PageCacheDB) + val PageCacheDB = Wire(new PageCacheDB) + PageCacheDB.vpn := cache.io.resp.bits.toTlb.tag + PageCacheDB.source := cache.io.resp.bits.req_info.source + PageCacheDB.bypassed := cache.io.resp.bits.bypassed + PageCacheDB.is_first := cache.io.resp.bits.isFirst + PageCacheDB.prefetched := cache.io.resp.bits.toTlb.prefetch + PageCacheDB.prefetch := cache.io.resp.bits.prefetch + PageCacheDB.l2Hit := cache.io.resp.bits.toFsm.l2Hit + PageCacheDB.l1Hit := cache.io.resp.bits.toFsm.l1Hit + PageCacheDB.hit := cache.io.resp.bits.hit + PageCacheTable.log(PageCacheDB, cache.io.resp.fire, "PageCache", clock, reset) + + val PTWTable = ChiselDB.createTable("PTW_hart" + p(XSCoreParamsKey).HartId.toString, new PTWDB) + val PTWReqDB, PTWRespDB, LLPTWReqDB, LLPTWRespDB = Wire(new PTWDB) + PTWReqDB.vpn := ptw.io.req.bits.req_info.vpn + PTWReqDB.source := ptw.io.req.bits.req_info.source + PTWRespDB.vpn := ptw.io.refill.req_info.vpn + PTWRespDB.source := ptw.io.refill.req_info.source + LLPTWReqDB.vpn := llptw.io.in.bits.req_info.vpn + LLPTWReqDB.source := llptw.io.in.bits.req_info.source + LLPTWRespDB.vpn := llptw.io.mem.refill.vpn + LLPTWRespDB.source := llptw.io.mem.refill.source + PTWTable.log(PTWReqDB, ptw.io.req.fire, "PTWReq", clock, reset) + PTWTable.log(PTWRespDB, ptw.io.mem.resp.fire, "PTWResp", clock, reset) + PTWTable.log(LLPTWReqDB, llptw.io.in.fire, "LLPTWReq", clock, reset) + PTWTable.log(LLPTWRespDB, llptw.io.mem.resp.fire, "LLPTWResp", clock, reset) + + val L2TlbMissQueueTable = ChiselDB.createTable("L2TlbMissQueue_hart" + p(XSCoreParamsKey).HartId.toString, new L2TlbMissQueueDB) + val L2TlbMissQueueInDB, L2TlbMissQueueOutDB = Wire(new L2TlbMissQueueDB) + L2TlbMissQueueInDB.vpn := missQueue.io.in.bits.vpn + L2TlbMissQueueOutDB.vpn := missQueue.io.out.bits.vpn + L2TlbMissQueueTable.log(L2TlbMissQueueInDB, missQueue.io.in.fire, "L2TlbMissQueueIn", clock, reset) + L2TlbMissQueueTable.log(L2TlbMissQueueOutDB, missQueue.io.out.fire, "L2TlbMissQueueOut", clock, reset) } /** BlockHelper, block missqueue, not to send too many req to cache @@ -424,29 +477,83 @@ class PTEHelper() extends ExtModule { val pf = IO(Output(UInt(8.W))) } +class PTWDelayN[T <: Data](gen: T, n: Int, flush: Bool) extends Module { + val io = IO(new Bundle() { + val in = Input(gen) + val out = Output(gen) + val ptwflush = Input(flush.cloneType) + }) + val out = RegInit(VecInit(Seq.fill(n)(0.U.asTypeOf(gen)))) + val t = RegInit(VecInit(Seq.fill(n)(0.U.asTypeOf(gen)))) + out(0) := io.in + if (n == 1) { + io.out := out(0) + } else { + when (io.ptwflush) { + for (i <- 0 until n) { + t(i) := 0.U.asTypeOf(gen) + out(i) := 0.U.asTypeOf(gen) + } + io.out := 0.U.asTypeOf(gen) + } .otherwise { + for (i <- 1 until n) { + t(i-1) := out(i-1) + out(i) := t(i-1) + } + io.out := out(n-1) + } + } +} + +object PTWDelayN { + def apply[T <: Data](in: T, n: Int, flush: Bool): T = { + val delay = Module(new PTWDelayN(in.cloneType, n, flush)) + delay.io.in := in + delay.io.ptwflush := flush + delay.io.out + } +} + class FakePTW()(implicit p: Parameters) extends XSModule with HasPtwConst { val io = IO(new L2TLBIO) - + val flush = VecInit(Seq.fill(PtwWidth)(false.B)) + flush(0) := DelayN(io.sfence.valid || io.csr.tlb.satp.changed, itlbParams.fenceDelay) + flush(1) := DelayN(io.sfence.valid || io.csr.tlb.satp.changed, ldtlbParams.fenceDelay) for (i <- 0 until PtwWidth) { - io.tlb(i).req(0).ready := true.B - val helper = Module(new PTEHelper()) helper.clock := clock - helper.enable := io.tlb(i).req(0).valid helper.satp := io.csr.tlb.satp.ppn - helper.vpn := io.tlb(i).req(0).bits.vpn + + if (coreParams.softPTWDelay == 1) { + helper.enable := io.tlb(i).req(0).fire + helper.vpn := io.tlb(i).req(0).bits.vpn + } else { + helper.enable := PTWDelayN(io.tlb(i).req(0).fire, coreParams.softPTWDelay - 1, flush(i)) + helper.vpn := PTWDelayN(io.tlb(i).req(0).bits.vpn, coreParams.softPTWDelay - 1, flush(i)) + } + val pte = helper.pte.asTypeOf(new PteBundle) val level = helper.level val pf = helper.pf + val empty = RegInit(true.B) + when (io.tlb(i).req(0).fire) { + empty := false.B + } .elsewhen (io.tlb(i).resp.fire || flush(i)) { + empty := true.B + } - io.tlb(i).resp.valid := RegNext(io.tlb(i).req(0).valid) + io.tlb(i).req(0).ready := empty || io.tlb(i).resp.fire + io.tlb(i).resp.valid := PTWDelayN(io.tlb(i).req(0).fire, coreParams.softPTWDelay, flush(i)) assert(!io.tlb(i).resp.valid || io.tlb(i).resp.ready) - io.tlb(i).resp.bits.entry.tag := RegNext(io.tlb(i).req(0).bits.vpn) + io.tlb(i).resp.bits.entry.tag := PTWDelayN(io.tlb(i).req(0).bits.vpn, coreParams.softPTWDelay, flush(i)) io.tlb(i).resp.bits.entry.ppn := pte.ppn io.tlb(i).resp.bits.entry.perm.map(_ := pte.getPerm()) io.tlb(i).resp.bits.entry.level.map(_ := level) io.tlb(i).resp.bits.pf := pf io.tlb(i).resp.bits.af := DontCare // TODO: implement it + io.tlb(i).resp.bits.entry.v := !pf + io.tlb(i).resp.bits.entry.prefetch := DontCare + io.tlb(i).resp.bits.entry.asid := io.csr.tlb.satp.asid } } diff --git a/src/main/scala/xiangshan/cache/mmu/L2TLBMissQueue.scala b/src/main/scala/xiangshan/cache/mmu/L2TLBMissQueue.scala index c26f2a5e5..3772d93ea 100644 --- a/src/main/scala/xiangshan/cache/mmu/L2TLBMissQueue.scala +++ b/src/main/scala/xiangshan/cache/mmu/L2TLBMissQueue.scala @@ -23,6 +23,7 @@ import chisel3.internal.naming.chiselName import xiangshan._ import xiangshan.cache.{HasDCacheParameters, MemoryOpConstants} import utils._ +import utility._ import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} import freechips.rocketchip.tilelink._ diff --git a/src/main/scala/xiangshan/cache/mmu/L2TlbPrefetch.scala b/src/main/scala/xiangshan/cache/mmu/L2TlbPrefetch.scala index 608cf28b6..2a52b9c16 100644 --- a/src/main/scala/xiangshan/cache/mmu/L2TlbPrefetch.scala +++ b/src/main/scala/xiangshan/cache/mmu/L2TlbPrefetch.scala @@ -20,6 +20,7 @@ import chisel3.util._ import chipsalliance.rocketchip.config.Parameters import xiangshan.{SfenceBundle, XSModule} import utils._ +import utility._ class L2TlbPrefetchIO(implicit p: Parameters) extends MMUIOBaseBundle with HasPtwConst { val in = Flipped(ValidIO(new Bundle { @@ -36,7 +37,7 @@ class L2TlbPrefetch(implicit p: Parameters) extends XSModule with HasPtwConst { val OldRecordSize = 4 val old_reqs = Reg(Vec(OldRecordSize, UInt(vpnLen.W))) - val old_v = VecInit(Seq.fill(OldRecordSize)(RegInit(false.B))) + val old_v = RegInit(VecInit(Seq.fill(OldRecordSize)(false.B))) val old_index = RegInit(0.U(log2Ceil(OldRecordSize).W)) def already_have(vpn: UInt): Bool = { @@ -63,6 +64,7 @@ class L2TlbPrefetch(implicit p: Parameters) extends XSModule with HasPtwConst { old_v.map(_ := false.B) } - XSPerfAccumulate("l2tlb_prefetch_input_count", input_valid) + XSPerfAccumulate("l2tlb_prefetch_input_count", io.in.valid) + XSPerfAccumulate("l2tlb_prefetch_valid_count", input_valid) XSPerfAccumulate("l2tlb_prefetch_output_count", io.out.fire()) } diff --git a/src/main/scala/xiangshan/cache/mmu/MMUBundle.scala b/src/main/scala/xiangshan/cache/mmu/MMUBundle.scala index f996b3238..f43ce30b4 100644 --- a/src/main/scala/xiangshan/cache/mmu/MMUBundle.scala +++ b/src/main/scala/xiangshan/cache/mmu/MMUBundle.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ import xiangshan.backend.rob.RobPtr import xiangshan.backend.fu.util.HasCSRConst import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} @@ -746,3 +747,32 @@ object ValidHoldBypass{ valid || infire } } + +class L1TlbDB(implicit p: Parameters) extends TlbBundle { + val vpn = UInt(vpnLen.W) +} + +class PageCacheDB(implicit p: Parameters) extends TlbBundle with HasPtwConst { + val vpn = UInt(vpnLen.W) + val source = UInt(bSourceWidth.W) + val bypassed = Bool() + val is_first = Bool() + val prefetched = Bool() + val prefetch = Bool() + val l2Hit = Bool() + val l1Hit = Bool() + val hit = Bool() +} + +class PTWDB(implicit p: Parameters) extends TlbBundle with HasPtwConst { + val vpn = UInt(vpnLen.W) + val source = UInt(bSourceWidth.W) +} + +class L2TlbPrefetchDB(implicit p: Parameters) extends TlbBundle { + val vpn = UInt(vpnLen.W) +} + +class L2TlbMissQueueDB(implicit p: Parameters) extends TlbBundle { + val vpn = UInt(vpnLen.W) +} diff --git a/src/main/scala/xiangshan/cache/mmu/MMUConst.scala b/src/main/scala/xiangshan/cache/mmu/MMUConst.scala index 4b7dac516..e7142ec33 100644 --- a/src/main/scala/xiangshan/cache/mmu/MMUConst.scala +++ b/src/main/scala/xiangshan/cache/mmu/MMUConst.scala @@ -22,6 +22,7 @@ import chisel3.util._ import xiangshan._ import xiangshan.cache.{HasDCacheParameters, MemoryOpConstants} import utils._ +import utility._ import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} import freechips.rocketchip.tilelink._ diff --git a/src/main/scala/xiangshan/cache/mmu/PageTableCache.scala b/src/main/scala/xiangshan/cache/mmu/PageTableCache.scala index 1c2afa7a8..4abc20ec1 100644 --- a/src/main/scala/xiangshan/cache/mmu/PageTableCache.scala +++ b/src/main/scala/xiangshan/cache/mmu/PageTableCache.scala @@ -23,6 +23,7 @@ import chisel3.internal.naming.chiselName import xiangshan._ import xiangshan.cache.{HasDCacheParameters, MemoryOpConstants} import utils._ +import utility._ import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} import freechips.rocketchip.tilelink._ @@ -640,7 +641,7 @@ class PtwCache()(implicit p: Parameters) extends XSModule with HasPtwConst with when (sfence_dup(0).bits.rs2) { // specific leaf of addr && all asid - spv := spv & (~VecInit(sp.map(_.hit(sfence_vpn, sfence_dup(0).bits.asid, ignoreAsid = true))).asUInt | spg) + spv := spv & (~VecInit(sp.map(_.hit(sfence_vpn, sfence_dup(0).bits.asid, ignoreAsid = true))).asUInt) } .otherwise { // specific leaf of addr && specific asid spv := spv & (~VecInit(sp.map(_.hit(sfence_vpn, sfence_dup(0).bits.asid))).asUInt | spg) diff --git a/src/main/scala/xiangshan/cache/mmu/PageTableWalker.scala b/src/main/scala/xiangshan/cache/mmu/PageTableWalker.scala index 775c3a730..9b611580b 100644 --- a/src/main/scala/xiangshan/cache/mmu/PageTableWalker.scala +++ b/src/main/scala/xiangshan/cache/mmu/PageTableWalker.scala @@ -23,6 +23,7 @@ import chisel3.internal.naming.chiselName import xiangshan._ import xiangshan.cache.{HasDCacheParameters, MemoryOpConstants} import utils._ +import utility._ import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} import freechips.rocketchip.tilelink._ import xiangshan.backend.fu.{PMPReqBundle, PMPRespBundle} diff --git a/src/main/scala/xiangshan/cache/mmu/Repeater.scala b/src/main/scala/xiangshan/cache/mmu/Repeater.scala index fcc17bcd2..a472e0063 100644 --- a/src/main/scala/xiangshan/cache/mmu/Repeater.scala +++ b/src/main/scala/xiangshan/cache/mmu/Repeater.scala @@ -22,6 +22,7 @@ import chisel3.util._ import xiangshan._ import xiangshan.cache.{HasDCacheParameters, MemoryOpConstants} import utils._ +import utility._ import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} import freechips.rocketchip.tilelink._ diff --git a/src/main/scala/xiangshan/cache/mmu/TLB.scala b/src/main/scala/xiangshan/cache/mmu/TLB.scala index 265be83ed..1d0850b56 100644 --- a/src/main/scala/xiangshan/cache/mmu/TLB.scala +++ b/src/main/scala/xiangshan/cache/mmu/TLB.scala @@ -23,6 +23,7 @@ import chisel3.util._ import freechips.rocketchip.util.SRAMAnnotation import xiangshan._ import utils._ +import utility._ import xiangshan.backend.fu.{PMPChecker, PMPReqBundle, PMPConfig => XSPMPConfig} import xiangshan.backend.rob.RobPtr import xiangshan.backend.fu.util.HasCSRConst diff --git a/src/main/scala/xiangshan/cache/mmu/TLBStorage.scala b/src/main/scala/xiangshan/cache/mmu/TLBStorage.scala index d21a3026d..65a65e5e9 100644 --- a/src/main/scala/xiangshan/cache/mmu/TLBStorage.scala +++ b/src/main/scala/xiangshan/cache/mmu/TLBStorage.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.experimental.chiselName import chisel3.util._ import utils._ +import utility._ import freechips.rocketchip.formal.PropertyClass import scala.math.min diff --git a/src/main/scala/xiangshan/cache/prefetch/BestOffsetPrefetch.scala b/src/main/scala/xiangshan/cache/prefetch/BestOffsetPrefetch.scala index 2ada4789b..5b2f4b4bc 100644 --- a/src/main/scala/xiangshan/cache/prefetch/BestOffsetPrefetch.scala +++ b/src/main/scala/xiangshan/cache/prefetch/BestOffsetPrefetch.scala @@ -23,6 +23,7 @@ import xiangshan._ import xiangshan.cache._ import xiangshan.cache.mmu.{HasTlbConst} import utils._ +import utility._ case object BOPParamsKey extends Field[BOPParameters] diff --git a/src/main/scala/xiangshan/cache/prefetch/Prefetcher.scala b/src/main/scala/xiangshan/cache/prefetch/Prefetcher.scala index 142097252..e581318af 100644 --- a/src/main/scala/xiangshan/cache/prefetch/Prefetcher.scala +++ b/src/main/scala/xiangshan/cache/prefetch/Prefetcher.scala @@ -22,6 +22,7 @@ import chisel3.util._ import xiangshan._ import xiangshan.cache._ import utils._ +import utility._ trait HasPrefetchParameters extends HasXSParameter { val bopParams = p(BOPParamsKey) diff --git a/src/main/scala/xiangshan/cache/prefetch/StreamPrefetch.scala b/src/main/scala/xiangshan/cache/prefetch/StreamPrefetch.scala index 57f6c98a5..7c6c742af 100644 --- a/src/main/scala/xiangshan/cache/prefetch/StreamPrefetch.scala +++ b/src/main/scala/xiangshan/cache/prefetch/StreamPrefetch.scala @@ -23,6 +23,7 @@ import xiangshan._ import xiangshan.cache._ import xiangshan.cache.mmu.{HasTlbConst} import utils._ +import utility._ case object StreamParamsKey extends Field[StreamPrefetchParameters] diff --git a/src/main/scala/xiangshan/frontend/BPU.scala b/src/main/scala/xiangshan/frontend/BPU.scala index 930f445b5..4775a149c 100644 --- a/src/main/scala/xiangshan/frontend/BPU.scala +++ b/src/main/scala/xiangshan/frontend/BPU.scala @@ -22,6 +22,7 @@ import chisel3.experimental.chiselName import chisel3.util._ import xiangshan._ import utils._ +import utility._ import scala.math.min diff --git a/src/main/scala/xiangshan/frontend/Bim.scala b/src/main/scala/xiangshan/frontend/Bim.scala index d63bac29d..696b01568 100644 --- a/src/main/scala/xiangshan/frontend/Bim.scala +++ b/src/main/scala/xiangshan/frontend/Bim.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ import chisel3.experimental.chiselName trait BimParams extends HasXSParameter { diff --git a/src/main/scala/xiangshan/frontend/Composer.scala b/src/main/scala/xiangshan/frontend/Composer.scala index 5d0acee3a..317f6d8e0 100644 --- a/src/main/scala/xiangshan/frontend/Composer.scala +++ b/src/main/scala/xiangshan/frontend/Composer.scala @@ -22,6 +22,7 @@ import chisel3.util._ import chisel3.experimental.chiselName import xiangshan._ import utils._ +import utility._ @chiselName class Composer(implicit p: Parameters) extends BasePredictor with HasBPUConst with HasPerfEvents { diff --git a/src/main/scala/xiangshan/frontend/FTB.scala b/src/main/scala/xiangshan/frontend/FTB.scala index 27cb470c8..89932b75d 100644 --- a/src/main/scala/xiangshan/frontend/FTB.scala +++ b/src/main/scala/xiangshan/frontend/FTB.scala @@ -22,6 +22,7 @@ import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage} import chisel3.util._ import xiangshan._ import utils._ +import utility._ import chisel3.experimental.chiselName import scala.math.min diff --git a/src/main/scala/xiangshan/frontend/FauFTB.scala b/src/main/scala/xiangshan/frontend/FauFTB.scala index b9a199f8f..f8058833e 100644 --- a/src/main/scala/xiangshan/frontend/FauFTB.scala +++ b/src/main/scala/xiangshan/frontend/FauFTB.scala @@ -20,6 +20,7 @@ import chipsalliance.rocketchip.config.Parameters import chisel3._ import chisel3.util._ import utils._ +import utility._ import xiangshan._ import chisel3.experimental.chiselName import scala.{Tuple2 => &} diff --git a/src/main/scala/xiangshan/frontend/Frontend.scala b/src/main/scala/xiangshan/frontend/Frontend.scala index a72d54dab..affbc52b4 100644 --- a/src/main/scala/xiangshan/frontend/Frontend.scala +++ b/src/main/scala/xiangshan/frontend/Frontend.scala @@ -20,6 +20,7 @@ import chisel3._ import chisel3.util._ import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} import utils._ +import utility._ import xiangshan._ import xiangshan.backend.fu.{PFEvent, PMP, PMPChecker,PMPReqBundle} import xiangshan.cache.mmu._ diff --git a/src/main/scala/xiangshan/frontend/FrontendBundle.scala b/src/main/scala/xiangshan/frontend/FrontendBundle.scala index b3b550077..f3c6deb86 100644 --- a/src/main/scala/xiangshan/frontend/FrontendBundle.scala +++ b/src/main/scala/xiangshan/frontend/FrontendBundle.scala @@ -22,6 +22,7 @@ import chisel3.experimental.chiselName import xiangshan._ import xiangshan.frontend.icache._ import utils._ +import utility._ import scala.math._ @chiselName diff --git a/src/main/scala/xiangshan/frontend/IFU.scala b/src/main/scala/xiangshan/frontend/IFU.scala index 366426046..0733daa28 100644 --- a/src/main/scala/xiangshan/frontend/IFU.scala +++ b/src/main/scala/xiangshan/frontend/IFU.scala @@ -24,8 +24,9 @@ import xiangshan._ import xiangshan.cache.mmu._ import xiangshan.frontend.icache._ import utils._ +import utility._ import xiangshan.backend.fu.{PMPReqBundle, PMPRespBundle} -import huancun.utils.ChiselDB +import utility.ChiselDB trait HasInstrMMIOConst extends HasXSParameter with HasIFUConst{ def mmioBusWidth = 64 diff --git a/src/main/scala/xiangshan/frontend/ITTAGE.scala b/src/main/scala/xiangshan/frontend/ITTAGE.scala index 5033beeaa..02494b4d0 100644 --- a/src/main/scala/xiangshan/frontend/ITTAGE.scala +++ b/src/main/scala/xiangshan/frontend/ITTAGE.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ import chisel3.experimental.chiselName import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage} import firrtl.stage.RunFirrtlTransformAnnotation diff --git a/src/main/scala/xiangshan/frontend/Ibuffer.scala b/src/main/scala/xiangshan/frontend/Ibuffer.scala index e9122363f..fa23ddee1 100644 --- a/src/main/scala/xiangshan/frontend/Ibuffer.scala +++ b/src/main/scala/xiangshan/frontend/Ibuffer.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ import xiangshan.ExceptionNO._ class IbufPtr(implicit p: Parameters) extends CircularQueuePtr[IbufPtr]( diff --git a/src/main/scala/xiangshan/frontend/NewFtq.scala b/src/main/scala/xiangshan/frontend/NewFtq.scala index baee0020d..9d19e809d 100644 --- a/src/main/scala/xiangshan/frontend/NewFtq.scala +++ b/src/main/scala/xiangshan/frontend/NewFtq.scala @@ -20,11 +20,12 @@ import chipsalliance.rocketchip.config.Parameters import chisel3._ import chisel3.util._ import utils._ +import utility._ import xiangshan._ import xiangshan.frontend.icache._ import xiangshan.backend.CtrlToFtqIO import xiangshan.backend.decode.ImmUnion -import huancun.utils.ChiselDB +import utility.ChiselDB class FtqDebugBundle extends Bundle { val pc = UInt(39.W) diff --git a/src/main/scala/xiangshan/frontend/PreDecode.scala b/src/main/scala/xiangshan/frontend/PreDecode.scala index b7d259e1e..0db44106d 100644 --- a/src/main/scala/xiangshan/frontend/PreDecode.scala +++ b/src/main/scala/xiangshan/frontend/PreDecode.scala @@ -21,6 +21,7 @@ import freechips.rocketchip.rocket.{RVCDecoder, ExpandedInstruction} import chisel3.{util, _} import chisel3.util._ import utils._ +import utility._ import xiangshan._ import xiangshan.frontend.icache._ import xiangshan.backend.decode.isa.predecode.PreDecodeInst diff --git a/src/main/scala/xiangshan/frontend/RAS.scala b/src/main/scala/xiangshan/frontend/RAS.scala index 15234a2b1..66a84084a 100644 --- a/src/main/scala/xiangshan/frontend/RAS.scala +++ b/src/main/scala/xiangshan/frontend/RAS.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.experimental.chiselName import chisel3.util._ import utils._ +import utility._ import xiangshan._ class RASEntry()(implicit p: Parameters) extends XSBundle { diff --git a/src/main/scala/xiangshan/frontend/SC.scala b/src/main/scala/xiangshan/frontend/SC.scala index 1bda091c9..a15b2f33e 100644 --- a/src/main/scala/xiangshan/frontend/SC.scala +++ b/src/main/scala/xiangshan/frontend/SC.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ import chisel3.experimental.chiselName import scala.math.min diff --git a/src/main/scala/xiangshan/frontend/Tage.scala b/src/main/scala/xiangshan/frontend/Tage.scala index e5acd992a..bd39be7b0 100644 --- a/src/main/scala/xiangshan/frontend/Tage.scala +++ b/src/main/scala/xiangshan/frontend/Tage.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ import chisel3.experimental.chiselName import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage} import firrtl.stage.RunFirrtlTransformAnnotation diff --git a/src/main/scala/xiangshan/frontend/WrBypass.scala b/src/main/scala/xiangshan/frontend/WrBypass.scala index 6b73cdb8a..6dcac36ab 100644 --- a/src/main/scala/xiangshan/frontend/WrBypass.scala +++ b/src/main/scala/xiangshan/frontend/WrBypass.scala @@ -20,6 +20,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ import chisel3.experimental.chiselName import xiangshan.cache.mmu.CAMTemplate diff --git a/src/main/scala/xiangshan/frontend/icache/ICache.scala b/src/main/scala/xiangshan/frontend/icache/ICache.scala index e932c955f..c12fe5497 100644 --- a/src/main/scala/xiangshan/frontend/icache/ICache.scala +++ b/src/main/scala/xiangshan/frontend/icache/ICache.scala @@ -26,7 +26,8 @@ import huancun.{AliasField, DirtyField, PreferCacheField, PrefetchField} import xiangshan._ import xiangshan.frontend._ import xiangshan.cache._ -import utils.{SRAMTemplate, _} +import utils._ +import utility._ import xiangshan.backend.fu.PMPReqBundle import xiangshan.cache.mmu.{TlbRequestIO, TlbReq} diff --git a/src/main/scala/xiangshan/frontend/icache/ICacheBundle.scala b/src/main/scala/xiangshan/frontend/icache/ICacheBundle.scala index 25c881fd8..cee51b6b0 100644 --- a/src/main/scala/xiangshan/frontend/icache/ICacheBundle.scala +++ b/src/main/scala/xiangshan/frontend/icache/ICacheBundle.scala @@ -22,6 +22,7 @@ import chisel3.util._ import freechips.rocketchip.tilelink.{ClientMetadata, TLPermissions} import xiangshan._ import utils._ +import utility._ class ICacheReadBundle(implicit p: Parameters) extends ICacheBundle { diff --git a/src/main/scala/xiangshan/frontend/icache/ICacheMainPipe.scala b/src/main/scala/xiangshan/frontend/icache/ICacheMainPipe.scala index 0be172899..61f04a93e 100644 --- a/src/main/scala/xiangshan/frontend/icache/ICacheMainPipe.scala +++ b/src/main/scala/xiangshan/frontend/icache/ICacheMainPipe.scala @@ -23,6 +23,7 @@ import freechips.rocketchip.tilelink.ClientStates import xiangshan._ import xiangshan.cache.mmu._ import utils._ +import utility._ import xiangshan.backend.fu.{PMPReqBundle, PMPRespBundle} import xiangshan.frontend.{FtqICacheInfo, FtqToICacheRequestBundle} diff --git a/src/main/scala/xiangshan/frontend/icache/ICacheMissUnit.scala b/src/main/scala/xiangshan/frontend/icache/ICacheMissUnit.scala index 87e608c7b..a46ad4fad 100644 --- a/src/main/scala/xiangshan/frontend/icache/ICacheMissUnit.scala +++ b/src/main/scala/xiangshan/frontend/icache/ICacheMissUnit.scala @@ -27,6 +27,7 @@ import xiangshan._ import huancun.{AliasKey, DirtyKey} import xiangshan.cache._ import utils._ +import utility._ import difftest._ diff --git a/src/main/scala/xiangshan/frontend/icache/IPrefetch.scala b/src/main/scala/xiangshan/frontend/icache/IPrefetch.scala index 2e80a507d..418d568b6 100644 --- a/src/main/scala/xiangshan/frontend/icache/IPrefetch.scala +++ b/src/main/scala/xiangshan/frontend/icache/IPrefetch.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import freechips.rocketchip.tilelink._ import utils._ +import utility._ import xiangshan.cache.mmu._ import xiangshan.frontend._ import xiangshan.backend.fu.{PMPReqBundle, PMPRespBundle} diff --git a/src/main/scala/xiangshan/frontend/icache/InstrUncache.scala b/src/main/scala/xiangshan/frontend/icache/InstrUncache.scala index 9c907fac1..8ceb8bb78 100644 --- a/src/main/scala/xiangshan/frontend/icache/InstrUncache.scala +++ b/src/main/scala/xiangshan/frontend/icache/InstrUncache.scala @@ -19,6 +19,7 @@ package xiangshan.frontend.icache import chisel3._ import chisel3.util._ import utils._ +import utility._ import chipsalliance.rocketchip.config.Parameters import freechips.rocketchip.diplomacy.{IdRange, LazyModule, LazyModuleImp, TransferSizes} import freechips.rocketchip.tilelink.{TLArbiter, TLBundleA, TLBundleD, TLClientNode, TLEdgeOut, TLMasterParameters, TLMasterPortParameters} diff --git a/src/main/scala/xiangshan/frontend/icache/ReleaseUnit.scala b/src/main/scala/xiangshan/frontend/icache/ReleaseUnit.scala index 730745dfd..dc1956749 100644 --- a/src/main/scala/xiangshan/frontend/icache/ReleaseUnit.scala +++ b/src/main/scala/xiangshan/frontend/icache/ReleaseUnit.scala @@ -22,6 +22,7 @@ import chisel3.util._ import freechips.rocketchip.tilelink.{ClientMetadata, ClientStates, TLArbiter, TLBundleC, TLBundleD, TLEdgeOut, TLPermissions} import xiangshan._ import utils._ +import utility._ import huancun.{DirtyField, DirtyKey} class ReleaseReq(implicit p: Parameters) extends ICacheBundle{ diff --git a/src/main/scala/xiangshan/frontend/icache/ReplacePipe.scala b/src/main/scala/xiangshan/frontend/icache/ReplacePipe.scala index 7d097406b..b423c1460 100644 --- a/src/main/scala/xiangshan/frontend/icache/ReplacePipe.scala +++ b/src/main/scala/xiangshan/frontend/icache/ReplacePipe.scala @@ -22,6 +22,7 @@ import chisel3.util._ import freechips.rocketchip.tilelink.{ClientMetadata, ClientStates, TLPermissions} import xiangshan._ import utils._ +import utility._ class ReplacePipeReq(implicit p: Parameters) extends ICacheBundle { diff --git a/src/main/scala/xiangshan/mem/MaskedDataModule.scala b/src/main/scala/xiangshan/mem/MaskedDataModule.scala index a45ff9853..f48c4ec4b 100644 --- a/src/main/scala/xiangshan/mem/MaskedDataModule.scala +++ b/src/main/scala/xiangshan/mem/MaskedDataModule.scala @@ -20,6 +20,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ import xiangshan.cache._ class MaskedSyncDataModuleTemplate[T <: Data]( diff --git a/src/main/scala/xiangshan/mem/MemCommon.scala b/src/main/scala/xiangshan/mem/MemCommon.scala index e04c3b4c6..d97ca4414 100644 --- a/src/main/scala/xiangshan/mem/MemCommon.scala +++ b/src/main/scala/xiangshan/mem/MemCommon.scala @@ -22,6 +22,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ import xiangshan.backend.rob.RobPtr import xiangshan.cache._ import xiangshan.backend.fu.FenceToSbuffer @@ -48,7 +49,7 @@ object genWdata { } } -class LsPipelineBundle(implicit p: Parameters) extends XSBundleWithMicroOp { +class LsPipelineBundle(implicit p: Parameters) extends XSBundleWithMicroOp with HasDCacheParameters{ val vaddr = UInt(VAddrBits.W) val paddr = UInt(PAddrBits.W) // val func = UInt(6.W) @@ -74,6 +75,11 @@ class LsPipelineBundle(implicit p: Parameters) extends XSBundleWithMicroOp { // For load replay val isLoadReplay = Bool() + + // For dcache miss load + val mshrid = UInt(log2Up(cfg.nMissEntries).W) + + val forward_tlDchannel = Bool() } class LqWriteBundle(implicit p: Parameters) extends LsPipelineBundle { @@ -99,6 +105,8 @@ class LqWriteBundle(implicit p: Parameters) extends LsPipelineBundle { isSoftPrefetch := input.isSoftPrefetch isFirstIssue := input.isFirstIssue isLoadReplay := input.isLoadReplay + mshrid := input.mshrid + forward_tlDchannel := input.forward_tlDchannel lq_data_wen_dup := DontCare } @@ -193,9 +201,22 @@ class LoadDataFromDcacheBundle(implicit p: Parameters) extends DCacheBundle { val uop = new MicroOp // for data selection, only fwen and fuOpType are used val addrOffset = UInt(3.W) // for data selection + // forward tilelink D channel + val forward_D = Input(Bool()) + val forwardData_D = Input(Vec(8, UInt(8.W))) + + // forward mshr data + val forward_mshr = Input(Bool()) + val forwardData_mshr = Input(Vec(8, UInt(8.W))) + + val forward_result_valid = Input(Bool()) + // val dcacheData = UInt(64.W) def dcacheData(): UInt = { - Mux1H(bank_oh, bankedDcacheData) + val dcache_data = Mux1H(bank_oh, bankedDcacheData) + val use_D = forward_D && forward_result_valid + val use_mshr = forward_mshr && forward_result_valid + Mux(use_D, forwardData_D.asUInt, Mux(use_mshr, forwardData_mshr.asUInt, dcache_data)) } def mergedData(): UInt = { diff --git a/src/main/scala/xiangshan/mem/lsqueue/LSQWrapper.scala b/src/main/scala/xiangshan/mem/lsqueue/LSQWrapper.scala index 4847cd73d..bfa520534 100644 --- a/src/main/scala/xiangshan/mem/lsqueue/LSQWrapper.scala +++ b/src/main/scala/xiangshan/mem/lsqueue/LSQWrapper.scala @@ -20,6 +20,7 @@ import chipsalliance.rocketchip.config.Parameters import chisel3._ import chisel3.util._ import utils._ +import utility._ import xiangshan._ import xiangshan.cache._ import xiangshan.cache.{DCacheWordIO, DCacheLineIO, MemoryOpConstants} diff --git a/src/main/scala/xiangshan/mem/lsqueue/LoadQueue.scala b/src/main/scala/xiangshan/mem/lsqueue/LoadQueue.scala index 78ce75178..b149dbdce 100644 --- a/src/main/scala/xiangshan/mem/lsqueue/LoadQueue.scala +++ b/src/main/scala/xiangshan/mem/lsqueue/LoadQueue.scala @@ -20,6 +20,7 @@ import chipsalliance.rocketchip.config.Parameters import chisel3._ import chisel3.util._ import utils._ +import utility._ import xiangshan._ import xiangshan.backend.fu.fpu.FPU import xiangshan.backend.rob.RobLsqIO @@ -135,10 +136,10 @@ class LoadQueue(implicit p: Parameters) extends XSModule val uop = Reg(Vec(LoadQueueSize, new MicroOp)) // val data = Reg(Vec(LoadQueueSize, new LsRobEntry)) - val dataModule = Module(new LoadQueueDataWrapper(LoadQueueSize, wbNumRead = LoadPipelineWidth, wbNumWrite = LoadPipelineWidth)) + val dataModule = Module(new LoadQueueDataWrapper(LoadQueueSize, wbNumWrite = LoadPipelineWidth)) dataModule.io := DontCare - // vaddrModule's read port 0 for exception addr, port {1, 2} for debug module, port {3, 4} for load replay - val vaddrModule = Module(new SyncDataModuleTemplate(UInt(VAddrBits.W), LoadQueueSize, numRead = LoadPipelineWidth + 1 + 2, numWrite = LoadPipelineWidth)) + // vaddrModule's read port 0 for exception addr, port 1 for uncache vaddr read, port {2, 3} for load replay + val vaddrModule = Module(new SyncDataModuleTemplate(UInt(VAddrBits.W), LoadQueueSize, numRead = 1 + 1 + LoadPipelineWidth, numWrite = LoadPipelineWidth)) vaddrModule.io := DontCare val vaddrTriggerResultModule = Module(new SyncDataModuleTemplate(Vec(3, Bool()), LoadQueueSize, numRead = LoadPipelineWidth, numWrite = LoadPipelineWidth)) vaddrTriggerResultModule.io := DontCare @@ -162,6 +163,7 @@ class LoadQueue(implicit p: Parameters) extends XSModule val cache_bank_no_conflict = RegInit(VecInit(List.fill(LoadQueueSize)(true.B))) val cache_no_replay = RegInit(VecInit(List.fill(LoadQueueSize)(true.B))) val forward_data_valid = RegInit(VecInit(List.fill(LoadQueueSize)(true.B))) + val cache_hited = RegInit(VecInit(List.fill(LoadQueueSize)(true.B))) /** @@ -172,11 +174,13 @@ class LoadQueue(implicit p: Parameters) extends XSModule // ptrs to control which cycle to choose val block_ptr_tlb = RegInit(VecInit(List.fill(LoadQueueSize)(0.U(2.W)))) + val block_ptr_cache = RegInit(VecInit(List.fill(LoadQueueSize)(0.U(2.W)))) val block_ptr_others = RegInit(VecInit(List.fill(LoadQueueSize)(0.U(2.W)))) // specific cycles to block val block_cycles_tlb = Reg(Vec(4, UInt(ReSelectLen.W))) block_cycles_tlb := io.tlbReplayDelayCycleCtrl + val block_cycles_cache = RegInit(VecInit(Seq(11.U(ReSelectLen.W), 0.U(ReSelectLen.W), 31.U(ReSelectLen.W), 0.U(ReSelectLen.W)))) val block_cycles_others = RegInit(VecInit(Seq(0.U(ReSelectLen.W), 0.U(ReSelectLen.W), 0.U(ReSelectLen.W), 0.U(ReSelectLen.W)))) val sel_blocked = RegInit(VecInit(List.fill(LoadQueueSize)(false.B))) @@ -185,19 +189,39 @@ class LoadQueue(implicit p: Parameters) extends XSModule val block_sq_idx = RegInit(VecInit(List.fill(LoadQueueSize)(0.U((log2Ceil(StoreQueueSize).W))))) val block_by_data_forward_fail = RegInit(VecInit(List.fill(LoadQueueSize)(false.B))) + // dcache miss block + val miss_mshr_id = RegInit(VecInit(List.fill(LoadQueueSize)(0.U((log2Up(cfg.nMissEntries).W))))) + val block_by_cache_miss = RegInit(VecInit(List.fill(LoadQueueSize)(false.B))) + + val true_cache_miss_replay = WireInit(VecInit(List.fill(LoadQueueSize)(false.B))) + (0 until LoadQueueSize).map{i => { + true_cache_miss_replay(i) := tlb_hited(i) && ld_ld_check_ok(i) && st_ld_check_ok(i) && cache_bank_no_conflict(i) && + cache_no_replay(i) && forward_data_valid(i) && !cache_hited(i) + }} + val creditUpdate = WireInit(VecInit(List.fill(LoadQueueSize)(0.U(ReSelectLen.W)))) credit := creditUpdate (0 until LoadQueueSize).map(i => { creditUpdate(i) := Mux(credit(i) > 0.U(ReSelectLen.W), credit(i) - 1.U(ReSelectLen.W), credit(i)) - sel_blocked(i) := creditUpdate(i) =/= 0.U(ReSelectLen.W) || credit(i) =/= 0.U(ReSelectLen.W) + sel_blocked(i) := creditUpdate(i) =/= 0.U(ReSelectLen.W) }) (0 until LoadQueueSize).map(i => { block_by_data_forward_fail(i) := Mux(block_by_data_forward_fail(i) === true.B && io.storeDataValidVec(block_sq_idx(i)) === true.B , false.B, block_by_data_forward_fail(i)) }) + (0 until LoadQueueSize).map(i => { + block_by_cache_miss(i) := Mux(block_by_cache_miss(i) === true.B && io.refill.valid && io.refill.bits.id === miss_mshr_id(i), false.B, block_by_cache_miss(i)) + when(creditUpdate(i) === 0.U && block_by_cache_miss(i) === true.B) { + block_by_cache_miss(i) := false.B + } + when(block_by_cache_miss(i) === true.B && io.refill.valid && io.refill.bits.id === miss_mshr_id(i)) { + creditUpdate(i) := 0.U + } + }) + val debug_mmio = Reg(Vec(LoadQueueSize, Bool())) // mmio: inst is an mmio inst val debug_paddr = Reg(Vec(LoadQueueSize, UInt(PAddrBits.W))) // mmio: inst is an mmio inst @@ -254,15 +278,18 @@ class LoadQueue(implicit p: Parameters) extends XSModule cache_bank_no_conflict(index) := true.B cache_no_replay(index) := true.B forward_data_valid(index) := true.B + cache_hited(index) := true.B /** * used for delaying load(block-ptr to control how many cycles to block) */ credit(index) := 0.U(ReSelectLen.W) block_ptr_tlb(index) := 0.U(2.W) + block_ptr_cache(index) := 0.U(2.W) block_ptr_others(index) := 0.U(2.W) block_by_data_forward_fail(index) := false.B + block_by_cache_miss(index) := false.B XSError(!io.enq.canAccept || !io.enq.sqCanAccept, s"must accept $i\n") XSError(index =/= lqIdx.value, s"must be the same entry $i\n") @@ -286,8 +313,8 @@ class LoadQueue(implicit p: Parameters) extends XSModule val loadReplaySelV = Wire(Vec(LoadPipelineWidth, Bool())) // index selected in last cycle is valid val loadReplaySelVec = VecInit((0 until LoadQueueSize).map(i => { - val blocked = s1_block_load_mask(i) || s2_block_load_mask(i) || sel_blocked(i) || block_by_data_forward_fail(i) - allocated(i) && (!tlb_hited(i) || !ld_ld_check_ok(i) || !st_ld_check_ok(i) || !cache_bank_no_conflict(i) || !cache_no_replay(i) || !forward_data_valid(i)) && !blocked + val blocked = s1_block_load_mask(i) || s2_block_load_mask(i) || sel_blocked(i) || block_by_data_forward_fail(i) || block_by_cache_miss(i) + allocated(i) && (!tlb_hited(i) || !ld_ld_check_ok(i) || !st_ld_check_ok(i) || !cache_bank_no_conflict(i) || !cache_no_replay(i) || !forward_data_valid(i) || !cache_hited(i)) && !blocked })).asUInt() // use uint instead vec to reduce verilog lines val remReplayDeqMask = Seq.tabulate(LoadPipelineWidth)(getRemBits(deqMask)(_)) @@ -318,7 +345,7 @@ class LoadQueue(implicit p: Parameters) extends XSModule }) (0 until LoadPipelineWidth).map(i => { - vaddrModule.io.raddr(LoadPipelineWidth + 1 + i) := loadReplaySelGen(i) + vaddrModule.io.raddr(LoadPipelineWidth + i) := loadReplaySelGen(i) }) (0 until LoadPipelineWidth).map(i => { @@ -346,10 +373,12 @@ class LoadQueue(implicit p: Parameters) extends XSModule io.loadOut(i).bits := DontCare io.loadOut(i).bits.uop := uop(replayIdx) - io.loadOut(i).bits.vaddr := vaddrModule.io.rdata(LoadPipelineWidth + 1 + i) - io.loadOut(i).bits.mask := genWmask(vaddrModule.io.rdata(LoadPipelineWidth + 1 + i), uop(replayIdx).ctrl.fuOpType(1,0)) + io.loadOut(i).bits.vaddr := vaddrModule.io.rdata(LoadPipelineWidth + i) + io.loadOut(i).bits.mask := genWmask(vaddrModule.io.rdata(LoadPipelineWidth + i), uop(replayIdx).ctrl.fuOpType(1,0)) io.loadOut(i).bits.isFirstIssue := false.B io.loadOut(i).bits.isLoadReplay := true.B + io.loadOut(i).bits.mshrid := miss_mshr_id(replayIdx) + io.loadOut(i).bits.forward_tlDchannel := true_cache_miss_replay(replayIdx) when(io.loadOut(i).fire) { replayRemFire(i) := true.B @@ -401,11 +430,11 @@ class LoadQueue(implicit p: Parameters) extends XSModule io.loadIn(i).bits.mmio )} if(EnableFastForward){ - datavalid(loadWbIndex) := (!io.loadIn(i).bits.miss || io.s2_load_data_forwarded(i)) && + datavalid(loadWbIndex) := !io.loadIn(i).bits.miss && !io.loadIn(i).bits.mmio && // mmio data is not valid until we finished uncache access !io.s2_dcache_require_replay(i) // do not writeback if that inst will be resend from rs } else { - datavalid(loadWbIndex) := (!io.loadIn(i).bits.miss || io.s2_load_data_forwarded(i)) && + datavalid(loadWbIndex) := !io.loadIn(i).bits.miss && !io.loadIn(i).bits.mmio // mmio data is not valid until we finished uncache access } writebacked(loadWbIndex) := !io.loadIn(i).bits.miss && !io.loadIn(i).bits.mmio @@ -450,12 +479,7 @@ class LoadQueue(implicit p: Parameters) extends XSModule // dirty code to reduce load_s2.valid fanout when(io.loadIn(i).bits.lq_data_wen_dup(0)){ - val loadWbData = Wire(new LQDataEntry) - loadWbData.paddr := io.loadIn(i).bits.paddr - loadWbData.mask := io.loadIn(i).bits.mask - loadWbData.data := io.loadIn(i).bits.forwardData.asUInt // fwd data - loadWbData.fwdMask := io.loadIn(i).bits.forwardMask - dataModule.io.wbWrite(i, loadWbIndex, loadWbData) + dataModule.io.wbWrite(i, loadWbIndex, io.loadIn(i).bits.mask) dataModule.io.wb.wen(i) := true.B } // dirty code for load instr @@ -516,33 +540,47 @@ class LoadQueue(implicit p: Parameters) extends XSModule when(io.replaySlow(i).valid){ val idx = io.replaySlow(i).ld_idx - val needreplay = !io.replaySlow(i).tlb_hited || !io.replaySlow(i).st_ld_check_ok || !io.replaySlow(i).cache_no_replay || !io.replaySlow(i).forward_data_valid + val needreplay = !io.replaySlow(i).tlb_hited || !io.replaySlow(i).st_ld_check_ok || !io.replaySlow(i).cache_no_replay || !io.replaySlow(i).forward_data_valid || !io.replaySlow(i).cache_hited tlb_hited(idx) := io.replaySlow(i).tlb_hited st_ld_check_ok(idx) := io.replaySlow(i).st_ld_check_ok cache_no_replay(idx) := io.replaySlow(i).cache_no_replay forward_data_valid(idx) := io.replaySlow(i).forward_data_valid + cache_hited(idx) := io.replaySlow(i).cache_hited val invalid_sq_idx = io.replaySlow(i).data_invalid_sq_idx when(needreplay) { + // update credit and ptr + val data_in_last_beat = io.replaySlow(i).data_in_last_beat creditUpdate(idx) := Mux( !io.replaySlow(i).tlb_hited, block_cycles_tlb(block_ptr_tlb(idx)), - Mux(!io.replaySlow(i).cache_no_replay || !io.replaySlow(i).st_ld_check_ok, block_cycles_others(block_ptr_others(idx)), 0.U)) + Mux(!io.replaySlow(i).cache_hited, block_cycles_cache(block_ptr_cache(idx)) + data_in_last_beat, + Mux(!io.replaySlow(i).cache_no_replay || !io.replaySlow(i).st_ld_check_ok, block_cycles_others(block_ptr_others(idx)), 0.U))) when(!io.replaySlow(i).tlb_hited) { block_ptr_tlb(idx) := Mux(block_ptr_tlb(idx) === 3.U(2.W), block_ptr_tlb(idx), block_ptr_tlb(idx) + 1.U(2.W)) + }.elsewhen(!io.replaySlow(i).cache_hited) { + block_ptr_cache(idx) := Mux(block_ptr_cache(idx) === 3.U(2.W), block_ptr_cache(idx), block_ptr_cache(idx) + 1.U(2.W)) }.elsewhen(!io.replaySlow(i).cache_no_replay || !io.replaySlow(i).st_ld_check_ok) { block_ptr_others(idx) := Mux(block_ptr_others(idx) === 3.U(2.W), block_ptr_others(idx), block_ptr_others(idx) + 1.U(2.W)) } - } + } + // special case: data forward fail block_by_data_forward_fail(idx) := false.B - when(!io.replaySlow(i).forward_data_valid) { + when(!io.replaySlow(i).forward_data_valid && io.replaySlow(i).tlb_hited) { when(!io.storeDataValidVec(invalid_sq_idx)) { block_by_data_forward_fail(idx) := true.B block_sq_idx(idx) := invalid_sq_idx } } + + // special case: cache miss + miss_mshr_id(idx) := io.replaySlow(i).miss_mshr_id + block_by_cache_miss(idx) := io.replaySlow(i).tlb_hited && io.replaySlow(i).cache_no_replay && io.replaySlow(i).st_ld_check_ok && // this load tlb hit and no cache replay + !io.replaySlow(i).cache_hited && !io.replaySlow(i).can_forward_full_data && // cache miss + !(io.refill.valid && io.refill.bits.id === io.replaySlow(i).miss_mshr_id) && // no refill in this cycle + creditUpdate(idx) =/= 0.U // credit is not zero } } @@ -551,31 +589,13 @@ class LoadQueue(implicit p: Parameters) extends XSModule XSDebug("miss resp: paddr:0x%x data %x\n", io.refill.bits.addr, io.refill.bits.data) } - // Refill 64 bit in a cycle - // Refill data comes back from io.dcache.resp - dataModule.io.refill.valid := io.refill.valid - dataModule.io.refill.paddr := io.refill.bits.addr - dataModule.io.refill.data := io.refill.bits.data + // NOTE: we don't refill data from dcache now! val s2_dcache_require_replay = WireInit(VecInit((0 until LoadPipelineWidth).map(i =>{ RegNext(io.loadIn(i).fire()) && RegNext(io.s2_dcache_require_replay(i)) }))) dontTouch(s2_dcache_require_replay) - (0 until LoadQueueSize).map(i => { - dataModule.io.refill.refillMask(i) := allocated(i) && miss(i) - when(dataModule.io.refill.valid && dataModule.io.refill.refillMask(i) && dataModule.io.refill.matchMask(i)) { - datavalid(i) := true.B - miss(i) := false.B - when(!s2_dcache_require_replay.asUInt.orR){ - refilling(i) := true.B - } - when(io.refill.bits.error) { - error(i) := true.B - } - } - }) - for (i <- 0 until LoadPipelineWidth) { val loadWbIndex = io.loadIn(i).bits.uop.lqIdx.value val lastCycleLoadWbIndex = RegNext(loadWbIndex) @@ -602,116 +622,6 @@ class LoadQueue(implicit p: Parameters) extends XSModule } } - - // Writeback up to 2 missed load insts to CDB - // - // Pick 2 missed load (data refilled), write them back to cdb - // 2 refilled load will be selected from even/odd entry, separately - - // Stage 0 - // Generate writeback indexes - - def getRemBits(input: UInt)(rem: Int): UInt = { - VecInit((0 until LoadQueueSize / LoadPipelineWidth).map(i => { input(LoadPipelineWidth * i + rem) })).asUInt - } - - val loadWbSel = Wire(Vec(LoadPipelineWidth, UInt(log2Up(LoadQueueSize).W))) // index selected last cycle - val loadWbSelV = Wire(Vec(LoadPipelineWidth, Bool())) // index selected in last cycle is valid - - val loadWbSelVec = VecInit((0 until LoadQueueSize).map(i => { - // allocated(i) && !writebacked(i) && (datavalid(i) || refilling(i)) - allocated(i) && !writebacked(i) && datavalid(i) // query refilling will cause bad timing - })).asUInt() // use uint instead vec to reduce verilog lines - - val remDeqMask = Seq.tabulate(LoadPipelineWidth)(getRemBits(deqMask)(_)) - - // generate lastCycleSelect mask - val remFireMask = Seq.tabulate(LoadPipelineWidth)(rem => getRemBits(UIntToOH(loadWbSel(rem)))(rem)) - // generate real select vec - def toVec(a: UInt): Vec[Bool] = { - VecInit(a.asBools) - } - val loadRemSelVecFire = Seq.tabulate(LoadPipelineWidth)(rem => getRemBits(loadWbSelVec)(rem) & ~remFireMask(rem)) - val loadRemSelVecNotFire = Seq.tabulate(LoadPipelineWidth)(getRemBits(loadWbSelVec)(_)) - val loadRemSel = Seq.tabulate(LoadPipelineWidth)(rem => Mux( - io.ldout(rem).fire(), - getFirstOne(toVec(loadRemSelVecFire(rem)), remDeqMask(rem)), - getFirstOne(toVec(loadRemSelVecNotFire(rem)), remDeqMask(rem)) - )) - - - val loadWbSelGen = Wire(Vec(LoadPipelineWidth, UInt(log2Up(LoadQueueSize).W))) - val loadWbSelVGen = Wire(Vec(LoadPipelineWidth, Bool())) - (0 until LoadPipelineWidth).foreach(index => { - loadWbSelGen(index) := ( - if (LoadPipelineWidth > 1) Cat(loadRemSel(index), index.U(log2Ceil(LoadPipelineWidth).W)) - else loadRemSel(index) - ) - loadWbSelVGen(index) := Mux(io.ldout(index).fire, loadRemSelVecFire(index).asUInt.orR, loadRemSelVecNotFire(index).asUInt.orR) - }) - - (0 until LoadPipelineWidth).map(i => { - loadWbSel(i) := RegNext(loadWbSelGen(i)) - loadWbSelV(i) := RegNext(loadWbSelVGen(i), init = false.B) - when(io.ldout(i).fire()){ - // Mark them as writebacked, so they will not be selected in the next cycle - writebacked(loadWbSel(i)) := true.B - } - }) - - // Stage 1 - // Use indexes generated in cycle 0 to read data - // writeback data to cdb - (0 until LoadPipelineWidth).map(i => { - // data select - dataModule.io.wb.raddr(i) := loadWbSelGen(i) - val rdata = dataModule.io.wb.rdata(i).data - val seluop = uop(loadWbSel(i)) - val func = seluop.ctrl.fuOpType - val raddr = dataModule.io.wb.rdata(i).paddr - val rdataSel = LookupTree(raddr(2, 0), List( - "b000".U -> rdata(63, 0), - "b001".U -> rdata(63, 8), - "b010".U -> rdata(63, 16), - "b011".U -> rdata(63, 24), - "b100".U -> rdata(63, 32), - "b101".U -> rdata(63, 40), - "b110".U -> rdata(63, 48), - "b111".U -> rdata(63, 56) - )) - val rdataPartialLoad = rdataHelper(seluop, rdataSel) - - // writeback missed int/fp load - // - // Int load writeback will finish (if not blocked) in one cycle - io.ldout(i).bits.uop := seluop - io.ldout(i).bits.uop.lqIdx := loadWbSel(i).asTypeOf(new LqPtr) - io.ldout(i).bits.data := rdataPartialLoad // not used - io.ldout(i).bits.redirectValid := false.B - io.ldout(i).bits.redirect := DontCare - io.ldout(i).bits.debug.isMMIO := debug_mmio(loadWbSel(i)) - io.ldout(i).bits.debug.isPerfCnt := false.B - io.ldout(i).bits.debug.paddr := debug_paddr(loadWbSel(i)) - io.ldout(i).bits.debug.vaddr := vaddrModule.io.rdata(i+1) - io.ldout(i).bits.fflags := DontCare - io.ldout(i).valid := loadWbSelV(i) - - // merged data, uop and offset for data sel in load_s3 - io.ldRawDataOut(i).lqData := dataModule.io.wb.rdata(i).data - io.ldRawDataOut(i).uop := io.ldout(i).bits.uop - io.ldRawDataOut(i).addrOffset := dataModule.io.wb.rdata(i).paddr - - when(io.ldout(i).fire()) { - XSInfo("int load miss write to cbd robidx %d lqidx %d pc 0x%x mmio %x\n", - io.ldout(i).bits.uop.robIdx.asUInt, - io.ldout(i).bits.uop.lqIdx.asUInt, - io.ldout(i).bits.uop.cf.pc, - debug_mmio(loadWbSel(i)) - ) - } - - }) - /** * Load commits * @@ -724,6 +634,14 @@ class LoadQueue(implicit p: Parameters) extends XSModule } }) + def toVec(a: UInt): Vec[Bool] = { + VecInit(a.asBools) + } + + def getRemBits(input: UInt)(rem: Int): UInt = { + VecInit((0 until LoadQueueSize / LoadPipelineWidth).map(i => { input(LoadPipelineWidth * i + rem) })).asUInt + } + def getFirstOne(mask: Vec[Bool], startMask: UInt) = { val length = mask.length val highBits = (0 until length).map(i => mask(i) & ~startMask(i)) @@ -805,7 +723,7 @@ def detectRollback(i: Int) = { dataModule.io.violation(i).mask := io.storeIn(i).bits.mask val addrMaskMatch = RegNext(dataModule.io.violation(i).violationMask) val entryNeedCheck = RegNext(VecInit((0 until LoadQueueSize).map(j => { - allocated(j) && stToEnqPtrMask(j) && (datavalid(j) || miss(j)) + allocated(j) && stToEnqPtrMask(j) && datavalid(j) }))) val lqViolationVec = VecInit((0 until LoadQueueSize).map(j => { addrMaskMatch(j) && entryNeedCheck(j) @@ -1004,13 +922,22 @@ def detectRollback(i: Int) = { } } } + + // used for uncache commit + val uncacheData = RegInit(0.U(XLEN.W)) + val uncacheCommitFired = RegInit(false.B) + + when(uncacheState === s_req) { + uncacheCommitFired := false.B + } + io.uncache.req.valid := uncacheState === s_req dataModule.io.uncache.raddr := deqPtrExtNext.value io.uncache.req.bits.cmd := MemoryOpConstants.M_XRD io.uncache.req.bits.addr := dataModule.io.uncache.rdata.paddr - io.uncache.req.bits.data := dataModule.io.uncache.rdata.data + io.uncache.req.bits.data := DontCare io.uncache.req.bits.mask := dataModule.io.uncache.rdata.mask io.uncache.req.bits.id := RegNext(deqPtrExtNext.value) io.uncache.req.bits.instrtype := DontCare @@ -1031,32 +958,71 @@ def detectRollback(i: Int) = { } // (3) response from uncache channel: mark as datavalid - dataModule.io.uncache.wen := false.B when(io.uncache.resp.fire()){ datavalid(deqPtr) := true.B - dataModule.io.uncacheWrite(deqPtr, io.uncache.resp.bits.data(XLEN-1, 0)) - dataModule.io.uncache.wen := true.B + uncacheData := io.uncache.resp.bits.data(XLEN-1, 0) XSDebug("uncache resp: data %x\n", io.refill.bits.data) } + // writeback mmio load, Note: only use ldout(0) to write back + // + // Int load writeback will finish (if not blocked) in one cycle + io.ldout(0).bits.uop := uop(deqPtr) + io.ldout(0).bits.uop.lqIdx := deqPtr.asTypeOf(new LqPtr) + io.ldout(0).bits.data := DontCare // not used + io.ldout(0).bits.redirectValid := false.B + io.ldout(0).bits.redirect := DontCare + io.ldout(0).bits.debug.isMMIO := true.B + io.ldout(0).bits.debug.isPerfCnt := false.B + io.ldout(0).bits.debug.paddr := debug_paddr(deqPtr) + io.ldout(0).bits.debug.vaddr := vaddrModule.io.rdata(1) + io.ldout(0).bits.fflags := DontCare + + io.ldout(0).valid := (uncacheState === s_wait) && !uncacheCommitFired + + io.ldout(1).bits := DontCare + io.ldout(1).valid := false.B + + // merged data, uop and offset for data sel in load_s3 + io.ldRawDataOut(0).lqData := uncacheData + io.ldRawDataOut(0).uop := io.ldout(0).bits.uop + io.ldRawDataOut(0).addrOffset := dataModule.io.uncache.rdata.paddr + + io.ldRawDataOut(1) := DontCare + + when(io.ldout(0).fire()){ + uncacheCommitFired := true.B + } + + XSPerfAccumulate("uncache_load_write_back", io.ldout(0).fire()) + // Read vaddr for mem exception // no inst will be commited 1 cycle before tval update vaddrModule.io.raddr(0) := (deqPtrExt + commitCount).value io.exceptionAddr.vaddr := vaddrModule.io.rdata(0) - // Read vaddr for debug - (0 until LoadPipelineWidth).map(i => { - vaddrModule.io.raddr(i+1) := loadWbSel(i) - }) + // read vaddr for mmio, and only port {1} is used + vaddrModule.io.raddr(1) := deqPtr (0 until LoadPipelineWidth).map(i => { - vaddrTriggerResultModule.io.raddr(i) := loadWbSelGen(i) - io.trigger(i).lqLoadAddrTriggerHitVec := Mux( - loadWbSelV(i), - vaddrTriggerResultModule.io.rdata(i), - VecInit(Seq.fill(3)(false.B)) - ) + if(i == 0) { + vaddrTriggerResultModule.io.raddr(i) := deqPtr + io.trigger(i).lqLoadAddrTriggerHitVec := Mux( + io.ldout(i).valid, + vaddrTriggerResultModule.io.rdata(i), + VecInit(Seq.fill(3)(false.B)) + ) + }else { + vaddrTriggerResultModule.io.raddr(i) := DontCare + io.trigger(i).lqLoadAddrTriggerHitVec := VecInit(Seq.fill(3)(false.B)) + } + // vaddrTriggerResultModule.io.raddr(i) := loadWbSelGen(i) + // io.trigger(i).lqLoadAddrTriggerHitVec := Mux( + // loadWbSelV(i), + // vaddrTriggerResultModule.io.rdata(i), + // VecInit(Seq.fill(3)(false.B)) + // ) }) // misprediction recovery / exception redirect diff --git a/src/main/scala/xiangshan/mem/lsqueue/LoadQueueData.scala b/src/main/scala/xiangshan/mem/lsqueue/LoadQueueData.scala index 709eea7d3..0acfa4c97 100644 --- a/src/main/scala/xiangshan/mem/lsqueue/LoadQueueData.scala +++ b/src/main/scala/xiangshan/mem/lsqueue/LoadQueueData.scala @@ -20,6 +20,7 @@ import chipsalliance.rocketchip.config.Parameters import chisel3._ import chisel3.util._ import utils._ +import utility._ import xiangshan._ import xiangshan.cache._ import xiangshan.cache.{DCacheWordIO, DCacheLineIO, MemoryOpConstants} @@ -41,10 +42,9 @@ class LQDataEntry(implicit p: Parameters) extends LQDataEntryWoPaddr { // load queue paddr module // -// It supports 3 cam sources: +// It supports 2 cam sources: // * st-ld violation addr cam // * data release addr cam -// * data refill addr cam class LQPaddrModule(numEntries: Int, numRead: Int, numWrite: Int, numWBanks: Int)(implicit p: Parameters) extends XSModule with HasDCacheParameters { val io = IO(new Bundle { // normal read/write ports @@ -59,9 +59,6 @@ class LQPaddrModule(numEntries: Int, numRead: Int, numWrite: Int, numWBanks: Int // release cam: hit if addr is in the same cacheline val releaseMdata = Input(Vec(LoadPipelineWidth, UInt((PAddrBits).W))) val releaseMmask = Output(Vec(LoadPipelineWidth, Vec(numEntries, Bool()))) - // refill cam: hit if addr is in the same cacheline - val refillMdata = Input(UInt((PAddrBits).W)) - val refillMmask = Output(Vec(numEntries, Bool())) }) require(isPow2(numWBanks)) @@ -135,10 +132,6 @@ class LQPaddrModule(numEntries: Int, numRead: Int, numWrite: Int, numWBanks: Int } } - for (j <- 0 until numEntries) { - io.refillMmask(j) := get_refill_addr(io.refillMdata) === get_refill_addr(data(j)) - } - // DataModuleTemplate should not be used when there're any write conflicts for (i <- 0 until numWrite) { for (j <- i+1 until numWrite) { @@ -192,6 +185,7 @@ class LQMaskModule(numEntries: Int, numRead: Int, numWrite: Int)(implicit p: Par } // SQDataModule is a wrapper of 8 bit MaskedSyncDataModuleTemplates +// NOTE: SQDataModule is not used now // // It also contains: // * fwdMask, which is used to merge refill data and forwarded data @@ -282,9 +276,8 @@ class LQDataModule(numEntries: Int, numRead: Int, numWrite: Int)(implicit p: Par // LoadQueueDataWrapper wraps: // * load queue paddrModule // * load queue maskModule -// * load queue dataModule // and their interconnect -class LoadQueueDataWrapper(size: Int, wbNumRead: Int, wbNumWrite: Int)(implicit p: Parameters) extends XSModule with HasDCacheParameters with HasCircularQueuePtrHelper { +class LoadQueueDataWrapper(size: Int, wbNumWrite: Int)(implicit p: Parameters) extends XSModule with HasDCacheParameters with HasCircularQueuePtrHelper { val io = IO(new Bundle() { val paddr = new Bundle() { val wen = Vec(wbNumWrite, Input(Bool())) @@ -294,24 +287,12 @@ class LoadQueueDataWrapper(size: Int, wbNumRead: Int, wbNumWrite: Int)(implicit val wb = new Bundle() { val wen = Vec(wbNumWrite, Input(Bool())) val waddr = Input(Vec(wbNumWrite, UInt(log2Up(size).W))) - val wdata = Input(Vec(wbNumWrite, new LQDataEntry)) - val raddr = Input(Vec(wbNumRead, UInt(log2Up(size).W))) - val rdata = Output(Vec(wbNumRead, new LQDataEntry)) + val wdata = Input(Vec(wbNumWrite, UInt(8.W))) } val uncache = new Bundle() { - val wen = Input(Bool()) - val waddr = Input(UInt(log2Up(size).W)) - val wdata = Input(UInt(XLEN.W)) // only write back uncache data val raddr = Input(UInt(log2Up(size).W)) val rdata = Output(new LQDataEntry) } - val refill = new Bundle() { - val valid = Input(Bool()) - val paddr = Input(UInt(PAddrBits.W)) - val data = Input(UInt(l1BusDataWidth.W)) - val refillMask = Input(Vec(size, Bool())) - val matchMask = Output(Vec(size, Bool())) - } // st-ld violation query, word level cam val violation = Vec(StorePipelineWidth, new Bundle() { val paddr = Input(UInt(PAddrBits.W)) @@ -326,66 +307,38 @@ class LoadQueueDataWrapper(size: Int, wbNumRead: Int, wbNumWrite: Int)(implicit }) val debug = Output(Vec(size, new LQDataEntry)) - def wbWrite(channel: Int, waddr: UInt, wdata: LQDataEntry): Unit = { + def wbWrite(channel: Int, waddr: UInt, wdata: UInt): Unit = { require(channel < wbNumWrite && wbNumWrite >= 0) // need extra "this.wb(channel).wen := true.B" this.wb.waddr(channel) := waddr this.wb.wdata(channel) := wdata } - - def uncacheWrite(waddr: UInt, wdata: UInt): Unit = { - // need extra "this.uncache.wen := true.B" - this.uncache.waddr := waddr - this.uncache.wdata := wdata - } }) // data module - val paddrModule = Module(new LQPaddrModule(size, numRead = LoadPipelineWidth+1, numWrite = LoadPipelineWidth, numWBanks = LoadQueueNWriteBanks)) - val maskModule = Module(new LQMaskModule(size, numRead = LoadPipelineWidth+1, numWrite = LoadPipelineWidth)) - val dataModule = Module(new LQDataModule(size, numRead = LoadPipelineWidth+1, numWrite = LoadPipelineWidth+1)) + val paddrModule = Module(new LQPaddrModule(size, numRead = 1, numWrite = LoadPipelineWidth, numWBanks = LoadQueueNWriteBanks)) + val maskModule = Module(new LQMaskModule(size, numRead = 1, numWrite = LoadPipelineWidth)) - // read data - // read port 0 -> wbNumRead-1 - (0 until wbNumRead).map(i => { - paddrModule.io.raddr(i) := io.wb.raddr(i) - maskModule.io.raddr(i) := io.wb.raddr(i) - dataModule.io.raddr(i) := io.wb.raddr(i) + // read port for uncache + paddrModule.io.raddr(0) := io.uncache.raddr + maskModule.io.raddr(0) := io.uncache.raddr - io.wb.rdata(i).paddr := paddrModule.io.rdata(i) - io.wb.rdata(i).mask := maskModule.io.rdata(i) - io.wb.rdata(i).data := dataModule.io.rdata(i) - io.wb.rdata(i).fwdMask := DontCare - }) - - // read port wbNumRead - paddrModule.io.raddr(wbNumRead) := io.uncache.raddr - maskModule.io.raddr(wbNumRead) := io.uncache.raddr - dataModule.io.raddr(wbNumRead) := io.uncache.raddr - - io.uncache.rdata.paddr := paddrModule.io.rdata(wbNumRead) - io.uncache.rdata.mask := maskModule.io.rdata(wbNumRead) - io.uncache.rdata.data := dataModule.io.rdata(wbNumRead) + io.uncache.rdata.paddr := paddrModule.io.rdata(0) + io.uncache.rdata.mask := maskModule.io.rdata(0) + io.uncache.rdata.data := DontCare io.uncache.rdata.fwdMask := DontCare - // write data + // write mask and paddr // write port 0 -> wbNumWrite-1 (0 until wbNumWrite).map(i => { paddrModule.io.wen(i) := false.B maskModule.io.wen(i) := false.B - dataModule.io.wen(i) := false.B maskModule.io.waddr(i) := io.wb.waddr(i) - dataModule.io.waddr(i) := io.wb.waddr(i) - - maskModule.io.wdata(i) := io.wb.wdata(i).mask - dataModule.io.wdata(i) := io.wb.wdata(i).data - dataModule.io.fwdMaskWdata(i) := io.wb.wdata(i).fwdMask.asUInt - dataModule.io.paddrWdata(i) := io.wb.wdata(i).paddr + maskModule.io.wdata(i) := io.wb.wdata(i) when(io.wb.wen(i)){ maskModule.io.wen(i) := true.B - dataModule.io.wen(i) := true.B } paddrModule.io.wen(i) := io.paddr.wen(i) @@ -393,17 +346,6 @@ class LoadQueueDataWrapper(size: Int, wbNumRead: Int, wbNumWrite: Int)(implicit paddrModule.io.wdata(i) := io.paddr.wdata(i) }) - // write port wbNumWrite - dataModule.io.wen(wbNumWrite) := io.uncache.wen - // dataModule.io.fwdMaskWen(wbNumWrite) := false.B - // dataModule.io.paddrWen(wbNumWrite) := false.B - - dataModule.io.waddr(wbNumWrite) := io.uncache.waddr - - dataModule.io.fwdMaskWdata(wbNumWrite) := DontCare - dataModule.io.paddrWdata(wbNumWrite) := DontCare - dataModule.io.wdata(wbNumWrite) := io.uncache.wdata - // st-ld mem access violation check, gen violationMask (0 until StorePipelineWidth).map(i => { paddrModule.io.violationMdata(i) := io.violation(i).paddr @@ -417,19 +359,6 @@ class LoadQueueDataWrapper(size: Int, wbNumRead: Int, wbNumWrite: Int)(implicit io.release_violation(i).match_mask := paddrModule.io.releaseMmask(i) }) - // gen paddr match mask - paddrModule.io.refillMdata := io.refill.paddr - (0 until size).map(i => { - io.refill.matchMask := paddrModule.io.refillMmask - // io.refill.matchMask(i) := get_block_addr(data(i).paddr) === get_block_addr(io.refill.paddr) - }) - - // refill data according to matchMask, refillMask and refill.valid - dataModule.io.refillData := io.refill.data - (0 until size).map(i => { - dataModule.io.mwmask(i) := io.refill.valid && io.refill.matchMask(i) && io.refill.refillMask(i) - }) - // debug data read io.debug := DontCare } diff --git a/src/main/scala/xiangshan/mem/lsqueue/StoreQueue.scala b/src/main/scala/xiangshan/mem/lsqueue/StoreQueue.scala index 7f4e0a4f1..88e1c2a10 100644 --- a/src/main/scala/xiangshan/mem/lsqueue/StoreQueue.scala +++ b/src/main/scala/xiangshan/mem/lsqueue/StoreQueue.scala @@ -20,6 +20,7 @@ import chipsalliance.rocketchip.config.Parameters import chisel3._ import chisel3.util._ import utils._ +import utility._ import xiangshan._ import xiangshan.cache._ import xiangshan.cache.{DCacheWordIO, DCacheLineIO, MemoryOpConstants} diff --git a/src/main/scala/xiangshan/mem/lsqueue/StoreQueueData.scala b/src/main/scala/xiangshan/mem/lsqueue/StoreQueueData.scala index 59e2388e9..e3dbf42b2 100644 --- a/src/main/scala/xiangshan/mem/lsqueue/StoreQueueData.scala +++ b/src/main/scala/xiangshan/mem/lsqueue/StoreQueueData.scala @@ -20,6 +20,7 @@ import chipsalliance.rocketchip.config.Parameters import chisel3._ import chisel3.util._ import utils._ +import utility._ import xiangshan._ import xiangshan.cache._ import xiangshan.cache.{DCacheWordIO, DCacheLineIO, MemoryOpConstants} diff --git a/src/main/scala/xiangshan/mem/mdp/StoreSet.scala b/src/main/scala/xiangshan/mem/mdp/StoreSet.scala index 676d3af81..13119e964 100644 --- a/src/main/scala/xiangshan/mem/mdp/StoreSet.scala +++ b/src/main/scala/xiangshan/mem/mdp/StoreSet.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ import xiangshan.backend.rob.RobPtr // store set load violation predictor diff --git a/src/main/scala/xiangshan/mem/mdp/WaitTable.scala b/src/main/scala/xiangshan/mem/mdp/WaitTable.scala index 9009ce0ab..e18e01b56 100644 --- a/src/main/scala/xiangshan/mem/mdp/WaitTable.scala +++ b/src/main/scala/xiangshan/mem/mdp/WaitTable.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ // 21264-like wait table, uses 2-bit counter class WaitTable(implicit p: Parameters) extends XSModule { diff --git a/src/main/scala/xiangshan/mem/pipeline/AtomicsUnit.scala b/src/main/scala/xiangshan/mem/pipeline/AtomicsUnit.scala index ba115fd48..0821f2fb6 100644 --- a/src/main/scala/xiangshan/mem/pipeline/AtomicsUnit.scala +++ b/src/main/scala/xiangshan/mem/pipeline/AtomicsUnit.scala @@ -20,6 +20,7 @@ import chipsalliance.rocketchip.config.Parameters import chisel3._ import chisel3.util._ import utils._ +import utility._ import xiangshan._ import xiangshan.cache.{AtomicWordIO, MemoryOpConstants, HasDCacheParameters} import xiangshan.cache.mmu.{TlbCmd, TlbRequestIO} diff --git a/src/main/scala/xiangshan/mem/pipeline/LoadUnit.scala b/src/main/scala/xiangshan/mem/pipeline/LoadUnit.scala index c3b031ff4..31cfd4067 100644 --- a/src/main/scala/xiangshan/mem/pipeline/LoadUnit.scala +++ b/src/main/scala/xiangshan/mem/pipeline/LoadUnit.scala @@ -20,6 +20,7 @@ import chipsalliance.rocketchip.config.Parameters import chisel3._ import chisel3.util._ import utils._ +import utility._ import xiangshan.ExceptionNO._ import xiangshan._ import xiangshan.backend.fu.PMPRespBundle @@ -34,14 +35,18 @@ class LoadToLsqFastIO(implicit p: Parameters) extends XSBundle { val ld_idx = Output(UInt(log2Ceil(LoadQueueSize).W)) } -class LoadToLsqSlowIO(implicit p: Parameters) extends XSBundle { +class LoadToLsqSlowIO(implicit p: Parameters) extends XSBundle with HasDCacheParameters { val valid = Output(Bool()) val tlb_hited = Output(Bool()) val st_ld_check_ok = Output(Bool()) val cache_no_replay = Output(Bool()) val forward_data_valid = Output(Bool()) + val cache_hited = Output(Bool()) + val can_forward_full_data = Output(Bool()) val ld_idx = Output(UInt(log2Ceil(LoadQueueSize).W)) val data_invalid_sq_idx = Output(UInt(log2Ceil(StoreQueueSize).W)) + val miss_mshr_id = Output(UInt(log2Up(cfg.nMissEntries).W)) + val data_in_last_beat = Output(Bool()) } class LoadToLsqIO(implicit p: Parameters) extends XSBundle { @@ -102,7 +107,7 @@ class LoadUnit_S0(implicit p: Parameters) extends XSModule with HasDCacheParamet // * 3. load try pointchaising when no issued or replayed load (io.fastpath) // the priority is - // 1 > 2 > 3 + // 2 > 1 > 3 // now in S0, choise a load according to priority val s0_vaddr = Wire(UInt(VAddrBits.W)) @@ -123,7 +128,15 @@ class LoadUnit_S0(implicit p: Parameters) extends XSModule with HasDCacheParamet // assign default value s0_uop := DontCare - when(io.in.valid) { + when(io.lsqOut.valid) { + s0_vaddr := io.lsqOut.bits.vaddr + s0_mask := io.lsqOut.bits.mask + s0_uop := io.lsqOut.bits.uop + s0_isFirstIssue := io.lsqOut.bits.isFirstIssue + s0_rsIdx := io.lsqOut.bits.rsIdx + s0_sqIdx := io.lsqOut.bits.uop.sqIdx + + }.elsewhen(io.in.valid) { val imm12 = io.in.bits.uop.ctrl.imm(11, 0) s0_vaddr := io.in.bits.src(0) + SignExt(imm12, VAddrBits) s0_mask := genWmask(s0_vaddr, io.in.bits.uop.ctrl.fuOpType(1,0)) @@ -132,14 +145,6 @@ class LoadUnit_S0(implicit p: Parameters) extends XSModule with HasDCacheParamet s0_rsIdx := io.rsIdx s0_sqIdx := io.in.bits.uop.sqIdx - }.elsewhen(io.lsqOut.valid) { - s0_vaddr := io.lsqOut.bits.vaddr - s0_mask := io.lsqOut.bits.mask - s0_uop := io.lsqOut.bits.uop - s0_isFirstIssue := io.lsqOut.bits.isFirstIssue - s0_rsIdx := io.lsqOut.bits.rsIdx - s0_sqIdx := io.lsqOut.bits.uop.sqIdx - }.otherwise { if (EnableLoadToLoadForward) { tryFastpath := io.fastpath.valid @@ -163,10 +168,10 @@ class LoadUnit_S0(implicit p: Parameters) extends XSModule with HasDCacheParamet "b11".U -> (s0_vaddr(2, 0) === 0.U) //d )) - // io.in has highest priority - io.in.ready := !io.in.valid || (io.out.ready && io.dcacheReq.ready) - // io.lsqOut can fire only when there in no RS-issued load - io.lsqOut.ready := (io.out.ready && io.dcacheReq.ready && !io.in.valid) + // io.lsqOut has highest priority + io.lsqOut.ready := (io.out.ready && io.dcacheReq.ready) + // io.in can fire only when there in no lsq-replayed load + io.in.ready := (io.out.ready && io.dcacheReq.ready && !io.lsqOut.valid) val isSoftPrefetch = LSUOpType.isPrefetch(s0_uop.ctrl.fuOpType) val isSoftPrefetchRead = s0_uop.ctrl.fuOpType === LSUOpType.prefetch_r @@ -213,7 +218,9 @@ class LoadUnit_S0(implicit p: Parameters) extends XSModule with HasDCacheParamet io.out.bits.rsIdx := s0_rsIdx io.out.bits.isFirstIssue := s0_isFirstIssue io.out.bits.isSoftPrefetch := isSoftPrefetch - io.out.bits.isLoadReplay := !io.in.valid && io.lsqOut.valid + io.out.bits.isLoadReplay := io.lsqOut.valid + io.out.bits.mshrid := io.lsqOut.bits.mshrid + io.out.bits.forward_tlDchannel := io.lsqOut.valid && io.lsqOut.bits.forward_tlDchannel XSDebug(io.dcacheReq.fire, p"[DCACHE LOAD REQ] pc ${Hexadecimal(s0_uop.cf.pc)}, vaddr ${Hexadecimal(s0_vaddr)}\n" @@ -227,6 +234,7 @@ class LoadUnit_S0(implicit p: Parameters) extends XSModule with HasDCacheParamet XSPerfAccumulate("addr_spec_failed", io.out.fire && s0_vaddr(VAddrBits-1, 12) =/= io.in.bits.src(0)(VAddrBits-1, 12)) XSPerfAccumulate("addr_spec_success_once", io.out.fire && s0_vaddr(VAddrBits-1, 12) === io.in.bits.src(0)(VAddrBits-1, 12) && io.isFirstIssue) XSPerfAccumulate("addr_spec_failed_once", io.out.fire && s0_vaddr(VAddrBits-1, 12) =/= io.in.bits.src(0)(VAddrBits-1, 12) && io.isFirstIssue) + XSPerfAccumulate("forward_tlDchannel", io.out.bits.forward_tlDchannel) } @@ -367,7 +375,7 @@ class LoadUnit_S1(implicit p: Parameters) extends XSModule with HasCircularQueue // Load Pipeline Stage 2 // DCache resp -class LoadUnit_S2(implicit p: Parameters) extends XSModule with HasLoadHelper with HasCircularQueuePtrHelper { +class LoadUnit_S2(implicit p: Parameters) extends XSModule with HasLoadHelper with HasCircularQueuePtrHelper with HasDCacheParameters { val io = IO(new Bundle() { val in = Flipped(Decoupled(new LsPipelineBundle)) val out = Decoupled(new LsPipelineBundle) @@ -391,7 +399,16 @@ class LoadUnit_S2(implicit p: Parameters) extends XSModule with HasLoadHelper wi val loadDataFromDcache = Output(new LoadDataFromDcacheBundle) val reExecuteQuery = Flipped(Vec(StorePipelineWidth, Valid(new LoadReExecuteQueryIO))) val needReExecute = Output(Bool()) - // val write_lq_safe = Output(Bool()) // used by duplicate wen signals + // forward tilelink D channel + val forward_D = Input(Bool()) + val forwardData_D = Input(Vec(8, UInt(8.W))) + + // forward mshr data + val forward_mshr = Input(Bool()) + val forwardData_mshr = Input(Vec(8, UInt(8.W))) + + // indicate whether forward tilelink D channel or mshr data is valid + val forward_result_valid = Input(Bool()) }) val pmp = WireInit(io.pmpResp) @@ -404,6 +421,10 @@ class LoadUnit_S2(implicit p: Parameters) extends XSModule with HasLoadHelper wi val s2_is_prefetch = io.in.bits.isSoftPrefetch + val forward_D_or_mshr_valid = io.forward_result_valid && (io.forward_D || io.forward_mshr) + + // assert(!reset && io.forward_D && io.forward_mshr && io.in.valid && io.in.bits.forward_tlDchannel, "forward D and mshr at the same time") + // exception that may cause load addr to be invalid / illegal // // if such exception happen, that inst and its exception info @@ -414,7 +435,7 @@ class LoadUnit_S2(implicit p: Parameters) extends XSModule with HasLoadHelper wi when (s2_is_prefetch) { s2_exception_vec := 0.U.asTypeOf(s2_exception_vec.cloneType) } - val s2_exception = ExceptionNO.selectByFu(s2_exception_vec, lduCfg).asUInt.orR && !io.in.bits.tlbMiss // ???????? + val s2_exception = ExceptionNO.selectByFu(s2_exception_vec, lduCfg).asUInt.orR && !io.in.bits.tlbMiss // writeback access fault caused by ecc error / bus error // @@ -438,8 +459,8 @@ class LoadUnit_S2(implicit p: Parameters) extends XSModule with HasLoadHelper wi val s2_paddr = io.in.bits.paddr val s2_tlb_miss = io.in.bits.tlbMiss val s2_mmio = !s2_is_prefetch && actually_mmio && !s2_exception - val s2_cache_miss = io.dcacheResp.bits.miss - val s2_cache_replay = io.dcacheResp.bits.replay + val s2_cache_miss = io.dcacheResp.bits.miss && !forward_D_or_mshr_valid + val s2_cache_replay = io.dcacheResp.bits.replay && !forward_D_or_mshr_valid val s2_cache_tag_error = io.dcacheResp.bits.tag_error val s2_forward_fail = io.lsq.matchInvalid || io.sbuffer.matchInvalid val s2_ldld_violation = io.loadViolationQueryResp.valid && @@ -519,6 +540,12 @@ class LoadUnit_S2(implicit p: Parameters) extends XSModule with HasLoadHelper wi io.loadDataFromDcache.forwardData := forwardData io.loadDataFromDcache.uop := io.out.bits.uop io.loadDataFromDcache.addrOffset := s2_paddr(2, 0) + // forward D or mshr + io.loadDataFromDcache.forward_D := io.forward_D + io.loadDataFromDcache.forwardData_D := io.forwardData_D + io.loadDataFromDcache.forward_mshr := io.forward_mshr + io.loadDataFromDcache.forwardData_mshr := io.forwardData_mshr + io.loadDataFromDcache.forward_result_valid := io.forward_result_valid io.s2_can_replay_from_fetch := !s2_mmio && !s2_is_prefetch && !s2_tlb_miss // if forward fail, replay this inst from fetch @@ -609,8 +636,12 @@ class LoadUnit_S2(implicit p: Parameters) extends XSModule with HasLoadHelper wi io.replaySlow.cache_no_replay := !s2_cache_replay || s2_is_prefetch || s2_mmio || s2_exception || io.dataForwarded } io.replaySlow.forward_data_valid := !s2_data_invalid || s2_is_prefetch + io.replaySlow.cache_hited := !io.out.bits.miss || io.out.bits.mmio + io.replaySlow.can_forward_full_data := io.dataForwarded io.replaySlow.ld_idx := io.in.bits.uop.lqIdx.value io.replaySlow.data_invalid_sq_idx := io.dataInvalidSqIdx + io.replaySlow.miss_mshr_id := io.dcacheResp.bits.mshr_id + io.replaySlow.data_in_last_beat := io.in.bits.paddr(log2Up(refillBytes)) // s2_cache_replay is quite slow to generate, send it separately to LQ if (EnableFastForward) { @@ -641,6 +672,7 @@ class LoadUnit_S2(implicit p: Parameters) extends XSModule with HasLoadHelper wi XSPerfAccumulate("replay_tlb_miss_lq", io.replaySlow.valid && !io.replaySlow.tlb_hited) XSPerfAccumulate("replay_sl_vio", io.replaySlow.valid && io.replaySlow.tlb_hited && !io.replaySlow.st_ld_check_ok) XSPerfAccumulate("replay_cache_lq", io.replaySlow.valid && io.replaySlow.tlb_hited && io.replaySlow.st_ld_check_ok && !io.replaySlow.cache_no_replay) + XSPerfAccumulate("replay_cache_miss_lq", io.replaySlow.valid && !io.replaySlow.cache_hited) } class LoadUnit(implicit p: Parameters) extends XSModule @@ -659,6 +691,8 @@ class LoadUnit(implicit p: Parameters) extends XSModule val dcache = new DCacheLoadIO val sbuffer = new LoadForwardQueryIO val lsq = new LoadToLsqIO + val tlDchannel = Input(new DcacheToLduForwardIO) + val forward_mshr = Flipped(new LduToMissqueueForwardIO) val refill = Flipped(ValidIO(new Refill)) val fastUop = ValidIO(new MicroOp) // early wakeup signal generated in load_s1, send to RS in load_s2 val trigger = Vec(3, new LoadUnitTriggerIO) @@ -757,7 +791,7 @@ class LoadUnit(implicit p: Parameters) extends XSModule when (cancelPointerChasing) { load_s1.io.s1_kill := true.B }.otherwise { - load_s0.io.s0_kill := s1_tryPointerChasing + load_s0.io.s0_kill := s1_tryPointerChasing && !io.lsqOut.valid when (s1_tryPointerChasing) { io.ldin.ready := true.B } @@ -778,8 +812,21 @@ class LoadUnit(implicit p: Parameters) extends XSModule PipelineConnect(load_s1.io.out, load_s2.io.in, true.B, load_s1.io.out.bits.uop.robIdx.needFlush(io.redirect) || cancelPointerChasing) + val (forward_D, forwardData_D) = io.tlDchannel.forward(load_s1.io.out.valid && load_s1.io.out.bits.forward_tlDchannel, load_s1.io.out.bits.mshrid, load_s1.io.out.bits.paddr) + io.forward_mshr.valid := load_s1.io.out.valid && load_s1.io.out.bits.forward_tlDchannel + io.forward_mshr.mshrid := load_s1.io.out.bits.mshrid + io.forward_mshr.paddr := load_s1.io.out.bits.paddr + val (forward_result_valid, forward_mshr, forwardData_mshr) = io.forward_mshr.forward() + + XSPerfAccumulate("successfully_forward_channel_D", forward_D && forward_result_valid) + XSPerfAccumulate("successfully_forward_mshr", forward_mshr && forward_result_valid) // load s2 + load_s2.io.forward_D := forward_D + load_s2.io.forwardData_D := forwardData_D + load_s2.io.forward_result_valid := forward_result_valid + load_s2.io.forward_mshr := forward_mshr + load_s2.io.forwardData_mshr := forwardData_mshr io.dcache.s2_kill := load_s2.io.dcache_kill // to kill mmio resp which are redirected load_s2.io.dcacheResp <> io.dcache.resp load_s2.io.pmpResp <> io.pmp @@ -821,7 +868,8 @@ class LoadUnit(implicit p: Parameters) extends XSModule // assert(load_s2.io.dcacheResp.bits.data === io.dcache.resp.bits.data) // now io.fastUop.valid is sent to RS in load_s2 - val s2_dcache_hit = io.dcache.s2_hit // dcache hit dup in lsu side + val forward_D_or_mshr_valid = forward_result_valid && (forward_D || forward_mshr) + val s2_dcache_hit = io.dcache.s2_hit || forward_D_or_mshr_valid // dcache hit dup in lsu side io.fastUop.valid := RegNext( !io.dcache.s1_disable_fast_wakeup && // load fast wakeup should be disabled when dcache data read is not ready diff --git a/src/main/scala/xiangshan/mem/pipeline/StoreUnit.scala b/src/main/scala/xiangshan/mem/pipeline/StoreUnit.scala index 952c66d39..87679c302 100644 --- a/src/main/scala/xiangshan/mem/pipeline/StoreUnit.scala +++ b/src/main/scala/xiangshan/mem/pipeline/StoreUnit.scala @@ -20,6 +20,7 @@ import chipsalliance.rocketchip.config.Parameters import chisel3._ import chisel3.util._ import utils._ +import utility._ import xiangshan.ExceptionNO._ import xiangshan._ import xiangshan.backend.fu.PMPRespBundle diff --git a/src/main/scala/xiangshan/mem/sbuffer/DatamoduleResultBuffer.scala b/src/main/scala/xiangshan/mem/sbuffer/DatamoduleResultBuffer.scala index 8f45f064e..428c51f98 100644 --- a/src/main/scala/xiangshan/mem/sbuffer/DatamoduleResultBuffer.scala +++ b/src/main/scala/xiangshan/mem/sbuffer/DatamoduleResultBuffer.scala @@ -22,6 +22,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ import xiangshan.cache._ import difftest._ diff --git a/src/main/scala/xiangshan/mem/sbuffer/Sbuffer.scala b/src/main/scala/xiangshan/mem/sbuffer/Sbuffer.scala index a7ce4b250..06e450e85 100644 --- a/src/main/scala/xiangshan/mem/sbuffer/Sbuffer.scala +++ b/src/main/scala/xiangshan/mem/sbuffer/Sbuffer.scala @@ -21,6 +21,7 @@ import chisel3._ import chisel3.util._ import xiangshan._ import utils._ +import utility._ import xiangshan.cache._ import difftest._ import freechips.rocketchip.util._ diff --git a/src/main/scala/xiangshan/mem/vector/DummyVLSQ.scala b/src/main/scala/xiangshan/mem/vector/DummyVLSQ.scala index 378dbf706..0645e1fd5 100644 --- a/src/main/scala/xiangshan/mem/vector/DummyVLSQ.scala +++ b/src/main/scala/xiangshan/mem/vector/DummyVLSQ.scala @@ -20,6 +20,7 @@ import chipsalliance.rocketchip.config.Parameters import chisel3._ import chisel3.util._ import utils._ +import utility._ import xiangshan._ class DummyVectorLsq(implicit p: Parameters) extends BaseVectorLsq { diff --git a/src/main/scala/xiangshan/mem/vector/MemVectorInterface.scala b/src/main/scala/xiangshan/mem/vector/MemVectorInterface.scala index feba185c5..15dd5391b 100644 --- a/src/main/scala/xiangshan/mem/vector/MemVectorInterface.scala +++ b/src/main/scala/xiangshan/mem/vector/MemVectorInterface.scala @@ -20,6 +20,7 @@ import chipsalliance.rocketchip.config.Parameters import chisel3._ import chisel3.util._ import utils._ +import utility._ import xiangshan._ import xiangshan.cache._ diff --git a/src/test/scala/top/SimTop.scala b/src/test/scala/top/SimTop.scala index c51999f72..3048c76ce 100644 --- a/src/test/scala/top/SimTop.scala +++ b/src/test/scala/top/SimTop.scala @@ -23,9 +23,9 @@ import device.{AXI4MemorySlave, SimJTAG} import difftest._ import freechips.rocketchip.diplomacy.{DisableMonitors, LazyModule} import freechips.rocketchip.util.ElaborationArtefacts -import huancun.utils.ChiselDB +import utility.ChiselDB import top.TopMain.writeOutputFile -import utils.GTimer +import utility.GTimer import xiangshan.DebugOptionsKey class SimTop(implicit p: Parameters) extends Module { diff --git a/utility b/utility new file mode 160000 index 000000000..6d8b9a4fd --- /dev/null +++ b/utility @@ -0,0 +1 @@ +Subproject commit 6d8b9a4fd52d865faa6dfd2d6d92cf3ab5fbc99b