Skip to content

Commit 374bf92

Browse files
authored
Merge pull request #224 from DFiantHDL/designparam_refactor
Designparam refactor
2 parents ad593de + ad0c545 commit 374bf92

File tree

66 files changed

+1471
-153
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+1471
-153
lines changed

compiler/ir/src/main/scala/dfhdl/compiler/analysis/DFValAnalysis.scala

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -41,19 +41,26 @@ object Ident:
4141
// val arg: Bit <> CONST = newArg
4242
// val x = Bit <> IN init arg
4343
//```
44-
object DesignParam:
45-
def unapply(alias: DFVal.Alias.AsIs)(using MemberGetSet): Option[DFVal] =
46-
if (alias.hasTagOf[DFVal.Alias.DesignParamTag.type])
47-
val relVal = alias.relValRef.get
48-
// if (
49-
// relVal.existsInComposedReadDeps { dep =>
50-
// dep.hasTagOf[DFVal.Alias.DesignParamTag.type] &&
51-
// dep.isSameOwnerDesignAs(alias)
52-
// }
53-
// ) None
54-
Some(relVal)
55-
else None
56-
end DesignParam
44+
// object DesignParam:
45+
// def unapply(alias: DFVal.Alias.AsIs)(using MemberGetSet): Option[DFVal] =
46+
// if (alias.hasTagOf[DFVal.Alias.DesignParamTag.type])
47+
// val relVal = alias.relValRef.get
48+
// // if (
49+
// // relVal.existsInComposedReadDeps { dep =>
50+
// // dep.hasTagOf[DFVal.Alias.DesignParamTag.type] &&
51+
// // dep.isSameOwnerDesignAs(alias)
52+
// // }
53+
// // ) None
54+
// Some(relVal)
55+
// else None
56+
// end DesignParam
57+
58+
//extract the design param from its default value
59+
object DefaultOfDesignParam:
60+
def unapply(dfVal: DFVal)(using MemberGetSet): Option[DFVal.DesignParam] =
61+
dfVal.originMembers.collectFirst {
62+
case dp: DFVal.DesignParam if dp.defaultRef.get == dfVal => dp
63+
}
5764

5865
object OpaqueActual:
5966
def unapply(alias: DFVal.Alias.AsIs)(using MemberGetSet): Option[DFVal] =
@@ -410,7 +417,7 @@ extension (net: DFNet)
410417
extension (member: DFMember)
411418
def isPublicMember(using MemberGetSet): Boolean =
412419
member match
413-
case DclPort() => true
414-
case DesignParam(_) => true
415-
case _: DomainBlock => true
416-
case _ => false
420+
case DclPort() => true
421+
case _: DFVal.DesignParam => true
422+
case _: DomainBlock => true
423+
case _ => false

