@@ -3,10 +3,10 @@ name: Spacemit3.6-Build-And-Test
33# SpaceMiT RISC-V 后端 CI (root-triton plugin)。
44#
55# 执行环境: self-hosted runner (label spacemit3.6)。
6- # RPC 执行: bianbu_riscv64_env 容器 (RISC-V via QEMU binfmt) 跑 spine-rpc-server,
7- # host triton 交叉编译 kernel 后通过 TCP 9999 发给容器执行 。
8- # LLVM / spine-mlir / spine-runtime / rpc-runtime / toolchain 从
9- # zuoweixia497/spacemit-ci-assets GitHub release 下载并缓存。
6+ # RPC 执行: jdsk-qemu v10.0.2 用户态模拟 (-cpu max,vlen=1024,elen=64,vext_spec=v1.0)
7+ # 跑 spine-rpc-server, host triton 交叉编译 kernel 后通过 TCP 9999 发给 QEMU 执行 。
8+ # LLVM / spine-mlir / spine-runtime / rpc-runtime / toolchain / jdsk-qemu 从
9+ # zuoweixia497/spacemit-ci-assets GitHub release (及 archive.spacemit.com) 下载并缓存。
1010# 更新包: 修改 third_party/spacemit/spacemit-ci.env 里的 URL+MD5 即可。
1111
1212on :
@@ -127,6 +127,21 @@ jobs:
127127 tar -xf rpc-runtime.tar.gz -C rpc_runtime_installed --strip-components=1
128128 rm rpc-runtime.tar.gz
129129
130+ - name : Cache jdsk-qemu
131+ if : steps.check_backend.outputs.should_skip != 'true'
132+ id : cache-qemu
133+ uses : actions/cache@v4
134+ with :
135+ path : jdsk-qemu
136+ key : jdsk-qemu-${{ env.JDSK_QEMU_MD5 }}
137+
138+ - name : Download and extract jdsk-qemu
139+ if : steps.check_backend.outputs.should_skip != 'true' && steps.cache-qemu.outputs.cache-hit != 'true'
140+ run : |
141+ curl -k -L --retry 5 --retry-delay 5 --retry-all-errors -o jdsk-qemu.tar.gz "$JDSK_QEMU_URL"
142+ tar -xf jdsk-qemu.tar.gz
143+ rm jdsk-qemu.tar.gz
144+
130145 - name : Build (apply flagtree.patch + pip install)
131146 if : steps.check_backend.outputs.should_skip != 'true'
132147 run : |
@@ -144,35 +159,42 @@ jobs:
144159 MAX_JOBS="${MAX_JOBS:-4}" PIP="python -m pip" \
145160 bash third_party/spacemit/scripts/install_flagtree_plugin.sh
146161
147- - name : Start QEMU RPC server (bianbu container )
162+ - name : Start QEMU RPC server (jdsk-qemu )
148163 if : steps.check_backend.outputs.should_skip != 'true'
149164 run : |
150165 set -euo pipefail
151- docker pull harbor.spacemit.com/spacemit-ai/bianbu_riscv64_env:bianbu_3.x_v0.1
152- docker rm -f rpc-ci 2>/dev/null || true
153- # 不用 bind mount: runner 容器走 host docker socket 时, 路径在 host 上不存在
154- # (host /runner/_work/... 是空目录, 真实文件在 actions-runner/_work/...).
155- # docker cp 由 docker CLI 在 runner 容器侧读源文件, 再流式写入目标容器.
156- docker run -d --name rpc-ci \
157- -p 127.0.0.1:${RPC_PORT}:${RPC_PORT} \
158- harbor.spacemit.com/spacemit-ai/bianbu_riscv64_env:bianbu_3.x_v0.1 \
159- sleep 1200
160- docker cp rpc_runtime_installed/. rpc-ci:/rpc
161- # sanity: confirm the rpc-server binary is visible inside the container
162- docker exec rpc-ci ls -la /rpc/bin/spine-rpc-server /rpc/lib/libspert.so
163- # launch spine-rpc-server inside the RISC-V container (binfmt QEMU)
164- docker exec -d -e SPACEMIT_QEMU_RISCV_FLAGS="max,vlen=1024,elen=64,vext_spec=v1.0" rpc-ci \
165- bash -c "LD_LIBRARY_PATH=/rpc/lib /rpc/bin/spine-rpc-server ${RPC_PORT} > /tmp/rpc.log 2>&1"
166- # wait for the port to accept connections (server needs ~15s to boot under QEMU)
166+ QEMU_BIN="$(pwd)/jdsk-qemu/bin/qemu-riscv64"
167+ SYSROOT="$(pwd)/toolchain/sysroot"
168+ RPC_DIR="$(pwd)/rpc_runtime_installed"
169+ chmod +x "$QEMU_BIN" 2>/dev/null || true
170+ # sanity: confirm the rpc-server binary and qemu exist
171+ test -f "$QEMU_BIN" || { echo "ERROR: qemu not found at $QEMU_BIN" >&2; exit 1; }
172+ test -f "$RPC_DIR/bin/spine-rpc-server" || { echo "ERROR: rpc-server not found" >&2; exit 1; }
173+ "$QEMU_BIN" --version
174+ # launch spine-rpc-server under jdsk-qemu (RISC-V user-mode emulation on x86 runner)
175+ setsid bash -c "
176+ exec '$QEMU_BIN' -L '$SYSROOT' \
177+ -cpu max,vlen=1024,elen=64,vext_spec=v1.0 \
178+ -E LD_LIBRARY_PATH='$RPC_DIR/lib:$SYSROOT/lib:$SYSROOT/usr/lib' \
179+ '$RPC_DIR/bin/spine-rpc-server' ${RPC_PORT}
180+ " > /tmp/rpc.log 2>&1 &
181+ echo $! > /tmp/rpc_server.pid
182+ # wait for the port to accept connections
167183 for i in $(seq 1 60); do
168184 if python3 -c "import socket,sys; sys.exit(0 if socket.socket().connect_ex(('127.0.0.1',${RPC_PORT}))==0 else 1)" 2>/dev/null; then
169185 echo "RPC server ready on 127.0.0.1:${RPC_PORT} (${i}s)"
170186 exit 0
171187 fi
188+ # bail early if the server process died
189+ if ! kill -0 $(cat /tmp/rpc_server.pid) 2>/dev/null; then
190+ echo "ERROR: rpc-server process exited early" >&2
191+ cat /tmp/rpc.log 2>/dev/null || true
192+ exit 1
193+ fi
172194 sleep 1
173195 done
174196 echo "ERROR: RPC server did not come up on port ${RPC_PORT}" >&2
175- docker exec rpc-ci cat /tmp/rpc.log 2>/dev/null || true
197+ cat /tmp/rpc.log 2>/dev/null || true
176198 exit 1
177199
178200 - name : Minimal smoke test (import + spacemit backend + QEMU RPC)
@@ -236,12 +258,12 @@ jobs:
236258 - name : Dump RPC server log + compiled IR (on failure)
237259 if : failure() && steps.check_backend.outputs.should_skip != 'true'
238260 run : |
239- echo "=== rpc-ci state === "
240- docker ps -a --filter name=rpc-ci || true
241- echo "=== /tmp/rpc.log (server stderr) === "
242- docker exec rpc-ci cat /tmp/rpc.log 2>/dev/null || true
243- echo "=== spine-rpc-server processes (alive?) === "
244- docker exec rpc-ci bash -c 'ps -ef | grep -v grep | grep spine-rpc-server' 2>/dev/null || true
261+ echo "--- rpc-server process --- "
262+ if [ -f /tmp/rpc_server.pid ]; then
263+ ps -p "$(cat /tmp/rpc_server.pid)" 2>/dev/null || echo "process not running "
264+ fi
265+ echo "--- /tmp/rpc.log --- "
266+ cat /tmp/ rpc.log 2>/dev/null || true
245267 echo "=== triton_dump dir ==="
246268 ls -la triton_dump/ 2>/dev/null || true
247269 echo "=== dump file contents ==="
@@ -253,4 +275,8 @@ jobs:
253275
254276 - name : Stop QEMU RPC server
255277 if : always() && steps.check_backend.outputs.should_skip != 'true'
256- run : docker rm -f rpc-ci 2>/dev/null || true
278+ run : |
279+ if [ -f /tmp/rpc_server.pid ]; then
280+ kill "$(cat /tmp/rpc_server.pid)" 2>/dev/null || true
281+ fi
282+ pkill -f "spine-rpc-server" 2>/dev/null || true
0 commit comments