Skip to content

Commit f446fff

Browse files
Report firtool version when firtool invocation errors (backport #3174) (#3175)
* Report firtool version when firtool invocation errors (#3174) * the firtool version is now included in the BuildInfo * firtool now must be on the path when publishing, but is not required for building or testing * FirtoolNonZeroExitCode now no longer includes a stack trace (cherry picked from commit 06b569d) # Conflicts: # build.sbt * Resolve backport conflicts * [CI] Install firtool in the publish step (#3176) --------- Co-authored-by: Jack Koenig <koenig@sifive.com>
1 parent 3ef3ea2 commit f446fff

File tree

4 files changed

+40
-2
lines changed

4 files changed

+40
-2
lines changed

.github/workflows/test.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,8 @@ jobs:
195195
steps:
196196
- name: Checkout
197197
uses: actions/checkout@v3
198+
- name: Install CIRCT
199+
uses: ./.github/workflows/install-circt
198200
- name: Setup Scala
199201
uses: actions/setup-java@v3
200202
with:

build.sbt

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,18 @@ enablePlugins(SiteScaladocPlugin)
55
addCommandAlias("fmt", "; scalafmtAll ; scalafmtSbt")
66
addCommandAlias("fmtCheck", "; scalafmtCheckAll ; scalafmtSbtCheck")
77

8+
lazy val firtoolVersion = settingKey[Option[String]]("Determine the version of firtool on the PATH")
9+
ThisBuild / firtoolVersion := {
10+
import scala.sys.process._
11+
val Version = """^CIRCT firtool-(\S+)$""".r
12+
try {
13+
val lines = Process(Seq("firtool", "--version")).lineStream
14+
lines.collectFirst { case Version(v) => v }
15+
} catch {
16+
case e: java.io.IOException => None
17+
}
18+
}
19+
820
val defaultVersions = Map(
921
"firrtl" -> "edu.berkeley.cs" %% "firrtl" % "1.6-SNAPSHOT"
1022
// chiseltest intentionally excluded so that release automation does not try to set its version
@@ -69,6 +81,16 @@ lazy val publishSettings = Seq(
6981
versionScheme := Some("pvp"),
7082
publishMavenStyle := true,
7183
Test / publishArtifact := false,
84+
// We are just using 'publish / skip' as a hook to run checks required for publishing,
85+
// but that are not necessarily required for local development or running testing in CI
86+
publish / skip := {
87+
// Check that firtool exists on the PATH so Chisel can use the version it was tested against
88+
// in error messages
89+
if (firtoolVersion.value.isEmpty) {
90+
sys.error(s"Failed to determine firtool version. Make sure firtool is found on the PATH.")
91+
}
92+
(publish / skip).value
93+
},
7294
pomIncludeRepository := { x => false },
7395
pomExtra := <url>http://chisel.eecs.berkeley.edu/</url>
7496
<licenses>
@@ -197,7 +219,7 @@ lazy val core = (project in file("core"))
197219
.settings(
198220
buildInfoPackage := "chisel3",
199221
buildInfoUsePackageAsPath := true,
200-
buildInfoKeys := Seq[BuildInfoKey](buildInfoPackage, version, scalaVersion, sbtVersion)
222+
buildInfoKeys := Seq[BuildInfoKey](buildInfoPackage, version, scalaVersion, sbtVersion, firtoolVersion)
201223
)
202224
.settings(publishSettings: _*)
203225
.settings(mimaPreviousArtifacts := Set())

src/main/scala/circt/stage/phases/CIRCT.scala

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package circt.stage.phases
44

55
import chisel3.experimental.hierarchy.core.ImportDefinitionAnnotation
66
import chisel3.stage.{ChiselCircuitAnnotation, DesignAnnotation, SourceRootAnnotation}
7+
import chisel3.BuildInfo.{version => chiselVersion, firtoolVersion}
78

89
import circt.Implicits.BooleanImplicits
910
import circt.stage.{CIRCTOptions, CIRCTTarget, EmittedMLIR, PreserveAggregate}
@@ -26,6 +27,7 @@ import firrtl.stage.{FirrtlOptions, RunFirrtlTransformAnnotation}
2627
import _root_.logger.LogLevel
2728
import chisel3.InternalErrorException
2829

30+
import scala.util.control.NoStackTrace
2931
import scala.collection.mutable
3032
import java.io.File
3133

@@ -81,6 +83,10 @@ private[this] object Exceptions {
8183
|${"-" * 78}""".stripMargin
8284
}
8385

86+
def versionAdvice: String =
87+
s"Note that this version of Chisel ($chiselVersion) was published against firtool version " +
88+
firtoolVersion.getOrElse("<unknown>") + "."
89+
8490
/** Indicates that the firtool binary failed with a non-zero exit code. This generally indicates a compiler error
8591
* either originating from a user error or from a crash.
8692
*
@@ -92,10 +98,11 @@ private[this] object Exceptions {
9298
class FirtoolNonZeroExitCode(binary: String, exitCode: Int, stdout: String, stderr: String)
9399
extends RuntimeException(
94100
dramaticError(
95-
header = s"${binary} returned a non-zero exit code",
101+
header = s"${binary} returned a non-zero exit code. $versionAdvice",
96102
body = s"ExitCode:\n${exitCode}\nSTDOUT:\n${stdout}\nSTDERR:\n${stderr}"
97103
)
98104
)
105+
with NoStackTrace
99106

100107
/** Indicates that the firtool binary was not found. This likely indicates that the user didn't install
101108
* CIRCT/firtool.

src/test/scala/circtTests/stage/ChiselStageSpec.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,13 @@ class ChiselStageSpec extends AnyFunSpec with Matchers with chiselTests.Utils {
503503
lines(idx + 2) should equal(" ^")
504504
}
505505

506+
it("should report the firtool version against which Chisel was published in error messages") {
507+
val e = intercept[java.lang.Exception] {
508+
ChiselStage.emitSystemVerilog(new ChiselStageSpec.ErrorCaughtByFirtool)
509+
}
510+
val version = chisel3.BuildInfo.firtoolVersion.getOrElse("<unknown>")
511+
e.getMessage should include(s"firtool version $version")
512+
}
506513
}
507514

508515
describe("ChiselStage custom transform support") {

0 commit comments

Comments
 (0)