Skip to content

Commit 5de95cb

Browse files
authored
Merge pull request #244 from DFiantHDL/simulator
v0.10.0
2 parents 438c329 + acc43a0 commit 5de95cb

File tree

277 files changed

+5924
-1353
lines changed

Some content is hidden

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

277 files changed

+5924
-1353
lines changed

.scalafmt.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
version = 3.9.3
1+
version = 3.9.4
22
runner.dialect = scala3
33

44
maxColumn = 100

build.sbt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ commands += DFHDLCommands.docExamplesRefUpdate
33

44
// format: off
55
val projectName = "dfhdl"
6-
val compilerVersion = "3.6.4"
6+
val compilerVersion = "3.7.0-RC4"
77

88
inThisBuild(
99
List(
@@ -148,7 +148,7 @@ lazy val dependencies =
148148
private val scodecV = "1.2.1"
149149
private val munitV = "1.1.0"
150150
private val scalafmtV = "3.8.3"
151-
private val airframelogV = "2025.1.6"
151+
private val airframelogV = "2025.1.10"
152152
private val oslibV = "0.9.2"
153153
private val scallopV = "5.2.0"
154154
val scodec = "org.scodec" %% "scodec-bits" % scodecV
@@ -212,7 +212,9 @@ lazy val pluginTestUseSettings = Seq(
212212
val jar = (plugin / Compile / packageBin).value
213213
Seq(
214214
s"-Xplugin:${jar.getAbsolutePath}",
215-
s"-Jdummy=${jar.lastModified}"
215+
s"-Jdummy=${jar.lastModified}",
216+
// "-Yprofile-enabled",
217+
// "-Yprofile-trace:compiler.trace"
216218
)
217219
}
218220
)

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ extension [CB <: DFConditional.Block](cb: CB)(using MemberGetSet)
5050
def isExhaustive: Option[Boolean] = cb match
5151
case ib: DFConditional.DFIfElseBlock if ib.guardRef.get == DFMember.Empty =>
5252
Some(true) // else block
53-
case DFConditional.DFCaseBlock(Pattern.CatchAll, gr, _, _, _, _) if gr.get == DFMember.Empty =>
53+
case DFConditional.DFCaseBlock(pattern = Pattern.CatchAll, guardRef = gr)
54+
if gr.get == DFMember.Empty =>
5455
Some(true) // case _ => block
5556
case cb: DFConditional.Block if cb.guardRef.get != DFMember.Empty =>
5657
None // if not all guards are empty, then we cannot know if the coverage is exhaustive

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package dfhdl.compiler
22
package analysis
33
import dfhdl.internals.*
44
import ir.*
5-
5+
import scala.annotation.tailrec
66
extension (owner: DFOwner)
77
def members(memberView: MemberView)(using MemberGetSet): List[DFMember] =
88
getSet.designDB.getMembersOf(owner, memberView)
@@ -20,3 +20,12 @@ extension (owner: DFOwner)
2020
case x => x // return the very last member
2121
case x => x
2222
end extension
23+
24+
extension (domainOwner: DFDomainOwner)
25+
// true if the domainOwner is dependent at any level of thatDomainOwner's configuration
26+
@tailrec def isDependentOn(thatDomainOwner: DFDomainOwner)(using getSet: MemberGetSet): Boolean =
27+
getSet.designDB.dependentRTDomainOwners.get(domainOwner) match
28+
case Some(dependency) =>
29+
if (dependency == thatDomainOwner) true
30+
else dependency.isDependentOn(thatDomainOwner)
31+
case None => false

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

Lines changed: 53 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ object Ident:
2121
if (alias.hasTagOf[DFVal.Alias.IdentTag.type]) Some(alias.relValRef.get)
2222
else None
2323

24+
object StrippedPortByNameSelect:
25+
def unapply(dfVal: DFVal)(using MemberGetSet): Option[DFVal] = Some(dfVal.stripPortSel)
26+
2427
//A design parameter is an as-is alias that:
2528
//1. has `DesignParamTag` tag
2629
//TODO: This is not yet working. more complicated than initially thought.
@@ -101,9 +104,11 @@ object RstActive:
101104
case FuncOp.=== | FuncOp.=!= =>
102105
val List(lhsRef, rhsRef) = func.args
103106
val (dcl, const) = (lhsRef.get, rhsRef.get) match
104-
case (dcl: DFVal.Dcl, const: DFVal.Const) if const.dfType equals DFBit =>
107+
case (dcl: (DFVal.Dcl | DFVal.PortByNameSelect), const: DFVal.Const)
108+
if const.dfType equals DFBit =>
105109
(dcl, const)
106-
case (const: DFVal.Const, dcl: DFVal.Dcl) if const.dfType equals DFBit =>
110+
case (const: DFVal.Const, dcl: (DFVal.Dcl | DFVal.PortByNameSelect))
111+
if const.dfType equals DFBit =>
107112
(dcl, const)
108113
case _ => break(None)
109114
val value = const.data.asInstanceOf[Option[Boolean]].get
@@ -116,8 +121,8 @@ object RstActive:
116121
val relVal = func.args.head.get
117122
Some(relVal, RstCfg.Active.Low)
118123
case _ => None
119-
case dcl: DFVal.Dcl => Some(dcl, RstCfg.Active.High)
120-
case _ => None
124+
case dcl: (DFVal.Dcl | DFVal.PortByNameSelect) => Some(dcl, RstCfg.Active.High)
125+
case _ => None
121126
end RstActive
122127

123128
//not only `DFVal.Const` but all non-anonymous values that
@@ -210,19 +215,22 @@ extension (dfVal: DFVal)
210215
dfVal.originMembers.view
211216
.collect { case dfVal: DFVal => dfVal }
212217
.exists(dfVal => cond(dfVal) || dfVal.existsInComposedReadDeps(cond))
213-
def getReadDeps(using MemberGetSet): Set[DFNet | DFVal | DFConditional.Block] =
214-
val fromRefs: Set[DFNet | DFVal | DFConditional.Block] = dfVal.originMembersNoTypeRef.flatMap {
215-
case net: DFNet =>
216-
net match
217-
// ignoring receiver or if connecting to an OPEN
218-
case DFNet.Connection(toVal: DFVal, _, _) if toVal.isOpen || toVal == dfVal => None
219-
// ignoring receiver
220-
case DFNet.Assignment(toVal, _) if toVal == dfVal => None
221-
case _ => Some(net)
222-
case dfVal: DFVal => Some(dfVal)
223-
case guardBlock: DFConditional.Block if guardBlock.guardRef.get == dfVal => Some(guardBlock)
224-
case _ => None
225-
}
218+
def getReadDeps(using MemberGetSet): Set[TextOut | DFNet | DFVal | DFConditional.Block] =
219+
val fromRefs: Set[TextOut | DFNet | DFVal | DFConditional.Block] =
220+
dfVal.originMembersNoTypeRef.flatMap {
221+
case net: DFNet =>
222+
net match
223+
// ignoring receiver or if connecting to an OPEN
224+
case DFNet.Connection(toVal = toVal: DFVal) if toVal.isOpen || toVal == dfVal =>
225+
None
226+
// ignoring receiver
227+
case DFNet.Assignment(toVal = toVal) if toVal == dfVal => None
228+
case _ => Some(net)
229+
case dfVal: DFVal => Some(dfVal)
230+
case guardBlock: DFConditional.Block if guardBlock.guardRef.get == dfVal => Some(guardBlock)
231+
case textOut: TextOut => Some(textOut)
232+
case _ => None
233+
}
226234
dfVal match
227235
// for ports we need to also account for by-name referencing
228236
case port @ DclPort() =>
@@ -280,10 +288,10 @@ extension (dfVal: DFVal)
280288
case r: TypeRef =>
281289
// looking for what kind of type reference it is
282290
r.originMember.asInstanceOf[DFVal].dfType match
283-
case DFVector(_, (cellDimRef: TypeRef) :: _) if cellDimRef == r => Some("length")
284-
case DFBits(widthRef: TypeRef) if widthRef == r => Some("width")
285-
case DFDecimal(_, widthRef: TypeRef, _, _) if widthRef == r => Some("width")
286-
case _ => None
291+
case DFVector(_, (cellDimRef: TypeRef) :: _) if cellDimRef == r => Some("length")
292+
case DFBits(widthRef: TypeRef) if widthRef == r => Some("width")
293+
case DFDecimal(widthParamRef = widthRef: TypeRef) if widthRef == r => Some("width")
294+
case _ => None
287295
case _ => None
288296
}.headOption
289297
else None
@@ -324,9 +332,9 @@ extension (dfVal: DFVal)
324332
end refOwner
325333
refOwner match
326334
// name from assignment destination
327-
case Some(DFNet.Assignment(toVal, _)) => Some(partName(member, toVal))
335+
case Some(DFNet.Assignment(toVal = toVal)) => Some(partName(member, toVal))
328336
// name from connection destination
329-
case Some(DFNet.Connection(toVal: DFVal, _, _)) => Some(partName(member, toVal))
337+
case Some(DFNet.Connection(toVal = toVal: DFVal)) => Some(partName(member, toVal))
330338
// name from a named value which was referenced by an alias
331339
case Some(value: DFVal) if !value.isAnonymous => Some(partName(member, value))
332340
// found an (anonymous) value -> checking suggestion for it
@@ -342,22 +350,6 @@ extension (dfVal: DFVal)
342350
.replace('.', '_')
343351
)
344352
case _ => suggestName(dfVal)
345-
def isBubble(using MemberGetSet): Boolean =
346-
dfVal match
347-
case c: DFVal.Const => c.dfType.isDataBubble(c.data.asInstanceOf[c.dfType.Data])
348-
case f: DFVal.Func => f.args.exists(_.get.isBubble)
349-
case a: DFVal.Alias.ApplyIdx => a.relValRef.get.isBubble || a.relIdx.get.isBubble
350-
case a: DFVal.Alias.Partial => a.relValRef.get.isBubble
351-
case _ => false
352-
def isDFDomain(using MemberGetSet): Boolean = dfVal.getDomainType match
353-
case DomainType.DF => true
354-
case _ => false
355-
def isRTDomain(using MemberGetSet): Boolean = dfVal.getDomainType match
356-
case DomainType.RT(_) => true
357-
case _ => false
358-
def isEDDomain(using MemberGetSet): Boolean = dfVal.getDomainType match
359-
case DomainType.ED => true
360-
case _ => false
361353
// true if this is a variable that is never assigned/connected to
362354
def isConstVAR(using MemberGetSet): Boolean =
363355
dfVal match
@@ -376,16 +368,6 @@ extension (dfVal: DFVal)
376368

377369
end extension
378370

379-
extension (dcl: DFVal.Dcl)
380-
def hasNonBubbleInit(using MemberGetSet): Boolean = dcl.initRefList match
381-
case DFRef(dfVal) :: _ => !dfVal.isBubble
382-
case _ => false
383-
384-
extension (dcl: DFVal.Alias.History)
385-
def hasNonBubbleInit(using MemberGetSet): Boolean = dcl.initRefOption match
386-
case Some(DFRef(dfVal)) => !dfVal.isBubble
387-
case _ => false
388-
389371
extension (refTW: DFNet.Ref)
390372
def isViaRef(using MemberGetSet): Boolean =
391373
refTW.originMember match
@@ -413,14 +395,35 @@ extension (net: DFNet)
413395
@targetName("collectRelMembersDFNet")
414396
def collectRelMembers(using MemberGetSet): List[DFVal] =
415397
net match
416-
case DFNet(DFRef(lhs: DFVal), _, DFRef(rhs: DFVal), _, _, _) =>
398+
case DFNet(lhsRef = DFRef(lhs: DFVal), rhsRef = DFRef(rhs: DFVal)) =>
417399
lhs.collectRelMembers(false) ++ rhs.collectRelMembers(false)
418400
case _ => Nil
419401

402+
extension (textOut: TextOut)
403+
@targetName("collectRelMembersTextOut")
404+
def collectRelMembers(using MemberGetSet): List[DFVal] =
405+
textOut.getRefs.view
406+
.collect { case DFRef(dfVal: DFVal) => dfVal }
407+
.flatMap(_.collectRelMembers(false)).toList
408+
420409
extension (member: DFMember)
421410
def isPublicMember(using MemberGetSet): Boolean =
422411
member match
423412
case DclPort() => true
424413
case _: DFVal.DesignParam => true
425414
case _: DomainBlock => true
426415
case _ => false
416+
end extension
417+
418+
extension (member: DFMember)
419+
def consumesCycles(using MemberGetSet): Boolean =
420+
member match
421+
case loop: DFLoop.Block =>
422+
loop.isInRTDomain && !loop.isCombinational
423+
case wait: Wait => wait.isInRTDomain
424+
case _: StepBlock => true
425+
case _: Goto => true
426+
case cb: DFConditional.Block =>
427+
cb.members(MemberView.Folded).exists(_.consumesCycles)
428+
case _ => false
429+
end extension

0 commit comments

Comments
 (0)