Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions .cockpitrc
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
# ez130_8t_stdcell_v0
# ez130_8t_stdcell_v0.12
# ez130_8t_stdcell_v1.0
# ez130_8t_stdcell_v1.1
# ez130_7t_stdcell_v0
#
# memories : RM_IHPSG13_v1.0
Expand All @@ -63,7 +64,7 @@
#

libs = SG13CMOS5L_0.2 \
open_stdcell_rev0.1.3 \
ez130_8t_stdcell_v1.1 \
sg13cmos5l_io_v0.1 \
open_sram_v2.2 \
bondpad5l_70x70_v0
Expand Down Expand Up @@ -146,7 +147,7 @@
innovus = xterm -g 136x40 -T innovus-21.13 -e "cds_innovus-21.13.000 innovus"
calibre = xterm -g 120x40 -T calibredrv-2021.3 -e "./start_calibre 2021.3"
dfii = ./start_dfii
yosys = xterm -g 120x40 -T yosys -e "oseda -2026.02 yosys -C"
openroad = xterm -g 120x40 -T openroad -e "oseda -2026.02 openroad -gui"
yosys = xterm -g 120x40 -T yosys -e "oseda -2026.09 yosys -C"
openroad = xterm -g 120x40 -T openroad -e "oseda -2026.09 openroad -gui"
klayout = xterm -g 120x40 -T klayout -e "./start_klayout"
dz:llama = llama
9 changes: 7 additions & 2 deletions .github/scripts/report_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ def module_label(instance_name, modules):
return "Other logic"


def is_nand2(name):
# plain two-input NAND (NAND2X1, NAND2X1P5, ...), not the NAND2B variants with an inverted input
return re.search(r"(?:^|_)nand2(?=x|_|\d|$)", name, re.IGNORECASE) is not None


