From 2d48221e45d73279dd75f2cf48d1b56df4e9dc4d Mon Sep 17 00:00:00 2001 From: Johannes Wirth Date: Tue, 30 Sep 2025 18:20:38 +0200 Subject: [PATCH] First toolflow version --- init-workspace.sh | 29 ++++ scripts/build_hammer.sh | 7 + toolflow/.gitignore | 144 ++++++++++++++++++ toolflow/README.md | 8 + toolflow/build.sbt | 15 ++ toolflow/project/build.properties | 1 + toolflow/project/plugins.sbt | 1 + .../scala/com/minres/tgc/hammer/Global.scala | 10 ++ .../scala/com/minres/tgc/hammer/Main.scala | 17 +++ .../minres/tgc/hammer/cli/HammerConf.scala | 9 ++ .../minres/tgc/hammer/cli/MySubcommand.scala | 8 + .../tgc/hammer/cli/TreenailCommand.scala | 19 +++ .../com/minres/tgc/hammer/tasks/Task.scala | 12 ++ .../tgc/hammer/tasks/TreenailTask.scala | 16 ++ toolflow/src/test/scala/MySuite.scala | 9 ++ 15 files changed, 305 insertions(+) create mode 100644 init-workspace.sh create mode 100644 scripts/build_hammer.sh create mode 100644 toolflow/.gitignore create mode 100644 toolflow/README.md create mode 100644 toolflow/build.sbt create mode 100644 toolflow/project/build.properties create mode 100644 toolflow/project/plugins.sbt create mode 100644 toolflow/src/main/scala/com/minres/tgc/hammer/Global.scala create mode 100644 toolflow/src/main/scala/com/minres/tgc/hammer/Main.scala create mode 100644 toolflow/src/main/scala/com/minres/tgc/hammer/cli/HammerConf.scala create mode 100644 toolflow/src/main/scala/com/minres/tgc/hammer/cli/MySubcommand.scala create mode 100644 toolflow/src/main/scala/com/minres/tgc/hammer/cli/TreenailCommand.scala create mode 100644 toolflow/src/main/scala/com/minres/tgc/hammer/tasks/Task.scala create mode 100644 toolflow/src/main/scala/com/minres/tgc/hammer/tasks/TreenailTask.scala create mode 100644 toolflow/src/test/scala/MySuite.scala diff --git a/init-workspace.sh b/init-workspace.sh new file mode 100644 index 0000000..b8d7e86 --- /dev/null +++ b/init-workspace.sh @@ -0,0 +1,29 @@ + +if [ -n "$BASH_VERSION" ]; then + command -v xargs > /dev/null || { echo >&2 "ERROR: xargs program not available."; } + + if [ "`uname`" = "Darwin" ]; then + export TGC_HAMMER_HOME=`dirname ${BASH_SOURCE[0]} | xargs cd | pwd` + else + command -v realpath > /dev/null || command -v readlink > /dev/null || { echo "ERROR: neither realpath nor readlink programs are available."; } + command -v xargs > /dev/null && command -v realpath > /dev/null && export TGC_HAMMER_HOME=`dirname ${BASH_SOURCE[0]} | xargs realpath` + command -v xargs > /dev/null && command -v readlink > /dev/null && export TGC_HAMMER_HOME=`dirname ${BASH_SOURCE[0]} | xargs readlink -f` + fi +elif [ -n "$ZSH_VERSION" ]; then + command -v realpath > /dev/null || command -v readlink > /dev/null || { echo "ERROR: neither realpath nor readlink programs are available."; } + command -v xargs > /dev/null && command -v realpath > /dev/null && export TGC_HAMMER_HOME=`dirname ${(%):-%x} | xargs realpath` + command -v xargs > /dev/null && command -v readlink > /dev/null && export TGC_HAMMER_HOME=`dirname ${(%):-%x} | xargs readlink -f` +else + echo "ERROR: unknown shell" +elif [ -f "source.sh" ]; then + echo "Directory already seems to be workspace." +elif [ -f "init-workspace.sh" ]; then + echo "Cannot create workspace in TGC-Hammer directly, use different directory." +else + echo "Creating workspace ..." + echo "export TGC_HAMMER_HOME=\"${TGC_HAMMER_HOME}\"" > source.sh + echo "export TGC_HAMMER_WORKDIR=\"$PWD\"" >> source.sh + echo "export PATH=\"${TGC_HAMMER_HOME}/toolflow/target/universal/stage/bin:$PATH\"" >> source.sh + + mkdir -p output +fi \ No newline at end of file diff --git a/scripts/build_hammer.sh b/scripts/build_hammer.sh new file mode 100644 index 0000000..3c05ee7 --- /dev/null +++ b/scripts/build_hammer.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +pushd toolflow + +sbt stage + +popd diff --git a/toolflow/.gitignore b/toolflow/.gitignore new file mode 100644 index 0000000..f402cef --- /dev/null +++ b/toolflow/.gitignore @@ -0,0 +1,144 @@ +# Created by https://www.toptal.com/developers/gitignore/api/scala,intellij,sbt +# Edit at https://www.toptal.com/developers/gitignore?templates=scala,intellij,sbt + +### Intellij ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### Intellij Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + +# Sonarlint plugin +# https://plugins.jetbrains.com/plugin/7973-sonarlint +.idea/**/sonarlint/ + +# SonarQube Plugin +# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin +.idea/**/sonarIssues.xml + +# Markdown Navigator plugin +# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced +.idea/**/markdown-navigator.xml +.idea/**/markdown-navigator-enh.xml +.idea/**/markdown-navigator/ + +# Cache file creation bug +# See https://youtrack.jetbrains.com/issue/JBR-2257 +.idea/$CACHE_FILE$ + +# CodeStream plugin +# https://plugins.jetbrains.com/plugin/12206-codestream +.idea/codestream.xml + +# Azure Toolkit for IntelliJ plugin +# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij +.idea/**/azureSettings.xml + +### SBT ### +# Simple Build Tool +# http://www.scala-sbt.org/release/docs/Getting-Started/Directories.html#configuring-version-control + +dist/* +target/ +lib_managed/ +src_managed/ +project/boot/ +project/plugins/project/ +.history +.cache +.lib/ + +### SBT Patch ### +.bsp/ + +### Scala ### +*.class +*.log + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +# End of https://www.toptal.com/developers/gitignore/api/scala,intellij,sbt + + +.idea/ \ No newline at end of file diff --git a/toolflow/README.md b/toolflow/README.md new file mode 100644 index 0000000..102c5ca --- /dev/null +++ b/toolflow/README.md @@ -0,0 +1,8 @@ +## sbt project compiled with Scala 3 + +### Usage + +This is a normal sbt project. You can compile code with `sbt compile`, run it with `sbt run`, and `sbt console` will start a Scala 3 REPL. + +For more information on the sbt-dotty plugin, see the +[scala3-example-project](https://github.com/scala/scala3-example-project/blob/main/README.md). diff --git a/toolflow/build.sbt b/toolflow/build.sbt new file mode 100644 index 0000000..c3f0ab2 --- /dev/null +++ b/toolflow/build.sbt @@ -0,0 +1,15 @@ +val scala3Version = "3.7.3" + +lazy val root = project + .in(file(".")) + .enablePlugins(JavaAppPackaging) + .settings( + name := "tgc-hammer", + version := "0.1.0-SNAPSHOT", + + scalaVersion := scala3Version, + + libraryDependencies += "org.rogach" %% "scallop" % "5.2.0", + libraryDependencies += "com.lihaoyi" %% "os-lib" % "0.11.5", + libraryDependencies += "org.scalameta" %% "munit" % "1.2.0" % Test + ) diff --git a/toolflow/project/build.properties b/toolflow/project/build.properties new file mode 100644 index 0000000..5e6884d --- /dev/null +++ b/toolflow/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.11.6 diff --git a/toolflow/project/plugins.sbt b/toolflow/project/plugins.sbt new file mode 100644 index 0000000..bab8e7e --- /dev/null +++ b/toolflow/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("com.github.sbt" % "sbt-native-packager" % "1.11.1") \ No newline at end of file diff --git a/toolflow/src/main/scala/com/minres/tgc/hammer/Global.scala b/toolflow/src/main/scala/com/minres/tgc/hammer/Global.scala new file mode 100644 index 0000000..04d0854 --- /dev/null +++ b/toolflow/src/main/scala/com/minres/tgc/hammer/Global.scala @@ -0,0 +1,10 @@ +package com.minres.tgc.hammer + +import os.Path + +object Global { + def pathFromEnv(env: String): Option[Path] = sys.env.get("string").map { rawPath => Path(rawPath, os.pwd) } + lazy val HAMMER: Path = pathFromEnv("TGC_HAMMER_HOME").get + lazy val WORKDIR: Path = pathFromEnv("TGC_HAMMER_WORKDIR").get + lazy val TREENAIL: Path = HAMMER / "deps" / "treenail" +} diff --git a/toolflow/src/main/scala/com/minres/tgc/hammer/Main.scala b/toolflow/src/main/scala/com/minres/tgc/hammer/Main.scala new file mode 100644 index 0000000..5f97653 --- /dev/null +++ b/toolflow/src/main/scala/com/minres/tgc/hammer/Main.scala @@ -0,0 +1,17 @@ +package com.minres.tgc.hammer + +import com.minres.tgc.hammer.cli.{HammerConf, MySubcommand} + +object Main { + def main(args: Array[String]): Unit = { + val conf = new HammerConf(args.toIndexedSeq) + + conf.subcommand match { + case Some(c: MySubcommand) => + val tasks = c.getRequiredTasks + tasks.foreach(_.validate()) + tasks.foreach(_.execute()) + case _ => + } + } +} diff --git a/toolflow/src/main/scala/com/minres/tgc/hammer/cli/HammerConf.scala b/toolflow/src/main/scala/com/minres/tgc/hammer/cli/HammerConf.scala new file mode 100644 index 0000000..d5f6187 --- /dev/null +++ b/toolflow/src/main/scala/com/minres/tgc/hammer/cli/HammerConf.scala @@ -0,0 +1,9 @@ +package com.minres.tgc.hammer.cli + +import org.rogach.scallop.ScallopConf + +class HammerConf(arguments: Seq[String]) extends ScallopConf(arguments) { + addSubcommand(new TreenailCommand) + + verify() +} diff --git a/toolflow/src/main/scala/com/minres/tgc/hammer/cli/MySubcommand.scala b/toolflow/src/main/scala/com/minres/tgc/hammer/cli/MySubcommand.scala new file mode 100644 index 0000000..92dcbad --- /dev/null +++ b/toolflow/src/main/scala/com/minres/tgc/hammer/cli/MySubcommand.scala @@ -0,0 +1,8 @@ +package com.minres.tgc.hammer.cli + +import com.minres.tgc.hammer.tasks.Task +import org.rogach.scallop.Subcommand + +abstract class MySubcommand(name: String) extends Subcommand(name) { + def getRequiredTasks: Seq[Task] +} diff --git a/toolflow/src/main/scala/com/minres/tgc/hammer/cli/TreenailCommand.scala b/toolflow/src/main/scala/com/minres/tgc/hammer/cli/TreenailCommand.scala new file mode 100644 index 0000000..930abc8 --- /dev/null +++ b/toolflow/src/main/scala/com/minres/tgc/hammer/cli/TreenailCommand.scala @@ -0,0 +1,19 @@ +package com.minres.tgc.hammer.cli + +import com.minres.tgc.hammer.tasks.{Task, TreenailTask} +import org.rogach.scallop.* + +import java.io.File +import os.Path + +class TreenailCommand extends MySubcommand("parseCoreDSL") { + val coreDSL: ScallopOption[File] = trailArg[File]("coreDSL") + val output: ScallopOption[File] = opt[File](short = 'o', default = Some(new File("isax.mlir"))) + + validateFileExists(coreDSL) + validateFileIsFile(coreDSL) + + override def getRequiredTasks: Seq[Task] = Seq( + new TreenailTask(Path(coreDSL(), os.pwd), Path(output(), os.pwd)) + ) +} diff --git a/toolflow/src/main/scala/com/minres/tgc/hammer/tasks/Task.scala b/toolflow/src/main/scala/com/minres/tgc/hammer/tasks/Task.scala new file mode 100644 index 0000000..7f3f086 --- /dev/null +++ b/toolflow/src/main/scala/com/minres/tgc/hammer/tasks/Task.scala @@ -0,0 +1,12 @@ +package com.minres.tgc.hammer.tasks + +import os.{Path, Shellable} + +trait Task { + def validate(): Unit + def execute(): Unit + + def runExecutable(execPath: Path, args: Shellable*): os.CommandResult = { + os.proc(execPath, args).call() + } +} diff --git a/toolflow/src/main/scala/com/minres/tgc/hammer/tasks/TreenailTask.scala b/toolflow/src/main/scala/com/minres/tgc/hammer/tasks/TreenailTask.scala new file mode 100644 index 0000000..b5d1097 --- /dev/null +++ b/toolflow/src/main/scala/com/minres/tgc/hammer/tasks/TreenailTask.scala @@ -0,0 +1,16 @@ +package com.minres.tgc.hammer.tasks + +import com.minres.tgc.hammer.Global + +import os.* + +class TreenailTask(coreDSLInput: Path, output: Path) extends Task { + private val EXECUTABLE = Global.TREENAIL / "app" / "build" / "install" / "app" / "bin" / "app" + + override def validate(): Unit = { + assert(isFile(EXECUTABLE), "Treenail Executable is missing, build Treenail") + } + override def execute(): Unit = { + runExecutable(EXECUTABLE, "-o", output, coreDSLInput) + } +} diff --git a/toolflow/src/test/scala/MySuite.scala b/toolflow/src/test/scala/MySuite.scala new file mode 100644 index 0000000..621784d --- /dev/null +++ b/toolflow/src/test/scala/MySuite.scala @@ -0,0 +1,9 @@ +// For more information on writing tests, see +// https://scalameta.org/munit/docs/getting-started.html +class MySuite extends munit.FunSuite { + test("example test that succeeds") { + val obtained = 42 + val expected = 42 + assertEquals(obtained, expected) + } +}