Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[cd] Bump CIRCT from firtool-1.76.0 to firtool-1.77.0 #4277

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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