Skip to content

Commit

Permalink
Merge pull request #4277 from chipsalliance/cd/update-circt-from-firt…
Browse files Browse the repository at this point in the history
…ool-1.76.0-to-firtool-1.77.0

[cd] Bump CIRCT from firtool-1.76.0 to firtool-1.77.0
  • Loading branch information
jackkoenig authored Jul 13, 2024
2 parents d5ccf48 + da02e6a commit ae54349
Show file tree
Hide file tree
Showing 14 changed files with 491 additions and 80 deletions.
38 changes: 37 additions & 1 deletion core/src/main/scala/chisel3/Layer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import chisel3.experimental.{SourceInfo, UnlocatableSourceInfo}
import chisel3.internal.{Builder, HasId}
import chisel3.internal.firrtl.ir.{LayerBlockBegin, LayerBlockEnd, Node}
import chisel3.util.simpleClassName
import java.nio.file.{Path, Paths}
import scala.annotation.tailrec
import scala.collection.mutable.LinkedHashSet

Expand All @@ -28,12 +29,23 @@ object layer {
case object Bind extends Type
}

sealed trait OutputDirBehavior
final case object DefaultOutputDir extends OutputDirBehavior
final case object NoOutputDir extends OutputDirBehavior
final case class CustomOutputDir(path: Path) extends OutputDirBehavior

