Skip to content

Commit 449bfb6

Browse files
authored
Merge pull request #7 from rameloni/tywaves-submodules-support
Tywaves submodules support
2 parents 52a3d68 + 9033ec2 commit 449bfb6

File tree

16 files changed

+471
-43
lines changed

16 files changed

+471
-43
lines changed

build.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
val chiselVersion = "6.1.0-tywaves-SNAPSHOT"
1+
val chiselVersion = "6.1.0-tywaves-SNAPSHOT" // Local version of chisel
22
val scalatestVersion = "3.2.16"
33
val circeVersion = "0.14.6"
44

src/main/scala/chisel3/tywaves/circuitparser/ChiselIRParser.scala

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class ChiselIRParser
6565

6666
// Parse generic info and create an ID for the port
6767
val (name, info, dir) = (portData.toNamed.name, port.sourceInfo, port.dir)
68-
val elId = this.createId(info, Some(name))
68+
val elId = this.createId(info, Some(name + scope))
6969

7070
ports.put(
7171
elId,
@@ -161,8 +161,8 @@ class ChiselIRParser
161161
case _ =>
162162
// TODO: other cases need to be implemented. For now, simply add the element to the map
163163
if (hwType == HardwareType("Port", Some(dataType.getWidth)))
164-
flattenedPorts.put(elId.addName(name.name), (name, dir, hwType, Type(dataType.typeName)))
165-
allElements.put(elId.addName(name.name), (name, dir, Type(dataType.typeName)))
164+
flattenedPorts.put(elId.addName(name.name + parentModule), (name, dir, hwType, Type(dataType.typeName)))
165+
allElements.put(elId.addName(name.name + parentModule), (name, dir, Type(dataType.typeName)))
166166
case _ => throw new Exception(s"Failed to parse type $dataType. Unknown type.")
167167
}
168168
// ??? // TODO: Implement for Data types
@@ -184,6 +184,13 @@ class ChiselIRParser
184184
case _: chiselIR.Printf => logger.debug("ChiselIRParser: Parsing Printf. Skip."); None
185185
case _: chiselIR.AltBegin => logger.debug("ChiselIRParser: Parsing AltBegin. Skip."); None
186186
case _: chiselIR.OtherwiseEnd => logger.debug("ChiselIRParser: Parsing OtherwiseEnd. Skip."); None
187+
case chiselIR.DefInstance(sourceInfo, module, _ports) => {
188+
val elId = this.createId(sourceInfo, Some(module.name))
189+
// _ports.foreach(parsePort(module.name, _, module.name))
190+
modules.put(elId, (Name(module.name, scope, parentModule), null)) // Add the module and its name
191+
logger.error(s"DefInstance not implemented: $module. Skip.")
192+
None
193+
}
187194
case a =>
188195
logger.error(s"Match case not covered: $a")
189196
None

src/main/scala/chisel3/tywaves/circuitparser/CircuitParser.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,14 @@ trait CircuitParser[T, ModuleT, PortT, AggregateT, ElementT, BodyStatementT] {
5252
case chisel: chisel3.Record => chisel.className
5353
case aggr: chisel3.Aggregate => aggr.typeName
5454
}
55-
if (hwType == HardwareType("Port", Some(this.getWidth(agg))))
55+
if (hwType == HardwareType("Port", Some(this.getWidth(agg)))) {
5656
flattenedPorts.put(
57-
elId.addName(name.name),
57+
elId.addName(name.name + parentModule),
5858
(name.addTywaveScope(parentModule), dir, hwType, Type(aggString)),
5959
)
60+
}
6061

61-
allElements.put(elId.addName(name.name), (name.addTywaveScope(parentModule), dir, Type(aggString)))
62+
allElements.put(elId.addName(name.name + parentModule), (name.addTywaveScope(parentModule), dir, Type(aggString)))
6263
}
6364