def database_metrics(path, modules):
db = odb.dbDatabase.create()
odb.read_db(db, str(path))
Expand All @@ -130,7 +135,7 @@ def area(master):
area(master)
for library in db.getLibs()
for master in library.getMasters()
if str(master.getType()) == "CORE" and re.search(r"(?:^|_)nand2(?:_|$)", master.getName(), re.IGNORECASE)
if str(master.getType()) == "CORE" and is_nand2(master.getName())
]
if not nand_areas or min(nand_areas) <= 0:
raise ValueError("No positive-area NAND2 master for GE reference")
Expand Down Expand Up @@ -188,7 +193,7 @@ def main():
raise ValueError(f"Invalid source SHA {sha!r}")
metrics = {
"source_sha": sha,
"technology": os.environ.get("CROC_PDK", "sg13cmos5l"),
"technology": "sg13cmos5l",
**database_metrics(root / "openroad/out/croc.odb", modules),
**timing_metrics(
(root / "openroad/reports/05_croc.final.rpt").read_text(),
Expand Down
2 changes: 0 additions & 2 deletions .github/scripts/run_sim_flow.sh
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,6 @@ if [[ "$simulation_mode" == "rtl" ]]; then
simulation_binary="obj_dir_rtl/Vtb_croc_soc"
simulation_log="croc_rtl.log"
else
export CROC_PDK=sg13cmos5l

default_netlist="yosys/out/croc_yosys_debug.v"
idma_netlist="yosys/out/croc_idma_yosys_debug.v"
for required_file in \
Expand Down
10 changes: 8 additions & 2 deletions .github/scripts/test_report_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,12 @@ def test_missing_and_duplicate_timing_rejected(self):
metrics.timing_metrics(self.report.replace("0.4431", "1.1"), self.sdc)

def test_functional_classification(self):
self.assertEqual(metrics.category(Master("sg13g2_buf_1")), "Logic cells")
self.assertEqual(metrics.category(Master("BUFX2")), "Logic cells")
self.assertEqual(metrics.category(Master("pad", "PAD_POWER")), "Signal + power pads")
self.assertEqual(metrics.category(Master("memory", "BLOCK")), "Macros")
for master in (
Master("filler", "CORE_SPACER"),
Master("sg13g2_decap_1"),
Master("DECAP4"),
Master("antenna", "CORE_ANTENNACELL"),
Master("bondpad", "COVER"),
):
Expand All @@ -90,6 +90,12 @@ def test_modules_use_boundaries_and_deepest_owner(self):
self.assertEqual(metrics.module_label("soc/gen_sram_bank[1].cell", modules), "SRAM")
self.assertEqual(metrics.module_label("soc/i_uart2/cell", modules), "UART")

def test_nand2_reference(self):
for name in ("NAND2X1", "NAND2X1P5", "NAND2X4", "nand2_1"):
self.assertTrue(metrics.is_nand2(name), name)
for name in ("NAND2BX1", "NAND3X1", "AND2X1", "NOR2X1"):
self.assertFalse(metrics.is_nand2(name), name)


if __name__ == "__main__":
suite = unittest.defaultTestLoader.loadTestsFromTestCase(MetricsTests)
Expand Down
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ __pycache__/
/.setPDK.csh
# public PDK mirror
/ihp13/pdk/gds/*.gds
!/ihp13/pdk/gds/bondpad_70x70.gds
!/ihp13/pdk/gds/bondpad5l_70x70.gds
# dfii
/dfii/
Expand Down
30 changes: 12 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Croc System-on-Chip

A simple SoC for education using PULP IPs. Croc includes all scripts necessary to produce a nearly finished chip in [IHPs open-source 130nm technology](https://github.com/IHP-GmbH/IHP-Open-PDK/tree/main).
A simple SoC for education using PULP IPs. Croc includes all scripts necessary to produce a nearly finished chip in [IHPs open-source 130nm technology](https://github.com/IHP-GmbH/IHP-Open-PDK/tree/main), using the open [EZ130 8T standard cells](https://iip.ethz.ch/ez-library/ihp130-8t.html) and the 5-metal CMOS5L back-end.

As it is oriented towards education, it forgoes some configurability to increase readability of the RTL and scripts.

Expand Down Expand Up @@ -94,11 +94,11 @@ graph LR;
## Requirements

We are using the excellent docker container maintained by Harald Pretl. If you get stuck with installing the tools, we urge you to check the [Tool Repository](https://github.com/iic-jku/IIC-OSIC-TOOLS).
The current supported version is 2025.12, no other version is officially supported.
The current supported version is 2026.09, no other version is officially supported.

### ETHZ systems

ETHZ Design Center maintains an internal version of the IHP PDK, with integrations into all tools we have access to. For this reason if you work on the ETH systems, it is recommended to use the `icdesign` tool (cockpit) instead of the linked GitHub PDK repositories.
ETHZ Design Center maintains an internal version of the IHP PDK, with integrations into all tools we have access to, including the EZ130 8T standard cells. For this reason if you work on the ETH systems, it is recommended to use the `icdesign` tool (cockpit) instead of the linked GitHub PDK repositories.
You can directly create a cockpit `technology/` directory inside the Croc repository:

```sh
Expand All @@ -113,7 +113,7 @@ You may want to start a shell in the pre-installed osic-tools container using:

```sh
oseda bash
# specific version eg: oseda -2025.12 bash
# specific version eg: oseda -2026.09 bash
```

### Other systems
Expand Down Expand Up @@ -160,19 +160,16 @@ You need to build/install the required tools manually:

### PDK versions and sources

The ASIC flow supports two IHP PDKs selected via the `CROC_PDK` environmental variable:
The ASIC flow uses the [EZ130 8T standard-cell library](https://iip.ethz.ch/ez-library/ihp130-8t.html) with the IHP SG13CMOS5L 5-metal back-end, the SG13CMOS5L IO cells, and the IHP SRAM macros.
Synthesis, place and route, simulation, and DEF-to-GDS conversion all use one active view:

- `sg13cmos5l`: the default 5-metal CMOS5L option.
- `sg13g2`: the original SG13G2 7-metal option.

`CROC_PDK` is the only PDK setting users select. There is one active view used by synthesis, place and route, simulation, and DEF-to-GDS conversion:

- `technology/`: Liberty, LEF, Verilog models, and GDS files for the selected PDK.
- `technology/`: Liberty, LEF, Verilog models, and GDS files of these libraries.

On ETH systems, the `technology/` directory is set up by the ETHZ Design Center cockpit and takes priority.
Outside ETH, `env.sh` creates `technology -> ihp13/pdk` symbolic link on demand if `technology/` does not already exist.
If you use the EZ130 8T cells, please cite the reference given in `ihp13/pdk/licenses/NOTICE.ez130_8t`.
The committed `ihp13/pdk` mirror contains the Apache-2.0 Liberty, LEF, and Verilog files needed by the flow.
The two Croc bondpad GDS files are committed in `ihp13/pdk/gds`; IHP GDS files are kept out of git and can be downloaded with:
The Croc bondpad GDS file is committed in `ihp13/pdk/gds`; the EZ130 8T, IO, and SRAM GDS files are kept out of git and can be downloaded with:

```sh
scripts/download_gds.sh
Expand All @@ -184,8 +181,8 @@ Maintainers can update the pinned PDK mirror with `scripts/update_pdk.sh`.
You can also run `scripts/setup_technology.sh` manually to print the active technology view. `env.sh` runs the same setup quietly before the ASIC scripts use the PDK.

KLayout needs technology scripts, filling rules, and layer properties in addition to the files mentioned above.
KLayout tool files are always taken from the pinned PDK submodule, either
`ihp13/sg13cmos5l` or `ihp13/sg13g2`.
KLayout tool files are taken from the pinned `ihp13/sg13cmos5l` submodule.
It relies on `ihp13/sg13g2` for the shared PCell API and default DRC rules.

The OSIC/oseda container also contains a PDK under `/foss/pdks`, but Croc does not currently use it.

Expand Down Expand Up @@ -221,17 +218,14 @@ Use `./run_drc.sh --full` when reviewing the final layout before tapeout. It
runs the slower and stricter checks across all layers. Full DRC is the default
when no mode is specified.

The ASIC flow defaults to `CROC_PDK=sg13cmos5l`.
To switch back to the original metal stack, export `CROC_PDK=sg13g2` before running the scripts.

ArtistIC uses [`artistic/croc.toml`](artistic/croc.toml) to generate the logo,
chip images, module outlines, and layer map. Outlines use the matching placed
DEF in `openroad/out/croc.def`. Host image processing needs Python 3.11+,
Pillow, img2pdf, Inkscape, and potrace. Run the GDS stages in OSEDA:

```sh
make -C artistic/artistic PROJECT=../croc.toml logo-prepare
oseda -2025.12 bash -c 'source env.sh; make -C artistic/artistic PROJECT=../croc.toml logo-merge render-generate map-generate'
oseda -2026.09 bash -c 'source env.sh; make -C artistic/artistic PROJECT=../croc.toml logo-merge render-generate map-generate'
make -C artistic/artistic PROJECT=../croc.toml render-compose render-annotate map-build
```

Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

services:
pulp-docker:
image: hpretl/iic-osic-tools:2025.12
image: hpretl/iic-osic-tools:2026.09
environment:
- UID=${UID}
- GID=${GID}
Expand Down
92 changes: 4 additions & 88 deletions env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,49 +20,11 @@ echo "[INFO][ENV] Croc root: $CROC_ROOT"
######################
export PROJ_NAME="${PROJ_NAME:-croc}"
export TOP_DESIGN="${TOP_DESIGN:-croc_chip}"
if [[ -z "${CROC_PDK:-}" ]]; then
if [[ "${PDK:-}" == "sg13g2" || "${PDK:-}" == "sg13cmos5l" ]]; then
echo "[WARNING][ENV] Ignoring PDK=$PDK. Use CROC_PDK to select the Croc PDK."
fi
export CROC_PDK="sg13cmos5l"
fi

# Explicit file basenames used by downstream scripts. Directory/source
# selection lives below; cell names and basenames stay spelled out here.
export PDK_STDCELL_LEF_FILE="sg13g2_stdcell.lef"
export PDK_STDCELL_GDS_FILE="sg13g2_stdcell.gds"
export PDK_STDCELL_LIB_TT_FILE="sg13g2_stdcell_typ_1p20V_25C.lib"
export PDK_STDCELL_LIB_FF_FILE="sg13g2_stdcell_fast_1p32V_m40C.lib"
export CROC_TECHNOLOGY_VIEW=""

case "$CROC_PDK" in
sg13cmos5l)
export BENDER_PDK_ARGS="-D IHP_SG13CMOS5L=1"
export PDK_TECH_LEF_FILE="sg13cmos5l_tech.lef"
export PDK_IO_LEF_FILE="sg13cmos5l_io.lef"
export PDK_IO_GDS_FILE="sg13cmos5l_io.gds"
export PDK_IO_LIB_TT_FILE="sg13cmos5l_io_typ_1p2V_3p3V_25C.lib"
export PDK_IO_LIB_FF_FILE="sg13cmos5l_io_fast_1p32V_3p6V_m40C.lib"
export PDK_BONDPAD_LEF="bondpad5l_70x70.lef"
export PDK_BONDPAD_GDS="bondpad5l_70x70.gds"
export KLAYOUT_PATH="$CROC_ROOT/ihp13/sg13cmos5l/libs.tech/klayout"
;;
sg13g2)
export BENDER_PDK_ARGS=""
export PDK_TECH_LEF_FILE="sg13g2_tech.lef"
export PDK_IO_LEF_FILE="sg13g2_io.lef"
export PDK_IO_GDS_FILE="sg13g2_io.gds"
export PDK_IO_LIB_TT_FILE="sg13g2_io_typ_1p2V_3p3V_25C.lib"
export PDK_IO_LIB_FF_FILE="sg13g2_io_fast_1p32V_3p6V_m40C.lib"
export PDK_BONDPAD_LEF="bondpad_70x70.lef"
export PDK_BONDPAD_GDS="bondpad_70x70.gds"
export KLAYOUT_PATH="$CROC_ROOT/ihp13/sg13g2/ihp-sg13g2/libs.tech/klayout"
;;
*)
echo "[ERROR][ENV] Unknown CROC_PDK '$CROC_PDK'" >&2
return 1 2>/dev/null || exit 1
;;
esac
# KLayout tooling comes from the pinned IHP SG13CMOS5L submodule
export KLAYOUT_PATH="$CROC_ROOT/ihp13/sg13cmos5l/libs.tech/klayout"
export KLAYOUT_TECH="sg13cmos5l"
export PDK_LAYER_MAP_FILE="$KLAYOUT_PATH/tech/sg13cmos5l.map"


###################
Expand All @@ -72,7 +34,6 @@ esac
# Verilog, and GDS files. Cockpit provides it on ETH systems; elsewhere,
# env.sh creates a link to ihp13/pdk.

PUBLIC_PDK_ROOT="$CROC_ROOT/ihp13/pdk"
if [[ "${CROC_SKIP_TECH_SETUP:-0}" != "1" ]]; then
if ! "$CROC_ROOT/scripts/setup_technology.sh" --quiet; then
return 1 2>/dev/null || exit 1
Expand All @@ -81,49 +42,4 @@ else
echo "[INFO][ENV] Skipping technology setup"
fi

if [[ -e "${CROC_ROOT}/technology" || ( "${CROC_SKIP_TECH_SETUP:-0}" == "1" && -d "$PUBLIC_PDK_ROOT" ) ]]; then

if [[ -e "${CROC_ROOT}/technology" ]]; then
export PDK_ROOT="$CROC_ROOT/technology"
else
# Dry runs use the public mirror directly without creating technology/.
export PDK_ROOT="$PUBLIC_PDK_ROOT"
fi
public_pdk_realpath="$(realpath -m "$PUBLIC_PDK_ROOT")"
technology_realpath="$(realpath -m "$PDK_ROOT")"
if [[ "$technology_realpath" == "$public_pdk_realpath" ]]; then
export CROC_TECHNOLOGY_VIEW="public mirror"
else
export CROC_TECHNOLOGY_VIEW="local technology directory"
fi

export PDK_DIR_LEF_TECH="$PDK_ROOT/lef"
export PDK_DIR_LEF_CELLS="$PDK_ROOT/lef"
export PDK_DIR_LEF_SRAMS="$PDK_ROOT/lef"
export PDK_DIR_LEF_IOS="$PDK_ROOT/lef"
export PDK_DIR_LEF_BOND="$PDK_ROOT/lef"
export PDK_DIR_LIB_CELLS="$PDK_ROOT/lib"
export PDK_DIR_LIB_SRAMS="$PDK_ROOT/lib"
export PDK_DIR_LIB_IOS="$PDK_ROOT/lib"
export PDK_DIR_GDS_CELLS="$PDK_ROOT/gds"
export PDK_DIR_GDS_SRAMS="$PDK_ROOT/gds"
export PDK_DIR_GDS_IOS="$PDK_ROOT/gds"
export PDK_DIR_GDS_BOND="$PDK_ROOT/gds"

else
echo "[WARNING][ENV] PDK not found. Initialize cockpit or ensure ihp13/pdk exists"
export PDK_ROOT="" # Set to empty to avoid unbound variable error
export KLAYOUT_PATH="" # Set to empty to avoid unbound variable error
fi

echo "[INFO][ENV] PDK root: $PDK_ROOT"
echo "[INFO][ENV] Croc PDK: $CROC_PDK"
echo "[INFO][ENV] Active technology view: ${CROC_TECHNOLOGY_VIEW:-<none>}"
echo "[INFO][ENV] KLayout path: $KLAYOUT_PATH"
echo "[INFO][ENV] Bender PDK args: ${BENDER_PDK_ARGS:-<none>}"
echo "[INFO][ENV] Tech LEF: $PDK_TECH_LEF_FILE"
echo "[INFO][ENV] IO LEF/GDS: $PDK_IO_LEF_FILE/$PDK_IO_GDS_FILE"
echo "[INFO][ENV] IO Liberty tt/ff: $PDK_IO_LIB_TT_FILE/$PDK_IO_LIB_FF_FILE"
echo "[INFO][ENV] Bondpad LEF/GDS: $PDK_BONDPAD_LEF/$PDK_BONDPAD_GDS"
export KLAYOUT_TECH="$CROC_PDK"
export PDK_LAYER_MAP_FILE="$KLAYOUT_PATH/tech/${CROC_PDK}.map"
Loading
Loading