In this example we will examine the availible actions that we can do on elements in netlist. First step is building the target netlist with variable elements:
The opposite action is to delete with the ::SpiceGenTcl::Netlist::del method. For example, we can delete the 'c1' element from the netlist by specifying its name:
Result is:
As you can see, capacitor 'c1' is no more in netlist.
Next important operation is getting reference of element in netlist. We can do it again by specifying its name:
After it, we can change the resistance parameter of element:
We apply method ::SpiceGenTcl::Device::setParamValue with two arguments: name of parameter 'r' and its new value '100'. The other action we can do is change the pin connection of element:
To create subcircuit definition we use special ::SpiceGenTcl::Subcircuit class and make subcircuit by defining new class with it as superclass:
In constructor of this class we define pins as list with names in order of appearance in subcircuit header:
Then we define parameters as list of two-elements list that contains name and default value of parameter:
Next step is adding elements to subcircuit:
The last action is to pass name of subcircuit, list of pins and parameters to constructor of superclass:
Name passed to superclass constructor rcnet is not necessarily the same as name of the class, this name will be printed in subcircuit definition in netlist.
To create and add this definition to netlist, we use name of the class RCnet:
But place definition of subcircuit is not enough - we need to place netlist instance of subcircuit. We can do it by using two mechanisms:
First way is direct construction of element by providing pins and parameter lists:
But the second way is simpler and allow to check if we have mistake in definition:
In this approach, we pass the reference of our subcircuit as the first argument. Then, we only need to provide a list of nets connected to the pins, in the order defined in the subcircuit, and parameters in the form of -paramName paramValue. If you try to add a parameter that does not exist in the subcircuit definition, you'll receive an error.
In this example, we examine the parametric simulation of a diode model's current curve, with the ambient temperature as the parameter. To achieve this, we need to run the simulation multiple times at different temperatures, save the results from each iteration, and then combine them into a single plot.
The circuit is simple:
As in previous examples, we start by creating the top circuit and adding elements to it:
The temperature in Ngspice is set using the .temp statement. We create an instance with the ::SpiceGenTcl::Temp command, save the object reference in the variable tempSt, and then add it to the circuit:
The only thing left is to set the temperature value in the ::SpiceGenTcl::Temp class object, run the circuit, save the data, and repeat this process multiple times:
Plotting the results:
In the picture, you can see how temperature affects the forward current of the diode. Because the series resistance has a temperature dependence, all the lines intersect near 1.8V, indicating the point of zero temperature coefficient:
This circuit works almost without modification in Xyce simulator, see "examples/xyce/dc/diode_iv.tcl" file. The one of the differences is how we set the global temperature: in Xyce there is no .temp statement, for setting global temperature we use .options statement with class ::SpiceGenTcl::Options:
In this example, we measure the volt-farad (or capacitance-voltage) relationship of the diode's depletion charge. To achieve this, we need to apply a negative voltage bias to the anode and perform an AC simulation at a single frequency. We then repeat this process at different voltages, collect all the results, and finally plot the entire curve. We calculate the capacitance value using the following equation:
where I and V - voltage and current phasors, freq - frequency of applied AC signal. First, we can define π constant manually, or borrow the value from ::math::constants library:
We again go through the circuit building sequence:
What are new here:
AC voltage source [Vac new b nin 0 -ac 1] - uses to generate AC signal
AC analysis statement [Ac new -variation lin -n 1 -fstart 1e5 -fstop 1e5] - uses to define AC frequency, 100 kHz in our case.
The final circuit looks like this:
Nest step is to add voltage sweep:
Then we as usual, create ::SpiceGenTcl::Ngspice::Simulators::BatchLiveLog class object, attach it to $circuit, run it multiple times, collect results and apply the equation to calculate the capacitance (with the voltage phasor set to 1, so it is omitted):
Here, we collect the imaginary component of the current flowing through the AC voltage source 'Va'.
You might wonder why we use two indices, 0 and 1, when extracting values from the vector i(va).
The answer is as follows: the first index extracts values from the list of values at different frequencies, while the second index retrieves the imaginary component.
The AC data vectors are organized as follows:
Here, reVal0 is the real value at frequency index 0, imVal0is the imaginary value at the same frequency, reVal1 is the real value at frequency index 1, imVal1 is the imaginary value at that frequency, and so on. Even if there is only one frequency in the AC analysis, you should still extract the value using index 0.
Now we can plot the results:
As a result, we obtain the expected curve, showing a decrease in capacitance value with higher reverse voltage:
Sensitive analysis of differential pairTop, Main, Index
In this circuit we run DC sensitive analysis of differential pair:
We build circuit step by step:
Then we add models for NPN and PNP bipolar transistors:
In DC sensistive analysis we add input voltage to which we sense ohter parameters in the circuit:
We create simulator, run it and read data:
To print resulted sensitivities we use format command where we specify the format of the number:
Transient simulation of ring oscillatorTop, Main, Index
In this example, we analyze a circuit with transient analysis and demonstrate how to use a Tcl script to build a circuit containing multiple stages of the same subcircuit.
The circuit is a ring oscillator composed of voltage-controlled switches, based on an example from Ngspice (/examples/p-to-n-examples/switch-oscillators.cir). Each stage of the oscillator is a simple two-switch inverter, and the entire circuit consists of 17 stages.
At the beginning, we create a class called Inverter to describe the inverter and then instantiate an object of this class:
Next, we define the other elements and the top-level circuit:
We can add multiple stages of inverters using a loop, which saves many lines of code and allows us to dynamically adjust the number of stages:
After that, we add the first and last stages, as well as the models of the switches:
Now we can run and read data:
We save output waveform and power currents, and then plot it:
Transient simulation of four-bit adderTop, Main, Index
This example, like the previous one, involves a circuit run in transient analysis. However, it differs in terms of complexity and the presence of nested subcircuit elements.
The circuit is a classic adder with 2 four-bit inputs, sourced from Ngspice tests (/tests/transient/fourbitadder.cir). We incrementally build it from the simplest NAND logic blocks up to the four-bit adder circuit.
The NAND block itself is constructed from a combination of bipolar transistors, diodes, and resistors. Its definition is as follows:
To build one-bit adder we use combination of NAND subcircuits:
Previously, we built subcircuits, but here we demonstrate that subcircuits can be used within the definitions of other subcircuits, allowing us to create a multi-level hierarchy for building complex circuits. We start by combining one-bit adders to form two-bit adders, and then increase the level of grouping by connecting two two-bit subcircuits to create a four-bit adder:
Next step is to initialize top circuit and add all subcircuit definitions to it:
To properly see the circuit in action we define input signals to all eight inputs, as well as power: