Skip to content

Commit 7f27d14

Browse files
author
Oron Port
committed
fix vhdl process to verilog process conversion to consider internal design ports
1 parent 3453fe3 commit 7f27d14

File tree

3 files changed

+105
-14
lines changed

3 files changed

+105
-14
lines changed

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

Lines changed: 9 additions & 4 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

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

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import DFConditional.{DFIfElseBlock, DFIfHeader}
88
import DFVal.Func.Op as FuncOp
99
import ProcessBlock.Sensitivity
1010
import dfhdl.core.DomainType.ED
11+
import dfhdl.compiler.ir.DFVal.PortByNameSelect
1112

1213
/** This stage transforms a sequential process from a VHDL style to Verilog style. E.g.,
1314
* {{{
@@ -30,30 +31,39 @@ case object VHDLProcToVerilog extends Stage:
3031
def transform(designDB: DB)(using MemberGetSet, CompilerOptions): DB =
3132
val patchList: List[(DFMember, Patch)] = designDB.members.flatMap {
3233
case pb @ ProcessBlock(sensitivity = Sensitivity.List(stRefs)) =>
33-
val stVals = stRefs.view.map(_.get).toSet
34+
def getStVals = stRefs.view.map(_.get)
35+
val stValsStripped = getStVals.map(_.stripPortSel).toSet
3436
pb
3537
.members(MemberView.Folded)
3638
.collect { case ifBlock: DFIfElseBlock => ifBlock } match
37-
case ifBlock :: Nil if stVals.size == 1 =>
39+
case ifBlock :: Nil if stValsStripped.size == 1 =>
3840
ifBlock.guardRef.get match
39-
case clkEdge @ ClkEdge(clk, edge) if stVals.contains(clk) =>
41+
case clkEdge @ ClkEdge(clkns @ StrippedPortByNameSelect(clk), edge)
42+
if stValsStripped.contains(clk) =>
4043
val dsn = new MetaDesign(pb, Patch.Add.Config.ReplaceWithLast(), domainType = ED):
4144
val clkEdgeSig = edge match
4245
case ClkCfg.Edge.Rising => clk.asValOf[Bit].rising
4346
case ClkCfg.Edge.Falling => clk.asValOf[Bit].falling
4447
val newPB =
4548
dfhdl.core.Process.Block.list(List(clkEdgeSig))(using dfc.setMeta(pb.meta)).asIR
46-
List(
49+
val pbnsRemoveList = (clkns :: getStVals.toList).collect {
50+
case pbns: PortByNameSelect =>
51+
pbns -> Patch.Remove()
52+
}
53+
pbnsRemoveList ++ List(
4754
clkEdge -> Patch.Remove(),
4855
ifBlock.prevBlockOrHeaderRef.get -> Patch.Remove(),
4956
dsn.patch,
5057
ifBlock -> Patch.Replace(dsn.newPB, Patch.Replace.Config.ChangeRefAndRemove)
5158
)
52-
case _ => None
53-
case ifBlock :: elseBlock :: Nil if stVals.size == 2 && elseBlock.getFirstCB == ifBlock =>
59+
case _ => Nil
60+
case ifBlock :: elseBlock :: Nil
61+
if stValsStripped.size == 2 && elseBlock.getFirstCB == ifBlock =>
5462
(ifBlock.guardRef.get, elseBlock.guardRef.get) match
55-
case (rstActive @ RstActive(rst, active), clkEdge @ ClkEdge(clk, edge))
56-
if stVals == Set(clk, rst) =>
63+
case (
64+
rstActive @ RstActive(StrippedPortByNameSelect(rst), active),
65+
clkEdge @ ClkEdge(clkns @ StrippedPortByNameSelect(clk), edge)
66+
) if stValsStripped == Set(clk, rst) =>
5767
val dsn = new MetaDesign(pb, Patch.Add.Config.ReplaceWithLast(), domainType = ED):
5868
val clkEdgeSig = edge match
5969
case ClkCfg.Edge.Rising => clk.asValOf[Bit].rising
@@ -65,11 +75,15 @@ case object VHDLProcToVerilog extends Stage:
6575
dfhdl.core.Process.Block.list(List(clkEdgeSig, rstEdgeSig))(using
6676
dfc.setMeta(pb.meta)
6777
).asIR
68-
List(
78+
val pbnsRemoveList = (clkns :: getStVals.toList).collect {
79+
case pbns: PortByNameSelect =>
80+
pbns -> Patch.Remove()
81+
}
82+
pbnsRemoveList ++ List(
6983
clkEdge -> Patch.Replace(DFMember.Empty, Patch.Replace.Config.ChangeRefAndRemove),
7084
dsn.patch
7185
)
72-
case _ => None
86+
case _ => Nil
7387
case _ => None
7488
end match
7589
case _ => None

compiler/stages/src/test/scala/StagesSpec/VHDLProcToVerilogSpec.scala

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,4 +98,76 @@ class VHDLProcToVerilogSpec extends StageSpec:
9898
|""".stripMargin
9999
)
100100
}
101+
test("internal clk/rst ports") {
102+
class ClkGen extends EDDesign:
103+
val clk = Bit <> OUT
104+
clk <> 1
105+
class ClkRstGen extends EDDesign:
106+
val clk = Bit <> OUT
107+
val rst = Bit <> OUT
108+
clk <> 1
109+
rst <> 0
110+
111+
class Foo extends EDDesign:
112+
val y = Bit <> IN
113+
val z = Bit <> OUT
114+
val z2 = Bit <> OUT
115+
val z3 = Bit <> OUT
116+
val clkGen = ClkGen()
117+
val clkRstGen = ClkRstGen()
118+
process(clkGen.clk):
119+
if (clkGen.clk.rising) println(y)
120+
process(clkRstGen.clk, clkRstGen.rst):
121+
if (clkRstGen.rst)
122+
z := 0
123+
else if (clkRstGen.clk.rising)
124+
z := 1
125+
process(clkRstGen.clk, clkRstGen.rst):
126+
if (clkRstGen.rst == 0)
127+
z2 := 0
128+
else if (clkRstGen.clk.falling)
129+
z2 := 1
130+
process(clkRstGen.clk, clkRstGen.rst):
131+
if (!clkRstGen.rst)
132+
z3 := 0
133+
else if (clkRstGen.clk.falling)
134+
z3 := 1
135+
end Foo
136+
val top = (new Foo).vhdlProcToVerilog
137+
assertCodeString(
138+
top,
139+
"""|class ClkGen extends EDDesign:
140+
| val clk = Bit <> OUT
141+
| clk <> 1
142+
|end ClkGen
143+
|
144+
|class ClkRstGen extends EDDesign:
145+
| val clk = Bit <> OUT
146+
| val rst = Bit <> OUT
147+
| clk <> 1
148+
| rst <> 0
149+
|end ClkRstGen
150+
|
151+
|class Foo extends EDDesign:
152+
| val y = Bit <> IN
153+
| val z = Bit <> OUT
154+
| val z2 = Bit <> OUT
155+
| val z3 = Bit <> OUT
156+
| val clkGen = ClkGen()
157+
| val clkRstGen = ClkRstGen()
158+
| process(clkGen.clk.rising):
159+
| println(s"${y}")
160+
| process(clkRstGen.clk.rising, clkRstGen.rst.rising):
161+
| if (clkRstGen.rst) z := 0
162+
| else z := 1
163+
| process(clkRstGen.clk.falling, clkRstGen.rst.falling):
164+
| if (clkRstGen.rst == 0) z2 := 0
165+
| else z2 := 1
166+
| process(clkRstGen.clk.falling, clkRstGen.rst.falling):
167+
| if (!clkRstGen.rst) z3 := 0
168+
| else z3 := 1
169+
|end Foo
170+
|""".stripMargin
171+
)
172+
}
101173
end VHDLProcToVerilogSpec

0 commit comments

Comments
 (0)