From b079cb6ad08cfd0cfe7d82f65b09238602866d5c Mon Sep 17 00:00:00 2001 From: daiyongyuan <1533208939@qq.com> Date: Sun, 30 Aug 2026 12:37:03 +0800 Subject: [PATCH 1/2] fix(verilator): select RushB RTL through bbdev --- .../bebop/verilator/01_clean_api.step.py | 6 +++- .../bebop/verilator/01_clean_event.step.py | 8 +++++- .../bebop/verilator/02_verilog_api.step.py | 2 +- .../bebop/verilator/03_build_api.step.py | 8 +++++- .../bebop/verilator/03_build_event.step.py | 8 +++++- .../bebop/verilator/04_sim_event.step.py | 8 +++++- .../bebop/verilator/06_batch_api.step.py | 4 ++- .../bebop/verilator/06_batch_event.step.py | 8 +++++- api/steps/compiler/scripts/build.py | 28 ++++++++++++------- .../06_bebop_verilator_verilog_event.step.py | 6 +++- api/utils/path.py | 19 +++++++++---- 11 files changed, 80 insertions(+), 25 deletions(-) diff --git a/api/steps/bebop/verilator/01_clean_api.step.py b/api/steps/bebop/verilator/01_clean_api.step.py index 451f35f..0a28884 100644 --- a/api/steps/bebop/verilator/01_clean_api.step.py +++ b/api/steps/bebop/verilator/01_clean_api.step.py @@ -20,10 +20,14 @@ async def handler(req: ApiRequest, ctx: FlowContext) -> ApiResponse: except ValueError as e: return ApiResponse(status=400, body={"error": str(e)}) - build_dir = rtl_dir(bbdir, chip, "verilog", body.get("output_dir")) + rushb = bool(body.get("rushB", False)) + build_dir = rtl_dir( + bbdir, chip, "verilog", body.get("output_dir"), rushb=rushb + ) data = { "chip": chip, "output_dir": build_dir, + "rushB": rushb, } await ctx.enqueue({"topic": "bebop.verilator.clean", "data": {**data, "_trace_id": ctx.trace_id}}) return ApiResponse(status=202, body={"trace_id": ctx.trace_id}) diff --git a/api/steps/bebop/verilator/01_clean_event.step.py b/api/steps/bebop/verilator/01_clean_event.step.py index 3588322..f364a21 100644 --- a/api/steps/bebop/verilator/01_clean_event.step.py +++ b/api/steps/bebop/verilator/01_clean_event.step.py @@ -37,7 +37,13 @@ async def handler(input_data: dict, ctx: FlowContext) -> None: trace_id=origin_tid, ) return - build_dir = rtl_dir(bbdir, chip, "verilog", input_data.get("output_dir")) + build_dir = rtl_dir( + bbdir, + chip, + "verilog", + input_data.get("output_dir"), + rushb=bool(input_data.get("rushB", False)), + ) command = f"rm -rf {build_dir}" result = await stream_run_logger_async( diff --git a/api/steps/bebop/verilator/02_verilog_api.step.py b/api/steps/bebop/verilator/02_verilog_api.step.py index 2a023d1..fc470fe 100644 --- a/api/steps/bebop/verilator/02_verilog_api.step.py +++ b/api/steps/bebop/verilator/02_verilog_api.step.py @@ -34,7 +34,7 @@ async def handler(request: ApiRequest, ctx: FlowContext) -> ApiResponse: }, ) - data = {"chip": chip} + data = {"chip": chip, "rushB": bool(body.get("rushB", False))} if body.get("output_dir"): data["output_dir"] = body["output_dir"] await ctx.enqueue({"topic": "bebop.verilator.verilog", "data": {**data, "_trace_id": ctx.trace_id}}) diff --git a/api/steps/bebop/verilator/03_build_api.step.py b/api/steps/bebop/verilator/03_build_api.step.py index 6603386..0565463 100644 --- a/api/steps/bebop/verilator/03_build_api.step.py +++ b/api/steps/bebop/verilator/03_build_api.step.py @@ -28,12 +28,18 @@ async def handler(request: ApiRequest, ctx: FlowContext) -> ApiResponse: except ValueError as e: return ApiResponse(status=400, body={"error": str(e)}) + rushb = bool(body.get("rushB", False)) data = { "chip": chip, "jobs": body.get("jobs", 16), "diff": bool(body.get("diff", False)), + "rushB": rushb, "vsrc_dir": rtl_dir( - bbdir, chip, "verilog", body.get("vsrc-dir") or body.get("output-dir"), + bbdir, + chip, + "verilog", + body.get("vsrc-dir") or body.get("output-dir"), + rushb=rushb, ), } await ctx.enqueue({"topic": "bebop.verilator.build", "data": {**data, "_trace_id": ctx.trace_id}}) diff --git a/api/steps/bebop/verilator/03_build_event.step.py b/api/steps/bebop/verilator/03_build_event.step.py index 079b840..7de3a6b 100644 --- a/api/steps/bebop/verilator/03_build_event.step.py +++ b/api/steps/bebop/verilator/03_build_event.step.py @@ -39,7 +39,13 @@ async def handler(input_data: dict, ctx: FlowContext) -> None: bebop_dir = f"{bbdir}/bebop" chip = require_chip(input_data) - vsrc_dir = rtl_dir(bbdir, chip, "verilog", input_data.get("vsrc_dir")) + vsrc_dir = rtl_dir( + bbdir, + chip, + "verilog", + input_data.get("vsrc_dir"), + rushb=bool(input_data.get("rushB", False)), + ) ctx.logger.info(f"Using verilog source directory: {vsrc_dir}") diff = bool(input_data.get("diff", False)) diff --git a/api/steps/bebop/verilator/04_sim_event.step.py b/api/steps/bebop/verilator/04_sim_event.step.py index 642b4f6..bb3e706 100644 --- a/api/steps/bebop/verilator/04_sim_event.step.py +++ b/api/steps/bebop/verilator/04_sim_event.step.py @@ -74,7 +74,13 @@ async def handler(input_data: dict, ctx: FlowContext) -> None: ) return - vsrc_dir = rtl_dir(bbdir, chip, "verilog", input_data.get("vsrc_dir")) + vsrc_dir = rtl_dir( + bbdir, + chip, + "verilog", + input_data.get("vsrc_dir"), + rushb=bool(input_data.get("rushB", False)), + ) ctx.logger.info(f"Using verilog source directory: {vsrc_dir}") build_dir = bebop_dir chip = input_data.get("chip") diff --git a/api/steps/bebop/verilator/06_batch_api.step.py b/api/steps/bebop/verilator/06_batch_api.step.py index 979bae0..d2b3b7e 100644 --- a/api/steps/bebop/verilator/06_batch_api.step.py +++ b/api/steps/bebop/verilator/06_batch_api.step.py @@ -42,7 +42,9 @@ async def handler(request: ApiRequest, ctx: FlowContext) -> ApiResponse: body={"error": "--diff and --rushB cannot be used together"}, ) - vsrc_dir = rtl_dir(bbdir, chip, "verilog", body.get("vsrc_dir")) + vsrc_dir = rtl_dir( + bbdir, chip, "verilog", body.get("vsrc_dir"), rushb=rushB + ) data = { "chip": chip, diff --git a/api/steps/bebop/verilator/06_batch_event.step.py b/api/steps/bebop/verilator/06_batch_event.step.py index e6771b5..6a850df 100644 --- a/api/steps/bebop/verilator/06_batch_event.step.py +++ b/api/steps/bebop/verilator/06_batch_event.step.py @@ -85,7 +85,13 @@ async def handler(input_data: dict, ctx: FlowContext) -> None: f"rushB={rushB} diff={diff}" ) - vsrc_dir = rtl_dir(bbdir, chip, "verilog", input_data.get("vsrc_dir")) + vsrc_dir = rtl_dir( + bbdir, + chip, + "verilog", + input_data.get("vsrc_dir"), + rushb=rushB, + ) vsrc_config = shlex.quote(f"env.VSRC_PATH='{vsrc_dir}'") env = os.environ.copy() env.update(bebop_cargo_env(bbdir, chip)) diff --git a/api/steps/compiler/scripts/build.py b/api/steps/compiler/scripts/build.py index fcafd3f..bba660b 100644 --- a/api/steps/compiler/scripts/build.py +++ b/api/steps/compiler/scripts/build.py @@ -47,14 +47,22 @@ def _run( raise RuntimeError(f"command failed ({result.returncode}): {' '.join(cmd)}") -def compiler_python() -> str: - python = shutil.which("python3") - if not python: - raise RuntimeError("python3 not in PATH; enter nix develop") - probe = subprocess.run([python, "-c", "import nanobind"], capture_output=True) - if probe.returncode != 0: - raise RuntimeError(f"python3 lacks nanobind ({python}); enter nix develop") - return python +def compiler_python(repo: str | Path) -> str: + root = _repo(repo) + candidates = [root / "result" / "bin" / "python3"] + path_python = shutil.which("python3") + if path_python: + candidates.append(Path(path_python)) + for candidate in candidates: + if not candidate.is_file(): + continue + probe = subprocess.run( + [str(candidate), "-c", "import nanobind"], capture_output=True + ) + if probe.returncode == 0: + return str(candidate) + checked = ", ".join(str(candidate) for candidate in candidates) + raise RuntimeError(f"python3 with nanobind not found (checked: {checked})") def build_llvm( @@ -67,7 +75,7 @@ def build_llvm( if not llvm_src.is_dir(): raise RuntimeError(f"missing LLVM source: {llvm_src}") - python = compiler_python() + python = compiler_python(root) cmake = [ "cmake", "-G", @@ -129,7 +137,7 @@ def build_compiler( raise RuntimeError(f"missing {chip_pb}; run bbdev config --install") buddy = root / "compiler" / "thirdparty" / "buddy-mlir" llvm = build_llvm(root, logger=logger, task_scope=task_scope) - python = compiler_python() + python = compiler_python(root) build = compiler_build_dir(root, chip) build.mkdir(parents=True, exist_ok=True) cmake = [ diff --git a/api/steps/mill/06_bebop_verilator_verilog_event.step.py b/api/steps/mill/06_bebop_verilator_verilog_event.step.py index b3ab033..09ee4bb 100644 --- a/api/steps/mill/06_bebop_verilator_verilog_event.step.py +++ b/api/steps/mill/06_bebop_verilator_verilog_event.step.py @@ -55,7 +55,11 @@ async def handler(input_data: dict, ctx: FlowContext) -> None: try: chip = require_chip(input_data) mill_config, build_dir = rtl_out( - bbdir, chip, "verilog", input_data.get("output_dir"), + bbdir, + chip, + "verilog", + input_data.get("output_dir"), + rushb=bool(input_data.get("rushB", False)), ) os.makedirs(build_dir, exist_ok=True) ctx.logger.info(f"Using mill config: {mill_config}") diff --git a/api/utils/path.py b/api/utils/path.py index 807a6d2..e61fc89 100644 --- a/api/utils/path.py +++ b/api/utils/path.py @@ -67,7 +67,7 @@ def chip_arch_root(bbdir, chip): return os.path.join(bbdir, "arch", "build", _chip_name(chip)) -def sim_name(bbdir, chip, product): +def sim_name(bbdir, chip, product, *, rushb=False): if product not in _PRODUCT: raise ValueError(f"invalid rtl product: {product}") path = ( @@ -80,17 +80,24 @@ def sim_name(bbdir, chip, product): / "config" / "config.json" ) - return json.loads(path.read_text(encoding="utf-8"))["sims"][_PRODUCT[product]] + name = json.loads(path.read_text(encoding="utf-8"))["sims"][_PRODUCT[product]] + if not rushb: + return name + if product != "verilog" or not name.endswith("VerilatorConfig"): + raise ValueError(f"rushB RTL is not supported for product {product}: {name}") + return f"{name[:-len('VerilatorConfig')]}RushBVerilatorConfig" -def rtl_dir(bbdir, chip, product, output_dir=None): +def rtl_dir(bbdir, chip, product, output_dir=None, *, rushb=False): if output_dir: return output_dir - return os.path.join(chip_arch_root(bbdir, chip), sim_name(bbdir, chip, product)) + return os.path.join( + chip_arch_root(bbdir, chip), sim_name(bbdir, chip, product, rushb=rushb) + ) -def rtl_out(bbdir, chip, product, output_dir=None): - name = sim_name(bbdir, chip, product) +def rtl_out(bbdir, chip, product, output_dir=None, *, rushb=False): + name = sim_name(bbdir, chip, product, rushb=rushb) out = output_dir or os.path.join(chip_arch_root(bbdir, chip), name) return name, out From b0bd921d6d113d1ec184a7a404debcc4f91a96f0 Mon Sep 17 00:00:00 2001 From: daiyongyuan <1533208939@qq.com> Date: Mon, 31 Aug 2026 16:09:24 +0800 Subject: [PATCH 2/2] [BBDev][Verilator] Load the current RushB backend --- api/steps/bebop/verilator/04_sim_event.step.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/api/steps/bebop/verilator/04_sim_event.step.py b/api/steps/bebop/verilator/04_sim_event.step.py index bb3e706..a308b72 100644 --- a/api/steps/bebop/verilator/04_sim_event.step.py +++ b/api/steps/bebop/verilator/04_sim_event.step.py @@ -198,7 +198,11 @@ async def handler(input_data: dict, ctx: FlowContext) -> None: backend_library = f"{bebop_target_dir(bbdir, chip)}/release/deps/libbebop_verilator.so" binary_dir = os.path.dirname(binary_path) copy_cmd = shlex.join(["cmake", "-E", "copy_if_different", backend_library, binary_dir]) - inner_cmd = f"cd {shlex.quote(binary_dir)} && {copy_cmd} && exec {shlex.quote(binary_path)}" + library_env = f"LD_LIBRARY_PATH={shlex.quote(binary_dir)}:${{LD_LIBRARY_PATH:-}}" + inner_cmd = ( + f"cd {shlex.quote(binary_dir)} && {copy_cmd} && " + f"{library_env} exec {shlex.quote(binary_path)}" + ) run_cmd = f"nix develop -c sh -c {shlex.quote(inner_cmd)}" ctx.logger.info(f"Running rushB Verilator: {run_cmd}") stdout_prefix = "rushB verilator"