# OSDI Callbacks

`osdicallback.h`/`osdicallback.cpp` implement the callback surface compiled OSDI (Verilog-A) code calls back into the simulator through - the simulator side of the OSDI ABI's function-pointer callbacks.

## Logging

`osdiLogMessage()` is the callback a compiled model uses to emit a log/warning/error message. It decodes the OSDI level bitmask (`LOG_LVL_DEBUG`/`DISPLAY`/`INFO`/`WARN`/`ERR`/`FATAL`) to pick the matching `Simulator::dbg()`/`out()`/`wrn()`/`err()` stream and a matching prefix, handles the `LOG_FMT_ERR` flag (the model failed to format its own message) as a special case, and - per the OSDI ownership convention - `free()`s the message string after printing it, since ownership of that heap allocation passes to the simulator across the callback boundary.

## Limiting functions

`OsdiCallbackHandle`/`OsdiLimitFunction` and the module-level `osdiPnjlim()`/`osdiTypedpnjlim()`/`osdiLimvds()`/`osdiFetlim()`/`osdiLimitlog()` functions are the simulator's implementations of classic SPICE Newton-Raphson damping heuristics (junction-voltage limiting, drain-source voltage limiting, FET voltage limiting, ...), each wrapping the corresponding `DEV*lim`/`limitlog` routine (see [Builtin Limit Functions](limitfunctions.md)) behind the small `(init, check, ...)` calling convention OSDI expects: an `init` call seeds a starting value, subsequent calls limit a proposed new value against the previous one and report via `*check` whether limiting actually changed it (which forces another Newton iteration).

`OsdiFile::limitFunctionTable` (defined here, declared as a static member of [`OsdiFile`](osdifile.md)) is the fixed name-to-function-pointer table `OsdiFile`'s constructor matches, by name and argument count, against a loaded shared library's own `OSDI_LIM_TABLE` - a compiled Verilog-A model that calls `$limit(x, "pnjlim", ...)` gets wired to one shared, simulator-supplied implementation, rather than every compiled model needing to bundle (and potentially disagree on) its own.