compiler/ir/src/main/scala/dfhdl/compiler/ir/DB.scala

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -753,7 +753,9 @@ final case class DB(
753753
membersNoGlobals.view.drop(1).flatMap {
754754
case _: PortByNameSelect => None
755755
case m =>
756-
val isDesignParam = m.hasTagOf[DFVal.Alias.DesignParamTag.type]
756+
val isDesignParam = m match
757+
case _: DFVal.DesignParam => true
758+
case _ => false
757759
m.getRefs.view.map(_.get).flatMap {
758760
// global values are ok to be referenced
759761
case dfVal: DFVal.CanBeGlobal if dfVal.isGlobal => None
@@ -765,18 +767,21 @@ final case class DB(
765767
if (refMember.isOutsideOwner(m.getOwnerDesign))
766768
Some(refMember)
767769
else None
768-
// design parameters are expected to reference values from their parent design
769-
case refMember if isDesignParam =>
770-
if (m.isOneLevelBelow(refMember)) None
771-
else Some(refMember)
772770
// design referenced by its member (like in RelatedDomain)
773771
case refMember: DFDesignBlock =>
774772
if (m.isMemberOf(refMember)) None
775773
else Some(refMember)
776-
// the rest must be in the same design
777-
case refMember if !refMember.isSameOwnerDesignAs(m) =>
778-
Some(refMember)
779-
case _ => None
774+
case refMember =>
775+
m match
776+
// design parameters are expected to reference values from their parent design
777+
// or from the same design for default parameter values
778+
case dp: DFVal.DesignParam =>
779+
if (refMember.isSameOwnerDesignAs(dp) && dp.defaultRef.get == refMember) None
780+
else if (m.isOneLevelBelow(refMember)) None
781+
else Some(refMember)
782+
// the rest must be in the same design
783+
case _ if !refMember.isSameOwnerDesignAs(m) => Some(refMember)
784+
case _ => None
780785
}.map(m -> _)
781786
}.toList
782787
val errorMessages = problemReferences.map { (from, to) =>

compiler/ir/src/main/scala/dfhdl/compiler/ir/DFMember.scala

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -155,11 +155,13 @@ sealed trait DFVal extends DFMember.Named:
155155
final def isConst(using MemberGetSet): Boolean = getConstData.nonEmpty
156156
// two expressions are considered to be similar if
157157
final def isSimilarTo(that: DFVal)(using MemberGetSet): Boolean =
158-
def dealiasAsIs(dfVal: DFVal): DFVal = dfVal match
158+
def stripAsIsAndDesignParam(dfVal: DFVal): DFVal = dfVal match
159159
case DFVal.Alias.AsIs(dfType, DFRef(relVal), _, _, _) if dfType == relVal.dfType =>
160-
dealiasAsIs(relVal)
160+
stripAsIsAndDesignParam(relVal)
161+
case DFVal.DesignParam(_, DFRef(dfVal), _, _, _, _) =>
162+
stripAsIsAndDesignParam(dfVal)
161163
case _ => dfVal
162-
(dealiasAsIs(this), dealiasAsIs(that)) match
164+
(stripAsIsAndDesignParam(this), stripAsIsAndDesignParam(that)) match
163165
case (lhs: DFVal.CanBeExpr, rhs: DFVal.CanBeExpr) => lhs.protIsSimilarTo(rhs)
164166
case (lhs, rhs) => lhs == rhs
165167
protected def protGetConstData(using MemberGetSet): Option[Any]
@@ -221,6 +223,9 @@ object DFVal:
221223
def isOpen: Boolean = dfVal match
222224
case _: DFVal.OPEN => true
223225
case _ => false
226+
def isDesignParam: Boolean = dfVal match
227+
case _: DFVal.DesignParam => true
228+
case _ => false
224229
@tailrec def dealias(using MemberGetSet): Option[DFVal.Dcl | DFVal.OPEN] = dfVal match
225230
case dcl: DFVal.Dcl => Some(dcl)
226231
case portByNameSelect: DFVal.PortByNameSelect => Some(portByNameSelect.getPortDcl)
@@ -337,6 +342,48 @@ object DFVal:
337342
).asInstanceOf[this.type]
338343
end Const
339344

345+
final case class DesignParam(
346+
dfType: DFType,
347+
dfValRef: DesignParam.Ref,
348+
defaultRef: DesignParam.DefaultRef,
349+
ownerRef: DFOwner.Ref,
350+
meta: Meta,
351+
tags: DFTags
352+
) extends CanBeExpr:
353+
assert(!this.isAnonymous, "Design parameters cannot be anonymous.")
354+
protected def protIsFullyAnonymous(using MemberGetSet): Boolean = false
355+
protected def protGetConstData(using MemberGetSet): Option[Any] =
356+
dfValRef.get.getConstData
357+
protected def `prot_=~`(that: DFMember)(using MemberGetSet): Boolean = that match
358+
case that: DesignParam =>
359+
// design parameters are considered to be the same even if they are referencing
360+
// a different member (this should be quite common), because that member is
361+
// external to the design. however, different default value is considered to be a
362+
// different design parameter.
363+
this.dfType =~ that.dfType && this.defaultRef =~ that.defaultRef &&
364+
this.meta =~ that.meta && this.tags =~ that.tags
365+
case _ => false
366+
protected[ir] def protIsSimilarTo(that: CanBeExpr)(using MemberGetSet): Boolean =
367+
that match
368+
case that: DesignParam =>
369+
this.dfType.isSimilarTo(that.dfType) &&
370+
this.dfValRef.get.isSimilarTo(that.dfValRef.get)
371+
case _ => false
372+
protected def setMeta(meta: Meta): this.type = copy(meta = meta).asInstanceOf[this.type]
373+
protected def setTags(tags: DFTags): this.type = copy(tags = tags).asInstanceOf[this.type]
374+
lazy val getRefs: List[DFRef.TwoWayAny] = dfValRef :: defaultRef :: dfType.getRefs
375+
def updateDFType(dfType: DFType): this.type = copy(dfType = dfType).asInstanceOf[this.type]
376+
def copyWithNewRefs: this.type = copy(
377+
dfType = dfType.copyWithNewRefs,
378+
ownerRef = ownerRef.copyAsNewRef,
379+
dfValRef = dfValRef.copyAsNewRef,
380+
defaultRef = defaultRef.copyAsNewRef
381+
).asInstanceOf[this.type]
382+
end DesignParam
383+
object DesignParam:
384+
type Ref = DFRef.TwoWay[DFVal, DesignParam]
385+
type DefaultRef = DFRef.TwoWay[DFVal | DFMember.Empty, DesignParam]
386+
340387
final case class OPEN(
341388
dfType: DFType,
342389
ownerRef: DFOwner.Ref
@@ -517,7 +564,6 @@ object DFVal:
517564

518565
object Alias:
519566
case object IdentTag extends DFTagOf[DFVal]
520-
case object DesignParamTag extends DFTagOf[DFVal]
521567
type Ref = DFRef.TwoWay[DFVal, Alias]
522568
// This is complete alias that consumes its relative val
523569
sealed trait Consumer extends Alias:
@@ -546,13 +592,7 @@ object DFVal:
546592
)
547593
protected def `prot_=~`(that: DFMember)(using MemberGetSet): Boolean = that match
548594
case that: AsIs =>
549-
// design parameters are considered to be the same even if they are referencing
550-
// a different member (this should be quite common), because that member is
551-
// external to the design.
552-
val sameRelVal =
553-
if (this.hasTagOf[DesignParamTag.type]) true
554-
else this.relValRef =~ that.relValRef
555-
this.dfType =~ that.dfType && sameRelVal &&
595+
this.dfType =~ that.dfType && this.relValRef =~ that.relValRef &&
556596
this.meta =~ that.meta && this.tags =~ that.tags
557597
case _ => false
558598
protected[ir] def protIsSimilarTo(that: CanBeExpr)(using MemberGetSet): Boolean =

compiler/ir/src/main/scala/dfhdl/compiler/printing/DFOwnerPrinter.scala

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ trait AbstractOwnerPrinter extends AbstractPrinter:
1818
// excluding binds
1919
case Bind(_) => false
2020
// excluding design params
21-
case DesignParam(_) => false
21+
case _: DFVal.DesignParam => false
2222
// an ident placeholder (can be anonymous)
2323
case Ident(_) => true
2424
// a def design that is anonymous may not be referenced later,
@@ -176,7 +176,7 @@ protected trait DFOwnerPrinter extends AbstractOwnerPrinter:
176176
val defArgsCS =
177177
if (defArgList.length <= 2) defArgList.mkString(", ")
178178
else defArgList.mkString("\n", ",\n", "\n").hindent(2)
179-
val designParamList = design.members(MemberView.Folded).collect { case param @ DesignParam(_) =>
179+
val designParamList = design.members(MemberView.Folded).collect { case param: DesignParam =>
180180
s"${param.getName}${printer.csDFValConstType(param.dfType)}"
181181
}
182182
val designParamCS =
@@ -194,8 +194,8 @@ protected trait DFOwnerPrinter extends AbstractOwnerPrinter:
194194
val DFNet.Connection(_, from: DFVal, _) = port.getConnectionTo.get: @unchecked
195195
printer.csDFValRef(from, design.getOwner)
196196
}.mkString(", ")
197-
val designParamList = design.members(MemberView.Folded).collect { case param @ DesignParam(_) =>
198-
s"${param.getName} = ${param.relValRef.refCodeString}"
197+
val designParamList = design.members(MemberView.Folded).collect { case param: DesignParam =>
198+
s"${param.getName} = ${param.dfValRef.refCodeString}"
199199
}
200200
val designParamCS =
201201
if (designParamList.length == 0) ""
@@ -218,8 +218,13 @@ protected trait DFOwnerPrinter extends AbstractOwnerPrinter:
218218
case _ => s"(${printer.csRTDomainCfg(rt.cfg)})"
219219
s"""RTDesign$cfgStr""".stripMargin
220220
case _ => "EDDesign"
221-
val designParamList = design.members(MemberView.Folded).collect { case param @ DesignParam(_) =>
222-
val defaultValue = if (design.isTop) s" = ${param.relValRef.refCodeString}" else ""
221+
val designParamList = design.members(MemberView.Folded).collect { case param: DesignParam =>
222+
val defaultValue =
223+
if (design.isTop) s" = ${param.dfValRef.refCodeString}"
224+
else
225+
param.defaultRef.get match
226+
case DFMember.Empty => ""
227+
case _ => s" = ${param.defaultRef.refCodeString}"
223228
s"val ${param.getName}${printer.csDFValConstType(param.dfType)}$defaultValue"
224229
}
225230
val designParamCS =
@@ -233,8 +238,8 @@ protected trait DFOwnerPrinter extends AbstractOwnerPrinter:
233238
end csDFDesignBlockDcl
234239
def csDFDesignBlockInst(design: DFDesignBlock): String =
235240
val body = csDFDesignLateBody(design)
236-
val designParamList = design.members(MemberView.Folded).collect { case param @ DesignParam(_) =>
237-
s"${param.getName} = ${param.relValRef.refCodeString}"
241+
val designParamList = design.members(MemberView.Folded).collect { case param: DesignParam =>
242+
s"${param.getName} = ${param.dfValRef.refCodeString}"
238243
}
239244
val designParamCS =
240245
if (designParamList.length <= 1) designParamList.mkString("(", ", ", ")")

compiler/ir/src/main/scala/dfhdl/compiler/printing/DFValPrinter.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ trait AbstractValPrinter extends AbstractPrinter:
7373
extension (named: DFMember.Named)
7474
def nameCS: String = if (typeCS) s"${csDFMemberName(named)}.type" else csDFMemberName(named)
7575
member match
76-
case dfVal @ DesignParam(_) => dfVal.nameCS
76+
case dfVal: DFVal.DesignParam => dfVal.nameCS
7777
case dfVal: DFVal.CanBeGlobal if dfVal.isGlobal =>
7878
if (dfVal.isAnonymous) printer.csDFValExpr(dfVal)
7979
else dfVal.nameCS
@@ -133,6 +133,7 @@ trait AbstractValPrinter extends AbstractPrinter:
133133
case dv: Const => csDFValConstExpr(dv)
134134
case dv: Func => csDFValFuncExpr(dv, typeCS)
135135
case dv: Alias => csDFValAliasExpr(dv)
136+
case dv: DFVal.DesignParam => dv.dfValRef.refCodeString
136137
case dv: DFConditional.Header => printer.csDFConditional(dv)
137138
case dv: Timer.IsActive => csTimerIsActive(dv)
138139
case dv: NOTHING => csNOTHING(dv)

compiler/stages/src/main/resources/dfhdl_defs.svh

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,6 @@
2424
//
2525
// For more information, please refer to <http://unlicense.org/>
2626

27-
`ifndef DFHDL_DEFS
28-
`define DFHDL_DEFS
2927
`define MAX(a,b) ((a) > (b) ? (a) : (b))
3028
`define MIN(a,b) ((a) < (b) ? (a) : (b))
31-
`endif
3229

compiler/stages/src/main/resources/dfhdl_defs.vh

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424
//
2525
// For more information, please refer to <http://unlicense.org/>
2626

27-
`ifndef DFHDL_DEFS
28-
`define DFHDL_DEFS
2927
`define MAX(a,b) ((a) > (b) ? (a) : (b))
3028
`define MIN(a,b) ((a) < (b) ? (a) : (b))
3129
`define TO_VEC_HEX(hex, hw, vw) \
@@ -77,5 +75,4 @@ begin
7775
end
7876
end
7977
endfunction
80-
`endif
8178

compiler/stages/src/main/scala/dfhdl/compiler/analysis/DBAnalysis.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ extension (designDB: DB)
1515
def getUnusedParamAnnotValues: List[DFVal] =
1616
import designDB.getSet
1717
designDB.members.collect:
18-
case dfVal @ DesignParam(_) if dfVal.wasConstDataAccessed => dfVal
18+
case dfVal: DFVal.DesignParam if dfVal.wasConstDataAccessed => dfVal
1919
def getUnusedBitsValues: List[(DFVal, Int, Int)] =
2020
import designDB.getSet
2121
designDB.members.flatMap:

compiler/stages/src/main/scala/dfhdl/compiler/stages/GlobalizePortVectorParams.scala

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import scala.collection.immutable.ListMap
99
import scala.collection.mutable
1010
import dfhdl.compiler.stages.vhdl.VHDLDialect
1111
import dfhdl.core.{DFTypeAny, asFE}
12-
import dfhdl.compiler.ir.DFVal.Alias.DesignParamTag
1312
import dfhdl.compiler.ir.DFVal.PortByNameSelect
1413

1514
/** This stage globalizes design parameters that set port vector lengths. This is needed only for
@@ -30,14 +29,16 @@ case object GlobalizePortVectorParams extends Stage:
3029
val designParams = mutable.LinkedHashSet.empty[DFVal]
3130
// check ref
3231
def checkRef(ref: DFRef.TwoWayAny): Int =
33-
val dfVal = ref.get.asInstanceOf[DFVal]
34-
if (dfVal.isGlobal) 0
35-
else
36-
val ret = dfVal.getRefs.map(checkRef).sum
37-
if (dfVal.isAnonymous) ret
38-
else
39-
designParams += dfVal
40-
ret + 1
32+
ref.get match
33+
case dfVal: DFVal =>
34+
if (dfVal.isGlobal) 0
35+
else
36+
val ret = dfVal.getRefs.map(checkRef).sum
37+
if (dfVal.isAnonymous) ret
38+
else
39+
designParams += dfVal
40+
ret + 1
41+
case _ => 0
4142
// check int param ref
4243
def checkIntParamRef(intParamRef: IntParamRef): Int =
4344
intParamRef.getRef.map(checkRef).getOrElse(0)
@@ -171,9 +172,23 @@ case object GlobalizePortVectorParams extends Stage:
171172
val dsn = new MetaDesign(dupDesignDB.top, Patch.Add.Config.Before):
172173
// patches to replace with properly named parameter or just move the anonymous members
173174
val replacePatches = addedGlobals.map {
174-
case m if !m.isAnonymous =>
175+
// design parameters are transformed into global as-is named aliases
176+
case param: DFVal.DesignParam =>
177+
val updatedMeta = param.meta.setName(param.getFullName.replaceAll("\\.", "_"))
175178
val globalParam =
176-
m.setName(m.getFullName.replaceAll("\\.", "_")).removeTagOf[DesignParamTag.type]
179+
DFVal.Alias.AsIs(
180+
param.dfType,
181+
// TODO: the class tag here is incorrect (currently is DesignParam) and should be fixed or...
182+
// do we really need the tags at all?
183+
param.dfValRef.asInstanceOf[DFVal.Alias.PartialRef],
184+
param.ownerRef,
185+
updatedMeta,
186+
param.tags
187+
)
188+
plantMember(globalParam)
189+
param -> Patch.Replace(globalParam, Patch.Replace.Config.ChangeRefAndRemove)
190+
case m if !m.isAnonymous =>
191+
val globalParam = m.setName(m.getFullName.replaceAll("\\.", "_"))
177192
plantMember(globalParam)
178193
m -> Patch.Replace(globalParam, Patch.Replace.Config.ChangeRefAndRemove)
179194
case m =>

compiler/stages/src/main/scala/dfhdl/compiler/stages/OrderMembers.scala

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,21 +33,23 @@ object OrderMembers:
3333
object Order:
3434
object Simple extends Order:
3535
def apply()(using MemberGetSet): DFMember => Int = {
36-
// design parameters come first as they are dependent only on external
37-
// initialization and everything else can depend on them
38-
case DesignParam(_) => 1
39-
// anonymous members that are referenced by declarations come second
40-
case dfVal: DFVal if dfVal.isReferencedByAnyDcl => 2
41-
// third to come are constant declarations that may be referenced by ports
42-
case DclConst() => 3
43-
// fourth are ports
44-
case DclPort() => 4
45-
// fifth are variables
46-
case DclVar() => 5
47-
// sixth are design blocks instances
48-
case _: DFDesignBlock => 6
36+
// design parameter's default value comes first
37+
case DefaultOfDesignParam(_) => 1
38+
// design parameters come second as they are dependent only on external
39+
// initialization or default values and everything else can depend on them
40+
case _: DFVal.DesignParam => 2
41+
// anonymous members that are referenced by declarations come third
42+
case dfVal: DFVal if dfVal.isReferencedByAnyDcl => 3
43+
// fourth to come are constant declarations that may be referenced by ports
44+
case DclConst() => 4
45+
// fifth are ports
46+
case DclPort() => 5
47+
// sixth are variables
48+
case DclVar() => 6
49+
// seventh are design blocks instances
50+
case _: DFDesignBlock => 7
4951
// then the rest
50-
case _ => 7
52+
case _ => 8
5153
}
5254
end Simple
5355
// val GuardedLast: Order = new Order:

0 commit comments

Comments
 (0)