Skip to content

Commit 51567ef

Browse files
committed
Fix visualization to handle FIRRTL arrays and vectors
The visualize() function was generating invalid GraphViz DOT syntax when processing FIRRTL with array types like: reg zs : UInt<8>[3] products[0] <= _products_T Error was: "syntax error in line X near ']'" Root cause: Array index syntax `name[0]` contains brackets which are invalid in DOT node identifiers. Fix: Added sanitizeName() helper that: - Converts array indices to underscores: zs[0] -> zs_0 - Strips other invalid characters for DOT format - Applied to all signal names (inputs, outputs, regs, wires, connections) This allows visualization of complex circuits with vectors and arrays, such as FIR filters with coefficient arrays.
1 parent f5b2c9a commit 51567ef

File tree

1 file changed

+16
-7
lines changed

1 file changed

+16
-7
lines changed

source/load-ivy.sc

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -127,13 +127,20 @@ def visualize(gen: () => chisel3.RawModule): Unit = {
127127

128128
val firrtlString = firrtlCircuit.serialize
129129

130+
// Helper function to sanitize node names for DOT format
131+
def sanitizeName(name: String): String = {
132+
// Replace array indices with underscores and remove other invalid chars
133+
name.replaceAll("\\[([0-9]+)\\]", "_$1")
134+
.replaceAll("[^a-zA-Z0-9_]", "_")
135+
}
136+
130137
// Parse FIRRTL to extract structure
131138
val lines = firrtlString.split("\n")
132139
val moduleName = lines.find(_.trim.startsWith("module ")).map(_.trim.split(" ")(1).replace(":", "")).getOrElse("Module")
133-
val inputs = lines.filter(_.trim.startsWith("input ")).map(l => l.trim.split(" ")(1).split(":")(0))
134-
val outputs = lines.filter(_.trim.startsWith("output ")).map(l => l.trim.split(" ")(1).split(":")(0))
135-
val regs = lines.filter(_.trim.startsWith("reg ")).map(l => l.trim.split(" ")(1).split(":")(0))
136-
val wires = lines.filter(_.trim.startsWith("wire ")).map(l => l.trim.split(" ")(1).split(":")(0))
140+
val inputs = lines.filter(_.trim.startsWith("input ")).map(l => sanitizeName(l.trim.split(" ")(1).split(":")(0)))
141+
val outputs = lines.filter(_.trim.startsWith("output ")).map(l => sanitizeName(l.trim.split(" ")(1).split(":")(0)))
142+
val regs = lines.filter(_.trim.startsWith("reg ")).map(l => sanitizeName(l.trim.split(" ")(1).split(":")(0)))
143+
val wires = lines.filter(_.trim.startsWith("wire ")).map(l => sanitizeName(l.trim.split(" ")(1).split(":")(0)))
137144

138145
// Generate GraphViz DOT
139146
val dot = new StringBuilder
@@ -170,9 +177,11 @@ def visualize(gen: () => chisel3.RawModule): Unit = {
170177
lines.filter(l => l.contains("<=") && !l.trim.startsWith("reset")).foreach { line =>
171178
val parts = line.trim.split("<=").map(_.trim)
172179
if (parts.length == 2) {
173-
val target = parts(0).split("\\.")(0).split("\\(")(0)
174-
val source = parts(1).split("\\.")(0).split("\\(")(0).split(" ")(0)
175-
if (!source.startsWith("UInt") && !source.contains("\"")) {
180+
val targetRaw = parts(0).split("\\.")(0).split("\\(")(0)
181+
val sourceRaw = parts(1).split("\\.")(0).split("\\(")(0).split(" ")(0)
182+
if (!sourceRaw.startsWith("UInt") && !sourceRaw.contains("\"") && !sourceRaw.startsWith("_")) {
183+
val target = sanitizeName(targetRaw)
184+
val source = sanitizeName(sourceRaw)
176185
dot ++= s" $source -> $target;\n"
177186
}
178187
}

0 commit comments

Comments
 (0)