Skip to content

Commit

Permalink
Add documentation for custom scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
mole99 committed Oct 1, 2024
1 parent 5554f85 commit a42687f
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 4 deletions.
98 changes: 97 additions & 1 deletion docs/source/tutorials/custom_scripts.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,98 @@
# Tutorial - Using Custom Scripts to Preprocess Simulation Results
# Using Custom Scripts to Postprocess Simulation Results

```{warning}
Custom scripts are still a WIP and the function signature of `postprocess` might still change!
```

This tutorial shows how to use custom Python scripts to postprocess simulation results of the `ngspice` tool.

This feature can be used to extract certain parameters from simulation results. For example, it could be used to calculate the INL, DNL, offset error and gain error of a DAC. An example of this can be seen in [sky130_ef_ip__rdac3v_8bit](https://github.com/RTimothyEdwards/sky130_ef_ip__rdac3v_8bit).

For a step-by-step guide on how to set up custom scripts, please see below.

## Specifying Custom Scripts in the Datasheet

At present, only the `ngspice` tool allows postprocessing of the simulation results. Please have a look at its arguments at {doc}`../reference_manual/tools`.

To add a custom script for postprocessing, you simply need to specify the `script` and `script_variables` arguments.

```yaml
tool:
ngspice:
template: voltage_output.sch
collate: iterations
format: ascii
suffix: .data
variables: [null, vout]
script: inl.py
script_variables: [inl]
```
The `script` argument defines the name of the Python script that is called for each of the simulation results. The `script_variables` argument defines the results generated by the script. In this case, the script generates a single variable called `dnl`. The variables can then be used in the `spec` or `plot` section as if they came from the simulation run itself. The script needs to be placed in the `scripts` folder of CACE.

CACE expects the custom script to provide a function called `postprocess`. The function signature of `postprocess` is as follows:

```Python
def postprocess(results: dict[str, list], conditions: dict[str, Any], collate: str|None) -> dict[str, list]:
```

The `results` argument contains the results of a single simulation run. Since `variables: [null, vout]` is set in the datasheet, `results` contains a single key `vout` with a list of values (`results['vout'] = [..., ...]`). The `conditions` argument contains the conditions for this simulation run. For example, it contains a key `temperature` with the value for this simulation run, e.g. `27` (`conditions['temperature'] = 27`).

If you collate simulation results based on a condition, then this condition will contain a list of values instead of a single value. For a Monte Carlo simulation that is collated with the `iterations` condition, `conditions['iterations']` contains a list of all the iterations for all collated simulations (`conditions['iterations'] = [1, 2, 3...]`).

The return value of `postprocess` is another dictionary that must contain the keys specified in the `script_variables` argument in the datasheet. In this case `{'inl': [..., ...]}` is returned, where the list can also contain only a single value.

To get a feel for the data being passed to your script, you can simply print `results` and `conditions` and return an empty dictionary. (Note that `script_variables` in the datasheet must be an empty list as this script does not return any results.)

```Python
def postprocess(results: dict[str, list], conditions: dict[str, Any]) -> dict[str, list]:
print(f'results: {results}')
print(f'conditions: {conditions}')
return {}
```

For a real example, see the contents of `inl.py`:

```Python
def postprocess(results: dict[str, list], conditions: dict[str, Any]) -> dict[str, list]:
print(f'results: {results}')
print(f'conditions: {conditions}')
# INL calculation:
# x is the digital value b7:0 converted to an integer
# V(x) is the original value in RESULT: The voltage output of the DAC
# under the given set of conditions.
# ALSB = (Vhigh - Vlow) / 256 (ideal voltage step size per LSB)
#
# INL(x) = (RESULT - (x * ALSB + Vlow)) / ALSB (in units of LSB)
#
# NOTE that this DAC is based on 256 steps with the highest step being
# 1 lsb below Vhigh.
Vhigh = float(conditions['Vhigh'])
Vlow = float(conditions['Vlow'])
x = float(conditions['b'])
alsb = (Vhigh - Vlow) / 256
inl = []
# Iterate over MC results
for vout in results['vout']:
inl.append((vout - (x * alsb + Vlow)) / alsb)
return {'inl': inl}
```

For a simulation run the result might look like this in the summary:

```
Parameter Tool Result Min Limit Min Value Typ Target Typ Value Max Limit Max Value Status
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
INL ngspice inl -2 lsb 0.998 lsb 0 lsb 1.136 lsb 2 lsb 3.995 lsb Fail ❌
```

6 changes: 3 additions & 3 deletions docs/source/tutorials/ota_5t.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Tutorial - CACE Setup for a 5T-OTA
# CACE Setup for a 5T-OTA

This tutorial will guide you step by step through the creation of a simple 5-transistor OTA and the CACE setup for it.
It is assumed that you have already set up CACE and its dependencies.
Expand Down Expand Up @@ -443,12 +443,12 @@ If you click on one of the column headings, you will get a plot of the selected

![CACE CLI Running](img/gui_3.png)

-->

## Final Thoughts

We hope this tutorial was able to give you an introduction to setting up and using CACE. If you already designed an IP block, you can add a CACE setup to it. Or you could try adding CACE to your next design. Have fun!

```{note}
Did you notice any issues with this tutorial or have ideas for improvements? Please open an [issue](https://github.com/efabless/cace/issues) so we can improve this tutorial. Thank you!
```

-->

0 comments on commit a42687f

Please sign in to comment.