From 4ae371d686cfcbb7735d80e16a5ddea8acc65679 Mon Sep 17 00:00:00 2001 From: Asuna Date: Thu, 14 Mar 2024 07:25:36 +0100 Subject: [PATCH] [om] add omreader and omreaderlib --- build.sc | 36 ++++++++++++++++++ common.sc | 29 +++++++++++++++ nix/t1/omreader.nix | 5 ++- omreader/src/Main.scala | 66 +++++++++++++++++++++++++++++++++ omreaderlib/src/Interface.scala | 64 ++++++++++++++++++++++++++++++++ t1/src/T1.scala | 15 ++++++++ 6 files changed, 213 insertions(+), 2 deletions(-) create mode 100644 omreader/src/Main.scala create mode 100644 omreaderlib/src/Interface.scala diff --git a/build.sc b/build.sc index e1d638b444..d494f961d1 100644 --- a/build.sc +++ b/build.sc @@ -280,6 +280,42 @@ trait Elaborator def chiselIvy = None } +object omreaderlib extends OMReaderLib + +trait OMReaderLib + extends millbuild.common.OMReaderLibModule { + def scalaVersion = T(v.scala) + + def panamaconverterModule = panamaconverter + + def circtInstallPath = T.input(PathRef(os.Path(T.ctx().env("CIRCT_INSTALL_PATH")))) + + def mainargsIvy = v.mainargs + + def chiselModule = Some(chisel) + def chiselPluginJar = T(Some(chisel.pluginModule.jar())) + def chiselPluginIvy = None + def chiselIvy = None +} + +object omreader extends OMReader + +trait OMReader + extends millbuild.common.OMReaderModule { + def scalaVersion = T(v.scala) + + def panamaconverterModule = panamaconverter + def omreaderlibModule = omreaderlib + + def circtInstallPath = T.input(PathRef(os.Path(T.ctx().env("CIRCT_INSTALL_PATH")))) + + def mainargsIvy = v.mainargs + + def chiselModule = Some(chisel) + def chiselPluginJar = T(Some(chisel.pluginModule.jar())) + def chiselPluginIvy = None + def chiselIvy = None +} /** A simple release flow for T1 generator: * package required dependency to flat jar. diff --git a/common.sc b/common.sc index 56350ff933..60e029e54d 100644 --- a/common.sc +++ b/common.sc @@ -129,3 +129,32 @@ trait ElaboratorModule super.forkArgs() ++ Seq("--enable-native-access=ALL-UNNAMED", "--enable-preview", s"-Djava.library.path=${ circtInstallPath().path / "lib"}") ) } + +trait OMReaderLibModule + extends ScalaModule + with HasChisel { + def panamaconverterModule: ScalaModule + def circtInstallPath: T[PathRef] + override def moduleDeps = super.moduleDeps ++ Seq(panamaconverterModule) + def mainargsIvy: Dep + override def ivyDeps = T(super.ivyDeps() ++ Seq(mainargsIvy)) + override def javacOptions = T(super.javacOptions() ++ Seq("--enable-preview", "--release", "21")) + override def forkArgs: T[Seq[String]] = T( + super.forkArgs() ++ Seq("--enable-native-access=ALL-UNNAMED", "--enable-preview", s"-Djava.library.path=${ circtInstallPath().path / "lib"}") + ) +} + +trait OMReaderModule + extends ScalaModule + with HasChisel { + def panamaconverterModule: ScalaModule + def omreaderlibModule: ScalaModule + def circtInstallPath: T[PathRef] + override def moduleDeps = super.moduleDeps ++ Seq(panamaconverterModule, omreaderlibModule) + def mainargsIvy: Dep + override def ivyDeps = T(super.ivyDeps() ++ Seq(mainargsIvy)) + override def javacOptions = T(super.javacOptions() ++ Seq("--enable-preview", "--release", "21")) + override def forkArgs: T[Seq[String]] = T( + super.forkArgs() ++ Seq("--enable-native-access=ALL-UNNAMED", "--enable-preview", s"-Djava.library.path=${ circtInstallPath().path / "lib"}") + ) +} diff --git a/nix/t1/omreader.nix b/nix/t1/omreader.nix index c9a5c9f12c..e3754e00ca 100644 --- a/nix/t1/omreader.nix +++ b/nix/t1/omreader.nix @@ -8,7 +8,7 @@ , mill , espresso , circt-full -, jextract +, jextract-21 , strip-nondeterminism , submodules @@ -54,7 +54,7 @@ let nativeBuildInputs = [ mill - jextract + jextract-21 strip-nondeterminism circt-full @@ -78,6 +78,7 @@ let strip-nondeterminism out/omreader/assembly.dest/out.jar mv out/omreader/assembly.dest/out.jar "$out"/share/java/omreader.jar makeWrapper ${jdk21}/bin/java "$out"/bin/omreader --add-flags "--enable-preview --enable-native-access=ALL-UNNAMED -Djava.library.path=${circt-full}/lib -jar $out/share/java/omreader.jar" + echo "$(cat "$out"/bin/omreader) 2> /dev/null" > "$out"/bin/omreader ''; meta = { diff --git a/omreader/src/Main.scala b/omreader/src/Main.scala new file mode 100644 index 0000000000..394dbf22e0 --- /dev/null +++ b/omreader/src/Main.scala @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2022 Jiuyang Liu + +package org.chipsalliance.t1.omreader + +import java.io.BufferedInputStream +import mainargs._ +import chisel3.panamaom._ +import org.chipsalliance.t1.omreaderlib._ + +object Main { + implicit object PathRead extends TokensReader.Simple[os.Path] { + def shortName = "path" + def read(strs: Seq[String]): Either[String, os.Path] = Right(os.Path(strs.head, os.pwd)) + } + + @main + def run( + @arg(name = "mlirbc-file") mlirbcFile: Option[os.Path], + @arg(name = "dump-methods") dumpMethods: Flag, + @arg(name = "eval") eval: Option[String], + ) = { + val t1Reader = (mlirbcFile match { + case Some(path) => OMReader.fromFile(path) + case None => + val stdin = new BufferedInputStream(System.in) + val bytes = Stream.continually(stdin.read).takeWhile(_ != -1).map(_.toByte).toArray + OMReader.fromBytes(bytes) + }).t1Reader + + if (eval.nonEmpty) { + println(SimpleInputEval(t1Reader.entry, eval.get)) + } else if (dumpMethods.value) { + t1Reader.dumpMethods() + } else { + t1Reader.dumpAll() + } + } + + @main + def vlen(@arg(name = "mlirbc-file") mlirbcFile: os.Path) = { + println(simplyGetT1Reader(mlirbcFile).vlen) + } + + @main + def dlen(@arg(name = "mlirbc-file") mlirbcFile: os.Path) = { + println(simplyGetT1Reader(mlirbcFile).dlen) + } + + def simplyGetT1Reader(mlirbcFile: os.Path) = OMReader.fromFile(mlirbcFile).t1Reader + + def main(args: Array[String]): Unit = ParserForMethods(this).runOrExit(args) +} + +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) + } + } + } +} diff --git a/omreaderlib/src/Interface.scala b/omreaderlib/src/Interface.scala new file mode 100644 index 0000000000..33c301053b --- /dev/null +++ b/omreaderlib/src/Interface.scala @@ -0,0 +1,64 @@ +package org.chipsalliance.t1.omreaderlib + +import scala.reflect.runtime.universe._ +import chisel3.panamalib.option._ +import chisel3.panamaom._ +import chisel3.panamaconverter.PanamaCIRCTConverter + +object OMReader { + def fromFile(mlirbcFile: os.Path): OMReader = { + new OMReader(os.read.bytes(mlirbcFile)) + } + + def fromBytes(mlirbc: Array[Byte]): OMReader = { + new OMReader(mlirbc) + } +} + +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) { + 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) + } + } + private val t1 = { + if (isSubsystem) { + entry + .field("om").asInstanceOf[PanamaCIRCTOMEvaluatorValueObject] + .field("t1").asInstanceOf[PanamaCIRCTOMEvaluatorValueObject] + } + else { + entry + .field("om").asInstanceOf[PanamaCIRCTOMEvaluatorValueObject] + } + } + + def vlen: Long = t1.field("vlen").asInstanceOf[PanamaCIRCTOMEvaluatorValuePrimitiveInteger].integer + def dlen: Long = t1.field("dlen").asInstanceOf[PanamaCIRCTOMEvaluatorValuePrimitiveInteger].integer + + 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 + ) + methods.foreach(method => { + if (!method.name.toString.startsWith("dump")) { + val value = mirror.reflectMethod(method.asMethod)() + println(s"${method.name} = $value") + } + }) + } + + def dumpAll(): Unit = { + entry.foreachField((name, value) => println(s".$name => $value")) + } +} diff --git a/t1/src/T1.scala b/t1/src/T1.scala index a2235ac5d3..106a26c4e0 100644 --- a/t1/src/T1.scala +++ b/t1/src/T1.scala @@ -22,6 +22,18 @@ import org.chipsalliance.t1.rtl.vrf.{RamType, VRFParam, VRFProbe} // 3. Lane(Retime, VRF memory type, id, multiple instances(does it affect dedup? not for sure)) @instantiable class T1OM extends Class { + @public + val vlen = IO(Output(Property[Int]())) + @public + val vlenIn = IO(Input(Property[Int]())) + vlen := vlenIn + + @public + val dlen = IO(Output(Property[Int]())) + @public + val dlenIn = IO(Input(Property[Int]())) + dlen := dlenIn + @public val lanes = IO(Output(Property[Seq[AnyClassType]]())) @public @@ -264,6 +276,9 @@ class T1(val parameter: T1Parameter) extends Module with SerializableModule[T1Pa val om: Property[ClassType] = IO(Output(Property[omType.Type]())) om := omInstance.getPropertyReference + omInstance.vlenIn := Property(parameter.vLen) + omInstance.dlenIn := Property(parameter.dLen) + /** request from CPU. * because the interrupt and exception of previous instruction is unpredictable, * and the `kill` logic in Vector processor is too high,