DMG-CPU Research
On this page
  1. Environment (Windows tools run from WSL)
  2. Icarus Verilog compile/simulate
  3. GTKWave .gtkw save-file format (the big gotcha)
  4. Waveform images
  5. Repo test benches
  6. Checking signals for z/x (floating-net debugging)
  7. DMG-CPU SoC netlists (emu-russia/dmgcpu) - extra notes

GTKWave / Icarus Verilog skill (adapted for emu-russia/dmgcpu)

Adapted and extended for this repository while bringing up the PPU regression testbench (issue #390). Keep this file updated when working on new testbenches (APU, MMIO, Arb, Ser, ...) under HDL/soc/icarus.

Origin: emu-russia/skills hdl-sim-icarus-gtkwave.md, extended with DMG-CPU SoC netlist notes (bus aliasing, tristate conventions, the oam_ram.v/lcd_stub.v models and the wave tooling used here).


Icarus Verilog + GTKWave tooling

Hard facts learned while completing the NES PPU Verilog model (emu-russia/breaks). Version-specific; verify with -V if anything changes.

Environment (Windows tools run from WSL)

CRITICAL: Windows CWD must not be a UNC path

iverilog.exe runs under cmd.exe, which rejects a UNC current directory (\\wsl.localhost\...). Symptom: CMD.EXE ... UNC paths are not supported / No such file or directory / Preprocessor failed. Fix: cd into a /mnt/c/... (drive-mapped) directory before running, or use workdir = a /mnt/c/... path. Do not compile from /tmp or a bare WSL path.

Icarus Verilog compile/simulate

cd /mnt/c/.../HDL/Framework/Icarus/ppu   # a /mnt/c path
/mnt/c/iverilog/bin/iverilog.exe -g2012 -D RP2C02 -D ICARUS -o ppu.run ../../../Common/*.v ../../../PPU/*.v ppu.v
/mnt/c/iverilog/bin/vvp.exe ppu.run      # -> ppu_ntsc.vcd

GTKWave .gtkw save-file format (the big gotcha)

Two incompatible formats exist: v3.3.100 (old) vs v3.3.128 (current). Old save files open but silently stop loading the trace list (or hang) in 3.3.128.

Element v3.3.100 (broken in 3.3.128) v3.3.128 (correct)
scalar @28 @28 (unchanged)
bus / vector @c00024, @c00022 @22 (plain color; vector-ness comes from the signal name [N:0], NOT a flag)
group header @200 @201 + -Name
group end @1401200 + -group_end omit entirely (groups just run until the next header)
header line GTKWave Analyzer v3.3.100 GTKWave Analyzer v3.3.128
marker line *-14.000000 37110 -1 ... *0.000000 -1 -1 ... (26 × -1)
footer [pattern_trace] 1 then [pattern_trace] 0

Generating a correct .gtkw

Parse the actual VCD scope tree (never guess instance names):

# parse $scope/$var/$enddefinitions; build path -> [(name, width)]
# signal name for a bus includes the [msb:lsb] suffix from the $var line
# filter auto-generated wires (^w\d+$, ^bus\d+_\d+$)
# emit: @201 + -Category  (header), @22 + path (bus), @28 + path (scalar)

Verifying a .gtkw actually loads

GTKWave Tcl (run via -S, script must live on a Windows path like C:\..., NOT /tmp):

gtkwave file.gtkw -S C:/path/check.tcl
# check.tcl:
#   gtkwave::getTotalNumTraces   -> total traces (signals + comments)
#   gtkwave::getTraceNameFromIndex $i
#   gtkwave::getTraceFlagsFromIndex $i   (scalar=40/0x28, comment=513/0x201)

Waveform images

Repo test benches

Checking signals for z/x (floating-net debugging)

When a signal should be driven but the waveform shows z/x, parse the VCD and scan each signal's value-change records. Vector changes are b<bits> <id> (two tokens); scalar changes are <0/1/x/z><id> (one token). Group by the signal's declared width from the $var line; a bit is z/x if any dumped value starts with z/x.

# tokens on a value-change line: 'b0' is a vector value whose id is the NEXT token
# '0k' is a scalar (value '0', id 'k')

DMG-CPU SoC netlists (emu-russia/dmgcpu) - extra notes

Worked out while bringing up the PPU regression testbench (HDL/soc/icarus/ppu, issue emu-russia/dmgcpu#390).