vpi: extended VCD ($dumpports) writer + native structural VPI (process/primitive/driver/contassign)#1389
Open
wm2015email wants to merge 2 commits into
Open
vpi: extended VCD ($dumpports) writer + native structural VPI (process/primitive/driver/contassign)#1389wm2015email wants to merge 2 commits into
wm2015email wants to merge 2 commits into
Conversation
Implement the IEEE 1364-2005 Clause 18 extended VCD task family ($dumpports / $dumpportsall / $dumpportsoff / $dumpportson / $dumpportsflush / $dumpportslimit), which were previously registered as "not implemented" stubs. The new vpi/sys_evcd.c reaches each port's value-bearing net through the port's vpiLowConn relationship and reads per-bit drive strength with vpiStrengthVal, emitting $var port declarations and p-records (per-bit state character plus strength0/strength1 components). Scalar and vector ports are supported; the initial checkpoint is deferred to the read-only synch so it records settled values. The encoding is byte-compatible with the GHDL --evcd writer so one waveform reader works across Verilog and VHDL. To resolve a port to its net, the VPI is completed: vpiLowConn and vpiHighConn are now implemented on vpiPortInfo. tgt-vvp emits the port's low (formal) and high (actual) net symbols in the .port_info directive, the vvp assembler parses them (compile_port_info), and vpiPortInfo resolves each to the __vpiSignal sharing that net. New vpi_user.h constants vpiHighConn (135) and vpiLowConn (136) use iverilog's private numbering to avoid colliding with vpiArgument/vpiBit. Tests: ivtest evcd_basic (scalar in/out/inout), evcd_bus (vector ports) and evcd_onoff ($dumpportsoff/on/all), each gold-diffed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Implement the IEEE 1364 structural VPI objects that Icarus previously left unimplemented, so a single-source consumer (e.g. a dataflow/waveform viewer) gets real data instead of empty fallbacks. Each object is sourced faithfully from the compiler and threaded ivl -> tgt-vvp -> .vvp directive -> assembler -> runtime __vpi* -> scope iterator -> vpi_user.h constants. * vpiProcess (always/initial/final): .process directive from ivl_design_process; object reports vpiType/vpiLineNo/vpiFile/vpiScope. * vpiPrimitive / vpiPrimTerm (gate/switch/UDP): .primitive directive from ivl_scope_logs; reports vpiPrimType, vpiSize (#inputs), name, location, and iterates terminals (vpiDirection, vpiTermIndex). * vpiDriver: the tri resolver already retains each driver's value+strength; tgt-vvp tags each input with its driver scope (.resolv_drv), and vpi_iterate(vpiDriver, net) exposes per-driver value (vpiStrengthVal) and scope. signal->node->fun is the resolver, so no extra linkage is needed. * vpiContAssign (+vpiLhs/vpiRhs): continuous assignments are preserved through the frontend (NetScope records each lval/rval/location/drive in PGAssign::elaborate; dll_target::end_design builds ivl_cont_assign_s, exposed via the new ivl_scope_cassigns/ivl_cassign_* API); tgt-vvp emits .contassign and the runtime materialises __vpiContAssign. vpiLhs/size/location are always faithful; vpiRhs resolves to the r-value net for simple assigns and is null for an expression r-value (anonymous synthesised temp). * EVCD ($dumpports) inout conflict states: sys_evcd.c walks vpiDriver on an inout's net, separates module-side from external drives by scope, and maps the pair to the full IEEE 1364-2005 18.4.3 state characters (0/1/?/F, the A/a/B/b/C/c conflicts, and d/u/l/h by drive strength) instead of collapsing a genuine bus conflict to '?'. New ivtest evcd_inout covers it. Full Verilog regression (regress-vlg.list) stays clean: the only failures are pre-existing (gold-less Expected-Fail tests, a VHDL test, a test needing -gno-io-range-error, and a pre-existing .port_info bug). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Collaborator
|
How odd. I was reading the extended dump part of the standard earlier wondering if it was ever going to be needed in Icarus. Regarding the duplicate value in vpi_user.h there should only be a value collision if they are used as part of the same property. If we have inadvertently coded something with the wrong value that should be fixed otherwise we should be following what is given in the standard. This is true even if the values are the same. |
Collaborator
|
Some test failures to look at and to get windows to compile you will need to add the new routines to the appropriate .def file. One of the oddities of windows versus Unix based systems. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two related additions to Icarus's VPI, on top of one another:
Extended VCD (
$dumpports) writer — asystem.vpitask family(
$dumpports,$dumpportsoff/on/all/flush/limit) that writes an IEEE1364-2005 Clause 18 extended VCD recording a module instance's ports with
direction and drive strength. Output is byte-compatible with the GHDL
--evcdwriter, so one reader works across Verilog and VHDL.Native structural-connectivity VPI — the IEEE 1364 object model that
Icarus previously left unimplemented, so structural consumers (dataflow /
waveform / analysis tools) get real data instead of empty fallbacks. Each
object is sourced faithfully from the compiler and threaded
ivl→ tgt-vvp →.vvpdirective → assembler → runtime__vpi*→ scopeiterator →
vpi_user.h:vpiProcess(always/initial/final): type, location, scope.vpiPrimitive/vpiPrimTerm(gate/switch/UDP):vpiPrimType,vpiSize, terminals withvpiDirection/vpiTermIndex.vpiDriver: per-driver value (vpiStrengthVal) and scope, read fromthe tri resolver (tagged at elaboration via
.resolv_drv).vpiContAssign(+vpiLhs/vpiRhs): continuous assignments preservedthrough the frontend (
NetScope→dll_target::end_design→ newivl_scope_cassigns/ivl_cassign_*API →.contassign→__vpiContAssign).vpiLhs/size/location always faithful;vpiRhsis ther-value net for simple assigns, null for an expression r-value.
Building on
vpiDriver, the$dumpportswriter now separates an inout'smodule-side drive from its external drive and emits the full IEEE 1364-2005
§18.4.3 conflict-state characters (
0/1/?/F, theA/a/B/b/C/cconflicts, andd/u/l/hby drive strength) rather than collapsing a genuine bus conflict to?.Constants
New object/relationship/property codes are added to
vpi_user.husing thestandard IEEE values where they are free in Icarus's numbering, and
Icarus-local values (continuing the 13x block) where the standard value
collides with an existing Icarus code (noted inline).
Tests
ivtestregressions:evcd_basic,evcd_bus,evcd_onoff, andevcd_inout(the inout conflict states) all pass. The full Verilog regression
(
regress-vlg.list) stays clean — the remaining failures are pre-existing andunrelated.
Notes / follow-ups
vpiLoadand full expression objects forvpiRhsare left as follow-ups.rather than the directional
H/U; inouts driven from both sides (thenormal testbench case) get the full set.
🤖 Generated with Claude Code