Initial commit of public repository open_pdks.
diff --git a/README b/README
new file mode 100644
index 0000000..24fc238
--- /dev/null
+++ b/README
@@ -0,0 +1,574 @@
+open_pdks : A system for installing silicon foundry PDKs for open-source EDA tools
+(also maybe works for installing commercial tools)
+
+----------------------------------------------------------------------------------
+
+Written by Tim Edwards 2019 / 2020 for efabless (efabless.com)
+and Open Circuit Design (opencircuitdesign.com)
+
+----------------------------------------------------------------------------------
+
+Introduction:
+
+ Silicon foundry PDKs are notoriously non-standard, and files obtained
+ from the foundry may end up in any possibly configuration of files and
+ folders. In addition, silicon foundries are notorious among open source
+ EDA tool enthusiasts for supplying user setups for commercial EDA tools
+ and all but ignoring open source EDA tools. Open_pdks aims to mitigate
+ the problem by defining a standard layout of files and directories for
+ known open standard formats (e.g., SPICE, verilog, liberty, LEF, etc.)
+ and for various open source EDA tools (e.g., magic, netgen, OpenROAD,
+ klayout) using a Makefile system and a number of conversion scripts to
+ ensure that for any process, all files needed by all EDA tools can be
+ found in predictable locations.
+
+ The scripts aim to be as general-purpose as possible to allow easy
+ adaptation to new tools, formats, and foundries. Where foundry data
+ is intractably unusable, custom install files can be added to overwrite
+ or annotate vendor data as needed.
+
+ Each foundry process is a subdirectory of the open_pdks top level and
+ has its own Makefile. The typical install process is to cd to the
+ foundry top level and run "make" (see below for details).
+
+ The general file structure created by open_pdks is as follows:
+
+ <foundry_root>/
+ <name_of_pdk_variant_1>/
+ <name_of_pdk_variant_2>/
+ ...
+ <name_of_pdk_variant_x>/
+ libs.tech/
+ <name_of_EDA_tool_1>/
+ <name_of_EDA_tool_2>/
+ ...
+ <name_of_EDA_tool_x>/
+ <EDA_tool_setup_files>
+ libs.ref
+ <name_of_IP_library_1>/
+ <name_of_IP_library_2>/
+ ...
+ <name_of_IP_library_x>/
+ <name_of_file_format_1>
+ <name_of_file_format_2>
+ ...
+ <name_of_file_format_x>
+ <vendor_files>
+
+ Note that this format is very general and does not constrain the
+ EDA tools supported or file formats supported, so long as there
+ are scripts in the system to provide that support. It is intended
+ that open_pdks can be extended as needed to support new tools or
+ new file formats.
+
+ Current EDA tools supported in this version of open_pdks:
+ Tool Directory name
+ --------------------------
+ ngspice ngspice
+ magic magic
+ netgen netgen
+ klayout klayout
+ qflow qflow
+ openlane openlane
+
+ Current IP library file formats supported in this version of open_pdks*:
+ Format Directory name
+ --------------------------
+ CDL cdl
+ SPICE spice
+ magic mag, maglef
+ LEF lef, techlef
+ GDS gds
+ verilog verilog
+ liberty lib
+ PDF** doc
+
+ (* "Supported" meaning expected/handled by conversion scripts;
+ as noted, the install is very general purpose and any name
+ can be used as a target for any vendor or custom files.)
+ (** or HTML or any valid document format, plus supporting files.)
+
+How to use open_pdks:
+
+ There are a seriously limited number of open foundry PDKs. Those that
+ are known (SkyWater, MOSIS SCMOS) are included in the repository. In
+ other cases (X-Fab XH035, XH018) it is possible to get an extension to
+ open_pdks from a known trusted source through NDA verification with
+ the foundry. In all other cases, foundries should be berated until
+ they agree to support the open_pdks format.
+
+ Open_pdks does not attempt to keep any foundry data to the extent
+ possible. Instead, it adapts to the file structure available from
+ whatever system each foundry uses for downloads. Each foundry
+ directory should contain a README file that details how to obtain
+ downloads from the foundry, and what files need to be downloaded.
+ Since the download methods vary wildly, it is up to the user to obtain
+ the foundry data as instructed. The Makefile in the open_pdks foundry
+ directory then needs to be edited to set the correct path to the
+ foundry source data.
+
+ The installation is a bootstrapping process, so needs to be done in
+ stages. The first stage installs setup files for all the EDA tools.
+ The second stage installs IP libraries (e.g., standard cells, padframe
+ I/O, analog circuits) and depends heavily on the use of the open EDA
+ tools themselves to fill in any missing file formats. Therefore the
+ tool setup files need to be installed first, and then the IP libraries.
+ If using a distributed install (see below), then the tool setup files
+ need to be installed and distributed (relocated to the final run-time
+ location) before the IP libraries are installed.
+
+ There are two distinct install types supported by open_pdks:
+
+ (1) Local install: Use a local install when the EDA tools will be run
+ on a single host, and all the PDK data are on the same host.
+
+ The local install sequence is:
+
+ make Generate local staging area
+ make install-local Migrate to install directory
+
+ (2) Distributed install: Use the distributed install when the PDK
+ will be run from multiple hosts, but will be installed into a
+ different location such as a git repo which is then distributed to
+ all hosts, and may not itself reside in the same root directory tree.
+
+ The distributed install sequence is:
+
+ make Generate local staging area
+ make install-dist Migrate to distribution directory
+
+ Note that local installs may opt to make symbolic links back to the
+ foundry sources, where possible (see options for foundry_install.py,
+ below). Distributed installs and local installs may also make
+ symbolic links from any PDK variant back to a "master" PDK variant,
+ where possible (that is, where the files are the same). For example,
+ a standard cell library will probably be compatible with all metal
+ back-end stacks, and so only one copy of all the library files is
+ needed in one of the PDK variants. For the other PDK variants, the
+ same files are all symbolic links to the files in the first PDK
+ variant. But an I/O library would have different layouts for different
+ metal back-end stacks, so layout-dependent files like GDS would be
+ different for each PDK, but layout-independent files like verilog
+ might be symbolic links to files in the first PDK.
+
+Prerequisites:
+
+ The following tools/software stacks are needed to run open_pdks:
+
+ python3
+
+ magic opencircuitdesign.com/magic or github.com/RTimothyEdwards
+
+ assumed to be installed and discoverable in the standard
+ search path as defined by the shell (version 8.2+ required)
+
+How to make or update an open PDK:
+
+ The backbone of the open_pdks system is a set of scripts found in the
+ common/ subdirectory. The two main scripts are "preproc.py" and
+ "foundry_install.py", with a host of supporting scripts.
+
+ Creating a new PDK starts with generating a Makefile, which can be
+ done by copying a Makefile from an existing project. The first thing
+ to do is to define the number of PDK variants (usually based on back-end
+ metal stacks available, but can also include front-end options, especially
+ if they are mutually exclusive rather than simply additional masks).
+ Then create the make and make-install targets for local and distributed
+ install, including install (plain), install-vendor, and install-custom.
+ Define the default source and target paths.
+
+ (Needed: A "make makefile" script that generates the "local" and "dist"
+ automatically, and potentially can also make all the different PDK
+ targets automatically, from a much shorter and simpler master Makefile.)
+
+ Create the basic scripts for tools. Since foundries do not support open
+ EDA tools, it is inevitable that these files need to be created by hand
+ unless there is an option to import other formats. Because Magic is used
+ heavily by open_pdks to create missing file formats from other existing
+ file formats, a Magic techfile is critical. Each of the basic scripts
+ will contain #ifdef ... #endif and similar conditionals to allow the
+ script to be parsed for each target PDK variant. Each of these scripts
+ is passed through common/preproc.py to handle the conditionals. Of course,
+ it is possible to make a separate file for each PDK variant as long as the
+ Makefile handles them properly, but use of the preproc.py script allows
+ all the PDK variants to be handled in the same way, simplifying the Makefile.
+
+ --------------------------------------------------------------------------
+ preproc.py Usage:
+
+ preproc.py input_file [output_file] [-D<variable> ...]
+
+ Where <variable> may be a keyword or a key=value pair
+
+ Syntax: Basically like cpp. However, this preprocessor handles
+ only a limited set of keywords, so it does not otherwise mangle
+ the file in the belief that it must be C code. Handling of boolean
+ relations is important, so these are thoroughly defined (see below)
+
+ #if defined(<variable>) [...]
+ #ifdef <variable>
+ #ifndef <variable>
+ #elseif <variable>
+ #else
+ #endif
+
+ #define <variable> [...]
+ #undef <variable>
+
+ #include <filename>
+
+ <variable> may be
+ <keyword>
+ <keyword>=<value>
+
+ <keyword> without '=' is effectively the same as <keyword>=1
+ Lack of a keyword is equivalent to <keyword>=0, in a conditional.
+
+ Boolean operators (in order of precedence):
+ ! NOT
+ && AND
+ || OR
+
+ Comments:
+ Most comments (C-like or Tcl-like) are output as-is. A
+ line beginning with "###" is treated as a preprocessor
+ comment and is not copied to the output.
+
+ Examples;
+ #if defined(X) || defined(Y)
+ #else
+ #if defined(Z)
+ #endif
+
+ --------------------------------------------------------------------------
+
+ The script common/foundry_install.py handles all the IP library processing
+ and installation. It generates the local directory structure and populates
+ the directories with foundry vendor data, and filters or otherwise uses
+ open EDA tools to generate missing standard file formats or create file
+ formats needed by the open EDA tools.
+
+ foundry_install.py Usage:
+
+ foundry_install.py [option [option_arguments]] ...
+
+ All options begin with "-" and may be followed by one or more
+ arguments (that do not begin with "-"). The foundry_install.py
+ script may be called multiple times, although it is best to
+ group together all files for the installation of an IP library,
+ since the options given will be used to determine what files are
+ missing and need to be generated.
+
+ Global options:
+ -link_from <type>
+ Make symbolic links to vendor files from target
+ Types are: "none", "source", or a PDK name.
+ Default "none" (copy all files from source)
+ -source <path>
+ Path to source data top level directory
+ -target <path>
+ Path to target top level directory
+ -local <path>
+ For distributed installs, this is the local
+ path to target top level directory.
+
+ -library <type> <name>
+ The install target is an IP library with
+ name <name>.
+ -ef_format
+ Use the original efabless format for file
+ installs. This has several differences from
+ then no-efabless install. The most important
+ is that the order of directories for IP libraries
+ is <file_format>/<library_name> instead of
+ <library_name>/<file_format>. As the efabless
+ platform migrates to the open_pdks developing
+ standard, this use should eventually be
+ deprecated. In open_pdks, the option is set
+ from the EF_FORMAT variable setting in the Makefile.
+
+ All other options represent installation into specific directories.
+ The primary rule is that if foundry_install.py is passed an option
+ "-library" (see syntax below), then all other non-global options
+ represent subdirectories of the IP library, given the same name as
+ the option word following the "-". If the foundry_install.py command
+ line does not have an option "-library", then all non-global options
+ represent per-EDA tool subdirectories, where the name of the subdirectory
+ is the same as the option word following the "-".
+
+ Each tool install option has the syntax:
+
+ -<tool_name> <path> [<option_arguments>]
+
+ Each IP library install option has the syntax:
+
+ -<file_format_name> <path> [<option_arguments>]
+
+ The <path> is a directory path that is relative to the path prefix
+ given by the -source option. The path may be wildcarded with the
+ escape string "%l", which is replaced by the name of the library,
+ and for simplicity with versioning, "%v" will be interpreted to
+ match any versioning string in the form "major[.minor[.rev]]".
+ Note that only the numerical part of a versioning string is
+ represented, so, for example, to match "/V1.1.0/" the <path> should
+ use "/V%v/". In the unlikely event of a percent character in the
+ path, use the escape string "%%".
+
+ "*" has the usual meaning of matching any characters in a name (see
+ python glob.glob() command for reference). However, for backwards
+ compatibility with earlier versions of open_pdks, the library name
+ in the path may also be wildcarded with "*" in the specific text
+ "/*/".
+
+ Library name wildcarding in either form is only valid if "-library"
+ is given as an an option.
+
+ (Note that the INSTALL variable in the Makefile starts with "set -f"
+ to suppress the OS from doing wildcard substitution; otherwise the
+ wildcards in the install options will get expanded by the OS before
+ being passed to the install script.)
+
+ Library option:
+
+ -library <type> <name> [<target>]
+
+ <type> may be one of the following:
+
+ digital Digital standard cells
+ primitive Primitive devices
+ general All others
+
+ Analog and I/O libraries fall under the category "general".
+
+ <name> is the vendor name of the library.
+
+ [<target>] is the (optional) local name of the library. If omitted,
+ then the vendor name is used for the target (there is no particular
+ reason to specify a different local name for a library).
+
+ Any number of libraries may be supported, and one "-library" option
+ may be provided for each supported library. The use of multiple
+ libraries for a single run of foundry_install.py only works if the
+ formats (gds, cdl, lef, etc.) happen to all work with the same wildcards.
+ But it is generally most common to declare only one library name per
+ call to foundry_install.py.
+
+ Common foundry_install.py options when used with "-library":
+
+ -techlef <path> [option_arguments] Technology LEF file
+ -doc <path> [option_arguments] library documentation
+ -lef <path> [option_arguments] LEF file
+ -spice <path> [option_arguments] SPICE netlists
+ -cdl <path> [option_arguments] CDL netlists
+ -lib <path> [option_arguments] Liberty timing files
+ -gds <path> [option_arguments] GDS layout data
+ -verilog <path> [option_arguments] Verilog models
+
+ Any name can be used after the "-" and the installation of files
+ will be made into a directory of that name, which will be created
+ if it does not exist. The names used above are preferred, for
+ the sake of compatibility between EDA tools.
+
+ Of special note is "techlef", as technology LEF files are often
+ associated with a PDK and not an IP library. In this system,
+ the technology LEF file should be associated with each standard
+ cell library for which it is intended.
+
+ [option_arguments] may be one of the following:
+
+ up <number>
+ Any tool option can use this argument to indicate that
+ the source hierarchy should be copied entirely, starting
+ from <number> levels above the files indicated by <path>.
+ For example, if liberty files are kept in multiple
+ directories according to voltage level, then
+
+ -liberty x/y/z/PVT_*/*.lib
+
+ would install all .lib files directly into
+ libs.ref/<libname>/liberty/*.lib while
+
+ -liberty x/y/z/PVT_*/*.lib up 1
+
+ would install all .lib files into
+ libs.ref/liberty/<libname>/PVT_*/*.lib.
+
+ nospec
+ Remove timing specification before installing (used with
+ verilog files only; could be extended to liberty files).
+
+ compile
+ Create a single library from all components. Used when a
+ foundry library has inconveniently split an IP library
+ (LEF, CDL, verilog, etc.) into individual files.
+
+ compile-only
+ Same as argument "compile", except that the individual
+ files are not copied to the target; only the compiled
+ library is created.
+
+ stub
+ Remove contents of subcircuits from CDL and SPICE netlist,
+ or verilog files. This is useful to LVS and other tools
+ to know the order of pins in a circuit (for CDL or SPICE),
+ or simply to ignore the contents of the file (any format)
+ so that the circuit in question is treated as a "black box".
+
+ priv
+ Mark the contents being installed as privleged, and put
+ them in a separate root directory libs.priv where they
+ can be given additional read/write restrictions.
+
+ rename <file_name>
+ Rename the file being copied to the name of the argument.
+ This can be used to copy one file into multiple destination
+ libraries and give each copy a name related to the
+ destination library.
+
+ filter <script_file_path>
+ Process all files through the script <script_file_path>,
+ which is given as a relative path to the directory
+ containing the Makefile. The filter script traditionally
+ is put in local subdirectory custom/scripts/. The filter
+ script should be written to take a single argument, which
+ is the path to a file, and process that file, and overwrite
+ the file with the result. Commonly used filters are found
+ in the common/ directory. See common/fixspice.py for an
+ example.
+
+ noclobber
+ Mainly diagnostic. When specified, any temporary files
+ used during installation will be retained instead of
+ deleted after use. This includes, for example, scripts
+ passed to magic for running extraction or file format
+ generation. It is useful when debugging problems with
+ the install.
+
+ anno
+ Currently only supported for LEF files. This argument
+ indicates that the vendor LEF files should be used only
+ for annotating GDS input with port location information,
+ but the LEF files themselves should not be installed.
+
+ File conversions handled by foundry_install.py:
+
+ The following file format conversions can be done automatically by
+ foundry_install.py:
+
+ CDL to SPICE: A CDL netlist or library can be converted to a
+ general-purpose SPICE netlist that can be read
+ by any tool that can read Berkeley SPICE 3f5
+ syntax.
+
+ GDS to LEF: An abstract view can be generated from a full
+ layout view using Magic.
+
+ GDS to SPICE: In the absence of any netlist, Magic will
+ extract a SPICE netlist from a full layout.
+
+ SPICE (any) to SPICE (ngspice): The fixspice.py script will
+ attempt to convert any SPICE model file,
+ cell library, or netlist to a form that is
+ compatible with ngspice version 30.
+
+ open_pdks additional Makefile notes:
+
+ The "make install-local" ("make install-dist") step is generally
+ broken into individual make sections, one for each tool (e.g.,
+ magic, netgen, klayout). There is an additional section called
+ "general" which installs a ".config" directory at the PDK top
+ level, containing a file "nodeinfo.json" which has general
+ information about the PDK that may be used by any tool that
+ understands the key:value pairs used in the JSON file. Keys used
+ are as follows:
+
+ foundry : Short name of the foundry, equal to the foundry
+ directory root, above the PDK variants.
+ foundry-name : Long name of the foundry.
+ node : The name of the PDK variant
+ feature-size : The foundry process feature size (e.g., 130nm)
+ status : "active" or "inactive". May be used by tools
+ to present or hide specific PDK variants.
+ description : Long text description of the process variant
+ (e.g., 6-metal stack + MiM caps)
+ options : List of options, corresponding to the definitions
+ used in the Makefile and passed to preproc.py.
+ stdcells : List of standard cell libraries available for this
+ PDK variant.
+ iocells : List of I/O pad cell libraries available for this
+ PDK variant.
+
+ Note that the JSON file is, like other EDA tool setup files, usually a
+ master file that is parsed by preproc.py; therefore when specifying
+ "options", use #undef before specifying each option name so that the
+ option name itself is ignored by the pre-processor.
+
+
+Goals of the open_pdks project:
+
+ The intended goal of open_pdks is to be able to support as many open source
+ EDA tools as practical, and to be able to generate all needed files for
+ those tools from any sufficiently complete set of vendor files.
+
+ A number of file converions are not available but would be useful to have:
+
+ SPICE to liberty: Create timing files by running simulations
+ on SPICE netlists using ngspice.
+
+ liberty to verilog: Use the function statements in liberty
+ format to create verilog primitives. Maybe
+ use liberty timing information to generate
+ LEF specify sections.
+
+ verilog to liberty: Reverse of the above. Use verilog logic
+ tables and specify sections to generate liberty
+ functions and timing tables.
+
+ File formats that need to be supported:
+
+ Schematic and symbol: There are few standards, so either everyone
+ needs to agree on a good format to use, or there
+ needs to be a lot of scripts to do conversions
+ between formats. Open EDA tools that could be
+ supported include:
+
+ electric, xcircuit, kicad, sue2
+
+ Other open source EDA tools that need to be supported:
+
+ OpenROAD
+ Coriolis2
+ (add more here. . .)
+
+ Commercial EDA tools can potentially be supported under this same system,
+ provided sufficient compatibility with the file system structure.
+
+ Other scripts needed:
+
+ Project setup script: It would be useful to define a "standard
+ project file structure" that is similar to the standard PDK file
+ structure defined in open_pdks. The preferred project setup
+ based on the efabless model is:
+
+ <project_name>
+ .config/
+ techdir (symbolic link to open_pdks PDK)
+ project.json (information file for tools)
+ <tool_name> (magic, qflow, ngspice, etc.) or
+ <format_name> (spice, gds, verilog, etc.)
+
+ In general, <tool_name> directories are intended to be workspaces
+ for specific EDA tools (and may have their own nested hierarchies;
+ e.g., qflow/<digital_block>/source,synthesis,layout) while
+ <format_name> is a place to keep (final) files of a specific format,
+ with the intention that any project can easily be made into an
+ IP library and folded into the open_pdks scheme with little effort.
+
+ The project.json file contains project information that can be used
+ by a script to build a setup for any EDA tool. One goal of the
+ project.json file is to define "datasheet" (documented elsewhere)
+ that can be used to drive characterization simulations and create
+ a datasheet for the project. Field "ip-name" of "datasheet" is
+ the canonical name of the project, which can be distinguished from
+ the project directory top-level name, such that the project can be
+ moved or copied without affecting the tool flows.