Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API Support? #203

Open
ziadhm001 opened this issue Oct 20, 2023 · 4 comments
Open

API Support? #203

ziadhm001 opened this issue Oct 20, 2023 · 4 comments

Comments

@ziadhm001
Copy link

Hello, me & my team are currently working on a project that can be summarized into hardware kit powered by a simulator (so no real hardware in the background), so real-time simulation is a must for us, but though we aren't interested into running this with any GUI involved, we just need to pass params by APIs, netlists or acm format whatever it takes and get the output as a response.

So do we you have/planning to have an API support in livespice?

@dsharlet
Copy link
Owner

This is an interesting question. A few thoughts on the topic:

  • There are various levels at which you can interact with LiveSPICE internals. For example, the tests run circuit simulations from a command line program here:

    LiveSPICE/Tests/Test.cs

    Lines 36 to 95 in 2dafc08

    public Dictionary<Expression, List<double>> Run(
    Circuit.Circuit C,
    Func<double, double> Vin,
    int SampleRate,
    int Samples,
    int Oversample,
    int Iterations,
    Expression? Input = null,
    IEnumerable<Expression>? Outputs = null)
    {
    Analysis analysis = C.Analyze();
    TransientSolution TS = TransientSolution.Solve(analysis, (Real)1 / (SampleRate * Oversample));
    // By default, pass Vin to each input of the circuit.
    if (Input == null)
    Input = C.Components.Where(i => i is Input)
    .Select(i => Component.DependentVariable(i.Name, Component.t))
    // If there are no inputs, just make a dummy.
    .DefaultIfEmpty("V[t]")
    // Require exactly one input.
    .Single();
    // By default, produce every node of the circuit as output.
    if (Outputs == null)
    Outputs = C.Nodes.Select(i => i.V);
    Simulation S = new Simulation(TS)
    {
    Oversample = Oversample,
    Iterations = Iterations,
    Input = new[] { Input },
    Output = Outputs,
    };
    Dictionary<Expression, List<double>> outputs =
    S.Output.ToDictionary(i => i, i => new List<double>(Samples));
    double T = S.TimeStep;
    double t = 0;
    Random rng = new Random();
    int remaining = Samples;
    while (remaining > 0)
    {
    // Using a varying number of samples on each call to S.Run
    int N = Math.Min(remaining, rng.Next(1000, 10000));
    double[] inputBuffer = new double[N];
    List<double[]> outputBuffers = S.Output.Select(i => new double[N]).ToList();
    for (int n = 0; n < N; ++n, t += T)
    inputBuffer[n] = Vin(t);
    S.Run(inputBuffer, outputBuffers);
    for (int i = 0; i < S.Output.Count(); ++i)
    outputs[S.Output.ElementAt(i)].AddRange(outputBuffers[i]);
    remaining -= N;
    }
    return outputs;
    }
    .
  • The interface at that level is using the internal representation of circuits, e.g. the Circuit type. It's possible but not trivial to convert e.g. a SPICE net list to a LiveSPICE circuit description. It doesn't require a GUI representation, but it's not a 1:1 mapping with SPICE netlists either.
  • I'm not sure what the OS/hardware you are working with looks like, but LiveSPICE relies on some corners of the .NET runtime that might not be generally well supported. I'm thinking of the LINQ expression compiler that LiveSPICE (ab)uses to JIT compile the simulation code at runtime.
  • In general, unless you are already very familiar with LiveSPICE and it's limitations, I'd expect to be disappointed :) For example, changing a parameter (potentiometer) requires recompiling the simulation code, which takes a good amount of time (varies between a few milliseconds to a few seconds depending on circuit complexity).

@ziadhm001
Copy link
Author

Through my case, the layout may remain static (same components every time) but the interconnections between components may vary, a few milliseconds up to maybe 0.5 or 0.6 second would not be a problem, as long as after that time the audio our signal output is gonna be real-time (That may be another thought, the output can be read as an ordinary signal right?).

@dsharlet
Copy link
Owner

The performance of both simulation and recompiling the circuit really completely depends on the circuit complexity, and the hardware you are running on. Some examples (all 8x oversample rate, on AMD desktop CPU from ~2 years ago):

  • Simple linear circuit: 1 ms build, 30 MHz simulation rate (681x real time)
  • Simple non-linear circuit (tube amplifier): 30 ms build, ~300 khz simulation rate (7x real time)
  • Common guitar distortion pedal circuits (e.g. Tube screamer): 30 ms build, ~800 kHz simulation rate (19x real time)
  • Guitar preamp: 300 ms build, 50 kHz simulation rate (barely real time)

I'm not sure what you mean by ordinary signal. https://github.com/dsharlet/LiveSPICE/blob/master/Circuit/Simulation/Simulation.cs#L156 is the API that accepts the signal buffers, they're just double[] in C#. It should be possible to set things up so there are no allocations (so no garbage collection needed). I've periodically spot checked this is the case in our applications.

@dsharlet
Copy link
Owner

Before digging too much into the code, I'd recommend building some circuits you want to simulate with the GUI, and then try running the test application (the benchmark mode) on your target hardware on that circuit. That way, you'll be able to see how long it takes to compile the circuit, and how fast it simulates, on your real hardware. This will also reveal if there are going to be any challenges with dependencies on your target platform.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants