switch from conda to nix for tooling

This commit is contained in:
Jesse Cirimelli-Low
2026-04-30 12:00:56 -07:00
parent 2780fda35c
commit ddac4254ec
17 changed files with 178 additions and 177 deletions
+13 -14
View File
@@ -19,31 +19,30 @@ jobs:
run: | run: |
rm -rf ~/.local/lib/python3.8/site-packages/openram* rm -rf ~/.local/lib/python3.8/site-packages/openram*
make library make library
- name: Build conda
run: |
./install_conda.sh
- name: PDK Install - name: PDK Install
run: | run: |
export OPENRAM_HOME="${{ github.workspace }}/compiler" nix --extra-experimental-features 'nix-command flakes' develop --command bash -lc '
export OPENRAM_TECH="${{ github.workspace }}/technology" export OPENRAM_HOME="${{ github.workspace }}/compiler";
export PDK_ROOT="${{ github.workspace }}/pdk" export OPENRAM_TECH="${{ github.workspace }}/technology";
export PDK_ROOT="${{ github.workspace }}/pdk";
# Add make targets to install PDKs of all technologies that need it # Add make targets to install PDKs of all technologies that need it
make sky130-pdk make sky130-pdk;
make sky130-install make sky130-install
- name: Regress - name: Regress
run: | run: |
export OPENRAM_HOME="${{ github.workspace }}/compiler" nix --extra-experimental-features 'nix-command flakes' develop --command bash -lc '
export OPENRAM_TECH="${{ github.workspace }}/technology" export OPENRAM_HOME="${{ github.workspace }}/compiler";
export PDK_ROOT="${{ github.workspace }}/pdk" export OPENRAM_TECH="${{ github.workspace }}/technology";
export FREEPDK45="~/FreePDK45" export PDK_ROOT="${{ github.workspace }}/pdk";
export FREEPDK45="~/FreePDK45";
# KLAYOUT_PATH breaks klayout installation. Unset it for now... # KLAYOUT_PATH breaks klayout installation. Unset it for now...
unset KLAYOUT_PATH unset KLAYOUT_PATH;
#cd $OPENRAM_HOME/.. && make pdk && make install #cd $OPENRAM_HOME/.. && make pdk && make install
#export OPENRAM_TMP="${{ github.workspace }}/scn4me_subm_temp" #export OPENRAM_TMP="${{ github.workspace }}/scn4me_subm_temp"
#python3-coverage run -p $OPENRAM_HOME/tests/regress.py -j 12 -t scn4m_subm #python3-coverage run -p $OPENRAM_HOME/tests/regress.py -j 12 -t scn4m_subm
#$OPENRAM_HOME/tests/regress.py -j 24 -t scn4m_subm #$OPENRAM_HOME/tests/regress.py -j 24 -t scn4m_subm
cd $OPENRAM_HOME/tests cd $OPENRAM_HOME/tests;
make clean make clean;
make -k -j 48 make -k -j 48
- name: Archive - name: Archive
if: ${{ failure() }} if: ${{ failure() }}
-1
View File
@@ -19,7 +19,6 @@ compiler/tests/results/
open_pdks/ open_pdks/
dist/ dist/
openram.egg-info/ openram.egg-info/
miniconda/
sky130A sky130A
sky130B sky130B
gf180mcuA gf180mcuA
-1
View File
@@ -2,7 +2,6 @@ include Makefile
include openram.mk include openram.mk
include setpaths.sh include setpaths.sh
include requirements.txt include requirements.txt
include install_conda.sh
include docker/* include docker/*
recursive-include compiler * recursive-include compiler *
recursive-include technology * recursive-include technology *
+8 -10
View File
@@ -57,8 +57,8 @@ INSTALL_BASE_DIRS := gds_lib mag_lib sp_lib lvs_lib calibre_lvs_lib klayout_lvs_
INSTALL_BASE := $(OPENRAM_HOME)/../technology/sky130 INSTALL_BASE := $(OPENRAM_HOME)/../technology/sky130
INSTALL_DIRS := $(addprefix $(INSTALL_BASE)/,$(INSTALL_BASE_DIRS)) INSTALL_DIRS := $(addprefix $(INSTALL_BASE)/,$(INSTALL_BASE_DIRS))
# If conda is installed, we will use ciel from there # If nix is available, run ciel via nix develop
CONDA_DIR := $(wildcard $(TOP_DIR)/miniconda) NIX_BIN := $(shell command -v nix 2>/dev/null)
check-pdk-root: check-pdk-root:
ifndef PDK_ROOT ifndef PDK_ROOT
@@ -102,23 +102,21 @@ sky130-install: $(SRAM_LIB_DIR)
sky130-pdk: $(SKY130_PDKS_DIR) sky130-pdk: $(SKY130_PDKS_DIR)
@echo "Installing SKY130 via ciel..." @echo "Installing SKY130 via ciel..."
ifeq ($(CONDA_DIR),) ifeq ($(NIX_BIN),)
ciel enable --pdk sky130 $(SKY130_CIEL) ciel enable --pdk sky130 $(SKY130_CIEL)
else else
source $(TOP_DIR)/miniconda/bin/activate && \ nix --extra-experimental-features 'nix-command flakes' develop --command \
ciel enable --pdk sky130 $(SKY130_CIEL) && \ ciel enable --pdk sky130 $(SKY130_CIEL)
conda deactivate
endif endif
.PHONY: sky130-pdk .PHONY: sky130-pdk
gf180mcu-pdk: gf180mcu-pdk:
@echo "Installing GF180 via ciel..." @echo "Installing GF180 via ciel..."
ifeq ($(CONDA_DIR),) ifeq ($(NIX_BIN),)
ciel enable --pdk gf180mcu $(GF180_CIEL) ciel enable --pdk gf180mcu $(GF180_CIEL)
else else
source $(TOP_DIR)/miniconda/bin/activate && \ nix --extra-experimental-features 'nix-command flakes' develop --command \
ciel enable --pdk gf180mcu $(GF180_CIEL) && \ ciel enable --pdk gf180mcu $(GF180_CIEL)
conda deactivate
endif endif
.PHONY: gf180mcu-pdk .PHONY: gf180mcu-pdk
+5 -16
View File
@@ -23,22 +23,11 @@ if "OPENRAM_HOME" not in os.environ.keys():
__path__.insert(0, OPENRAM_HOME) __path__.insert(0, OPENRAM_HOME)
# Find the conda installer script # Nix toolchain root (flake location)
if os.path.exists(OPENRAM_HOME + "/install_conda.sh"): NIX_HOME = os.path.abspath(OPENRAM_HOME + "/..")
CONDA_INSTALLER = OPENRAM_HOME + "/install_conda.sh" if "NIX_HOME" in os.environ.keys():
CONDA_HOME = OPENRAM_HOME + "/miniconda" NIX_HOME = os.environ["NIX_HOME"]
elif os.path.exists(OPENRAM_HOME + "/../install_conda.sh"): os.environ["NIX_HOME"] = NIX_HOME
CONDA_INSTALLER = OPENRAM_HOME + "/../install_conda.sh"
CONDA_HOME = os.path.abspath(OPENRAM_HOME + "/../miniconda")
# Override CONDA_HOME if it's set as an environment variable
if "CONDA_HOME" in os.environ.keys():
CONDA_HOME = os.environ["CONDA_HOME"]
# Add CONDA_HOME to environment variables just in case
try:
os.environ["CONDA_HOME"] = CONDA_HOME
except:
from openram import debug
debug.warning("Couldn't find conda setup directory.")
# Import everything in globals.py # Import everything in globals.py
+8 -3
View File
@@ -12,6 +12,7 @@ simulations as well.
""" """
import os import os
import shlex
import subprocess import subprocess
import numpy as np import numpy as np
from openram import debug from openram import debug
@@ -406,11 +407,15 @@ class stimuli():
spice_stdout = open("{0}spice_stdout.log".format(OPTS.openram_temp), 'w') spice_stdout = open("{0}spice_stdout.log".format(OPTS.openram_temp), 'w')
spice_stderr = open("{0}spice_stderr.log".format(OPTS.openram_temp), 'w') spice_stderr = open("{0}spice_stderr.log".format(OPTS.openram_temp), 'w')
# Wrap the command with conda activate & conda deactivate # Run spice in the Nix devShell when Nix-managed tools are enabled.
# FIXME: Should use verify/run_script.py here but run_script doesn't return # FIXME: Should use verify/run_script.py here but run_script doesn't return
# the return code of the subprocess. File names might also mismatch. # the return code of the subprocess. File names might also mismatch.
from openram import CONDA_HOME if OPTS.use_nix:
cmd = "/bin/bash -c 'source {0}/bin/activate && {1} && conda deactivate'".format(CONDA_HOME, cmd) cmd = (
"nix --extra-experimental-features 'nix-command flakes' "
"develop --command /bin/bash -lc {0}"
.format(shlex.quote(cmd))
)
debug.info(2, cmd) debug.info(2, cmd)
proc = subprocess.run(cmd, stdout=spice_stdout, stderr=spice_stderr, shell=True) proc = subprocess.run(cmd, stdout=spice_stdout, stderr=spice_stderr, shell=True)
+32 -16
View File
@@ -188,7 +188,7 @@ def init_openram(config_file, is_unit_test=False):
read_config(config_file, is_unit_test) read_config(config_file, is_unit_test)
install_conda() install_nix()
import_tech() import_tech()
@@ -209,17 +209,40 @@ def init_openram(config_file, is_unit_test=False):
from openram import verify from openram import verify
def install_conda(): def install_nix():
""" Setup conda for default tools. """ """Initialize Nix-based toolchain dependencies."""
# Don't setup conda if not used # Don't setup tools during unit tests.
if not OPTS.use_conda or OPTS.is_unit_test: if OPTS.is_unit_test:
return return
debug.info(1, "Creating conda setup..."); if not OPTS.use_nix or OPTS.is_unit_test:
return
from openram import CONDA_INSTALLER debug.info(1, "Bootstrapping toolchain with Nix...")
subprocess.call(CONDA_INSTALLER)
nix_exe = shutil.which("nix")
if nix_exe is None:
debug.error("Nix is required for automatic tool setup, but 'nix' was not found in PATH.", -1)
repo_root = os.path.abspath(os.path.join(OPENRAM_HOME, ".."))
flake_file = os.path.join(repo_root, "flake.nix")
if not os.path.exists(flake_file):
debug.error("Expected Nix flake at {} for tool setup.".format(flake_file), -1)
# Trigger materialization/build of the devShell dependencies once.
# Environment activation still happens outside OpenRAM via `nix develop`.
cmd = [
nix_exe,
"--extra-experimental-features", "nix-command flakes",
"develop",
"--command", "true",
]
result = subprocess.call(cmd, cwd=repo_root)
if result != 0:
debug.error("Failed to initialize Nix toolchain (nix develop returned {}).".format(result), -1)
return
def setup_bitcell(): def setup_bitcell():
@@ -446,14 +469,7 @@ def find_exe(check_exe):
Check if the binary exists in any path dir and return the full path. Check if the binary exists in any path dir and return the full path.
""" """
# Search for conda setup if used search_path = os.environ["PATH"]
if OPTS.use_conda:
from openram import CONDA_HOME
search_path = "{0}/bin{1}{2}".format(CONDA_HOME,
os.pathsep,
os.environ["PATH"])
else:
search_path = os.environ["PATH"]
# Check if the preferred spice option exists in the path # Check if the preferred spice option exists in the path
for path in search_path.split(os.pathsep): for path in search_path.split(os.pathsep):
+3 -3
View File
@@ -151,9 +151,9 @@ class options(optparse.Values):
################### ###################
# Top process that was ran (openram, memchar, memfunc) # Top process that was ran (openram, memchar, memfunc)
top_process = None top_process = None
# Use conda to install the default tools # Use Nix to initialize the default open-source toolchain.
# (existing tools will be used if disabled) # If disabled, OpenRAM uses whatever tools are already in PATH.
use_conda = True use_nix = True
# Variable to select the variant of spice # Variable to select the variant of spice
spice_name = None spice_name = None
# The spice executable being used which is derived from the user PATH. # The spice executable being used which is derived from the user PATH.
+11 -16
View File
@@ -29,26 +29,21 @@ def run_script(cell_name, script="lvs"):
scriptpath = '{0}run_{1}.sh'.format(OPTS.openram_temp, script) scriptpath = '{0}run_{1}.sh'.format(OPTS.openram_temp, script)
# Wrap with conda activate & conda deactivate
if OPTS.use_conda:
from openram import CONDA_HOME
with open(scriptpath, "r") as f:
script_content = f.readlines()
with open(scriptpath, "w") as f:
# First line is shebang
f.write(script_content[0])
# Activate conda using the activate script
f.write("source {}/bin/activate\n".format(CONDA_HOME))
for line in script_content[1:]:
f.write(line)
# Deactivate conda at the end
f.write("conda deactivate\n")
debug.info(2, "Starting {}".format(scriptpath)) debug.info(2, "Starting {}".format(scriptpath))
start = time.time() start = time.time()
with open(outfile, 'wb') as fo, open(errfile, 'wb') as fe: with open(outfile, 'wb') as fo, open(errfile, 'wb') as fe:
if OPTS.use_nix:
p_cmd = [
"nix",
"--extra-experimental-features", "nix-command flakes",
"develop",
"--command",
scriptpath,
]
else:
p_cmd = [scriptpath]
p = subprocess.Popen( p = subprocess.Popen(
[scriptpath], stdout=fo, stderr=fe, cwd=OPTS.openram_temp) p_cmd, stdout=fo, stderr=fe, cwd=OPTS.openram_temp)
if echo_cmd_output: if echo_cmd_output:
tailo = subprocess.Popen([ tailo = subprocess.Popen([
+15 -42
View File
@@ -7,8 +7,8 @@ This page shows the basic setup for using OpenRAM to generate an SRAM.
## Table of Contents ## Table of Contents
1. [Dependencies](#dependencies) 1. [Dependencies](#dependencies)
1. [Anaconda](#anaconda) 1. [Nix](#nix)
1. [Docker](#docker-deprecated-use-anaconda-instead) 1. [Docker](#docker-deprecated-use-nix-instead)
1. [Environment](#environment) 1. [Environment](#environment)
1. [Sky130 Setup](#sky130-setup) 1. [Sky130 Setup](#sky130-setup)
@@ -20,51 +20,25 @@ In general, the OpenRAM compiler has very few dependencies:
+ Make + Make
+ Python 3.5 or higher + Python 3.5 or higher
+ Various Python packages (pip install -r requirements.txt) + Various Python packages (pip install -r requirements.txt)
+ Anaconda + Nix
## Anaconda ## Nix
We use Anaconda package manager to install the tools used by OpenRAM. This way, OpenRAM uses Nix to provide the external toolchain (layout tools, simulators,
you don't have to worry about updating/installing these tools. OpenRAM installs etc.) needed for SRAM generation.
Anaconda silently in the background (without affecting any existing Anaconda
setup you have).
You don't have to manually activate/deactivate the Anaconda environment. OpenRAM Enter the Nix development environment with:
automatically manages this before and after running the tools.
OpenRAM uses Anaconda by default, but you can turn this feature off by setting
`use_conda = False` in your config file. Then, OpenRAM will use the tools you
have installed on your system.
You can also tell OpenRAM where Anaconda should be installed or which Anaconda
setup it should use. You can set the `$CONDA_HOME` variable like this:
``` ```
export CONDA_HOME="/path/to/conda/setup" nix develop
``` ```
> **Note**: If you want to install Anaconda without running OpenRAM (for example Within the devShell, required executables are available on `PATH`
> to run unit tests, which do not install Anaconda), you can run:
> ```
> ./install_conda.sh
> ```
> **Note**: You can uninstall OpenRAM's Anaconda installation by simply deleting OpenRAM uses the `use_nix` option (enabled by default) to initialize Nix-based
> the folder Anaconda is installed to. You can run: tool dependencies via `nix develop`.
> ```
> rm -rf miniconda
> ```
> **Note**: You can change a tool's version with the following commands: ## Docker (deprecated, use Nix instead)
> ```
> source ./miniconda/bin/activate
> conda uninstall <tool>
> conda install -y -c vlsida-eda <tool>=<version>
> ```
## Docker (deprecated, use Anaconda instead)
We have a [docker setup](../../docker) to run OpenRAM. To use this, you should We have a [docker setup](../../docker) to run OpenRAM. To use this, you should
run: run:
``` ```
@@ -124,12 +98,11 @@ make sky130-pdk
This will use ciel to get the PDK. This will use ciel to get the PDK.
> **Note**: If you don't have Magic installed, you need to install and activate > **Note**: If you don't have Magic installed, enter the OpenRAM Nix devShell
> the conda environment before running this command. You can run: > first (it provides Magic and other tools via `PATH`):
> >
> ``` > ```
> ./install_conda.sh > nix develop
> source miniconda/bin/activate
> ``` > ```
Then you must also install the [Sky130] SRAM build space with the appropriate Then you must also install the [Sky130] SRAM build space with the appropriate
+3 -4
View File
@@ -61,10 +61,9 @@ make -j 3
``` ```
The `-j` can run with 3 threads. By default, this will run in all technologies. The `-j` can run with 3 threads. By default, this will run in all technologies.
> **Note**: If you have not run openram before running unit tests, the conda > **Note**: The external EDA toolchain is provided by the Nix devShell.
> environment will not be installed. You can install it by running > If you run unit tests without being in a Nix environment, enter it first:
> `OpenRAM/install_conda.sh` (see [Basic Setup](basic_setup.md#anaconda) for > `nix develop` (see [Basic Setup](basic_setup.md#nix) for more details).
> more details).
To run a specific test in all technologies: To run a specific test in all technologies:
``` ```
+1 -1
View File
@@ -40,7 +40,7 @@ In general, the OpenRAM compiler has very few dependencies:
+ Make + Make
+ Python 3.5 or higher + Python 3.5 or higher
+ Various Python packages (pip install -r requirements.txt) + Various Python packages (pip install -r requirements.txt)
+ Anaconda + Nix
Commercial tools (optional): Commercial tools (optional):
* Spice Simulator * Spice Simulator
+3 -3
View File
@@ -11,7 +11,7 @@ In this section, the detailed usage of using OpenRAM framework will be demonstra
> >
> Before you go through, make sure that environment of Sky130 has been already set up. > Before you go through, make sure that environment of Sky130 has been already set up.
1. Activate miniconda 1. Enter the Nix devShell
2. Edit the sram configuration file 2. Edit the sram configuration file
@@ -19,11 +19,11 @@ In this section, the detailed usage of using OpenRAM framework will be demonstra
4. Check the results 4. Check the results
#### Activate miniconda #### Enter Nix devShell
```bash ```bash
cd OpenRAM/ cd OpenRAM/
source ./miniconda/bin/activate nix develop
``` ```
#### Modified the sram configuration #### Modified the sram configuration
Generated
+27
View File
@@ -0,0 +1,27 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1777270315,
"narHash": "sha256-yKB4G6cKsQsWN7M6rZGk6gkJPDNPIzT05y4qzRyCDlI=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "6368eda62c9775c38ef7f714b2555a741c20c72d",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}
+48
View File
@@ -0,0 +1,48 @@
{
description = "OpenRAM development environment (Nix)";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
};
outputs = { self, nixpkgs }:
let
systems = [ "x86_64-linux" ];
forAllSystems = f: nixpkgs.lib.genAttrs systems (system: f system);
in
{
devShells = forAllSystems (system:
let
pkgs = import nixpkgs { inherit system; };
in
{
default = pkgs.mkShell {
packages = [
# EDA / verification tools
pkgs.klayout
pkgs.magic-vlsi
# Use the LVS-focused netgen package; the generic netgen package
# may require a local build that can fail on some hosts.
pkgs.netgen-vlsi
pkgs.ngspice
pkgs.iverilog
pkgs.xyce
pkgs.xyce-parallel
pkgs.trilinos
pkgs.trilinos-mpi
# Dev conveniences
pkgs.git
pkgs.gnumake
pkgs.curl
];
shellHook = ''
export OPENRAM_USE_CONDA=0
echo "OpenRAM: using tools from Nix devShell"
'';
};
});
};
}
-46
View File
@@ -1,46 +0,0 @@
#!/bin/bash
#CONDA_INSTALLER_URL="https://repo.anaconda.com/miniconda/Miniconda3-py313_25.11.1-1-Linux-x86_64.sh"
#CONDA_INSTALLER_FILE="miniconda_installer_py313.sh"
CONDA_INSTALLER_URL="https://repo.anaconda.com/miniconda/Miniconda3-py38_23.11.0-2-Linux-x86_64.sh"
CONDA_INSTALLER_FILE="miniconda_installer_py38.sh"
CONDA_HOME="${CONDA_HOME:-miniconda}"
# The tool name format is "<tool>=<version>".
# If you want to use the latest version, just use "<tool>".
TOOLS=""
TOOLS+="klayout=0.28.3 "
TOOLS+="magic=8.3.587 "
TOOLS+="netgen=1.5.286 "
TOOLS+="ngspice=26 "
TOOLS+="trilinos=12.12.1=1 "
TOOLS+="xyce=7.4"
# Install miniconda if not already installed
if [[ ! -d "${CONDA_HOME}/bin" ]]
then
curl -s -o ${CONDA_INSTALLER_FILE} ${CONDA_INSTALLER_URL}
/bin/bash ${CONDA_INSTALLER_FILE} -b -p ${CONDA_HOME}
rm ${CONDA_INSTALLER_FILE}
source ${CONDA_HOME}/bin/activate
# Prioritize channels to prevent version conflicts
conda config --add channels conda-forge
conda config --add channels vlsida-eda
#conda install -q -y -c conda-forge trilinos
# Install rest of the tools from vlsida-eda
for tool in ${TOOLS}
do
conda install -q -y -c vlsida-eda ${tool}
done
# Install iverilog from conda-eda
conda install -q -y -c litex-hub iverilog
# Install required Python packages
# (This step isn't required but used to prevent possible issues)
python3 -m pip install -r requirements.txt --ignore-installed
conda deactivate
fi
+1 -1
View File
@@ -11,7 +11,7 @@ from setuptools import setup, find_namespace_packages
# Include these folder from the root of repo as submodules # Include these folder from the root of repo as submodules
include = ["compiler", "docker", "technology", "macros"] include = ["compiler", "docker", "technology", "macros"]
# Exclude files/folders with these words # Exclude files/folders with these words
exclude = ["docs", "images", "miniconda"] exclude = ["docs", "images"]
# Find all modules inside the 'compiler' folder # Find all modules inside the 'compiler' folder