/** A layer declaration.
*
* @param convention how this layer should be lowered
* @param outputDirBehavior an optional user-provided output directory for this layer
* @param _parent the parent layer, if any
*/
abstract class Layer(val convention: Convention.Type)(implicit _parent: Layer, _sourceInfo: SourceInfo) {
abstract class Layer(
val convention: Convention.Type,
val outputDirBehavior: OutputDirBehavior = DefaultOutputDir
)(
implicit _parent: Layer,
_sourceInfo: SourceInfo) {
self: Singleton =>

/** This establishes a new implicit val for any nested layers. */
Expand All @@ -51,6 +63,30 @@ object layer {
case _ => s"${parent.fullName}.$name"
}

/** The output directory of this layer.
*
* The output directory of a layer serves as a hint to the toolchain,
* specifying where files related to the layer (such as a bindfile, in
* verilog) should be output. If a layer has no output directory, then files
* related to this layer will be placed in the default output directory.
*
* Unless overridden, the outputDir's name matches the name of the layer,
* and is located under the parent layer's directory.
*/
private[chisel3] final def outputDir: Option[Path] = outputDirBehavior match {
case NoOutputDir => None
case CustomOutputDir(dir) => Some(dir)
case DefaultOutputDir =>
parent match {
case Layer.Root => Some(Paths.get(name))
case _ =>
parent.outputDir match {
case None => Some(Paths.get(name))
case Some(dir) => Some(dir.resolve(name))
}
}
}

@tailrec
final private[chisel3] def canWriteTo(that: Layer): Boolean = that match {
case null => false
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/chisel3/internal/Builder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1108,7 +1108,7 @@ private[chisel3] object Builder extends LazyLogging {
case layer.Convention.Bind => LayerConvention.Bind
case _ => ???
}
Layer(l.sourceInfo, l.name, convention, children.map(foldLayers).toSeq)
Layer(l.sourceInfo, l.name, convention, l.outputDir.map(_.toString), children.map(foldLayers).toSeq)
}

val optionDefs = groupByIntoSeq(options)(opt => opt.group).map {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@ private[chisel3] object Converter {
val convention = layer.convention match {
case LayerConvention.Bind => fir.LayerConvention.Bind
}
fir.Layer(convert(layer.sourceInfo), layer.name, convention, layer.children.map(convertLayer))
fir.Layer(convert(layer.sourceInfo), layer.name, convention, layer.outputDir, layer.children.map(convertLayer))
}

def convertOption(option: DefOption): fir.DefOption = {
Expand Down
1 change: 1 addition & 0 deletions core/src/main/scala/chisel3/internal/firrtl/IR.scala
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,7 @@ private[chisel3] object ir {
sourceInfo: SourceInfo,
name: String,
convention: LayerConvention.Type,
outputDir: Option[String],
children: Seq[Layer])

case class LayerBlockBegin(sourceInfo: SourceInfo, layer: chisel3.layer.Layer) extends Command
Expand Down
2 changes: 1 addition & 1 deletion etc/circt.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"version": "firtool-1.76.0"
"version": "firtool-1.77.0"
}
7 changes: 6 additions & 1 deletion firrtl/src/main/scala/firrtl/ir/IR.scala
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,12 @@ object LayerConvention {
}
}

case class Layer(info: Info, name: String, convention: LayerConvention.Type, body: Seq[Layer])
case class Layer(
info: Info,
name: String,
convention: LayerConvention.Type,
outputDir: Option[String],
body: Seq[Layer])
extends FirrtlNode
with IsDeclaration
with UseSerializer
Expand Down
8 changes: 7 additions & 1 deletion firrtl/src/main/scala/firrtl/ir/Serializer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,13 @@ object Serializer {
val layers = if (circuit.layers.nonEmpty) {
implicit val b = new StringBuilder
def layerIt(layer: Layer)(implicit indent: Int): Unit = {
b ++= s"${NewLine}"; doIndent(); b ++= s"layer ${layer.name}, ${layer.convention} :"
b ++= s"${NewLine}"
doIndent()
b ++= s"layer ${layer.name}, ${layer.convention}"
for (d <- layer.outputDir) {
b ++= ", \"" ++ d ++ "\""
}
b ++= " :"
s(layer.info)
layer.body.foreach(layerIt(_)(indent + 1))
}
Expand Down
19 changes: 3 additions & 16 deletions src/main/scala/chisel3/ltl/LTL.scala
Original file line number Diff line number Diff line change
Expand Up @@ -302,10 +302,6 @@ sealed trait Property {

/** See `Property.clock`. */
def clock(clock: Clock)(implicit sourceInfo: SourceInfo): Property = Property.clock(this, clock)

/** See `Property.disable`. */
@deprecated("Use withDisable", "Chisel 6.5")
def disable(cond: Disable)(implicit sourceInfo: SourceInfo): Property = Property.disable(this, cond)
}

/** Prefix-style utilities to work with properties.
Expand Down Expand Up @@ -390,14 +386,6 @@ object Property {
*/
def clock(prop: Property, clock: Clock)(implicit sourceInfo: SourceInfo): Property =
OpaqueProperty(LTLClockIntrinsic(prop.inner, clock))

/** Disable the checking of a property if a condition is true. If the
* condition is true at any time during the evaluation of the property, the
* evaluation is aborted. Equivalent to `disable iff (cond) prop` in SVA.
*/
@deprecated("Use withDisable", "Chisel 6.5")
def disable(prop: Property, cond: Disable)(implicit sourceInfo: SourceInfo): Property =
OpaqueProperty(LTLDisableIntrinsic(prop.inner, cond.value))
}

/** The base class for the `AssertProperty`, `AssumeProperty`, and
Expand Down Expand Up @@ -426,9 +414,8 @@ sealed abstract class AssertPropertyLike {
)(
implicit sourceInfo: SourceInfo
): Unit = {
val disabled = disable.fold(prop)(prop.disable(_))
val clocked = clock.fold(disabled)(disabled.clock(_))
createIntrinsic(label)(sourceInfo)(clocked.inner)
val clocked = clock.fold(prop)(prop.clock(_))
createIntrinsic(label)(sourceInfo)(clocked.inner, disable.map(!_.value))
}

/** Assert, assume, or cover that a boolean predicate holds.
Expand Down Expand Up @@ -486,7 +473,7 @@ sealed abstract class AssertPropertyLike {
apply(Sequence.BoolSequence(cond), Some(clock), Some(disable), Some(label))
}

protected def createIntrinsic(label: Option[String])(implicit sourceInfo: SourceInfo): (Bool) => Unit
protected def createIntrinsic(label: Option[String])(implicit sourceInfo: SourceInfo): (Bool, Option[Bool]) => Unit
}

/** Assert that a property holds.
Expand Down
141 changes: 141 additions & 0 deletions src/main/scala/chisel3/util/circt/DPI.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
// SPDX-License-Identifier: Apache-2.0

package chisel3.util.circt.dpi

import chisel3._

import chisel3.experimental.{IntParam, IntrinsicModule, Param, StringParam}

private object GetDPIParams {
def apply(
functionName: String,
isClocked: Boolean,
inputNames: Option[Seq[String]],
outputName: Option[String] = None
): Seq[(String, Param)] = {
val inputNamesParam =
inputNames.map(_.mkString(";")).map(x => Seq("inputNames" -> StringParam(x))).getOrElse(Seq())
val outputNameParam = outputName.map(x => Seq("outputName" -> StringParam(x))).getOrElse(Seq())
Seq[(String, Param)](
"functionName" -> functionName,
"isClocked" -> (if (isClocked) 1 else 0)
) ++ inputNamesParam ++ outputNameParam
}
}

object RawClockedNonVoidFunctionCall {

/** Creates an intrinsic that calls non-void DPI function at its clock posedge.
* The result values behave like registers and the DPI function is used as a state
* transfer function of them.
*
* `enable` operand is used to conditionally call the DPI since DPI call could be quite
* more expensive than native constructs.
*
* When an `enable` is false, it means the state transfer function is not called. Hence
* their values will not be modified in that clock.
*
* Please refer https://github.com/llvm/circt/blob/main/docs/Dialects/FIRRTL/FIRRTLIntrinsics.md#dpi-intrinsic-abi for DPI function ABI.
* @example {{{
* val a = RawClockedNonVoidFunctionCall("dpi_func_foo", UInt(1.W), clock, enable, b, c)
* }}}
*/
def apply[T <: Data](
functionName: String,
ret: => T,
inputNames: Option[Seq[String]] = None,
outputName: Option[String] = None
)(clock: Clock,
enable: Bool,
data: Data*
): T = {
IntrinsicExpr(
"circt_dpi_call",
ret,
GetDPIParams(functionName, true, inputNames, outputName): _*
)(
(Seq(clock, enable) ++ data): _*
)
}
}

object RawUnclockedNonVoidFunctionCall {

/** Creates an intrinsic that calls non-void DPI function for its input value changes.
* The DPI call is considered as a combinational logic.
*
* `enable` operand is used to conditionally call the DPI since DPI call could be quite
* more expensive than native constructs.
* When `enable` is false, results of unclocked calls are undefined and evaluated into X.
*
* Please refer https://github.com/llvm/circt/blob/main/docs/Dialects/FIRRTL/FIRRTLIntrinsics.md#dpi-intrinsic-abi for DPI function ABI.
* @example {{{
* val a = RawUnclockedNonVoidFunctionCall("dpi_func_foo", UInt(1.W), enable, b, c)
* }}}
*/
def apply[T <: Data](
functionName: String,
ret: => T,
inputNames: Option[Seq[String]] = None,
outputName: Option[String] = None
)(enable: Bool,
data: Data*
): T = {
IntrinsicExpr(
"circt_dpi_call",
ret,
GetDPIParams(functionName, false, inputNames, outputName): _*
)(
(Seq(enable) ++ data): _*
)
}
}

object RawClockedVoidFunctionCall {

/** Creates an intrinsic that calls void DPI function at its clock posedge.
*
* Please refer https://github.com/llvm/circt/blob/main/docs/Dialects/FIRRTL/FIRRTLIntrinsics.md#dpi-intrinsic-abi for DPI function ABI.
* @example {{{
* RawClockedVoidFunctionCall("dpi_func_foo", UInt(1.W), clock, enable, b, c)
* }}}
*/
def apply(
functionName: String,
inputNames: Option[Seq[String]] = None
)(clock: Clock,
enable: Bool,
data: Data*
): Unit = {
Intrinsic("circt_dpi_call", GetDPIParams(functionName, true, inputNames): _*)(
(Seq(clock, enable) ++ data): _*
)
}
}

// A common trait for DPI functions.
trait DPIFunctionImport {
def functionName: String
def inputNames: Option[Seq[String]] = None
}

// Base trait for a non-void function that returns `T`.
trait DPINonVoidFunctionImport[T <: Data] extends DPIFunctionImport {
def ret: T
def clocked: Boolean
def outputName: Option[String] = None
final def callWithEnable(enable: Bool, data: Data*): T =
if (clocked) {
RawClockedNonVoidFunctionCall(functionName, ret, inputNames, outputName)(Module.clock, enable, data: _*)
} else {
RawUnclockedNonVoidFunctionCall(functionName, ret, inputNames, outputName)(enable, data: _*)
}
final def call(data: Data*): T = callWithEnable(true.B, data: _*)
}

// Base trait for a clocked void function.
trait DPIClockedVoidFunctionImport extends DPIFunctionImport {
final def callWithEnable(enable: Bool, data: Data*): Unit =
RawClockedVoidFunctionCall(functionName, inputNames)(Module.clock, enable, data: _*)
final def call(data: Data*): Unit = callWithEnable(true.B, data: _*)
}
26 changes: 15 additions & 11 deletions src/main/scala/chisel3/util/circt/LTLIntrinsics.scala
Original file line number Diff line number Diff line change
Expand Up @@ -145,29 +145,33 @@ private[chisel3] object LTLDisableIntrinsic {

/** Base class for assert, assume, and cover intrinsics. */
private[chisel3] object VerifAssertLikeIntrinsic {
def apply(intrinsicName: String, label: Option[String])(prop: Bool)(implicit sourceInfo: SourceInfo): Unit = {
def apply(
intrinsicName: String,
label: Option[String]
)(prop: Bool,
enable: Option[Bool]
)(
implicit sourceInfo: SourceInfo
): Unit = {
val name = f"circt_verif_$intrinsicName"
if (label.isEmpty)
Intrinsic(name)(prop)
else
Intrinsic(name, "label" -> label.get)(prop)
Intrinsic(name, (label.map("label" -> StringParam(_)).toSeq): _*)((Seq(prop) ++ enable.toSeq): _*)
}
}

/** A wrapper intrinsic for the CIRCT `verif.assert` operation. */
private[chisel3] object VerifAssertIntrinsic {
def apply(label: Option[String] = None)(prop: Bool)(implicit sourceInfo: SourceInfo) =
VerifAssertLikeIntrinsic("assert", label)(prop)
def apply(label: Option[String] = None)(prop: Bool, enable: Option[Bool])(implicit sourceInfo: SourceInfo) =
VerifAssertLikeIntrinsic("assert", label)(prop, enable)
}

/** A wrapper intrinsic for the CIRCT `verif.assume` operation. */
private[chisel3] object VerifAssumeIntrinsic {
def apply(label: Option[String] = None)(prop: Bool)(implicit sourceInfo: SourceInfo) =
VerifAssertLikeIntrinsic("assume", label)(prop)
def apply(label: Option[String] = None)(prop: Bool, enable: Option[Bool])(implicit sourceInfo: SourceInfo) =
VerifAssertLikeIntrinsic("assume", label)(prop, enable)
}

/** A wrapper intrinsic for the CIRCT `verif.cover` operation. */
private[chisel3] object VerifCoverIntrinsic {
def apply(label: Option[String] = None)(prop: Bool)(implicit sourceInfo: SourceInfo) =
VerifAssertLikeIntrinsic("cover", label)(prop)
def apply(label: Option[String] = None)(prop: Bool, enable: Option[Bool])(implicit sourceInfo: SourceInfo) =
VerifAssertLikeIntrinsic("cover", label)(prop, enable)
}
Loading

0 comments on commit ae54349

Please sign in to comment.