All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dfhdl.compiler.patching.MetaDesign.scala Maven / Gradle / Ivy

package dfhdl.compiler.patching
import dfhdl.core.*
import dfhdl.compiler.ir
import Patch.Add.Config as AddCfg
import scala.annotation.unchecked.uncheckedVariance

type MetaDesignAny = MetaDesign[DFC.Domain]
abstract class MetaDesign[+D <: DFC.Domain](
    positionMember: ir.DFMember,
    addCfg: AddCfg,
    domainType: D = DFC.Domain.DF
)(using
    getSet: ir.MemberGetSet
) extends Design
    with reflect.Selectable:
  lazy val patch = positionMember -> Patch.Add(this, addCfg)
  lazy val injectedOwner: ir.DFOwner = addCfg match
    case AddCfg.InsideFirst | AddCfg.InsideLast =>
      positionMember match
        case positionOwner: ir.DFOwner => positionOwner
        case _ => throw new IllegalArgumentException("Expecting owner member for AddInside config.")
    case _ => positionMember.getOwner
  final override private[dfhdl] def initOwner: Design.Block =
    dfc.mutableDB.addMember(injectedOwner)
    injectedOwner.getThisOrOwnerDesign.asFE
  injectedOwner match
    case design: ir.DFDesignBlock => // do nothing
    case _ =>
      dfc.enterOwner(injectedOwner.asFE)

  dfc.mutableDB.setMetaGetSet(getSet)
  final type TDomain = D @uncheckedVariance
  final protected given TDomain = domainType
  // we don't really care about the IR domain type of a meta design, since it is removed.
  // only the compile-time domain type is important for meta-programming with the relevant constraints.
  final lazy val __domainType: ir.DomainType = ir.DomainType.DF

  final def plantMember[T <: ir.DFMember](member: T): T =
    dfc.mutableDB.plantMember(dfc.owner.asIR, member)
  final def applyBlock(owner: ir.DFOwner)(block: => Unit): Unit =
    dfc.mutableDB.OwnershipContext.enter(owner)
    block
    dfc.mutableDB.OwnershipContext.exit()
  // meta designs may be intermediate erroneous designs
  final override private[dfhdl] def skipChecks: Boolean = true

  export dfhdl.hdl.{RTDomainCfg => _, ClkCfg => _, RstCfg => _, *}
  export dfhdl.core.{asValAny, asVarAny, asDclAny, asConstAny}
  extension (dfVal: ir.DFVal)
    def cloneAnonValueAndDepsHere: ir.DFVal =
      if (dfVal.isAnonymous)
        val dfcForClone = dfc.setMeta(dfVal.meta)
        val dfType = dfVal.dfType.asFE[DFTypeAny]
        val cloned = locally {
          given DFC = dfcForClone
          dfVal match
            case const: ir.DFVal.Const =>
              DFVal.Const.forced(const.dfType.asFE[DFTypeAny], const.data)
            case func: ir.DFVal.Func =>
              val clonedArgs = func.args.map(_.get.cloneAnonValueAndDepsHere)
              DFVal.Func(func.dfType.asFE[DFTypeAny], func.op, clonedArgs)
            case alias: ir.DFVal.Alias.Partial =>
              val clonedRelValIR = alias.relValRef.get.cloneAnonValueAndDepsHere
              val clonedRelVal = clonedRelValIR.asValAny
              alias match
                case alias: ir.DFVal.Alias.AsIs =>
                  DFVal.Alias.AsIs(dfType, clonedRelVal, forceNewAlias = true)
                case alias: ir.DFVal.Alias.ApplyRange =>
                  DFVal.Alias.ApplyRange(
                    clonedRelVal.asValOf[Bits[Int]],
                    alias.relBitHigh,
                    alias.relBitLow
                  )
                case alias: ir.DFVal.Alias.ApplyIdx =>
                  val clonedIdx = alias.relIdx.get.cloneAnonValueAndDepsHere.asValOf[DFUInt[Int]]
                  DFVal.Alias.ApplyIdx(dfType, clonedRelVal, clonedIdx)
                case alias: ir.DFVal.Alias.SelectField =>
                  DFVal.Alias.SelectField(clonedRelVal, alias.fieldName)
            case _ => throw new IllegalArgumentException(s"Unsupported cloning for: $dfVal")
          end match
        }
        cloned.asIR.setTags(_ => dfVal.tags)
      else dfVal
  extension [T <: DFTypeAny, A, C, I, P](dfVal: DFVal[T, Modifier[A, C, I, P]])
    def asInitialized: DFVal[T, Modifier[A, C, Modifier.Initialized, P]] =
      dfVal.asInstanceOf[DFVal[T, Modifier[A, C, Modifier.Initialized, P]]]
    def asUninitialized: DFVal[T, Modifier[A, C, Modifier.Initializable, P]] =
      dfVal.asInstanceOf[DFVal[T, Modifier[A, C, Modifier.Initializable, P]]]
end MetaDesign




© 2015 - 2025 Weber Informatics LLC | Privacy Policy