Skip to content

Commit

Permalink
[cd] Bump CIRCT from firtool-1.62.0 to firtool-1.63.0 (#3760)
Browse files Browse the repository at this point in the history
* [binder] Emit invalidate according to the value flow
* [binder] Use inferred result type in primitive ops to avoid handling zero-width operands
* [cd] Bump CIRCT from firtool-1.62.0 to firtool-1.63.0

Co-authored-by: Sprite <SpriteOvO@gmail.com>
Co-authored-by: chiselbot <chiselbot@users.noreply.github.com>
  • Loading branch information
3 people committed Jan 23, 2024
1 parent 150f6db commit f2c4888
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 15 deletions.
1 change: 1 addition & 0 deletions circtpanamabinding/includeFunctions.txt
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ firrtlAttrGetNameKind
firrtlAttrGetRUW
firrtlAttrGetMemoryInit
firrtlAttrGetMemDir
firrtlValueFoldFlow

# CHIRRTL Attribute
chirrtlTypeGetCMemory
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.62.0"
"version": "firtool-1.63.0"
}
136 changes: 122 additions & 14 deletions panamaconverter/src/PanamaCIRCTConverter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -589,13 +589,17 @@ class PanamaCIRCTConverter {
}

def newNode(id: HasId, name: String, resultType: fir.Type, input: MlirValue, loc: MlirLocation): Unit = {
newNode(id, name, util.convert(resultType), input, loc)
}

def newNode(id: HasId, name: String, resultType: MlirType, input: MlirValue, loc: MlirLocation): Unit = {
val op = util
.OpBuilder("firrtl.node", firCtx.currentBlock, loc)
.withNamedAttr("name", circt.mlirStringAttrGet(name))
.withNamedAttr("nameKind", circt.firrtlAttrGetNameKind(FIRRTLNameKind.InterestingName))
.withNamedAttr("annotations", circt.emptyArrayAttr)
.withOperand(input)
.withResult(util.convert(resultType))
.withResult(resultType)
// .withResult( /* ref */ )
.build()
firCtx.ops += ((id._id, op.op))
Expand Down Expand Up @@ -719,6 +723,114 @@ class PanamaCIRCTConverter {
.withOperand( /* src */ src.value)
.build()
}

case class RecursiveTypeProperties(isPassive: Boolean, containsAnalog: Boolean)

def recursiveTypeProperties(tpe: fir.Type): RecursiveTypeProperties = {
tpe match {
case fir.ClockType | fir.ResetType | fir.AsyncResetType | _: fir.SIntType | _: fir.UIntType =>
RecursiveTypeProperties(true, false)
case _: fir.AnalogType => RecursiveTypeProperties(true, true)
case bundle: fir.BundleType =>
bundle.fields.foldLeft(RecursiveTypeProperties(true, false)) {
case (properties, field) =>
val fieldProperties = recursiveTypeProperties(field.tpe)
RecursiveTypeProperties(
properties.isPassive && fieldProperties.isPassive && field.flip == fir.Flip,
properties.containsAnalog || fieldProperties.containsAnalog
)
}
case _: fir.PropertyType => RecursiveTypeProperties(true, false)
case vector: fir.VectorType => recursiveTypeProperties(vector.tpe)
}
}

sealed trait Flow
object Flow {
final case object None extends Flow
final case object Source extends Flow
final case object Sink extends Flow
final case object Duplex extends Flow
}

def swapFlow(flow: Flow): Flow = flow match {
case Flow.None => Flow.None
case Flow.Source => Flow.Sink
case Flow.Sink => Flow.Source
case Flow.Duplex => Flow.Duplex
}

def foldFlow(value: Reference.Value, acc: Flow = Flow.Source): Flow = {
circt.firrtlValueFoldFlow(
value.value,
acc match {
case Flow.None => 0
case Flow.Source => 1
case Flow.Sink => 2
case Flow.Duplex => 3
}
) match {
case 0 => Flow.None
case 1 => Flow.Source
case 2 => Flow.Sink
case 3 => Flow.Duplex
}
}

def emitInvalidate(value: Reference.Value, loc: MlirLocation): Unit = emitInvalidate(value, loc, foldFlow(value))

def emitInvalidate(value: Reference.Value, loc: MlirLocation, flow: Flow): Unit = {
val props = recursiveTypeProperties(value.tpe)
if (props.isPassive && !props.containsAnalog) {
if (flow == Flow.Source) {
return
}

val invalidValue = Reference.Value(
util
.OpBuilder("firrtl.invalidvalue", firCtx.currentBlock, loc)
.withResult(util.convert(value.tpe))
.build()
.results(0),
value.tpe
)
emitConnect(value, invalidValue, loc)
return
}

val indexType = circt.mlirIntegerTypeGet(32)
value.tpe match {
case bundle: fir.BundleType =>
bundle.fields.zipWithIndex.foreach {
case (field, index) =>
val fieldAccess = Reference.Value(
util
.OpBuilder("firrtl.subfield", firCtx.currentBlock, loc)
.withNamedAttr("fieldIndex", circt.mlirIntegerAttrGet(indexType, index))
.withOperand(value.value)
.withResult(util.convert(field.tpe))
.build()
.results(0),
field.tpe
)
emitInvalidate(fieldAccess, loc, if (field.flip == fir.Flip) swapFlow(flow) else flow)
}
case vector: fir.VectorType =>
for (index <- 0 until vector.size) {
val elementAccess = Reference.Value(
util
.OpBuilder("firrtl.subindex", firCtx.currentBlock, loc)
.withNamedAttr("index", circt.mlirIntegerAttrGet(indexType, index))
.withOperand(value.value)
.withResult(util.convert(vector.tpe))
.build()
.results(0),
vector.tpe
)
emitInvalidate(elementAccess, loc, flow)
}
}
}
}

