Repository navigation
Expand file tree
/
Copy pathMakefile
More file actions
290 lines (257 loc) · 11.3 KB
/
Copy pathMakefile
File metadata and controls
290 lines (257 loc) · 11.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
# Current Workspace Dir
CWD ?= output/workspace_$*
PYTHON ?= python3
NODE ?= node
GUIDE_DOC_CACHE ?= Guide_Doc
CFG ?= config.yaml
BBV ?= false
SRC ?= examples
SWARM_IMAGE ?= ghcr.nju.edu.cn/xs-mlvp/ucagent:latest
SWARM_NETWORK ?= ucagent_net
SWARM_MASTER_SERVICE ?= ucagent_master
SWARM_MASTER_PORT ?= 8800
SWARM_MASTER_PERSIST ?= /tmp/ucagent_master
SWARM_DOCKER_SOCK ?= /var/run/docker.sock
SWARM_MASTER_HOST ?=
SWARM_LOCAL_UCAGENT_DIR := $(CURDIR)
SWARM_IS_COLIMA ?= $(shell ctx="$$(docker context show 2>/dev/null)"; host="$$(docker context inspect "$$ctx" --format '{{.Endpoints.docker.Host}}' 2>/dev/null)"; printf '%s\n%s\n' "$$ctx" "$$host" | grep -Eq '(^colima|[/.]colima)' && echo 1 || echo 0)
SWARM_COLIMA_SSH ?= colima ssh --
SWARM_MASTER_PERSIST_SOURCE := $(abspath $(SWARM_MASTER_PERSIST))
SWARM_COMMA := ,
MASTER_IP ?= 127.0.0.1
SWARM_MASTER_PUBLISH = published=$(SWARM_MASTER_PORT),target=$(SWARM_MASTER_PORT)$(if $(filter 1 true yes,$(SWARM_IS_COLIMA)),$(SWARM_COMMA)mode=host)
SWARM_DOCKER_SOCK_CHECK = $(if $(filter 1 true yes,$(SWARM_IS_COLIMA)),$(SWARM_COLIMA_SSH) test -S $(SWARM_DOCKER_SOCK),test -S $(SWARM_DOCKER_SOCK))
SWARM_MASTER_PERSIST_MKDIR = $(if $(filter 1 true yes,$(SWARM_IS_COLIMA)),$(SWARM_COLIMA_SSH) mkdir -p $(SWARM_MASTER_PERSIST_SOURCE),mkdir -p $(SWARM_MASTER_PERSIST_SOURCE))
ifneq ($(strip $(UCAGENT_MASTER_SOURCE)),)
SWARM_MASTER_SOURCE_DIR := $(abspath $(UCAGENT_MASTER_SOURCE))
SWARM_MASTER_UCAGENT_MOUNT := --mount type=bind,source=$(SWARM_MASTER_SOURCE_DIR),target=/UCAgent
SWARM_MASTER_CMD := python3 /UCAgent/ucagent/cli.py
SWARM_MASTER_SOURCE_ENV := --env UCAGENT_MASTER_SOURCE=$(SWARM_MASTER_SOURCE_DIR)
else
SWARM_MASTER_SOURCE_DIR :=
SWARM_MASTER_UCAGENT_MOUNT :=
SWARM_MASTER_CMD := ucagent
SWARM_MASTER_SOURCE_ENV := --env UCAGENT_MASTER_SOURCE=
endif
SWARM_OVERRIDE := --override launch.default_args.launch_mode=docker_swarm \
--override launch.cluster.docker_network=$(SWARM_NETWORK) \
--override launch.cluster.master_ip=$(SWARM_MASTER_SERVICE)
# --override launch.default_args.extra_args[0:0]=@base64:LS1vdmVycmlkZQpzdGFnZVstMV0ubmVlZF9odW1hbl9jaGVjaz1UcnVl
UCAGENT_PY := $(wildcard ucagent.py)
ifdef UCAGENT_PY
CMD ?= python3 ucagent.py
else
CMD ?= ucagent
endif
all: clean test
.PHONY: unitytest
unitytest:
$(PYTHON) -m pytest -q tests
$(NODE) --test tests/test_*.js
init:
pip3 install -r requirements.txt
reset_%:
rm $(CWD)/unity_test -rf || true
rm $(CWD)/.ucagent -rf || true
rm $(CWD)/uc_test_report -rf || true
rm $(CWD)/*.md -rf || true
refresh_%:
$(PYTHON) ucagent/scripts/refresh_workspace_assets.py --workspace "$(CWD)" --guide-doc-cache "$(GUIDE_DOC_CACHE)"
init_%:
mkdir -p $(CWD)/$*_RTL
cp $(SRC)/$*/*.v $(CWD)/$*_RTL/ || true
cp $(SRC)/$*/*.sv $(CWD)/$*_RTL/ || true
cp $(SRC)/$*/*.vh $(CWD)/$*_RTL/ || true
cp $(SRC)/$*/*.scala $(CWD)/$*_RTL/ || true
cp $(SRC)/$*/filelist.txt $(CWD)/$*_RTL/ || true
@if [ -d $(SRC)/$*/Doc ]; then \
echo "Copying Doc files from $(SRC)/$*/Doc to $(CWD)/$*_Doc/"; \
cp -r $(SRC)/$*/Doc $(CWD)/$*_Doc/ || true; \
fi
@if [ ! -d $(CWD)/$* ]; then \
option_fs=""; \
if [ -f $(CWD)/$*_RTL/filelist.txt ]; then \
option_fs="--fs $(CWD)/$*_RTL/filelist.txt"; \
fi; \
if [ -f $(CWD)/$*_RTL/$*.v ]; then \
picker export $(CWD)/$*_RTL/$*.v --rw 1 --sname $* --tdir $(CWD)/ -c -w $(CWD)/$*/$*.fst $$option_fs; \
elif [ -f $(CWD)/$*_RTL/$*.sv ]; then \
picker export $(CWD)/$*_RTL/$*.sv --rw 1 --sname $* --tdir $(CWD)/ -c -w $(CWD)/$*/$*.fst $$option_fs; \
fi; \
fi
cp $(SRC)/$*/*.md $(CWD)/$*/ || true
cp $(SRC)/$*/*.py $(CWD)/$*/ || true
@if [ $(BBV) = "true" ]; then \
echo "Enable BBV mode: clear RTL files"; \
for f in $(CWD)/$*/$*.v $(CWD)/$*/$*.sv $(CWD)/$*/$*.vh; do \
if [ -f $$f ]; then \
echo "clear file $$f"; \
echo "" > $$f; \
fi; \
done; \
for f in `find $(CWD)/$*_RTL/*|grep -v '.scala'`; do \
echo "" > $$f; \
done; \
fi
@python3 $(CWD)/$*/example.py || { echo "Error: picker try to generate DUT, but failed.\n"; exit 1; }
test_%: init_%
$(CMD) $(CWD)/ $* --config $(CFG) -s -hm --tui -l ${ARGS}
test_with_master_%: init_%
$(CMD) $(CWD)/ $* --config $(CFG) -s -hm --tui -l --master ${MASTER_IP} --export-cmd-api ${ARGS}
mcp_%: init_%
$(CMD) $(CWD)/ $* --config $(CFG) -s -hm --tui --mcp-server-no-file-tools ${ARGS}
mcp_with_master_%: init_%
$(CMD) $(CWD)/ $* --config $(CFG) -s -hm --tui --mcp-server-no-file-tools --master ${MASTER_IP} --export-cmd-api ${ARGS}
mcp_all_tools_%: init_%
$(CMD) $(CWD)/ $* --config $(CFG) -s -hm --tui --mcp-server ${ARGS}
clean_%:
rm -rf $(CWD)
clean:
rm -rf .pytest_cache
rm -rf log
rm -rf UCAgent.egg-info
rm -rf build
rm -rf dist
rm -rf site
find ./ -name '*.dat'|xargs rm -f
find ./ -name '*.vcd'|xargs rm -f
find ./ -name '*.fst'|xargs rm -f
find ./ -name __pycache__|xargs rm -rf
find ./ -name output|xargs rm -rf
clean_test_%:
rm -rf $(CWD)/unity_test
continue_%:
$(CMD) $(CWD)/ ${DUT} --config config.yaml ${ARGS}
as_master:
$(CMD) --as-master --export-cmd-api ${ARGS}
as_master_persist:
$(CMD) --as-master-persist ${PATH_PERSISTENT} --export-cmd-api --as-master ${ARGS}
swarm_check:
@command -v docker >/dev/null 2>&1 || { echo "Error: docker CLI is not installed or not in PATH."; exit 1; }
@docker info >/dev/null 2>&1 || { echo "Error: Docker daemon is not available. Please start Docker first."; exit 1; }
@$(SWARM_DOCKER_SOCK_CHECK) || { echo "Error: Docker socket $(SWARM_DOCKER_SOCK) is not available."; exit 1; }
@if [ -n "$(SWARM_MASTER_SOURCE_DIR)" ] && [ ! -f "$(SWARM_MASTER_SOURCE_DIR)/ucagent/cli.py" ]; then \
echo "Error: UCAGENT_MASTER_SOURCE must point to a UCAgent source tree containing ucagent/cli.py: $(SWARM_MASTER_SOURCE_DIR)"; \
exit 1; \
fi
@state=$$(docker info --format '{{.Swarm.LocalNodeState}}' 2>/dev/null); \
if [ "$$state" != "active" ]; then \
echo "Error: Docker Swarm is not active (state: $${state:-unknown})."; \
echo "Hint: initialize or join a swarm first, for example: docker swarm init"; \
exit 1; \
fi
@control=$$(docker info --format '{{.Swarm.ControlAvailable}}' 2>/dev/null); \
if [ "$$control" != "true" ]; then \
echo "Error: this Docker node is not a Swarm manager, so it cannot launch Swarm services."; \
echo "Hint: run make swarm_master on a manager node, or promote this node with: docker node promote <node>"; \
exit 1; \
fi
swarm_init:
$(MAKE) swarm_check
@if docker network inspect $(SWARM_NETWORK) >/dev/null 2>&1; then \
driver=$$(docker network inspect $(SWARM_NETWORK) --format '{{.Driver}}'); \
scope=$$(docker network inspect $(SWARM_NETWORK) --format '{{.Scope}}'); \
if [ "$$driver" != "overlay" ] || [ "$$scope" != "swarm" ]; then \
echo "Error: Docker network $(SWARM_NETWORK) exists but is $$driver/$$scope, expected overlay/swarm."; \
echo "Hint: remove or rename the existing network, then run make swarm_master again."; \
exit 1; \
fi; \
else \
docker network create --driver overlay --attachable $(SWARM_NETWORK); \
fi
@if ! docker image inspect $(SWARM_IMAGE) >/dev/null 2>&1; then \
echo "Pulling Docker image $(SWARM_IMAGE)..."; \
docker pull $(SWARM_IMAGE); \
fi
swarm_clean:
@echo "Removing existing Docker Swarm services with name prefix $(SWARM_MASTER_SERVICE)...";
@sid=`docker service list|grep ucagent|awk '{print $$1}'|xargs`; if [ -n "$$sid" ]; then echo "stop service $$sid"; docker service rm $$sid; fi;
@docker service ls
@echo "Stop all containers...";
@did=`docker ps|grep ucagent|awk '{print $$1}'|xargs`; if [ -n "$$did" ]; then echo "stop container $$did"; docker stop $$did; fi;
@docker ps -a
swarm_master: swarm_init
@$(SWARM_MASTER_PERSIST_MKDIR)
@if docker service inspect $(SWARM_MASTER_SERVICE) >/dev/null 2>&1; then \
echo "Removing existing Docker Swarm service $(SWARM_MASTER_SERVICE)..."; \
docker service rm $(SWARM_MASTER_SERVICE) >/dev/null; \
while docker service inspect $(SWARM_MASTER_SERVICE) >/dev/null 2>&1; do sleep 1; done; \
fi
@docker service create \
--name $(SWARM_MASTER_SERVICE) \
--hostname $(SWARM_MASTER_SERVICE) \
--detach=true \
--replicas 1 \
--restart-condition any \
--constraint node.role==manager \
--network $(SWARM_NETWORK) \
--env DOCKER_HOST=unix://$(SWARM_DOCKER_SOCK) \
--env UCAGENT_LAUNCH_IMAGE=$(SWARM_IMAGE) \
--env UCAGENT_LAUNCH_MASTER_IP=$(SWARM_MASTER_SERVICE) \
--env OPENAI_MODEL \
--env OPENAI_API_KEY \
--env OPENAI_API_BASE \
--env EMBED_MODEL \
--env EMBED_OPENAI_API_KEY \
--env EMBED_OPENAI_API_BASE \
--env UC_MODEL_TYPE \
--env ANTHROPIC_BASE_URL \
--env ANTHROPIC_AUTH_TOKEN \
--env ANTHROPIC_MODEL \
--env ANTHROPIC_BIG_MODEL \
--env ANTHROPIC_SML_MODEL \
--env GOOGLE_GENAI_API_KEY \
--env GOOGLE_GENAI_MODEL \
--env UC_ENV_CMD_BACKEND_EX_ARGS \
--env UC_ENV_CMD_BACKEND_EX_ARGS_N \
--env UC_ENV_CMD_BACKEND_EX_ARGS_C \
$(SWARM_MASTER_SOURCE_ENV) \
--publish $(SWARM_MASTER_PUBLISH) \
--mount type=bind,source=$(SWARM_MASTER_PERSIST_SOURCE),target=$(SWARM_MASTER_PERSIST) \
--mount type=bind,source=$(SWARM_DOCKER_SOCK),target=$(SWARM_DOCKER_SOCK) \
$(SWARM_MASTER_UCAGENT_MOUNT) \
--workdir /workspace/UCAgent \
$(SWARM_IMAGE) \
sh -c "tail -f /dev/null | $(SWARM_MASTER_CMD) --export-cmd-api --as-master-persist $(SWARM_MASTER_PERSIST) --as-master 0.0.0.0:$(SWARM_MASTER_PORT) $(SWARM_OVERRIDE) $(ARGS)"
@echo "Waiting for $(SWARM_MASTER_SERVICE) to start..."
@for i in $$(seq 1 30); do \
replicas=$$(docker service ls --filter name=$(SWARM_MASTER_SERVICE) --format '{{.Replicas}}' | head -n 1); \
if [ "$$replicas" = "1/1" ]; then \
host="$(SWARM_MASTER_HOST)"; \
if [ -z "$$host" ]; then \
host=$$(docker node inspect self --format '{{.Status.Addr}}' 2>/dev/null | head -n 1); \
fi; \
if [ -z "$$host" ] || [ "$$host" = "<no value>" ]; then \
host=$$(docker info --format '{{.Swarm.NodeAddr}}' 2>/dev/null); \
fi; \
if [ -z "$$host" ] || [ "$$host" = "<no value>" ]; then \
host=$$(hostname -I 2>/dev/null | awk '{print $$1}'); \
fi; \
if [ -z "$$host" ]; then host=127.0.0.1; fi; \
echo "Docker Swarm master is running: http://$(SWARM_MASTER_SERVICE):$(SWARM_MASTER_PORT) on network $(SWARM_NETWORK)"; \
echo "Published on host: http://$$host:$(SWARM_MASTER_PORT)"; \
echo "Override the printed host with: make swarm_master SWARM_MASTER_HOST=<reachable-ip-or-dns>"; \
exit 0; \
fi; \
sleep 1; \
done; \
echo "Error: Docker Swarm service $(SWARM_MASTER_SERVICE) did not reach 1/1 replicas."; \
echo "Hint: inspect it with: docker service ps $(SWARM_MASTER_SERVICE) --no-trunc"; \
echo "Hint: view logs with: docker service logs $(SWARM_MASTER_SERVICE)"; \
exit 1
# Include docs Makefile
-include docs/Makefile
# ---------- Formal Verification ----------
FORMAL_DIR := examples/Formal
FORMAL_CWD ?= $(FORMAL_DIR)/output/workspace_$*
FORMAL_CFG := ucagent/lang/zh/config/formal.yaml
FORMAL_DOC := ucagent/lang/zh/doc/Formal_Doc
formal_init_%:
mkdir -p $(FORMAL_CWD)
cp -r $(FORMAL_DIR)/$* $(FORMAL_CWD)/
formal_%: formal_init_%
$(CMD) $(FORMAL_CWD)/ $* --config $(FORMAL_CFG) -s -hm --tui --guid-doc-path $(FORMAL_DOC)/ --output formal_test $(ARGS)
formal_mcp_%: formal_init_%
$(CMD) $(FORMAL_CWD)/ $* --config $(FORMAL_CFG) -s -hm --tui --mcp-server-no-file-tools --guid-doc-path $(FORMAL_DOC)/ --output formal_test --mcp-server-port 5000 --master 127.0.0.1 --export-cmd-api --use-skill --log $(ARGS)
clean_formal:
rm -rf $(FORMAL_DIR)/output