diff --git a/binder/includeConstants.txt b/binder/includeConstants.txt index ed3f92be129..b72808d1b3f 100644 --- a/binder/includeConstants.txt +++ b/binder/includeConstants.txt @@ -1,6 +1,6 @@ -# enum FIRRTLPortDirection -FIRRTL_PORT_DIR_INPUT -FIRRTL_PORT_DIR_OUTPUT +# enum FIRRTLDirection +FIRRTL_DIRECTION_IN +FIRRTL_DIRECTION_OUT # enum FIRRTLConvention FIRRTL_CONVENTION_INTERNAL FIRRTL_CONVENTION_SCALARIZED diff --git a/binder/includeFunctions.txt b/binder/includeFunctions.txt index 4d8a1502b90..630d389423a 100644 --- a/binder/includeFunctions.txt +++ b/binder/includeFunctions.txt @@ -19,7 +19,9 @@ mlirOperationStateGet mlirNamedAttributeGet mlirIntegerAttrGet mlirFloatAttrDoubleGet +mlirBoolAttrGet mlirStringAttrGet +mlirStringAttrGetValue mlirArrayAttrGet mlirTypeAttrGet mlirArrayAttrGet @@ -66,6 +68,14 @@ firrtlTypeGetAsyncReset firrtlTypeGetAnalog firrtlTypeGetVector firrtlTypeGetBundle +firrtlTypeGetAnyRef +firrtlTypeGetInteger +firrtlTypeGetDouble +firrtlTypeGetString +firrtlTypeGetBoolean +firrtlTypeGetPath +firrtlTypeGetList +firrtlTypeGetClass # FIRRTL Attribute firrtlAttrGetPortDirs @@ -172,3 +182,68 @@ firtoolPopulateHWToSV firtoolPopulateExportVerilog firtoolPopulateExportSplitVerilog firtoolPopulateFinalizeIR + +# +# OM C-API +# + +# Type +omTypeIsAClassType +omClassTypeGetTypeID +omClassTypeGetName +omTypeIsAFrozenBasePathType +omFrozenBasePathTypeGetTypeID +omTypeIsAFrozenPathType +omFrozenPathTypeGetTypeID +omTypeIsAMapType +omMapTypeGetKeyType +omTypeIsAStringType +# Evaluator +omEvaluatorNew +omEvaluatorInstantiate +omEvaluatorGetModule +# Object +omEvaluatorObjectIsNull +omEvaluatorObjectGetType +omEvaluatorObjectGetField +omEvaluatorObjectGetHash +omEvaluatorObjectIsEq +omEvaluatorObjectGetFieldNames +# EvaluatorValue +omEvaluatorValueGetContext +omEvaluatorValueGetLoc +omEvaluatorValueIsNull +omEvaluatorValueIsAObject +omEvaluatorValueIsAPrimitive +omEvaluatorValueGetPrimitive +omEvaluatorValueFromPrimitive +omEvaluatorValueIsAList +omEvaluatorListGetNumElements +omEvaluatorListGetElement +omEvaluatorValueIsATuple +omEvaluatorTupleGetNumElements +omEvaluatorTupleGetElement +omEvaluatorMapGetElement +omEvaluatorMapGetKeys +omEvaluatorValueIsAMap +omEvaluatorMapGetType +omEvaluatorValueIsABasePath +omEvaluatorBasePathGetEmpty +omEvaluatorValueIsAPath +omEvaluatorPathGetAsString +# ReferenceAttr API +omAttrIsAReferenceAttr +omReferenceAttrGetInnerRef +# IntegerAttr API +omAttrIsAIntegerAttr +omIntegerAttrGetInt +omIntegerAttrGet +# ListAttr API +omAttrIsAListAttr +omListAttrGetNumElements +omListAttrGetElement +# MapAttr API +omAttrIsAMapAttr +omMapAttrGetNumElements +omMapAttrGetElementKey +omMapAttrGetElementValue diff --git a/binder/includeStructs.txt b/binder/includeStructs.txt index eb92de794ed..9db0bbdbf42 100644 --- a/binder/includeStructs.txt +++ b/binder/includeStructs.txt @@ -17,4 +17,7 @@ MlirOpPassManager MlirPass MlirLogicalResult FIRRTLBundleField +FIRRTLClassElement FirtoolOptions +OMEvaluator +OMEvaluatorValue diff --git a/binder/jextract-headers.h b/binder/jextract-headers.h index 81bcaa2ae26..9df367caff8 100644 --- a/binder/jextract-headers.h +++ b/binder/jextract-headers.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include diff --git a/binder/linkLibraries.txt b/binder/linkLibraries.txt index 3b17d2b8925..cc3826af9ff 100644 --- a/binder/linkLibraries.txt +++ b/binder/linkLibraries.txt @@ -4,6 +4,7 @@ CIRCTCAPICHIRRTL CIRCTCAPIHW CIRCTCAPISV CIRCTCAPISeq +CIRCTCAPIOM CIRCTCAPIFirtool CIRCTCAPIExportFIRRTL CIRCTCAPIExportVerilog diff --git a/binder/src/main/scala/PanamaCIRCT.scala b/binder/src/main/scala/PanamaCIRCT.scala index 616a43f12fb..afa1531527d 100644 --- a/binder/src/main/scala/PanamaCIRCT.scala +++ b/binder/src/main/scala/PanamaCIRCT.scala @@ -168,8 +168,15 @@ class PanamaCIRCT { def mlirTypeAttrGet(tpe: MlirType) = MlirAttribute(CAPI.mlirTypeAttrGet(arena, tpe.get)) + def mlirBoolAttrGet(value: Boolean) = MlirAttribute(CAPI.mlirBoolAttrGet(arena, mlirCtx, if (value) 1 else 0)) + def mlirStringAttrGet(string: String) = MlirAttribute(CAPI.mlirStringAttrGet(arena, mlirCtx, newString(string).get)) + def mlirStringAttrGetValue(attr: MlirAttribute): String = { + val string = CAPI.mlirStringAttrGetValue(arena, attr.get) + MlirStringRef(string).toString + } + def mlirIntegerAttrGet(tpe: MlirType, value: Int) = MlirAttribute(CAPI.mlirIntegerAttrGet(arena, tpe.get, value)) def mlirFloatAttrDoubleGet(tpe: MlirType, value: Double) = MlirAttribute( @@ -412,6 +419,9 @@ class PanamaCIRCT { CAPI.firtoolPopulateExportSplitVerilog(arena, pm.get, options.get, newString(directory).get) ) + def firtoolPopulateFinalizeIR(pm: MlirPassManager, options: FirtoolOptions) = + MlirLogicalResult(CAPI.firtoolPopulateFinalizeIR(arena, pm.get, options.get)) + def mlirLogicalResultIsSuccess(res: MlirLogicalResult): Boolean = circt.MlirLogicalResult.value$get(res.get) != 0 def mlirLogicalResultIsFailure(res: MlirLogicalResult): Boolean = circt.MlirLogicalResult.value$get(res.get) == 0 @@ -444,7 +454,33 @@ class PanamaCIRCT { MlirType(CAPI.firrtlTypeGetBundle(arena, mlirCtx, fields.length, buffer)) } - def firrtlAttrGetPortDirs(dirs: Seq[FIRRTLPortDir]): MlirAttribute = { + def firrtlTypeGetAnyRef() = MlirType(CAPI.firrtlTypeGetAnyRef(arena, mlirCtx)) + + def firrtlTypeGetInteger() = MlirType(CAPI.firrtlTypeGetInteger(arena, mlirCtx)) + + def firrtlTypeGetDouble() = MlirType(CAPI.firrtlTypeGetDouble(arena, mlirCtx)) + + def firrtlTypeGetString() = MlirType(CAPI.firrtlTypeGetString(arena, mlirCtx)) + + def firrtlTypeGetBoolean() = MlirType(CAPI.firrtlTypeGetBoolean(arena, mlirCtx)) + + def firrtlTypeGetPath() = MlirType(CAPI.firrtlTypeGetPath(arena, mlirCtx)) + + def firrtlTypeGetList(elementType: MlirType) = MlirType(CAPI.firrtlTypeGetList(arena, mlirCtx, elementType.get)) + + def firrtlTypeGetClass(name: MlirAttribute /* FlatSymbolRefAttr */, elements: Seq[FIRRTLClassElement]): MlirType = { + val buffer = circt.FIRRTLClassElement.allocateArray(elements.length, arena) + elements.zipWithIndex.foreach { + case (element, i) => + val elementBuffer = buffer.asSlice(circt.FIRRTLClassElement.sizeof() * i, circt.FIRRTLClassElement.sizeof()) + circt.FIRRTLClassElement.name$slice(elementBuffer).copyFrom(mlirIdentifierGet(element.name).get) + circt.FIRRTLClassElement.type$slice(elementBuffer).copyFrom(element.tpe.get) + circt.FIRRTLClassElement.direction$set(elementBuffer, element.direction.get) + } + MlirType(CAPI.firrtlTypeGetClass(arena, mlirCtx, name.get, elements.length, buffer)) + } + + def firrtlAttrGetPortDirs(dirs: Seq[FIRRTLDirection]): MlirAttribute = { val (ptr, length) = seqToArray(dirs) MlirAttribute(CAPI.firrtlAttrGetPortDirs(arena, mlirCtx, length, ptr)) } @@ -470,6 +506,62 @@ class PanamaCIRCT { ) def chirrtlTypeGetCMemoryPort() = MlirType(CAPI.chirrtlTypeGetCMemoryPort(arena, mlirCtx)) + + // + // OM C-API + // + + def omTypeIsAClassType(tpe: MlirType): Boolean = CAPI.omTypeIsAClassType(tpe.get) + def omClassTypeGetName(tpe: MlirType) = MlirIdentifier(CAPI.omClassTypeGetName(arena, tpe.get)) + def omTypeIsAFrozenBasePathType(tpe: MlirType): Boolean = CAPI.omTypeIsAFrozenBasePathType(tpe.get) + def omTypeIsAFrozenPathType(tpe: MlirType): Boolean = CAPI.omTypeIsAFrozenPathType(tpe.get) + def omTypeIsAMapType(tpe: MlirType): Boolean = CAPI.omTypeIsAMapType(tpe.get) + def omMapTypeGetKeyType(tpe: MlirType) = MlirType(CAPI.omMapTypeGetKeyType(arena, tpe.get)) + def omTypeIsAStringType(tpe: MlirType): Boolean = CAPI.omTypeIsAStringType(tpe.get) + def omEvaluatorNew(mod: MlirModule) = OMEvaluator(CAPI.omEvaluatorNew(arena, mod.get)) + def omEvaluatorInstantiate(evaluator: OMEvaluator, className: String, actualParams: Seq[OMEvaluatorValue]) = { + val params = seqToArray(actualParams); + OMEvaluatorValue(CAPI.omEvaluatorInstantiate(arena, evaluator.get, mlirStringAttrGet(className).get, params._2, params._1)) + } + def omEvaluatorGetModule(evaluator: OMEvaluator) = MlirModule(CAPI.omEvaluatorGetModule(arena, evaluator.get)) + def omEvaluatorObjectIsNull(obj: OMEvaluatorValue): Boolean = CAPI.omEvaluatorObjectIsNull(obj.get) + def omEvaluatorObjectGetType(obj: OMEvaluatorValue) = MlirType(CAPI.omEvaluatorObjectGetType(arena, obj.get)) + def omEvaluatorObjectGetField(obj: OMEvaluatorValue, name: String) = OMEvaluatorValue(CAPI.omEvaluatorObjectGetField(arena, obj.get, mlirStringAttrGet(name).get)) + def omEvaluatorObjectGetHash(obj: OMEvaluatorValue): Int = CAPI.omEvaluatorObjectGetHash(obj.get) + def omEvaluatorObjectIsEq(obj: OMEvaluatorValue, other: OMEvaluatorValue): Boolean = CAPI.omEvaluatorObjectIsEq(obj.get, other.get) + def omEvaluatorObjectGetFieldNames(obj: OMEvaluatorValue) = MlirAttribute(CAPI.omEvaluatorObjectGetFieldNames(arena, obj.get)) + def omEvaluatorValueGetLoc(evaluatorValue: OMEvaluatorValue) = MlirLocation(CAPI.omEvaluatorValueGetLoc(arena, evaluatorValue.get)) + def omEvaluatorValueIsNull(evaluatorValue: OMEvaluatorValue): Boolean = CAPI.omEvaluatorValueIsNull(evaluatorValue.get) + def omEvaluatorValueIsAObject(evaluatorValue: OMEvaluatorValue): Boolean = CAPI.omEvaluatorValueIsAObject(evaluatorValue.get) + def omEvaluatorValueIsAPrimitive(evaluatorValue: OMEvaluatorValue): Boolean = CAPI.omEvaluatorValueIsAPrimitive(evaluatorValue.get) + def omEvaluatorValueGetPrimitive(evaluatorValue: OMEvaluatorValue) = MlirAttribute(CAPI.omEvaluatorValueGetPrimitive(arena, evaluatorValue.get)) + def omEvaluatorValueFromPrimitive(primitive: MlirAttribute) = OMEvaluatorValue(CAPI.omEvaluatorValueFromPrimitive(arena, primitive.get)) + def omEvaluatorValueIsAList(evaluatorValue: OMEvaluatorValue): Boolean = CAPI.omEvaluatorValueIsAList(evaluatorValue.get) + def omEvaluatorListGetNumElements(evaluatorValue: OMEvaluatorValue): Int = CAPI.omEvaluatorListGetNumElements(evaluatorValue.get).toInt + def omEvaluatorListGetElement(evaluatorValue: OMEvaluatorValue, pos: Int) = OMEvaluatorValue(CAPI.omEvaluatorListGetElement(arena, evaluatorValue.get, pos)) + def omEvaluatorValueIsATuple(evaluatorValue: OMEvaluatorValue): Boolean = CAPI.omEvaluatorValueIsATuple(evaluatorValue.get) + def omEvaluatorTupleGetNumElements(evaluatorValue: OMEvaluatorValue): Int = CAPI.omEvaluatorTupleGetNumElements(evaluatorValue.get).toInt + def omEvaluatorTupleGetElement(evaluatorValue: OMEvaluatorValue, pos: Int) = OMEvaluatorValue(CAPI.omEvaluatorTupleGetElement(arena, evaluatorValue.get, pos)) + def omEvaluatorMapGetElement(evaluatorValue: OMEvaluatorValue, attr: MlirAttribute) = OMEvaluatorValue(CAPI.omEvaluatorMapGetElement(arena, evaluatorValue.get, attr.get)) + def omEvaluatorMapGetKeys(obj: OMEvaluatorValue) = MlirAttribute(CAPI.omEvaluatorMapGetKeys(arena, obj.get)) + def omEvaluatorValueIsAMap(evaluatorValue: OMEvaluatorValue): Boolean = CAPI.omEvaluatorValueIsAMap(evaluatorValue.get) + def omEvaluatorMapGetType(evaluatorValue: OMEvaluatorValue): MlirType = MlirType(CAPI.omEvaluatorMapGetType(arena, evaluatorValue.get)) + def omEvaluatorValueIsABasePath(evaluatorValue: OMEvaluatorValue): Boolean = CAPI.omEvaluatorValueIsABasePath(evaluatorValue.get) + def omEvaluatorBasePathGetEmpty() = OMEvaluatorValue(CAPI.omEvaluatorBasePathGetEmpty(arena, mlirCtx)) + def omEvaluatorValueIsAPath(evaluatorValue: OMEvaluatorValue): Boolean = CAPI.omEvaluatorValueIsAPath(evaluatorValue.get) + def omEvaluatorPathGetAsString(evaluatorValue: OMEvaluatorValue): String = mlirStringAttrGetValue(MlirAttribute(CAPI.omEvaluatorPathGetAsString(arena, evaluatorValue.get))) + def omAttrIsAReferenceAttr(attr: MlirAttribute): Boolean = CAPI.omAttrIsAReferenceAttr(attr.get) + def omReferenceAttrGetInnerRef(attr: MlirAttribute) = MlirAttribute(CAPI.omReferenceAttrGetInnerRef(arena, attr.get)) + def omAttrIsAIntegerAttr(attr: MlirAttribute): Boolean = CAPI.omAttrIsAIntegerAttr(attr.get) + def omIntegerAttrGetInt(attr: MlirAttribute) = MlirAttribute(CAPI.omIntegerAttrGetInt(arena, attr.get)) + def omIntegerAttrGet(attr: MlirAttribute) = MlirAttribute(CAPI.omIntegerAttrGet(arena, attr.get)) + def omAttrIsAListAttr(attr: MlirAttribute): Boolean = CAPI.omAttrIsAListAttr(attr.get) + def omListAttrGetNumElements(attr: MlirAttribute): Int = CAPI.omListAttrGetNumElements(attr.get).toInt + def omListAttrGetElement(attr: MlirAttribute, pos: Int) = MlirAttribute(CAPI.omListAttrGetElement(arena, attr.get, pos)) + def omAttrIsAMapAttr(attr: MlirAttribute): Boolean = CAPI.omAttrIsAMapAttr(attr.get) + def omMapAttrGetNumElements(attr: MlirAttribute): Int = CAPI.omMapAttrGetNumElements(attr.get).toInt + def omMapAttrGetElementKey(attr: MlirAttribute, pos: Int) = MlirIdentifier(CAPI.omMapAttrGetElementKey(arena, attr.get, pos)) + def omMapAttrGetElementValue(attr: MlirAttribute, pos: Int) = MlirAttribute(CAPI.omMapAttrGetElementValue(arena, attr.get, pos)) } // @@ -627,6 +719,8 @@ object MlirPass { final case class FIRRTLBundleField(name: String, isFlip: Boolean, tpe: MlirType) +final case class FIRRTLClassElement(name: String, tpe: MlirType, direction: FIRRTLDirection) + final case class FirtoolOptions(ptr: MemorySegment) extends ForeignType[MemorySegment] { private[circt] def get = ptr private[circt] val sizeof = circt.FirtoolOptions.sizeof().toInt @@ -635,6 +729,22 @@ object FirtoolOptions { private[circt] def apply(ptr: MemorySegment) = new FirtoolOptions(ptr) } +final case class OMEvaluator(ptr: MemorySegment) extends ForeignType[MemorySegment] { + private[circt] def get = ptr + private[circt] val sizeof = circt.OMEvaluator.sizeof().toInt +} +object OMEvaluator { + private[circt] def apply(ptr: MemorySegment) = new OMEvaluator(ptr) +} + +final case class OMEvaluatorValue(ptr: MemorySegment) extends ForeignType[MemorySegment] { + private[circt] def get = ptr + private[circt] val sizeof = circt.OMEvaluatorValue.sizeof().toInt +} +object OMEvaluatorValue { + private[circt] def apply(ptr: MemorySegment) = new OMEvaluatorValue(ptr) +} + // // MLIR & CIRCT Enums // @@ -657,13 +767,13 @@ object FIRRTLNameKind { final case object InterestingName extends FIRRTLNameKind(value = CAPI.FIRRTL_NAME_KIND_INTERESTING_NAME()) } -sealed abstract class FIRRTLPortDir(val value: Int) extends ForeignType[Int] { +sealed abstract class FIRRTLDirection(val value: Int) extends ForeignType[Int] { private[circt] def get = value private[circt] val sizeof = 4 // FIXME: jextract doesn't export type for C enum } -object FIRRTLPortDir { - final case object Input extends FIRRTLPortDir(value = CAPI.FIRRTL_PORT_DIR_INPUT()) - final case object Output extends FIRRTLPortDir(value = CAPI.FIRRTL_PORT_DIR_OUTPUT()) +object FIRRTLDirection { + final case object In extends FIRRTLDirection(value = CAPI.FIRRTL_DIRECTION_IN()) + final case object Out extends FIRRTLDirection(value = CAPI.FIRRTL_DIRECTION_OUT()) } sealed abstract class firrtlAttrGetRUW(val value: Int) extends ForeignType[Int] { diff --git a/binder/src/main/scala/PanamaCIRCTConverter.scala b/binder/src/main/scala/PanamaCIRCTConverter.scala index 46d0f81e7bb..a8ad6f12558 100644 --- a/binder/src/main/scala/PanamaCIRCTConverter.scala +++ b/binder/src/main/scala/PanamaCIRCTConverter.scala @@ -10,6 +10,7 @@ import scala.math._ import firrtl.{ir => fir} import firrtl.annotations.NoTargetAnnotation import chisel3.{Data => ChiselData, _} +import chisel3.properties.PropertyType import chisel3.experimental._ import chisel3.internal._ import chisel3.internal.firrtl._ @@ -33,7 +34,7 @@ case class Op(state: MlirOperationState, op: MlirOperation, regions: Seq[Region] case class Ports( types: Seq[MlirType], - dirs: Seq[FIRRTLPortDir], + dirs: Seq[FIRRTLDirection], locs: Seq[MlirLocation], names: Seq[String], nameAttrs: Seq[MlirAttribute], @@ -166,6 +167,14 @@ class PanamaCIRCTConverter extends CIRCTConverter { ) ) ) + case fir.AnyRefPropertyType => circt.firrtlTypeGetAnyRef() + case fir.IntegerPropertyType => circt.firrtlTypeGetInteger() + case fir.DoublePropertyType => circt.firrtlTypeGetDouble() + case fir.StringPropertyType => circt.firrtlTypeGetString() + case fir.BooleanPropertyType => circt.firrtlTypeGetBoolean() + case fir.PathPropertyType => circt.firrtlTypeGetPath() + case t: fir.SequencePropertyType => circt.firrtlTypeGetList(convert(t.tpe)) + case t: fir.ClassPropertyType => circt.firrtlTypeGetClass(circt.mlirFlatSymbolRefAttrGet(t.name), Seq.empty /* TODO: where is the elements? */) } } @@ -199,8 +208,8 @@ class PanamaCIRCTConverter extends CIRCTConverter { Ports( types = types, dirs = irs.map(_.direction match { - case fir.Input => FIRRTLPortDir.Input - case fir.Output => FIRRTLPortDir.Output + case fir.Input => FIRRTLDirection.In + case fir.Output => FIRRTLDirection.Out }), locs = locs, names = irs.map(_.name), @@ -439,7 +448,7 @@ class PanamaCIRCTConverter extends CIRCTConverter { } } - def referTo(arg: Arg, loc: MlirLocation): Reference.Value = { + def referTo(arg: Arg, loc: MlirLocation, ctx: Option[(Component, SourceInfo)] = None): Reference.Value = { def referToNewConstant(n: Int, w: Width, isSigned: Boolean): Reference.Value = { val (firWidth, valWidth) = w match { case _: UnknownWidth => @@ -453,10 +462,46 @@ class PanamaCIRCTConverter extends CIRCTConverter { Reference.Value(util.newConstantValue(resultType, valueType, n.toInt, loc), resultType) } + def referToNewProperty[T, U](propLit: PropertyLit[T, U]): Reference.Value = { + def rec(tpe: fir.PropertyType, exp: fir.Expression): MlirValue = { + val (opName, attrs, operands) = exp match { + case fir.IntegerPropertyLiteral(value) => + val attrs = Seq(("value", circt.mlirIntegerAttrGet(circt.mlirIntegerTypeSignedGet(util.bitLength(value) + 1), value.toInt))) + ("integer", attrs, Seq.empty) + case fir.DoublePropertyLiteral(value) => + val attrs = Seq(("value", circt.mlirFloatAttrDoubleGet(circt.mlirF64TypeGet(), value))) + ("double", attrs, Seq.empty) + case fir.StringPropertyLiteral(value) => + val attrs = Seq(("value", circt.mlirStringAttrGet(value))) + ("string", attrs, Seq.empty) + case fir.BooleanPropertyLiteral(value) => + val attrs = Seq(("value", circt.mlirBoolAttrGet(value))) + ("bool", attrs, Seq.empty) + case fir.PathPropertyLiteral(value) => + val attrs = Seq(("target", circt.mlirStringAttrGet(value))) + ("unresolved_path", attrs, Seq.empty) + case fir.SequencePropertyValue(elementTpe, values) => + ("list.create", Seq.empty, values.map(rec(elementTpe.asInstanceOf[fir.PropertyType], _))) + } + util + .OpBuilder(s"firrtl.$opName", firCtx.currentBlock, loc) + .withNamedAttrs(attrs) + .withOperands(operands) + .withResult(util.convert(tpe)) + .build() + .results(0) + } + + val tpe = propLit.propertyType.getPropertyType() + val exp = propLit.propertyType.convert(propLit.lit, ctx.get._1, ctx.get._2); + Reference.Value(rec(tpe, exp), tpe) + } + arg match { case Node(id) => referTo(id, loc) case ULit(value, width) => referToNewConstant(value.toInt, width, false) case SLit(value, width) => referToNewConstant(value.toInt, width, true) + case propLit: PropertyLit[_, _] => referToNewProperty(propLit) case unhandled => throw new Exception(s"unhandled arg type to be reference: $unhandled") } } @@ -489,21 +534,19 @@ class PanamaCIRCTConverter extends CIRCTConverter { val verilogStream = new Writable { def writeBytesTo(out: OutputStream): Unit = { - def assertResult(result: MlirLogicalResult): Unit = { - assert(circt.mlirLogicalResultIsSuccess(result)) - } - - val pm = circt.mlirPassManagerCreate() - val options = circt.firtoolOptionsCreateDefault() - assertResult(circt.firtoolPopulatePreprocessTransforms(pm, options)) - assertResult(circt.firtoolPopulateCHIRRTLToLowFIRRTL(pm, options, mlirRootModule, "-")) - assertResult(circt.firtoolPopulateLowFIRRTLToHW(pm, options)) - assertResult(circt.firtoolPopulateHWToSV(pm, options)) - assertResult(circt.firtoolPopulateExportVerilog(pm, options, message => out.write(message.getBytes))) - assertResult(circt.mlirPassManagerRunOnOp(pm, circt.mlirModuleGetOperation(mlirRootModule))) + val pm = passManager() + assert(pm.populatePreprocessTransforms()) + assert(pm.populateCHIRRTLToLowFIRRTL()) + assert(pm.populateLowFIRRTLToHW()) + assert(pm.populateLowHWToSV()) + assert(pm.populateExportVerilog(message => out.write(message.getBytes))) + assert(pm.run()) } } + def passManager(): CIRCTPassManager = new PanamaCIRCTPassManager(circt, mlirRootModule) + def om(): CIRCTOM = new PanamaCIRCTOM(circt, mlirRootModule) + def visitCircuit(name: String): Unit = { val firCircuit = util .OpBuilder("firrtl.circuit", circt.mlirModuleGetBody(mlirRootModule), circt.unkLoc) @@ -1185,6 +1228,21 @@ class PanamaCIRCTConverter extends CIRCTConverter { // TODO: CIRCT emits `assert` for this, is it expected? visitVerification(cover, "firrtl.cover", Seq.empty) } + + def visitPropAssign(parent: Component, propAssign: PropAssign): Unit = { + val loc = util.convert(propAssign.sourceInfo) + + val dest = util.referTo(propAssign.loc.id, loc) + var src = util.referTo(Converter.getRef(propAssign.exp match { + case Node(id) => id + }, propAssign.sourceInfo), loc, Some((parent, propAssign.sourceInfo))) + + util + .OpBuilder("firrtl.propassign", firCtx.currentBlock, loc) + .withOperand( /* dest */ dest.value) + .withOperand( /* src */ src.value) + .build() + } } private[chisel3] object PanamaCIRCTConverter { @@ -1236,6 +1294,7 @@ private[chisel3] object PanamaCIRCTConverter { case cover: Verification[VerifCover] => visitVerfiCover(cover) case printf: Verification[VerifPrintf] => visitVerfiPrintf(printf) case stop: Verification[VerifStop] => visitVerfiStop(stop) + case propAssign: PropAssign => visitPropAssign(defModule, propAssign) case unhandled => throw new Exception(s"unhandled op: $unhandled") } } @@ -1318,4 +1377,7 @@ private[chisel3] object PanamaCIRCTConverter { // TODO: Not used anywhere? throw new Exception("unimplemented") } + def visitPropAssign(parent: Component, propAssign: PropAssign)(implicit cvt: CIRCTConverter): Unit = { + cvt.visitPropAssign(parent, propAssign) + } } diff --git a/binder/src/main/scala/PanamaCIRCTOM.scala b/binder/src/main/scala/PanamaCIRCTOM.scala new file mode 100644 index 00000000000..342438ab7bf --- /dev/null +++ b/binder/src/main/scala/PanamaCIRCTOM.scala @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: Apache-2.0 + +package chisel3.internal.panama.circt + +import chisel3.internal._ + +class PanamaCIRCTOM private[chisel3](circt: PanamaCIRCT, mlirModule: MlirModule) extends CIRCTOM { + def evaluator(): CIRCTOMEvaluator = new PanamaCIRCTOMEvaluator(circt, mlirModule) + + def newBasePathEmpty(): CIRCTOMEvaluatorValue = new PanamaCIRCTOMEvaluatorValueBasePath(circt, circt.omEvaluatorBasePathGetEmpty()) +} + +class PanamaCIRCTOMEvaluator private[chisel3](circt: PanamaCIRCT, mlirModule: MlirModule) extends CIRCTOMEvaluator { + val evaluator = circt.omEvaluatorNew(mlirModule) + + def instantiate(className: String, actualParams: Seq[CIRCTOMEvaluatorValue]): CIRCTOMObject = { + val params = actualParams.map(_.asInstanceOf[PanamaCIRCTOMEvaluatorValue].value) + + val value = circt.omEvaluatorInstantiate(evaluator, className, params) + assert(!circt.omEvaluatorObjectIsNull(value)) + new PanamaCIRCTOMObject(circt, value) + } +} + +abstract class PanamaCIRCTOMEvaluatorValue extends CIRCTOMEvaluatorValue { + val value: OMEvaluatorValue +} +object PanamaCIRCTOMEvaluatorValue { + def newValue(circt: PanamaCIRCT, value: OMEvaluatorValue): PanamaCIRCTOMEvaluatorValue = { + if (circt.omEvaluatorValueIsAObject(value)) { + throw new Exception("TODO") + } else if (circt.omEvaluatorValueIsAPrimitive(value)) { + new PanamaCIRCTOMEvaluatorValuePrimitive(circt, value) + } else if (circt.omEvaluatorValueIsAList(value)) { + new PanamaCIRCTOMEvaluatorValueList(circt, value) + } else if (circt.omEvaluatorValueIsATuple(value)) { + new PanamaCIRCTOMEvaluatorValueTuple(circt, value) + } else if (circt.omEvaluatorValueIsAMap(value)) { + new PanamaCIRCTOMEvaluatorValueMap(circt, value) + } else if (circt.omEvaluatorValueIsABasePath(value)) { + new PanamaCIRCTOMEvaluatorValueBasePath(circt, value) + } else if (circt.omEvaluatorValueIsAPath(value)) { + new PanamaCIRCTOMEvaluatorValuePath(circt, value) + } else { + throw new Exception("unknown OMEvaluatorValue type") + } + } +} + +class PanamaCIRCTOMEvaluatorValueList private[chisel3](circt: PanamaCIRCT, val value: OMEvaluatorValue) extends PanamaCIRCTOMEvaluatorValue { + val numElements: Int = circt.omEvaluatorListGetNumElements(value) + def getElement(index: Int) = PanamaCIRCTOMEvaluatorValue.newValue(circt, circt.omEvaluatorListGetElement(value, index)) +} + +class PanamaCIRCTOMEvaluatorValueTuple private[chisel3](circt: PanamaCIRCT, val value: OMEvaluatorValue) extends PanamaCIRCTOMEvaluatorValue { + val numElements: Int = circt.omEvaluatorTupleGetNumElements(value) + def getElement(index: Int) = PanamaCIRCTOMEvaluatorValue.newValue(circt, circt.omEvaluatorTupleGetElement(value, index)) +} + +class PanamaCIRCTOMEvaluatorValueMap private[chisel3](circt: PanamaCIRCT, val value: OMEvaluatorValue) extends PanamaCIRCTOMEvaluatorValue { + val tpe: MlirType = circt.omEvaluatorMapGetType(value) + val keys: MlirAttribute = circt.omEvaluatorMapGetKeys(value) + def getElement(attr: MlirAttribute) = PanamaCIRCTOMEvaluatorValue.newValue(circt, circt.omEvaluatorMapGetElement(value, attr)) +} + +class PanamaCIRCTOMEvaluatorValueBasePath private[chisel3](circt: PanamaCIRCT, val value: OMEvaluatorValue) extends PanamaCIRCTOMEvaluatorValue {} + +class PanamaCIRCTOMEvaluatorValuePath private[chisel3](circt: PanamaCIRCT, val value: OMEvaluatorValue) extends PanamaCIRCTOMEvaluatorValue { + def asString(): String = circt.omEvaluatorPathGetAsString(value) +} + +class PanamaCIRCTOMEvaluatorValuePrimitive private[chisel3](circt: PanamaCIRCT, val value: OMEvaluatorValue) extends PanamaCIRCTOMEvaluatorValue { + val primitive: MlirAttribute = circt.omEvaluatorValueGetPrimitive(value) +} + +class PanamaCIRCTOMObject private[chisel3](circt: PanamaCIRCT, value: OMEvaluatorValue) extends CIRCTOMObject { + def field(name: String): CIRCTOMEvaluatorValue = PanamaCIRCTOMEvaluatorValue.newValue(circt, circt.omEvaluatorObjectGetField(value, name)) +} diff --git a/binder/src/main/scala/PanamaCIRCTPassManager.scala b/binder/src/main/scala/PanamaCIRCTPassManager.scala new file mode 100644 index 00000000000..d5cb4aa45eb --- /dev/null +++ b/binder/src/main/scala/PanamaCIRCTPassManager.scala @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: Apache-2.0 + +package chisel3.internal.panama.circt + +import chisel3.internal._ + +class PanamaCIRCTPassManager private[chisel3](circt: PanamaCIRCT, mlirModule: MlirModule) extends CIRCTPassManager { + val pm = circt.mlirPassManagerCreate() + val options = circt.firtoolOptionsCreateDefault() // TODO: Make it configurable from CIRCTPassManager + + private def isSuccess(result: MlirLogicalResult): Boolean = circt.mlirLogicalResultIsSuccess(result) + + def populatePreprocessTransforms(): Boolean = isSuccess(circt.firtoolPopulatePreprocessTransforms(pm, options)) + def populateCHIRRTLToLowFIRRTL(): Boolean = isSuccess(circt.firtoolPopulateCHIRRTLToLowFIRRTL(pm, options, mlirModule, "-")) + def populateLowFIRRTLToHW(): Boolean = isSuccess(circt.firtoolPopulateLowFIRRTLToHW(pm, options)) + def populateLowHWToSV(): Boolean = isSuccess(circt.firtoolPopulateHWToSV(pm, options)) + def populateExportVerilog(callback: String => Unit): Boolean = isSuccess(circt.firtoolPopulateExportVerilog(pm, options, callback)) + def populateExportSplitVerilog(directory: String): Boolean = isSuccess(circt.firtoolPopulateExportSplitVerilog(pm, options, directory)) + def populateFinalizeIR(): Boolean = isSuccess(circt.firtoolPopulateFinalizeIR(pm, options)) + + def run(): Boolean = isSuccess(circt.mlirPassManagerRunOnOp(pm, circt.mlirModuleGetOperation(mlirModule))) +} diff --git a/binder/src/test/scala/BinderSpec.scala b/binder/src/test/scala/BinderSpec.scala index e1ccae93437..27cc6591f1d 100644 --- a/binder/src/test/scala/BinderSpec.scala +++ b/binder/src/test/scala/BinderSpec.scala @@ -2,12 +2,15 @@ package chiselTests.util.random +import java.io.OutputStream import geny.Writable +import scala.collection.immutable.SeqMap import chisel3._ import chisel3.util._ import chisel3.experimental._ import chisel3.internal.CIRCTConverter -import chisel3.internal.panama.circt.PanamaCIRCTConverterAnnotation +import chisel3.internal.panama.circt._ +import chisel3.properties._ import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers @@ -38,6 +41,18 @@ class BitLengthOfNeg1Test extends RawModule { a := -1.S.asUInt } +class PropertyTest extends RawModule { + val i = IO(Input(UInt(8.W))) + + val p = IO(Output(Property[Path]())) + p := Property(Path(i)) + + val a = IO(Output(Property[Seq[Seq[Property[Int]]]]())) + val b = IO(Output(Property[Seq[Property[Seq[Int]]]]())) + a := Property(Seq[Seq[Int]](Seq(123))) + b := Property(Seq[Seq[Int]](Seq(123))) +} + class BinderTest extends AnyFlatSpec with Matchers { def streamString(module: => RawModule, stream: CIRCTConverter => Writable): String = Seq( @@ -85,5 +100,25 @@ class BinderTest extends AnyFlatSpec with Matchers { firrtlString(new TruncationTest) should include("connect dest, tail(src, 8)") firrtlString(new BitLengthOfNeg1Test) should include("asUInt(SInt<1>(-1))") + + streamString(new PropertyTest, (converter: CIRCTConverter) => { + val pm = converter.passManager() + assert(pm.populatePreprocessTransforms()) + assert(pm.populateCHIRRTLToLowFIRRTL()) + assert(pm.populateLowFIRRTLToHW()) + assert(pm.populateFinalizeIR()) + assert(pm.run()) + + val om = converter.om() + val evaluator = om.evaluator() + val obj = evaluator.instantiate("PropertyTest_Class", Seq(om.newBasePathEmpty)) + val path = obj.field("p").asInstanceOf[PanamaCIRCTOMEvaluatorValuePath].asString + + assert(path == "OMReferenceTarget:~PropertyTest|PropertyTest>i") + + converter.mlirStream + }) should include("om.class.field @p, %1 : !om.frozenpath") + .and(include("om.class.field @a, %3 : !om.list>")) + .and(include("om.class.field @b, %3 : !om.list>")) } } diff --git a/core/src/main/scala/chisel3/internal/CIRCTConverter.scala b/core/src/main/scala/chisel3/internal/CIRCTConverter.scala index e0019036ffc..f42ccbce8d2 100644 --- a/core/src/main/scala/chisel3/internal/CIRCTConverter.scala +++ b/core/src/main/scala/chisel3/internal/CIRCTConverter.scala @@ -10,9 +10,13 @@ import chisel3.cover.Cover import chisel3.internal.firrtl._ abstract class CIRCTConverter { + val mlirStream: Writable val firrtlStream: Writable val verilogStream: Writable + def passManager(): CIRCTPassManager + def om(): CIRCTOM + def visitCircuit(name: String): Unit def visitDefBlackBox(defBlackBox: DefBlackBox): Unit @@ -60,4 +64,6 @@ abstract class CIRCTConverter { def visitAssume(assume: Verification[Assume]): Unit def visitCover(cover: Verification[Cover]): Unit + + def visitPropAssign(parent: Component, propAssign: PropAssign): Unit } diff --git a/core/src/main/scala/chisel3/internal/CIRCTOM.scala b/core/src/main/scala/chisel3/internal/CIRCTOM.scala new file mode 100644 index 00000000000..c4c67a412d8 --- /dev/null +++ b/core/src/main/scala/chisel3/internal/CIRCTOM.scala @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: Apache-2.0 + +package chisel3.internal + +abstract class CIRCTOM { + def evaluator(): CIRCTOMEvaluator + + def newBasePathEmpty(): CIRCTOMEvaluatorValue +} + +abstract class CIRCTOMEvaluator { + def instantiate(name: String, actualParams: Seq[CIRCTOMEvaluatorValue]): CIRCTOMObject +} + +abstract class CIRCTOMEvaluatorValue {} + +abstract class CIRCTOMObject { + def field(name: String): CIRCTOMEvaluatorValue +} diff --git a/core/src/main/scala/chisel3/internal/CIRCTPassManager.scala b/core/src/main/scala/chisel3/internal/CIRCTPassManager.scala new file mode 100644 index 00000000000..80a64f3497c --- /dev/null +++ b/core/src/main/scala/chisel3/internal/CIRCTPassManager.scala @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: Apache-2.0 + +package chisel3.internal + +abstract class CIRCTPassManager { + def populatePreprocessTransforms(): Boolean + def populateCHIRRTLToLowFIRRTL(): Boolean + def populateLowFIRRTLToHW(): Boolean + def populateLowHWToSV(): Boolean + def populateExportVerilog(callback: String => Unit): Boolean + def populateExportSplitVerilog(directory: String): Boolean + def populateFinalizeIR(): Boolean + + def run(): Boolean; +}