6465
def parseElement(

src/main/scala/chisel3/tywaves/circuitparser/FirrtlIRParser.scala

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class FirrtlIRParser
3131
override def parseModule(firrtlModule: firrtlIR.DefModule): Unit = {
3232
// Parse generic info and create an ID for the module
3333
val (name, info) = (firrtlModule.name, firrtlModule.info)
34-
val elId = this.createId(info)
34+
val elId = this.createId(info, Some(name))
3535

3636
modules.put(elId, (Name(name, "root", "root"), firrtlModule)) // Add the module and its name
3737

@@ -52,7 +52,7 @@ class FirrtlIRParser
5252
override def parsePort(scope: String, port: firrtlIR.Port, parentModule: String): Unit = {
5353
// Parse generic info and create an ID for the port
5454
val (name, info, dir, firrtlType) = (port.name, port.info, port.direction, port.tpe)
55-
val elId = this.createId(info, Some(name))
55+
val elId = this.createId(info, Some(name + scope))
5656

5757
ports.put(
5858
elId,
@@ -133,8 +133,8 @@ class FirrtlIRParser
133133
case ClockType | AsyncResetType | ResetType |
134134
UIntType(_) | SIntType(_) | AnalogType(_) =>
135135
if (hwType == HardwareType("Port", None))
136-
flattenedPorts.put(elId.addName(name.name), (name, dir, hwType, Type(firrtlType.toString)))
137-
allElements.put(elId.addName(name.name), (name, dir, Type(firrtlType.toString)))
136+
flattenedPorts.put(elId.addName(name.name + parentModule), (name, dir, hwType, Type(firrtlType.toString)))
137+
allElements.put(elId.addName(name.name + parentModule), (name, dir, Type(firrtlType.toString)))
138138
case _ => throw new Exception(s"Failed to parse type $firrtlType. Unknown type.")
139139
}
140140
}
@@ -175,7 +175,9 @@ class FirrtlIRParser
175175
tpe,
176176
parentModule,
177177
)
178-
178+
case DefInstance(info, name, module, tpe) => {
179+
logger.error(s"DefInstance: name: $name, module: $module, tpe: $tpe. Skip.")
180+
}
179181
case _: Connect => logger.debug("FirrtlIR parser: Parsing Connect. Skip.")
180182
case _: DefNode => logger.debug("FirrtlIR parser: Parsing DefNode. Skip.")
181183
case _: Conditionally => logger.debug("FirrtlIR parser: Parsing Conditionally. Skip.")

src/main/scala/tywaves/circuitmapper/MapChiselToVcd.scala

Lines changed: 86 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,16 @@ class MapChiselToVcd[T <: RawModule](generateModule: () => T, private val workin
5252
chiselIRParser.parseCircuit(circuitChiselIR)
5353

5454
// Step 4. Parse the debug information
55-
private val gDebugIRParser = new DebugIRParser(workingDir, TypedConverter.getDebugIRFile(gOpt = true))
55+
private val topModuleName = circuitChiselIR.name
56+
private val gDebugIRParser = new DebugIRParser(workingDir, TypedConverter.getDebugIRFile(gOpt = true, topModuleName))
57+
logger.error(s"HGDD file used: ${TypedConverter.getDebugIRFile(gOpt = true, topModuleName)}")
5658
// val debugIRParser =
5759
// new DebugIRParser(workingDir, TypedConverter.getDebugIRFile(gOpt = false)) // TODO: check if this is needed or not
5860

5961
gDebugIRParser.parse()
6062
// debugIRParser.parse()
63+
mapCircuits()
64+
dumpLog()
6165

6266
/** Print debug information */
6367
def printDebug(): Unit = {
@@ -187,21 +191,25 @@ class MapChiselToVcd[T <: RawModule](generateModule: () => T, private val workin
187191

188192
// Each element is associated to the 3 IRs
189193
// The goal here is to create a Tywavestate
190-
val (childVariables, childScopes) = groupIrPerElement.flatMap {
194+
val (childVariables, _) = groupIrPerElement.flatMap {
191195
case (elId, irs) =>
192196
logger.info(s"Element: $elId")
193197
// Iterate over the IRs
194198
irs.flatMap {
195199
case (ir, Some(value)) =>
196-
Some((findChildVariable(elId, value, ir), findChildScopes(value)))
200+
Some((
201+
findChildVariable(elId, value, ir, circuitChiselIR.name),
202+
Seq.empty,
203+
))
197204
case (ir, None) =>
198205
logger.debug(s"IR without match: $ir", None)
199206
None
200207
}.filter { case (variableOpt, _) => variableOpt.isDefined }
201208
.map { case (variableOpt, scopes) => (variableOpt.get, scopes) }
202-
}.unzip
203209

204-
val scopes = Seq(tywaves_symbol_table.Scope(name = dutName, childVariables.toSeq, childScopes.flatten.toSeq))
210+
}.unzip
211+
val childScopes = findChildScopes(circuitChiselIR.name, groupIrPerElement)
212+
val scopes = Seq(tywaves_symbol_table.Scope(name = dutName, childVariables.toSeq, childScopes))
205213
// Finalize the scopes -> mergeScopes(scope) is not needed anymore
206214
val finalScopes = cleanFromFlattenedSignals(scopes)
207215

@@ -294,16 +302,23 @@ class MapChiselToVcd[T <: RawModule](generateModule: () => T, private val workin
294302
}
295303

296304
/** Find the child variables of a given tuple for a given representation */
297-
private def findChildVariable[Tuple](elId: ElId, tuple: Tuple, ir: String): Option[tywaves_symbol_table.Variable] =
305+
private def findChildVariable[Tuple](
306+
elId: ElId,
307+
tuple: Tuple,
308+
ir: String,
309+
moduleScope: String,
310+
): Option[tywaves_symbol_table.Variable] =
298311
if (ir == "debugIR")
299312
tuple match {
300313
case (
301-
Name(name, scope, _),
314+
Name(name, scope, tywaveScope),
302315
Direction(dir),
303316
HardwareType(hardwareType, size),
304317
Type(_),
305318
VerilogSignals(verilogSignals),
306319
) =>
320+
if (moduleScope != tywaveScope)
321+
return None
307322
// Get the list of children of this variable
308323
val listChildren = gDebugIRParser.signals.filter {
309324
case (_: ElId, (Name(_, childScope, _), Direction(_), HardwareType(_, _), Type(_), VerilogSignals(_))) =>
@@ -319,7 +334,7 @@ class MapChiselToVcd[T <: RawModule](generateModule: () => T, private val workin
319334
// TODO: Understand how to handle other types
320335
tywaves_symbol_table.realtype.Bundle(
321336
fields = listChildren.flatMap { child =>
322-
findChildVariable(child._1, child._2, ir)
337+
findChildVariable(child._1, child._2, ir, moduleScope)
323338
}.toSeq,
324339
vcdName = Some(name),
325340
)
@@ -342,7 +357,67 @@ class MapChiselToVcd[T <: RawModule](generateModule: () => T, private val workin
342357
None
343358
}
344359

345-
private def findChildScopes[Tuple](value: Tuple): Seq[tywaves_symbol_table.Scope] =
346-
// TODO: implement it to support submodules
347-
Seq.empty
360+
private def findChildScopes(
361+
parentScope: String,
362+
groupIrPerElement: Map[ElId, Seq[(String, Option[?])]],
363+
): Seq[tywaves_symbol_table.Scope] = {
364+
365+
var childScopes: Seq[tywaves_symbol_table.Scope] = Seq.empty
366+
367+
println(s"findChildScopes of: $parentScope")
368+
gDebugIRParser.modules.foreach(println(_))
369+
370+
val childScopeNames = gDebugIRParser.modules.filter {
371+
case (_, Name(_, _, tywaveScope)) =>
372+
tywaveScope == parentScope
373+
}.map { case (_, Name(name, scope, _)) => (name, scope) }.toSet
374+
375+
childScopeNames.foreach(println)
376+
377+
childScopeNames.foreach { x =>
378+
val (childScopeName, instanceName) = x
379+
val (childVariables, _) = groupIrPerElement.flatMap {
380+
case (elId, irs) =>
381+
logger.info(s"Element: $elId")
382+
// Iterate over the IRs
383+
irs.flatMap {
384+
case (ir, Some(value)) =>
385+
Some((
386+
findChildVariable(elId, value, ir, childScopeName),
387+
Seq.empty,
388+
))
389+
case (ir, None) =>
390+
logger.debug(s"IR without match: $ir", None)
391+
None
392+
}.filter { case (variableOpt, _) => variableOpt.isDefined }
393+
.map { case (variableOpt, scopes) => (variableOpt.get, scopes) }
394+
395+
}.unzip
396+
childScopes :+= tywaves_symbol_table.Scope(
397+
instanceName,
398+
childVariables.toSeq,
399+
findChildScopes(childScopeName, groupIrPerElement),
400+
)
401+
}
402+
childScopes
403+
// val (childVariables, childScopes) = groupIrPerElement.flatMap {
404+
// case (elId, irs) =>
405+
// logger.info(s"Element: $elId")
406+
// // Iterate over the IRs
407+
// irs.flatMap {
408+
// case (ir, Some(value)) =>
409+
// Some((findChildVariable(elId, value, ir, childScope), findChildScopes(circuitChiselIR.name)))
410+
// case (ir, None) =>
411+
// logger.debug(s"IR without match: $ir", None)
412+
// None
413+
// }.filter { case (variableOpt, _) => variableOpt.isDefined }
414+
// .map { case (variableOpt, scopes) => (variableOpt.get, scopes) }
415+
//
416+
// }.unzip
417+
// Find all the child scopes of this scope
418+
419+
// Check if the scope is
420+
// Seq.empty
421+
}
422+
// TODO: implement it to support submodules
348423
}

src/main/scala/tywaves/circuitmapper/TypedConverter.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,19 +50,19 @@ private object TypedConverter {
5050

5151
chiselStage.execute(
5252
args ++ Array("--target-dir", hglddDebugDir),
53-
annotations ++ Seq(circt.stage.FirtoolOption("-g")),
53+
annotations ++ Seq(circt.stage.FirtoolOption("-g"), circt.stage.FirtoolOption("-O=debug")),
5454
// execute returns the passThrough annotations in CIRCT transform stage
5555
)
5656
}
5757

5858
/** Get the name of the debug file */
59-
def getDebugIRFile(gOpt: Boolean): String = {
59+
def getDebugIRFile(gOpt: Boolean, topModuleName: String): String = {
6060

6161
def getFile(_workingDir: String): String = {
6262
val workingDir = new java.io.File(_workingDir)
6363
// Open the HGLDD file and extract the information
6464
if (workingDir.exists() && workingDir.isDirectory) {
65-
workingDir.listFiles().filter(_.getName.endsWith(debugFileExt)).head.getAbsolutePath
65+
workingDir.listFiles().filter(_.getName == topModuleName + debugFileExt).head.getAbsolutePath
6666
} else
6767
throw new Exception(s"WorkingDir: $workingDir does not exist or is not a directory.")
6868
}
@@ -81,6 +81,6 @@ object GenerateHgldd {
8181
def apply[T <: RawModule](generateModule: () => T, workingDir: String = "workingDir"): String = {
8282
val mapChiselToVcd = new MapChiselToVcd(generateModule, workingDir)("TOP", "TbName", "DutName")
8383
mapChiselToVcd.dumpLog()
84-
TypedConverter.getDebugIRFile(gOpt = true)
84+
TypedConverter.getDebugIRFile(gOpt = true, generateModule.toString())
8585
}
8686
}

src/main/scala/tywaves/hglddparser/DebugIRParser.scala

Lines changed: 72 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,30 +90,96 @@ class DebugIRParser(val workingDir: String, ddFilePath: String) {
9090
}
9191

9292
/** Parse an object from the HGLDD representation */
93-
private def parseObject(fileInfo: Seq[String], hglddObject: HglddObject): Unit = {
93+
private def parseObject(
94+
fileInfo: Seq[String],
95+
hglddObject: HglddObject,
96+
thisChildParentName: Option[String] = None,
97+
thisChildName: Option[String] = None,
98+
): Unit = {
9499

95100
val scope =
96-
hglddObject.obj_name.lastIndexOf("_") match { case -1 => "root"; case i => hglddObject.obj_name.substring(0, i) }
101+
hglddObject.obj_name.lastIndexOf("_") match {
102+
case -1 => thisChildName.getOrElse("root")
103+
case i =>
104+
// TODO: here the problem, multiple instances are separated by _ + an index
105+
val lastPart = hglddObject.obj_name.substring(i + 1)
106+
107+
val tmpScope = hglddObject.obj_name.substring(0, i)
108+
109+
if (lastPart.forall(Character.isDigit)) {
110+
println("FOUND: " + hglddObject.obj_name)
111+
thisChildName.getOrElse("root")
112+
} else {
113+
println("NOT FOUND: " + s"tmpScope: $tmpScope" + s" hglddObject.obj_name ${hglddObject.obj_name}")
114+
tmpScope
115+
}
116+
117+
}
97118
// Drop the scope from the object name
98119
val obj_name =
99-
scope match { case "root" => hglddObject.obj_name; case _ => hglddObject.obj_name.substring(scope.length + 1) }
120+
if (scope == thisChildName.getOrElse("root"))
121+
hglddObject.obj_name
122+
else
123+
hglddObject.obj_name.substring(scope.length + 1)
124+
100125
val elId =
101-
createId(fileInfo, hglddObject.hgl_loc, obj_name)
126+
createId(fileInfo, hglddObject.hgl_loc, obj_name + scope)
102127
val parentModule =
103-
hglddObject.obj_name.lastIndexOf("_") match { case -1 => "root"; case i => hglddObject.obj_name.substring(0, i) }
128+
hglddObject.obj_name.lastIndexOf("_") match {
129+
case -1 => thisChildParentName.getOrElse("root");
130+
case i =>
131+
// TODO: here the problem, multiple instances are separated by _ + an index
132+
val lastPart = hglddObject.obj_name.substring(i + 1)
133+
134+
val tmpScope = hglddObject.obj_name.substring(0, i)
135+
136+
if (lastPart.forall(Character.isDigit)) {
137+
println("FOUND: " + hglddObject.obj_name)
138+
thisChildParentName.getOrElse("root")
139+
} else {
140+
println("NOT FOUND: " + s"tmpScope: $tmpScope" + s" hglddObject.obj_name ${hglddObject.obj_name}")
141+
tmpScope
142+
}
143+
}
104144
// Parse the kind of the object
105145
hglddObject.kind match {
106146
case s @ "struct" =>
107147
allElements.put(elId, (Name(obj_name, scope, parentModule), Direction("Unknown"), Type(s)))
108148
hglddObject.port_vars.foreach(parsePortVarFromModule(fileInfo, _, hglddObject.obj_name, parentModule))
109149
case "module" =>
150+
println("Module: " + hglddObject.obj_name + " " + scope + " " + parentModule + " " + elId)
110151
modules.put(elId, Name(obj_name, scope, parentModule))
111152
hglddObject.port_vars.foreach(parsePortVarFromModule(fileInfo, _, hglddObject.obj_name, hglddObject.obj_name))
112153
case a =>
113154
logger.error(s"Kind: $a not implemented")
114155
???
115156
}
116157

158+
hglddObject.children match {
159+
case Some(children) =>
160+
children.foreach(parseChild(_, hglddObject.obj_name))
161+
case None => ()
162+
}
163+
164+
}
165+
166+
def parseChild(child: Child, parentModuleName: String): Unit = {
167+
val childPath = ddFilePath.substring(0, ddFilePath.lastIndexOf("/")) + "/" + child.module_name + ".dd"
168+
val hgldd = parseFile(childPath)
169+
val (fileInfo, hdlFileActualIndex) = (hgldd.HGLDD.file_info, hgldd.HGLDD.hdl_file_index - 1)
170+
171+
hgldd.objects.foreach(
172+
parseObject(
173+
fileInfo.map(f =>
174+
f.replaceAll("\\.\\./", "")
175+
), // Use the same of the other parsers (ChiselIR and FIRRTL IR) TODO: needs better version
176+
_,
177+
thisChildParentName = Some(parentModuleName),
178+
thisChildName = Some(child.name),
179+
)
180+
)
181+
182+
// ???
117183
}
118184

119185
/**
@@ -129,7 +195,7 @@ class DebugIRParser(val workingDir: String, ddFilePath: String) {
129195
scope: String,
130196
parentModule: String,
131197
): Unit = {
132-
val elId = createId(fileInfo, portVar.hgl_loc, portVar.var_name)
198+
val elId = createId(fileInfo, portVar.hgl_loc, portVar.var_name + parentModule)
133199
val name = Name(portVar.var_name, scope, parentModule)
134200
val dir = Direction("Unknown")
135201
val typ = Type(portVar.type_name)

0 commit comments

Comments
 (0)