diff --git a/.github/workflows/ci_nix.yml b/.github/workflows/ci_nix.yml index 15c3af4..355b010 100644 --- a/.github/workflows/ci_nix.yml +++ b/.github/workflows/ci_nix.yml @@ -262,3 +262,41 @@ jobs: ciel enable --pdk-family ${{ matrix.pdk_family }} \ --pdk-root ./.ciel-${{ matrix.pdk_family }} \ ${{ env.PDK_HASH }} + - name: Compile Verilog-A (ihp-sg13g2) + if: matrix.pdk_family == 'ihp-sg13g2' + run: | + wget https://fides.fe.uni-lj.si/openvaf/download/openvaf-reloaded-20260616-linux_x64.tar.gz + sudo tar -xvzf openvaf-reloaded-20260616-linux_x64.tar.gz -C /usr/bin/ + cd ./.ciel-${{ matrix.pdk_family }}/${{ matrix.pdk }}/libs.tech/verilog-a; source openvaf-compile-va.sh + - name: Run Example (sky130) + if: matrix.pdk_family == 'sky130' + run: | + PDK_ROOT=$(realpath ./.ciel-${{ matrix.pdk_family }}) PDK=${{ matrix.pdk }} nix develop --command bash -c "cd examples/sky130_cace_ip__ota5t/; cace" + - name: Run Example (ihp-sg13g2) + if: matrix.pdk_family == 'ihp-sg13g2' + run: | + PDK_ROOT=$(realpath ./.ciel-${{ matrix.pdk_family }}) PDK=${{ matrix.pdk }} nix develop --command bash -c "cd examples/sg13g2_cace_ip__ota5t/; cace" + # Upload artifacts + - name: Upload Artifacts + if: matrix.pdk_family == 'sky130' + uses: actions/upload-artifact@v4 + with: + name: runs_sky130 + path: | + examples/sky130_cace_ip__ota5t/runs/ + # Add summary + - name: Add Markdown to Step Summary + if: matrix.pdk_family == 'sky130' + run: cat examples/sky130_cace_ip__ota5t/runs/*/summary.md >> $GITHUB_STEP_SUMMARY + # Upload artifacts + - name: Upload Artifacts + if: matrix.pdk_family == 'ihp-sg13g2' + uses: actions/upload-artifact@v4 + with: + name: runs_ihp-sg13g2 + path: | + examples/sg13g2_cace_ip__ota5t/runs/ + # Add summary + - name: Add Markdown to Step Summary + if: matrix.pdk_family == 'ihp-sg13g2' + run: cat examples/sg13g2_cace_ip__ota5t/runs/*/summary.md >> $GITHUB_STEP_SUMMARY diff --git a/cace/__version__.py b/cace/__version__.py index 7a71b48..d325f0d 100644 --- a/cace/__version__.py +++ b/cace/__version__.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "2.10.0" +__version__ = "2.11.0" if __name__ == "__main__": print(__version__, end="") diff --git a/cace/cace_cli.py b/cace/cace_cli.py index 775649c..93a73e4 100755 --- a/cace/cace_cli.py +++ b/cace/cace_cli.py @@ -352,7 +352,9 @@ def cli(): ) # Run the simulations - parameter_manager.run_parameters_async() + if parameter_manager.run_parameters_async(): + err(f"CACE failed to dispatch parameters.") + sys.exit(1) # Wait for completion parameter_manager.join_parameters() diff --git a/cace/common/cace_read.py b/cace/common/cace_read.py index 4a0f440..44fcb66 100755 --- a/cace/common/cace_read.py +++ b/cace/common/cace_read.py @@ -627,10 +627,6 @@ def validate_datasheet(datasheet): # Find tool via old name or new ID if cls := find_tool(toolname): - print("-----------") - print(toolname) - print(variables) - for config_var in cls.config_vars: if config_var.name in variables: value = variables[config_var.name] @@ -641,11 +637,6 @@ def validate_datasheet(datasheet): key_path = f"{param_name}.{cls.id}.{config_var.name}" - print(key_path) - print(value) - print(config_var.default) - print(config_var.type) - # Validate the types config_var._Variable__process( key_path=key_path, diff --git a/cace/parameter/parameter_klayout_drc.py b/cace/parameter/parameter_klayout_drc.py index 17b0b23..620c5d7 100755 --- a/cace/parameter/parameter_klayout_drc.py +++ b/cace/parameter/parameter_klayout_drc.py @@ -141,7 +141,7 @@ def implementation(self): "drc", f'{self.datasheet["PDK"]}_mr.drc', ) - if self.datasheet["PDK"].startswith("ihp-sg13g2"): + if self.datasheet["PDK"].startswith("ihp-sg13"): drc_script_path = os.path.join( get_pdk_root(), self.datasheet["PDK"], @@ -149,7 +149,7 @@ def implementation(self): "klayout", "tech", "drc", - "run_drc.py", + f'{self.datasheet["PDK"]}.drc', ) if not os.path.exists(drc_script_path): @@ -158,7 +158,7 @@ def implementation(self): self.jobs_sem.release(jobs) return - report_file_path = os.path.join(self.param_dir, "report.xml") + report_file_path = os.path.join(self.param_dir, "drc_report.lyrdb") arguments = [] @@ -178,41 +178,29 @@ def implementation(self): f"thr={jobs}", ] - if self.datasheet["PDK"].startswith("ihp-sg13g2"): + if self.datasheet["PDK"].startswith("ihp-sg13"): arguments = [ + "-b", + "-r", drc_script_path, - f"--topcell={projname}", - f"--path={os.path.abspath(layout_filepath)}", - f"--run_dir={self.param_dir}", - f"--mp={jobs}", + "-rd", + f"input={os.path.abspath(layout_filepath)}", + "-rd", + f"topcell={projname}", + "-rd", + f"report={report_file_path}", + "-rd", + f"threads={jobs}", ] - if self.config["args"]: - arguments.extend(self.config["args"]) - - # IHP has a python wrapper for running the DRC - returncode = self.run_subprocess( - "python3", - arguments, - cwd=self.param_dir, - ) + if self.config["args"]: + arguments.extend(self.config["args"]) - # The report is placed in a .lyrdb file - # - The name of this file depends on which rulesets were checked... - # - Only one report should remain after merging by run_drc.py - report_files = glob.glob(f"{self.param_dir}/*.lyrdb") - if len(report_files) > 0: - report_file_path = report_files[0] - - else: - if self.config["args"]: - arguments.extend(self.config["args"]) - - returncode = self.run_subprocess( - "klayout", - arguments, - cwd=self.param_dir, - ) + returncode = self.run_subprocess( + "klayout", + arguments, + cwd=self.param_dir, + ) # Free job(s) from the global jobs semaphore self.jobs_sem.release(jobs) diff --git a/cace/parameter/parameter_manager.py b/cace/parameter/parameter_manager.py index 0971d42..e695fb9 100755 --- a/cace/parameter/parameter_manager.py +++ b/cace/parameter/parameter_manager.py @@ -32,6 +32,7 @@ generate_documentation, ) from ..common.cace_regenerate import regenerate_netlists, regenerate_gds +from ..common.common import get_pdk_root from ..logging import ( dbg, @@ -487,10 +488,6 @@ def queue_parameter( if cls := find_tool(toolname): - print("-----------") - print(toolname) - print(variables) - processed_variables = {} for config_var in cls.config_vars: @@ -503,11 +500,6 @@ def queue_parameter( key_path = f"{pname}.{cls.id}.{config_var.name}" - print(key_path) - print(value) - print(config_var.default) - print(config_var.type) - # Validate the types val = config_var._Variable__process( key_path=key_path, @@ -519,8 +511,6 @@ def queue_parameter( processed_variables[config_var.name] = val - print(processed_variables) - new_sim_param = cls( pname, processed_variables, @@ -644,6 +634,8 @@ def prepare_run_dir(self): for run in remove: shutil.rmtree(run) + info(f"PDK root is '{get_pdk_root()}'.") + def run_parameters_async(self): """Start a worker thread to start parameter threads""" @@ -656,13 +648,13 @@ def run_parameters_async(self): if not fullnetlistpath: err("Failed to regenerate project netlist, aborting.") self.cancel_parameters(True) - return + return 1 # If mag files are given as layout, regenerate the gds if needed if regenerate_gds(self.datasheet, self.runtime_options): err("Failed to regenerate GDSII layout from magic layout, aborting.") self.cancel_parameters(True) - return + return 1 # Only start a new worker thread, if # the previous one hasn't completed yet @@ -671,6 +663,8 @@ def run_parameters_async(self): self.worker_thread = threading.Thread(target=self.run_parameters_thread) self.worker_thread.start() + return 0 + def run_parameters_thread(self): """Called as a thread, starts the threads of queued parameters""" diff --git a/docs/source/examples/index.md b/docs/source/examples/index.md index ced05f3..6da6c58 100644 --- a/docs/source/examples/index.md +++ b/docs/source/examples/index.md @@ -1,12 +1,13 @@ # Examples -The following repositories contain example circuit designs, each having a `cace/` subdirectory with a specification input (the datasheet), and a set of testbench schematics which are used by CACE to measure all specified parameters, generate results, and analyze them to determine circuit performance over corners. +You can find examples using CACE in the `examples/` directory of the repository. -Example circuit repositories: +Each has a `cace/` subdirectory with a specification input (the datasheet), and a set of testbench schematics which are used by CACE to measure all specified parameters, generate results, and analyze them to determine circuit performance over corners. + +### Community IP | Design | Description | PDK | |----------------------------|----------------------------|-----| -| [ota-5t](https://github.com/mole99/ota-5t/) | A simple 5-transistor OTA | Sky130A | | [sky130_ef_ip__opamp](https://github.com/RTimothyEdwards/sky130_ef_ip__opamp) | Operational Amplifier | Sky130A | | ... | ... | diff --git a/examples/.gitignore b/examples/.gitignore new file mode 100644 index 0000000..800a7f5 --- /dev/null +++ b/examples/.gitignore @@ -0,0 +1,7 @@ +netlist/ +xschem/sim/ +xschem/simulations/ +runs/ +cace/templates/*.spice +cace/templates/*.sym +docs/ diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..ad933fb --- /dev/null +++ b/examples/README.md @@ -0,0 +1,6 @@ +# Examples + +These are simple examples for using CACE for sky130 and ihp-sg13g2. + +Please note that for ihp-sg13g2 you need to compile the simulation models first. +See `ihp-sg13g2/libs.tech/verilog-a/` for more information. diff --git a/examples/sg13g2_cace_ip__ota5t/LICENSE b/examples/sg13g2_cace_ip__ota5t/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/examples/sg13g2_cace_ip__ota5t/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/examples/sg13g2_cace_ip__ota5t/README.md b/examples/sg13g2_cace_ip__ota5t/README.md new file mode 100644 index 0000000..355de8e --- /dev/null +++ b/examples/sg13g2_cace_ip__ota5t/README.md @@ -0,0 +1,38 @@ +# A simple 5-transistor OTA ![](../../workflows/cace/badge.svg) + +This example showcases how to setup a project for [CACE](https://github.com/fossi-foundation/cace). + +- [Documentation](docs/sg13g2_cace_ip__ota5t.md) +- [Characterization](docs/sg13g2_cace_ip__ota5t_rcx.md) + +# Repository Structure + +Besides the normal directories such as `xschem/` for the schematic and testbench and `gds/` for the layout, there is also the `cace/` subdirectory. +Here you will find the CACE datasheet for this project named `sg13g2_cace_ip__ota5t.yaml`, which contains the specification for the design and represents the configuration for CACE. + +In the `templates/` subdirectory you will find some xschem testbench. These are not a normal testbenches, but instead acts as templates for CACE. +They contain placeholders for various conditions such as `CACE{temperature}` or `CACE{corner}`, which will get substituted by CACE to generate the final simulation testbenches. + +The subdirectory `scripts/` contains all user-defined scripts, in this case a custom script `run_project_lvs.tcl` to run LVS. + +# Run CACE + +After you have installed CACE and all dependencies, invoking the characterization of this project is as easy as running: + +```console +cace +``` + +This will use the "best" netlist available. Since a layout is provided, the netlist source will be "rcx" (R-C-extracted). To perform characterization on a different netlist, pass the `--source` argument to cace. For help on arguments, run `cace --help`. + +After characterization is completed, you will find the simulation files, log files and reports under `run/TIMESTAMP/`, where TIMESTAMP is the time and date when cace was started. + +# Continuous Integration + +This project also demonstrates how CACE can be used for continuous integration. Under `.github/workflows/` you will find the `ci.yml` GitHub action. It makes use of the composite action [cace-action](https://github.com/mole99/cace-action). + +First, the environment is set up and CACE is started. Then the `run/` directory is uploaded so that it can be viewed later. Finally, the summary is added to the step overview. + +Take a look at the latest runs under [actions](https://github.com/mole99/sg13g2_cace_ip__ota5t/actions). If you are logged in to GitHub, you can also click on a run and view the summary. + + diff --git a/examples/sg13g2_cace_ip__ota5t/cace/scripts/run_project_lvs.tcl b/examples/sg13g2_cace_ip__ota5t/cace/scripts/run_project_lvs.tcl new file mode 100644 index 0000000..76c5644 --- /dev/null +++ b/examples/sg13g2_cace_ip__ota5t/cace/scripts/run_project_lvs.tcl @@ -0,0 +1,15 @@ +# NOTE: PDK_ROOT, PDK and CACE_ROOT are set in the local environment by CACE +# +# This is an example script to drive LVS; because this is a simple +# example, there is no specific benefit of using this instead of the +# default handling in CACE. + +set PDK_ROOT $::env(PDK_ROOT) +set PDK $::env(PDK) +set CACE_ROOT $::env(CACE_ROOT) +set TOP sg13g2_cace_ip__ota5t + +set circuit1 [readnet spice $CACE_ROOT/netlist/layout/$TOP.spice] +set circuit2 [readnet spice $CACE_ROOT/netlist/schematic/$TOP.spice] + +lvs "$circuit1 $TOP" "$circuit2 $TOP" $PDK_ROOT/$PDK/libs.tech/netgen/${PDK}_setup.tcl ${TOP}_comp.out -json diff --git a/examples/sg13g2_cace_ip__ota5t/cace/sg13g2_cace_ip__ota5t.yaml b/examples/sg13g2_cace_ip__ota5t/cace/sg13g2_cace_ip__ota5t.yaml new file mode 100644 index 0000000..71a0bc9 --- /dev/null +++ b/examples/sg13g2_cace_ip__ota5t/cace/sg13g2_cace_ip__ota5t.yaml @@ -0,0 +1,325 @@ +#-------------------------------------------------------------- +# CACE circuit characterization file +#-------------------------------------------------------------- + +name: sg13g2_cace_ip__ota5t +description: A simple 5-transistor OTA +PDK: ihp-sg13g2 + +cace_format: 5.2 + +authorship: + designer: Leo Moser + creation_date: June 27, 2025 + license: Apache 2.0 + +paths: + root: .. + schematic: xschem + layout: gds + netlist: netlist + documentation: docs + +pins: + VDD: + description: Positive analog power supply + type: power + direction: inout + Vmin: 1.4 + Vmax: 1.6 + VSS: + description: Analog ground + type: ground + direction: inout + Ib: + description: Bias current input + type: signal + direction: input + Vp: + description: Voltage positive input + type: signal + direction: input + Vn: + description: Voltage negative input + type: signal + direction: input + Vout: + description: Voltage output + type: signal + direction: output + +default_conditions: + vdd: + description: Analog power supply voltage + display: Vdd + unit: V + typical: 1.5 + vcm: + description: Input common mode voltage + display: Vcm + unit: V + typical: 0.75 + ib: + description: Bias current + display: Ib + unit: uA + typical: 10 + cl: + description: Output load capacitance + display: CLoad + unit: pF + maximum: 1 + corner: + description: Process corner + display: Corner + typical: mos_tt + temperature: + description: Ambient temperature + display: Temp + unit: °C + typical: 27 + +parameters: + dc_params: + display: DC Params + spec: + a0: + display: DC gain + description: The DC gain of the OTA + unit: V/V + minimum: + value: 10 + typical: + value: any + maximum: + value: any + ugf: + display: Unity Gain Frequency + description: The unity gain frequency of the OTA + unit: Hz + minimum: + value: 1e6 + typical: + value: any + maximum: + value: any + pm: + display: Phase Margin + description: The phase margin of the OTA + unit: ° + minimum: + value: 60 + typical: + value: any + maximum: + value: any + tool: + ngspice: + template: ac.sch + format: ascii + suffix: .data + variables: [a0, ugf, pm] + plot: + gain_vs_temp: + type: xyplot + xaxis: temperature + yaxis: a0 + limits: auto + ugf_vs_corner: + type: xyplot + xaxis: corner + yaxis: ugf + limits: true + pm_vs_vdd: + type: xyplot + xaxis: vdd + yaxis: pm + limits: false + conditions: + corner: + minimum: mos_ss + typical: mos_tt + maximum: mos_ff + vdd: + minimum: 1.7 + typical: 1.8 + maximum: 1.9 + temperature: + minimum: -40 + typical: 27 + maximum: 130 + + gain_mc: + description: DC gain Monte Carlo + display: DC gain MC + unit: V/V + spec: + a0: + minimum: + value: 10 + typical: + value: any + maximum: + value: any + tool: + ngspice: + template: ac.sch + # Merge runs with the same conditions + # but different iterations + # This is used for plotting + collate: iterations + format: ascii + suffix: .data + variables: [a0, null, null] + plot: + gain_mc: + type: histogram + xaxis: a0 + limits: auto + conditions: + iterations: + description: Iterations to run + display: Iterations + minimum: 1 + maximum: 10 + step: linear + stepsize: 1 + corner: + typical: mos_tt_stat + temperature: + minimum: -40 + typical: 27 + maximum: 130 + + transient_response: + description: Large signal transient response + display: Large signal transient response + status: skip + unit: mV + tool: + ngspice: + template: transient.sch + format: ascii + suffix: .data + variables: [time, Vout, Vinp] + jobs: 4 + plot: + transient: + suffix: .svg + xaxis: time + yaxis: [Vout, Vinp] + variables: + time: + display: Time + unit: ms + Vinp: + display: Vinp + unit: V + Vout: + display: Vout + unit: V + conditions: + Tmax: + display: Simulation time + unit: ns + typical: 500 + temperature: + minimum: -40 + typical: 27 + maximum: 130 + corner: + minimum: mos_ss + typical: mos_tt + maximum: mos_ff + + magic_area: + spec: + area: + display: Area + description: Total circuit layout area + unit: µm² + maximum: + value: 600 + width: + display: Width + description: Total circuit layout width + unit: µm + maximum: + value: any + height: + display: Height + description: Total circuit layout height + unit: µm + maximum: + value: any + tool: + magic_area + + magic_drc: + description: Magic DRC + display: Magic DRC + spec: + drc_errors: + maximum: + value: 0 + tool: + magic_drc: + gds_flatten: true + + netgen_lvs: + description: Netgen LVS + display: Netgen LVS + spec: + lvs_errors: + maximum: + value: 0 + tool: + netgen_lvs: + script: run_project_lvs.tcl + + klayout_drc_maximal: + description: KLayout DRC maximal + display: KLayout DRC maximal + spec: + drc_errors: + maximum: + value: 0 + tool: + klayout_drc: + jobs: max + args: ['-rd', 'densityRules=false'] + +# klayout_lvs: +# description: KLayout LVS +# display: KLayout LVS +# spec: +# lvs_errors: +# maximum: +# value: 0 +# tool: +# klayout_lvs: +# jobs: max +# args: [ +# '-rd', 'spice_net_names=true', +# '-rd', 'spice_comments=true', +# '-rd', 'scale=true', +# '-rd', 'verbose=true', +# '-rd', 'schematic_simplify=true', +# '-rd', 'net_only=true', +# '-rd', 'top_lvl_pins=true', +# '-rd', 'combine=true', +# '-rd', 'purge=true', +# '-rd', 'purge_nets=true', +# '-rd', 'lvs_sub=VSS', +# '-rd', 'convert_subckts=true', +# ] + + magic_antenna_check: + description: Run antenna violation check using magic + display: Antenna Checks + spec: + antenna_violations: + maximum: + value: 0 + tool: + magic_antenna_check diff --git a/examples/sg13g2_cace_ip__ota5t/cace/templates/ac.sch b/examples/sg13g2_cace_ip__ota5t/cace/templates/ac.sch new file mode 100644 index 0000000..b512c1a --- /dev/null +++ b/examples/sg13g2_cace_ip__ota5t/cace/templates/ac.sch @@ -0,0 +1,135 @@ +v {xschem version=3.4.6 file_version=1.2} +G {} +K {} +V {} +S {} +E {} +N 540 130 560 130 { +lab=Vout} +N 560 130 560 150 { +lab=Vout} +N 50 170 50 190 { +lab=GND} +N 50 70 50 110 { +lab=VSS} +N 130 170 130 190 { +lab=GND} +N 50 190 50 210 { +lab=GND} +N 130 70 130 110 { +lab=VDD} +N 50 190 130 190 { +lab=GND} +N 210 70 210 110 { +lab=VDD} +N 210 170 210 210 { +lab=Ib} +N 230 370 270 370 { +lab=#net1} +N 50 320 50 480 { +lab=#net1} +N 50 320 230 320 { +lab=#net1} +N 50 540 50 560 { +lab=GND} +N 230 540 230 560 { +lab=GND} +N 230 460 310 460 { +lab=#net2} +N 230 460 230 480 { +lab=#net2} +N 230 410 270 410 { +lab=GND} +N 230 410 230 430 { +lab=GND} +N 150 420 150 460 { +lab=#net2} +N 310 420 310 460 { +lab=#net2} +N 230 320 230 370 { +lab=#net1} +N 310 280 310 360 { +lab=Vn} +N 150 280 150 360 { +lab=Vp} +N 150 460 230 460 { +lab=#net2} +N 190 410 230 410 { +lab=GND} +N 190 370 230 370 { +lab=#net1} +C {devices/isource.sym} 210 140 0 0 {name=I0 value=CACE\{ib\}} +C {devices/lab_wire.sym} 450 70 0 0 {name=p2 sig_type=std_logic lab=VDD} +C {devices/capa.sym} 560 180 0 0 {name=C1 +m=1 +value=CACE\{cl\} +footprint=1206 +device="ceramic capacitor"} +C {devices/gnd.sym} 560 210 0 0 {name=l2 lab=GND} +C {devices/lab_wire.sym} 390 90 0 0 {name=p3 sig_type=std_logic lab=Vp} +C {devices/lab_wire.sym} 390 170 0 0 {name=p4 sig_type=std_logic lab=Vn} +C {devices/lab_wire.sym} 390 130 0 0 {name=p7 sig_type=std_logic lab=Ib} +C {devices/code_shown.sym} 660 220 0 0 {name=SETUP +simulator=ngspice +only_toplevel=false +value=" +.include CACE\{DUT_path\} + +.temp CACE\{temperature\} + +.option SEED=CACE[CACE\{seed=12345\} + CACE\{iterations=0\}] + +* Flag unsafe operating conditions (exceeds models' specified limits) +.option warn=1 +"} +C {devices/lab_wire.sym} 560 130 0 1 {name=p11 sig_type=std_logic lab=Vout} +C {devices/vsource.sym} 50 140 0 0 {name=V0 value=0 savecurrent=false} +C {devices/gnd.sym} 50 210 0 0 {name=l3 lab=GND} +C {devices/vsource.sym} 130 140 0 0 {name=V2 value=CACE\{vdd\} savecurrent=false} +C {devices/lab_wire.sym} 50 70 0 0 {name=p1 sig_type=std_logic lab=VSS} +C {devices/lab_wire.sym} 210 210 2 0 {name=p8 sig_type=std_logic lab=Ib} +C {devices/vcvs.sym} 150 390 0 1 {name=E1 value=0.5} +C {devices/vcvs.sym} 310 390 0 0 {name=E2 value=-0.5} +C {devices/vsource.sym} 50 510 0 0 {name=Vdm value="ac 1" savecurrent=false} +C {devices/vsource.sym} 230 510 0 0 {name=Vcm value=CACE\{vcm\} savecurrent=false} +C {devices/gnd.sym} 50 560 0 0 {name=l5 lab=GND} +C {devices/gnd.sym} 230 560 0 0 {name=l6 lab=GND} +C {devices/gnd.sym} 230 430 0 0 {name=l7 lab=GND} +C {devices/lab_wire.sym} 150 280 0 0 {name=p12 sig_type=std_logic lab=Vp} +C {devices/lab_wire.sym} 310 280 0 0 {name=p13 sig_type=std_logic lab=Vn} +C {devices/lab_wire.sym} 130 70 0 0 {name=p5 sig_type=std_logic lab=VDD} +C {devices/lab_wire.sym} 210 70 0 0 {name=p6 sig_type=std_logic lab=VDD} +C {devices/lab_wire.sym} 450 190 2 1 {name=p9 sig_type=std_logic lab=VSS} +C {sg13g2_cace_ip__ota5t.sym} 460 130 0 0 {name=x1} +C {devices/code_shown.sym} 660 430 0 0 {name=CONTROL +simulator=ngspice +only_toplevel=false +value=" +.control + + + * run ac simulation + ac dec 20 1k 100e6 + + * measure parameters + let vout_mag = abs(v(Vout)) + let vout_phase_margin = phase(v(Vout)) * 180/pi + 180 + meas ac A0 find vout_mag at=1k + meas ac UGF when vout_mag=1 fall=1 + meas ac PM find vout_phase_margin when vout_mag=1 + + echo $&A0 $&ugf $&PM > CACE\{simpath\}/CACE\{filename\}_CACE\{N\}.data +.endc +"} +C {devices/code_shown.sym} 660 50 0 0 { +name=TT_MODELS +only_toplevel=true +value=" +** IHP models +.lib cornerMOSlv.lib CACE\{corner\} +.lib cornerMOShv.lib CACE\{corner\} +.lib cornerHBT.lib hbt_typ +.lib cornerRES.lib res_typ +" +spice_ignore=false + } diff --git a/examples/sg13g2_cace_ip__ota5t/cace/templates/transient.sch b/examples/sg13g2_cace_ip__ota5t/cace/templates/transient.sch new file mode 100644 index 0000000..13340bb --- /dev/null +++ b/examples/sg13g2_cace_ip__ota5t/cace/templates/transient.sch @@ -0,0 +1,113 @@ +v {xschem version=3.4.6 file_version=1.2} +G {} +K {} +V {} +S {} +E {} +N 790 120 790 140 { +lab=Vout} +N 60 160 60 180 { +lab=GND} +N 60 60 60 100 { +lab=VSS} +N 140 160 140 180 { +lab=GND} +N 60 180 60 200 { +lab=GND} +N 140 60 140 100 { +lab=VDD} +N 60 180 140 180 { +lab=GND} +N 220 60 220 100 { +lab=VDD} +N 220 160 220 200 { +lab=Ib} +N 730 120 790 120 { +lab=Vout} +N 730 120 730 290 { +lab=Vout} +N 690 260 690 280 { +lab=Vn} +N 510 260 690 260 { +lab=Vn} +N 510 160 510 260 { +lab=Vn} +N 510 160 540 160 { +lab=Vn} +N 690 340 690 420 { +lab=GND} +N 730 330 730 420 { +lab=GND} +N 710 420 730 420 { +lab=GND} +N 710 420 710 440 { +lab=GND} +N 300 60 300 100 { +lab=Vp} +N 300 160 300 200 { +lab=GND} +N 690 120 730 120 { +lab=Vout} +N 690 420 710 420 { +lab=GND} +C {devices/code_shown.sym} 880 430 0 0 {name=CONTROL only_toplevel=false value=" +.control + + + * Step function applied at time 100ns, save transient data + tran 10n CACE\{Tmax\} + set wr_singlescale + wrdata CACE\{simpath\}/CACE\{filename\}_CACE\{N\}.data V(Vout) V(Vp) +.endc +"} +C {devices/isource.sym} 220 130 0 0 {name=I0 value=CACE\{ib\}} +C {devices/lab_wire.sym} 600 60 0 0 {name=p4 sig_type=std_logic lab=VDD} +C {devices/capa.sym} 790 170 0 0 {name=C1 +m=1 +value=CACE\{cl\} +footprint=1206 +device="ceramic capacitor"} +C {devices/gnd.sym} 790 200 0 0 {name=l2 lab=GND} +C {devices/lab_wire.sym} 540 80 0 0 {name=p5 sig_type=std_logic lab=Vp} +C {devices/lab_wire.sym} 540 160 0 0 {name=p6 sig_type=std_logic lab=Vn} +C {devices/lab_wire.sym} 540 120 0 0 {name=p7 sig_type=std_logic lab=Ib} +C {devices/lab_wire.sym} 790 120 0 1 {name=p8 sig_type=std_logic lab=Vout} +C {devices/vsource.sym} 60 130 0 0 {name=V0 value=0 savecurrent=false} +C {devices/gnd.sym} 60 200 0 0 {name=l3 lab=GND} +C {devices/vsource.sym} 140 130 0 0 {name=V2 value=CACE\{vdd\} savecurrent=false} +C {devices/lab_wire.sym} 60 60 0 0 {name=p9 sig_type=std_logic lab=VSS} +C {devices/lab_wire.sym} 220 200 2 0 {name=p10 sig_type=std_logic lab=Ib} +C {devices/lab_wire.sym} 140 60 0 0 {name=p12 sig_type=std_logic lab=VDD} +C {devices/lab_wire.sym} 220 60 0 0 {name=p13 sig_type=std_logic lab=VDD} +C {devices/lab_wire.sym} 600 180 2 1 {name=p14 sig_type=std_logic lab=VSS} +C {sg13g2_cace_ip__ota5t.sym} 610 120 0 0 {name=x2} +C {devices/vcvs.sym} 690 310 0 1 {name=Evdrv1 value=1} +C {devices/vsource.sym} 300 130 0 0 {name=V3 value="DC 0 PWL(0 0 100n 0 100.1n CACE\{vdd\})" savecurrent=false} +C {devices/gnd.sym} 710 440 0 0 {name=l4 lab=GND} +C {devices/lab_wire.sym} 300 60 0 0 {name=p15 sig_type=std_logic lab=Vp} +C {devices/gnd.sym} 300 200 0 0 {name=l5 lab=GND} +C {devices/code_shown.sym} 880 220 0 0 {name=SETUP +simulator=ngspice +only_toplevel=false +value=" +.include CACE\{DUT_path\} + +.temp CACE\{temperature\} + +.option SEED=CACE[CACE\{seed=12345\} + CACE\{iterations=0\}] + +* Flag unsafe operating conditions (exceeds models' specified limits) +.option warn=1 +"} +C {devices/code_shown.sym} 880 50 0 0 { +name=TT_MODELS +only_toplevel=true +value=" +** IHP models +.lib cornerMOSlv.lib CACE\{corner\} +.lib cornerMOShv.lib CACE\{corner\} +.lib cornerHBT.lib hbt_typ +.lib cornerRES.lib res_typ +" +spice_ignore=false + } diff --git a/examples/sg13g2_cace_ip__ota5t/cace/templates/xschemrc b/examples/sg13g2_cace_ip__ota5t/cace/templates/xschemrc new file mode 100644 index 0000000..589dc42 --- /dev/null +++ b/examples/sg13g2_cace_ip__ota5t/cace/templates/xschemrc @@ -0,0 +1,10 @@ +# Source the PDK xschemrc file +if {![info exists PDK]} { + source $env(PDK_ROOT)/$env(PDK)/libs.tech/xschem/xschemrc +} + +# Add current directory +append XSCHEM_LIBRARY_PATH :[file dirname [info script]] + +# Source project xschemrc +source [file dirname [info script]]/../../xschem/xschemrc diff --git a/examples/sg13g2_cace_ip__ota5t/gds/sg13g2_cace_ip__ota5t.gds b/examples/sg13g2_cace_ip__ota5t/gds/sg13g2_cace_ip__ota5t.gds new file mode 100644 index 0000000..58fd46a Binary files /dev/null and b/examples/sg13g2_cace_ip__ota5t/gds/sg13g2_cace_ip__ota5t.gds differ diff --git a/examples/sg13g2_cace_ip__ota5t/xschem/sg13g2_cace_ip__ota5t.sch b/examples/sg13g2_cace_ip__ota5t/xschem/sg13g2_cace_ip__ota5t.sch new file mode 100644 index 0000000..6782ee9 --- /dev/null +++ b/examples/sg13g2_cace_ip__ota5t/xschem/sg13g2_cace_ip__ota5t.sch @@ -0,0 +1,142 @@ +v {xschem version=3.4.6 file_version=1.2} +G {} +K {} +V {} +S {} +E {} +N 220 220 220 280 { +lab=#net1} +N 280 170 340 170 { +lab=#net1} +N 280 170 280 220 { +lab=#net1} +N 220 220 280 220 { +lab=#net1} +N 380 240 380 280 { +lab=Vout} +N 220 340 220 370 { +lab=node} +N 220 370 300 370 { +lab=node} +N 300 370 300 400 { +lab=node} +N 300 370 380 370 { +lab=node} +N 380 340 380 370 { +lab=node} +N 180 430 260 430 { +lab=Ib} +N 120 380 180 380 { +lab=Ib} +N 180 380 180 430 { +lab=Ib} +N 120 460 120 500 { +lab=VSS} +N 300 460 300 500 { +lab=VSS} +N 300 500 380 500 { +lab=VSS} +N 220 100 380 100 { +lab=VDD} +N 380 100 380 140 { +lab=VDD} +N 220 100 220 140 { +lab=VDD} +N 120 380 120 400 { +lab=Ib} +N 220 310 230 310 { +lab=VSS} +N 380 170 390 170 { +lab=VDD} +N 210 170 220 170 { +lab=VDD} +N 370 310 380 310 { +lab=VSS} +N 300 430 310 430 { +lab=VSS} +N 110 430 120 430 { +lab=VSS} +N 380 240 410 240 { +lab=Vout} +N 260 170 280 170 { +lab=#net1} +N 220 200 220 220 { +lab=#net1} +N 120 360 120 380 { +lab=Ib} +N 160 430 180 430 { +lab=Ib} +N 100 500 120 500 { +lab=VSS} +N 120 500 300 500 { +lab=VSS} +N 100 100 220 100 { +lab=VDD} +N 380 200 380 240 { +lab=Vout} +N 110 430 110 460 {lab=VSS} +N 110 460 120 460 {lab=VSS} +N 310 430 310 460 {lab=VSS} +N 300 460 310 460 {lab=VSS} +N 210 140 210 170 {lab=VDD} +N 210 140 220 140 {lab=VDD} +N 390 140 390 170 {lab=VDD} +N 380 140 390 140 {lab=VDD} +C {devices/ipin.sym} 180 310 0 0 {name=p1 lab=Vp} +C {devices/ipin.sym} 420 310 0 1 {name=p2 lab=Vn} +C {devices/opin.sym} 410 240 0 0 {name=p3 lab=Vout +} +C {devices/iopin.sym} 100 100 0 1 {name=p4 lab=VDD} +C {devices/iopin.sym} 110 500 2 0 {name=p5 lab=VSS} +C {devices/ipin.sym} 120 360 1 0 {name=p6 lab=Ib} +C {devices/lab_wire.sym} 230 310 0 1 {name=p7 sig_type=std_logic lab=VSS} +C {devices/lab_wire.sym} 370 310 0 0 {name=p11 sig_type=std_logic lab=VSS} +C {devices/lab_wire.sym} 300 370 0 1 {name=p17 sig_type=std_logic lab=node} +C {sg13g2_pr/sg13_lv_nmos.sym} 280 430 0 0 {name=M10 +l=1u +w=2u +ng=2 +m=1 +model=sg13_lv_nmos +spiceprefix=X +} +C {sg13g2_pr/sg13_lv_pmos.sym} 360 170 0 0 {name=M11 +l=1u +w=2u +ng=2 +m=1 +model=sg13_lv_pmos +spiceprefix=X +} +C {sg13g2_pr/sg13_lv_nmos.sym} 140 430 0 1 {name=M1 +l=1u +w=2u +ng=2 +m=1 +model=sg13_lv_nmos +spiceprefix=X +} +C {sg13g2_pr/sg13_lv_pmos.sym} 240 170 0 1 {name=M2 +l=1u +w=2u +ng=2 +m=1 +model=sg13_lv_pmos +spiceprefix=X +} +C {sg13g2_pr/sg13_lv_nmos.sym} 400 310 0 1 {name=M3 +l=0.5u +w=20u +ng=4 +m=1 +model=sg13_lv_nmos +spiceprefix=X +} +C {sg13g2_pr/sg13_lv_nmos.sym} 200 310 0 0 {name=M4 +l=0.5u +w=20u +ng=4 +m=1 +model=sg13_lv_nmos +spiceprefix=X +} diff --git a/examples/sg13g2_cace_ip__ota5t/xschem/sg13g2_cace_ip__ota5t.sym b/examples/sg13g2_cace_ip__ota5t/xschem/sg13g2_cace_ip__ota5t.sym new file mode 100644 index 0000000..aed13b6 --- /dev/null +++ b/examples/sg13g2_cace_ip__ota5t/xschem/sg13g2_cace_ip__ota5t.sym @@ -0,0 +1,33 @@ +v {xschem version=3.4.5 file_version=1.2 +} +G {} +K {type=subcircuit +format="@name @pinlist @symname" +template="name=x1" +} +V {} +S {} +E {} +L 4 60 0 80 0 {} +L 4 -70 -40 -50 -40 {} +L 4 -70 40 -50 40 {} +L 4 -70 0 -50 0 {} +L 4 -50 -60 -50 60 {} +L 4 -50 -60 60 0 {} +L 4 -50 60 60 0 {} +L 7 -10 -60 -10 -40 {} +L 7 -10 40 -10 60 {} +B 5 -72.5 -42.5 -67.5 -37.5 {name=Vp dir=in} +B 5 -72.5 37.5 -67.5 42.5 {name=Vn dir=in} +B 5 77.5 -2.5 82.5 2.5 {name=Vout dir=out} +B 5 -12.5 -62.5 -7.5 -57.5 {name=VDD dir=inout} +B 5 -12.5 57.5 -7.5 62.5 {name=VSS dir=inout} +B 5 -72.5 -2.5 -67.5 2.5 {name=Ib dir=in} +T {@symname} -25 -6 0 0 0.2 0.2 {} +T {@name} 35 -32 0 0 0.2 0.2 {} +T {VDD} -14 -35 3 1 0.2 0.2 {} +T {Vout} 45 -4 0 1 0.2 0.2 {} +T {Vp} -45 -44 0 0 0.2 0.2 {} +T {Vn} -45 36 0 0 0.2 0.2 {} +T {Ib} -45 -4 0 0 0.2 0.2 {} +T {VSS} -6 35 1 1 0.2 0.2 {} diff --git a/examples/sg13g2_cace_ip__ota5t/xschem/sg13g2_cace_ip__ota5t_tb.sch b/examples/sg13g2_cace_ip__ota5t/xschem/sg13g2_cace_ip__ota5t_tb.sch new file mode 100644 index 0000000..1cebc89 --- /dev/null +++ b/examples/sg13g2_cace_ip__ota5t/xschem/sg13g2_cace_ip__ota5t_tb.sch @@ -0,0 +1,187 @@ +v {xschem version=3.4.6 file_version=1.2} +G {} +K {} +V {} +S {} +E {} +B 2 60 660 860 1060 {flags=graph +y1=-19 +y2=22 +ypos1=0 +ypos2=2 +divy=5 +subdivy=4 +unity=1 +x1=3 +x2=8 +divx=5 +subdivx=1 +xlabmag=1.0 +ylabmag=1.0 + + +dataset=-1 +unitx=1 +logx=1 +logy=0 +color=4 +node="\\"Vout db20()\\""} +B 2 60 1060 860 1460 {flags=graph +y1=-92 +y2=-0.06 +ypos1=0 +ypos2=2 +divy=5 +subdivy=1 +unity=1 +x1=3 +x2=8 +divx=5 +subdivx=1 +xlabmag=1.0 +ylabmag=1.0 +node="ph(Vout)" +color="" +dataset=-1 +unitx=1 +logx=1 +logy=0 +} +T {tcleval(A0: [to_eng [xschem raw value A0 0]] +UGF: [to_eng [xschem raw value ugf 0]] +PM: [to_eng [xschem raw value pm 0]])} 950 1020 0 0 0.6 0.6 {floater=1} +N 540 130 560 130 { +lab=Vout} +N 560 130 560 150 { +lab=Vout} +N 50 170 50 190 { +lab=GND} +N 50 70 50 110 { +lab=VSS} +N 130 170 130 190 { +lab=GND} +N 50 190 50 210 { +lab=GND} +N 130 70 130 110 { +lab=VDD} +N 50 190 130 190 { +lab=GND} +N 210 70 210 110 { +lab=VDD} +N 210 170 210 210 { +lab=Ib} +N 230 370 270 370 { +lab=#net1} +N 50 320 50 480 { +lab=#net1} +N 50 320 230 320 { +lab=#net1} +N 50 540 50 560 { +lab=GND} +N 230 540 230 560 { +lab=GND} +N 230 460 310 460 { +lab=#net2} +N 230 460 230 480 { +lab=#net2} +N 230 410 270 410 { +lab=GND} +N 230 410 230 430 { +lab=GND} +N 150 420 150 460 { +lab=#net2} +N 310 420 310 460 { +lab=#net2} +N 230 320 230 370 { +lab=#net1} +N 310 280 310 360 { +lab=Vn} +N 150 280 150 360 { +lab=Vp} +N 150 460 230 460 { +lab=#net2} +N 190 410 230 410 { +lab=GND} +N 190 370 230 370 { +lab=#net1} +C {devices/isource.sym} 210 140 0 0 {name=I0 value=10u} +C {devices/lab_wire.sym} 450 70 0 0 {name=p2 sig_type=std_logic lab=VDD} +C {devices/capa.sym} 560 180 0 0 {name=C1 +m=1 +value=1p} +C {devices/gnd.sym} 560 210 0 0 {name=l2 lab=GND} +C {devices/lab_wire.sym} 390 90 0 0 {name=p3 sig_type=std_logic lab=Vp} +C {devices/lab_wire.sym} 390 170 0 0 {name=p4 sig_type=std_logic lab=Vn} +C {devices/lab_wire.sym} 390 130 0 0 {name=p7 sig_type=std_logic lab=Ib} +C {devices/code_shown.sym} 960 310 0 0 {name=COMMANDS +simulator=ngspice +only_toplevel=false +value=" +.param vdd=1.5 +.param vcm=0.75 + +.control + + save all + + * operating point + op + + write sg13g2_cace_ip__ota5t_tb.raw + set appendwrite + + * run ac simulation + ac dec 20 1k 100e6 + + * measure parameters + let vout_mag = abs(v(Vout)) + let vout_phase_margin = phase(v(Vout)) * 180/pi + 180 + meas ac A0 find vout_mag at=1k + meas ac UGF when vout_mag=1 fall=1 + meas ac PM find vout_phase_margin when vout_mag=1 + + write sg13g2_cace_ip__ota5t_tb.raw +.endc +"} +C {devices/launcher.sym} 460 550 0 0 {name=h26 +descr="Annotate OP" +tclcommand="set show_hidden_texts 1; xschem annotate_op" +} +C {devices/launcher.sym} 460 610 0 0 {name=h27 +descr="Load waves AC" +tclcommand=" +xschem raw_read $netlist_dir/[file tail [file rootname [xschem get current_name]]].raw ac + +" +} +C {devices/lab_wire.sym} 560 130 0 1 {name=p11 sig_type=std_logic lab=Vout} +C {sg13g2_cace_ip__ota5t.sym} 460 130 0 0 {name=x1} +C {devices/vsource.sym} 50 140 0 0 {name=V0 value=0 savecurrent=false} +C {devices/gnd.sym} 50 210 0 0 {name=l3 lab=GND} +C {devices/vsource.sym} 130 140 0 0 {name=V2 value=\{vdd\} savecurrent=false} +C {devices/lab_wire.sym} 50 70 0 0 {name=p1 sig_type=std_logic lab=VSS} +C {devices/lab_wire.sym} 210 210 2 0 {name=p8 sig_type=std_logic lab=Ib} +C {devices/vcvs.sym} 150 390 0 1 {name=E1 value=0.5} +C {devices/vcvs.sym} 310 390 0 0 {name=E2 value=-0.5} +C {devices/vsource.sym} 50 510 0 0 {name=Vdm value="ac 1" savecurrent=false} +C {devices/vsource.sym} 230 510 0 0 {name=Vcm value=\{vcm\} savecurrent=false} +C {devices/gnd.sym} 50 560 0 0 {name=l5 lab=GND} +C {devices/gnd.sym} 230 560 0 0 {name=l6 lab=GND} +C {devices/gnd.sym} 230 430 0 0 {name=l7 lab=GND} +C {devices/lab_wire.sym} 150 280 0 0 {name=p12 sig_type=std_logic lab=Vp} +C {devices/lab_wire.sym} 310 280 0 0 {name=p13 sig_type=std_logic lab=Vn} +C {devices/lab_wire.sym} 130 70 0 0 {name=p5 sig_type=std_logic lab=VDD} +C {devices/lab_wire.sym} 210 70 0 0 {name=p6 sig_type=std_logic lab=VDD} +C {devices/lab_wire.sym} 450 190 2 1 {name=p9 sig_type=std_logic lab=VSS} +C {devices/code_shown.sym} 930 70 0 0 { +name=TT_MODELS +only_toplevel=true +value=" +** IHP models +.lib cornerMOSlv.lib mos_tt +.lib cornerMOShv.lib mos_tt +.lib cornerHBT.lib hbt_typ +.lib cornerRES.lib res_typ +" +spice_ignore=false + } diff --git a/examples/sg13g2_cace_ip__ota5t/xschem/xschemrc b/examples/sg13g2_cace_ip__ota5t/xschem/xschemrc new file mode 100644 index 0000000..f74e994 --- /dev/null +++ b/examples/sg13g2_cace_ip__ota5t/xschem/xschemrc @@ -0,0 +1,31 @@ +# Set default PDK_ROOT +if { ![info exists env(PDK_ROOT)] } { + puts stderr "Warning: PDK_ROOT env. var. not found or empty, trying to find an open_pdks install" + if {[file isdir /usr/share/pdk]} {set ::env(PDK_ROOT) /usr/share/pdk + } elseif {[file isdir /usr/local/share/pdk]} {set ::env(PDK_ROOT) /usr/local/share/pdk + } elseif {[file isdir $env(HOME)/share/pdk]} {set ::env(PDK_ROOT) $env(HOME)/share/pdk + } elseif {[file isdir $env(HOME)/.ciel]} {set ::env(PDK_ROOT) $env(HOME)/.ciel + } elseif {[file isdir $env(HOME)/.volare]} {set ::env(PDK_ROOT) $env(HOME)/.volare + } else { + puts stderr {No open_pdks installation found, set PDK_ROOT env. var. and restart xschem} + } +} + +# Set default PDK +if { ![info exists env(PDK)] } { + set ::env(PDK) ihp-sg13g2 +} + +# Source the PDK xschemrc file +if {![info exists PDK]} { + source $env(PDK_ROOT)/$env(PDK)/libs.tech/xschem/xschemrc +} + +# Add current directory to xschem library path +append XSCHEM_LIBRARY_PATH :[file dirname [info script]] + +# Source the dependencies xschemrc files +foreach rcfile [glob -nocomplain ../ip/*/xschem/xschemrc] { + puts "sourcing $rcfile" + source $rcfile +} diff --git a/examples/sky130_cace_ip__ota5t/LICENSE b/examples/sky130_cace_ip__ota5t/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/examples/sky130_cace_ip__ota5t/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/examples/sky130_cace_ip__ota5t/README.md b/examples/sky130_cace_ip__ota5t/README.md new file mode 100644 index 0000000..983cd9f --- /dev/null +++ b/examples/sky130_cace_ip__ota5t/README.md @@ -0,0 +1,36 @@ +# A simple 5-transistor OTA ![](../../workflows/cace/badge.svg) + +This example showcases how to setup a project for [CACE](https://github.com/fossi-foundation/cace). + +- [Documentation](docs/sky130_cace_ip__ota5t.md) +- [Characterization](docs/sky130_cace_ip__ota5t_rcx.md) + +# Repository Structure + +Besides the normal directories such as `xschem/` for the schematic and testbench and `gds/` for the layout, there is also the `cace/` subdirectory. +Here you will find the CACE datasheet for this project named `sky130_cace_ip__ota5t.yaml`, which contains the specification for the design and represents the configuration for CACE. + +In the `templates/` subdirectory you will find some xschem testbench. These are not a normal testbenches, but instead acts as templates for CACE. +They contain placeholders for various conditions such as `CACE{temperature}` or `CACE{corner}`, which will get substituted by CACE to generate the final simulation testbenches. + +The subdirectory `scripts/` contains all user-defined scripts, in this case a custom script `run_project_lvs.tcl` to run LVS. + +# Run CACE + +After you have installed CACE and all dependencies, invoking the characterization of this project is as easy as running: + +```console +cace +``` + +This will use the "best" netlist available. Since a layout is provided, the netlist source will be "rcx" (R-C-extracted). To perform characterization on a different netlist, pass the `--source` argument to cace. For help on arguments, run `cace --help`. + +After characterization is completed, you will find the simulation files, log files and reports under `run/TIMESTAMP/`, where TIMESTAMP is the time and date when cace was started. + +# Continuous Integration + +This project also demonstrates how CACE can be used for continuous integration. Under `.github/workflows/` you will find the `cace.yml` GitHub action. It makes use of the composite action [cace-action](https://github.com/mole99/cace-action). + +First, the environment is set up and CACE is started. Then the `run/` directory is uploaded so that it can be viewed later. Finally, the summary is added to the step overview. + +Take a look at the latest runs under [actions](https://github.com/mole99/sky130_cace_ip__ota5t/actions). If you are logged in to GitHub, you can also click on a run and view the summary. diff --git a/examples/sky130_cace_ip__ota5t/cace/scripts/run_project_lvs.tcl b/examples/sky130_cace_ip__ota5t/cace/scripts/run_project_lvs.tcl new file mode 100644 index 0000000..36c71be --- /dev/null +++ b/examples/sky130_cace_ip__ota5t/cace/scripts/run_project_lvs.tcl @@ -0,0 +1,15 @@ +# NOTE: PDK_ROOT, PDK and CACE_ROOT are set in the local environment by CACE +# +# This is an example script to drive LVS; because this is a simple +# example, there is no specific benefit of using this instead of the +# default handling in CACE. + +set PDK_ROOT $::env(PDK_ROOT) +set PDK $::env(PDK) +set CACE_ROOT $::env(CACE_ROOT) +set TOP sky130_cace_ip__ota5t + +set circuit1 [readnet spice $CACE_ROOT/netlist/layout/$TOP.spice] +set circuit2 [readnet spice $CACE_ROOT/netlist/schematic/$TOP.spice] + +lvs "$circuit1 $TOP" "$circuit2 $TOP" $PDK_ROOT/$PDK/libs.tech/netgen/${PDK}_setup.tcl ${TOP}_comp.out -json diff --git a/examples/sky130_cace_ip__ota5t/cace/sky130_cace_ip__ota5t.yaml b/examples/sky130_cace_ip__ota5t/cace/sky130_cace_ip__ota5t.yaml new file mode 100644 index 0000000..28b0ee4 --- /dev/null +++ b/examples/sky130_cace_ip__ota5t/cace/sky130_cace_ip__ota5t.yaml @@ -0,0 +1,347 @@ +#-------------------------------------------------------------- +# CACE circuit characterization file +#-------------------------------------------------------------- + +name: sky130_cace_ip__ota5t +description: A simple 5-transistor OTA +PDK: sky130A + +cace_format: 5.2 + +authorship: + designer: Leo Moser + creation_date: May 27, 2024 + license: Apache 2.0 + +paths: + root: .. + schematic: xschem + layout: gds + netlist: netlist + documentation: docs + +pins: + VDD: + description: Positive analog power supply + type: power + direction: inout + Vmin: 1.7 + Vmax: 1.9 + VSS: + description: Analog ground + type: ground + direction: inout + Ib: + description: Bias current input + type: signal + direction: input + Vp: + description: Voltage positive input + type: signal + direction: input + Vn: + description: Voltage negative input + type: signal + direction: input + Vout: + description: Voltage output + type: signal + direction: output + +default_conditions: + vdd: + description: Analog power supply voltage + display: Vdd + unit: V + typical: 1.8 + vcm: + description: Input common mode voltage + display: Vcm + unit: V + typical: 0.9 + ib: + description: Bias current + display: Ib + unit: uA + typical: 10 + cl: + description: Output load capacitance + display: CLoad + unit: pF + maximum: 1 + corner: + description: Process corner + display: Corner + typical: tt + temperature: + description: Ambient temperature + display: Temp + unit: °C + typical: 27 + +parameters: + dc_params: + display: DC Params + spec: + a0: + display: DC gain + description: The DC gain of the OTA + unit: V/V + minimum: + value: 50 + typical: + value: any + maximum: + value: any + ugf: + display: Unity Gain Frequency + description: The unity gain frequency of the OTA + unit: Hz + minimum: + value: 1e6 + typical: + value: any + maximum: + value: any + pm: + display: Phase Margin + description: The phase margin of the OTA + unit: ° + minimum: + value: 60 + typical: + value: any + maximum: + value: any + tool: + ngspice: + template: ac.sch + format: ascii + suffix: .data + variables: [a0, ugf, pm] + plot: + gain_vs_temp: + type: xyplot + xaxis: temperature + yaxis: a0 + limits: auto + ugf_vs_corner: + type: xyplot + xaxis: corner + yaxis: ugf + limits: true + pm_vs_vdd: + type: xyplot + xaxis: vdd + yaxis: pm + limits: false + conditions: + corner: + enumerate: [ss, tt, ff] + vdd: + minimum: 1.7 + typical: 1.8 + maximum: 1.9 + temperature: + minimum: -40 + typical: 27 + maximum: 130 + + gain_mc: + description: DC gain Monte Carlo + display: DC gain MC + unit: V/V + spec: + a0: + minimum: + value: 50 + typical: + value: any + maximum: + value: any + tool: + ngspice: + template: ac.sch + # Merge runs with the same conditions + # but different iterations + # This is used for plotting + collate: iterations + format: ascii + suffix: .data + variables: [a0, null, null] + plot: + gain_mc: + type: histogram + xaxis: a0 + limits: auto + conditions: + iterations: + description: Iterations to run + display: Iterations + minimum: 1 + maximum: 10 + step: linear + stepsize: 1 + corner: + typical: mc + temperature: + minimum: -40 + typical: 27 + maximum: 130 + + transient_response: + description: Large signal transient response + display: Large signal transient response + status: skip + unit: mV + tool: + ngspice: + template: transient.sch + format: ascii + suffix: .data + variables: [time, Vout, Vinp] + jobs: 4 + plot: + transient: + suffix: .svg + xaxis: time + yaxis: [Vout, Vinp] + variables: + time: + display: Time + unit: ms + Vinp: + display: Vinp + unit: V + Vout: + display: Vout + unit: V + conditions: + Tmax: + display: Simulation time + unit: ns + typical: 500 + temperature: + minimum: -40 + typical: 27 + maximum: 130 + corner: + minimum: ss + typical: tt + maximum: ff + + magic_area: + spec: + area: + display: Area + description: Total circuit layout area + unit: µm² + maximum: + value: 600 + width: + display: Width + description: Total circuit layout width + unit: µm + maximum: + value: any + height: + display: Height + description: Total circuit layout height + unit: µm + maximum: + value: any + tool: + magic_area + + magic_drc: + description: Magic DRC + display: Magic DRC + spec: + drc_errors: + maximum: + value: 0 + tool: + magic_drc: + gds_flatten: true + + netgen_lvs: + description: Netgen LVS + display: Netgen LVS + spec: + lvs_errors: + maximum: + value: 0 + tool: + netgen_lvs: + script: run_project_lvs.tcl + + klayout_drc_feol: + description: KLayout DRC feol + display: KLayout DRC feol + spec: + drc_errors: + maximum: + value: 0 + tool: + klayout_drc: + jobs: max + args: ['-rd', 'feol=true'] + + klayout_drc_beol: + description: KLayout DRC beol + display: KLayout DRC beol + spec: + drc_errors: + maximum: + value: 0 + tool: + klayout_drc: + jobs: max + args: ['-rd', 'beol=true'] + + klayout_drc_full: + description: KLayout DRC full + display: KLayout DRC full + spec: + drc_errors: + maximum: + value: 0 + tool: + klayout_drc: + jobs: max + args: ['-rd', 'feol=true', '-rd', 'beol=true', '-rd', 'offgrid=true'] + + klayout_lvs: + description: KLayout LVS + display: KLayout LVS + spec: + lvs_errors: + maximum: + value: 0 + tool: + klayout_lvs: + jobs: max + args: [ + '-rd', 'spice_net_names=true', + '-rd', 'spice_comments=true', + '-rd', 'scale=true', + '-rd', 'verbose=true', + '-rd', 'schematic_simplify=true', + '-rd', 'net_only=true', + '-rd', 'top_lvl_pins=true', + '-rd', 'combine=true', + '-rd', 'purge=true', + '-rd', 'purge_nets=true', + '-rd', 'lvs_sub=VSS', + '-rd', 'convert_subckts=true', + ] + + magic_antenna_check: + description: Run antenna violation check using magic + display: Antenna Checks + spec: + antenna_violations: + maximum: + value: 0 + tool: + magic_antenna_check diff --git a/examples/sky130_cace_ip__ota5t/cace/templates/ac.sch b/examples/sky130_cace_ip__ota5t/cace/templates/ac.sch new file mode 100644 index 0000000..ac342bd --- /dev/null +++ b/examples/sky130_cace_ip__ota5t/cace/templates/ac.sch @@ -0,0 +1,128 @@ +v {xschem version=3.4.5 file_version=1.2 +} +G {} +K {} +V {} +S {} +E {} +N 540 130 560 130 { +lab=Vout} +N 560 130 560 150 { +lab=Vout} +N 50 170 50 190 { +lab=GND} +N 50 70 50 110 { +lab=VSS} +N 130 170 130 190 { +lab=GND} +N 50 190 50 210 { +lab=GND} +N 130 70 130 110 { +lab=VDD} +N 50 190 130 190 { +lab=GND} +N 210 70 210 110 { +lab=VDD} +N 210 170 210 190 { +lab=Ib} +N 210 190 210 210 { +lab=Ib} +N 230 370 270 370 { +lab=#net1} +N 50 320 50 480 { +lab=#net1} +N 50 320 230 320 { +lab=#net1} +N 50 540 50 560 { +lab=GND} +N 230 540 230 560 { +lab=GND} +N 230 460 310 460 { +lab=#net2} +N 230 460 230 480 { +lab=#net2} +N 230 410 270 410 { +lab=GND} +N 230 410 230 430 { +lab=GND} +N 150 420 150 460 { +lab=#net2} +N 310 420 310 460 { +lab=#net2} +N 230 320 230 370 { +lab=#net1} +N 310 280 310 360 { +lab=Vn} +N 150 280 150 360 { +lab=Vp} +N 150 460 230 460 { +lab=#net2} +N 190 410 230 410 { +lab=GND} +N 190 370 230 370 { +lab=#net1} +C {devices/isource.sym} 210 140 0 0 {name=I0 value=CACE\{ib\}} +C {devices/lab_wire.sym} 450 70 0 0 {name=p2 sig_type=std_logic lab=VDD} +C {devices/capa.sym} 560 180 0 0 {name=C1 +m=1 +value=CACE\{cl\} +footprint=1206 +device="ceramic capacitor"} +C {devices/gnd.sym} 560 210 0 0 {name=l2 lab=GND} +C {devices/lab_wire.sym} 390 90 0 0 {name=p3 sig_type=std_logic lab=Vp} +C {devices/lab_wire.sym} 390 170 0 0 {name=p4 sig_type=std_logic lab=Vn} +C {devices/lab_wire.sym} 390 130 0 0 {name=p7 sig_type=std_logic lab=Ib} +C {devices/code_shown.sym} 660 90 0 0 {name=SETUP +simulator=ngspice +only_toplevel=false +value=" +.lib CACE\{PDK_ROOT\}/CACE\{PDK\}/libs.tech/combined/sky130.lib.spice CACE\{corner\} + +.include CACE\{DUT_path\} + +.temp CACE\{temperature\} + +.option SEED=CACE[CACE\{seed=12345\} + CACE\{iterations=0\}] + +* Flag unsafe operating conditions (exceeds models' specified limits) +.option warn=1 +"} +C {devices/lab_wire.sym} 560 130 0 1 {name=p11 sig_type=std_logic lab=Vout} +C {devices/vsource.sym} 50 140 0 0 {name=V0 value=0 savecurrent=false} +C {devices/gnd.sym} 50 210 0 0 {name=l3 lab=GND} +C {devices/vsource.sym} 130 140 0 0 {name=V2 value=CACE\{vdd\} savecurrent=false} +C {devices/lab_wire.sym} 50 70 0 0 {name=p1 sig_type=std_logic lab=VSS} +C {devices/lab_wire.sym} 210 210 2 0 {name=p8 sig_type=std_logic lab=Ib} +C {devices/vcvs.sym} 150 390 0 1 {name=E1 value=0.5} +C {devices/vcvs.sym} 310 390 0 0 {name=E2 value=-0.5} +C {devices/vsource.sym} 50 510 0 0 {name=Vdm value="ac 1" savecurrent=false} +C {devices/vsource.sym} 230 510 0 0 {name=Vcm value=CACE\{vcm\} savecurrent=false} +C {devices/gnd.sym} 50 560 0 0 {name=l5 lab=GND} +C {devices/gnd.sym} 230 560 0 0 {name=l6 lab=GND} +C {devices/gnd.sym} 230 430 0 0 {name=l7 lab=GND} +C {devices/lab_wire.sym} 150 280 0 0 {name=p12 sig_type=std_logic lab=Vp} +C {devices/lab_wire.sym} 310 280 0 0 {name=p13 sig_type=std_logic lab=Vn} +C {devices/lab_wire.sym} 130 70 0 0 {name=p5 sig_type=std_logic lab=VDD} +C {devices/lab_wire.sym} 210 70 0 0 {name=p6 sig_type=std_logic lab=VDD} +C {devices/lab_wire.sym} 450 190 2 1 {name=p9 sig_type=std_logic lab=VSS} +C {sky130_cace_ip__ota5t.sym} 460 130 0 0 {name=x1} +C {devices/code_shown.sym} 660 340 0 0 {name=CONTROL +simulator=ngspice +only_toplevel=false +value=" +.control + + + * run ac simulation + ac dec 20 1k 100e6 + + * measure parameters + let vout_mag = abs(v(Vout)) + let vout_phase_margin = phase(v(Vout)) * 180/pi + 180 + meas ac A0 find vout_mag at=1k + meas ac UGF when vout_mag=1 fall=1 + meas ac PM find vout_phase_margin when vout_mag=1 + + echo $&A0 $&ugf $&PM > CACE\{simpath\}/CACE\{filename\}_CACE\{N\}.data +.endc +"} diff --git a/examples/sky130_cace_ip__ota5t/cace/templates/transient.sch b/examples/sky130_cace_ip__ota5t/cace/templates/transient.sch new file mode 100644 index 0000000..aae3e09 --- /dev/null +++ b/examples/sky130_cace_ip__ota5t/cace/templates/transient.sch @@ -0,0 +1,104 @@ +v {xschem version=3.4.5 file_version=1.2 +} +G {} +K {} +V {} +S {} +E {} +N 770 120 790 120 { +lab=Vout} +N 790 120 790 140 { +lab=Vout} +N 60 160 60 180 { +lab=GND} +N 60 60 60 100 { +lab=VSS} +N 140 160 140 180 { +lab=GND} +N 60 180 60 200 { +lab=GND} +N 140 60 140 100 { +lab=VDD} +N 60 180 140 180 { +lab=GND} +N 220 60 220 100 { +lab=VDD} +N 220 160 220 180 { +lab=Ib} +N 220 180 220 200 { +lab=Ib} +N 690 120 770 120 { +lab=Vout} +N 730 120 730 290 { +lab=Vout} +N 690 260 690 280 { +lab=Vn} +N 510 260 690 260 { +lab=Vn} +N 510 160 510 260 { +lab=Vn} +N 510 160 540 160 { +lab=Vn} +N 690 340 690 420 { +lab=GND} +N 730 330 730 420 { +lab=GND} +N 690 420 730 420 { +lab=GND} +N 710 420 710 440 { +lab=GND} +N 300 60 300 100 { +lab=Vp} +N 300 160 300 200 { +lab=GND} +C {devices/code_shown.sym} 880 320 0 0 {name=CONTROL only_toplevel=false value=" +.control + + + * Step function applied at time 100ns, save transient data + tran 10n CACE\{Tmax\} + set wr_singlescale + wrdata CACE\{simpath\}/CACE\{filename\}_CACE\{N\}.data V(Vout) V(Vp) +.endc +"} +C {devices/isource.sym} 220 130 0 0 {name=I0 value=CACE\{ib\}} +C {devices/lab_wire.sym} 600 60 0 0 {name=p4 sig_type=std_logic lab=VDD} +C {devices/capa.sym} 790 170 0 0 {name=C1 +m=1 +value=CACE\{cl\} +footprint=1206 +device="ceramic capacitor"} +C {devices/gnd.sym} 790 200 0 0 {name=l2 lab=GND} +C {devices/lab_wire.sym} 540 80 0 0 {name=p5 sig_type=std_logic lab=Vp} +C {devices/lab_wire.sym} 540 160 0 0 {name=p6 sig_type=std_logic lab=Vn} +C {devices/lab_wire.sym} 540 120 0 0 {name=p7 sig_type=std_logic lab=Ib} +C {devices/lab_wire.sym} 790 120 0 1 {name=p8 sig_type=std_logic lab=Vout} +C {devices/vsource.sym} 60 130 0 0 {name=V0 value=0 savecurrent=false} +C {devices/gnd.sym} 60 200 0 0 {name=l3 lab=GND} +C {devices/vsource.sym} 140 130 0 0 {name=V2 value=CACE\{vdd\} savecurrent=false} +C {devices/lab_wire.sym} 60 60 0 0 {name=p9 sig_type=std_logic lab=VSS} +C {devices/lab_wire.sym} 220 200 2 0 {name=p10 sig_type=std_logic lab=Ib} +C {devices/lab_wire.sym} 140 60 0 0 {name=p12 sig_type=std_logic lab=VDD} +C {devices/lab_wire.sym} 220 60 0 0 {name=p13 sig_type=std_logic lab=VDD} +C {devices/lab_wire.sym} 600 180 2 1 {name=p14 sig_type=std_logic lab=VSS} +C {sky130_cace_ip__ota5t.sym} 610 120 0 0 {name=x2} +C {devices/vcvs.sym} 690 310 0 1 {name=Evdrv1 value=1} +C {devices/vsource.sym} 300 130 0 0 {name=V3 value="DC 0 PWL(0 0 100n 0 100.1n CACE\{vdd\})" savecurrent=false} +C {devices/gnd.sym} 710 440 0 0 {name=l4 lab=GND} +C {devices/lab_wire.sym} 300 60 0 0 {name=p15 sig_type=std_logic lab=Vp} +C {devices/gnd.sym} 300 200 0 0 {name=l5 lab=GND} +C {devices/code_shown.sym} 880 60 0 0 {name=SETUP +simulator=ngspice +only_toplevel=false +value=" +.lib CACE\{PDK_ROOT\}/CACE\{PDK\}/libs.tech/combined/sky130.lib.spice CACE\{corner\} + +.include CACE\{DUT_path\} + +.temp CACE\{temperature\} + +.option SEED=CACE[CACE\{seed=12345\} + CACE\{iterations=0\}] + +* Flag unsafe operating conditions (exceeds models' specified limits) +.option warn=1 +"} diff --git a/examples/sky130_cace_ip__ota5t/cace/templates/xschemrc b/examples/sky130_cace_ip__ota5t/cace/templates/xschemrc new file mode 100644 index 0000000..589dc42 --- /dev/null +++ b/examples/sky130_cace_ip__ota5t/cace/templates/xschemrc @@ -0,0 +1,10 @@ +# Source the PDK xschemrc file +if {![info exists PDK]} { + source $env(PDK_ROOT)/$env(PDK)/libs.tech/xschem/xschemrc +} + +# Add current directory +append XSCHEM_LIBRARY_PATH :[file dirname [info script]] + +# Source project xschemrc +source [file dirname [info script]]/../../xschem/xschemrc diff --git a/examples/sky130_cace_ip__ota5t/gds/sky130_cace_ip__ota5t.gds b/examples/sky130_cace_ip__ota5t/gds/sky130_cace_ip__ota5t.gds new file mode 100644 index 0000000..210ce31 Binary files /dev/null and b/examples/sky130_cace_ip__ota5t/gds/sky130_cace_ip__ota5t.gds differ diff --git a/examples/sky130_cace_ip__ota5t/xschem/sky130_cace_ip__ota5t.sch b/examples/sky130_cace_ip__ota5t/xschem/sky130_cace_ip__ota5t.sch new file mode 100644 index 0000000..e926905 --- /dev/null +++ b/examples/sky130_cace_ip__ota5t/xschem/sky130_cace_ip__ota5t.sch @@ -0,0 +1,261 @@ +v {xschem version=3.4.5 file_version=1.2 +} +G {} +K {} +V {} +S {} +E {} +N 220 200 220 280 { +lab=#net1} +N 260 170 340 170 { +lab=#net1} +N 280 170 280 220 { +lab=#net1} +N 220 220 280 220 { +lab=#net1} +N 380 200 380 280 { +lab=Vout} +N 220 340 220 370 { +lab=node} +N 220 370 300 370 { +lab=node} +N 300 370 300 400 { +lab=node} +N 300 370 380 370 { +lab=node} +N 380 340 380 370 { +lab=node} +N 160 430 260 430 { +lab=Ib} +N 120 380 180 380 { +lab=Ib} +N 180 380 180 430 { +lab=Ib} +N 120 460 120 480 { +lab=VSS} +N 300 460 300 480 { +lab=VSS} +N 220 120 220 140 { +lab=VDD} +N 380 120 380 140 { +lab=VDD} +N 100 500 380 500 { +lab=VSS} +N 120 480 120 500 { +lab=VSS} +N 300 480 300 500 { +lab=VSS} +N 100 100 380 100 { +lab=VDD} +N 380 100 380 120 { +lab=VDD} +N 220 100 220 120 { +lab=VDD} +N 120 360 120 400 { +lab=Ib} +N 220 310 230 310 { +lab=VSS} +N 380 170 390 170 { +lab=VDD} +N 210 170 220 170 { +lab=VDD} +N 370 310 380 310 { +lab=VSS} +N 300 430 310 430 { +lab=VSS} +N 110 430 120 430 { +lab=VSS} +N 380 240 410 240 { +lab=Vout} +N 520 130 520 170 { +lab=VDD} +N 520 170 530 170 { +lab=VDD} +N 570 170 580 170 { +lab=VDD} +N 580 130 580 170 { +lab=VDD} +N 520 130 580 130 { +lab=VDD} +N 570 130 570 140 { +lab=VDD} +N 520 440 530 440 { +lab=VSS} +N 520 440 520 480 { +lab=VSS} +N 520 480 570 480 { +lab=VSS} +N 570 470 570 480 { +lab=VSS} +N 570 440 580 440 { +lab=VSS} +N 580 440 580 480 { +lab=VSS} +N 570 480 580 480 { +lab=VSS} +N 570 400 570 410 { +lab=node} +N 570 200 570 220 { +lab=Vout} +N 520 310 530 310 { +lab=VSS} +N 520 310 520 350 { +lab=VSS} +N 520 350 570 350 { +lab=VSS} +N 570 340 570 350 { +lab=VSS} +N 570 310 580 310 { +lab=VSS} +N 580 310 580 350 { +lab=VSS} +N 570 350 580 350 { +lab=VSS} +N 570 270 570 280 { +lab=node} +C {devices/ipin.sym} 180 310 0 0 {name=p1 lab=Vp} +C {devices/ipin.sym} 420 310 0 1 {name=p2 lab=Vn} +C {devices/opin.sym} 410 240 0 0 {name=p3 lab=Vout +} +C {devices/iopin.sym} 100 100 0 1 {name=p4 lab=VDD} +C {devices/iopin.sym} 110 500 2 0 {name=p5 lab=VSS} +C {devices/ipin.sym} 120 360 1 0 {name=p6 lab=Ib} +C {sky130_fd_pr/nfet_01v8.sym} 200 310 0 0 {name=M4 +L=0.5 +W=20 +nf=4 +mult=1 +ad="'int((nf+1)/2) * W/nf * 0.29'" +pd="'2*int((nf+1)/2) * (W/nf + 0.29)'" +as="'int((nf+2)/2) * W/nf * 0.29'" +ps="'2*int((nf+2)/2) * (W/nf + 0.29)'" +nrd="'0.29 / W'" nrs="'0.29 / W'" +sa=0 sb=0 sd=0 +model=nfet_01v8 +spiceprefix=X +} +C {devices/lab_wire.sym} 230 310 0 1 {name=p7 sig_type=std_logic lab=VSS} +C {sky130_fd_pr/pfet_01v8.sym} 360 170 0 0 {name=M1 +L=1 +W=2 +nf=2 +mult=1 +ad="'int((nf+1)/2) * W/nf * 0.29'" +pd="'2*int((nf+1)/2) * (W/nf + 0.29)'" +as="'int((nf+2)/2) * W/nf * 0.29'" +ps="'2*int((nf+2)/2) * (W/nf + 0.29)'" +nrd="'0.29 / W'" nrs="'0.29 / W'" +sa=0 sb=0 sd=0 +model=pfet_01v8 +spiceprefix=X +} +C {devices/lab_wire.sym} 390 170 0 1 {name=p9 sig_type=std_logic lab=VDD} +C {sky130_fd_pr/pfet_01v8.sym} 240 170 0 1 {name=M2 +L=1 +W=2 +nf=2 +mult=1 +ad="'int((nf+1)/2) * W/nf * 0.29'" +pd="'2*int((nf+1)/2) * (W/nf + 0.29)'" +as="'int((nf+2)/2) * W/nf * 0.29'" +ps="'2*int((nf+2)/2) * (W/nf + 0.29)'" +nrd="'0.29 / W'" nrs="'0.29 / W'" +sa=0 sb=0 sd=0 +model=pfet_01v8 +spiceprefix=X +} +C {devices/lab_wire.sym} 210 170 0 0 {name=p10 sig_type=std_logic lab=VDD} +C {sky130_fd_pr/nfet_01v8.sym} 400 310 0 1 {name=M3 +L=0.5 +W=20 +nf=4 +mult=1 +ad="'int((nf+1)/2) * W/nf * 0.29'" +pd="'2*int((nf+1)/2) * (W/nf + 0.29)'" +as="'int((nf+2)/2) * W/nf * 0.29'" +ps="'2*int((nf+2)/2) * (W/nf + 0.29)'" +nrd="'0.29 / W'" nrs="'0.29 / W'" +sa=0 sb=0 sd=0 +model=nfet_01v8 +spiceprefix=X +} +C {devices/lab_wire.sym} 370 310 0 0 {name=p11 sig_type=std_logic lab=VSS} +C {sky130_fd_pr/nfet_01v8.sym} 280 430 0 0 {name=M5 +L=1 +W=2 +nf=2 +mult=1 +ad="'int((nf+1)/2) * W/nf * 0.29'" +pd="'2*int((nf+1)/2) * (W/nf + 0.29)'" +as="'int((nf+2)/2) * W/nf * 0.29'" +ps="'2*int((nf+2)/2) * (W/nf + 0.29)'" +nrd="'0.29 / W'" nrs="'0.29 / W'" +sa=0 sb=0 sd=0 +model=nfet_01v8 +spiceprefix=X +} +C {devices/lab_wire.sym} 310 430 0 1 {name=p12 sig_type=std_logic lab=VSS} +C {sky130_fd_pr/nfet_01v8.sym} 140 430 0 1 {name=M6 +L=1 +W=2 +nf=2 +mult=1 +ad="'int((nf+1)/2) * W/nf * 0.29'" +pd="'2*int((nf+1)/2) * (W/nf + 0.29)'" +as="'int((nf+2)/2) * W/nf * 0.29'" +ps="'2*int((nf+2)/2) * (W/nf + 0.29)'" +nrd="'0.29 / W'" nrs="'0.29 / W'" +sa=0 sb=0 sd=0 +model=nfet_01v8 +spiceprefix=X +} +C {devices/lab_wire.sym} 110 430 0 0 {name=p13 sig_type=std_logic lab=VSS} +C {sky130_fd_pr/pfet_01v8.sym} 550 170 0 0 {name=M7 +L=1 +W=2 +nf=2 +mult=1 +ad="'int((nf+1)/2) * W/nf * 0.29'" +pd="'2*int((nf+1)/2) * (W/nf + 0.29)'" +as="'int((nf+2)/2) * W/nf * 0.29'" +ps="'2*int((nf+2)/2) * (W/nf + 0.29)'" +nrd="'0.29 / W'" nrs="'0.29 / W'" +sa=0 sb=0 sd=0 +model=pfet_01v8 +spiceprefix=X +} +C {sky130_fd_pr/nfet_01v8.sym} 550 310 0 0 {name=M8 +L=0.5 +W=20 +nf=4 +mult=1 +ad="'int((nf+1)/2) * W/nf * 0.29'" +pd="'2*int((nf+1)/2) * (W/nf + 0.29)'" +as="'int((nf+2)/2) * W/nf * 0.29'" +ps="'2*int((nf+2)/2) * (W/nf + 0.29)'" +nrd="'0.29 / W'" nrs="'0.29 / W'" +sa=0 sb=0 sd=0 +model=nfet_01v8 +spiceprefix=X +} +C {sky130_fd_pr/nfet_01v8.sym} 550 440 0 0 {name=M9 +L=1 +W=2 +nf=2 +mult=1 +ad="'int((nf+1)/2) * W/nf * 0.29'" +pd="'2*int((nf+1)/2) * (W/nf + 0.29)'" +as="'int((nf+2)/2) * W/nf * 0.29'" +ps="'2*int((nf+2)/2) * (W/nf + 0.29)'" +nrd="'0.29 / W'" nrs="'0.29 / W'" +sa=0 sb=0 sd=0 +model=nfet_01v8 +spiceprefix=X +} +C {devices/lab_wire.sym} 580 130 0 1 {name=p8 sig_type=std_logic lab=VDD} +C {devices/lab_wire.sym} 520 480 0 1 {name=p14 sig_type=std_logic lab=VSS} +C {devices/lab_wire.sym} 570 220 0 1 {name=p16 sig_type=std_logic lab=Vout} +C {devices/lab_wire.sym} 300 370 0 1 {name=p17 sig_type=std_logic lab=node} +C {devices/lab_wire.sym} 520 350 0 1 {name=p15 sig_type=std_logic lab=VSS} +C {devices/lab_wire.sym} 570 400 0 1 {name=p19 sig_type=std_logic lab=node} +C {devices/lab_wire.sym} 570 270 0 1 {name=p18 sig_type=std_logic lab=node} diff --git a/examples/sky130_cace_ip__ota5t/xschem/sky130_cace_ip__ota5t.sym b/examples/sky130_cace_ip__ota5t/xschem/sky130_cace_ip__ota5t.sym new file mode 100644 index 0000000..aed13b6 --- /dev/null +++ b/examples/sky130_cace_ip__ota5t/xschem/sky130_cace_ip__ota5t.sym @@ -0,0 +1,33 @@ +v {xschem version=3.4.5 file_version=1.2 +} +G {} +K {type=subcircuit +format="@name @pinlist @symname" +template="name=x1" +} +V {} +S {} +E {} +L 4 60 0 80 0 {} +L 4 -70 -40 -50 -40 {} +L 4 -70 40 -50 40 {} +L 4 -70 0 -50 0 {} +L 4 -50 -60 -50 60 {} +L 4 -50 -60 60 0 {} +L 4 -50 60 60 0 {} +L 7 -10 -60 -10 -40 {} +L 7 -10 40 -10 60 {} +B 5 -72.5 -42.5 -67.5 -37.5 {name=Vp dir=in} +B 5 -72.5 37.5 -67.5 42.5 {name=Vn dir=in} +B 5 77.5 -2.5 82.5 2.5 {name=Vout dir=out} +B 5 -12.5 -62.5 -7.5 -57.5 {name=VDD dir=inout} +B 5 -12.5 57.5 -7.5 62.5 {name=VSS dir=inout} +B 5 -72.5 -2.5 -67.5 2.5 {name=Ib dir=in} +T {@symname} -25 -6 0 0 0.2 0.2 {} +T {@name} 35 -32 0 0 0.2 0.2 {} +T {VDD} -14 -35 3 1 0.2 0.2 {} +T {Vout} 45 -4 0 1 0.2 0.2 {} +T {Vp} -45 -44 0 0 0.2 0.2 {} +T {Vn} -45 36 0 0 0.2 0.2 {} +T {Ib} -45 -4 0 0 0.2 0.2 {} +T {VSS} -6 35 1 1 0.2 0.2 {} diff --git a/examples/sky130_cace_ip__ota5t/xschem/sky130_cace_ip__ota5t_tb.sch b/examples/sky130_cace_ip__ota5t/xschem/sky130_cace_ip__ota5t_tb.sch new file mode 100644 index 0000000..36e08a1 --- /dev/null +++ b/examples/sky130_cace_ip__ota5t/xschem/sky130_cace_ip__ota5t_tb.sch @@ -0,0 +1,187 @@ +v {xschem version=3.4.5 file_version=1.2 +} +G {} +K {} +V {} +S {} +E {} +B 2 60 660 860 1060 {flags=graph +y1=-19 +y2=22 +ypos1=0 +ypos2=2 +divy=5 +subdivy=4 +unity=1 +x1=3 +x2=8 +divx=5 +subdivx=1 +xlabmag=1.0 +ylabmag=1.0 + + +dataset=-1 +unitx=1 +logx=1 +logy=0 +color=4 +node="\\"Vout db20()\\""} +B 2 60 1060 860 1460 {flags=graph +y1=-92 +y2=-0.06 +ypos1=0 +ypos2=2 +divy=5 +subdivy=1 +unity=1 +x1=3 +x2=8 +divx=5 +subdivx=1 +xlabmag=1.0 +ylabmag=1.0 +node="ph(Vout)" +color="" +dataset=-1 +unitx=1 +logx=1 +logy=0 +} +T {tcleval(A0: [to_eng [xschem raw value A0 0]] +UGF: [to_eng [xschem raw value ugf 0]] +PM: [to_eng [xschem raw value pm 0]])} 950 1020 0 0 0.6 0.6 {floater=1} +N 540 130 560 130 { +lab=Vout} +N 560 130 560 150 { +lab=Vout} +N 50 170 50 190 { +lab=GND} +N 50 70 50 110 { +lab=VSS} +N 130 170 130 190 { +lab=GND} +N 50 190 50 210 { +lab=GND} +N 130 70 130 110 { +lab=VDD} +N 50 190 130 190 { +lab=GND} +N 210 70 210 110 { +lab=VDD} +N 210 170 210 190 { +lab=Ib} +N 210 190 210 210 { +lab=Ib} +N 230 370 270 370 { +lab=#net1} +N 50 320 50 480 { +lab=#net1} +N 50 320 230 320 { +lab=#net1} +N 50 540 50 560 { +lab=GND} +N 230 540 230 560 { +lab=GND} +N 230 460 310 460 { +lab=#net2} +N 230 460 230 480 { +lab=#net2} +N 230 410 270 410 { +lab=GND} +N 230 410 230 430 { +lab=GND} +N 150 420 150 460 { +lab=#net2} +N 310 420 310 460 { +lab=#net2} +N 230 320 230 370 { +lab=#net1} +N 310 280 310 360 { +lab=Vn} +N 150 280 150 360 { +lab=Vp} +N 150 460 230 460 { +lab=#net2} +N 190 410 230 410 { +lab=GND} +N 190 370 230 370 { +lab=#net1} +C {devices/isource.sym} 210 140 0 0 {name=I0 value=10u} +C {devices/lab_wire.sym} 450 70 0 0 {name=p2 sig_type=std_logic lab=VDD} +C {devices/capa.sym} 560 180 0 0 {name=C1 +m=1 +value=1p} +C {devices/gnd.sym} 560 210 0 0 {name=l2 lab=GND} +C {devices/lab_wire.sym} 390 90 0 0 {name=p3 sig_type=std_logic lab=Vp} +C {devices/lab_wire.sym} 390 170 0 0 {name=p4 sig_type=std_logic lab=Vn} +C {devices/lab_wire.sym} 390 130 0 0 {name=p7 sig_type=std_logic lab=Ib} +C {devices/code_shown.sym} 960 310 0 0 {name=COMMANDS +simulator=ngspice +only_toplevel=false +value=" +.param vdd=1.8 +.param vcm=0.9 + +.control + + save all + + save @m.x1.xm1.msky130_fd_pr__pfet_01v8[id] @m.x1.xm1.msky130_fd_pr__pfet_01v8[gm] @m.x1.xm1.msky130_fd_pr__pfet_01v8[gds] + save @m.x1.xm2.msky130_fd_pr__pfet_01v8[id] @m.x1.xm2.msky130_fd_pr__pfet_01v8[gm] @m.x1.xm2.msky130_fd_pr__pfet_01v8[gds] + + save @m.x1.xm3.msky130_fd_pr__nfet_01v8[id] @m.x1.xm3.msky130_fd_pr__nfet_01v8[gm] @m.x1.xm3.msky130_fd_pr__nfet_01v8[gds] + save @m.x1.xm4.msky130_fd_pr__nfet_01v8[id] @m.x1.xm4.msky130_fd_pr__nfet_01v8[gm] @m.x1.xm4.msky130_fd_pr__nfet_01v8[gds] + save @m.x1.xm5.msky130_fd_pr__nfet_01v8[id] @m.x1.xm5.msky130_fd_pr__nfet_01v8[gm] @m.x1.xm5.msky130_fd_pr__nfet_01v8[gds] + save @m.x1.xm6.msky130_fd_pr__nfet_01v8[id] @m.x1.xm6.msky130_fd_pr__nfet_01v8[gm] @m.x1.xm6.msky130_fd_pr__nfet_01v8[gds] + + * operating point + op + + write sky130_cace_ip__ota5t_tb.raw + set appendwrite + + * run ac simulation + ac dec 20 1k 100e6 + + * measure parameters + let vout_mag = abs(v(Vout)) + let vout_phase_margin = phase(v(Vout)) * 180/pi + 180 + meas ac A0 find vout_mag at=1k + meas ac UGF when vout_mag=1 fall=1 + meas ac PM find vout_phase_margin when vout_mag=1 + + write sky130_cace_ip__ota5t_tb.raw +.endc +"} +C {devices/launcher.sym} 460 550 0 0 {name=h26 +descr="Annotate OP" +tclcommand="set show_hidden_texts 1; xschem annotate_op" +} +C {devices/launcher.sym} 460 610 0 0 {name=h27 +descr="Load waves AC" +tclcommand=" +xschem raw_read $netlist_dir/[file tail [file rootname [xschem get current_name]]].raw ac + +" +} +C {devices/lab_wire.sym} 560 130 0 1 {name=p11 sig_type=std_logic lab=Vout} +C {sky130_cace_ip__ota5t.sym} 460 130 0 0 {name=x1} +C {devices/vsource.sym} 50 140 0 0 {name=V0 value=0 savecurrent=false} +C {devices/gnd.sym} 50 210 0 0 {name=l3 lab=GND} +C {devices/vsource.sym} 130 140 0 0 {name=V2 value=\{vdd\} savecurrent=false} +C {devices/lab_wire.sym} 50 70 0 0 {name=p1 sig_type=std_logic lab=VSS} +C {devices/lab_wire.sym} 210 210 2 0 {name=p8 sig_type=std_logic lab=Ib} +C {devices/vcvs.sym} 150 390 0 1 {name=E1 value=0.5} +C {devices/vcvs.sym} 310 390 0 0 {name=E2 value=-0.5} +C {devices/vsource.sym} 50 510 0 0 {name=Vdm value="ac 1" savecurrent=false} +C {devices/vsource.sym} 230 510 0 0 {name=Vcm value=\{vcm\} savecurrent=false} +C {devices/gnd.sym} 50 560 0 0 {name=l5 lab=GND} +C {devices/gnd.sym} 230 560 0 0 {name=l6 lab=GND} +C {devices/gnd.sym} 230 430 0 0 {name=l7 lab=GND} +C {devices/lab_wire.sym} 150 280 0 0 {name=p12 sig_type=std_logic lab=Vp} +C {devices/lab_wire.sym} 310 280 0 0 {name=p13 sig_type=std_logic lab=Vn} +C {devices/lab_wire.sym} 130 70 0 0 {name=p5 sig_type=std_logic lab=VDD} +C {devices/lab_wire.sym} 210 70 0 0 {name=p6 sig_type=std_logic lab=VDD} +C {devices/lab_wire.sym} 450 190 2 1 {name=p9 sig_type=std_logic lab=VSS} +C {sky130_fd_pr/corner.sym} 790 130 0 0 {name=CORNER only_toplevel=false corner=tt} diff --git a/examples/sky130_cace_ip__ota5t/xschem/xschemrc b/examples/sky130_cace_ip__ota5t/xschem/xschemrc new file mode 100644 index 0000000..48250ea --- /dev/null +++ b/examples/sky130_cace_ip__ota5t/xschem/xschemrc @@ -0,0 +1,31 @@ +# Set default PDK_ROOT +if { ![info exists env(PDK_ROOT)] } { + puts stderr "Warning: PDK_ROOT env. var. not found or empty, trying to find an open_pdks install" + if {[file isdir /usr/share/pdk]} {set ::env(PDK_ROOT) /usr/share/pdk + } elseif {[file isdir /usr/local/share/pdk]} {set ::env(PDK_ROOT) /usr/local/share/pdk + } elseif {[file isdir $env(HOME)/share/pdk]} {set ::env(PDK_ROOT) $env(HOME)/share/pdk + } elseif {[file isdir $env(HOME)/.ciel]} {set ::env(PDK_ROOT) $env(HOME)/.ciel + } elseif {[file isdir $env(HOME)/.volare]} {set ::env(PDK_ROOT) $env(HOME)/.volare + } else { + puts stderr {No open_pdks installation found, set PDK_ROOT env. var. and restart xschem} + } +} + +# Set default PDK +if { ![info exists env(PDK)] } { + set ::env(PDK) sky130A +} + +# Source the PDK xschemrc file +if {![info exists PDK]} { + source $env(PDK_ROOT)/$env(PDK)/libs.tech/xschem/xschemrc +} + +# Add current directory to xschem library path +append XSCHEM_LIBRARY_PATH :[file dirname [info script]] + +# Source the dependencies xschemrc files +foreach rcfile [glob -nocomplain ../ip/*/xschem/xschemrc] { + puts "sourcing $rcfile" + source $rcfile +}