diff --git a/src/osdi/osdi.h b/src/osdi/osdi.h index c9d3c8cea..ac279903b 100644 --- a/src/osdi/osdi.h +++ b/src/osdi/osdi.h @@ -37,7 +37,7 @@ #define JACOBIAN_ENTRY_REACT_CONST 2 #define JACOBIAN_ENTRY_RESIST 4 #define JACOBIAN_ENTRY_REACT 8 -/* OSDI v0.5 (2C AC delay) — entry has a delay-coupling part loaded +/* OpenVA OSDI — entry has a delay-coupling part loaded * x e^{-jw*td} during AC (touches both real and imag matrix parts). */ #define JACOBIAN_ENTRY_DELAY 16 @@ -63,7 +63,7 @@ #define EVAL_RET_FLAG_FATAL 2 #define EVAL_RET_FLAG_FINISH 4 #define EVAL_RET_FLAG_STOP 8 -/* OSDI v0.5 axis-3 step rejection. Model raises this when it detects +/* OpenVA OSDI step rejection. Model raises this when it detects * an ill-conditioned regime (degenerate Jacobian, predicted-voltage * out of validity, internal-node blow-up). ngspice cuts the transient * step and retries with smaller delta instead of iterating fruitlessly @@ -72,8 +72,7 @@ * step-rejection semantics when the model itself doesn't set the flag. */ #define EVAL_RET_FLAG_REJECT_STEP 16 -/* OSDI v0.5 axis-4 event-driven analog operators. See - * OSDI_0_5_DESIGN.md in the OpenVA tree for the full design. +/* OpenVA OSDI event-driven analog operators. * * EVENT — the model wrote one or more entries into the * pending_events array of OsdiSimInfo. The simulator @@ -84,14 +83,11 @@ * track them across consecutive accepted evals and * bisect on sign-flip per the corresponding * OsdiCrossExprMeta direction. - * - * S3a (this commit) defines the bits; S3b implements the runtime - * loop logic that acts on them. */ #define EVAL_RET_FLAG_EVENT 32 #define EVAL_RET_FLAG_CROSS 64 -/* OSDI v0.5 OsdiEventKind discriminants (§2.6 of the design doc). +/* OpenVA OSDI OsdiEventKind discriminants. * Stored in the `kind` field of OsdiEventRequest (filled by the * model) and OsdiEventSlotMeta (defined by OpenVA at compile time) * to tell the simulator which kind of analog-block event-control @@ -128,13 +124,12 @@ typedef struct OsdiSimParas { char **vals_str; }OsdiSimParas; -/* OSDI v0.5 — event request slot in OsdiSimInfo.pending_events. +/* OpenVA OSDI — event request slot in OsdiSimInfo.pending_events. * * The model writes one of these per eval() per active timer/event * body that wants the simulator to advance to a specific future * time. The simulator consumes the slots, schedules the requests, * and zeros at_time before the next eval to indicate "consumed". - * See OSDI_0_5_DESIGN.md §2.5 for the layout and lifecycle. */ typedef struct OsdiEventRequest { double at_time; /* zero / NaN = no request from this slot */ @@ -142,7 +137,7 @@ typedef struct OsdiEventRequest { uint32_t kind; /* OSDI_EVENT_KIND_* */ }OsdiEventRequest; -/* OSDI v0.5 — per-cross-expression metadata in OsdiDescriptor. +/* OpenVA OSDI — per-cross-expression metadata in OsdiDescriptor. * * One entry per `@(cross(...))` body the model declares. OpenVA * fills this at compile time from the body's explicit arguments @@ -158,7 +153,7 @@ typedef struct OsdiCrossExprMeta { * cross is bracketed */ }OsdiCrossExprMeta; -/* OSDI v0.5 — per-event-slot metadata in OsdiDescriptor. +/* OpenVA OSDI — per-event-slot metadata in OsdiDescriptor. * * One entry per `@(cross)` / `@(timer)` / `@(initial_step)` / * `@(final_step)` body. `kind` is the OSDI_EVENT_KIND_* @@ -177,7 +172,7 @@ typedef struct OsdiSimInfo { double *prev_state; double *next_state; uint32_t flags; - /* OSDI v0.5 — see OSDI_0_5_DESIGN.md §2.3. + /* OpenVA OSDI event-driven state. * Allocated per-instance by setup_instance (sized from the * descriptor's num_cross_exprs / num_event_slots). Zero-init * is safe and represents "no event-driven state for this @@ -190,7 +185,7 @@ typedef struct OsdiSimInfo { uint32_t at_scheduled_event; /* bool, widened to u32 for ABI * stability across compilers */ uint32_t fired_event_id; - /* S3c — when at_scheduled_event != 0, this carries the true + /* When at_scheduled_event != 0, this carries the true * scheduled t_event the simulator originally computed (e.g. * the linear-interpolated cross-expr crossing time). The * simulator can't always land EXACTLY on t_event, so it fires @@ -199,19 +194,19 @@ typedef struct OsdiSimInfo { * last_crossing lowering reads THIS field instead of abstime * to latch the correct crossing time. */ double scheduled_event_time; - /* OSDI v0.5 — set to 1 by the simulator on the eval(s) of the final + /* OpenVA OSDI — set to 1 by the simulator on the eval(s) of the final * transient timepoint (CKTtime == CKTfinalTime), 0 otherwise. Lets a * model gate an `@(final_step)` body. Appended at the struct tail so * older .osdi binaries (which never read it) stay ABI-compatible. */ uint32_t at_final_step; - /* OSDI v0.5 (axis 2) — the current Newton iteration index (1-based, + /* OpenVA OSDI — the current Newton iteration index (1-based, * per-Newton-solve; resets each NIiter call), forwarded from * ckt->CKTosdiNewtonIter. Lets a model / compiler-synthesised $limit * make its damping iteration-aware (tighten as the count climbs to * break oscillation). Appended at the struct tail so older .osdi * binaries (which never read it) stay ABI-compatible. */ uint32_t newton_iter; - /* OSDI v0.5 (2C — absdelay exact transport). Tail-appended, ABI-safe. + /* OpenVA OSDI (absdelay exact transport). Tail-appended, ABI-safe. * delay_input : per-site scratch (sized num_delay_sites); the model * writes its current input x there each eval. The * simulator pushes (abstime, delay_input[site]) into @@ -335,12 +330,12 @@ typedef struct OsdiDescriptor { void (*load_jacobian_react)(void *inst, void* model, double alpha); void (*load_jacobian_tran)(void *inst, void* model, double alpha); - /* OSDI v0.4 fields — present in the descriptor produced by - * OpenVA / openvaf-reloaded for some time but not previously - * declared in this header (ngspice didn't need them). Added - * now because the OSDI v0.5 fields below sit after them and - * the C struct must mirror the binary's layout to compute - * the right offsets. */ + /* OpenVAF-Reloaded OSDI fields — present in the descriptor + * produced by OpenVAF-Reloaded and OpenVA but not previously + * declared in this header (ngspice didn't need them). Declared + * because the OpenVA OSDI fields below sit after them and the + * C struct must mirror the binary's layout to compute the + * right offsets. */ uint32_t (*given_flag_model)(void *model, uint32_t id); uint32_t (*given_flag_instance)(void *inst, uint32_t id); uint32_t num_resistive_jacobian_entries; @@ -352,29 +347,30 @@ typedef struct OsdiDescriptor { void (*load_jacobian_with_offset_resist)(void *inst, void* model, size_t offset); void (*load_jacobian_with_offset_react)(void *inst, void* model, size_t offset); - /* OSDI v0.5 — event-driven analog operators (§2.4 of the design - * doc). S3a (this commit) declares the field layout; S3b uses - * `num_cross_exprs` / `num_event_slots` to size the per-instance - * SimInfo arrays and walks the metadata arrays to drive the - * bisection state machine. Models that don't use cross/timer - * features emit zero for the counts and NULL for the metadata - * pointers, so older non-0.5 binaries (where these fields don't - * exist) read as zero via the OSDI_DESCRIPTOR_SIZE bounds-check - * the loader already enforces. */ + /* OpenVA OSDI — event-driven analog operators. The simulator + * uses `num_cross_exprs` / `num_event_slots` to size the + * per-instance SimInfo arrays and walks the metadata arrays to + * drive the bisection state machine. Models that don't use + * cross/timer features emit zero for the counts and NULL for the + * metadata pointers. Older binaries (OpenVAF / OpenVAF-Reloaded, + * where these fields don't exist) also read as zero: the loader + * copies each descriptor into a zeroed full-size struct at load + * time (osdiregistry.c), so all tail fields beyond the file's + * real descriptor are guaranteed 0. */ uint32_t num_cross_exprs; OsdiCrossExprMeta *cross_expr_metadata; uint32_t num_event_slots; OsdiEventSlotMeta *event_slot_metadata; - /* OSDI v0.5 (2C — absdelay exact transport). Number of per-instance + /* OpenVA OSDI (absdelay exact transport). Number of per-instance * transport-delay "sites" (one per absdelay call site in the model). * The simulator sizes and manages a (time, value) ring buffer per site * per instance; the model records its input each eval and reads delayed * values via SimInfo.delay_read. Zero for models with no absdelay. - * Tail-appended — ABI-safe via the OSDI_DESCRIPTOR_SIZE bounds check. */ + * Tail-appended — ABI-safe via the loader's zeroed-copy normalization. */ uint32_t num_delay_sites; - /* OSDI v0.5 (2C AC delay — 1B). The delay-coupling jacobian category: + /* OpenVA OSDI (AC delay). The delay-coupling jacobian category: * absdelay's AC contribution. num_delay_jacobian_entries jacobian entries * carry a delay part (flagged JACOBIAN_ENTRY_DELAY). write_jacobian_array * _delay(inst, model, dst) writes their raw values (ddx(-input)) into dst[ @@ -387,13 +383,13 @@ typedef struct OsdiDescriptor { void (*write_jacobian_array_delay)(void *inst, void *model, double *dst); uint32_t *delay_jacobian_sites; - /* OSDI 0.5 — per-instance persistent state (transition()/slew()/event + /* OpenVA OSDI — per-instance persistent state (transition()/slew()/event * toolkit). Byte offset and slot count of the persistent_state f64 array * inside the instance struct. The simulator snapshots this array and DEFERS * its commit to accepted steps only, so predictor / Newton iterates can't * corrupt the previous-accepted value the model reads back. Both zero for * models with no persistent state. Tail-appended — ABI-safe via the - * OSDI_DESCRIPTOR_SIZE bounds check. */ + * loader's zeroed-copy normalization. */ uint32_t persistent_state_offset; uint32_t persistent_state_count; }OsdiDescriptor; diff --git a/src/osdi/osdiacld.c b/src/osdi/osdiacld.c index 9a954c66c..96dda73c5 100644 --- a/src/osdi/osdiacld.c +++ b/src/osdi/osdiacld.c @@ -40,7 +40,7 @@ int OSDIacLoad(GENmodel *inModel, CKTcircuit *ckt) { descr->load_jacobian_resist(inst, model); descr->load_jacobian_react(inst, model, ckt->CKTomega); - /* OSDI v0.5 (2C AC delay — 1B). absdelay's exact AC phase: each delay + /* OpenVA OSDI (2C AC delay — 1B). absdelay's exact AC phase: each delay * jacobian entry's value V (= ddx(-input), computed at the OP) is stamped * as V * e^{-jw*td(site)} into the complex matrix -- V*cos(w*td) into the * real part and V*(-sin(w*td)) into the imag part. This is the diff --git a/src/osdi/osdicallbacks.c b/src/osdi/osdicallbacks.c index b4a864b02..aa9330990 100644 --- a/src/osdi/osdicallbacks.c +++ b/src/osdi/osdicallbacks.c @@ -87,7 +87,7 @@ double osdi_limitlog(bool init, bool *check, double vnew, double vold, return res; } -/* OSDI v0.5 (2C) — absdelay exact-transport reader. Bound to +/* OpenVA OSDI (2C) — absdelay exact-transport reader. Bound to * SimInfo.delay_read; the model calls it mid-eval to obtain * x(abstime - td) by linear interpolation over the per-instance ring * (accepted (time,value) samples, oldest..newest). SimInfo.delay_state @@ -108,7 +108,7 @@ double osdi_delay_read(const OsdiSimInfo *info, uint32_t site, double td, if (max_td >= 0.0 && td > max_td) td = max_td; - /* OSDI v0.5 (2C AC delay) — stash the (clamped) td so OSDIacLoad can read + /* OpenVA OSDI (2C AC delay) — stash the (clamped) td so OSDIacLoad can read * td(OP) for this site's e^{-jw*td} delay jacobian. */ if (extra->delay_td_arr) extra->delay_td_arr[site] = td; diff --git a/src/osdi/osdidefs.h b/src/osdi/osdidefs.h index eb0141974..5e6e64256 100644 --- a/src/osdi/osdidefs.h +++ b/src/osdi/osdidefs.h @@ -65,7 +65,7 @@ typedef struct OsdiExtraInstData { bool dt_given; uint32_t eval_flags; - /* OSDI v0.5 — event-driven analog operators (S3b). + /* OpenVA OSDI — event-driven analog operators (S3b). * * Per-instance scratch buffers for the SimInfo.cross_expr and * .pending_events pointers. Lazily allocated on first eval if @@ -97,14 +97,14 @@ typedef struct OsdiExtraInstData { uint32_t scheduled_count; bool cross_init; - /* OSDI v0.5 (S3c) — abstime of the last accepted eval that + /* OpenVA OSDI (S3c) — abstime of the last accepted eval that * latched prev_cross_expr_arr. Used as the lower bound for * interpolating the crossing time when the next eval detects a * sign flip. Default -1.0 (no prior eval); the first latched * eval sets it to the eval's abstime. */ double prev_eval_time; - /* OSDI v0.5 — the SECOND prior accepted (time, cross_expr) sample, + /* OpenVA OSDI — the SECOND prior accepted (time, cross_expr) sample, * kept so the crossing time can be QUADRATICALLY interpolated from * three points (t_prev2, t_prev, t_now) -> O(dt^3) error, instead of * the 2-point linear fit -> O(dt^2). The cross_expr VALUE already @@ -119,7 +119,7 @@ typedef struct OsdiExtraInstData { double *prev2_cross_expr_arr; double prev2_eval_time; - /* OSDI v0.5 (2C) — absdelay exact-transport delay rings. Lazily + /* OpenVA OSDI (2C) — absdelay exact-transport delay rings. Lazily * allocated on first eval when descr->num_delay_sites > 0. * delay_input_arr[site] : current input written by the model each eval * (exposed as SimInfo.delay_input); pushed into the ring at accept. @@ -130,7 +130,7 @@ typedef struct OsdiExtraInstData { * points back at THIS struct so SimInfo.delay_read can reach them. */ double *delay_input_arr; double *delay_maxtd_arr; - /* OSDI v0.5 (2C AC delay) — last td the model passed to delay_read per site, + /* OpenVA OSDI (2C AC delay) — last td the model passed to delay_read per site, * stashed by osdi_delay_read. At the AC operating point this holds td(OP), * which OSDIacLoad uses for e^{-jw*td} on that site's delay jacobian. */ double *delay_td_arr; @@ -139,7 +139,7 @@ typedef struct OsdiExtraInstData { uint32_t *delay_count; uint32_t *delay_cap; - /* OSDI 0.5 — DEFERRED-COMMIT snapshot of the model's persistent_state array + /* OpenVA OSDI — DEFERRED-COMMIT snapshot of the model's persistent_state array * (transition()/slew()/event toolkit). Sized to * entry->persistent_state_count, lazily allocated on first eval. Holds the * value as of the last ACCEPTED step. Each eval restores the live @@ -196,7 +196,7 @@ double osdi_limitlog(bool init, bool *icheck, double vnew, double vold, double osdi_fetlim(bool init, bool *icheck, double vnew, double vold, double vto); -/* OSDI v0.5 (2C) — absdelay exact-transport reader (bound to +/* OpenVA OSDI (2C) — absdelay exact-transport reader (bound to * SimInfo.delay_read). */ double osdi_delay_read(const OsdiSimInfo *info, uint32_t site, double td, double max_td); diff --git a/src/osdi/osdiload.c b/src/osdi/osdiload.c index 385b82735..93fd2fe69 100644 --- a/src/osdi/osdiload.c +++ b/src/osdi/osdiload.c @@ -73,7 +73,7 @@ OsdiSimParas get_simparams(const CKTcircuit *ckt) { return sim_params_; } -/* OSDI v0.5 (S3b) — per-instance event-state preparation BEFORE +/* OpenVA OSDI (S3b) — per-instance event-state preparation BEFORE * descr->eval is called. Lazy-allocate cross_expr / pending_events * buffers (sized from the descriptor), wire them onto the per-eval * SimInfo, and decide whether this eval is at a previously @@ -217,7 +217,7 @@ static double osdi_cross_time(double t0, double v0, return (denom > 0.0) ? t1 + span * (fabs(v1) / denom) : t2; } -/* OSDI v0.5 — post-eval processing. +/* OpenVA OSDI — post-eval processing. * * S3b: drain model-written pending_events into the sorted * scheduled_events queue. @@ -321,7 +321,7 @@ static void eval(const OsdiDescriptor *descr, const GENinstance *gen_inst, OsdiNgspiceHandle handle = (OsdiNgspiceHandle){.kind = 3, .name = gen_inst->GENname}; - /* OSDI v0.5 — per-instance scratch SimInfo with event-state + /* OpenVA OSDI — per-instance scratch SimInfo with event-state * pointers wired up. Originals stay shared/read-only across the * OMP parallel region. */ OsdiSimInfo sim_info_local = *sim_info; @@ -572,7 +572,7 @@ static void load(CKTcircuit *ckt, const GENinstance *gen_inst, void *model, } } -/* OSDI v0.5 (2C) — push one accepted (time, value) sample into delay ring +/* OpenVA OSDI (2C) — push one accepted (time, value) sample into delay ring * `s`, growing capacity geometrically, then prune leading samples that can * no longer bracket any delay <= maxtd (keeping >= 2 for interpolation). * maxtd < 0 means unbounded — capped at a defensive ceiling so a deck that @@ -614,7 +614,7 @@ static void osdi_delay_push(OsdiExtraInstData *extra, uint32_t s, double t, } } -/* OSDI 0.5 — DEFERRED-COMMIT persistent state. +/* OpenVA OSDI — DEFERRED-COMMIT persistent state. * * The model's persistent_state array (transition()/slew()/event toolkit) is * read-modify-written in place during eval, so a predictor eval and every @@ -662,7 +662,7 @@ static void osdi_persist_commit(const OsdiRegistryEntry *entry, void *inst, memcpy(extra->persist_snapshot, live, (size_t)n * sizeof(double)); } -/* OSDI v0.5 (2C) — DEVaccept hook. Fires once per ACCEPTED transient step +/* OpenVA OSDI (2C) — DEVaccept hook. Fires once per ACCEPTED transient step * (from CKTaccept); records each instance's current delay input (written by * the model during the converged eval) into its per-site transport-delay * ring. Only the accepted trajectory is recorded, which the model itself @@ -777,7 +777,7 @@ extern int OSDIload(GENmodel *inModel, CKTcircuit *ckt) { sim_info.flags |= CALC_REACT_JACOBIAN | CALC_REACT_RESIDUAL | CALC_REACT_LIM_RHS | ANALYSIS_TRAN; - /* OSDI 0.5 — flag the final transient timepoint so a model can fire + /* OpenVA OSDI — flag the final transient timepoint so a model can fire * an @(final_step) body. dctran puts a hard breakpoint at * CKTfinalTime, so the last accepted step lands exactly on it. */ if (AlmostEqualUlps(ckt->CKTtime, ckt->CKTfinalTime, 100)) { @@ -908,7 +908,7 @@ extern int OSDIload(GENmodel *inModel, CKTcircuit *ckt) { ckt->CKTnoncon++; } - /* Axis-3 (OSDI v0.5): a model has raised REJECT_STEP, signalling that + /* Axis-3 (OpenVA OSDI): a model has raised REJECT_STEP, signalling that * its linearization is invalid at the current operating point (predicted * voltage outside model validity, internal-node blow-up, ...). NIiter * will observe CKTosdiStepReject after CKTload returns and bail with diff --git a/src/osdi/osdiregistry.c b/src/osdi/osdiregistry.c index 85986fb0c..6d41f9c26 100644 --- a/src/osdi/osdiregistry.c +++ b/src/osdi/osdiregistry.c @@ -400,9 +400,8 @@ extern OsdiObjectFile load_object_file(const char *input) { } else { /* Original OpenVAF binaries don't publish OSDI_DESCRIPTOR_SIZE * and must be v0.3 exactly. OSDI_VERSION_MAJOR_CURR / - * OSDI_VERSION_MINOR_CURR now track the current - * openvaf-reloaded/OpenVA version (0.5 as of S3a) so the - * v0.3 check is hard-coded here. */ + * OSDI_VERSION_MINOR_CURR track the current OpenVA OSDI + * version, so the v0.3 check is hard-coded here. */ if (OSDI_VERSION_MAJOR != 0 || OSDI_VERSION_MINOR != 3) { printf("NGSPICE only supports OSDI v0.3 (original OpenVAF) " "or v0.4+ (OpenVAF-reloaded / OpenVA) but \"%s\" uses " @@ -411,7 +410,11 @@ extern OsdiObjectFile load_object_file(const char *input) { txfree(path); return INVALID_OBJECT; } - descriptor_size = sizeof(OsdiDescriptor); + /* The v0.3 descriptor ends right where the v0.4 fields begin: it is + * the prefix of the current struct up to given_flag_model. Using + * sizeof(OsdiDescriptor) here would walk a multi-descriptor v0.3 + * file with the wrong stride. */ + descriptor_size = offsetof(OsdiDescriptor, given_flag_model); } GET_CONST(OSDI_NUM_DESCRIPTORS, uint32_t); @@ -461,12 +464,31 @@ extern OsdiObjectFile load_object_file(const char *input) { } OsdiRegistryEntry *dst = TMALLOC(OsdiRegistryEntry, OSDI_NUM_DESCRIPTORS); - - char* desc_ptr = (char*)OSDI_DESCRIPTORS; + + /* Normalize the file's descriptors to this build's layout. The .osdi + * stores an array with stride descriptor_size, which for a v0.3/v0.4 file + * is smaller than the current struct (and for a future version may be + * larger). Copy each descriptor into a zeroed full-size OsdiDescriptor so + * every field this build knows about reads as a true zero when the file + * predates it — downstream code (osdiload.c, osditrunc.c) reads tail + * fields like num_cross_exprs without per-field size checks. The copies + * only hold counts/offsets and pointers back into the .so, which stays + * loaded for the lifetime of the process. */ + OsdiDescriptor *descriptors = TMALLOC(OsdiDescriptor, OSDI_NUM_DESCRIPTORS); + memset(descriptors, 0, sizeof(OsdiDescriptor) * OSDI_NUM_DESCRIPTORS); + { + size_t copy_size = descriptor_size < sizeof(OsdiDescriptor) + ? descriptor_size + : sizeof(OsdiDescriptor); + for (uint32_t i = 0; i < OSDI_NUM_DESCRIPTORS; i++) + memcpy(&descriptors[i], + (const char *)OSDI_DESCRIPTORS + (size_t)i * descriptor_size, + copy_size); + } + for (uint32_t i = 0; i < OSDI_NUM_DESCRIPTORS; i++) { - const OsdiDescriptor *descr = (OsdiDescriptor*)desc_ptr; - desc_ptr += descriptor_size; - + const OsdiDescriptor *descr = &descriptors[i]; + uint32_t dt = descr->num_params + descr->num_opvars; bool has_m = false; uint32_t temp = descr->num_params + descr->num_opvars + 1; @@ -491,28 +513,11 @@ extern OsdiObjectFile load_object_file(const char *input) { size_t inst_off = calc_osdi_instance_data_off(descr); size_t noise_off = calc_osdi_noise_off(descr); - /* OSDI v0.5 (2C) — only trust num_delay_sites if the published - * descriptor size actually reaches that field; a pre-2C .osdi has a - * smaller descriptor and reading it would dereference past its slot. */ - uint32_t num_delay_sites = - (descriptor_size >= offsetof(OsdiDescriptor, num_delay_sites) + - sizeof(uint32_t)) - ? descr->num_delay_sites - : 0u; - - /* Persistent-state offset/count: only trust them if the published - * descriptor actually reaches these tail fields (a pre-0.5 .osdi has a - * smaller descriptor). */ - uint32_t persistent_state_count = - (descriptor_size >= offsetof(OsdiDescriptor, persistent_state_count) + - sizeof(uint32_t)) - ? descr->persistent_state_count - : 0u; - uint32_t persistent_state_offset = - (descriptor_size >= offsetof(OsdiDescriptor, persistent_state_offset) + - sizeof(uint32_t)) - ? descr->persistent_state_offset - : 0u; + /* v0.5 tail fields: the normalized copy guarantees these read as zero + * when the .osdi predates them, so no per-field size checks needed. */ + uint32_t num_delay_sites = descr->num_delay_sites; + uint32_t persistent_state_count = descr->persistent_state_count; + uint32_t persistent_state_offset = descr->persistent_state_offset; dst[i] = (OsdiRegistryEntry){ .descriptor = descr, diff --git a/src/osdi/osditrunc.c b/src/osdi/osditrunc.c index 655848305..3864fcf66 100644 --- a/src/osdi/osditrunc.c +++ b/src/osdi/osditrunc.c @@ -20,7 +20,7 @@ int OSDItrunc(GENmodel *in_model, CKTcircuit *ckt, double *timestep) { bool has_boundstep = offset != UINT32_MAX; offset += entry->inst_offset; - /* OSDI v0.5 (S3b) — clamp the proposed timestep against any + /* OpenVA OSDI (S3b) — clamp the proposed timestep against any * pending scheduled events on instances of this model. Each * instance has a sorted per-instance queue of scheduled events; * the earliest one bounds dt so the simulator lands exactly on