|
| 1 | +#!/usr/bin/env bash |
| 2 | +set -euo pipefail |
| 3 | + |
| 4 | +# Portable ArtistIC rendering pipeline for Croc |
| 5 | +# Requires: git, gh CLI (for artifact download), python3, make, klayout, inkscape, imagemagick, sed, gzip. |
| 6 | +# Optional: apt-get and sudo for dependency installation. |
| 7 | +# Environment (override as needed): |
| 8 | +# GH_TOKEN - GitHub token with repo read access (needed to download artifacts) |
| 9 | +# REPO - GitHub repo in owner/name form (default: pulp-platform/croc) |
| 10 | +# WF_NAME - Workflow name to source artifacts from (default: "Full Flow") |
| 11 | +# RUN_ID - Workflow run-id to download artifacts from (optional; auto-detect latest successful if empty) |
| 12 | +# ARTIFACT_NAME - Artifact name containing croc GDS (default: croc-gds) |
| 13 | +# ARTISTIC_REF - Artistic commit-ish to use (default pinned to known-good) |
| 14 | +# WORKDIR - Working directory (default: repo root) |
| 15 | + |
| 16 | +log() { echo "[artistic] $*"; } |
| 17 | +err() { echo "[artistic][error] $*" >&2; } |
| 18 | + |
| 19 | +ROOT=${WORKDIR:-"$(git -C "$(pwd)" rev-parse --show-toplevel 2>/dev/null || pwd)"} |
| 20 | +REPO=${REPO:-"pulp-platform/croc"} |
| 21 | +WF_NAME=${WF_NAME:-"Full Flow"} |
| 22 | +RUN_ID=${RUN_ID:-""} |
| 23 | +ARTIFACT_NAME=${ARTIFACT_NAME:-"croc-gds"} |
| 24 | +ARTISTIC_REF=${ARTISTIC_REF:-"33986fa39e07d89a8337d65e84b01113bf18ea03"} |
| 25 | + |
| 26 | +ARTISTIC_DIR="${ROOT}/artistic" |
| 27 | +KLAYOUT_DIR="${ROOT}/klayout" |
| 28 | +RENDER_DIR="${ARTISTIC_DIR}/renderics" |
| 29 | +MAPIFY_DIR="${ARTISTIC_DIR}/mapify" |
| 30 | +LOGO_SRC="${ROOT}/doc/artwork/logo_chip.svg" |
| 31 | +LOGO_OUT="${ROOT}/doc/artwork/logo.svg" |
| 32 | +LOGO_PNG="${ROOT}/doc/artwork/logo.png" |
| 33 | + |
| 34 | +if [[ -z "${GH_TOKEN:-}" ]]; then |
| 35 | + err "GH_TOKEN is required to download artifacts via gh CLI."; exit 1; |
| 36 | +fi |
| 37 | + |
| 38 | +check_cmd() { |
| 39 | + if ! command -v "$1" >/dev/null 2>&1; then |
| 40 | + err "Missing required tool: $1"; return 1; fi |
| 41 | +} |
| 42 | + |
| 43 | +# Try installing common deps if apt-get is available and the tool is missing. |
| 44 | +maybe_install() { |
| 45 | + local pkg=$1; local bin=$2 |
| 46 | + if command -v "$bin" >/dev/null 2>&1; then return 0; fi |
| 47 | + if command -v apt-get >/dev/null 2>&1; then |
| 48 | + log "Installing $pkg via apt-get"; |
| 49 | + sudo apt-get update -y >/dev/null |
| 50 | + sudo apt-get install -y "$pkg" |
| 51 | + else |
| 52 | + err "Please install $pkg (provides $bin) manually."; return 1; |
| 53 | + fi |
| 54 | +} |
| 55 | + |
| 56 | +# Ensure core tools |
| 57 | +for tool in git gh python3 make sed gzip; do check_cmd "$tool"; done |
| 58 | +maybe_install inkscape inkscape || true |
| 59 | +maybe_install imagemagick convert || true |
| 60 | +maybe_install klayout klayout || true |
| 61 | + |
| 62 | +# Python deps |
| 63 | +python3 - <<'PY' |
| 64 | +import importlib, subprocess, sys |
| 65 | +missing=[] |
| 66 | +for m in ("gdspy",): |
| 67 | + try: |
| 68 | + importlib.import_module(m) |
| 69 | + except ImportError: |
| 70 | + missing.append(m) |
| 71 | +if missing: |
| 72 | + cmd=[sys.executable, "-m", "pip", "install", "--break-system-packages", *missing] |
| 73 | + print("Installing python deps:", " ".join(missing)) |
| 74 | + subprocess.check_call(cmd) |
| 75 | +PY |
| 76 | + |
| 77 | +# Download GDS artifact |
| 78 | +mkdir -p "$KLAYOUT_DIR" |
| 79 | +if [[ -z "$RUN_ID" ]]; then |
| 80 | + log "Resolving latest run-id for workflow '$WF_NAME' in $REPO" |
| 81 | + RUN_ID=$(gh run --repo "$REPO" list --workflow "$WF_NAME" --json databaseId,status,conclusion --jq '[.[]|select(.conclusion=="success")][0].databaseId') |
| 82 | +fi |
| 83 | +if [[ -z "$RUN_ID" ]]; then |
| 84 | + err "Could not resolve a successful run for workflow '$WF_NAME'"; exit 1; |
| 85 | +fi |
| 86 | +log "Downloading artifact '$ARTIFACT_NAME' from run $RUN_ID" |
| 87 | +GH_TOKEN="$GH_TOKEN" gh run download --repo "$REPO" --name "$ARTIFACT_NAME" --run-id "$RUN_ID" --dir "$KLAYOUT_DIR" |
| 88 | + |
| 89 | +# Clone Artistic |
| 90 | +if [[ ! -d "$ARTISTIC_DIR/.git" ]]; then |
| 91 | + log "Cloning Artistic repo" |
| 92 | + git clone --depth 1 --branch "$ARTISTIC_REF" https://github.com/pulp-platform/artistic.git "$ARTISTIC_DIR" |
| 93 | +else |
| 94 | + log "Updating Artistic repo" |
| 95 | + git -C "$ARTISTIC_DIR" fetch --depth 1 origin "$ARTISTIC_REF" |
| 96 | + git -C "$ARTISTIC_DIR" checkout "$ARTISTIC_REF" |
| 97 | +fi |
| 98 | + |
| 99 | +# Create working dirs |
| 100 | +mkdir -p "$RENDER_DIR" "$MAPIFY_DIR" "$ARTISTIC_DIR/meerkat_work" |
| 101 | + |
| 102 | +# Prepare logo |
| 103 | +if [[ -f "$LOGO_SRC" ]]; then |
| 104 | + log "Customizing logo" |
| 105 | + sed "s/#DATE#/$(date '+%Y-%m-%d')/g" "$LOGO_SRC" > "$LOGO_OUT" |
| 106 | + sed -i "s/#HASH#/$(git -C "$ROOT" rev-parse --short HEAD)/g" "$LOGO_OUT" |
| 107 | + sed -i "s|#REPO#|gh.io/${REPO}|g" "$LOGO_OUT" |
| 108 | + inkscape "$LOGO_OUT" -w 660 -h 660 -o "$LOGO_PNG" |
| 109 | +else |
| 110 | + err "Logo source not found at $LOGO_SRC"; exit 1; |
| 111 | +fi |
| 112 | + |
| 113 | +# Convert to mono for mapify |
| 114 | +convert "$LOGO_PNG" -remap pattern:gray50 "$ARTISTIC_DIR/meerkat_work/logo_mono.png" |
| 115 | + |
| 116 | +# Run meerkat interface (top-level GDS preparation) |
| 117 | +log "Running meerkat_interface" |
| 118 | +python3 "$ARTISTIC_DIR/scripts/meerkat_interface.py" \ |
| 119 | + -i "$KLAYOUT_DIR/croc_chip.gds" \ |
| 120 | + -m "$ARTISTIC_DIR/meerkat_work/croc_tm.gds.gz" \ |
| 121 | + -g "$ARTISTIC_DIR/meerkat_work/croc_logo.gds" \ |
| 122 | + -o "$ARTISTIC_DIR/meerkat_work/croc_chip.gds.gz" \ |
| 123 | + -w "$ARTISTIC_DIR/meerkat_work" \ |
| 124 | + -l 134 |
| 125 | + |
| 126 | +# Export top metal and decompress |
| 127 | +( cd "$ARTISTIC_DIR/meerkat_work" && klayout -zz -rm ../scripts/export_top_metal.py && gzip -d -f croc_tm.gds.gz ) |
| 128 | + |
| 129 | +# Generate logo GDS |
| 130 | +python3 "$ARTISTIC_DIR/scripts/meerkat.py" \ |
| 131 | + -m "7,7,7,7" \ |
| 132 | + -i "$ARTISTIC_DIR/meerkat_work/logo_mono.png" \ |
| 133 | + -g "$ARTISTIC_DIR/meerkat_work/croc_tm.gds" \ |
| 134 | + -l 134 \ |
| 135 | + -n croc \ |
| 136 | + -s "$ARTISTIC_DIR/meerkat_work/croc_logo.svg" \ |
| 137 | + -o "$ARTISTIC_DIR/meerkat_work/croc_logo.gds" |
| 138 | + |
| 139 | +# Merge logo |
| 140 | +( cd "$ARTISTIC_DIR/meerkat_work" && klayout -zz -rm ../scripts/merge_logo.py ) |
| 141 | + |
| 142 | +gen_cfg() { |
| 143 | + local src=$1 dst=$2 |
| 144 | + sed "s|/fosic/designs|$ROOT|g" "$src" > "$dst" |
| 145 | +} |
| 146 | + |
| 147 | +gen_cfg "$ROOT/.github/config/croc_ci.json" "$RENDER_DIR/croc_ci_runner.json" |
| 148 | +gen_cfg "$ROOT/.github/config/croc_map_ci.json" "$RENDER_DIR/croc_map_ci_runner.json" |
| 149 | +cp "$ROOT/.github/config/croc_ci.json" "$RENDER_DIR/croc_ci.json" |
| 150 | +cp "$ROOT/.github/config/croc_map_ci.json" "$RENDER_DIR/croc_map_ci.json" |
| 151 | + |
| 152 | +# Analyze and render |
| 153 | +log "Analyzing" |
| 154 | +make -C "$ARTISTIC_DIR" analyze CFG_FILE="$RENDER_DIR/croc_ci_runner.json" > "$RENDER_DIR/analyze.txt" |
| 155 | +log "Rendering raw tiles" |
| 156 | +make -C "$ARTISTIC_DIR" gen_raw CFG_FILE="$RENDER_DIR/croc_ci_runner.json" |
| 157 | +log "Rendering PDFs" |
| 158 | +make -C "$ARTISTIC_DIR" -j gen_pdfs CFG_FILE="$RENDER_DIR/croc_ci_runner.json" |
| 159 | +log "Rendering map tiles" |
| 160 | +make -C "$ARTISTIC_DIR" gen_raw CFG_FILE="$RENDER_DIR/croc_map_ci_runner.json" |
| 161 | +make -C "$ARTISTIC_DIR" -j gen_tiles CFG_FILE="$RENDER_DIR/croc_map_ci_runner.json" |
| 162 | +( cd "$ARTISTIC_DIR" && python3 scripts/mapify.py "$RENDER_DIR/croc_map_ci_runner.json" | sh ) |
| 163 | + |
| 164 | +# Final assets |
| 165 | +mv "$RENDER_DIR"/DPI__croc_0-0.png "$RENDER_DIR/croc_render.png" |
| 166 | +mv "$RENDER_DIR"/PDF__croc_0-0.pdf "$RENDER_DIR/croc_render.pdf" |
| 167 | +convert "$RENDER_DIR/croc_render.png" "$RENDER_DIR/croc_render.jpg" |
| 168 | + |
| 169 | +# Copy index for pages map |
| 170 | +cp "$ROOT/.github/config/gh-pages-map.html" "$MAPIFY_DIR/index.html" |
| 171 | +cp "$ARTISTIC_DIR/meerkat_work/croc_logo.gds" "$MAPIFY_DIR/croc_logo.gds" |
| 172 | + |
| 173 | +log "Done. Outputs are in $ROOT/artistic/renderics and $ROOT/artistic/mapify" |
0 commit comments