Skip to content

Commit

Permalink
Scala 3 Cross-Compilation Support (#14)
Browse files Browse the repository at this point in the history
* slowly porting over changes for scala 3 to check for test failures

* more fixes, shouldnt break anything yet

* more fixes, shouldnt break anything yet 2

* final batch of fixes before the potentially impactful stuff

* remove scala-reflect, try another way to check if an object is a singleton

* bump oss cad suite version

* add scala 3 cross, revert oss-cad-suite version

* fix formatting

* unidoc only on scala 2.13

* remove failing JSON test

---------

Co-authored-by: Kevin Läufer <laeufer@cs.berkeley.edu>
  • Loading branch information
vighneshiyer and ekiwi committed May 10, 2023
1 parent 811d767 commit 62db135
Show file tree
Hide file tree
Showing 63 changed files with 141 additions and 142 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
scala: [2.13.10]
scala: ["2.13.10", "3.2.2"]

steps:
- name: Checkout
Expand All @@ -33,7 +33,8 @@ jobs:
- name: Check Formatting (Scala 2.13 only)
if: startsWith(matrix.scala, '2.13')
run: sbt ++${{ matrix.scala }} scalafmtCheckAll
- name: Unidoc
- name: Unidoc (Scala 2.13 only)
if: startsWith(matrix.scala, '2.13')
run: sbt ++${{ matrix.scala }} unidoc
- name: Sanity check benchmarking scripts (Scala 2.13 only)
if: startsWith(matrix.scala, '2.13')
Expand Down
8 changes: 3 additions & 5 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ enablePlugins(SiteScaladocPlugin)

lazy val commonSettings = Seq(
organization := "edu.berkeley.cs",
scalaVersion := "2.13.10",
crossScalaVersions := Seq("2.13.10")
scalaVersion := "3.2.2",
crossScalaVersions := Seq("2.13.10", "3.2.2")
)

lazy val firrtlSettings = Seq(
Expand All @@ -16,13 +16,11 @@ lazy val firrtlSettings = Seq(
"-unchecked",
"-language:reflectiveCalls",
"-language:existentials",
"-language:implicitConversions",
"-Yrangepos" // required by SemanticDB compiler plugin
"-language:implicitConversions"
),
// Always target Java8 for maximum compatibility
javacOptions ++= Seq("-source", "1.8", "-target", "1.8"),
libraryDependencies ++= Seq(
"org.scala-lang" % "scala-reflect" % scalaVersion.value,
"org.scalatest" %% "scalatest" % "3.2.14" % "test",
"org.scalatestplus" %% "scalacheck-1-15" % "3.2.11.0" % "test",
"com.github.scopt" %% "scopt" % "4.1.0",
Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/firrtl/AddDescriptionNodes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -215,11 +215,11 @@ class AddDescriptionNodes extends Transform with DependencyAPIMigration {
val (docs: Seq[DocString] @unchecked, nodocs) = descs.partition {
case _: DocString => true
case _ => false
}
}: @unchecked
val (attrs: Seq[Attribute] @unchecked, rest) = nodocs.partition {
case _: Attribute => true
case _ => false
}
}: @unchecked

val doc = if (docs.nonEmpty) {
Seq(DocString(StringLit.unescape(docs.map(_.string.string).mkString("\n\n"))))
Expand Down
8 changes: 0 additions & 8 deletions src/main/scala/firrtl/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,6 @@ import firrtl.options.{Dependency, DependencyAPI, StageUtils, TransformLike}
import firrtl.stage.Forms
import firrtl.transforms.DedupAnnotationsTransform

/** Container of all annotations for a Firrtl compiler */
class AnnotationSeq private (underlying: Seq[Annotation]) {
def toSeq: Seq[Annotation] = underlying
}
object AnnotationSeq {
def apply(xs: Seq[Annotation]): AnnotationSeq = new AnnotationSeq(xs)
}

/** Current State of the Circuit
*
* @constructor Creates a CircuitState object
Expand Down
1 change: 1 addition & 0 deletions src/main/scala/firrtl/Emitter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import firrtl.options.Viewer.view
import firrtl.options.{CustomFileEmission, Dependency, HasShellOptions, PhaseException, ShellOption}
import firrtl.passes.PassException
import firrtl.stage.{FirrtlFileAnnotation, FirrtlOptions, RunFirrtlTransformAnnotation}
import firrtl.stage.FirrtlOptionsView

case class EmitterException(message: String) extends PassException(message)

Expand Down
14 changes: 7 additions & 7 deletions src/main/scala/firrtl/Mappers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import firrtl.ir._
// TODO: Implement remaining mappers and recursive mappers
object Mappers {
// ********** Port Mappers **********
private trait PortMagnet {
trait PortMagnet {
def map(p: Port): Port
}
private object PortMagnet {
Expand All @@ -23,7 +23,7 @@ object Mappers {
}

// ********** Stmt Mappers **********
private trait StmtMagnet {
trait StmtMagnet {
def map(stmt: Statement): Statement
}
private object StmtMagnet {
Expand All @@ -49,7 +49,7 @@ object Mappers {
}

// ********** Expression Mappers **********
private trait ExprMagnet {
trait ExprMagnet {
def map(expr: Expression): Expression
}
private object ExprMagnet {
Expand All @@ -68,7 +68,7 @@ object Mappers {
}

// ********** Type Mappers **********
private trait TypeMagnet {
trait TypeMagnet {
def map(tpe: Type): Type
}
private object TypeMagnet {
Expand All @@ -84,7 +84,7 @@ object Mappers {
}

// ********** Width Mappers **********
private trait WidthMagnet {
trait WidthMagnet {
def map(width: Width): Width
}
private object WidthMagnet {
Expand All @@ -100,7 +100,7 @@ object Mappers {
}

// ********** Module Mappers **********
private trait ModuleMagnet {
trait ModuleMagnet {
def map(module: DefModule): DefModule
}
private object ModuleMagnet {
Expand All @@ -122,7 +122,7 @@ object Mappers {
}

// ********** Circuit Mappers **********
private trait CircuitMagnet {
trait CircuitMagnet {
def map(module: Circuit): Circuit
}
private object CircuitMagnet {
Expand Down
6 changes: 4 additions & 2 deletions src/main/scala/firrtl/Namespace.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ class Namespace private {
else {
var idx = indices.getOrElse(value, 0)
var str = value
do {
var cond = true
while (cond) {
str = s"${value}_$idx"
idx += 1
} while (!(tryName(str)))
cond = !tryName(str)
}
indices(value) = idx
str
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/firrtl/Utils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ object Utils extends LazyLogging {
/** Returns an inlined expression (replacing node references with values),
* stopping on a stopping condition or until the reference is not a node
*/
def inline(nodeMap: NodeMap, stop: String => Boolean = { x: String => false })(e: Expression): Expression = {
def inline(nodeMap: NodeMap, stop: String => Boolean = { (x: String) => false })(e: Expression): Expression = {
def onExp(e: Expression): Expression = e.map(onExp) match {
case Reference(name, _, _, _) if nodeMap.contains(name) && !stop(name) => onExp(nodeMap(name))
case other => other
Expand Down
3 changes: 1 addition & 2 deletions src/main/scala/firrtl/annotations/JsonProtocol.scala
Original file line number Diff line number Diff line change
Expand Up @@ -292,8 +292,7 @@ object JsonProtocol extends LazyLogging {
}

def deserializeTry(in: JsonInput, allowUnrecognizedAnnotations: Boolean = false): Try[Seq[Annotation]] = Try {
val parsed = parse(in)
val annos = parsed match {
val annos: Seq[JValue] = parse(in) match {
case JArray(objs) => objs
case x =>
throw new InvalidAnnotationJSONException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import firrtl.options.{CustomFileEmission, Dependency}
import firrtl.passes.LowerTypes
import firrtl.passes.MemPortUtils.memPortField
import firrtl.stage.{FirrtlOptions, TransformManager}
import firrtl.stage.FirrtlOptionsView

import scala.annotation.tailrec
import scala.collection.mutable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import firrtl._
import firrtl.annotations.{Annotation, NoTargetAnnotation}
import firrtl.options.Viewer.view
import firrtl.options.{CustomFileEmission, Dependency}
import firrtl.stage.FirrtlOptions
import firrtl.stage.{FirrtlOptions, FirrtlOptionsView}

private[firrtl] abstract class SMTEmitter private[firrtl] ()
extends Transform
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/firrtl/constraint/Constraint.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ package firrtl.constraint
trait Constraint {
def serialize: String
def map(f: Constraint => Constraint): Constraint
val children: Vector[Constraint]
def children: Vector[Constraint]
def reduce(): Constraint
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/firrtl/constraint/IsFloor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ case class IsFloor private (child: Constraint, dummyArg: Int) extends Constraint
case x: IsFloor => x
case _ => this
}
val children = Vector(child)
lazy val children = Vector(child)

override def map(f: Constraint => Constraint): Constraint = IsFloor(f(child))

Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/firrtl/constraint/IsKnown.scala
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ trait IsKnown extends Constraint {

override def map(f: Constraint => Constraint): Constraint = this

val children: Vector[Constraint] = Vector.empty[Constraint]
lazy val children: Vector[Constraint] = Vector.empty[Constraint]

def reduce(): IsKnown = this
}
2 changes: 1 addition & 1 deletion src/main/scala/firrtl/constraint/IsPow.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ case class IsPow private (child: Constraint, dummyArg: Int) extends Constraint {
case _ => this
}

val children = Vector(child)
lazy val children = Vector(child)

override def map(f: Constraint => Constraint): Constraint = IsPow(f(child))

Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/firrtl/constraint/IsVar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ trait IsVar extends Constraint {

override def reduce() = this

val children = Vector()
lazy val children = Vector()
}

case class VarCon(name: String) extends IsVar
6 changes: 4 additions & 2 deletions src/main/scala/firrtl/graph/DiGraph.scala
Original file line number Diff line number Diff line change
Expand Up @@ -279,11 +279,13 @@ class DiGraph[T](private[graph] val edges: LinkedHashMap[T, LinkedHashSet[T]]) {
if (frame.childCall.isEmpty) {
if (lowlinks(v) == indices(v)) {
val scc = new mutable.ArrayBuffer[T]
do {
var cond = true
while (cond) {
val w = stack.pop()
onstack -= w
scc += w
} while (scc.last != v);
cond = scc.last != v
}
sccs.append(scc.toSeq)
}
callStack.pop()
Expand Down
6 changes: 3 additions & 3 deletions src/main/scala/firrtl/ir/IR.scala
Original file line number Diff line number Diff line change
Expand Up @@ -884,13 +884,13 @@ case object UnknownBound extends Bound {
def serialize: String = Serializer.serialize(this)
def map(f: Constraint => Constraint): Constraint = this
override def reduce(): Constraint = this
val children = Vector()
lazy val children = Vector()
}
case class CalcBound(arg: Constraint) extends Bound {
def serialize: String = Serializer.serialize(this)
def map(f: Constraint => Constraint): Constraint = f(arg)
override def reduce(): Constraint = arg
val children = Vector(arg)
lazy val children = Vector(arg)
}
case class VarBound(name: String) extends IsVar with Bound {
override def serialize: String = Serializer.serialize(this)
Expand Down Expand Up @@ -1039,7 +1039,7 @@ case class IntervalType(lower: Bound, upper: Bound, point: Width) extends Ground
})

/** If bounds are known, calculates the width, otherwise returns UnknownWidth */
lazy val width: Width = (point, lower, upper) match {
val width: Width = (point, lower, upper) match {
case (IntWidth(i), l: IsKnown, u: IsKnown) =>
IntWidth(Math.max(Utils.getSIntWidth(minAdjusted.get), Utils.getSIntWidth(maxAdjusted.get)))
case _ => UnknownWidth
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/firrtl/ir/Serializer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ object Serializer {

// We could initialze the StringBuilder size, but this is bad for small modules which may not
// even reach the bufferSize.
private implicit val b = new StringBuilder
private implicit val b: StringBuilder = new StringBuilder

// The flattening of Whens into WhenBegin and friends requires us to keep track of the
// indention level
Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/firrtl/options/OptionParser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ case object OptionsHelpException extends Exception("Usage help invoked")
/** OptionParser mixin that causes the OptionParser to not call exit (call `sys.exit`) if the `--help` option is
* passed
*/
trait DoNotTerminateOnExit { this: OptionParser[_] =>
trait DoNotTerminateOnExit[T] extends OptionParser[T] {
override def terminate(exitState: Either[String, Unit]): Unit = ()
}

Expand All @@ -21,7 +21,7 @@ trait DoNotTerminateOnExit { this: OptionParser[_] =>
* [[StageUtils.dramaticError]]. By converting this to an [[OptionsException]], a [[Stage]] can then catch the error an
* convert it to an [[OptionsException]] that a [[Stage]] can get at.
*/
trait ExceptOnError { this: OptionParser[_] =>
trait ExceptOnError[T] extends OptionParser[T] {
override def reportError(msg: String): Unit = throw new OptionsException(msg)
}

Expand Down
9 changes: 6 additions & 3 deletions src/main/scala/firrtl/options/Phase.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ object Dependency {
}

private def isSingleton(obj: AnyRef): Boolean = {
reflect.runtime.currentMirror.reflect(obj).symbol.isModuleClass
// https://stackoverflow.com/questions/36018355/in-scala-is-there-any-way-to-check-if-an-instance-is-a-singleton-object-or-not
// https://stackoverflow.com/questions/37388677/how-to-check-if-a-value-is-a-scala-singleton-object-without-a-static-type?noredirect=1&lq=1
// reflect.runtime.currentMirror.reflect(obj).symbol.isModuleClass
obj.getClass.getName.endsWith("$")
}
}

Expand All @@ -55,7 +58,7 @@ case class Dependency[+A <: DependencyAPI[_]](id: Either[Class[_ <: A], A with S
}

/** Wrap an [[IllegalAccessException]] due to attempted object construction in a [[DependencyManagerException]] */
private def safeConstruct[A](a: Class[_ <: A]): A = try { a.newInstance }
private def safeConstruct[A](a: Class[_ <: A]): A = try { a.getDeclaredConstructor().newInstance() }
catch {
case e: IllegalAccessException =>
throw new DependencyManagerException(s"Failed to construct '$a'! (Did you try to construct an object?)", e)
Expand Down Expand Up @@ -192,7 +195,7 @@ trait DependencyAPI[A <: DependencyAPI[A]] { this: TransformLike[_] =>
"Use an explicit `override def invalidates` returning false. This will be removed in FIRRTL 1.5.",
"FIRRTL 1.4"
)
trait PreservesAll[A <: DependencyAPI[A]] { this: DependencyAPI[A] =>
trait PreservesAll[A <: DependencyAPI[A]] { this: DependencyAPI[A] with TransformLike[_] =>

override final def invalidates(a: A): Boolean = false

Expand Down
6 changes: 3 additions & 3 deletions src/main/scala/firrtl/options/Shell.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ import java.util.ServiceLoader
class Shell(val applicationName: String) {

/** Command line argument parser (OptionParser) with modifications */
protected val parser = new OptionParser[AnnotationSeq](applicationName)
val parser = new OptionParser[AnnotationSeq](applicationName)
with DuplicateHandling
with ExceptOnError
with DoNotTerminateOnExit
with ExceptOnError[AnnotationSeq]
with DoNotTerminateOnExit[AnnotationSeq]

/** Contains all discovered [[RegisteredLibrary]] */
final lazy val registeredLibraries: Seq[RegisteredLibrary] = {
Expand Down
3 changes: 2 additions & 1 deletion src/main/scala/firrtl/options/phases/GetIncludes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import firrtl.annotations.{AnnotationFileNotFoundException, JsonProtocol}
import firrtl.options.{InputAnnotationFileAnnotation, Phase, StageUtils}
import firrtl.FileUtils
import firrtl.stage.AllowUnrecognizedAnnotations
import org.json4s.FileInput

import java.io.File
import scala.collection.mutable
Expand All @@ -31,7 +32,7 @@ class GetIncludes extends Phase {
): AnnotationSeq = {
val file = new File(filename).getCanonicalFile
if (!file.exists) { throw new AnnotationFileNotFoundException(file) }
JsonProtocol.deserialize(file, allowUnrecognizedAnnotations)
JsonProtocol.deserialize(FileInput(file), allowUnrecognizedAnnotations)
}

/** Recursively read all [[Annotation]]s from any [[InputAnnotationFileAnnotation]]s while making sure that each file is
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import firrtl.options.{
Unserializable,
Viewer
}
import firrtl.options.StageOptionsView

import java.io.{BufferedOutputStream, File, FileOutputStream, PrintWriter}

Expand Down

0 comments on commit 62db135

Please sign in to comment.