Tcl · Module 21
Writing the Netlist
Writing the netlist is one command. Recording what produced it is the part that decides whether anybody can trust the file in six months.
Advanced15 min readtcledapart-iisynthesisnetlistprovenancehandoff
Part II · Module 21 · Chapter 21.9 · Writing the Netlist
The last phase hands the result to whatever comes next. The write is one command. Everything worth saying about this phase is about what goes beside it.
1. The write
write_verilog [file join $RUN netlist ${TOP}_mapped.v] ;# a tool command=== writing the netlist, and the provenance record beside it ===
netlist: cpu_top_mapped.v (34 bytes)Two details worth getting right:
The name comes from $TOP. Chapter 21.3 §6 made the top a variable precisely so the netlist cannot be named after a different design than the one elaborated.
It goes in the run directory, beside the reports — Chapter 21.8 §6. The netlist and the evidence for it belong together.
2. Check it landed
Same discipline as the reports:
set nl [file join $RUN netlist ${TOP}_mapped.v]
write_verilog $nl
if {![file isfile $nl] || [file size $nl] == 0} {
error "netlist was not written: $nl" {} [list NETLIST EMPTY $nl]
}
puts " netlist: [file tail $nl] ([file size $nl] bytes)"A zero-byte netlist is the same hazard as Chapter 21.8 §3's zero-byte report, and more consequential: the next stage reads it, finds nothing, and reports an empty design.
3. The question six months later
Somebody finds this netlist and asks: what produced it?
Which sources, at which revision. Which libraries, at which corner. Which constraints. Which compile options. Which tool version.
Without a record, the honest answer is "probably the script in the repository, as it was then" — which is a guess. With one, it is a file.
4. The provenance record
proc write_provenance {path args} {
set fp [open $path w]
puts $fp "# what produced the netlist in this directory"
foreach {k v} $args { puts $fp [format "%-14s %s" $k $v] }
close $fp
return $path
}
write_provenance [file join $RUN netlist PROVENANCE.txt] \
top cpu_top \
sources [join $names {,}] \
source_count [llength $files] \
tcl_version [info patchlevel] \
script [file tail [info script]] PROVENANCE.txt:
# what produced the netlist in this directory
top cpu_top
sources alu.v,cpu_top.v,fifo.v
source_count 3
tcl_version 8.5.9
script netlist.tclTwelve lines of ordinary Tcl — args as key-value pairs (Chapter 10.4), format to align, info patchlevel and info script from Chapter 14.10.
A real record should also carry:
- The libraries and the corner — Chapter 21.4 §5. Without these the timing numbers cannot be interpreted at all.
- The constraint files sourced — Chapter 21.6 §6.
- The compile options and runtime — Chapter 21.7 §4.
- The tool name and version, not just Tcl's.
- The source revision, if the sources are under version control.
- The summary numbers — worst slack, area — so the file says what it achieved as well as how it was made.
5. Make it machine-readable
The name value per line format is deliberate — Chapter 16.3 §5. It is readable by a person and parseable in two lines:
proc read_provenance {path} {
set d [dict create]
set fp [open $path r]
while {[gets $fp line] >= 0} {
set line [string trim $line]
if {$line eq "" || [string index $line 0] eq "#"} { continue }
dict set d [lindex $line 0] [lrange $line 1 end]
}
close $fp
return $d
}Which makes the interesting question cheap: what differs between this run and the last one? Two provenance files and a dict comparison, outside the tool, with no licence — and the answer to "why did these two runs disagree" is usually in that diff.
6. The handoff
A netlist handed to the next stage should arrive with:
- the netlist itself,
- the constraints that produced it, or the post-synthesis constraints,
- the reports, so the receiver can see what was achieved,
- the provenance, so they can tell what it was built from,
- and an exit status from the run that says it is complete — Chapter 21.10.
The last is the one that is usually missing, and it is the one that matters most: a netlist produced by a run that exited non-zero should not be used, and nothing in the file itself says so.
7. Exercises
Exercise 1. Why should the netlist filename be built from $TOP?
Exercise 2. Why check the netlist size after writing it?
Exercise 3. What question does a provenance record answer?
Exercise 4. Name four things a real provenance record should contain beyond the sources.
Exercise 5. Why keep it beside the netlist rather than in a tracking system?
Exercise 6. Why use name value per line rather than prose?
Exercise 7. What should accompany a netlist handed to the next stage?
Where this fits
Part of the Tcl curriculum.
