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>
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>