val mlirStream = new Writable {
Expand Down Expand Up @@ -871,17 +983,7 @@ class PanamaCIRCTConverter {
val loc = util.convert(defInvalid.sourceInfo)
val dest = util.referTo(defInvalid.arg, defInvalid.sourceInfo)

val invalidValue = util
.OpBuilder("firrtl.invalidvalue", firCtx.currentBlock, loc)
.withResult(util.convert(dest.tpe))
.build()
.results(0)

util
.OpBuilder("firrtl.connect", firCtx.currentBlock, loc)
.withOperand( /* dest */ dest.value)
.withOperand( /* src */ invalidValue)
.build()
util.emitInvalidate(dest, loc)
}

def visitOtherwiseEnd(otherwiseEnd: OtherwiseEnd): Unit = {
Expand Down Expand Up @@ -1333,9 +1435,15 @@ class PanamaCIRCTConverter {
.OpBuilder(s"firrtl.${defPrim.op.toString}", firCtx.currentBlock, loc)
.withNamedAttrs(attrs)
.withOperands(operands.map(_.value))
.withResult(util.convert(resultType))
// Chisel will produce zero-width types (`{S,U}IntType(IntWidth(0))`) for zero values
// This causes problems for example `Cat(u32 >> 32, u32)`, we expect it produces type `UIntType(IntWidth(33))` but width 32 is calculated since the first operand of `Cat` is zero-width
// To easily fix this, we use the result type inferred by CIRCT instead of giving it manually from Chisel
//
// .withResult(util.convert(resultType))
.withResultInference(1)
.build()
util.newNode(defPrim.id, name, resultType, op.results(0), loc)
val resultTypeInferred = circt.mlirValueGetType(op.results(0))
util.newNode(defPrim.id, name, resultTypeInferred, op.results(0), loc)
}

def visitDefReg(defReg: DefReg): Unit = {
Expand Down
2 changes: 2 additions & 0 deletions panamalib/src/PanamaCIRCT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,8 @@ class PanamaCIRCT {

def firrtlAttrGetMemDir(dir: FIRRTLMemDir) = MlirAttribute(CAPI.firrtlAttrGetMemDir(arena, mlirCtx, dir.value))

def firrtlValueFoldFlow(value: MlirValue, flow: Int): Int = CAPI.firrtlValueFoldFlow(value.get, flow)

def chirrtlTypeGetCMemory(elementType: MlirType, numElements: Long) = MlirType(
CAPI.chirrtlTypeGetCMemory(arena, mlirCtx, elementType.get, numElements)
)
Expand Down

0 comments on commit f2c4888

Please sign in to comment.