CIM-E optimizes BNN and TNN inference for RRAM crossbars. It uses the mappings and the crossbar simulator from analog-cim-sim.
If you find this repository helpful, please consider citing the corresponding paper:
@misc{pelke2025optimizingbinaryternaryneural,
title={{Optimizing Binary and Ternary Neural Network Inference on RRAM Crossbars using CIM-Explorer}},
author={Rebecca Pelke and José Cubero-Cascante and Nils Bosbach and Niklas Degener and Florian Idrizi and Lennart M. Reimann and Jan Moritz Joseph and Rainer Leupers},
year={2025},
eprint={2505.14303},
archivePrefix={arXiv},
primaryClass={cs.ET},
url={https://arxiv.org/abs/2505.14303},
}
To build the project, you need cmake and a dev version of python. If you don't have python3-dev, the simulator won't compile.
The following steps were tested with Python3.10 and Python3.11.
-
Clone the repository including submodules:
git clone --recursive https://github.com/rpelke/CIM-E.git
-
Download the pre-compiled BNNs/TNNs:
./models/download_models.bash
-
Download the docker image OR build the image from scratch:
Build image from scratch (recommended):
docker build -f docker/build_simulator.dockerfile -t cim-e .Download the pre-built image (attention: this image belongs to the latest commit on the
mainbranch):docker pull docker.io/pelke/cim-e:latest
This project is designed to run rootless, so you can also use
podman. Make surepodman-dockeris installed or create an alias for docker that points to podman.
The benchmarks can be executed with either docker or podman. The default is docker.
If you want to use podman, please execute export CONTAINER_ENGINE=podman before staring the scripts below.
-
Execute the benchmarks inside the container:
The name of the test is the input argument.
./scripts/benchmark.bash exp_name=test n_jobs=8 ./scripts/benchmark.bash exp_name=adc n_jobs=8 ./scripts/benchmark.bash exp_name=lrs_var n_jobs=8 ./scripts/benchmark.bash exp_name=hrs_var n_jobs=8 ./scripts/benchmark.bash exp_name=adc_vgg7 n_jobs=8 ./scripts/benchmark.bash exp_name=parasitics n_jobs=8
Optional arguments:
use_same_inputs=True # Use the same IFMs for each run save_sim_stats=True # Save simulator stats after execution
-
Visualize the results:
python3 src/plot.py --config <path_to_config>
For example:
python3 src/plot.py --config src/configs/lrs_var.json
-
Create a new file
<exp_name>.jsonin the configs folder. -
Specify all parameters to be used in the design space exploration. Every combination of parameters will be simulated. A tick in the
DSE listcolumn means that a list with several possible parameters can be created here. Otherwise, only aSingle Choiceis possible.Parameter Explanation DSE
ListSingle
ChoiceOptional
Parameternn_namesNames of the neural network architectures ✅ no ifmDimension of the input feature map ✅ no nn_data_setData set ✅ no nn_dataChoise of dataset parts (test or train) ✅ no batchBatch size of input feature map ✅ no num_runsTotal number of images: batch*num_runs✅ no xbar_sizeDimensions of the offloaded matrix (MxN) ✅ no digital_onlyTrue if mappings should use digital values only ✅ no hrs_lrsHRS/LRS current (in uA) if V_read is applied✅ yes gmin_gmaxConductance values (in uS), needs V_read✅ yes adc_typeCurrently only supports FP_ADC_ALPHA✅ no resolutionADC resolution in bit ✅ yes adc_profileEnable ADC input profiling ✅ yes adc_calib_modeCalibration mode for ADC, can be MAXorCALIB✅ yes adc_calib_dictPer-layer calibrated current limits for use with CALIBADC mode✅ yes m_modeMapping mode (see next table) ✅ no hrs_noiseStd. dev. of the gaussian noise (uA) around hrs ✅ no lrs_noiseStd. dev. of the gaussian noise (uA) around lrs ✅ no c2c_varEnable Cycle-to-Cycle variability modeling ✅ yes parasiticsEnable parasitic wire resistance modeling ✅ yes w_resParasitic wire resistance (Ohms) ✅ yes V_readFixed read voltage applied when row is activated ✅ yes verboseEnable verbose output of the simulator ✅ no A brief overview of the mapping modes is given in the tables below:
BNN Mapping Weights Inputs BNN (I) $w_{NN} = g_D^+ - g_D^-$ $i_{NN} = 2 \cdot v_D - 1$ BNN (II) $w_{NN} = g_D^+ - g_D^-$ $i_{NN} = -2 \cdot v_D + 1$ BNN (III) $w_{NN} = 2 \cdot g_D - 1$ $i_{NN} = v_D^+ - v_D^-$ BNN (IV) $w_{NN} = -2 \cdot g_D + 1$ $i_{NN} = v_D^+ - v_D^-$ BNN (V) XOR mapping ( $v_D^+g_D^+ + v_D^-g_D^-$ )BNN (VI) $w_{NN} = g_D^+ - g_D^-$ $i_{NN} = v_D^+ - v_D^-$ TNN Mapping Weights Inputs TNN (I) $w_{NN} = g_D^+ - g_D^-$ $i_{NN} = v_D^+ - v_D^-$ TNN (II) $w_{NN} = g_D^+ - g_D^-$ $i_{NN} = (v_D^1, v_D^0)$ TNN (III) $w_{NN} = g_D^+ - g_D^-$ $i_{NN} + 1 = (v_D^1, v_D^0)$ TNN (IV) $w_{NN} = (g_D^1, g_D^0)$ $i_{NN} = v_D^+ - v_D^-$ TNN (V) $w_{NN} + 1 = (g_D^1, g_D^0)$ $i_{NN} = v_D^+ - v_D^-$
-
Native build of the simulator (without docker):
You need a
python-devversion since pybind11 needs thePython.hheader file.python3 -m venv .venv source .venv/bin/activate pip3 install -r analog-cim-sim/requirements.txt pip3 install -r requirements.txt ./scripts/build_simulator.bash -
Run simulations:
Select the desired configuration file in the configs folder.
python3 src/main.py --config src/configs/test.json --n_jobs 4
Make sure that you create a folder for the results manually beforehand.
-
Test the simulator
analog-cim-simmanually in docker:docker run -it --rm --entrypoint "/bin/bash" \ -v "$PWD/src:/apps/src" \ -v "$PWD/models:/apps/models" \ -v "$PWD/results:/apps/results" \ cim-e source .venv/bin/activate python3 -m unittest discover -s analog-cim-sim/int-bindings/test -p '*_test.py' deactivate && exit
In case you are using podman, change the first command to:
podman run -it --rm --entrypoint "/bin/bash" \ -v "$PWD/src:/apps/src:Z" \ -v "$PWD/models:/apps/models:Z" \ -v "$PWD/results:/apps/results:Z" \ cim-e
-
Debug Python code in VSCode:
Install a Python debugger extension in VSCode and add the following configuration in your
launch.json:{ "name": "Run simulation (Python)", "type": "debugpy", "request": "launch", "program": "${workspaceFolder}/src/main.py", "console": "integratedTerminal", "justMyCode": false, "args": [ "--debug", // Optional: Single-thread execution "--config", "${workspaceFolder}/src/configs/test.json", "--n_jobs", "4", "--use_same_inputs" "--save_sim_stats" ] }The
--debugflag ensures that all simulations are executed in one process and not in several parallel processes.