Merge remote-tracking branch 'origin/master' into rf-after-issue

This commit is contained in:
ZhangZifei 2022-12-29 22:09:13 +08:00
commit b6c99e8e08
165 changed files with 741 additions and 3445 deletions

6
.gitmodules vendored
View File

@ -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

View File

@ -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
}

@ -1 +1 @@
Subproject commit 57ccacbf0c5b552a3d6dda5baeef3abc8bad033c
Subproject commit f96ac25904091ae7ab96b7f6f5bd7047d4129466

View File

@ -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

View File

@ -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()))

View File

@ -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 {

View File

@ -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())

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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}

View File

@ -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())

View File

@ -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

View File

@ -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

View File

@ -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}

View File

@ -22,6 +22,7 @@
//import bus.axi4._
//import device.AXI4SlaveModule
//import utils._
import utility._
//
//class PixelBundle extends Bundle {
// val a = UInt(8.W)

View File

@ -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._

View File

@ -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}

View File

@ -20,6 +20,7 @@ import chisel3._
import chisel3.util._
import xiangshan._
import utils._
import utility._
import system._
import device._
import chisel3.stage.ChiselGeneratorAnnotation

View File

@ -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
}
}

View File

@ -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")
}
}
}

View File

@ -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))
}

View File

@ -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)
}
}

View File

@ -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")
}
}

View File

@ -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!"))
}
}

View File

@ -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)
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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

View File

@ -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
}
}

View File

@ -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<<ptr_width else 0).U((ptr_width+1).W)
val enq_ptr = RegInit(enqPtrInitVal)
val deq_ptr = RegInit(deqPtrInitVal)
def ptrToIdx(ptr: UInt): UInt = ptr.tail(1)
def isFull(ptr1: UInt, ptr2: UInt): Bool = (ptr1.head(1)=/=ptr2.head(1)) && (ptr1.tail(1) === ptr2.tail(1))
def isEmpty(ptr1: UInt, ptr2: UInt): Bool = ptr1 === ptr2
def genPtrs(init: UInt, vec: Vec[DecoupledIO[T]]) = {
if(perf){
vec.indices.map(i => {
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")
// }
}

View File

@ -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)
}
}

View File

@ -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])
}
}

View File

@ -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
}
}

View File

@ -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())
}
}

View File

@ -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
}
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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
}
}

View File

@ -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()))
}}
}

View File

@ -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)
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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))

View File

@ -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}

View File

@ -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._

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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._

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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() {

View File

@ -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}

View File

@ -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._

View File

@ -20,6 +20,7 @@ import chipsalliance.rocketchip.config.Parameters
import chisel3._
import chisel3.util._
import utils._
import utility._
import xiangshan._
import xiangshan.backend.fu._

View File

@ -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

View File

@ -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 {

View File

@ -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._

View File

@ -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._

View File

@ -21,6 +21,7 @@ import chisel3._
import chisel3.util._
import xiangshan._
import utils._
import utility._
import xiangshan.ExceptionNO.illegalInstr
class FenceToSbuffer extends Bundle {

View File

@ -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

View File

@ -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._

View File

@ -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{

View File

@ -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 */

View File

@ -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 {

View File

@ -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))

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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._

View File

@ -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

View File

@ -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 {

View File

@ -21,6 +21,7 @@ import chisel3._
import chisel3.util._
import xiangshan._
import utils._
import utility._
class BypassInfo(numWays: Int, dataBits: Int) extends Bundle {

View File

@ -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

View File

@ -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))

View File

@ -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

View File

@ -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 {

View File

@ -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}

View File

@ -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 {

View File

@ -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))

View File

@ -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._

View File

@ -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

View File

@ -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 {

View File

@ -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 {

View File

@ -21,6 +21,7 @@ import chisel3._
import chisel3.util._
import xiangshan._
import utils._
import utility._

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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

Some files were not shown because too many files have changed in this diff Show More