Merge remote-tracking branch 'origin/master' into rf-after-issue
This commit is contained in:
commit
b6c99e8e08
|
|
@ -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
|
||||
|
|
|
|||
17
build.sc
17
build.sc
|
|
@ -114,7 +114,8 @@ object huancun extends XSModule with SbtModule {
|
|||
override def millSourcePath = os.pwd / "huancun"
|
||||
|
||||
override def moduleDeps = super.moduleDeps ++ Seq(
|
||||
rocketchip
|
||||
rocketchip,
|
||||
utility
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -128,6 +129,15 @@ object yunsuan extends XSModule with SbtModule {
|
|||
|
||||
object fudian extends XSModule with SbtModule
|
||||
|
||||
object utility extends XSModule with SbtModule {
|
||||
|
||||
override def millSourcePath = os.pwd / "utility"
|
||||
|
||||
override def moduleDeps = super.moduleDeps ++ Seq(
|
||||
rocketchip
|
||||
)
|
||||
}
|
||||
|
||||
// extends this trait to use XiangShan in other projects
|
||||
trait CommonXiangShan extends XSModule with SbtModule { m =>
|
||||
|
||||
|
|
@ -137,6 +147,7 @@ trait CommonXiangShan extends XSModule with SbtModule { m =>
|
|||
def huancunModule: PublishModule
|
||||
def yunsuanModule: PublishModule
|
||||
def fudianModule: PublishModule
|
||||
def utilityModule: PublishModule
|
||||
|
||||
override def millSourcePath = os.pwd
|
||||
|
||||
|
|
@ -149,7 +160,8 @@ trait CommonXiangShan extends XSModule with SbtModule { m =>
|
|||
difftestModule,
|
||||
huancunModule,
|
||||
yunsuanModule,
|
||||
fudianModule
|
||||
fudianModule,
|
||||
utilityModule
|
||||
)
|
||||
|
||||
object test extends Tests with TestModule.ScalaTest {
|
||||
|
|
@ -170,4 +182,5 @@ object XiangShan extends CommonXiangShan {
|
|||
override def huancunModule = huancun
|
||||
override def yunsuanModule = yunsuan
|
||||
override def fudianModule = fudian
|
||||
override def utilityModule = utility
|
||||
}
|
||||
|
|
|
|||
2
huancun
2
huancun
|
|
@ -1 +1 @@
|
|||
Subproject commit 57ccacbf0c5b552a3d6dda5baeef3abc8bad033c
|
||||
Subproject commit f96ac25904091ae7ab96b7f6f5bd7047d4129466
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()))
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
//import bus.axi4._
|
||||
//import device.AXI4SlaveModule
|
||||
//import utils._
|
||||
import utility._
|
||||
//
|
||||
//class PixelBundle extends Bundle {
|
||||
// val a = UInt(8.W)
|
||||
|
|
|
|||
|
|
@ -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._
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import chisel3._
|
|||
import chisel3.util._
|
||||
import xiangshan._
|
||||
import utils._
|
||||
import utility._
|
||||
import system._
|
||||
import device._
|
||||
import chisel3.stage.ChiselGeneratorAnnotation
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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))
|
||||
}
|
||||
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
|
@ -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!"))
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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")
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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])
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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()))
|
||||
}}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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._
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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._
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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._
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import chipsalliance.rocketchip.config.Parameters
|
|||
import chisel3._
|
||||
import chisel3.util._
|
||||
import utils._
|
||||
import utility._
|
||||
import xiangshan._
|
||||
import xiangshan.backend.fu._
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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._
|
||||
|
||||
|
|
|
|||
|
|
@ -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._
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import chisel3._
|
|||
import chisel3.util._
|
||||
import xiangshan._
|
||||
import utils._
|
||||
import utility._
|
||||
import xiangshan.ExceptionNO.illegalInstr
|
||||
|
||||
class FenceToSbuffer extends Bundle {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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._
|
||||
|
|
|
|||
|
|
@ -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{
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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._
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import chisel3._
|
|||
import chisel3.util._
|
||||
import xiangshan._
|
||||
import utils._
|
||||
import utility._
|
||||
|
||||
|
||||
class BypassInfo(numWays: Int, dataBits: Int) extends Bundle {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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._
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import chisel3._
|
|||
import chisel3.util._
|
||||
import xiangshan._
|
||||
import utils._
|
||||
import utility._
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in New Issue