From 4321282baa760cb69a7387b6ecc621487dddf22f Mon Sep 17 00:00:00 2001 From: oronpo Date: Tue, 20 Aug 2024 23:53:49 +0300 Subject: [PATCH 01/15] upgrading to Scala 3.5.0 --- build.sbt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build.sbt b/build.sbt index c1f0b3355..92659b76a 100755 --- a/build.sbt +++ b/build.sbt @@ -2,7 +2,7 @@ commands += DFHDLCommands.quickTestSetup // format: off val projectName = "dfhdl" -val compilerVersion = "3.4.2" +val compilerVersion = "3.5.0" inThisBuild( List( @@ -59,7 +59,7 @@ def additionalSources(scalaVersion: String, base: File): Seq[File] = { case _ => Seq.empty } -} +} lazy val plugin = project .settings( name := s"$projectName-plugin", @@ -163,7 +163,7 @@ def compilerOptionsVersionDependent(scalaVersion: String) = { case _ => Seq.empty } -} +} lazy val compilerOptions = Seq( "-unchecked", @@ -178,7 +178,7 @@ lazy val compilerOptions = Seq( "-Wconf:msg=not declared infix:s", //ignore warning given by the plugin Jdummy dependency trick "-Wconf:msg=bad option '-Jdummy:s" -) +) lazy val pluginUseSettings = Seq( Compile / scalacOptions ++= { From 346d3861c0ca2091ace14a6b093e30b57f1e16eb Mon Sep 17 00:00:00 2001 From: oronpo Date: Wed, 21 Aug 2024 01:49:17 +0300 Subject: [PATCH 02/15] work around options double definition in anonymous givens https://github.com/scala/scala3/issues/21406 --- plugin/src/main/scala/plugin/PreTyperPhase.scala | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/plugin/src/main/scala/plugin/PreTyperPhase.scala b/plugin/src/main/scala/plugin/PreTyperPhase.scala index 5dbc682d6..8997a68c2 100644 --- a/plugin/src/main/scala/plugin/PreTyperPhase.scala +++ b/plugin/src/main/scala/plugin/PreTyperPhase.scala @@ -67,7 +67,6 @@ class PreTyperPhase(setting: Setting) extends PluginPhase: // only handling pure statements that begin as an infix case InfixOpChange(tree) => tree case tree => - debug(tree) tree override def transform(tree: Tree)(using Context): Tree = super.transform(tree) match @@ -88,12 +87,24 @@ class PreTyperPhase(setting: Setting) extends PluginPhase: if x.toString == "X" && conn.toString == "<>" => Some(InfixOp(Parens(InfixOp(a, Ident(x), b)), Ident(conn), c)) case _ => None + object FullSelectGivenName: + def unapply(tree: Select)(using Context): Option[String] = + tree match + case Select(Ident(options), name) if options.toString == "options" => + Some(s"options_${name}") + case Select(FullSelectGivenName(prev), name) => Some(s"${prev}_$name") + case _ => None override def transform(tree: Tree)(using Context): Tree = super.transform(tree) match case tree @ ValDef(_, InfixOpChange(tpt), _) => cpy.ValDef(tree)(tpt = tpt) case tree @ DefDef(_, _, InfixOpChange(tpt), _) => cpy.DefDef(tree)(tpt = tpt) + // workaround https://github.com/scala/scala3/issues/21406 + case tree @ ValDef(name, select: Select, _) if name.isEmpty && tree.mods.is(Given) => + select match + case FullSelectGivenName(updateName) => cpy.ValDef(tree)(name = updateName.toTermName) + case _ => tree // workaround https://github.com/scala/scala3/issues/20053 case tree @ Select(t, name) => val nameStr = name.toString() @@ -105,7 +116,8 @@ class PreTyperPhase(setting: Setting) extends PluginPhase: ) tree else tree - case t => t + case t => + t end match end transform From 9314b20e976bdaaf680a96c7c8719cd9e0180923 Mon Sep 17 00:00:00 2001 From: oronpo Date: Wed, 21 Aug 2024 15:41:25 +0300 Subject: [PATCH 03/15] fix printGenFiles with proper filtering according to options --- .../src/main/scala/dfhdl/compiler/printing/Printer.scala | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/compiler/ir/src/main/scala/dfhdl/compiler/printing/Printer.scala b/compiler/ir/src/main/scala/dfhdl/compiler/printing/Printer.scala index 8516328d6..3c3c75bd6 100644 --- a/compiler/ir/src/main/scala/dfhdl/compiler/printing/Printer.scala +++ b/compiler/ir/src/main/scala/dfhdl/compiler/printing/Printer.scala @@ -207,9 +207,11 @@ end Printer object Printer: def printGenFiles(db: DB)(using po: PrinterOptions): Unit = - val srcFiles = - if (po.showGlobals) db.srcFiles - else db.srcFiles.drop(1) + val srcTypeFilter: SourceType => Boolean = + if (po.showGlobals) + srcType => srcType == SourceType.Design.Regular | srcType == SourceType.Design.GlobalDef + else srcType => srcType == SourceType.Design.Regular + val srcFiles = db.srcFiles.view.filter(srcFile => srcTypeFilter(srcFile.sourceType)) srcFiles.foreach { case srcFile @ SourceFile( SourceOrigin.Compiled | SourceOrigin.Committed, From bd0c39dca38525b532e6cf4ac4a7e942bdef89d5 Mon Sep 17 00:00:00 2001 From: oronpo Date: Wed, 21 Aug 2024 18:27:50 +0300 Subject: [PATCH 04/15] common handling of sbt/scala-cli detection in internals --- core/src/main/scala/dfhdl/options/OnError.scala | 13 ++----------- .../src/main/scala/dfhdl/internals/helpers.scala | 15 ++++++++++++++- lib/src/main/scala/dfhdl/DFApp.scala | 16 ++++++---------- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/core/src/main/scala/dfhdl/options/OnError.scala b/core/src/main/scala/dfhdl/options/OnError.scala index c9d73a130..c022736f5 100644 --- a/core/src/main/scala/dfhdl/options/OnError.scala +++ b/core/src/main/scala/dfhdl/options/OnError.scala @@ -1,16 +1,7 @@ package dfhdl.options -import dfhdl.internals.getShellCommand +import dfhdl.internals.{sbtShellIsRunning, sbtTestIsRunning} enum OnError derives CanEqual: case Exit, Exception object OnError: - private val possibleCommandsSuffix = List( - "xsbt.boot.Boot", - "xsbt.boot.Boot test", - "sbt-launch.jar", - "sbt-launch.jar test" - ) - private lazy val sbtShellOrTestIsRunning = getShellCommand match - case Some(cmd) if possibleCommandsSuffix.exists(suf => cmd.endsWith(suf)) => true - case _ => false - given OnError = if (sbtShellOrTestIsRunning) Exception else Exit + given OnError = if (sbtShellIsRunning || sbtTestIsRunning) Exception else Exit diff --git a/internals/src/main/scala/dfhdl/internals/helpers.scala b/internals/src/main/scala/dfhdl/internals/helpers.scala index 8e0096c4e..209ba6ecd 100644 --- a/internals/src/main/scala/dfhdl/internals/helpers.scala +++ b/internals/src/main/scala/dfhdl/internals/helpers.scala @@ -329,7 +329,7 @@ extension [T](seq: Iterable[T]) accumulator(seq.drop(subseq.size), f, (key -> subseq) :: res) accumulator(seq, f, Nil).view.map(e => (e._1, e._2.toList)).toList -def getShellCommand: Option[String] = +lazy val getShellCommand: Option[String] = import scala.io.Source import scala.util.{Try, Success, Failure} import sys.process.* @@ -356,3 +356,16 @@ def getShellCommand: Option[String] = case Failure(_) => None end match end getShellCommand + +lazy val sbtShellIsRunning: Boolean = + getShellCommand.exists(cmd => cmd.endsWith("xsbt.boot.Boot") || cmd.endsWith("sbt-launch.jar")) + +lazy val sbtTestIsRunning: Boolean = + getShellCommand.exists(cmd => + cmd.endsWith("xsbt.boot.Boot test") || cmd.endsWith("sbt-launch.jar test") + ) + +lazy val sbtIsRunning: Boolean = + getShellCommand.exists(cmd => cmd.contains("xsbt.boot.Boot") || cmd.contains("sbt-launch.jar")) + +lazy val scala_cliIsRunning: Boolean = getShellCommand.exists(_.contains(".scala-build")) diff --git a/lib/src/main/scala/dfhdl/DFApp.scala b/lib/src/main/scala/dfhdl/DFApp.scala index 74b9a317f..ba847e83a 100644 --- a/lib/src/main/scala/dfhdl/DFApp.scala +++ b/lib/src/main/scala/dfhdl/DFApp.scala @@ -92,16 +92,12 @@ trait DFApp: elaborated private def programName: String = - dfhdl.internals.getShellCommand match - // sbt - case Some(cmd) if cmd.contains("xsbt.boot.Boot") => - if (cmd.endsWith("xsbt.boot.Boot")) s"runMain $topScalaPath" - else s"""sbt "runMain $topScalaPath [options]"""" - // scala-cli - case Some(cmd) if cmd.contains(".scala-build") => - s"scala-cli run . -M $topScalaPath --" - case _ => - "" + import dfhdl.internals.{sbtIsRunning, scala_cliIsRunning, sbtShellIsRunning} + if (scala_cliIsRunning) s"scala-cli run . -M $topScalaPath --" + else if (sbtIsRunning) + if (sbtShellIsRunning) s"runMain $topScalaPath" + else s"""sbt "runMain $topScalaPath [options]"""" + else "" private lazy val parser = new scopt.OptionParser[Unit](programName): override def terminate(exitState: Either[String, Unit]): Unit = () def optDesignArg = opt[Map[String, String]]("design-args") From 51a6ed838af5883a03bd2a8c398dd8fa5533fdf2 Mon Sep 17 00:00:00 2001 From: oronpo Date: Wed, 21 Aug 2024 18:29:46 +0300 Subject: [PATCH 05/15] fix running help still compiles --- lib/src/main/scala/dfhdl/DFApp.scala | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/src/main/scala/dfhdl/DFApp.scala b/lib/src/main/scala/dfhdl/DFApp.scala index ba847e83a..1f52958fa 100644 --- a/lib/src/main/scala/dfhdl/DFApp.scala +++ b/lib/src/main/scala/dfhdl/DFApp.scala @@ -139,12 +139,14 @@ trait DFApp: else failure(s"Acceptable values are: ${accepted.mkString(", ")}") ) .text(s"linter tool: ${accepted.mkString(", ")}") - help("help").text("display usage text") head(s"Design Name: $designName") optDesignArg + cmd("help") + .foreach(_ => mode = "help") + .text("Display usage text") cmd("list-design-args") - .text("Mode: List all design arguments") .foreach(_ => mode = "list-design-args") + .text("Mode: List all design arguments") cmd("elaborate") .foreach(_ => mode = "elaborate") .text("Mode: Elaboration only (no compilation)") @@ -171,6 +173,8 @@ trait DFApp: def main(args: Array[String]): Unit = if (parser.parse(args, ()).isDefined) mode match + case "help" => + println(parser.usage) case "elaborate" => elaborate case "compile" => From e5c393f5b4f9ada9d0c077cfe2966b12e09d3f9e Mon Sep 17 00:00:00 2001 From: oronpo Date: Wed, 21 Aug 2024 22:33:19 +0300 Subject: [PATCH 06/15] expanded command-line options control in DFApp --- lib/src/main/scala/dfhdl/DFApp.scala | 103 ++++++++++++++++++++++----- 1 file changed, 86 insertions(+), 17 deletions(-) diff --git a/lib/src/main/scala/dfhdl/DFApp.scala b/lib/src/main/scala/dfhdl/DFApp.scala index 1f52958fa..e8773332e 100644 --- a/lib/src/main/scala/dfhdl/DFApp.scala +++ b/lib/src/main/scala/dfhdl/DFApp.scala @@ -6,6 +6,7 @@ import dfhdl.compiler.ir import wvlet.log.{Logger, LogFormatter} import scala.collection.mutable import scala.annotation.static +import dfhdl.options.CompilerOptions trait DFApp: private val logger = Logger("DFHDL App") logger.setFormatter(LogFormatter.BareFormatter) @@ -49,7 +50,8 @@ trait DFApp: given options.CompilerOptions = compilerOptions given options.PrinterOptions = printerOptions private var dsn: () => core.Design = null - private var mode = "commit" + private var mode: String = "commit" + private var helpMode: String = "usage" // used by the plugin to get the updated design arguments that could be changed by the // command-line options final protected def getDsnArg(name: String): Any = @@ -141,12 +143,65 @@ trait DFApp: .text(s"linter tool: ${accepted.mkString(", ")}") head(s"Design Name: $designName") optDesignArg + def backendOption = + val defaultValue = compilerOptions.backend match + case backend: dfhdl.backends.verilog => s"verilog:${backend.dialect}" + case backend: dfhdl.backends.vhdl => s"vhdl:${backend.dialect}" + def parseValue(value: String): Either[String, CompilerOptions.Backend] = + value.split(":").toList match + case lang :: Nil => + lang match + case "verilog" => Right(dfhdl.backends.verilog) + case "vhdl" => Right(dfhdl.backends.vhdl) + case _ => Left(s"Invalid backend language: $lang") + case lang :: dialect :: Nil => + lang match + case "verilog" => + dialect match + case "v2001" => Right(dfhdl.backends.verilog.v2001) + case "sv2005" => Right(dfhdl.backends.verilog.sv2005) + case "sv2012" => Right(dfhdl.backends.verilog.sv2012) + case "sv2017" => Right(dfhdl.backends.verilog.sv2017) + case _ => Left(s"Invalid Verilog/SystemVerilog backend dialect: $dialect") + case "vhdl" => + dialect match + case "v93" => Right(dfhdl.backends.vhdl.v93) + case "v2008" => Right(dfhdl.backends.vhdl.v2008) + case "v2019" => Right(dfhdl.backends.vhdl.v2019) + case _ => Left(s"Invalid VHDL backend dialect: $dialect") + case _ => Left(s"Invalid backend language: $lang") + case _ => Left("Invalid backend syntax. Found too many separator colons.") + opt[String]("backend") + .abbr("b") + .validate(x => parseValue(x).map(_ => ())) + .foreach(x => compilerOptions = compilerOptions.copy(backend = parseValue(x).toOption.get)) + .valueName(s"[:] default=$defaultValue") + .text("backend selection (run `help backend` to get full list of languages and dialects)") + end backendOption + backendOption + opt[Unit]("print-elaborate") + .abbr("pe") + .foreach(_ => elaborationOptions = elaborationOptions.copy(printDesignCodeAfter = true)) + .text("print the DFHDL design after elaboration") + opt[Unit]("print-compile") + .abbr("pc") + .foreach(_ => compilerOptions = compilerOptions.copy(printDesignCodeAfter = true)) + .text("print the DFHDL design after compilation") + opt[Unit]("print-backend") + .abbr("pb") + .foreach(_ => compilerOptions = compilerOptions.copy(printGenFiles = true)) + .text("print the backend design after compilation") cmd("help") .foreach(_ => mode = "help") .text("Display usage text") - cmd("list-design-args") - .foreach(_ => mode = "list-design-args") - .text("Mode: List all design arguments") + .children( + cmd("backend") + .foreach(_ => helpMode = "backend") + .text("List all backend languages and dialects"), + cmd("design-args") + .foreach(_ => helpMode = "design-args") + .text("List all design arguments") + ) cmd("elaborate") .foreach(_ => mode = "elaborate") .text("Mode: Elaboration only (no compilation)") @@ -160,7 +215,6 @@ trait DFApp: .foreach(_ => mode = "lint") .text("Mode: Linting (after elaboration, compilation, and committing to disk)") .children(optLinter) - private def listDesignArgs: Unit = println("Design arguments:") val titles = f"${"Name"}%-20s${"Type"}%-20s${"Default"}%-20sDescription" @@ -169,22 +223,37 @@ trait DFApp: designArgs.values.foreach(a => println(f"${a.name}%-20s${a.typeName}%-20s${a.valueStr}%-20s${a.desc}") ) + private def listBackends: Unit = + println( + s"""|Available languages (see their dialects below): + |verilog - Verilog or SystemVerilog + |vhdl - VHDL + | + |Available Verilog/SystemVerilog dialects: + |v2001 - Verilog 2001 + |sv2005 - SystemVerilog 2005 [default] + |sv2012 - SystemVerilog 2012 + |sv2017 - SystemVerilog 2017 + | + |Available VHDL dialects: + |v93 - VHDL 1993 + |v2008 - VHDL 2008 [default] + |v2019 - VHDL 2019""".stripMargin + ) + end listBackends def main(args: Array[String]): Unit = if (parser.parse(args, ()).isDefined) mode match case "help" => - println(parser.usage) - case "elaborate" => - elaborate - case "compile" => - elaborate.compile - case "commit" => - elaborate.compile.commit - case "lint" => - elaborate.compile.commit.lint - case "list-design-args" => - listDesignArgs - case _ => + helpMode match + case "backend" => listBackends + case "design-args" => listDesignArgs + case _ => println(parser.usage) + case "elaborate" => elaborate + case "compile" => elaborate.compile + case "commit" => elaborate.compile.commit + case "lint" => elaborate.compile.commit.lint + case _ => end main end DFApp From 855484655d67c91f74907f2e12929aa5fe513b2d Mon Sep 17 00:00:00 2001 From: oronpo Date: Wed, 21 Aug 2024 22:49:00 +0300 Subject: [PATCH 07/15] dfhdl `if` accepts both `DFBit` and `DFBool` without conversion. The type should reflect that. --- core/src/main/scala/dfhdl/core/DFIf.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/scala/dfhdl/core/DFIf.scala b/core/src/main/scala/dfhdl/core/DFIf.scala index 66e313778..d8dee4135 100644 --- a/core/src/main/scala/dfhdl/core/DFIf.scala +++ b/core/src/main/scala/dfhdl/core/DFIf.scala @@ -16,7 +16,7 @@ protected[core] def analyzeControlRet(ret: Any)(using DFC): DFTypeAny = Exact.st object DFIf: def singleBranch[R]( - condOption: Option[DFValOf[DFBool]], + condOption: Option[DFValOf[DFBoolOrBit]], prevBlockOrHeader: DFOwnerAny | DFValAny, run: () => R )(using @@ -32,7 +32,7 @@ object DFIf: (dfType, block) end singleBranch def fromBranches[R]( - branches: List[(DFValOf[DFBool], () => R)], + branches: List[(DFValOf[DFBoolOrBit], () => R)], elseOption: Option[() => R] )(using DFC): R = try val header = Header(DFUnit) @@ -94,7 +94,7 @@ object DFIf: object Block: def apply( - guardOption: Option[DFValOf[DFBool]], + guardOption: Option[DFValOf[DFBoolOrBit]], prevBlockOrHeader: DFOwnerAny | DFValAny )(using DFC From c766d4dcee94df8334d446f3bbe936ad3b5a54fa Mon Sep 17 00:00:00 2001 From: oronpo Date: Wed, 21 Aug 2024 23:06:22 +0300 Subject: [PATCH 08/15] force vhdl `if` condition to boolean under vhdl v93 dialect --- .../scala/dfhdl/compiler/printing/DFOwnerPrinter.scala | 5 +++-- .../dfhdl/compiler/stages/vhdl/VHDLOwnerPrinter.scala | 9 +++++++++ .../scala/dfhdl/compiler/stages/vhdl/VHDLPrinter.scala | 3 +++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/compiler/ir/src/main/scala/dfhdl/compiler/printing/DFOwnerPrinter.scala b/compiler/ir/src/main/scala/dfhdl/compiler/printing/DFOwnerPrinter.scala index 61e11fbb8..366c1af85 100644 --- a/compiler/ir/src/main/scala/dfhdl/compiler/printing/DFOwnerPrinter.scala +++ b/compiler/ir/src/main/scala/dfhdl/compiler/printing/DFOwnerPrinter.scala @@ -76,16 +76,17 @@ trait AbstractOwnerPrinter extends AbstractPrinter: def csDFDesignDefInst(design: DFDesignBlock): String def csBlockBegin: String def csBlockEnd: String + def csDFIfGuard(ifBlock: DFConditional.DFIfElseBlock): String = ifBlock.guardRef.refCodeString def csDFIfStatement(csCond: String): String def csDFElseStatement: String def csDFElseIfStatement(csCond: String): String final def csDFIfElseStatement(ifBlock: DFConditional.DFIfElseBlock): String = ifBlock.prevBlockOrHeaderRef.get match - case _: DFConditional.Header => csDFIfStatement(ifBlock.guardRef.refCodeString) + case _: DFConditional.Header => csDFIfStatement(csDFIfGuard(ifBlock)) case _ => ifBlock.guardRef.get match case DFMember.Empty => csDFElseStatement - case _ => csDFElseIfStatement(ifBlock.guardRef.refCodeString) + case _ => csDFElseIfStatement(csDFIfGuard(ifBlock)) def csDFIfEnd(lastCB: DFConditional.DFIfElseBlock): String def csIfBlockEmpty: String def csDFCaseBlockEmpty: String diff --git a/compiler/stages/src/main/scala/dfhdl/compiler/stages/vhdl/VHDLOwnerPrinter.scala b/compiler/stages/src/main/scala/dfhdl/compiler/stages/vhdl/VHDLOwnerPrinter.scala index b0e3c3a72..e1198a763 100644 --- a/compiler/stages/src/main/scala/dfhdl/compiler/stages/vhdl/VHDLOwnerPrinter.scala +++ b/compiler/stages/src/main/scala/dfhdl/compiler/stages/vhdl/VHDLOwnerPrinter.scala @@ -154,6 +154,15 @@ protected trait VHDLOwnerPrinter extends AbstractOwnerPrinter: def csDFDesignDefInst(design: DFDesignBlock): String = printer.unsupported def csBlockBegin: String = "" def csBlockEnd: String = "" + override def csDFIfGuard(ifBlock: DFConditional.DFIfElseBlock): String = + val requiresBoolConv = + if (printer.inVHDL93) + ifBlock.guardRef.get.asInstanceOf[DFVal].dfType match + case DFBit => true + case _ => false + else false + if (requiresBoolConv) s"to_bool(${super.csDFIfGuard(ifBlock)})" + else super.csDFIfGuard(ifBlock) def csDFIfStatement(csCond: String): String = s"if $csCond then" def csDFElseStatement: String = "else" def csDFElseIfStatement(csCond: String): String = s"elsif $csCond then" diff --git a/compiler/stages/src/main/scala/dfhdl/compiler/stages/vhdl/VHDLPrinter.scala b/compiler/stages/src/main/scala/dfhdl/compiler/stages/vhdl/VHDLPrinter.scala index 8fbda598b..5e684f89b 100644 --- a/compiler/stages/src/main/scala/dfhdl/compiler/stages/vhdl/VHDLPrinter.scala +++ b/compiler/stages/src/main/scala/dfhdl/compiler/stages/vhdl/VHDLPrinter.scala @@ -16,6 +16,9 @@ class VHDLPrinter(val dialect: VHDLDialect)(using VHDLOwnerPrinter: type TPrinter = VHDLPrinter given printer: TPrinter = this + val inVHDL93: Boolean = dialect match + case VHDLDialect.v93 => true + case _ => false def unsupported: Nothing = throw new IllegalArgumentException( "Unsupported member for this RTPrinter." ) From ba33fea65dee10da228f682406cdddc67dfb7866 Mon Sep 17 00:00:00 2001 From: oronpo Date: Sat, 24 Aug 2024 00:02:18 +0300 Subject: [PATCH 09/15] move scastie detection to helpers --- .../ir/src/main/scala/dfhdl/options/PrinterOptions.scala | 7 ++----- internals/src/main/scala/dfhdl/internals/helpers.scala | 4 ++++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/compiler/ir/src/main/scala/dfhdl/options/PrinterOptions.scala b/compiler/ir/src/main/scala/dfhdl/options/PrinterOptions.scala index 8d9c989a5..705c3062a 100644 --- a/compiler/ir/src/main/scala/dfhdl/options/PrinterOptions.scala +++ b/compiler/ir/src/main/scala/dfhdl/options/PrinterOptions.scala @@ -2,6 +2,7 @@ package dfhdl.options import dfhdl.compiler.ir import dfhdl.internals.simplePattenToRegex import dfhdl.options.PrinterOptions.* +import dfhdl.internals.scastieIsRunning final case class PrinterOptions( align: Align, @@ -11,10 +12,6 @@ final case class PrinterOptions( ) object PrinterOptions: - // detecting if running in Scastie by checking the PWD - private def inScastie: Boolean = - System.getProperty("user.dir").startsWith("/tmp/scastie") - // disabling color if in Scastie because of https://github.com/scalacenter/scastie/issues/492 given default(using align: Align, @@ -36,7 +33,7 @@ object PrinterOptions: opaque type Color <: Boolean = Boolean object Color: - given Color = !inScastie + given Color = !scastieIsRunning given Conversion[Boolean, Color] = identity opaque type ShowGlobals <: Boolean = Boolean diff --git a/internals/src/main/scala/dfhdl/internals/helpers.scala b/internals/src/main/scala/dfhdl/internals/helpers.scala index 209ba6ecd..ccf711ef0 100644 --- a/internals/src/main/scala/dfhdl/internals/helpers.scala +++ b/internals/src/main/scala/dfhdl/internals/helpers.scala @@ -369,3 +369,7 @@ lazy val sbtIsRunning: Boolean = getShellCommand.exists(cmd => cmd.contains("xsbt.boot.Boot") || cmd.contains("sbt-launch.jar")) lazy val scala_cliIsRunning: Boolean = getShellCommand.exists(_.contains(".scala-build")) + +// detecting if running in Scastie by checking the PWD +lazy val scastieIsRunning: Boolean = + System.getProperty("user.dir").startsWith("/tmp/scastie") From 7ac59304105e88e124d9cbddd19538414936e4eb Mon Sep 17 00:00:00 2001 From: oronpo Date: Sat, 24 Aug 2024 18:57:46 +0300 Subject: [PATCH 10/15] docs: no need for brackets in FullAdder examples --- lib/src/test/scala/docExamples/FullAdder1.scala | 4 ++-- lib/src/test/scala/docExamples/FullAdderN.scala | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/src/test/scala/docExamples/FullAdder1.scala b/lib/src/test/scala/docExamples/FullAdder1.scala index 9d5b847aa..18fff5fbd 100644 --- a/lib/src/test/scala/docExamples/FullAdder1.scala +++ b/lib/src/test/scala/docExamples/FullAdder1.scala @@ -6,8 +6,8 @@ import dfhdl.* //import all the DFHDL goodness val a, b, c_in = Bit <> IN val sum, c_out = Bit <> OUT - sum <> (a ^ b ^ c_in) - c_out <> (a && b || b && c_in || c_in && a) + sum <> a ^ b ^ c_in + c_out <> a && b || b && c_in || c_in && a //////////////////////////////////////////////////////////////////////////////////////////////// // DFHDL Compiler Options: // diff --git a/lib/src/test/scala/docExamples/FullAdderN.scala b/lib/src/test/scala/docExamples/FullAdderN.scala index b5d50ac83..1559fe24d 100644 --- a/lib/src/test/scala/docExamples/FullAdderN.scala +++ b/lib/src/test/scala/docExamples/FullAdderN.scala @@ -6,8 +6,8 @@ class FullAdder1 extends EDDesign: val a, b, c_in = Bit <> IN val sum, c_out = Bit <> OUT - sum <> (a ^ b ^ c_in) - c_out <> (a && b || b && c_in || c_in && a) + sum <> a ^ b ^ c_in + c_out <> a && b || b && c_in || c_in && a @top class FullAdderN(val n: Int = 4) extends EDDesign: val a, b = Bits(n) <> IN From 317bf1731ccdd53668ad3c1d50bf1d6126046693 Mon Sep 17 00:00:00 2001 From: oronpo Date: Sat, 24 Aug 2024 19:02:43 +0300 Subject: [PATCH 11/15] docs: update packages --- docs/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index bf660677c..d35195f13 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,6 +1,6 @@ pygments==2.18.0 mkdocs==1.6.0 -mkdocs-material==9.5.31 +mkdocs-material==9.5.33 pymdown-extensions==10.9 mkdocs-redirects==1.2.1 mkdocs-glightbox==0.4.0 From b842c976744e02289e02477a71c1eda4fc13492d Mon Sep 17 00:00:00 2001 From: oronpo Date: Tue, 27 Aug 2024 06:11:33 +0300 Subject: [PATCH 12/15] refactor application command line options --- build.sbt | 6 +- .../src/main/scala/dfhdl/backends.scala | 2 + lib/src/main/scala/dfhdl/DFApp.scala | 259 ------------------ .../dfhdl/app/BackendValueConverter.scala | 33 +++ lib/src/main/scala/dfhdl/app/DFApp.scala | 132 +++++++++ lib/src/main/scala/dfhdl/app/DesignArgs.scala | 42 +++ .../scala/dfhdl/app/ParsedCommandLine.scala | 147 ++++++++++ .../dfhdl/app/SingleValueConverter.scala | 15 + .../main/scala/dfhdl/options/AppOptions.scala | 17 ++ lib/src/main/scala/dfhdl/top.scala | 3 +- .../scala/plugin/MetaContextPlacerPhase.scala | 2 +- .../src/main/scala/plugin/TopAnnotPhase.scala | 10 +- 12 files changed, 398 insertions(+), 270 deletions(-) delete mode 100644 lib/src/main/scala/dfhdl/DFApp.scala create mode 100644 lib/src/main/scala/dfhdl/app/BackendValueConverter.scala create mode 100644 lib/src/main/scala/dfhdl/app/DFApp.scala create mode 100644 lib/src/main/scala/dfhdl/app/DesignArgs.scala create mode 100644 lib/src/main/scala/dfhdl/app/ParsedCommandLine.scala create mode 100644 lib/src/main/scala/dfhdl/app/SingleValueConverter.scala create mode 100644 lib/src/main/scala/dfhdl/options/AppOptions.scala diff --git a/build.sbt b/build.sbt index 92659b76a..e153b7111 100755 --- a/build.sbt +++ b/build.sbt @@ -133,20 +133,20 @@ lazy val dependencies = private val scalafmtV = "3.8.2" private val airframelogV = "24.7.1" private val oslibV = "0.9.2" - private val scoptV = "4.1.0" + private val scallopV = "5.1.0" val scodec = "org.scodec" %% "scodec-bits" % scodecV val munit = "org.scalameta" %% "munit" % munitV % Test val scalafmt = ("org.scalameta" %% "scalafmt-dynamic" % scalafmtV).cross(CrossVersion.for3Use2_13) val airframelog = "org.wvlet.airframe" %% "airframe-log" % airframelogV val oslib = "com.lihaoyi" %% "os-lib" % oslibV - val scopt = "com.github.scopt" %% "scopt" % scoptV + val scallop = "org.rogach" %% "scallop" % scallopV } lazy val commonDependencies = Seq( dependencies.scodec, dependencies.munit, dependencies.airframelog, - dependencies.scopt + dependencies.scallop ) // SETTINGS diff --git a/compiler/stages/src/main/scala/dfhdl/backends.scala b/compiler/stages/src/main/scala/dfhdl/backends.scala index 1d170c282..7f8e9f04f 100644 --- a/compiler/stages/src/main/scala/dfhdl/backends.scala +++ b/compiler/stages/src/main/scala/dfhdl/backends.scala @@ -14,6 +14,7 @@ object backends: )(using CompilerOptions, PrinterOptions): Printer = val compiledDB = StageRunner.run(VerilogBackend)(designDB) new VerilogPrinter(dialect)(using compiledDB.getSet) + override def toString(): String = s"verilog.$dialect" object verilog extends verilog(VerilogDialect.sv2005): val v2001: verilog = new verilog(VerilogDialect.v2001) val sv2005: verilog = this @@ -26,6 +27,7 @@ object backends: )(using CompilerOptions, PrinterOptions): Printer = val compiledDB = StageRunner.run(VHDLBackend)(designDB) new VHDLPrinter(dialect)(using compiledDB.getSet) + override def toString(): String = s"vhdl.$dialect" object vhdl extends vhdl(VHDLDialect.v2008): val v93: vhdl = new vhdl(VHDLDialect.v93) val v2008: vhdl = this diff --git a/lib/src/main/scala/dfhdl/DFApp.scala b/lib/src/main/scala/dfhdl/DFApp.scala deleted file mode 100644 index e8773332e..000000000 --- a/lib/src/main/scala/dfhdl/DFApp.scala +++ /dev/null @@ -1,259 +0,0 @@ -package dfhdl -import scala.collection.immutable.ListMap -import dfhdl.core -import core.{DFValAny, asValAny} -import dfhdl.compiler.ir -import wvlet.log.{Logger, LogFormatter} -import scala.collection.mutable -import scala.annotation.static -import dfhdl.options.CompilerOptions -trait DFApp: - private val logger = Logger("DFHDL App") - logger.setFormatter(LogFormatter.BareFormatter) - logger.info(s"Welcome to DFiant HDL (DFHDL) v$dfhdlVersion !!!") - private var designName: String = "" - private var topScalaPath: String = "" - // this context is just for enabling `getConstData` to work. - // the internal global context inside `value` will be actually at play here. - val dfc: DFC = DFC.emptyNoEO - case class Arg(name: String, typeName: String, value: Any, desc: String): - def valueStr: String = value match - case dfConst: DFValAny => - import dfc.getSet - dfConst.asIR.getConstData.asInstanceOf[Option[Option[Any]]].get.get.toString() - case _ => value.toString() - def updateWithValueStr(updatedValueStr: String): Arg = - val scalaTypeName = typeName.replaceFirst("DFHDL ", "") - val updatedValueScala = scalaTypeName match - case "Int" => BigInt(updatedValueStr) - case "Double" => updatedValueStr.toDouble - case "Boolean" | "Bit" => - updatedValueStr match - case "1" => true - case "0" => false - case _ => updatedValueStr.toBoolean - case _ => updatedValueStr - - val updatedValue = value match - case dfConst: DFValAny => - core.DFVal.Const.forced(dfConst.dfType, Some(updatedValueScala)) - case _ => updatedValueScala - copy(value = updatedValue) - end updateWithValueStr - end Arg - - private var designArgs: ListMap[String, Arg] = ListMap.empty - private var elaborationOptions: options.ElaborationOptions = null - private var compilerOptions: options.CompilerOptions = null - private var printerOptions: options.PrinterOptions = null - private var linterOptions: options.LinterOptions = null - given options.CompilerOptions = compilerOptions - given options.PrinterOptions = printerOptions - private var dsn: () => core.Design = null - private var mode: String = "commit" - private var helpMode: String = "usage" - // used by the plugin to get the updated design arguments that could be changed by the - // command-line options - final protected def getDsnArg(name: String): Any = - designArgs(name).value - // used by the plugin to get the updated elaboration options that could be changed by the - // command-line options - final protected def getElaborationOptions: options.ElaborationOptions = elaborationOptions - final protected def setInitials( - _designName: String, - _topScalaPath: String, - top: dfhdl.top, - argNames: List[String], - argTypes: List[String], - argValues: List[Any], - argDescs: List[String] - ): Unit = - designName = _designName - topScalaPath = _topScalaPath - elaborationOptions = top.elaborationOptions - compilerOptions = top.compilerOptions - printerOptions = top.printerOptions - designArgs = ListMap.from( - argNames.lazyZip(argTypes).lazyZip(argValues).lazyZip(argDescs).map( - (name, typeName, value, desc) => name -> Arg(name, typeName, value, desc) - ) - ) - end setInitials - final protected def setDsn(d: => core.Design): Unit = dsn = () => d - private def elaborate: core.Design = - logger.info("Elaborating design...") - // the elaboration options are set in the compiler plugin using getElaborationOptions - val elaborated = dsn() - if (elaborationOptions.printDesignCodeAfter) - println( - """|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - |The design code after elaboration: - |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~""".stripMargin - ) - elaborated.printCodeString - elaborated - - private def programName: String = - import dfhdl.internals.{sbtIsRunning, scala_cliIsRunning, sbtShellIsRunning} - if (scala_cliIsRunning) s"scala-cli run . -M $topScalaPath --" - else if (sbtIsRunning) - if (sbtShellIsRunning) s"runMain $topScalaPath" - else s"""sbt "runMain $topScalaPath [options]"""" - else "" - private lazy val parser = new scopt.OptionParser[Unit](programName): - override def terminate(exitState: Either[String, Unit]): Unit = () - def optDesignArg = opt[Map[String, String]]("design-args") - .abbr("da") - .valueName("a1=v1,a2=v2...") - .validate(x => - val invalidKeys = x.keySet -- designArgs.keySet - if (invalidKeys.nonEmpty) - failure(s"Unrecognized design arguments: ${invalidKeys.mkString(", ")}") - else - val typeMismatches = x.flatMap((argName, updatedValueStr) => - val isValid = - designArgs(argName).typeName match - case "String" | "DFHDL String" => true - case "Int" | "DFHDL Int" => updatedValueStr.toIntOption.nonEmpty - case "Double" | "DFHDL Double" => updatedValueStr.toDoubleOption.nonEmpty - case "Boolean" | "Bit" | "DFHDL Boolean" | "DFHDL Bit" => - updatedValueStr.toBooleanOption - .nonEmpty || updatedValueStr == "1" || updatedValueStr == "0" - case _ => false - if (isValid) None - else Some(argName) - ) - if (typeMismatches.nonEmpty) - failure(s"Type mismatch in design arguments: ${typeMismatches.mkString(", ")}") - else success - end if - ) - .foreach(_.foreach { (argName, updatedValueStr) => - designArgs = - designArgs.updatedWith(argName)(ao => Some(ao.get.updateWithValueStr(updatedValueStr))) - }) - .text("design arguments (run list-design-args command to get a full list)") - def optLinter = - val accepted = Set("verilator", "ghdl") - opt[String]("linter") - .validate(x => - if (accepted.contains(x)) success - else failure(s"Acceptable values are: ${accepted.mkString(", ")}") - ) - .text(s"linter tool: ${accepted.mkString(", ")}") - head(s"Design Name: $designName") - optDesignArg - def backendOption = - val defaultValue = compilerOptions.backend match - case backend: dfhdl.backends.verilog => s"verilog:${backend.dialect}" - case backend: dfhdl.backends.vhdl => s"vhdl:${backend.dialect}" - def parseValue(value: String): Either[String, CompilerOptions.Backend] = - value.split(":").toList match - case lang :: Nil => - lang match - case "verilog" => Right(dfhdl.backends.verilog) - case "vhdl" => Right(dfhdl.backends.vhdl) - case _ => Left(s"Invalid backend language: $lang") - case lang :: dialect :: Nil => - lang match - case "verilog" => - dialect match - case "v2001" => Right(dfhdl.backends.verilog.v2001) - case "sv2005" => Right(dfhdl.backends.verilog.sv2005) - case "sv2012" => Right(dfhdl.backends.verilog.sv2012) - case "sv2017" => Right(dfhdl.backends.verilog.sv2017) - case _ => Left(s"Invalid Verilog/SystemVerilog backend dialect: $dialect") - case "vhdl" => - dialect match - case "v93" => Right(dfhdl.backends.vhdl.v93) - case "v2008" => Right(dfhdl.backends.vhdl.v2008) - case "v2019" => Right(dfhdl.backends.vhdl.v2019) - case _ => Left(s"Invalid VHDL backend dialect: $dialect") - case _ => Left(s"Invalid backend language: $lang") - case _ => Left("Invalid backend syntax. Found too many separator colons.") - opt[String]("backend") - .abbr("b") - .validate(x => parseValue(x).map(_ => ())) - .foreach(x => compilerOptions = compilerOptions.copy(backend = parseValue(x).toOption.get)) - .valueName(s"[:] default=$defaultValue") - .text("backend selection (run `help backend` to get full list of languages and dialects)") - end backendOption - backendOption - opt[Unit]("print-elaborate") - .abbr("pe") - .foreach(_ => elaborationOptions = elaborationOptions.copy(printDesignCodeAfter = true)) - .text("print the DFHDL design after elaboration") - opt[Unit]("print-compile") - .abbr("pc") - .foreach(_ => compilerOptions = compilerOptions.copy(printDesignCodeAfter = true)) - .text("print the DFHDL design after compilation") - opt[Unit]("print-backend") - .abbr("pb") - .foreach(_ => compilerOptions = compilerOptions.copy(printGenFiles = true)) - .text("print the backend design after compilation") - cmd("help") - .foreach(_ => mode = "help") - .text("Display usage text") - .children( - cmd("backend") - .foreach(_ => helpMode = "backend") - .text("List all backend languages and dialects"), - cmd("design-args") - .foreach(_ => helpMode = "design-args") - .text("List all design arguments") - ) - cmd("elaborate") - .foreach(_ => mode = "elaborate") - .text("Mode: Elaboration only (no compilation)") - cmd("compile") - .foreach(_ => mode = "compile") - .text("Mode: Compilation (after elaboration, and WITHOUT committing files to disk)") - cmd("commit") - .foreach(_ => mode = "commit") - .text("Mode: Committing to disk (after elaboration and compilation) [default]") - cmd("lint") - .foreach(_ => mode = "lint") - .text("Mode: Linting (after elaboration, compilation, and committing to disk)") - .children(optLinter) - private def listDesignArgs: Unit = - println("Design arguments:") - val titles = f"${"Name"}%-20s${"Type"}%-20s${"Default"}%-20sDescription" - println(titles) - println("-" * titles.length) - designArgs.values.foreach(a => - println(f"${a.name}%-20s${a.typeName}%-20s${a.valueStr}%-20s${a.desc}") - ) - private def listBackends: Unit = - println( - s"""|Available languages (see their dialects below): - |verilog - Verilog or SystemVerilog - |vhdl - VHDL - | - |Available Verilog/SystemVerilog dialects: - |v2001 - Verilog 2001 - |sv2005 - SystemVerilog 2005 [default] - |sv2012 - SystemVerilog 2012 - |sv2017 - SystemVerilog 2017 - | - |Available VHDL dialects: - |v93 - VHDL 1993 - |v2008 - VHDL 2008 [default] - |v2019 - VHDL 2019""".stripMargin - ) - end listBackends - - def main(args: Array[String]): Unit = - if (parser.parse(args, ()).isDefined) - mode match - case "help" => - helpMode match - case "backend" => listBackends - case "design-args" => listDesignArgs - case _ => println(parser.usage) - case "elaborate" => elaborate - case "compile" => elaborate.compile - case "commit" => elaborate.compile.commit - case "lint" => elaborate.compile.commit.lint - case _ => - end main -end DFApp diff --git a/lib/src/main/scala/dfhdl/app/BackendValueConverter.scala b/lib/src/main/scala/dfhdl/app/BackendValueConverter.scala new file mode 100644 index 000000000..18fb27288 --- /dev/null +++ b/lib/src/main/scala/dfhdl/app/BackendValueConverter.scala @@ -0,0 +1,33 @@ +package dfhdl.app +import dfhdl.options.CompilerOptions + +given SingleValueConverter[CompilerOptions.Backend] with + def parse( + arg: String + ): Either[String, Option[CompilerOptions.Backend]] = + arg.split("\\.").toList match + case lang :: Nil => + lang match + case "verilog" => Right(Some(dfhdl.backends.verilog)) + case "vhdl" => Right(Some(dfhdl.backends.vhdl)) + case _ => Left(s"Invalid backend language: $lang") + case lang :: dialect :: Nil => + lang match + case "verilog" => + dialect match + case "v2001" => Right(Some(dfhdl.backends.verilog.v2001)) + case "sv2005" => Right(Some(dfhdl.backends.verilog.sv2005)) + case "sv2012" => Right(Some(dfhdl.backends.verilog.sv2012)) + case "sv2017" => Right(Some(dfhdl.backends.verilog.sv2017)) + case _ => Left(s"Invalid Verilog/SystemVerilog backend dialect: $dialect") + case "vhdl" => + dialect match + case "v93" => Right(Some(dfhdl.backends.vhdl.v93)) + case "v2008" => Right(Some(dfhdl.backends.vhdl.v2008)) + case "v2019" => Right(Some(dfhdl.backends.vhdl.v2019)) + case _ => Left(s"Invalid VHDL backend dialect: $dialect") + case _ => Left(s"Invalid backend language: $lang") + case _ => Left("Invalid backend syntax. Found too many separator colons.") + end match + end parse +end given diff --git a/lib/src/main/scala/dfhdl/app/DFApp.scala b/lib/src/main/scala/dfhdl/app/DFApp.scala new file mode 100644 index 000000000..dab3aed78 --- /dev/null +++ b/lib/src/main/scala/dfhdl/app/DFApp.scala @@ -0,0 +1,132 @@ +package dfhdl.app +import dfhdl.* +import dfhdl.compiler.ir +import wvlet.log.{Logger, LogFormatter} +import scala.collection.mutable +import dfhdl.options.CompilerOptions +import org.rogach.scallop.* +import dfhdl.internals.sbtShellIsRunning + +trait DFApp: + private val logger = Logger("DFHDL App") + logger.setFormatter(LogFormatter.BareFormatter) + logger.info(s"Welcome to DFiant HDL (DFHDL) v$dfhdlVersion !!!") + private var designName: String = "" + private var topScalaPath: String = "" + // this context is just for enabling `getConstData` to work. + // the internal global context inside `value` will be actually at play here. + val dfc: DFC = DFC.emptyNoEO + + private var designArgs: DesignArgs = DesignArgs.empty + private var elaborationOptions: options.ElaborationOptions = null + private var compilerOptions: options.CompilerOptions = null + private var printerOptions: options.PrinterOptions = null + private var linterOptions: options.LinterOptions = null + private var appOptions: options.AppOptions = null + inline given options.CompilerOptions = compilerOptions + inline given options.PrinterOptions = printerOptions + inline given options.AppOptions = appOptions + private var dsn: () => core.Design = null + // used by the plugin to get the updated design arguments that could be changed by the + // command-line options + final protected def getDsnArg(name: String): Any = + designArgs(name).value + // used by the plugin to get the updated elaboration options that could be changed by the + // command-line options + final protected def getElaborationOptions: options.ElaborationOptions = elaborationOptions + final protected def setInitials( + _designName: String, + _topScalaPath: String, + top: dfhdl.top, + argNames: List[String], + argTypes: List[String], + argValues: List[Any], + argDescs: List[String] + ): Unit = + designName = _designName + topScalaPath = _topScalaPath + elaborationOptions = top.elaborationOptions + compilerOptions = top.compilerOptions + printerOptions = top.printerOptions + appOptions = top.appOptions + designArgs = DesignArgs(argNames, argTypes, argValues, argDescs) + end setInitials + final protected def setDsn(d: => core.Design): Unit = dsn = () => d + private def elaborate: core.Design = + logger.info("Elaborating design...") + // the elaboration options are set in the compiler plugin using getElaborationOptions + val elaborated = dsn() + if (elaborationOptions.printDesignCodeAfter) + println( + """|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + |The design code after elaboration: + |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~""".stripMargin + ) + elaborated.printCodeString + elaborated + + private def listBackends: Unit = + println( + s"""|Backend option pattern: -b [.] + | - the required backend language + | - the optional language dialect (each language has a default dialect) + |Examples: + |-b vhdl - VHDL v2008 (default dialect) + |-b verilog.v2001 - Verilog 2001 + | + |Available languages (see their dialects below): + |verilog - Verilog or SystemVerilog + |vhdl - VHDL + | + |Available Verilog/SystemVerilog dialects: + |v2001 - Verilog 2001 + |sv2005 - SystemVerilog 2005 [default] + |sv2012 - SystemVerilog 2012 + |sv2017 - SystemVerilog 2017 + | + |Available VHDL dialects: + |v93 - VHDL 1993 + |v2008 - VHDL 2008 [default] + |v2019 - VHDL 2019""".stripMargin + ) + end listBackends + + def main(commandArgs: Array[String]): Unit = + val parsedCommandLine = ParsedCommandLine(designName, topScalaPath, designArgs, commandArgs) + parsedCommandLine.getExitCodeOption match + case Some(code) => + if (!sbtShellIsRunning) sys.exit(code) + case None => + import parsedCommandLine.{Mode, HelpMode} + given CanEqual[ScallopConfBase, ScallopConfBase] = CanEqual.derived + // update design args from command line + designArgs = parsedCommandLine.updatedDesignArgs + // update elaboration options from command line + parsedCommandLine.mode match + case mode: Mode.ElaborateMode => + elaborationOptions = elaborationOptions.copy( + printDesignCodeAfter = mode.`print-elaborate`.toOption.get + ) + case _ => + // update compiler options from command line + parsedCommandLine.mode match + case mode: Mode.CompileMode => + compilerOptions = compilerOptions.copy( + backend = mode.backend.toOption.get, + printDesignCodeAfter = mode.`print-compile`.toOption.get, + printGenFiles = mode.`print-backend`.toOption.get + ) + case _ => + // execute command + parsedCommandLine.mode match + case help @ Mode.help => + help.subcommand match + case Some(HelpMode.backend) => listBackends + case _ => println(parsedCommandLine.getFullHelpString()) + case Mode.elaborate => elaborate + case Mode.compile => elaborate.compile + case Mode.commit => elaborate.compile.commit + case Mode.lint => elaborate.compile.commit.lint + end match + end main +end DFApp diff --git a/lib/src/main/scala/dfhdl/app/DesignArgs.scala b/lib/src/main/scala/dfhdl/app/DesignArgs.scala new file mode 100644 index 000000000..115768708 --- /dev/null +++ b/lib/src/main/scala/dfhdl/app/DesignArgs.scala @@ -0,0 +1,42 @@ +package dfhdl.app +import dfhdl.* +import core.{DFValAny, asValAny} +import scala.collection.immutable.ListMap + +case class DesignArg(name: String, typeName: String, value: Any, desc: String)(using DFC): + def getScalaValue: Any = + val data = value match + case dfConst: DFValAny => + import dfc.getSet + dfConst.asIR.getConstData.asInstanceOf[Option[Option[Any]]].get.get + case _ => value + data match + case bigInt: BigInt => bigInt.toInt + case _ => data + def updateScalaValue(updatedScalaValue: Any): DesignArg = + val updatedData = updatedScalaValue match + case int: Int => BigInt(int) + case _ => updatedScalaValue + val updatedValue = value match + case dfConst: DFValAny => + core.DFVal.Const.forced(dfConst.dfType, Some(updatedData)) + case _ => updatedData + copy(value = updatedValue) +end DesignArg + +type DesignArgs = ListMap[String, DesignArg] +object DesignArgs: + def empty: DesignArgs = ListMap.empty + def apply( + argNames: List[String], + argTypes: List[String], + argValues: List[Any], + argDescs: List[String] + ): DesignArgs = + ListMap.from( + argNames.lazyZip(argTypes).lazyZip(argValues).lazyZip(argDescs).map( + (name, typeName, value, desc) => name -> DesignArg(name, typeName, value, desc) + ) + ) + def apply(iter: Iterable[(String, DesignArg)]): DesignArgs = ListMap.from(iter) +end DesignArgs diff --git a/lib/src/main/scala/dfhdl/app/ParsedCommandLine.scala b/lib/src/main/scala/dfhdl/app/ParsedCommandLine.scala new file mode 100644 index 000000000..def9de1b3 --- /dev/null +++ b/lib/src/main/scala/dfhdl/app/ParsedCommandLine.scala @@ -0,0 +1,147 @@ +package dfhdl.app + +import org.rogach.scallop.* +import dfhdl.options.{CompilerOptions, ElaborationOptions, AppOptions} +import AppOptions.DefaultMode +import dfhdl.internals.scastieIsRunning +import dfhdl.internals.sbtShellIsRunning + +class ParsedCommandLine( + designName: String, + topScalaPath: String, + designArgs: DesignArgs, + commandArgs: Array[String] +)(using + eo: ElaborationOptions, + co: CompilerOptions, + ao: AppOptions +) extends ScallopConf(commandArgs.toSeq): + sealed abstract class Mode(val modeOption: DefaultMode, modeDesc: String) + extends Subcommand(modeOption.toString), + Product, + Serializable derives CanEqual: + if (modeOption == ao.defaultMode) + descr(s"$modeDesc [default]") + else + descr(modeDesc) + val help = opt[Boolean](hidden = true) + object Mode: + val helpFormatter = new ScallopHelpFormatter: + override protected def getSubcommandHeaderPrefix = "Mode: " + + trait ElaborateMode: + this: ScallopConf & Mode => + private val hidden = modeOption != DefaultMode.elaborate + val `print-elaborate` = opt[Boolean]( + descr = "print the DFHDL design after elaboration", + default = Some(eo.printDesignCodeAfter), + noshort = true, + hidden = hidden + ) + trait CompileMode extends ElaborateMode: + this: ScallopConf & Mode => + private val hidden = modeOption != DefaultMode.compile + val backend = opt[CompilerOptions.Backend]( + name = "backend", short = 'b', + descr = "backend selection (run `help backend` to get full list of languages and dialects)", + default = Some(co.backend), argName = "lang[.dialect]", hidden = hidden + ) + val `print-compile` = opt[Boolean]( + descr = "print the DFHDL design after compilation", + default = Some(co.printDesignCodeAfter), + hidden = hidden, + noshort = true + ) + val `print-backend` = opt[Boolean]( + descr = "print the backend design after compilation", + default = Some(co.printGenFiles), + hidden = hidden, + noshort = true + ) + end CompileMode + trait CommitMode extends CompileMode: + this: ScallopConf & Mode => + trait LintMode extends CommitMode: + this: ScallopConf & Mode => + case object elaborate + extends Mode(DefaultMode.elaborate, "Elaboration only (no compilation)"), + ElaborateMode + case object compile + extends Mode( + DefaultMode.compile, + "Compilation (after elaboration, and WITHOUT committing files to disk)" + ), + CompileMode: + footer(" ~~including all elaborate command options~~") + case object commit + extends Mode( + DefaultMode.commit, + "Committing to disk (after elaboration and compilation)" + ), + CommitMode: + footer(" ~~including all compile command options~~") + case object lint + extends Mode( + DefaultMode.lint, + "Linting (after elaboration, compilation, and committing to disk)" + ), + LintMode: + footer(" ~~including all commit command options~~") + case object help extends Mode(DefaultMode.help, "Display usage text"): + addSubcommand(HelpMode.backend) + end Mode + + sealed abstract class HelpMode(cmdName: String) extends Subcommand(cmdName), Product, Serializable + derives CanEqual: + val help = opt[Boolean](hidden = true) + object HelpMode: + case object backend extends HelpMode("backend"): + descr("List all backend languages and dialects") + + private val programName: String = + import dfhdl.internals.{sbtIsRunning, scala_cliIsRunning, sbtShellIsRunning} + if (scala_cliIsRunning) s"scala run . -M $topScalaPath --" + else if (sbtIsRunning) + if (sbtShellIsRunning) s"runMain $topScalaPath" + else s"""sbt "runMain $topScalaPath [options]"""" + else "" + + banner(s"Design Name: $designName\nUsage: $programName [design-args] [options]") + appendDefaultToDescription = true + helpFormatter = Mode.helpFormatter + private var exitCodeOption: Option[Int] = None + def getExitCodeOption: Option[Int] = exitCodeOption + exitHandler = code => exitCodeOption = Some(code) + private val designArgOptionGroup = group("Design arguments:") + private val designArgOptions = + for (designArg <- designArgs.values) + yield + val conv = designArg.typeName match + case "String" => summon[ValueConverter[String]] + case "Int" => summon[ValueConverter[Int]] + case "Double" => summon[ValueConverter[Double]] + case "Boolean" | "Bit" => summon[ValueConverter[Boolean]] + case _ => ??? + opt[Any]( + name = designArg.name, descr = designArg.desc, argName = designArg.typeName, + default = Some(designArg.getScalaValue), noshort = true, group = designArgOptionGroup + )(conv.asInstanceOf[ValueConverter[Any]]) + lazy val updatedDesignArgs: DesignArgs = DesignArgs(designArgs.lazyZip(designArgOptions).map { + case ((argName, designArg), opt) => + (argName, designArg.updateScalaValue(opt.toOption.get)) + }) + + addSubcommand(Mode.elaborate) + addSubcommand(Mode.compile) + addSubcommand(Mode.commit) + addSubcommand(Mode.lint) + addSubcommand(Mode.help) + lazy val mode: Mode = subcommand.getOrElse(ao.defaultMode match + case DefaultMode.help => Mode.help + case DefaultMode.elaborate => Mode.elaborate + case DefaultMode.compile => Mode.compile + case DefaultMode.commit => Mode.commit + case DefaultMode.lint => Mode.lint + ).asInstanceOf[Mode] + verify() +end ParsedCommandLine diff --git a/lib/src/main/scala/dfhdl/app/SingleValueConverter.scala b/lib/src/main/scala/dfhdl/app/SingleValueConverter.scala new file mode 100644 index 000000000..53fe1737e --- /dev/null +++ b/lib/src/main/scala/dfhdl/app/SingleValueConverter.scala @@ -0,0 +1,15 @@ +package dfhdl.app +import org.rogach.scallop.* + +trait SingleValueConverter[T] extends ValueConverter[T]: + def parse(arg: String): Either[String, Option[T]] + final def parse( + args: List[(String, List[String])] + ): Either[String, Option[T]] = + args match + case (_, arg :: Nil) :: Nil => parse(arg) + case _ => Right(None) + end parse + + final val argType = org.rogach.scallop.ArgType.SINGLE +end SingleValueConverter diff --git a/lib/src/main/scala/dfhdl/options/AppOptions.scala b/lib/src/main/scala/dfhdl/options/AppOptions.scala new file mode 100644 index 000000000..6b1ae777c --- /dev/null +++ b/lib/src/main/scala/dfhdl/options/AppOptions.scala @@ -0,0 +1,17 @@ +package dfhdl.options +import dfhdl.internals.scastieIsRunning +import AppOptions.* + +case class AppOptions( + defaultMode: DefaultMode +) + +object AppOptions: + given default(using + defaultMode: DefaultMode + ): AppOptions = AppOptions(defaultMode = defaultMode) + + enum DefaultMode derives CanEqual: + case help, elaborate, compile, commit, lint + object DefaultMode: + given DefaultMode = if (scastieIsRunning) compile else help diff --git a/lib/src/main/scala/dfhdl/top.scala b/lib/src/main/scala/dfhdl/top.scala index 8663c78ab..564b3286f 100644 --- a/lib/src/main/scala/dfhdl/top.scala +++ b/lib/src/main/scala/dfhdl/top.scala @@ -3,5 +3,6 @@ package dfhdl final case class top(genMain: Boolean = true)(using val elaborationOptions: dfhdl.options.ElaborationOptions, val compilerOptions: dfhdl.options.CompilerOptions, - val printerOptions: dfhdl.options.PrinterOptions + val printerOptions: dfhdl.options.PrinterOptions, + val appOptions: dfhdl.options.AppOptions ) extends scala.annotation.StaticAnnotation diff --git a/plugin/src/main/scala/plugin/MetaContextPlacerPhase.scala b/plugin/src/main/scala/plugin/MetaContextPlacerPhase.scala index f41a6618b..1267b26b7 100644 --- a/plugin/src/main/scala/plugin/MetaContextPlacerPhase.scala +++ b/plugin/src/main/scala/plugin/MetaContextPlacerPhase.scala @@ -287,7 +287,7 @@ class MetaContextPlacerPhase(setting: Setting) extends CommonPhase: hasClsMetaArgsTpe = requiredClassRef("dfhdl.internals.HasClsMetaArgs") clsMetaArgsTpe = requiredClassRef("dfhdl.internals.ClsMetaArgs") topAnnotSym = requiredClass("dfhdl.top") - appTpe = requiredClassRef("dfhdl.DFApp") + appTpe = requiredClassRef("dfhdl.app.DFApp") dfcArgStack = Nil ctx end MetaContextPlacerPhase diff --git a/plugin/src/main/scala/plugin/TopAnnotPhase.scala b/plugin/src/main/scala/plugin/TopAnnotPhase.scala index 14b84d22c..1f18f224b 100644 --- a/plugin/src/main/scala/plugin/TopAnnotPhase.scala +++ b/plugin/src/main/scala/plugin/TopAnnotPhase.scala @@ -79,13 +79,11 @@ class TopAnnotPhase(setting: Setting) extends CommonPhase: val dsnArgNames = mkList(paramVDs.map(vd => Literal(Constant(vd.name.toString)))) extension (vd: Type) def argType: Option[String] = - if (vd <:< defn.IntType) Some("Int") + if (vd <:< defn.IntType || vd <:< dfConstInt32Tpe) Some("Int") else if (vd <:< defn.StringType) Some("String") else if (vd <:< defn.DoubleType) Some("Double") - else if (vd <:< defn.BooleanType) Some("Boolean") - else if (vd <:< dfConstInt32Tpe) Some("DFHDL Int") - else if (vd <:< dfConstBoolTpe) Some("DFHDL Boolean") - else if (vd <:< dfConstBitTpe) Some("DFHDL Bit") + else if (vd <:< defn.BooleanType || vd <:< dfConstBoolTpe) Some("Boolean") + else if (vd <:< dfConstBitTpe) Some("Bit") else None val dsnArgTypes = mkList(paramVDs.map { vd => @@ -156,7 +154,7 @@ class TopAnnotPhase(setting: Setting) extends CommonPhase: override def prepareForUnit(tree: Tree)(using Context): Context = super.prepareForUnit(tree) topAnnotSym = requiredClass("dfhdl.top") - appTpe = requiredClassRef("dfhdl.DFApp") + appTpe = requiredClassRef("dfhdl.app.DFApp") dfConstBoolTpe = requiredClassRef("dfhdl.core.DFConstBool") dfConstBitTpe = requiredClassRef("dfhdl.core.DFConstBit") dfConstInt32Tpe = requiredClassRef("dfhdl.core.DFConstInt32") From 5d3a14c88ac39d9c6111a0e4ca0fdd13e1c80b62 Mon Sep 17 00:00:00 2001 From: oronpo Date: Tue, 27 Aug 2024 06:20:54 +0300 Subject: [PATCH 13/15] docs: no need for `PrintGenFiles = true` due to scastie special-casing --- lib/src/test/scala/docExamples/ALU.scala | 2 -- lib/src/test/scala/docExamples/Blinker.scala | 2 -- lib/src/test/scala/docExamples/Counter.scala | 2 -- lib/src/test/scala/docExamples/FullAdder1.scala | 2 -- lib/src/test/scala/docExamples/FullAdderN.scala | 2 -- lib/src/test/scala/docExamples/RegFile.scala | 2 -- lib/src/test/scala/docExamples/TrueDPR.scala | 2 -- lib/src/test/scala/docExamples/UART_Tx.scala | 2 -- 8 files changed, 16 deletions(-) diff --git a/lib/src/test/scala/docExamples/ALU.scala b/lib/src/test/scala/docExamples/ALU.scala index 38d0b6efa..dd1b95754 100644 --- a/lib/src/test/scala/docExamples/ALU.scala +++ b/lib/src/test/scala/docExamples/ALU.scala @@ -35,8 +35,6 @@ end ALU //////////////////////////////////////////////////////////////////////////////////////////////// // Select backend compiler: given options.CompilerOptions.Backend = backends.verilog -// Enables printing the generated chosen backend code: -given options.CompilerOptions.PrintGenFiles = true // Uncomment to enable printing design code after elaboration (before compilation): // given options.ElaborationOptions.PrintDesignCodeAfter = true // Uncomment to enable printing design code after compilation: diff --git a/lib/src/test/scala/docExamples/Blinker.scala b/lib/src/test/scala/docExamples/Blinker.scala index af951479c..987ca0d91 100644 --- a/lib/src/test/scala/docExamples/Blinker.scala +++ b/lib/src/test/scala/docExamples/Blinker.scala @@ -30,8 +30,6 @@ end Blinker //////////////////////////////////////////////////////////////////////////////////////////////// // Select backend compiler: given options.CompilerOptions.Backend = backends.verilog -// Enables printing the generated chosen backend code: -given options.CompilerOptions.PrintGenFiles = true // Uncomment to enable printing design code after elaboration (before compilation): // given options.ElaborationOptions.PrintDesignCodeAfter = true // Uncomment to enable printing design code after compilation: diff --git a/lib/src/test/scala/docExamples/Counter.scala b/lib/src/test/scala/docExamples/Counter.scala index 452a88221..60b23166a 100644 --- a/lib/src/test/scala/docExamples/Counter.scala +++ b/lib/src/test/scala/docExamples/Counter.scala @@ -19,8 +19,6 @@ import dfhdl.* //import all the DFHDL goodness //////////////////////////////////////////////////////////////////////////////////////////////// // Select backend compiler: given options.CompilerOptions.Backend = backends.verilog -// Enables printing the generated chosen backend code: -given options.CompilerOptions.PrintGenFiles = true // Uncomment to enable printing design code after elaboration (before compilation): // given options.ElaborationOptions.PrintDesignCodeAfter = true // Uncomment to enable printing design code after compilation: diff --git a/lib/src/test/scala/docExamples/FullAdder1.scala b/lib/src/test/scala/docExamples/FullAdder1.scala index 18fff5fbd..3478ea01c 100644 --- a/lib/src/test/scala/docExamples/FullAdder1.scala +++ b/lib/src/test/scala/docExamples/FullAdder1.scala @@ -14,8 +14,6 @@ import dfhdl.* //import all the DFHDL goodness //////////////////////////////////////////////////////////////////////////////////////////////// // Select backend compiler: given options.CompilerOptions.Backend = backends.vhdl -// Enables printing the generated chosen backend code: -given options.CompilerOptions.PrintGenFiles = true // Uncomment to enable printing design code after elaboration (before compilation): // given options.ElaborationOptions.PrintDesignCodeAfter = true // Uncomment to enable printing design code after compilation: diff --git a/lib/src/test/scala/docExamples/FullAdderN.scala b/lib/src/test/scala/docExamples/FullAdderN.scala index 1559fe24d..93c4df2c3 100644 --- a/lib/src/test/scala/docExamples/FullAdderN.scala +++ b/lib/src/test/scala/docExamples/FullAdderN.scala @@ -31,8 +31,6 @@ end FullAdderN //////////////////////////////////////////////////////////////////////////////////////////////// // Select backend compiler: given options.CompilerOptions.Backend = backends.verilog -// Enables printing the generated chosen backend code: -given options.CompilerOptions.PrintGenFiles = true // Uncomment to enable printing design code after elaboration (before compilation): // given options.ElaborationOptions.PrintDesignCodeAfter = true // Uncomment to enable printing design code after compilation: diff --git a/lib/src/test/scala/docExamples/RegFile.scala b/lib/src/test/scala/docExamples/RegFile.scala index c8f7def8e..ba9aaf738 100644 --- a/lib/src/test/scala/docExamples/RegFile.scala +++ b/lib/src/test/scala/docExamples/RegFile.scala @@ -32,8 +32,6 @@ end RegFile //////////////////////////////////////////////////////////////////////////////////////////////// // Select backend compiler: given options.CompilerOptions.Backend = backends.verilog -// Enables printing the generated chosen backend code: -given options.CompilerOptions.PrintGenFiles = true // Uncomment to enable printing design code after elaboration (before compilation): // given options.ElaborationOptions.PrintDesignCodeAfter = true // Uncomment to enable printing design code after compilation: diff --git a/lib/src/test/scala/docExamples/TrueDPR.scala b/lib/src/test/scala/docExamples/TrueDPR.scala index b4d1f87e2..8f1ba43f3 100644 --- a/lib/src/test/scala/docExamples/TrueDPR.scala +++ b/lib/src/test/scala/docExamples/TrueDPR.scala @@ -30,8 +30,6 @@ end TrueDPR //////////////////////////////////////////////////////////////////////////////////////////////// // Select backend compiler: given options.CompilerOptions.Backend = backends.verilog -// Enables printing the generated chosen backend code: -given options.CompilerOptions.PrintGenFiles = true // Uncomment to enable printing design code after elaboration (before compilation): // given options.ElaborationOptions.PrintDesignCodeAfter = true // Uncomment to enable printing design code after compilation: diff --git a/lib/src/test/scala/docExamples/UART_Tx.scala b/lib/src/test/scala/docExamples/UART_Tx.scala index f16be4ebd..e73bee632 100644 --- a/lib/src/test/scala/docExamples/UART_Tx.scala +++ b/lib/src/test/scala/docExamples/UART_Tx.scala @@ -82,8 +82,6 @@ end UART_Tx //////////////////////////////////////////////////////////////////////////////////////////////// // Select backend compiler: given options.CompilerOptions.Backend = backends.verilog -// Enables printing the generated chosen backend code: -given options.CompilerOptions.PrintGenFiles = true // Uncomment to enable printing design code after elaboration (before compilation): // given options.ElaborationOptions.PrintDesignCodeAfter = true // Uncomment to enable printing design code after compilation: From 626204d004631a62d8c2207a590221d48734431f Mon Sep 17 00:00:00 2001 From: oronpo Date: Tue, 27 Aug 2024 07:05:30 +0300 Subject: [PATCH 14/15] fix relative path saved in meta position after publishing the plugin and running with scala-cli --- .../scala/dfhdl/internals/MetaContext.scala | 7 +++++++ .../main/scala/dfhdl/internals/helpers.scala | 6 ++++++ plugin/src/main/scala/plugin/CommonPhase.scala | 17 +++++------------ 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/internals/src/main/scala/dfhdl/internals/MetaContext.scala b/internals/src/main/scala/dfhdl/internals/MetaContext.scala index 0239ba0fb..76516b27b 100644 --- a/internals/src/main/scala/dfhdl/internals/MetaContext.scala +++ b/internals/src/main/scala/dfhdl/internals/MetaContext.scala @@ -14,6 +14,13 @@ final case class Position( object Position: val unknown = Position("", 0, 0, 0, 0) + def fromAbsPath( + fileAbsPath: String, + lineStart: Int, + columnStart: Int, + lineEnd: Int, + columnEnd: Int + ): Position = Position(getRelativePath(fileAbsPath), lineStart, columnStart, lineEnd, columnEnd) trait MetaContext: def setMeta( diff --git a/internals/src/main/scala/dfhdl/internals/helpers.scala b/internals/src/main/scala/dfhdl/internals/helpers.scala index ccf711ef0..8b86a94a4 100644 --- a/internals/src/main/scala/dfhdl/internals/helpers.scala +++ b/internals/src/main/scala/dfhdl/internals/helpers.scala @@ -373,3 +373,9 @@ lazy val scala_cliIsRunning: Boolean = getShellCommand.exists(_.contains(".scala // detecting if running in Scastie by checking the PWD lazy val scastieIsRunning: Boolean = System.getProperty("user.dir").startsWith("/tmp/scastie") + +def getRelativePath(absolutePathStr: String): String = + import java.nio.file.Paths + val absolutePath = Paths.get(absolutePathStr).toAbsolutePath() + val currentDir = Paths.get("").toAbsolutePath() + currentDir.relativize(absolutePath).toString diff --git a/plugin/src/main/scala/plugin/CommonPhase.scala b/plugin/src/main/scala/plugin/CommonPhase.scala index 72b297c79..1700bf684 100755 --- a/plugin/src/main/scala/plugin/CommonPhase.scala +++ b/plugin/src/main/scala/plugin/CommonPhase.scala @@ -93,7 +93,7 @@ abstract class CommonPhase extends PluginPhase: var metaContextIgnoreAnnotSym: ClassSymbol = uninitialized var metaContextForwardAnnotSym: ClassSymbol = uninitialized var metaGenSym: Symbol = uninitialized - var positionCls: ClassSymbol = uninitialized + var positionGenSym: TermSymbol = uninitialized var contextFunctionSym: Symbol = uninitialized var hasDFCTpe: TypeRef = uninitialized var inlineAnnotSym: Symbol = uninitialized @@ -328,24 +328,17 @@ abstract class CommonPhase extends PluginPhase: case _ => None end ContextArg - def getRelativePath(absolutePathStr: String): String = - import java.nio.file.Paths - val absolutePath = Paths.get(absolutePathStr).toAbsolutePath() - val currentDir = Paths.get(System.getProperty("user.dir")).toAbsolutePath() - currentDir.relativize(absolutePath).toString - extension (srcPos: util.SrcPos)(using Context) def positionTree: Tree = if (srcPos.span == util.Spans.NoSpan) ref(requiredMethod("dfhdl.internals.Position.unknown")) else - val fileNameTree = Literal(Constant(getRelativePath(srcPos.startPos.source.path))) + val fileNameTree = Literal(Constant(srcPos.startPos.source.path)) val lineStartTree = Literal(Constant(srcPos.startPos.line + 1)) val columnStartTree = Literal(Constant(srcPos.startPos.column + 1)) val lineEndTree = Literal(Constant(srcPos.endPos.line + 1)) val columnEndTree = Literal(Constant(srcPos.endPos.column + 1)) - New( - positionCls.typeRef, - fileNameTree :: lineStartTree :: columnStartTree :: lineEndTree :: columnEndTree :: Nil + ref(positionGenSym).appliedTo( + fileNameTree, lineStartTree, columnStartTree, lineEndTree, columnEndTree ) end extension @@ -371,7 +364,7 @@ abstract class CommonPhase extends PluginPhase: metaContextIgnoreAnnotSym = requiredClass("dfhdl.internals.metaContextIgnore") metaContextForwardAnnotSym = requiredClass("dfhdl.internals.metaContextForward") metaGenSym = requiredMethod("dfhdl.compiler.ir.Meta.gen") - positionCls = requiredClass("dfhdl.internals.Position") + positionGenSym = requiredMethod("dfhdl.internals.Position.fromAbsPath") hasDFCTpe = requiredClassRef("dfhdl.core.HasDFC") inlineAnnotSym = requiredClass("scala.inline") constModTpe = requiredClassRef("dfhdl.core.ISCONST").appliedTo(ConstantType(Constant(true))) From ba5a24cad5652af2015e2a7b7f9e5aaa4fbbf121 Mon Sep 17 00:00:00 2001 From: oronpo Date: Tue, 27 Aug 2024 07:21:44 +0300 Subject: [PATCH 15/15] add more application logging --- lib/src/main/scala/dfhdl/app/DFApp.scala | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/lib/src/main/scala/dfhdl/app/DFApp.scala b/lib/src/main/scala/dfhdl/app/DFApp.scala index dab3aed78..bf3ccf348 100644 --- a/lib/src/main/scala/dfhdl/app/DFApp.scala +++ b/lib/src/main/scala/dfhdl/app/DFApp.scala @@ -6,6 +6,7 @@ import scala.collection.mutable import dfhdl.options.CompilerOptions import org.rogach.scallop.* import dfhdl.internals.sbtShellIsRunning +import scala.util.chaining.scalaUtilChainingOps trait DFApp: private val logger = Logger("DFHDL App") @@ -65,6 +66,15 @@ trait DFApp: elaborated.printCodeString elaborated + private inline def compile = + elaborate.tap(_ => logger.info("Compiling design...")).compile + + private inline def commit = + compile.tap(_ => logger.info("Committing backend files to disk...")).commit + + private inline def lint = + commit.tap(_ => logger.info("Running external linter...")).lint + private def listBackends: Unit = println( s"""|Backend option pattern: -b [.] @@ -124,9 +134,9 @@ trait DFApp: case Some(HelpMode.backend) => listBackends case _ => println(parsedCommandLine.getFullHelpString()) case Mode.elaborate => elaborate - case Mode.compile => elaborate.compile - case Mode.commit => elaborate.compile.commit - case Mode.lint => elaborate.compile.commit.lint + case Mode.compile => compile + case Mode.commit => commit + case Mode.lint => lint end match end main end DFApp