|
| 1 | +--- |
| 2 | +title: LAPLACE Next Compatibility Plan |
| 3 | +status: Draft / Roadmap |
| 4 | +scope: SpiceSharpParser |
| 5 | +last_reviewed: 2026-05-02 |
| 6 | +--- |
| 7 | + |
| 8 | +# LAPLACE Next Compatibility Plan |
| 9 | + |
| 10 | +## Summary |
| 11 | + |
| 12 | +SpiceSharpParser already supports the core LAPLACE feature set: source-level `E` / `G` / `F` / `H` transfer sources, function-style `LAPLACE(input, transfer)` in behavioral expressions, mixed-expression helper lowering, generated C# writer parity, and focused OP / AC / transient coverage. |
| 13 | + |
| 14 | +The next roadmap phase should improve compatibility with common PSpice / LTspice-style netlists and reduce avoidable user rewrites. The recommended order is: |
| 15 | + |
| 16 | +1. Add inline function-call options. |
| 17 | +2. Support multiple delayed function-style calls. |
| 18 | +3. Accept simple arbitrary input expressions through helper lowering. |
| 19 | +4. Broaden transient verification and diagnostics. |
| 20 | +5. Investigate coefficient-list and state-option syntax only after the above pieces are stable. |
| 21 | + |
| 22 | +## Current Baseline |
| 23 | + |
| 24 | +Implemented behavior to preserve: |
| 25 | + |
| 26 | +- Source-level forms: |
| 27 | + |
| 28 | + ```spice |
| 29 | + E1 out 0 LAPLACE {V(in)} = {H(s)} M=2 TD=1n |
| 30 | + G1 out 0 LAPLACE {V(in)} {H(s)} |
| 31 | + F1 out 0 LAPLACE = {I(Vsense)} {H(s)} |
| 32 | + H1 out 0 LAPLACE {I(Vsense)} = {H(s)} |
| 33 | + ``` |
| 34 | + |
| 35 | +- Function-style forms: |
| 36 | + |
| 37 | + ```spice |
| 38 | + E1 out 0 VALUE={LAPLACE(V(in), H(s))} |
| 39 | + B1 out 0 V={LAPLACE(V(in), H(s))} |
| 40 | + B2 out 0 I={1m + LAPLACE(V(in), H(s))} |
| 41 | + ``` |
| 42 | + |
| 43 | +- Supported inputs: |
| 44 | + |
| 45 | + ```spice |
| 46 | + V(node) |
| 47 | + V(node1,node2) |
| 48 | + I(source) |
| 49 | + ``` |
| 50 | + |
| 51 | +- Supported transfer expressions are finite, proper rational polynomials in `s` with non-singular DC gain. |
| 52 | +- Source-level options `M=`, `TD=`, and `DELAY=` are assignment-only, finite constants. |
| 53 | +- Function-style source-level `TD=` / `DELAY=` requires exactly one `LAPLACE(...)` call today. |
| 54 | + |
| 55 | +## Phase 1: Inline Function Options |
| 56 | + |
| 57 | +Add support for call-local options inside function-style LAPLACE: |
| 58 | + |
| 59 | +```spice |
| 60 | +LAPLACE(V(in), H(s), M=2) |
| 61 | +LAPLACE(V(in), H(s), TD=1n) |
| 62 | +LAPLACE(V(in), H(s), DELAY=1n) |
| 63 | +LAPLACE(V(in), H(s), M=2, TD=1n) |
| 64 | +``` |
| 65 | + |
| 66 | +Implementation notes: |
| 67 | + |
| 68 | +- Extend `LaplaceFunctionExpressionLowerer.TryParseCall(...)` to accept two or more arguments. |
| 69 | +- Keep the first argument as input and the second argument as transfer. |
| 70 | +- Treat remaining arguments as option assignments only. |
| 71 | +- Reuse existing finite constant validation for `M=`, `TD=`, and `DELAY=`. |
| 72 | +- Fold call-local `M=` into that call's numerator coefficients. |
| 73 | +- Apply call-local delay to that direct source or helper source. |
| 74 | +- Reject duplicate multiplier or duplicate delay options per call. |
| 75 | +- Reject unsupported option names with a targeted validation error. |
| 76 | +- If both call-local and source-level options are present, reject overlapping options rather than guessing precedence. |
| 77 | + |
| 78 | +Reader tests: |
| 79 | + |
| 80 | +- Direct voltage-output call with `M=2` scales OP gain. |
| 81 | +- Direct current-output call with `M=2` scales output current. |
| 82 | +- Mixed expression with two calls can give each call its own `M=`. |
| 83 | +- Direct call with `TD=1n` sets entity delay. |
| 84 | +- Duplicate `TD=` / `DELAY=` inside one call fails. |
| 85 | +- Source-level `TD=` plus call-local `TD=` fails with a clear message. |
| 86 | + |
| 87 | +Writer tests: |
| 88 | + |
| 89 | +- Generated C# emits scaled numerator and delay for direct calls. |
| 90 | +- Mixed calls emit helper entities with each helper's own numerator and delay. |
| 91 | +- Invalid inline options emit the existing writer error-comment style. |
| 92 | + |
| 93 | +Docs: |
| 94 | + |
| 95 | +- Update `src/docs/articles/laplace.md` and `src/docs/articles/behavioral-source.md`. |
| 96 | +- Remove the statement that inline function options are unsupported. |
| 97 | +- Document source-level versus call-local option conflict rules. |
| 98 | + |
| 99 | +## Phase 2: Multiple Delayed Function Calls |
| 100 | + |
| 101 | +Once call-local options exist, allow mixed expressions with multiple delayed calls: |
| 102 | + |
| 103 | +```spice |
| 104 | +B1 out 0 V={ |
| 105 | + LAPLACE(V(a), 1/(1+s*t1), TD=1n) |
| 106 | + + LAPLACE(V(b), 1/(1+s*t2), TD=2n) |
| 107 | +} |
| 108 | +``` |
| 109 | + |
| 110 | +Implementation notes: |
| 111 | + |
| 112 | +- Keep the existing source-level delay restriction for multiple calls. |
| 113 | +- Allow multiple calls when each delay is call-local. |
| 114 | +- Each call lowers to its own helper entity with its own `Parameters.Delay`. |
| 115 | +- Direct whole-expression calls continue to map directly to the final Laplace entity. |
| 116 | + |
| 117 | +Tests: |
| 118 | + |
| 119 | +- Mixed two-call expression creates two helpers with distinct delays. |
| 120 | +- Source-level `TD=` with two calls still fails. |
| 121 | +- One delayed call plus one undelayed call succeeds. |
| 122 | +- OP and AC behavior remain unchanged by delay where the runtime treats delay outside those analyses. |
| 123 | +- Add a transient smoke test that verifies the circuit runs and the delayed output stays bounded. |
| 124 | + |
| 125 | +## Phase 3: Simple Arbitrary Input Expressions |
| 126 | + |
| 127 | +Support common input expressions by lowering them into helper behavioral sources: |
| 128 | + |
| 129 | +```spice |
| 130 | +LAPLACE(V(a)-V(b), H(s)) |
| 131 | +LAPLACE(2*V(in), H(s)) |
| 132 | +LAPLACE(V(a)+I(Vsense)*rscale, H(s)) |
| 133 | +``` |
| 134 | + |
| 135 | +Implementation strategy: |
| 136 | + |
| 137 | +- Preserve existing direct probe input fast paths. |
| 138 | +- For a non-probe input expression, create an internal behavioral voltage helper that evaluates the input expression. |
| 139 | +- Feed that helper node into an ordinary voltage-controlled Laplace helper: |
| 140 | + |
| 141 | + ```text |
| 142 | + input expression -> helper behavioral voltage source -> Laplace voltage input |
| 143 | + ``` |
| 144 | + |
| 145 | +- Only allow arbitrary input expressions in function-style `LAPLACE(...)` first. |
| 146 | +- Do not expand source-level `E/G/F/H ... LAPLACE {input}` input syntax until the function-style path is stable. |
| 147 | +- Reuse the existing behavioral expression resolver so parameters, functions, and probes behave like normal `B` / `VALUE` expressions. |
| 148 | + |
| 149 | +Naming: |
| 150 | + |
| 151 | +- Use deterministic helper names below the existing reserved namespace: |
| 152 | + |
| 153 | + ```text |
| 154 | + __ssp_laplace_input_<sourceName>_<index> |
| 155 | + __ssp_laplace_input_<sourceName>_<index>_src |
| 156 | + ``` |
| 157 | + |
| 158 | +- Continue using the existing `__ssp_laplace_<sourceName>_<index>` names for transfer helper outputs. |
| 159 | +- Maintain collision checks against existing generated entities. |
| 160 | + |
| 161 | +Validation: |
| 162 | + |
| 163 | +- Reject nested `LAPLACE(...)` inside the input helper expression. |
| 164 | +- Reject input expressions that cannot be parsed by the existing behavioral expression parser. |
| 165 | +- Keep transfer expression validation unchanged: it must still be a rational polynomial in `s`. |
| 166 | + |
| 167 | +Tests: |
| 168 | + |
| 169 | +- `LAPLACE(V(a)-V(b), H(s))` matches `LAPLACE(V(a,b), H(s))`. |
| 170 | +- `LAPLACE(2*V(in), H(s))` doubles OP gain. |
| 171 | +- Mixed expression with arbitrary input creates input helper, Laplace helper, and final behavioral source in the correct order. |
| 172 | +- Subcircuit test verifies generated helper names are scoped and collision-safe. |
| 173 | + |
| 174 | +## Phase 4: Broader Verification And Diagnostics |
| 175 | + |
| 176 | +Expand confidence around behavior that already mostly works but is not fully claimed. |
| 177 | + |
| 178 | +Transient tests: |
| 179 | + |
| 180 | +- Delayed first-order `E` low-pass step response. |
| 181 | +- Delayed first-order `G` low-pass step response through a grounded load. |
| 182 | +- `F` and `H` current-controlled first-order transient smoke tests. |
| 183 | +- Mixed function-style transient smoke test with at least one helper. |
| 184 | + |
| 185 | +Diagnostics: |
| 186 | + |
| 187 | +- Include the rejected transfer form in validation messages where practical. |
| 188 | +- For improper transfers, report numerator and denominator degree. |
| 189 | +- For singular DC gain, suggest adding a low-frequency pole or finite leakage term. |
| 190 | +- For arbitrary input rejection, suggest `V(a,b)` when the expression is exactly `V(a)-V(b)`. |
| 191 | + |
| 192 | +Docs: |
| 193 | + |
| 194 | +- Update the limitations section in `laplace.md` to say which transient paths are verified. |
| 195 | +- Add a short troubleshooting table for `1/s`, `s`, arbitrary input expressions, duplicate options, and source-level delay with multiple calls. |
| 196 | + |
| 197 | +## Phase 5: Compatibility Investigation |
| 198 | + |
| 199 | +Investigate these forms after phases 1-4 are complete. Do not implement them until runtime semantics and dialect compatibility are clear. |
| 200 | + |
| 201 | +### Coefficient-List Syntax |
| 202 | + |
| 203 | +Potential user-facing goal: |
| 204 | + |
| 205 | +```spice |
| 206 | +E1 out 0 LAPLACE {V(in)} NUM={1} DEN={1 1u} |
| 207 | +E1 out 0 LAPLACE {V(in)} = [num coefficients] [den coefficients] |
| 208 | +``` |
| 209 | + |
| 210 | +Open decisions: |
| 211 | + |
| 212 | +- Which dialect syntax should be accepted? |
| 213 | +- Are coefficients ascending or descending in the source dialect? |
| 214 | +- Should coefficients allow parameters? |
| 215 | +- How should this interact with `M=`, `TD=`, and `DELAY=`? |
| 216 | + |
| 217 | +### Internal-State Options |
| 218 | + |
| 219 | +Potential user-facing goal: |
| 220 | + |
| 221 | +```spice |
| 222 | +LAPLACE(V(in), H(s), IC=...) |
| 223 | +``` |
| 224 | + |
| 225 | +Open decisions: |
| 226 | + |
| 227 | +- Does SpiceSharpBehavioral expose enough state initialization support? |
| 228 | +- Are these options source-level, call-local, or both? |
| 229 | +- How do they behave across OP, AC, and transient analyses? |
| 230 | + |
| 231 | +### Singular Or Improper Transfer Support |
| 232 | + |
| 233 | +Examples: |
| 234 | + |
| 235 | +```spice |
| 236 | +LAPLACE(V(in), 1/s) |
| 237 | +LAPLACE(V(in), s) |
| 238 | +``` |
| 239 | + |
| 240 | +Current policy is to reject these. Any relaxation must first prove: |
| 241 | + |
| 242 | +- OP behavior is deterministic. |
| 243 | +- AC behavior matches user expectations. |
| 244 | +- Transient behavior is numerically stable. |
| 245 | +- Diagnostics remain clear for unsupported analysis combinations. |
| 246 | + |
| 247 | +## Key Files |
| 248 | + |
| 249 | +- `src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/Sources/LaplaceFunctionExpressionLowerer.cs` |
| 250 | +- `src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/Sources/LaplaceSourceParser.cs` |
| 251 | +- `src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/Sources/SourceGenerator.cs` |
| 252 | +- `src/SpiceSharpParser/ModelWriters/CSharp/Entities/Components/SourceWriterHelper.cs` |
| 253 | +- `src/SpiceSharpParser.Tests/ModelReaders/Spice/Readers/EntityGenerators/Components/Sources/LaplaceSourceParserTests.cs` |
| 254 | +- `src/SpiceSharpParser.Tests/ModelWriters/LaplaceSourceWriterTests.cs` |
| 255 | +- `src/SpiceSharpParser.IntegrationTests/AnalogBehavioralModeling/LaplaceTests.cs` |
| 256 | +- `src/docs/articles/laplace.md` |
| 257 | +- `src/docs/articles/behavioral-source.md` |
| 258 | + |
| 259 | +## Acceptance Criteria |
| 260 | + |
| 261 | +- Existing source-level and function-style LAPLACE tests continue passing. |
| 262 | +- Inline call-local options work in direct and mixed expressions. |
| 263 | +- Multiple delayed function-style calls work when delay is call-local. |
| 264 | +- Source-level delay with multiple function calls still fails clearly. |
| 265 | +- Simple arbitrary input expressions are either supported through helper lowering or rejected with better diagnostics. |
| 266 | +- Generated C# output matches reader behavior for all newly supported forms. |
| 267 | +- Public docs accurately distinguish supported, deferred, and rejected LAPLACE forms. |
| 268 | + |
0 commit comments