From 126b7f4306527067f835d95cc2fa073b6471a9cd Mon Sep 17 00:00:00 2001 From: Asuna Date: Tue, 7 May 2024 16:33:12 +0200 Subject: [PATCH] [om] add omreader and omreaderlib --- build.sc | 36 +++++++++++++ common.sc | 29 +++++++++++ nix/t1/default.nix | 2 + nix/t1/om.nix | 25 +++++++++ nix/t1/omreader.nix | 90 +++++++++++++++++++++++++++++++++ omreader/src/Main.scala | 66 ++++++++++++++++++++++++ omreaderlib/src/Interface.scala | 64 +++++++++++++++++++++++ t1/src/T1.scala | 15 ++++++ 8 files changed, 327 insertions(+) create mode 100644 nix/t1/om.nix create mode 100644 nix/t1/omreader.nix create mode 100644 omreader/src/Main.scala create mode 100644 omreaderlib/src/Interface.scala diff --git a/build.sc b/build.sc index e1d638b44..d494f961d 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 56350ff93..60e029e54 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/default.nix b/nix/t1/default.nix index f80555f3c..b52ad2297 100644 --- a/nix/t1/default.nix +++ b/nix/t1/default.nix @@ -27,6 +27,7 @@ lib.makeScope newScope configgen = _millOutput.configgen // { meta.mainProgram = "configgen"; }; t1package = _millOutput.t1package; + omreader = self.callPackage ./omreader.nix { }; submodules = self.callPackage ./submodules.nix { }; riscv-opcodes-src = self.submodules.sources.riscv-opcodes.src; @@ -71,6 +72,7 @@ lib.makeScope newScope elaborate = innerSelf.callPackage ./elaborate.nix { target = "ip"; /* use-binder = true; */ }; mlirbc = innerSelf.callPackage ./mlirbc.nix { inherit elaborate; }; rtl = innerSelf.callPackage ./rtl.nix { inherit mlirbc; }; + omreaderlib = innerSelf.callPackage ./omreaderlib.nix { inherit mlirbc; }; emu-elaborate = innerSelf.callPackage ./elaborate.nix { target = "ipemu"; /* use-binder = true; */ }; emu-mlirbc = innerSelf.callPackage ./mlirbc.nix { elaborate = emu-elaborate; }; diff --git a/nix/t1/om.nix b/nix/t1/om.nix new file mode 100644 index 000000000..1f943072d --- /dev/null +++ b/nix/t1/om.nix @@ -0,0 +1,25 @@ +{ stdenvNoCC +, lib + +, omreader +, circt +, mlirbc +}: + +let + omReaderArgs = lib.filter (s: s != "") [ + "--mlirbc-file" + "${mlirbc}/${mlirbc.elaborateTarget}-${mlirbc.elaborateConfig}.mlirbc" + ]; +in +stdenvNoCC.mkDerivation { + name = "t1-${mlirbc.elaborateConfig}-${mlirbc.elaborateTarget}-om"; + + nativeBuildInputs = [ circt omreader ]; + + buildCommand = '' + omreader ${lib.escapeShellArgs omReaderArgs} + ''; + + meta.description = "Call CLI dumps OM properties from MLIR bytecodes"; +} diff --git a/nix/t1/omreader.nix b/nix/t1/omreader.nix new file mode 100644 index 000000000..62bff6677 --- /dev/null +++ b/nix/t1/omreader.nix @@ -0,0 +1,90 @@ +{ lib +, stdenv +, fetchMillDeps +, makeWrapper +, jdk21 + + # chisel deps +, mill +, espresso +, circt-full +, jextract-21 +, strip-nondeterminism + +, submodules +}: + +let + self = stdenv.mkDerivation rec { + name = "omreader"; + + src = with lib.fileset; toSource { + root = ./../..; + fileset = unions [ + ./../../build.sc + ./../../common.sc + ./../../omreader + ./../../omreaderlib + ]; + }; + + passthru.millDeps = fetchMillDeps { + inherit name; + src = with lib.fileset; toSource { + root = ./../..; + fileset = unions [ + ./../../build.sc + ./../../common.sc + ]; + }; + millDepsHash = "sha256-ZgcBH7p4/F8Jn6qmsTKmwN6PLVXi37iuRCD0xYxvEO4="; + nativeBuildInputs = [ submodules.setupHook ]; + }; + + passthru.editable = self.overrideAttrs (_: { + shellHook = '' + setupSubmodulesEditable + mill mill.bsp.BSP/install 0 + ''; + }); + + shellHook = '' + setupSubmodules + ''; + + nativeBuildInputs = [ + mill + jextract-21 + strip-nondeterminism + circt-full + + makeWrapper + passthru.millDeps.setupHook + + submodules.setupHook + ]; + + env = { + CIRCT_INSTALL_PATH = circt-full; + JAVA_TOOL_OPTIONS = "--enable-preview"; + }; + + buildPhase = '' + mill -i 'omreader.assembly' + ''; + + installPhase = '' + mkdir -p "$out"/bin "$out"/share/java + 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 = { + description = "CLI reads OM properties from MLIR bytecodes"; + mainProgram = "omreader"; + }; + }; +in +self diff --git a/omreader/src/Main.scala b/omreader/src/Main.scala new file mode 100644 index 000000000..394dbf22e --- /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 000000000..33c301053 --- /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 a2235ac5d..106a26c4e 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,