diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 08a40d68e..a58944e73 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -40,9 +40,15 @@ jobs: } nix develop '.#t1.elaborator' -c mill -i configgen.reformat + nix develop '.#t1.elaborator' -c mill -i elaborator.reformat + nix develop '.#t1.elaborator' -c mill -i omreader.reformat + nix develop '.#t1.elaborator' -c mill -i omreaderlib.reformat nix develop '.#t1.elaborator' -c mill -i rocketv.reformat + nix develop '.#t1.elaborator' -c mill -i rocketemu.reformat nix develop '.#t1.elaborator' -c mill -i t1.reformat + nix develop '.#t1.elaborator' -c mill -i t1emu.reformat nix develop '.#t1.elaborator' -c mill -i t1rocket.reformat + nix develop '.#t1.elaborator' -c mill -i t1rocketemu.reformat warnOnFileChanged "* Scala format fail, please run 'nix develop '.#t1.elaborator' -c mill -i _.reformat'" nix fmt diff --git a/build.sc b/build.sc index 18db1ccc3..c57817d0f 100644 --- a/build.sc +++ b/build.sc @@ -139,7 +139,7 @@ trait T1Rocket extends millbuild.common.T1RocketModule with ScalafmtModule { object t1emu extends T1Emulator -trait T1Emulator extends millbuild.common.T1EmulatorModule { +trait T1Emulator extends millbuild.common.T1EmulatorModule with ScalafmtModule { def scalaVersion = T(v.scala) def t1Module = t1 @@ -151,7 +151,8 @@ trait T1Emulator extends millbuild.common.T1EmulatorModule { } object rocketemu extends RocketEmulator -trait RocketEmulator extends millbuild.common.RocketEmulatorModule { + +trait RocketEmulator extends millbuild.common.RocketEmulatorModule with ScalafmtModule { def scalaVersion = T(v.scala) def rocketVModule = rocketv @@ -164,7 +165,7 @@ trait RocketEmulator extends millbuild.common.RocketEmulatorModule { object t1rocketemu extends T1RocketEmulator -trait T1RocketEmulator extends millbuild.common.T1RocketEmulatorModule { +trait T1RocketEmulator extends millbuild.common.T1RocketEmulatorModule with ScalafmtModule { def scalaVersion = T(v.scala) def t1rocketModule = t1rocket @@ -188,7 +189,7 @@ trait PanamaConverter extends millbuild.dependencies.chisel.build.PanamaConverte // Module to generate RTL from json config object elaborator extends Elaborator -trait Elaborator extends millbuild.common.ElaboratorModule { +trait Elaborator extends millbuild.common.ElaboratorModule with ScalafmtModule { def scalaVersion = T(v.scala) def panamaconverterModule = panamaconverter @@ -214,7 +215,7 @@ trait Elaborator extends millbuild.common.ElaboratorModule { object omreaderlib extends OMReaderLib -trait OMReaderLib extends millbuild.common.OMReaderLibModule { +trait OMReaderLib extends millbuild.common.OMReaderLibModule with ScalafmtModule { def scalaVersion = T(v.scala) def panamaconverterModule = panamaconverter @@ -231,7 +232,7 @@ trait OMReaderLib extends millbuild.common.OMReaderLibModule { object omreader extends OMReader -trait OMReader extends millbuild.common.OMReaderModule { +trait OMReader extends millbuild.common.OMReaderModule with ScalafmtModule { def scalaVersion = T(v.scala) def panamaconverterModule = panamaconverter diff --git a/elaborator/src/Elaborator.scala b/elaborator/src/Elaborator.scala index f4e080865..ab9bcb434 100644 --- a/elaborator/src/Elaborator.scala +++ b/elaborator/src/Elaborator.scala @@ -17,45 +17,48 @@ trait Elaborator { } def configImpl[P <: SerializableModuleParameter: universe.TypeTag]( - parameter: P - )(implicit rwP: upickle.default.Writer[P]) = os.write.over( + parameter: P + )( + implicit rwP: upickle.default.Writer[P] + ) = os.write.over( os.pwd / s"${getClass.getSimpleName.replace("$", "")}.json", upickle.default.write(parameter) ) - def designImpl[ - M <: SerializableModule[P]: universe.TypeTag, - P <: SerializableModuleParameter: universe.TypeTag - ](parameter: os.Path, runFirtool: Boolean)(implicit - rwP: upickle.default.Reader[P] + def designImpl[M <: SerializableModule[P]: universe.TypeTag, P <: SerializableModuleParameter: universe.TypeTag]( + parameter: os.Path, + runFirtool: Boolean + )( + implicit + rwP: upickle.default.Reader[P] ) = { var fir: firrtl.ir.Circuit = null - val annos = Seq( + val annos = Seq( new chisel3.stage.phases.Elaborate, new chisel3.stage.phases.Convert ).foldLeft( - Seq( - chisel3.stage.ChiselGeneratorAnnotation(() => - SerializableModuleGenerator( - runtimeMirror(getClass.getClassLoader) - .runtimeClass(typeOf[M].typeSymbol.asClass) - .asInstanceOf[Class[M]], - upickle.default.read[P](os.read(parameter)) - ).module().asInstanceOf[RawModule] - ) - ): firrtl.AnnotationSeq - ) { case (annos, stage) => stage.transform(annos) } + Seq( + chisel3.stage.ChiselGeneratorAnnotation(() => + SerializableModuleGenerator( + runtimeMirror(getClass.getClassLoader) + .runtimeClass(typeOf[M].typeSymbol.asClass) + .asInstanceOf[Class[M]], + upickle.default.read[P](os.read(parameter)) + ).module().asInstanceOf[RawModule] + ) + ): firrtl.AnnotationSeq + ) { case (annos, stage) => stage.transform(annos) } .flatMap { case firrtl.stage.FirrtlCircuitAnnotation(circuit) => fir = circuit None case _: chisel3.stage.DesignAnnotation[_] => None case _: chisel3.stage.ChiselCircuitAnnotation => None - case a => Some(a) + case a => Some(a) } val annoJsonFile = os.pwd / s"${fir.main}.anno.json" - val firFile = os.pwd / s"${fir.main}.fir" - val svFile = os.pwd / s"${fir.main}.sv" + val firFile = os.pwd / s"${fir.main}.fir" + val svFile = os.pwd / s"${fir.main}.sv" os.write.over(firFile, fir.serialize) os.write.over( annoJsonFile, diff --git a/elaborator/src/Main.scala b/elaborator/src/Main.scala index a6faf72a8..260151a47 100644 --- a/elaborator/src/Main.scala +++ b/elaborator/src/Main.scala @@ -20,7 +20,7 @@ object Main { @arg(name = "target-dir", short = 't') targetDir: os.Path, @arg(name = "binder-mlirbc-out") binderMlirbcOut: Option[String] = None) { def elaborate(gen: () => chisel3.RawModule): Unit = { - var fir: firrtl.ir.Circuit = null + var fir: firrtl.ir.Circuit = null var panamaCIRCTConverter: chisel3.panamaconverter.PanamaCIRCTConverter = null val annos = Seq( @@ -41,7 +41,7 @@ object Main { ): firrtl.AnnotationSeq ) { case (annos, stage) => stage.transform(annos) } .flatMap { - case firrtl.stage.FirrtlCircuitAnnotation(circuit) => + case firrtl.stage.FirrtlCircuitAnnotation(circuit) => if (binderMlirbcOut.isEmpty) fir = circuit None case chisel3.panamaconverter.stage.PanamaCIRCTConverterAnnotation(converter) => @@ -56,7 +56,7 @@ object Main { binderMlirbcOut match { case Some(outFile) => os.write(targetDir / s"$outFile.mlirbc", panamaCIRCTConverter.mlirBytecodeStream) - case None => + case None => os.write(targetDir / s"${fir.main}.fir", fir.serialize) os.write(targetDir / s"${fir.main}.anno.json", firrtl.annotations.JsonProtocol.serialize(annos)) } @@ -95,8 +95,8 @@ object Main { def parameter: T1RocketTileParameter = generator.parameter } - implicit def ipConfig: ParserForClass[IPConfig] = ParserForClass[IPConfig] - implicit def rocketConfig: ParserForClass[RocketConfig] = ParserForClass[RocketConfig] + implicit def ipConfig: ParserForClass[IPConfig] = ParserForClass[IPConfig] + implicit def rocketConfig: ParserForClass[RocketConfig] = ParserForClass[RocketConfig] implicit def t1RocketConfig: ParserForClass[T1RocketConfig] = ParserForClass[T1RocketConfig] @main def ip(elaborateConfig: ElaborateConfig, ipConfig: IPConfig): Unit = diff --git a/elaborator/src/rocketv/BTB.scala b/elaborator/src/rocketv/BTB.scala index 859e842e3..97118a2ad 100644 --- a/elaborator/src/rocketv/BTB.scala +++ b/elaborator/src/rocketv/BTB.scala @@ -12,7 +12,7 @@ object BTB extends Elaborator { @arg(name = "nEntries") nEntries: Int, @arg(name = "counterLength") counterLength: Int, @arg(name = "historyLength") historyLength: Int, - @arg(name = "historyBits") historyBits: Int) { + @arg(name = "historyBits") historyBits: Int) { def convert: BHTParameter = BHTParameter( nEntries, counterLength, @@ -39,8 +39,7 @@ object BTB extends Elaborator { @arg(name = "bht-counterLength") counterLength: Option[Int], @arg(name = "bht-historyLength") historyLength: Option[Int], @arg(name = "bht-historyBits") historyBits: Option[Int], - @arg(name = "fetchWidth") fetchWidth: Int, - ) { + @arg(name = "fetchWidth") fetchWidth: Int) { def convert: BTBParameter = BTBParameter( useAsyncReset, fetchBytes, @@ -58,9 +57,8 @@ object BTB extends Elaborator { .lazyZip(counterLength) .lazyZip(historyLength) .lazyZip(historyBits)) - .map { - case (nEntries, counterLength, historyLength, historyBits) => - BHTParameter(nEntries, counterLength, historyLength, historyBits) + .map { case (nEntries, counterLength, historyLength, historyBits) => + BHTParameter(nEntries, counterLength, historyLength, historyBits) } .headOption ) diff --git a/elaborator/src/rocketv/CSR.scala b/elaborator/src/rocketv/CSR.scala index 17725a517..c00fe13e2 100644 --- a/elaborator/src/rocketv/CSR.scala +++ b/elaborator/src/rocketv/CSR.scala @@ -30,7 +30,7 @@ object CSR extends Elaborator { @arg(name = "usingAtomics") usingAtomics: Boolean, @arg(name = "usingDebug") usingDebug: Boolean, @arg(name = "usingMulDiv") usingMulDiv: Boolean, - @arg(name = "usingVector") usingVector: Boolean) { + @arg(name = "usingVector") usingVector: Boolean) { def convert: CSRParameter = CSRParameter( useAsyncReset: Boolean, vLen: Int, diff --git a/elaborator/src/rocketv/DCache.scala b/elaborator/src/rocketv/DCache.scala index f791bdfea..8a6244b89 100644 --- a/elaborator/src/rocketv/DCache.scala +++ b/elaborator/src/rocketv/DCache.scala @@ -10,7 +10,7 @@ import org.chipsalliance.t1.elaborator.Elaborator object DCache extends Elaborator { implicit object BitSetRead extends TokensReader.Simple[BitSet] { - def shortName = "bitset" + def shortName = "bitset" def read(strs: Seq[String]) = { Right( strs.head @@ -19,13 +19,13 @@ object DCache extends Elaborator { if (opt.contains("-")) { val range = opt.split("-") require(range.size == 2) - val from = BigInt(range.head, 16) - val to = BigInt(range.last, 16) + 1 + val from = BigInt(range.head, 16) + val to = BigInt(range.last, 16) + 1 BitSet.fromRange(from, to - from, range.head.length * 4) } else if (opt.contains("+")) { - val range = opt.split("\\+") + val range = opt.split("\\+") require(range.size == 2) - val from = BigInt(range.head, 16) + val from = BigInt(range.head, 16) val length = BigInt(range.last, 16) BitSet.fromRange(from, length, range.head.length * 4) } else { @@ -63,7 +63,7 @@ object DCache extends Elaborator { @arg(name = "logic") logic: BitSet, @arg(name = "arithmetic") arithmetic: BitSet, @arg(name = "exec") exec: BitSet, - @arg(name = "sideEffects") sideEffects: BitSet) { + @arg(name = "sideEffects") sideEffects: BitSet) { def convert: HellaCacheParameter = HellaCacheParameter( useAsyncReset, clockGate, diff --git a/elaborator/src/rocketv/Decoder.scala b/elaborator/src/rocketv/Decoder.scala index 29f305d7e..059449e2d 100644 --- a/elaborator/src/rocketv/Decoder.scala +++ b/elaborator/src/rocketv/Decoder.scala @@ -9,8 +9,8 @@ import org.chipsalliance.t1.elaborator.Elaborator object Decoder extends Elaborator { @main case class DecoderParameterMain( - @arg(name = "instructionSets") instructionSets: Set[String], - @arg(name = "pipelinedMul") pipelinedMul: Boolean, + @arg(name = "instructionSets") instructionSets: Set[String], + @arg(name = "pipelinedMul") pipelinedMul: Boolean, @arg(name = "fenceIFlushDCache") fenceIFlushDCache: Boolean) { def convert: DecoderParameter = DecoderParameter( instructionSets, diff --git a/elaborator/src/rocketv/FPToFP.scala b/elaborator/src/rocketv/FPToFP.scala index c35094b93..e29ad7089 100644 --- a/elaborator/src/rocketv/FPToFP.scala +++ b/elaborator/src/rocketv/FPToFP.scala @@ -13,7 +13,7 @@ object FPToFP extends Elaborator { latency: Int, xLen: Int, fLen: Int, - minFLen: Int) { + minFLen: Int) { def convert: FPToFPParameter = FPToFPParameter( useAsyncReset, latency, diff --git a/elaborator/src/rocketv/FPToInt.scala b/elaborator/src/rocketv/FPToInt.scala index 2ac447b02..9cae363de 100644 --- a/elaborator/src/rocketv/FPToInt.scala +++ b/elaborator/src/rocketv/FPToInt.scala @@ -12,7 +12,7 @@ object FPToInt extends Elaborator { @arg(name = "useAsyncReset") useAsyncReset: Boolean, @arg(name = "xLen") xLen: Int, @arg(name = "fLen") fLen: Int, - @arg(name = "minFLen") minFLen: Int) { + @arg(name = "minFLen") minFLen: Int) { def convert: FPToIntParameter = FPToIntParameter( useAsyncReset, xLen, diff --git a/elaborator/src/rocketv/FPU.scala b/elaborator/src/rocketv/FPU.scala index 6a077b1b8..720eb4059 100644 --- a/elaborator/src/rocketv/FPU.scala +++ b/elaborator/src/rocketv/FPU.scala @@ -17,7 +17,7 @@ object FPU extends Elaborator { @arg(name = "sfmaLatency") sfmaLatency: Int, @arg(name = "dfmaLatency") dfmaLatency: Int, @arg(name = "divSqrt") divSqrt: Boolean, - @arg(name = "hartIdLen") hartIdLen: Int) { + @arg(name = "hartIdLen") hartIdLen: Int) { def convert: FPUParameter = FPUParameter( useAsyncReset, useClockGating, diff --git a/elaborator/src/rocketv/FPUFMAPipe.scala b/elaborator/src/rocketv/FPUFMAPipe.scala index 5c2b15724..71fad27de 100644 --- a/elaborator/src/rocketv/FPUFMAPipe.scala +++ b/elaborator/src/rocketv/FPUFMAPipe.scala @@ -14,7 +14,7 @@ object FPUFMAPipe extends Elaborator { xLen: Int, fLen: Int, minFLen: Int, - t: String) { + t: String) { def convert: FPUFMAPipeParameter = FPUFMAPipeParameter( useAsyncReset, diff --git a/elaborator/src/rocketv/Frontend.scala b/elaborator/src/rocketv/Frontend.scala index c36c94993..d5fb53113 100644 --- a/elaborator/src/rocketv/Frontend.scala +++ b/elaborator/src/rocketv/Frontend.scala @@ -10,7 +10,7 @@ import org.chipsalliance.t1.elaborator.Elaborator object Frontend extends Elaborator { implicit object BitSetRead extends TokensReader.Simple[BitSet] { - def shortName = "bitset" + def shortName = "bitset" def read(strs: Seq[String]) = { Right( strs.head @@ -19,13 +19,13 @@ object Frontend extends Elaborator { if (opt.contains("-")) { val range = opt.split("-") require(range.size == 2) - val from = BigInt(range.head, 16) - val to = BigInt(range.last, 16) + 1 + val from = BigInt(range.head, 16) + val to = BigInt(range.last, 16) + 1 BitSet.fromRange(from, to - from, range.head.length * 4) } else if (opt.contains("+")) { - val range = opt.split("\\+") + val range = opt.split("\\+") require(range.size == 2) - val from = BigInt(range.head, 16) + val from = BigInt(range.head, 16) val length = BigInt(range.last, 16) BitSet.fromRange(from, length, range.head.length * 4) } else { @@ -76,7 +76,7 @@ object Frontend extends Elaborator { @arg(name = "logic") logic: Seq[BitSet], @arg(name = "arithmetic") arithmetic: Seq[BitSet], @arg(name = "exec") exec: Seq[BitSet], - @arg(name = "sideEffects") sideEffects: Seq[BitSet]) { + @arg(name = "sideEffects") sideEffects: Seq[BitSet]) { def convert: FrontendParameter = FrontendParameter( useAsyncReset: Boolean, clockGate: Boolean, @@ -107,9 +107,8 @@ object Frontend extends Elaborator { .lazyZip(bhtCounterLength) .lazyZip(bhtHistoryLength) .lazyZip(bhtHistoryBits) - .map { - case (bhtNEntries, bhtCounterLength, bhtHistoryLength, bhtHistoryBits) => - BHTParameter(bhtNEntries, bhtCounterLength, bhtHistoryLength, bhtHistoryBits) + .map { case (bhtNEntries, bhtCounterLength, bhtHistoryLength, bhtHistoryBits) => + BHTParameter(bhtNEntries, bhtCounterLength, bhtHistoryLength, bhtHistoryBits) } .headOption, legal.foldLeft(BitSet.empty)(_.union(_)), diff --git a/elaborator/src/rocketv/IBuf.scala b/elaborator/src/rocketv/IBuf.scala index 1e2ac17da..26111c4c5 100644 --- a/elaborator/src/rocketv/IBuf.scala +++ b/elaborator/src/rocketv/IBuf.scala @@ -17,7 +17,7 @@ object IBuf extends Elaborator { @arg(name = "vaddrBitsExtended") vaddrBitsExtended: Int, @arg(name = "bhtHistoryLength") bhtHistoryLength: Option[Int], @arg(name = "bhtCounterLength") bhtCounterLength: Option[Int], - @arg(name = "fetchWidth") fetchWidth: Int) { + @arg(name = "fetchWidth") fetchWidth: Int) { def convert: IBufParameter = IBufParameter( useAsyncReset, xLen, diff --git a/elaborator/src/rocketv/ICache.scala b/elaborator/src/rocketv/ICache.scala index e80b84360..e85757574 100644 --- a/elaborator/src/rocketv/ICache.scala +++ b/elaborator/src/rocketv/ICache.scala @@ -16,7 +16,7 @@ object ICache extends Elaborator { @arg(name = "blockBytes") blockBytes: Int, @arg(name = "usingVM") usingVM: Boolean, @arg(name = "vaddrBits") vaddrBits: Int, - @arg(name = "paddrBits") paddrBits: Int) { + @arg(name = "paddrBits") paddrBits: Int) { def convert: ICacheParameter = ICacheParameter( useAsyncReset, prefetch, diff --git a/elaborator/src/rocketv/IntToFP.scala b/elaborator/src/rocketv/IntToFP.scala index b195becb7..fa64282be 100644 --- a/elaborator/src/rocketv/IntToFP.scala +++ b/elaborator/src/rocketv/IntToFP.scala @@ -13,7 +13,7 @@ object IntToFP extends Elaborator { @arg(name = "latency") latency: Int, @arg(name = "fLen") fLen: Int, @arg(name = "xLen") xLen: Int, - @arg(name = "minFLen") minFLen: Int) { + @arg(name = "minFLen") minFLen: Int) { def convert: IntToFPParameter = IntToFPParameter( useAsyncReset, latency, diff --git a/elaborator/src/rocketv/MulAddRecFNPipe.scala b/elaborator/src/rocketv/MulAddRecFNPipe.scala index 741567250..bc8ace996 100644 --- a/elaborator/src/rocketv/MulAddRecFNPipe.scala +++ b/elaborator/src/rocketv/MulAddRecFNPipe.scala @@ -12,7 +12,7 @@ object MulAddRecFNPipe extends Elaborator { @arg(name = "useAsyncReset") useAsyncReset: Boolean, @arg(name = "latency") latency: Int, @arg(name = "expWidth") expWidth: Int, - @arg(name = "sigWidth") sigWidth: Int) { + @arg(name = "sigWidth") sigWidth: Int) { def convert: MulAddRecFNPipeParameter = MulAddRecFNPipeParameter(useAsyncReset, latency, expWidth, sigWidth) } diff --git a/elaborator/src/rocketv/MulDiv.scala b/elaborator/src/rocketv/MulDiv.scala index 581558219..c97533591 100644 --- a/elaborator/src/rocketv/MulDiv.scala +++ b/elaborator/src/rocketv/MulDiv.scala @@ -17,15 +17,15 @@ object MulDiv extends Elaborator { @arg(name = "divEarlyOutGranularity") divEarlyOutGranularity: Int, @arg(name = "mulUnroll") mulUnroll: Int, @arg(name = "mulEarlyOut") mulEarlyOut: Boolean, - @arg(name = "instructionSets") instructionSets: Set[String], - @arg(name = "pipelinedMul") pipelinedMul: Boolean, + @arg(name = "instructionSets") instructionSets: Set[String], + @arg(name = "pipelinedMul") pipelinedMul: Boolean, @arg(name = "fenceIFlushDCache") fenceIFlushDCache: Boolean) { def decodeParam: DecoderParameter = DecoderParameter( instructionSets, pipelinedMul, fenceIFlushDCache ) - def convert: MulDivParameter = MulDivParameter( + def convert: MulDivParameter = MulDivParameter( useAsyncReset, latency, width, diff --git a/elaborator/src/rocketv/PMAChecker.scala b/elaborator/src/rocketv/PMAChecker.scala index 571acd126..f23d22eaa 100644 --- a/elaborator/src/rocketv/PMAChecker.scala +++ b/elaborator/src/rocketv/PMAChecker.scala @@ -11,38 +11,43 @@ import org.chipsalliance.t1.elaborator.Elaborator object PMAChecker extends Elaborator { implicit object BitSetRead extends TokensReader.Simple[BitSet] { - def shortName = "bitset" + def shortName = "bitset" def read(strs: Seq[String]) = { - Right(strs.head.split(",").map{ opt => - if (opt.contains("-")) { - val range = opt.split("-") - require(range.size == 2) - val from = BigInt(range.head, 16) - val to = BigInt(range.last, 16) + 1 - BitSet.fromRange(from, to - from, range.head.length * 4) - } else if (opt.contains("+")) { - val range = opt.split("\\+") - require(range.size == 2) - val from = BigInt(range.head, 16) - val length = BigInt(range.last, 16) - BitSet.fromRange(from, length, range.head.length * 4) - } else { - BitPat(s"b$opt") - } - }.reduce(_.union(_))) + Right( + strs.head + .split(",") + .map { opt => + if (opt.contains("-")) { + val range = opt.split("-") + require(range.size == 2) + val from = BigInt(range.head, 16) + val to = BigInt(range.last, 16) + 1 + BitSet.fromRange(from, to - from, range.head.length * 4) + } else if (opt.contains("+")) { + val range = opt.split("\\+") + require(range.size == 2) + val from = BigInt(range.head, 16) + val length = BigInt(range.last, 16) + BitSet.fromRange(from, length, range.head.length * 4) + } else { + BitPat(s"b$opt") + } + } + .reduce(_.union(_)) + ) } } @main case class PMACheckerParameterMain( - paddrBits: Int, - legal: Seq[BitSet], - cacheable: Seq[BitSet], - read: Seq[BitSet], - write: Seq[BitSet], - putPartial: Seq[BitSet], - logic: Seq[BitSet], - arithmetic: Seq[BitSet], - exec: Seq[BitSet], + paddrBits: Int, + legal: Seq[BitSet], + cacheable: Seq[BitSet], + read: Seq[BitSet], + write: Seq[BitSet], + putPartial: Seq[BitSet], + logic: Seq[BitSet], + arithmetic: Seq[BitSet], + exec: Seq[BitSet], sideEffects: Seq[BitSet]) { def convert: PMACheckerParameter = PMACheckerParameter( paddrBits, diff --git a/elaborator/src/rocketv/PMP.scala b/elaborator/src/rocketv/PMP.scala index bb8e69c10..f7dd45515 100644 --- a/elaborator/src/rocketv/PMP.scala +++ b/elaborator/src/rocketv/PMP.scala @@ -9,9 +9,9 @@ import org.chipsalliance.t1.elaborator.Elaborator object PMPChecker extends Elaborator { @main case class PMPCheckerParameterMain( - @arg(name = "nPMPs") nPMPs: Int, - @arg(name = "paddrBits") paddrBits: Int, - @arg(name = "lgMaxSize") lgMaxSize: Int, + @arg(name = "nPMPs") nPMPs: Int, + @arg(name = "paddrBits") paddrBits: Int, + @arg(name = "lgMaxSize") lgMaxSize: Int, @arg(name = "pmpGranularity") pmpGranularity: Int) { def convert: PMPCheckerParameter = PMPCheckerParameter( nPMPs: Int, diff --git a/elaborator/src/rocketv/PTW.scala b/elaborator/src/rocketv/PTW.scala index 4a20e110f..7b8cb19d7 100644 --- a/elaborator/src/rocketv/PTW.scala +++ b/elaborator/src/rocketv/PTW.scala @@ -21,7 +21,7 @@ object PTW extends Elaborator { @arg(name = "nPTECacheEntries") nPTECacheEntries: Int, @arg(name = "nL2TLBWays") nL2TLBWays: Int, @arg(name = "nL2TLBEntries") nL2TLBEntries: Int, - @arg(name = "nPMPs") nPMPs: Int) { + @arg(name = "nPMPs") nPMPs: Int) { def convert: PTWParameter = PTWParameter( useAsyncReset, hasClockGate, diff --git a/elaborator/src/rocketv/PipelinedMultiplier.scala b/elaborator/src/rocketv/PipelinedMultiplier.scala index 9ef2cb47b..59d06cde3 100644 --- a/elaborator/src/rocketv/PipelinedMultiplier.scala +++ b/elaborator/src/rocketv/PipelinedMultiplier.scala @@ -9,9 +9,9 @@ import org.chipsalliance.t1.elaborator.Elaborator object PipelinedMultiplier extends Elaborator { @main case class PipelinedMultiplierParameterMain( - @arg(name = "useAsyncReset") useAsyncReset: Boolean, - @arg(name = "latency") latency: Int, - @arg(name = "width") width: Int) { + @arg(name = "useAsyncReset") useAsyncReset: Boolean, + @arg(name = "latency") latency: Int, + @arg(name = "width") width: Int) { def convert: PipelinedMultiplierParameter = PipelinedMultiplierParameter( useAsyncReset: Boolean, latency: Int, @@ -19,7 +19,8 @@ object PipelinedMultiplier extends Elaborator { ) } - implicit def PipelinedMultiplierParameterMainParser: ParserForClass[PipelinedMultiplierParameterMain] = ParserForClass[PipelinedMultiplierParameterMain] + implicit def PipelinedMultiplierParameterMainParser: ParserForClass[PipelinedMultiplierParameterMain] = + ParserForClass[PipelinedMultiplierParameterMain] @main def config(@arg(name = "parameter") parameter: PipelinedMultiplierParameterMain) = configImpl(parameter.convert) diff --git a/elaborator/src/rocketv/RVCExpander.scala b/elaborator/src/rocketv/RVCExpander.scala index 2cf3aa7df..df6e9ce5d 100644 --- a/elaborator/src/rocketv/RVCExpander.scala +++ b/elaborator/src/rocketv/RVCExpander.scala @@ -9,7 +9,7 @@ import org.chipsalliance.t1.elaborator.Elaborator object RVCExpander extends Elaborator { @main case class RVCExpanderParameterMain( - @arg(name = "xLen") xLen: Int, + @arg(name = "xLen") xLen: Int, @arg(name = "usingCompressed") usingCompressed: Boolean) { def convert: RVCExpanderParameter = RVCExpanderParameter( xLen, diff --git a/elaborator/src/rocketv/Rocket.scala b/elaborator/src/rocketv/Rocket.scala index f5954500e..183e9fe0e 100644 --- a/elaborator/src/rocketv/Rocket.scala +++ b/elaborator/src/rocketv/Rocket.scala @@ -35,7 +35,7 @@ object Rocket extends Elaborator { @arg(name = "fastLoadWord") fastLoadWord: Boolean, @arg(name = "dcacheNSets") dcacheNSets: Int, @arg(name = "flushOnFenceI") flushOnFenceI: Boolean, - @arg(name = "usingT1") usingT1: Boolean) { + @arg(name = "usingT1") usingT1: Boolean) { def convert: RocketParameter = RocketParameter( useAsyncReset, clockGate, diff --git a/elaborator/src/rocketv/RocketTile.scala b/elaborator/src/rocketv/RocketTile.scala index 753d026a9..514eb0388 100644 --- a/elaborator/src/rocketv/RocketTile.scala +++ b/elaborator/src/rocketv/RocketTile.scala @@ -12,7 +12,7 @@ import org.chipsalliance.t1.elaborator.Elaborator object RocketTile extends Elaborator { implicit object BitSetRead extends TokensReader.Simple[BitSet] { - def shortName = "bitset" + def shortName = "bitset" def read(strs: Seq[String]) = { Right( strs.head @@ -21,13 +21,13 @@ object RocketTile extends Elaborator { if (opt.contains("-")) { val range = opt.split("-") require(range.size == 2) - val from = BigInt(range.head, 16) - val to = BigInt(range.last, 16) + 1 + val from = BigInt(range.head, 16) + val to = BigInt(range.last, 16) + 1 BitSet.fromRange(from, to - from, range.head.length * 4) } else if (opt.contains("+")) { - val range = opt.split("\\+") + val range = opt.split("\\+") require(range.size == 2) - val from = BigInt(range.head, 16) + val from = BigInt(range.head, 16) val length = BigInt(range.last, 16) BitSet.fromRange(from, length, range.head.length * 4) } else { @@ -101,45 +101,45 @@ object RocketTile extends Elaborator { @arg(name = "separateUncachedResp") separateUncachedResp: Boolean, @arg(name = "iCacheNSets") iCacheNSets: Int, @arg(name = "iCacheNWays") iCacheNWays: Int, - @arg(name = "iCachePrefetch") iCachePrefetch: Boolean) { + @arg(name = "iCachePrefetch") iCachePrefetch: Boolean) { def convert: RocketTileParameter = RocketTileParameter( - useAsyncReset: Boolean, - clockGate: Boolean, - instructionSets: Set[String], - priv: String, - hartIdLen: Int, - useBPWatch: Boolean, - mcontextWidth: Int, - scontextWidth: Int, - asidBits: Int, - resetVectorBits: Int, - nBreakpoints: Int, - dtlbNWays: Int, - dtlbNSets: Int, - itlbNSets: Int, - itlbNWays: Int, - itlbNSectors: Int, - itlbNSuperpageEntries: Int, - nPTECacheEntries: Int, - nL2TLBWays: Int, - nL2TLBEntries: Int, - paddrBits: Int, - cacheBlockBytes: Int, - nPMPs: Int, - legal: BitSet, - cacheable: BitSet, - read: BitSet, - write: BitSet, - putPartial: BitSet, - logic: BitSet, - arithmetic: BitSet, - exec: BitSet, - sideEffects: BitSet, - btbEntries: Int, - btbNMatchBits: Int, - btbUpdatesOutOfOrder: Boolean, - nPages: Int, - nRAS: Int, + useAsyncReset: Boolean, + clockGate: Boolean, + instructionSets: Set[String], + priv: String, + hartIdLen: Int, + useBPWatch: Boolean, + mcontextWidth: Int, + scontextWidth: Int, + asidBits: Int, + resetVectorBits: Int, + nBreakpoints: Int, + dtlbNWays: Int, + dtlbNSets: Int, + itlbNSets: Int, + itlbNWays: Int, + itlbNSectors: Int, + itlbNSuperpageEntries: Int, + nPTECacheEntries: Int, + nL2TLBWays: Int, + nL2TLBEntries: Int, + paddrBits: Int, + cacheBlockBytes: Int, + nPMPs: Int, + legal: BitSet, + cacheable: BitSet, + read: BitSet, + write: BitSet, + putPartial: BitSet, + logic: BitSet, + arithmetic: BitSet, + exec: BitSet, + sideEffects: BitSet, + btbEntries: Int, + btbNMatchBits: Int, + btbUpdatesOutOfOrder: Boolean, + nPages: Int, + nRAS: Int, bhtNEntries .lazyZip(bhtCounterLength) .lazyZip(bhtHistoryLength) diff --git a/elaborator/src/rocketv/TLB.scala b/elaborator/src/rocketv/TLB.scala index 1ee1ff458..c7a2e4ef4 100644 --- a/elaborator/src/rocketv/TLB.scala +++ b/elaborator/src/rocketv/TLB.scala @@ -10,7 +10,7 @@ import org.chipsalliance.t1.elaborator.Elaborator object TLB extends Elaborator { implicit object BitSetRead extends TokensReader.Simple[BitSet] { - def shortName = "bitset" + def shortName = "bitset" def read(strs: Seq[String]) = { Right( strs.head @@ -19,13 +19,13 @@ object TLB extends Elaborator { if (opt.contains("-")) { val range = opt.split("-") require(range.size == 2) - val from = BigInt(range.head, 16) - val to = BigInt(range.last, 16) + 1 + val from = BigInt(range.head, 16) + val to = BigInt(range.last, 16) + 1 BitSet.fromRange(from, to - from, range.head.length * 4) } else if (opt.contains("+")) { - val range = opt.split("\\+") + val range = opt.split("\\+") require(range.size == 2) - val from = BigInt(range.head, 16) + val from = BigInt(range.head, 16) val length = BigInt(range.last, 16) BitSet.fromRange(from, length, range.head.length * 4) } else { @@ -64,7 +64,7 @@ object TLB extends Elaborator { @arg(name = "arithmetic") arithmetic: Seq[BitSet], @arg(name = "exec") exec: Seq[BitSet], @arg(name = "sideEffects") sideEffects: Seq[BitSet], - @arg(name = "isITLB") isITLB: Boolean) { + @arg(name = "isITLB") isITLB: Boolean) { def convert: TLBParameter = TLBParameter( useAsyncReset, xLen, @@ -81,18 +81,20 @@ object TLB extends Elaborator { usingVM, usingAtomicsInCache, nPMPs, - PMAChecker.PMACheckerParameterMain( - paddrBits, - legal, - cacheable, - read, - write, - putPartial, - logic, - arithmetic, - exec, - sideEffects - ).convert, + PMAChecker + .PMACheckerParameterMain( + paddrBits, + legal, + cacheable, + read, + write, + putPartial, + logic, + arithmetic, + exec, + sideEffects + ) + .convert, paddrBits, isITLB ) diff --git a/elaborator/src/t1rocket/T1RocketTile.scala b/elaborator/src/t1rocket/T1RocketTile.scala index 3cb8398e2..c618fd7f2 100644 --- a/elaborator/src/t1rocket/T1RocketTile.scala +++ b/elaborator/src/t1rocket/T1RocketTile.scala @@ -13,7 +13,7 @@ import org.chipsalliance.t1.tile.{T1RocketTile, T1RocketTileParameter} // --instructionSets rv32_i --instructionSets rv_a --instructionSets rv_c --instructionSets rv_v --instructionSets Zve32x --instructionSets zvl1024b --cacheBlockBytes 32 --nPMPs 8 --cacheable 80000000-ffffffff --sideEffects 00000000-1fffffff --dcacheNSets 64 --dcacheNWays 4 --dcacheRowBits 32 --iCacheNSets 32 --iCacheNWays 4 --iCachePrefetch false --dLen 256 --vrfBankSize 2 --vrfRamType p0rp1w object T1RocketTile extends Elaborator { implicit object BitSetRead extends TokensReader.Simple[BitSet] { - def shortName = "bitset" + def shortName = "bitset" def read(strs: Seq[String]) = { Right( strs.head @@ -22,13 +22,13 @@ object T1RocketTile extends Elaborator { if (opt.contains("-")) { val range = opt.split("-") require(range.size == 2) - val from = BigInt(range.head, 16) - val to = BigInt(range.last, 16) + 1 + val from = BigInt(range.head, 16) + val to = BigInt(range.last, 16) + 1 BitSet.fromRange(from, to - from, range.head.length * 4) } else if (opt.contains("+")) { - val range = opt.split("\\+") + val range = opt.split("\\+") require(range.size == 2) - val from = BigInt(range.head, 16) + val from = BigInt(range.head, 16) val length = BigInt(range.last, 16) BitSet.fromRange(from, length, range.head.length * 4) } else { @@ -41,12 +41,12 @@ object T1RocketTile extends Elaborator { } implicit object RamTypeRead extends TokensReader.Simple[RamType] { - def shortName = "ramtype" + def shortName = "ramtype" def read(strs: Seq[String]) = { Right( strs.head match { - case "p0rw" => p0rw - case "p0rp1w" => p0rp1w + case "p0rw" => p0rw + case "p0rp1w" => p0rp1w case "p0rwp1rw" => p0rwp1rw } ) @@ -55,36 +55,35 @@ object T1RocketTile extends Elaborator { @main case class T1RocketTileParameterMain( - @arg(name = "instructionSets") instructionSets: Seq[String], - @arg(name = "cacheBlockBytes") cacheBlockBytes: Int, - @arg(name = "nPMPs") nPMPs: Int, - @arg(name = "cacheable") cacheable: BitSet, - @arg(name = "sideEffects") sideEffects: BitSet, - @arg(name = "dcacheNSets") dcacheNSets: Int, - @arg(name = "dcacheNWays") dcacheNWays: Int, - @arg(name = "dcacheRowBits") dcacheRowBits: Int, - @arg(name = "iCacheNSets") iCacheNSets: Int, - @arg(name = "iCacheNWays") iCacheNWays: Int, - @arg(name = "iCachePrefetch") iCachePrefetch: Boolean, - @arg(name = "dLen") dLen: Int, - @arg(name = "vrfBankSize") vrfBankSize: Int, - @arg(name = "vrfRamType") vrfRamType: RamType - ) { + @arg(name = "instructionSets") instructionSets: Seq[String], + @arg(name = "cacheBlockBytes") cacheBlockBytes: Int, + @arg(name = "nPMPs") nPMPs: Int, + @arg(name = "cacheable") cacheable: BitSet, + @arg(name = "sideEffects") sideEffects: BitSet, + @arg(name = "dcacheNSets") dcacheNSets: Int, + @arg(name = "dcacheNWays") dcacheNWays: Int, + @arg(name = "dcacheRowBits") dcacheRowBits: Int, + @arg(name = "iCacheNSets") iCacheNSets: Int, + @arg(name = "iCacheNWays") iCacheNWays: Int, + @arg(name = "iCachePrefetch") iCachePrefetch: Boolean, + @arg(name = "dLen") dLen: Int, + @arg(name = "vrfBankSize") vrfBankSize: Int, + @arg(name = "vrfRamType") vrfRamType: RamType) { def convert: T1RocketTileParameter = T1RocketTileParameter( instructionSets: Seq[String], cacheBlockBytes: Int, - nPMPs: Int, - cacheable: BitSet, - sideEffects: BitSet, - dcacheNSets: Int, - dcacheNWays: Int, - dcacheRowBits: Int, - iCacheNSets: Int, - iCacheNWays: Int, - iCachePrefetch: Boolean, - dLen: Int, - vrfBankSize: Int, - vrfRamType: RamType + nPMPs: Int, + cacheable: BitSet, + sideEffects: BitSet, + dcacheNSets: Int, + dcacheNWays: Int, + dcacheRowBits: Int, + iCacheNSets: Int, + iCacheNWays: Int, + iCachePrefetch: Boolean, + dLen: Int, + vrfBankSize: Int, + vrfRamType: RamType ) } diff --git a/omreader/src/Main.scala b/omreader/src/Main.scala index 97ebcb81c..b7a967260 100644 --- a/omreader/src/Main.scala +++ b/omreader/src/Main.scala @@ -16,13 +16,13 @@ object Main { @main def run( - @arg(name = "mlirbc-file") mlirbcFile: Option[os.Path], + @arg(name = "mlirbc-file") mlirbcFile: Option[os.Path], @arg(name = "dump-methods") dumpMethods: Flag, - @arg(name = "eval") eval: Option[String], + @arg(name = "eval") eval: Option[String] ) = { val t1Reader = (mlirbcFile match { case Some(path) => OMReader.fromFile(path) - case None => + case None => val stdin = new BufferedInputStream(System.in) val bytes = Stream.continually(stdin.read).takeWhile(_ != -1).map(_.toByte).toArray OMReader.fromBytes(bytes) @@ -74,13 +74,12 @@ object Main { object SimpleInputEval { def apply(entry: PanamaCIRCTOMEvaluatorValue, input: String): PanamaCIRCTOMEvaluatorValue = { - input.split("\\.").foldLeft(entry) { - case (obj, field) => - if (field.forall(_.isDigit)) { - obj.asInstanceOf[PanamaCIRCTOMEvaluatorValueList].getElement(field.toLong) - } else { - obj.asInstanceOf[PanamaCIRCTOMEvaluatorValueObject].field(field) - } + input.split("\\.").foldLeft(entry) { case (obj, field) => + if (field.forall(_.isDigit)) { + obj.asInstanceOf[PanamaCIRCTOMEvaluatorValueList].getElement(field.toLong) + } else { + obj.asInstanceOf[PanamaCIRCTOMEvaluatorValueObject].field(field) + } } } } diff --git a/omreaderlib/src/Interface.scala b/omreaderlib/src/Interface.scala index 298b21469..a882aa952 100644 --- a/omreaderlib/src/Interface.scala +++ b/omreaderlib/src/Interface.scala @@ -15,72 +15,73 @@ object OMReader { } } -class OMReader private(mlirbc: Array[Byte]) { - private val cvt = PanamaCIRCTConverter.newWithMlirBc(mlirbc) - private val om = cvt.om() +class OMReader private (mlirbc: Array[Byte]) { + private val cvt = PanamaCIRCTConverter.newWithMlirBc(mlirbc) + private val om = cvt.om() private val evaluator = om.evaluator() def t1Reader: T1Reader = new T1Reader(evaluator, om.newBasePathEmpty) } -class T1Reader private[omreaderlib](evaluator: PanamaCIRCTOMEvaluator, basePath: PanamaCIRCTOMEvaluatorValueBasePath) { +class T1Reader private[omreaderlib] (evaluator: PanamaCIRCTOMEvaluator, basePath: PanamaCIRCTOMEvaluatorValueBasePath) { val (entry, isSubsystem) = { evaluator.instantiate("T1Subsystem_Class", Seq(basePath)) match { case Some(subsystem) => (subsystem, true) - case None => (evaluator.instantiate("T1_Class", Seq(basePath)).get, false) + case None => (evaluator.instantiate("T1_Class", Seq(basePath)).get, false) } } - private val t1 = { + private val t1 = { if (isSubsystem) { entry - .field("om").asInstanceOf[PanamaCIRCTOMEvaluatorValueObject] - .field("t1").asInstanceOf[PanamaCIRCTOMEvaluatorValueObject] - } - else { + .field("om") + .asInstanceOf[PanamaCIRCTOMEvaluatorValueObject] + .field("t1") + .asInstanceOf[PanamaCIRCTOMEvaluatorValueObject] + } else { entry - .field("om").asInstanceOf[PanamaCIRCTOMEvaluatorValueObject] + .field("om") + .asInstanceOf[PanamaCIRCTOMEvaluatorValueObject] } } - def vlen: Long = t1.field("vlen").asInstanceOf[PanamaCIRCTOMEvaluatorValuePrimitiveInteger].integer - def dlen: Long = t1.field("dlen").asInstanceOf[PanamaCIRCTOMEvaluatorValuePrimitiveInteger].integer + def vlen: Long = t1.field("vlen").asInstanceOf[PanamaCIRCTOMEvaluatorValuePrimitiveInteger].integer + def dlen: Long = t1.field("dlen").asInstanceOf[PanamaCIRCTOMEvaluatorValuePrimitiveInteger].integer private def decoderInstructionsJsonImpl: ujson.Value = { - val decoder = t1.field("decoder").asInstanceOf[PanamaCIRCTOMEvaluatorValueObject] + val decoder = t1.field("decoder").asInstanceOf[PanamaCIRCTOMEvaluatorValueObject] val instructions = decoder.field("instructions").asInstanceOf[PanamaCIRCTOMEvaluatorValueList] instructions.elements.map(instruction => { - val instr = instruction.asInstanceOf[PanamaCIRCTOMEvaluatorValueObject] + val instr = instruction.asInstanceOf[PanamaCIRCTOMEvaluatorValueObject] val attributes = instr.field("attributes").asInstanceOf[PanamaCIRCTOMEvaluatorValueList] ujson.Obj( "attributes" -> attributes.elements.map(attribute => { - val attr = attribute.asInstanceOf[PanamaCIRCTOMEvaluatorValueObject] + val attr = attribute.asInstanceOf[PanamaCIRCTOMEvaluatorValueObject] val description = attr.field("description").asInstanceOf[PanamaCIRCTOMEvaluatorValuePrimitiveString].toString - val identifier = attr.field("identifier").asInstanceOf[PanamaCIRCTOMEvaluatorValuePrimitiveString].toString - val value = attr.field("value").asInstanceOf[PanamaCIRCTOMEvaluatorValuePrimitiveString].toString + val identifier = attr.field("identifier").asInstanceOf[PanamaCIRCTOMEvaluatorValuePrimitiveString].toString + val value = attr.field("value").asInstanceOf[PanamaCIRCTOMEvaluatorValuePrimitiveString].toString ujson.Obj( "description" -> description, - "identifier" -> identifier, - "value" -> value + "identifier" -> identifier, + "value" -> value ) }) ) }) } - def decoderInstructionsJson: String = ujson.write(decoderInstructionsJsonImpl) - def decoderInstructionsJsonPretty: String = ujson.write(decoderInstructionsJsonImpl, 2) - def extensionsJson: String = { + def decoderInstructionsJson: String = ujson.write(decoderInstructionsJsonImpl) + def decoderInstructionsJsonPretty: String = ujson.write(decoderInstructionsJsonImpl, 2) + def extensionsJson: String = { val extensions = t1.field("extensions").asInstanceOf[PanamaCIRCTOMEvaluatorValueList] - val j = extensions.elements.map(_.asInstanceOf[PanamaCIRCTOMEvaluatorValuePrimitiveString].toString) + val j = extensions.elements.map(_.asInstanceOf[PanamaCIRCTOMEvaluatorValuePrimitiveString].toString) ujson.write(j) } - def march: String = t1.field("march").asInstanceOf[PanamaCIRCTOMEvaluatorValuePrimitiveString].toString + def march: String = t1.field("march").asInstanceOf[PanamaCIRCTOMEvaluatorValuePrimitiveString].toString def dumpMethods(): Unit = { - val mirror = runtimeMirror(getClass.getClassLoader).reflect(this) - val methods = typeOf[T1Reader].decls.toList.filter( - m => m.isPublic && m.isMethod && !m.isConstructor && !m.asMethod.isGetter - ) + val mirror = runtimeMirror(getClass.getClassLoader).reflect(this) + val methods = + typeOf[T1Reader].decls.toList.filter(m => m.isPublic && m.isMethod && !m.isConstructor && !m.asMethod.isGetter) methods.foreach(method => { if (!method.name.toString.startsWith("dump")) { var value = mirror.reflectMethod(method.asMethod)().toString.replace("\n", "\\n") diff --git a/rocketemu/src/AXI4SlaveAgent.scala b/rocketemu/src/AXI4SlaveAgent.scala index 8c5937476..6a3597d0c 100644 --- a/rocketemu/src/AXI4SlaveAgent.scala +++ b/rocketemu/src/AXI4SlaveAgent.scala @@ -7,18 +7,38 @@ package org.chipsalliance.t1.rocketv.dpi import chisel3._ import chisel3.util.circt.dpi.{RawClockedVoidFunctionCall, RawUnclockedNonVoidFunctionCall} import chisel3.util.{isPow2, log2Ceil} -import org.chipsalliance.amba.axi4.bundle.{ARChannel, ARFlowControl, AWChannel, AWFlowControl, AXI4BundleParameter, AXI4ROIrrevocableVerilog, AXI4RWIrrevocableVerilog, AXI4WOIrrevocableVerilog, BChannel, BFlowControl, RChannel, RFlowControl, WChannel, WFlowControl} +import org.chipsalliance.amba.axi4.bundle.{ + ARChannel, + ARFlowControl, + AWChannel, + AWFlowControl, + AXI4BundleParameter, + AXI4ROIrrevocableVerilog, + AXI4RWIrrevocableVerilog, + AXI4WOIrrevocableVerilog, + BChannel, + BFlowControl, + RChannel, + RFlowControl, + WChannel, + WFlowControl +} -case class AXI4SlaveAgentParameter(name: String, axiParameter: AXI4BundleParameter, outstanding: Int, readPayloadSize: Int, writePayloadSize: Int) +case class AXI4SlaveAgentParameter( + name: String, + axiParameter: AXI4BundleParameter, + outstanding: Int, + readPayloadSize: Int, + writePayloadSize: Int) class AXI4SlaveAgentInterface(parameter: AXI4SlaveAgentParameter) extends Bundle { val clock: Clock = Input(Clock()) val reset: Reset = Input(Reset()) - val channelId: UInt = Input(Const(UInt(64.W))) + val channelId: UInt = Input(Const(UInt(64.W))) // don't issue read DPI - val gateRead: Bool = Input(Bool()) + val gateRead: Bool = Input(Bool()) // don't issue write DPI - val gateWrite: Bool = Input(Bool()) + val gateWrite: Bool = Input(Bool()) val channel = Flipped( org.chipsalliance.amba.axi4.bundle.verilog.irrevocable(parameter.axiParameter) ) @@ -30,7 +50,7 @@ class WritePayload(length: Int, dataWidth: Int) extends Bundle { val strb = Vec(length, UInt(math.max(8, dataWidth / 8).W)) } -class ReadPayload(length: Int,dataWidth: Int) extends Bundle { +class ReadPayload(length: Int, dataWidth: Int) extends Bundle { val data = Vec(length, UInt(dataWidth.W)) } @@ -51,50 +71,55 @@ class AXI4SlaveAgent(parameter: AXI4SlaveAgentParameter) private class WriteManager( channel: AWChannel with AWFlowControl with WChannel with WFlowControl with BChannel with BFlowControl) { withClockAndReset(io.clock, io.reset) { + /** There is an aw in the register. */ val awIssued = RegInit(false.B) + /** There is a w in the register. */ val last = RegInit(false.B) /** memory to store the write payload - * @todo limit the payload size based on the RTL configuration. + * @todo + * limit the payload size based on the RTL configuration. */ - val writePayload = RegInit(0.U.asTypeOf(new WritePayload(parameter.writePayloadSize, parameter.axiParameter.dataWidth))) + val writePayload = + RegInit(0.U.asTypeOf(new WritePayload(parameter.writePayloadSize, parameter.axiParameter.dataWidth))) + /** AWID, latch at AW fire, used at B fire. */ - val awid = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWID))) - val awaddr = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWADDR))) - val awlen = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWLEN))) - val awsize = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWSIZE))) - val awburst = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWBURST))) - val awlock = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWLOCK))) - val awcache = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWCACHE))) - val awprot = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWPROT))) - val awqos = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWQOS))) + val awid = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWID))) + val awaddr = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWADDR))) + val awlen = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWLEN))) + val awsize = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWSIZE))) + val awburst = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWBURST))) + val awlock = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWLOCK))) + val awcache = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWCACHE))) + val awprot = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWPROT))) + val awqos = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWQOS))) val awregion = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWREGION))) - val awuser = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWUSER))) + val awuser = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWUSER))) /** index the payload, used to write [[writePayload]] */ - val writeIdx = RegInit(0.U.asTypeOf(UInt(8.W))) - val bFire = channel.BREADY && channel.BVALID - val awFire = channel.AWREADY && channel.AWVALID + val writeIdx = RegInit(0.U.asTypeOf(UInt(8.W))) + val bFire = channel.BREADY && channel.BVALID + val awFire = channel.AWREADY && channel.AWVALID val wLastFire = channel.WVALID && channel.WREADY && channel.WLAST - val awExist = channel.AWVALID || awIssued - val wExist = channel.WVALID && channel.WLAST || last + val awExist = channel.AWVALID || awIssued + val wExist = channel.WVALID && channel.WLAST || last // AW channel.AWREADY := !awIssued || (wExist && channel.BREADY) when(channel.AWREADY && channel.AWVALID) { - awid := channel.AWID - awaddr := channel.AWADDR - awlen := channel.AWLEN - awsize := channel.AWSIZE - awburst := channel.AWBURST - awlock := channel.AWLOCK - awcache := channel.AWCACHE - awprot := channel.AWPROT - awqos := channel.AWQOS + awid := channel.AWID + awaddr := channel.AWADDR + awlen := channel.AWLEN + awsize := channel.AWSIZE + awburst := channel.AWBURST + awlock := channel.AWLOCK + awcache := channel.AWCACHE + awprot := channel.AWPROT + awqos := channel.AWQOS awregion := channel.AWREGION - awuser := channel.AWUSER + awuser := channel.AWUSER } when(awFire ^ bFire) { awIssued := awFire @@ -104,11 +129,11 @@ class AXI4SlaveAgent(parameter: AXI4SlaveAgentParameter) val writePayloadUpdate = WireDefault(writePayload) channel.WREADY := !last || (awExist && channel.BREADY) when(channel.WVALID && channel.WREADY) { - writePayload.data(writeIdx) := channel.WDATA + writePayload.data(writeIdx) := channel.WDATA writePayloadUpdate.data(writeIdx) := channel.WDATA - writePayload.strb(writeIdx) := channel.WSTRB.pad(writePayload.strb.getWidth) + writePayload.strb(writeIdx) := channel.WSTRB.pad(writePayload.strb.getWidth) writePayloadUpdate.strb(writeIdx) := channel.WSTRB.pad(writePayload.strb.getWidth) - writeIdx := writeIdx + 1.U + writeIdx := writeIdx + 1.U when(channel.WLAST) { writeIdx := 0.U } @@ -119,9 +144,9 @@ class AXI4SlaveAgent(parameter: AXI4SlaveAgentParameter) // B channel.BVALID := awExist && wExist - channel.BID := Mux(awIssued, awid, channel.AWID) - channel.BRESP := 0.U(2.W) // OK - channel.BUSER := Mux(awIssued, awuser, channel.AWUSER) + channel.BID := Mux(awIssued, awid, channel.AWID) + channel.BRESP := 0.U(2.W) // OK + channel.BUSER := Mux(awIssued, awuser, channel.AWUSER) when(channel.BVALID && channel.BREADY) { RawClockedVoidFunctionCall(s"axi_write_${parameter.name}")( io.clock, @@ -147,24 +172,28 @@ class AXI4SlaveAgent(parameter: AXI4SlaveAgentParameter) private class ReadManager(channel: ARChannel with ARFlowControl with RChannel with RFlowControl) { withClockAndReset(io.clock, io.reset) { class CAMValue extends Bundle { - val arid = UInt(16.W) - val arlen = UInt(8.W) - val readPayload = new ReadPayload(parameter.readPayloadSize, parameter.axiParameter.dataWidth) + val arid = UInt(16.W) + val arlen = UInt(8.W) + val readPayload = new ReadPayload(parameter.readPayloadSize, parameter.axiParameter.dataWidth) val readPayloadIndex = UInt(8.W) - val valid = Bool() + val valid = Bool() } + /** CAM to maintain order of read requests. This is maintained as FIFO. */ val cam: Vec[CAMValue] = RegInit(0.U.asTypeOf(Vec(parameter.outstanding, new CAMValue))) require(isPow2(parameter.outstanding), "Need to handle pointers") val arPtr = RegInit(0.U.asTypeOf(UInt(log2Ceil(parameter.outstanding).W))) - val rPtr = RegInit(0.U.asTypeOf(UInt(log2Ceil(parameter.outstanding).W))) + val rPtr = RegInit(0.U.asTypeOf(UInt(log2Ceil(parameter.outstanding).W))) // AR channel.ARREADY := !cam(arPtr).valid when(channel.ARREADY && channel.ARVALID) { - cam(arPtr).arid := channel.ARID - cam(arPtr).arlen := channel.ARLEN - cam(arPtr).readPayload := RawUnclockedNonVoidFunctionCall(s"axi_read_${parameter.name}", new ReadPayload(parameter.readPayloadSize, parameter.axiParameter.dataWidth))( + cam(arPtr).arid := channel.ARID + cam(arPtr).arlen := channel.ARLEN + cam(arPtr).readPayload := RawUnclockedNonVoidFunctionCall( + s"axi_read_${parameter.name}", + new ReadPayload(parameter.readPayloadSize, parameter.axiParameter.dataWidth) + )( when.cond && !io.gateRead, io.channelId, channel.ARID.asTypeOf(UInt(64.W)), @@ -179,23 +208,23 @@ class AXI4SlaveAgent(parameter: AXI4SlaveAgentParameter) channel.ARREGION.asTypeOf(UInt(64.W)) ) cam(arPtr).readPayloadIndex := 0.U - cam(arPtr).valid := true.B - arPtr := arPtr + 1.U + cam(arPtr).valid := true.B + arPtr := arPtr + 1.U } // R channel.RVALID := cam(rPtr).valid - channel.RID := cam(rPtr).arid - channel.RDATA := cam(rPtr).readPayload.data(cam(rPtr).readPayloadIndex) - channel.RRESP := 0.U // OK - channel.RLAST := (cam(rPtr).arlen === cam(rPtr).readPayloadIndex) && cam(rPtr).valid - channel.RUSER := DontCare + channel.RID := cam(rPtr).arid + channel.RDATA := cam(rPtr).readPayload.data(cam(rPtr).readPayloadIndex) + channel.RRESP := 0.U // OK + channel.RLAST := (cam(rPtr).arlen === cam(rPtr).readPayloadIndex) && cam(rPtr).valid + channel.RUSER := DontCare when(channel.RREADY && channel.RVALID) { // increase index cam(rPtr).readPayloadIndex := cam(rPtr).readPayloadIndex + 1.U when(channel.RLAST) { cam(rPtr).valid := false.B - rPtr := rPtr + 1.U + rPtr := rPtr + 1.U } } } diff --git a/rocketemu/src/TestBench.scala b/rocketemu/src/TestBench.scala index e22b93c05..aae7e9a94 100644 --- a/rocketemu/src/TestBench.scala +++ b/rocketemu/src/TestBench.scala @@ -6,7 +6,7 @@ package org.chipsalliance.t1.rocketv import chisel3._ import chisel3.experimental.{ExtModule, SerializableModuleGenerator} import chisel3.experimental.dataview.DataViewable -import chisel3.probe.{Probe, define} +import chisel3.probe.{define, Probe} import chisel3.util.{log2Ceil, HasExtModuleInline, PopCount, UIntToOH, Valid} import chisel3.util.circt.dpi.RawUnclockedNonVoidFunctionCall import org.chipsalliance.amba.axi4.bundle._ @@ -40,12 +40,12 @@ class TestBench(generator: SerializableModuleGenerator[RocketTile, RocketTilePar |endmodule |""".stripMargin ) - val clock = IO(Output(Bool())) - val reset = IO(Output(Bool())) + val clock = IO(Output(Bool())) + val reset = IO(Output(Bool())) }) val clock: Clock = clockGen.clock.asClock - val reset: Bool = clockGen.reset + val reset: Bool = clockGen.reset override protected def implicitClock: Clock = clockGen.clock.asClock override protected def implicitReset: Reset = clockGen.reset @@ -61,13 +61,13 @@ class TestBench(generator: SerializableModuleGenerator[RocketTile, RocketTilePar } val dut: RocketTile = withClockAndReset(clock, reset)(Module(generator.module())) - dut.io.clock := clockGen.clock.asClock - dut.io.reset := clockGen.reset - dut.io.hartid := 0.U - dut.io.debug := 0.U - dut.io.mtip := 0.U - dut.io.meip := 0.U - dut.io.msip := 0.U + dut.io.clock := clockGen.clock.asClock + dut.io.reset := clockGen.reset + dut.io.hartid := 0.U + dut.io.debug := 0.U + dut.io.mtip := 0.U + dut.io.meip := 0.U + dut.io.msip := 0.U dut.io.buserror := 0.U // get resetVector from simulator @@ -75,10 +75,14 @@ class TestBench(generator: SerializableModuleGenerator[RocketTile, RocketTilePar // output probes val rocketProbe = probe.read(dut.io.rocketProbe) - when(rocketProbe.rfWen && rocketProbe.rfWaddr =/= 0.U)(printf(cf"""{"event":"RegWrite","addr":${rocketProbe.rfWaddr},"data":${rocketProbe.rfWdata},"cycle":${simulationTime}}\n""")) + when(rocketProbe.rfWen && rocketProbe.rfWaddr =/= 0.U)( + printf( + cf"""{"event":"RegWrite","addr":${rocketProbe.rfWaddr},"data":${rocketProbe.rfWdata},"cycle":${simulationTime}}\n""" + ) + ) // Memory Drivers - val instFetchAXI = dut.io.instructionFetchAXI.viewAs[AXI4ROIrrevocableVerilog] + val instFetchAXI = dut.io.instructionFetchAXI.viewAs[AXI4ROIrrevocableVerilog] val instFetchAgent = Module( new AXI4SlaveAgent( AXI4SlaveAgentParameter( @@ -94,12 +98,12 @@ class TestBench(generator: SerializableModuleGenerator[RocketTile, RocketTilePar case io: AXI4ROIrrevocableVerilog => io <> instFetchAXI } instFetchAgent.io.clock := clock - instFetchAgent.io.reset := reset + instFetchAgent.io.reset := reset instFetchAgent.io.channelId := 0.U - instFetchAgent.io.gateRead := false.B + instFetchAgent.io.gateRead := false.B instFetchAgent.io.gateWrite := false.B - val loadStoreAXI = dut.io.loadStoreAXI.viewAs[AXI4RWIrrevocableVerilog] + val loadStoreAXI = dut.io.loadStoreAXI.viewAs[AXI4RWIrrevocableVerilog] val loadStoreAgent = Module( new AXI4SlaveAgent( AXI4SlaveAgentParameter( @@ -115,8 +119,8 @@ class TestBench(generator: SerializableModuleGenerator[RocketTile, RocketTilePar case io: AXI4RWIrrevocableVerilog => io <> loadStoreAXI } loadStoreAgent.io.clock := clock - loadStoreAgent.io.reset := reset + loadStoreAgent.io.reset := reset loadStoreAgent.io.channelId := 0.U - loadStoreAgent.io.gateRead := false.B + loadStoreAgent.io.gateRead := false.B loadStoreAgent.io.gateWrite := false.B } diff --git a/t1emu/src/AXI4SlaveAgent.scala b/t1emu/src/AXI4SlaveAgent.scala index 5767714b6..da4601c2d 100644 --- a/t1emu/src/AXI4SlaveAgent.scala +++ b/t1emu/src/AXI4SlaveAgent.scala @@ -7,18 +7,38 @@ package org.chipsalliance.t1.t1emu.dpi import chisel3._ import chisel3.util.circt.dpi.{RawClockedVoidFunctionCall, RawUnclockedNonVoidFunctionCall} import chisel3.util.{isPow2, log2Ceil} -import org.chipsalliance.amba.axi4.bundle.{ARChannel, ARFlowControl, AWChannel, AWFlowControl, AXI4BundleParameter, AXI4ROIrrevocableVerilog, AXI4RWIrrevocableVerilog, AXI4WOIrrevocableVerilog, BChannel, BFlowControl, RChannel, RFlowControl, WChannel, WFlowControl} +import org.chipsalliance.amba.axi4.bundle.{ + ARChannel, + ARFlowControl, + AWChannel, + AWFlowControl, + AXI4BundleParameter, + AXI4ROIrrevocableVerilog, + AXI4RWIrrevocableVerilog, + AXI4WOIrrevocableVerilog, + BChannel, + BFlowControl, + RChannel, + RFlowControl, + WChannel, + WFlowControl +} -case class AXI4SlaveAgentParameter(name: String, axiParameter: AXI4BundleParameter, outstanding: Int, readPayloadSize: Int, writePayloadSize: Int) +case class AXI4SlaveAgentParameter( + name: String, + axiParameter: AXI4BundleParameter, + outstanding: Int, + readPayloadSize: Int, + writePayloadSize: Int) class AXI4SlaveAgentInterface(parameter: AXI4SlaveAgentParameter) extends Bundle { val clock: Clock = Input(Clock()) val reset: Reset = Input(Reset()) - val channelId: UInt = Input(Const(UInt(64.W))) + val channelId: UInt = Input(Const(UInt(64.W))) // don't issue read DPI - val gateRead: Bool = Input(Bool()) + val gateRead: Bool = Input(Bool()) // don't issue write DPI - val gateWrite: Bool = Input(Bool()) + val gateWrite: Bool = Input(Bool()) val channel = Flipped( org.chipsalliance.amba.axi4.bundle.verilog.irrevocable(parameter.axiParameter) ) @@ -31,7 +51,7 @@ class WritePayload(length: Int, dataWidth: Int) extends Bundle { } // TODO: consider adding the latency of the read transaction -class ReadPayload(length: Int,dataWidth: Int) extends Bundle { +class ReadPayload(length: Int, dataWidth: Int) extends Bundle { val data = Vec(length, UInt(dataWidth.W)) } @@ -52,50 +72,55 @@ class AXI4SlaveAgent(parameter: AXI4SlaveAgentParameter) private class WriteManager( channel: AWChannel with AWFlowControl with WChannel with WFlowControl with BChannel with BFlowControl) { withClockAndReset(io.clock, io.reset) { + /** There is an aw in the register. */ val awIssued = RegInit(false.B) + /** There is a w in the register. */ val last = RegInit(false.B) /** memory to store the write payload - * @todo limit the payload size based on the RTL configuration. + * @todo + * limit the payload size based on the RTL configuration. */ - val writePayload = RegInit(0.U.asTypeOf(new WritePayload(parameter.writePayloadSize, parameter.axiParameter.dataWidth))) + val writePayload = + RegInit(0.U.asTypeOf(new WritePayload(parameter.writePayloadSize, parameter.axiParameter.dataWidth))) + /** AWID, latch at AW fire, used at B fire. */ - val awid = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWID))) - val awaddr = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWADDR))) - val awlen = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWLEN))) - val awsize = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWSIZE))) - val awburst = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWBURST))) - val awlock = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWLOCK))) - val awcache = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWCACHE))) - val awprot = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWPROT))) - val awqos = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWQOS))) + val awid = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWID))) + val awaddr = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWADDR))) + val awlen = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWLEN))) + val awsize = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWSIZE))) + val awburst = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWBURST))) + val awlock = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWLOCK))) + val awcache = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWCACHE))) + val awprot = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWPROT))) + val awqos = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWQOS))) val awregion = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWREGION))) - val awuser = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWUSER))) + val awuser = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWUSER))) /** index the payload, used to write [[writePayload]] */ - val writeIdx = RegInit(0.U.asTypeOf(UInt(8.W))) - val bFire = channel.BREADY && channel.BVALID - val awFire = channel.AWREADY && channel.AWVALID + val writeIdx = RegInit(0.U.asTypeOf(UInt(8.W))) + val bFire = channel.BREADY && channel.BVALID + val awFire = channel.AWREADY && channel.AWVALID val wLastFire = channel.WVALID && channel.WREADY && channel.WLAST - val awExist = channel.AWVALID || awIssued - val wExist = channel.WVALID && channel.WLAST || last + val awExist = channel.AWVALID || awIssued + val wExist = channel.WVALID && channel.WLAST || last // AW channel.AWREADY := !awIssued || (wExist && channel.BREADY) when(channel.AWREADY && channel.AWVALID) { - awid := channel.AWID - awaddr := channel.AWADDR - awlen := channel.AWLEN - awsize := channel.AWSIZE - awburst := channel.AWBURST - awlock := channel.AWLOCK - awcache := channel.AWCACHE - awprot := channel.AWPROT - awqos := channel.AWQOS + awid := channel.AWID + awaddr := channel.AWADDR + awlen := channel.AWLEN + awsize := channel.AWSIZE + awburst := channel.AWBURST + awlock := channel.AWLOCK + awcache := channel.AWCACHE + awprot := channel.AWPROT + awqos := channel.AWQOS awregion := channel.AWREGION - awuser := channel.AWUSER + awuser := channel.AWUSER } when(awFire ^ bFire) { awIssued := awFire @@ -105,11 +130,11 @@ class AXI4SlaveAgent(parameter: AXI4SlaveAgentParameter) val writePayloadUpdate = WireDefault(writePayload) channel.WREADY := !last || (awExist && channel.BREADY) when(channel.WVALID && channel.WREADY) { - writePayload.data(writeIdx) := channel.WDATA + writePayload.data(writeIdx) := channel.WDATA writePayloadUpdate.data(writeIdx) := channel.WDATA - writePayload.strb(writeIdx) := channel.WSTRB.pad(writePayload.strb.getWidth) + writePayload.strb(writeIdx) := channel.WSTRB.pad(writePayload.strb.getWidth) writePayloadUpdate.strb(writeIdx) := channel.WSTRB.pad(writePayload.strb.getWidth) - writeIdx := writeIdx + 1.U + writeIdx := writeIdx + 1.U when(channel.WLAST) { writeIdx := 0.U } @@ -120,9 +145,9 @@ class AXI4SlaveAgent(parameter: AXI4SlaveAgentParameter) // B channel.BVALID := awExist && wExist - channel.BID := Mux(awIssued, awid, channel.AWID) - channel.BRESP := 0.U(2.W) // OK - channel.BUSER := DontCare + channel.BID := Mux(awIssued, awid, channel.AWID) + channel.BRESP := 0.U(2.W) // OK + channel.BUSER := DontCare // TODO: add latency to the write transaction reply when(channel.BVALID && channel.BREADY) { RawClockedVoidFunctionCall(s"axi_write_${parameter.name}")( @@ -149,24 +174,28 @@ class AXI4SlaveAgent(parameter: AXI4SlaveAgentParameter) private class ReadManager(channel: ARChannel with ARFlowControl with RChannel with RFlowControl) { withClockAndReset(io.clock, io.reset) { class CAMValue extends Bundle { - val arid = UInt(16.W) - val arlen = UInt(8.W) - val readPayload = new ReadPayload(parameter.readPayloadSize, parameter.axiParameter.dataWidth) + val arid = UInt(16.W) + val arlen = UInt(8.W) + val readPayload = new ReadPayload(parameter.readPayloadSize, parameter.axiParameter.dataWidth) val readPayloadIndex = UInt(8.W) - val valid = Bool() + val valid = Bool() } + /** CAM to maintain order of read requests. This is maintained as FIFO. */ val cam: Vec[CAMValue] = RegInit(0.U.asTypeOf(Vec(parameter.outstanding, new CAMValue))) require(isPow2(parameter.outstanding), "Need to handle pointers") val arPtr = RegInit(0.U.asTypeOf(UInt(log2Ceil(parameter.outstanding).W))) - val rPtr = RegInit(0.U.asTypeOf(UInt(log2Ceil(parameter.outstanding).W))) + val rPtr = RegInit(0.U.asTypeOf(UInt(log2Ceil(parameter.outstanding).W))) // AR channel.ARREADY := !cam(arPtr).valid when(channel.ARREADY && channel.ARVALID) { - cam(arPtr).arid := channel.ARID - cam(arPtr).arlen := channel.ARLEN - cam(arPtr).readPayload := RawUnclockedNonVoidFunctionCall(s"axi_read_${parameter.name}", new ReadPayload(parameter.readPayloadSize, parameter.axiParameter.dataWidth))( + cam(arPtr).arid := channel.ARID + cam(arPtr).arlen := channel.ARLEN + cam(arPtr).readPayload := RawUnclockedNonVoidFunctionCall( + s"axi_read_${parameter.name}", + new ReadPayload(parameter.readPayloadSize, parameter.axiParameter.dataWidth) + )( when.cond && !io.gateRead, io.channelId, channel.ARID.asTypeOf(UInt(64.W)), @@ -181,23 +210,23 @@ class AXI4SlaveAgent(parameter: AXI4SlaveAgentParameter) channel.ARREGION.asTypeOf(UInt(64.W)) ) cam(arPtr).readPayloadIndex := 0.U - cam(arPtr).valid := true.B - arPtr := arPtr + 1.U + cam(arPtr).valid := true.B + arPtr := arPtr + 1.U } // R channel.RVALID := cam(rPtr).valid - channel.RID := cam(rPtr).arid - channel.RDATA := cam(rPtr).readPayload.data(cam(rPtr).readPayloadIndex) - channel.RRESP := 0.U // OK - channel.RLAST := (cam(rPtr).arlen === cam(rPtr).readPayloadIndex) && cam(rPtr).valid - channel.RUSER := DontCare + channel.RID := cam(rPtr).arid + channel.RDATA := cam(rPtr).readPayload.data(cam(rPtr).readPayloadIndex) + channel.RRESP := 0.U // OK + channel.RLAST := (cam(rPtr).arlen === cam(rPtr).readPayloadIndex) && cam(rPtr).valid + channel.RUSER := DontCare when(channel.RREADY && channel.RVALID) { // increase index cam(rPtr).readPayloadIndex := cam(rPtr).readPayloadIndex + 1.U when(channel.RLAST) { cam(rPtr).valid := false.B - rPtr := rPtr + 1.U + rPtr := rPtr + 1.U } } } diff --git a/t1emu/src/TestBench.scala b/t1emu/src/TestBench.scala index d623263ef..cf705fb1e 100644 --- a/t1emu/src/TestBench.scala +++ b/t1emu/src/TestBench.scala @@ -5,10 +5,14 @@ package org.chipsalliance.t1.t1emu import chisel3._ import chisel3.experimental.dataview.DataViewable -import chisel3.experimental.hierarchy.{Instance, Instantiate, instantiable, public} +import chisel3.experimental.hierarchy.{instantiable, public, Instance, Instantiate} import chisel3.experimental.{ExtModule, SerializableModuleGenerator} import chisel3.properties.{AnyClassType, Class, ClassType, Property} -import chisel3.util.circt.dpi.{RawClockedNonVoidFunctionCall, RawClockedVoidFunctionCall, RawUnclockedNonVoidFunctionCall} +import chisel3.util.circt.dpi.{ + RawClockedNonVoidFunctionCall, + RawClockedVoidFunctionCall, + RawUnclockedNonVoidFunctionCall +} import chisel3.util.{HasExtModuleInline, PopCount, UIntToOH, Valid} import org.chipsalliance.amba.axi4.bundle._ import org.chipsalliance.t1.t1emu.dpi._ @@ -17,7 +21,7 @@ import org.chipsalliance.t1.rtl.{T1, T1Parameter} @instantiable class TestBenchOM extends Class { @public - val t1 = IO(Output(Property[AnyClassType]())) + val t1 = IO(Output(Property[AnyClassType]())) @public val t1In = IO(Input(Property[AnyClassType]())) t1 := t1In @@ -29,9 +33,9 @@ class TestBench(generator: SerializableModuleGenerator[T1, T1Parameter]) with ImplicitReset { layer.enable(layers.Verification) val omInstance: Instance[TestBenchOM] = Instantiate(new TestBenchOM) - val omType: ClassType = omInstance.toDefinition.getClassType + val omType: ClassType = omInstance.toDefinition.getClassType @public - val om: Property[ClassType] = IO(Output(Property[omType.Type]())) + val om: Property[ClassType] = IO(Output(Property[omType.Type]())) om := omInstance.getPropertyReference val clockGen = Module(new ExtModule with HasExtModuleInline { @@ -70,11 +74,11 @@ class TestBench(generator: SerializableModuleGenerator[T1, T1Parameter]) |endmodule |""".stripMargin ) - val clock = IO(Output(Bool())) - val reset = IO(Output(Bool())) + val clock = IO(Output(Bool())) + val reset = IO(Output(Bool())) }) - def clock = clockGen.clock.asClock - def reset = clockGen.reset + def clock = clockGen.clock.asClock + def reset = clockGen.reset override def implicitClock = clockGen.clock.asClock override def implicitReset = clockGen.reset val dut: Instance[T1] = generator.instance() @@ -82,8 +86,8 @@ class TestBench(generator: SerializableModuleGenerator[T1, T1Parameter]) val simulationTime: UInt = RegInit(0.U(64.W)) simulationTime := simulationTime + 1.U - dut.io.clock := clockGen.clock.asClock - dut.io.reset := clockGen.reset + dut.io.clock := clockGen.clock.asClock + dut.io.reset := clockGen.reset omInstance.t1In := Property(dut.io.om.asAnyClassType) // Instruction Drivers @@ -99,23 +103,23 @@ class TestBench(generator: SerializableModuleGenerator[T1, T1Parameter]) } // uint32_t -> svBitVecVal -> reference type with 7 length. - class Issue extends Bundle { + class Issue extends Bundle { val instruction: UInt = UInt(32.W) val src1Data: UInt = UInt(32.W) val src2Data: UInt = UInt(32.W) // mstatus, vstatus? - val vtype: UInt = UInt(32.W) - val vl: UInt = UInt(32.W) + val vtype: UInt = UInt(32.W) + val vl: UInt = UInt(32.W) // vlenb - val vstart: UInt = UInt(32.W) + val vstart: UInt = UInt(32.W) // vxrm, vxsat are merged to vcsr - val vcsr: UInt = UInt(32.W) + val vcsr: UInt = UInt(32.W) // meta is used to control the simulation. // 0 is reserved, aka not valid // 1 is normal, it's a valid instruction // 2 is fence, it will request // others are exit, will end the simulation immediately - val meta: UInt = UInt(32.W) + val meta: UInt = UInt(32.W) } class Retire extends Bundle { val rd: UInt = UInt(32.W) @@ -125,37 +129,38 @@ class TestBench(generator: SerializableModuleGenerator[T1, T1Parameter]) } // X gated by didIssue val issue = WireDefault(0.U.asTypeOf(new Issue)) - val fence = RegInit(false.B) - val outstanding = RegInit(0.U(4.W)) + val fence = RegInit(false.B) + val outstanding = RegInit(0.U(4.W)) val hasBeenReset = RegNext(true.B, false.B) val doIssue: Bool = dut.io.issue.ready && !fence && hasBeenReset outstanding := outstanding + (RegNext(doIssue) && (issue.meta === 1.U)) - dut.io.issue.valid // TODO: refactor driver to spawn 3 scoreboards for record different retirement. val t1Probe = probe.read(dut.io.t1Probe) - fence := Mux(RegNext(doIssue), issue.meta === 2.U, fence && !t1Probe.retireValid && !(outstanding === 0.U)) - issue := Mux(doIssue, + fence := Mux(RegNext(doIssue), issue.meta === 2.U, fence && !t1Probe.retireValid && !(outstanding === 0.U)) + issue := Mux( + doIssue, RawClockedNonVoidFunctionCall("issue_vector_instruction", new Issue)( clock, - doIssue, + doIssue ), 0.U.asTypeOf(new Issue) ) dut.io.issue.bits.instruction := issue.instruction - dut.io.issue.bits.rs1Data := issue.src1Data - dut.io.issue.bits.rs2Data := issue.src2Data - dut.io.issue.bits.vtype := issue.vtype - dut.io.issue.bits.vl := issue.vl - dut.io.issue.bits.vstart := issue.vstart - dut.io.issue.bits.vcsr := issue.vcsr - dut.io.issue.valid := issue.meta === 1.U + dut.io.issue.bits.rs1Data := issue.src1Data + dut.io.issue.bits.rs2Data := issue.src2Data + dut.io.issue.bits.vtype := issue.vtype + dut.io.issue.bits.vl := issue.vl + dut.io.issue.bits.vstart := issue.vstart + dut.io.issue.bits.vcsr := issue.vcsr + dut.io.issue.valid := issue.meta === 1.U when(issue.meta =/= 0.U && issue.meta =/= 1.U && issue.meta =/= 2.U) { stop(cf"""{"event":"SimulationStop","reason": ${issue.meta},"cycle":${simulationTime}}\n""") } val retire = Wire(new Retire) - retire.rd := dut.io.retire.rd.bits.rdAddress - retire.data := dut.io.retire.rd.bits.rdData + retire.rd := dut.io.retire.rd.bits.rdAddress + retire.data := dut.io.retire.rd.bits.rdData retire.writeRd := dut.io.retire.rd.valid - retire.vxsat := dut.io.retire.csr.bits.vxsat + retire.vxsat := dut.io.retire.csr.bits.vxsat // TODO: // retire.fflag := dut.io.retire.csr.bits.fflag RawClockedVoidFunctionCall("retire_vector_instruction")(clock, t1Probe.retireValid, retire) @@ -172,34 +177,33 @@ class TestBench(generator: SerializableModuleGenerator[T1, T1Parameter]) Seq("highBandwidthPort", "indexedAccessPort") ) .zipWithIndex - .foreach { - case ((bundle: AXI4RWIrrevocableVerilog, channelName: String), index: Int) => - val agent = Module( - new AXI4SlaveAgent( - AXI4SlaveAgentParameter( - name = channelName, - axiParameter = bundle.parameter, - outstanding = 4, - readPayloadSize = 1, - writePayloadSize = 1 - ) + .foreach { case ((bundle: AXI4RWIrrevocableVerilog, channelName: String), index: Int) => + val agent = Module( + new AXI4SlaveAgent( + AXI4SlaveAgentParameter( + name = channelName, + axiParameter = bundle.parameter, + outstanding = 4, + readPayloadSize = 1, + writePayloadSize = 1 ) - ).suggestName(s"axi4_channel${index}_${channelName}") - agent.io.channel match { - case io: AXI4RWIrrevocableVerilog => io <> bundle - } - agent.io.clock := clock - agent.io.reset := reset - agent.io.channelId := index.U - agent.io.gateRead := false.B - agent.io.gateWrite := false.B + ) + ).suggestName(s"axi4_channel${index}_${channelName}") + agent.io.channel match { + case io: AXI4RWIrrevocableVerilog => io <> bundle + } + agent.io.clock := clock + agent.io.reset := reset + agent.io.channelId := index.U + agent.io.gateRead := false.B + agent.io.gateWrite := false.B } // Events for difftest and performance modeling // Probes - val laneProbes = t1Probe.laneProbes.zipWithIndex.map { - case (lane, i) => lane.suggestName(s"lane${i}Probe") + val laneProbes = t1Probe.laneProbes.zipWithIndex.map { case (lane, i) => + lane.suggestName(s"lane${i}Probe") } val lsuProbe = t1Probe.lsuProbe.suggestName("lsuProbe") @@ -209,14 +213,13 @@ class TestBench(generator: SerializableModuleGenerator[T1, T1Parameter]) val otherUnitProbe = lsuProbe.otherUnitProbe.suggestName("otherUnitProbe") // vrf write - laneProbes.zipWithIndex.foreach { - case (lane, i) => - val vrf = lane.vrfProbe.suggestName(s"lane${i}VrfProbe") - when(vrf.valid)( - printf( - cf"""{"event":"VrfWrite","issue_idx":${vrf.requestInstruction},"vd":${vrf.requestVd},"offset":${vrf.requestOffset},"mask":"${vrf.requestMask}%x","data":"${vrf.requestData}%x","lane":$i,"cycle":${simulationTime}}\n""" - ) + laneProbes.zipWithIndex.foreach { case (lane, i) => + val vrf = lane.vrfProbe.suggestName(s"lane${i}VrfProbe") + when(vrf.valid)( + printf( + cf"""{"event":"VrfWrite","issue_idx":${vrf.requestInstruction},"vd":${vrf.requestVd},"offset":${vrf.requestOffset},"mask":"${vrf.requestMask}%x","data":"${vrf.requestData}%x","lane":$i,"cycle":${simulationTime}}\n""" ) + ) } // memory write from store unit when(storeUnitProbe.valid)( @@ -251,34 +254,33 @@ class TestBench(generator: SerializableModuleGenerator[T1, T1Parameter]) val instructionValid = (laneProbes.map(laneProbe => laneProbe.instructionValid ## laneProbe.instructionValid) :+ lsuProbe.lsuInstructionValid :+ t1Probe.instructionValid).reduce(_ | _) - val scoreboardEnq = + val scoreboardEnq = Mux(t1Probe.instructionIssue, UIntToOH(t1Probe.issueTag), 0.U((2 * generator.parameter.chainingSize).W)) - vrfWriteScoreboard.zipWithIndex.foreach { - case (scoreboard, tag) => - val writeEnq: UInt = VecInit( - // vrf write from lane - laneProbes.flatMap(laneProbe => - laneProbe.slots.map(slot => slot.writeTag === tag.U && slot.writeQueueEnq && slot.writeMask.orR) - ) ++ laneProbes.flatMap(laneProbe => - laneProbe.crossWriteProbe.map(cp => cp.bits.writeTag === tag.U && cp.valid && cp.bits.writeMask.orR) - ) ++ - // vrf write from lsu - lsuProbe.slots.map(slot => slot.dataInstruction === tag.U && slot.writeValid && slot.dataMask.orR) ++ - // vrf write from Sequencer - Some(t1Probe.writeQueueEnq.bits === tag.U && t1Probe.writeQueueEnq.valid && t1Probe.writeQueueEnqMask.orR) - ).asUInt - // always equal to array index - scoreboard.bits := scoreboard.bits + PopCount(writeEnq) - when(scoreboard.valid && !instructionValid(tag)) { - printf( - cf"""{"event":"VrfScoreboardReport","count":${scoreboard.bits},"issue_idx":${tag},"cycle":${simulationTime}}\n""" - ) - scoreboard.valid := false.B - } - when(scoreboardEnq(tag)) { - scoreboard.valid := true.B - assert(!scoreboard.valid) - scoreboard.bits := 0.U - } + vrfWriteScoreboard.zipWithIndex.foreach { case (scoreboard, tag) => + val writeEnq: UInt = VecInit( + // vrf write from lane + laneProbes.flatMap(laneProbe => + laneProbe.slots.map(slot => slot.writeTag === tag.U && slot.writeQueueEnq && slot.writeMask.orR) + ) ++ laneProbes.flatMap(laneProbe => + laneProbe.crossWriteProbe.map(cp => cp.bits.writeTag === tag.U && cp.valid && cp.bits.writeMask.orR) + ) ++ + // vrf write from lsu + lsuProbe.slots.map(slot => slot.dataInstruction === tag.U && slot.writeValid && slot.dataMask.orR) ++ + // vrf write from Sequencer + Some(t1Probe.writeQueueEnq.bits === tag.U && t1Probe.writeQueueEnq.valid && t1Probe.writeQueueEnqMask.orR) + ).asUInt + // always equal to array index + scoreboard.bits := scoreboard.bits + PopCount(writeEnq) + when(scoreboard.valid && !instructionValid(tag)) { + printf( + cf"""{"event":"VrfScoreboardReport","count":${scoreboard.bits},"issue_idx":${tag},"cycle":${simulationTime}}\n""" + ) + scoreboard.valid := false.B + } + when(scoreboardEnq(tag)) { + scoreboard.valid := true.B + assert(!scoreboard.valid) + scoreboard.bits := 0.U + } } } diff --git a/t1rocketemu/src/AXI4SlaveAgent.scala b/t1rocketemu/src/AXI4SlaveAgent.scala index 3af3f3727..fef1ed557 100644 --- a/t1rocketemu/src/AXI4SlaveAgent.scala +++ b/t1rocketemu/src/AXI4SlaveAgent.scala @@ -7,18 +7,38 @@ package org.chipsalliance.t1.t1rocketemu.dpi import chisel3._ import chisel3.util.circt.dpi.{RawClockedVoidFunctionCall, RawUnclockedNonVoidFunctionCall} import chisel3.util.{isPow2, log2Ceil} -import org.chipsalliance.amba.axi4.bundle.{ARChannel, ARFlowControl, AWChannel, AWFlowControl, AXI4BundleParameter, AXI4ROIrrevocableVerilog, AXI4RWIrrevocableVerilog, AXI4WOIrrevocableVerilog, BChannel, BFlowControl, RChannel, RFlowControl, WChannel, WFlowControl} +import org.chipsalliance.amba.axi4.bundle.{ + ARChannel, + ARFlowControl, + AWChannel, + AWFlowControl, + AXI4BundleParameter, + AXI4ROIrrevocableVerilog, + AXI4RWIrrevocableVerilog, + AXI4WOIrrevocableVerilog, + BChannel, + BFlowControl, + RChannel, + RFlowControl, + WChannel, + WFlowControl +} -case class AXI4SlaveAgentParameter(name: String, axiParameter: AXI4BundleParameter, outstanding: Int, readPayloadSize: Int, writePayloadSize: Int) +case class AXI4SlaveAgentParameter( + name: String, + axiParameter: AXI4BundleParameter, + outstanding: Int, + readPayloadSize: Int, + writePayloadSize: Int) class AXI4SlaveAgentInterface(parameter: AXI4SlaveAgentParameter) extends Bundle { val clock: Clock = Input(Clock()) val reset: Reset = Input(Reset()) - val channelId: UInt = Input(Const(UInt(64.W))) + val channelId: UInt = Input(Const(UInt(64.W))) // don't issue read DPI - val gateRead: Bool = Input(Bool()) + val gateRead: Bool = Input(Bool()) // don't issue write DPI - val gateWrite: Bool = Input(Bool()) + val gateWrite: Bool = Input(Bool()) val channel = Flipped( org.chipsalliance.amba.axi4.bundle.verilog.irrevocable(parameter.axiParameter) ) @@ -30,7 +50,7 @@ class WritePayload(length: Int, dataWidth: Int) extends Bundle { val strb = Vec(length, UInt(math.max(8, dataWidth / 8).W)) } -class ReadPayload(length: Int,dataWidth: Int) extends Bundle { +class ReadPayload(length: Int, dataWidth: Int) extends Bundle { val data = Vec(length, UInt(dataWidth.W)) } @@ -51,50 +71,55 @@ class AXI4SlaveAgent(parameter: AXI4SlaveAgentParameter) private class WriteManager( channel: AWChannel with AWFlowControl with WChannel with WFlowControl with BChannel with BFlowControl) { withClockAndReset(io.clock, io.reset) { + /** There is an aw in the register. */ val awIssued = RegInit(false.B) + /** There is a w in the register. */ val last = RegInit(false.B) /** memory to store the write payload - * @todo limit the payload size based on the RTL configuration. + * @todo + * limit the payload size based on the RTL configuration. */ - val writePayload = RegInit(0.U.asTypeOf(new WritePayload(parameter.writePayloadSize, parameter.axiParameter.dataWidth))) + val writePayload = + RegInit(0.U.asTypeOf(new WritePayload(parameter.writePayloadSize, parameter.axiParameter.dataWidth))) + /** AWID, latch at AW fire, used at B fire. */ - val awid = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWID))) - val awaddr = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWADDR))) - val awlen = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWLEN))) - val awsize = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWSIZE))) - val awburst = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWBURST))) - val awlock = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWLOCK))) - val awcache = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWCACHE))) - val awprot = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWPROT))) - val awqos = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWQOS))) + val awid = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWID))) + val awaddr = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWADDR))) + val awlen = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWLEN))) + val awsize = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWSIZE))) + val awburst = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWBURST))) + val awlock = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWLOCK))) + val awcache = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWCACHE))) + val awprot = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWPROT))) + val awqos = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWQOS))) val awregion = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWREGION))) - val awuser = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWUSER))) + val awuser = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWUSER))) /** index the payload, used to write [[writePayload]] */ - val writeIdx = RegInit(0.U.asTypeOf(UInt(8.W))) - val bFire = channel.BREADY && channel.BVALID - val awFire = channel.AWREADY && channel.AWVALID + val writeIdx = RegInit(0.U.asTypeOf(UInt(8.W))) + val bFire = channel.BREADY && channel.BVALID + val awFire = channel.AWREADY && channel.AWVALID val wLastFire = channel.WVALID && channel.WREADY && channel.WLAST - val awExist = channel.AWVALID || awIssued - val wExist = channel.WVALID && channel.WLAST || last + val awExist = channel.AWVALID || awIssued + val wExist = channel.WVALID && channel.WLAST || last // AW channel.AWREADY := !awIssued || (wExist && channel.BREADY) when(channel.AWREADY && channel.AWVALID) { - awid := channel.AWID - awaddr := channel.AWADDR - awlen := channel.AWLEN - awsize := channel.AWSIZE - awburst := channel.AWBURST - awlock := channel.AWLOCK - awcache := channel.AWCACHE - awprot := channel.AWPROT - awqos := channel.AWQOS + awid := channel.AWID + awaddr := channel.AWADDR + awlen := channel.AWLEN + awsize := channel.AWSIZE + awburst := channel.AWBURST + awlock := channel.AWLOCK + awcache := channel.AWCACHE + awprot := channel.AWPROT + awqos := channel.AWQOS awregion := channel.AWREGION - awuser := channel.AWUSER + awuser := channel.AWUSER } when(awFire ^ bFire) { awIssued := awFire @@ -104,11 +129,11 @@ class AXI4SlaveAgent(parameter: AXI4SlaveAgentParameter) val writePayloadUpdate = WireDefault(writePayload) channel.WREADY := !last || (awExist && channel.BREADY) when(channel.WVALID && channel.WREADY) { - writePayload.data(writeIdx) := channel.WDATA + writePayload.data(writeIdx) := channel.WDATA writePayloadUpdate.data(writeIdx) := channel.WDATA - writePayload.strb(writeIdx) := channel.WSTRB.pad(writePayload.strb.getWidth) + writePayload.strb(writeIdx) := channel.WSTRB.pad(writePayload.strb.getWidth) writePayloadUpdate.strb(writeIdx) := channel.WSTRB.pad(writePayload.strb.getWidth) - writeIdx := writeIdx + 1.U + writeIdx := writeIdx + 1.U when(channel.WLAST) { writeIdx := 0.U } @@ -119,9 +144,9 @@ class AXI4SlaveAgent(parameter: AXI4SlaveAgentParameter) // B channel.BVALID := awExist && wExist - channel.BID := Mux(awIssued, awid, channel.AWID) - channel.BRESP := 0.U(2.W) // OK - channel.BUSER := Mux(awIssued, awuser, channel.AWUSER) + channel.BID := Mux(awIssued, awid, channel.AWID) + channel.BRESP := 0.U(2.W) // OK + channel.BUSER := Mux(awIssued, awuser, channel.AWUSER) when(channel.BVALID && channel.BREADY) { RawClockedVoidFunctionCall(s"axi_write_${parameter.name}")( io.clock, @@ -147,26 +172,30 @@ class AXI4SlaveAgent(parameter: AXI4SlaveAgentParameter) private class ReadManager(channel: ARChannel with ARFlowControl with RChannel with RFlowControl) { withClockAndReset(io.clock, io.reset) { class CAMValue extends Bundle { - val arid = UInt(16.W) - val arlen = UInt(8.W) - val readPayload = new ReadPayload(parameter.readPayloadSize, parameter.axiParameter.dataWidth) + val arid = UInt(16.W) + val arlen = UInt(8.W) + val readPayload = new ReadPayload(parameter.readPayloadSize, parameter.axiParameter.dataWidth) val readPayloadIndex = UInt(8.W) - val valid = Bool() + val valid = Bool() val user: UInt = UInt(channel.ARUSER.getWidth.W) } + /** CAM to maintain order of read requests. This is maintained as FIFO. */ val cam: Vec[CAMValue] = RegInit(0.U.asTypeOf(Vec(parameter.outstanding, new CAMValue))) require(isPow2(parameter.outstanding), "Need to handle pointers") val arPtr = RegInit(0.U.asTypeOf(UInt(log2Ceil(parameter.outstanding).W))) - val rPtr = RegInit(0.U.asTypeOf(UInt(log2Ceil(parameter.outstanding).W))) + val rPtr = RegInit(0.U.asTypeOf(UInt(log2Ceil(parameter.outstanding).W))) // AR channel.ARREADY := !cam(arPtr).valid when(channel.ARREADY && channel.ARVALID) { - cam(arPtr).arid := channel.ARID - cam(arPtr).arlen := channel.ARLEN - cam(arPtr).user := channel.ARUSER - cam(arPtr).readPayload := RawUnclockedNonVoidFunctionCall(s"axi_read_${parameter.name}", new ReadPayload(parameter.readPayloadSize, parameter.axiParameter.dataWidth))( + cam(arPtr).arid := channel.ARID + cam(arPtr).arlen := channel.ARLEN + cam(arPtr).user := channel.ARUSER + cam(arPtr).readPayload := RawUnclockedNonVoidFunctionCall( + s"axi_read_${parameter.name}", + new ReadPayload(parameter.readPayloadSize, parameter.axiParameter.dataWidth) + )( when.cond && !io.gateRead, io.channelId, channel.ARID.asTypeOf(UInt(64.W)), @@ -181,23 +210,23 @@ class AXI4SlaveAgent(parameter: AXI4SlaveAgentParameter) channel.ARREGION.asTypeOf(UInt(64.W)) ) cam(arPtr).readPayloadIndex := 0.U - cam(arPtr).valid := true.B - arPtr := arPtr + 1.U + cam(arPtr).valid := true.B + arPtr := arPtr + 1.U } // R channel.RVALID := cam(rPtr).valid - channel.RID := cam(rPtr).arid - channel.RDATA := cam(rPtr).readPayload.data(cam(rPtr).readPayloadIndex) - channel.RRESP := 0.U // OK - channel.RLAST := (cam(rPtr).arlen === cam(rPtr).readPayloadIndex) && cam(rPtr).valid - channel.RUSER := cam(rPtr).user + channel.RID := cam(rPtr).arid + channel.RDATA := cam(rPtr).readPayload.data(cam(rPtr).readPayloadIndex) + channel.RRESP := 0.U // OK + channel.RLAST := (cam(rPtr).arlen === cam(rPtr).readPayloadIndex) && cam(rPtr).valid + channel.RUSER := cam(rPtr).user when(channel.RREADY && channel.RVALID) { // increase index cam(rPtr).readPayloadIndex := cam(rPtr).readPayloadIndex + 1.U when(channel.RLAST) { cam(rPtr).valid := false.B - rPtr := rPtr + 1.U + rPtr := rPtr + 1.U } } } diff --git a/t1rocketemu/src/FPToIEEE.scala b/t1rocketemu/src/FPToIEEE.scala index 82af4541a..a0ed06a9b 100644 --- a/t1rocketemu/src/FPToIEEE.scala +++ b/t1rocketemu/src/FPToIEEE.scala @@ -14,7 +14,7 @@ object FPToIEEEParameter { implicit def rwP: upickle.default.ReadWriter[FPToIEEEParameter] = upickle.default.macroRW[FPToIEEEParameter] } -class FPToIEEEInput(fLen: Int) extends Bundle { +class FPToIEEEInput(fLen: Int) extends Bundle { val typeTag = UInt(2.W) val data = UInt((fLen + 1).W) } @@ -28,8 +28,8 @@ case class FPToIEEEParameter( class FPToIEEEInterface(parameter: FPToIEEEParameter) extends Bundle { val clock = Input(Clock()) val reset = Input(if (parameter.useAsyncReset) AsyncReset() else Bool()) - val in = Flipped(Valid(new FPToIEEEInput(parameter.fLen))) - val out = Valid(UInt(parameter.fLen.W)) + val in = Flipped(Valid(new FPToIEEEInput(parameter.fLen))) + val out = Valid(UInt(parameter.fLen.W)) } @instantiable @@ -44,16 +44,16 @@ class FPToIEEE(val parameter: FPToIEEEParameter) val minFLen: Int = parameter.minFLen val fLen: Int = parameter.fLen val xLen: Int = parameter.xLen - val helper = new FPUHelper(minFLen, fLen, xLen) + val helper = new FPUHelper(minFLen, fLen, xLen) val maxExpWidth = helper.maxExpWidth val maxSigWidth = helper.maxSigWidth - val floatTypes = helper.floatTypes - val maxType = helper.maxType - val minXLen = helper.minXLen - val nIntTypes = helper.nIntTypes + val floatTypes = helper.floatTypes + val maxType = helper.maxType + val minXLen = helper.minXLen + val nIntTypes = helper.nIntTypes def ieee(x: UInt, t: FType = maxType) = helper.ieee(x, t) - val in = io.in.bits + val in = io.in.bits val valid = io.in.valid def sextTo(x: UInt, n: Int): UInt = { @@ -70,5 +70,5 @@ class FPToIEEE(val parameter: FPToIEEEParameter) )(in.typeTag) io.out.valid := valid - io.out.bits := store + io.out.bits := store } diff --git a/t1rocketemu/src/TestBench.scala b/t1rocketemu/src/TestBench.scala index f76e245ba..c9e6459c9 100644 --- a/t1rocketemu/src/TestBench.scala +++ b/t1rocketemu/src/TestBench.scala @@ -17,7 +17,7 @@ class TestBench(generator: SerializableModuleGenerator[T1RocketTile, T1RocketTil with ImplicitClock with ImplicitReset { layer.enable(layers.Verification) - val clockGen = Module(new ExtModule with HasExtModuleInline { + val clockGen = Module(new ExtModule with HasExtModuleInline { override def desiredName = "ClockGen" setInline( s"$desiredName.sv", @@ -58,11 +58,11 @@ class TestBench(generator: SerializableModuleGenerator[T1RocketTile, T1RocketTil |endmodule |""".stripMargin ) - val clock = IO(Output(Bool())) - val reset = IO(Output(Bool())) + val clock = IO(Output(Bool())) + val reset = IO(Output(Bool())) }) - def clock = clockGen.clock.asClock - def reset = clockGen.reset + def clock = clockGen.clock.asClock + def reset = clockGen.reset override def implicitClock = clockGen.clock.asClock override def implicitReset = clockGen.reset val dut: T1RocketTile with BaseModule = Module(generator.module()) @@ -87,46 +87,45 @@ class TestBench(generator: SerializableModuleGenerator[T1RocketTile, T1RocketTil // get resetVector from simulator dut.io.resetVector := RawUnclockedNonVoidFunctionCall("get_resetvector", Const(UInt(64.W)))(simulationTime === 0.U) - dut.io.hartid := 0.U - dut.io.debug := 0.U - dut.io.mtip := 0.U - dut.io.msip := 0.U - dut.io.meip := 0.U + dut.io.hartid := 0.U + dut.io.debug := 0.U + dut.io.mtip := 0.U + dut.io.msip := 0.U + dut.io.meip := 0.U dut.io.buserror := 0.U // memory driver Seq( - dut.io.highBandwidthAXI, // index 0 + dut.io.highBandwidthAXI, // index 0 dut.io.highOutstandingAXI // index 1 ).map(_.viewAs[AXI4RWIrrevocableVerilog]) .lazyZip( Seq("highBandwidthAXI", "highOutstandingAXI") ) .zipWithIndex - .foreach { - case ((bundle: AXI4RWIrrevocableVerilog, channelName: String), index: Int) => - val agent = Module( - new AXI4SlaveAgent( - AXI4SlaveAgentParameter( - name = channelName, - axiParameter = bundle.parameter, - outstanding = 4, - readPayloadSize = 1, - writePayloadSize = 1 - ) + .foreach { case ((bundle: AXI4RWIrrevocableVerilog, channelName: String), index: Int) => + val agent = Module( + new AXI4SlaveAgent( + AXI4SlaveAgentParameter( + name = channelName, + axiParameter = bundle.parameter, + outstanding = 4, + readPayloadSize = 1, + writePayloadSize = 1 ) - ).suggestName(s"axi4_channel${index}_${channelName}") - agent.io.channel match { - case io: AXI4RWIrrevocableVerilog => io <> bundle - } - agent.io.clock := clock - agent.io.reset := reset - agent.io.channelId := index.U - agent.io.gateRead := false.B - agent.io.gateWrite := false.B + ) + ).suggestName(s"axi4_channel${index}_${channelName}") + agent.io.channel match { + case io: AXI4RWIrrevocableVerilog => io <> bundle + } + agent.io.clock := clock + agent.io.reset := reset + agent.io.channelId := index.U + agent.io.gateRead := false.B + agent.io.gateWrite := false.B } - val instFetchAXI = dut.io.instructionFetchAXI.viewAs[AXI4ROIrrevocableVerilog] + val instFetchAXI = dut.io.instructionFetchAXI.viewAs[AXI4ROIrrevocableVerilog] val instFetchAgent = Module( new AXI4SlaveAgent( AXI4SlaveAgentParameter( @@ -142,12 +141,12 @@ class TestBench(generator: SerializableModuleGenerator[T1RocketTile, T1RocketTil case io: AXI4ROIrrevocableVerilog => io <> instFetchAXI } instFetchAgent.io.clock := clock - instFetchAgent.io.reset := reset + instFetchAgent.io.reset := reset instFetchAgent.io.channelId := 0.U - instFetchAgent.io.gateRead := false.B + instFetchAgent.io.gateRead := false.B instFetchAgent.io.gateWrite := false.B - val loadStoreAXI = dut.io.loadStoreAXI.viewAs[AXI4RWIrrevocableVerilog] + val loadStoreAXI = dut.io.loadStoreAXI.viewAs[AXI4RWIrrevocableVerilog] val loadStoreAgent = Module( new AXI4SlaveAgent( AXI4SlaveAgentParameter( @@ -164,32 +163,32 @@ class TestBench(generator: SerializableModuleGenerator[T1RocketTile, T1RocketTil case io: AXI4RWIrrevocableVerilog => io <> loadStoreAXI } loadStoreAgent.io.clock := clock - loadStoreAgent.io.reset := reset + loadStoreAgent.io.reset := reset loadStoreAgent.io.channelId := 3.U - loadStoreAgent.io.gateRead := false.B + loadStoreAgent.io.gateRead := false.B loadStoreAgent.io.gateWrite := false.B // probes - val t1RocketProbe = probe.read(dut.io.t1RocketProbe) - val rocketProbe = t1RocketProbe.rocketProbe.suggestName(s"rocketProbe") - val t1Probe = t1RocketProbe.t1Probe.suggestName(s"t1Probe") - val lsuProbe = t1Probe.lsuProbe.suggestName(s"t1LSUProbe") - val laneProbes = t1Probe.laneProbes.zipWithIndex.map { - case (p, idx) => - val wire = WireDefault(p).suggestName(s"lane${idx}Probe") - wire + val t1RocketProbe = probe.read(dut.io.t1RocketProbe) + val rocketProbe = t1RocketProbe.rocketProbe.suggestName(s"rocketProbe") + val t1Probe = t1RocketProbe.t1Probe.suggestName(s"t1Probe") + val lsuProbe = t1Probe.lsuProbe.suggestName(s"t1LSUProbe") + val laneProbes = t1Probe.laneProbes.zipWithIndex.map { case (p, idx) => + val wire = WireDefault(p).suggestName(s"lane${idx}Probe") + wire } - val laneVrfProbes = t1Probe.laneProbes.map(_.vrfProbe).zipWithIndex.map { - case (p, idx) => - val wire = WireDefault(p).suggestName(s"lane${idx}VrfProbe") - wire + val laneVrfProbes = t1Probe.laneProbes.map(_.vrfProbe).zipWithIndex.map { case (p, idx) => + val wire = WireDefault(p).suggestName(s"lane${idx}VrfProbe") + wire } val storeUnitProbe = t1Probe.lsuProbe.storeUnitProbe.suggestName("storeUnitProbe") val otherUnitProbe = t1Probe.lsuProbe.otherUnitProbe.suggestName("otherUnitProbe") // output the probes // rocket reg write - when(rocketProbe.rfWen && !rocketProbe.isVector && rocketProbe.rfWaddr =/= 0.U && !(rocketProbe.waitWen && rocketProbe.waitWaddr =/= 0.U))( + when( + rocketProbe.rfWen && !rocketProbe.isVector && rocketProbe.rfWaddr =/= 0.U && !(rocketProbe.waitWen && rocketProbe.waitWaddr =/= 0.U) + )( printf( cf"""{"event":"RegWrite","idx":${rocketProbe.rfWaddr},"data":"${rocketProbe.rfWdata}%x","cycle":${simulationTime}}\n""" ) @@ -201,24 +200,32 @@ class TestBench(generator: SerializableModuleGenerator[T1RocketTile, T1RocketTil ) ) - // [[option]] rocket fpu reg write + // [[option]] rocket fpu reg write generator.parameter.fpuParameter.zip(t1RocketProbe.fpuProbe).zip(rocketProbe.fpuScoreboard).map { - case((fpuParameter, fpu), fpuScoreboard) => { - val fpToIEEE = Module(new FPToIEEE(FPToIEEEParameter( - fpuParameter.useAsyncReset, - fpuParameter.xLen, - fpuParameter.fLen, - fpuParameter.minFLen - ))) + case ((fpuParameter, fpu), fpuScoreboard) => { + val fpToIEEE = Module( + new FPToIEEE( + FPToIEEEParameter( + fpuParameter.useAsyncReset, + fpuParameter.xLen, + fpuParameter.fLen, + fpuParameter.minFLen + ) + ) + ) val isVectorForLLWrite = RegNext(rocketProbe.isVector, false.B) - fpToIEEE.io.clock := clock - fpToIEEE.io.reset := reset - fpToIEEE.io.in.valid := fpu.pipeWrite.rfWen || (fpu.loadOrVectorWrite.rfWen && !isVectorForLLWrite) - fpToIEEE.io.in.bits.data := Mux(fpu.pipeWrite.rfWen, fpu.pipeWrite.rfWdata, fpu.loadOrVectorWrite.rfWdata) - fpToIEEE.io.in.bits.typeTag := Mux(fpu.pipeWrite.rfWen, fpu.pipeWrite.rfWtypeTag, fpu.loadOrVectorWrite.rfWtypeTag) + fpToIEEE.io.clock := clock + fpToIEEE.io.reset := reset + fpToIEEE.io.in.valid := fpu.pipeWrite.rfWen || (fpu.loadOrVectorWrite.rfWen && !isVectorForLLWrite) + fpToIEEE.io.in.bits.data := Mux(fpu.pipeWrite.rfWen, fpu.pipeWrite.rfWdata, fpu.loadOrVectorWrite.rfWdata) + fpToIEEE.io.in.bits.typeTag := Mux( + fpu.pipeWrite.rfWen, + fpu.pipeWrite.rfWtypeTag, + fpu.loadOrVectorWrite.rfWtypeTag + ) - val rfWen = fpToIEEE.io.out.valid + val rfWen = fpToIEEE.io.out.valid val rfWaddr = Mux(fpu.pipeWrite.rfWen, fpu.pipeWrite.rfWaddr, fpu.loadOrVectorWrite.rfWaddr) val rfWdata = fpToIEEE.io.out.bits when(rfWen) { @@ -241,13 +248,12 @@ class TestBench(generator: SerializableModuleGenerator[T1RocketTile, T1RocketTil } // t1 vrf write - laneVrfProbes.zipWithIndex.foreach { - case (lane, i) => - when(lane.valid)( - printf( - cf"""{"event":"VrfWrite","issue_idx":${lane.requestInstruction},"vd":${lane.requestVd},"offset":${lane.requestOffset},"mask":"${lane.requestMask}%x","data":"${lane.requestData}%x","lane":$i,"cycle":${simulationTime}}\n""" - ) + laneVrfProbes.zipWithIndex.foreach { case (lane, i) => + when(lane.valid)( + printf( + cf"""{"event":"VrfWrite","issue_idx":${lane.requestInstruction},"vd":${lane.requestVd},"offset":${lane.requestOffset},"mask":"${lane.requestMask}%x","data":"${lane.requestData}%x","lane":$i,"cycle":${simulationTime}}\n""" ) + ) } // t1 memory write from store unit @@ -289,35 +295,34 @@ class TestBench(generator: SerializableModuleGenerator[T1RocketTile, T1RocketTil val instructionValid = (laneProbes.map(laneProbe => laneProbe.instructionValid ## laneProbe.instructionValid) :+ lsuProbe.lsuInstructionValid :+ t1Probe.instructionValid).reduce(_ | _) - val scoreboardEnq = + val scoreboardEnq = Mux(t1Probe.instructionIssue, UIntToOH(t1Probe.issueTag), 0.U((2 * generator.parameter.t1Parameter.chainingSize).W)) - vrfWriteScoreboard.zipWithIndex.foreach { - case (scoreboard, tag) => - val writeEnq: UInt = VecInit( - // vrf write from lane - laneProbes.flatMap(laneProbe => - laneProbe.slots.map(slot => slot.writeTag === tag.U && slot.writeQueueEnq && slot.writeMask.orR) - ) ++ laneProbes.flatMap(laneProbe => - laneProbe.crossWriteProbe.map(cp => cp.bits.writeTag === tag.U && cp.valid && cp.bits.writeMask.orR) - ) ++ - // vrf write from lsu - lsuProbe.slots.map(slot => slot.dataInstruction === tag.U && slot.writeValid && slot.dataMask.orR) ++ - // vrf write from Sequencer - Some(t1Probe.writeQueueEnq.bits === tag.U && t1Probe.writeQueueEnq.valid && t1Probe.writeQueueEnqMask.orR) - ).asUInt - // always equal to array index - scoreboard.bits := scoreboard.bits + PopCount(writeEnq) - when(scoreboard.valid && !instructionValid(tag)) { - printf( - cf"""{"event":"VrfScoreboard","count":${scoreboard.bits},"issue_idx":${tag},"cycle":${simulationTime}}\n""" - ) - scoreboard.valid := false.B - } - when(scoreboardEnq(tag)) { - scoreboard.valid := true.B - assert(!scoreboard.valid) - scoreboard.bits := 0.U - } + vrfWriteScoreboard.zipWithIndex.foreach { case (scoreboard, tag) => + val writeEnq: UInt = VecInit( + // vrf write from lane + laneProbes.flatMap(laneProbe => + laneProbe.slots.map(slot => slot.writeTag === tag.U && slot.writeQueueEnq && slot.writeMask.orR) + ) ++ laneProbes.flatMap(laneProbe => + laneProbe.crossWriteProbe.map(cp => cp.bits.writeTag === tag.U && cp.valid && cp.bits.writeMask.orR) + ) ++ + // vrf write from lsu + lsuProbe.slots.map(slot => slot.dataInstruction === tag.U && slot.writeValid && slot.dataMask.orR) ++ + // vrf write from Sequencer + Some(t1Probe.writeQueueEnq.bits === tag.U && t1Probe.writeQueueEnq.valid && t1Probe.writeQueueEnqMask.orR) + ).asUInt + // always equal to array index + scoreboard.bits := scoreboard.bits + PopCount(writeEnq) + when(scoreboard.valid && !instructionValid(tag)) { + printf( + cf"""{"event":"VrfScoreboard","count":${scoreboard.bits},"issue_idx":${tag},"cycle":${simulationTime}}\n""" + ) + scoreboard.valid := false.B + } + when(scoreboardEnq(tag)) { + scoreboard.valid := true.B + assert(!scoreboard.valid) + scoreboard.bits := 0.U + } } // t1 quit