SanketAI commited on
Commit
d8ff16a
·
verified ·
1 Parent(s): 2dfa1c8

Upload folder using huggingface_hub

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +3 -0
  2. Dockerfile +110 -0
  3. README.md +163 -6
  4. __init__.py +16 -0
  5. client.py +122 -0
  6. inference.py +504 -0
  7. models.py +164 -0
  8. obj_dir/Vsim +3 -0
  9. obj_dir/Vsim.cpp +137 -0
  10. obj_dir/Vsim.h +89 -0
  11. obj_dir/Vsim.mk +66 -0
  12. obj_dir/Vsim__ALL.a +0 -0
  13. obj_dir/Vsim__ALL.cpp +11 -0
  14. obj_dir/Vsim__ALL.d +15 -0
  15. obj_dir/Vsim__ALL.o +0 -0
  16. obj_dir/Vsim__Syms.h +40 -0
  17. obj_dir/Vsim__Syms__Slow.cpp +28 -0
  18. obj_dir/Vsim__TraceDecls__0__Slow.cpp +12 -0
  19. obj_dir/Vsim__Trace__0.cpp +52 -0
  20. obj_dir/Vsim__Trace__0__Slow.cpp +95 -0
  21. obj_dir/Vsim___024root.h +52 -0
  22. obj_dir/Vsim___024root__0.cpp +323 -0
  23. obj_dir/Vsim___024root__0__Slow.cpp +166 -0
  24. obj_dir/Vsim___024root__Slow.cpp +24 -0
  25. obj_dir/Vsim__main.cpp +40 -0
  26. obj_dir/Vsim__pch.h +27 -0
  27. obj_dir/Vsim__ver.d +1 -0
  28. obj_dir/Vsim__verFiles.dat +24 -0
  29. obj_dir/Vsim_classes.mk +57 -0
  30. obj_dir/verilated.d +12 -0
  31. obj_dir/verilated.o +3 -0
  32. obj_dir/verilated_threads.d +8 -0
  33. obj_dir/verilated_threads.o +0 -0
  34. obj_dir/verilated_timing.d +8 -0
  35. obj_dir/verilated_timing.o +0 -0
  36. obj_dir/verilated_vcd_c.d +12 -0
  37. obj_dir/verilated_vcd_c.o +3 -0
  38. openenv.yaml +7 -0
  39. openenv_chipforge.egg-info/PKG-INFO +12 -0
  40. openenv_chipforge.egg-info/SOURCES.txt +19 -0
  41. openenv_chipforge.egg-info/dependency_links.txt +1 -0
  42. openenv_chipforge.egg-info/entry_points.txt +2 -0
  43. openenv_chipforge.egg-info/requires.txt +8 -0
  44. openenv_chipforge.egg-info/top_level.txt +1 -0
  45. pyproject.toml +42 -0
  46. server/__init__.py +11 -0
  47. server/app.py +84 -0
  48. server/chipforge_environment.py +789 -0
  49. server/tasks/easy/01_inverter_semicolon/design_buggy.v +30 -0
  50. server/tasks/easy/01_inverter_semicolon/design_golden.v +30 -0
.gitattributes CHANGED
@@ -33,3 +33,6 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ obj_dir/Vsim filter=lfs diff=lfs merge=lfs -text
37
+ obj_dir/verilated.o filter=lfs diff=lfs merge=lfs -text
38
+ obj_dir/verilated_vcd_c.o filter=lfs diff=lfs merge=lfs -text
Dockerfile ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ # All rights reserved.
3
+ #
4
+ # This source code is licensed under the BSD-style license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ # Multi-stage build using openenv-base
8
+ # This Dockerfile is flexible and works for both:
9
+ # - In-repo environments (with local OpenEnv sources)
10
+ # - Standalone environments (with openenv from PyPI/Git)
11
+ # The build script (openenv build) handles context detection and sets appropriate build args.
12
+
13
+ ARG BASE_IMAGE=ghcr.io/meta-pytorch/openenv-base:latest
14
+ FROM ${BASE_IMAGE} AS builder
15
+
16
+ WORKDIR /app
17
+
18
+ # OSS CAD Suite release to install into the image.
19
+ ARG OSS_CAD_SUITE_VERSION=20260407
20
+ ARG TARGETARCH
21
+
22
+ # Ensure git and perl are available (required for installing dependencies from VCS and running Verilator)
23
+ RUN apt-get update && \
24
+ apt-get install -y --no-install-recommends git perl perl-modules-5.40 && \
25
+ rm -rf /var/lib/apt/lists/*
26
+
27
+ # Install OSS CAD Suite so tools like yosys are available in the container.
28
+ RUN set -eux; \
29
+ case "${TARGETARCH}" in \
30
+ arm64) asset_arch=arm64 ;; \
31
+ amd64) asset_arch=x64 ;; \
32
+ *) echo "Unsupported target architecture: ${TARGETARCH}" && exit 1 ;; \
33
+ esac; \
34
+ archive="/tmp/oss-cad-suite.tgz"; \
35
+ curl -fsSL -o "${archive}" \
36
+ "https://github.com/YosysHQ/oss-cad-suite-build/releases/download/2026-04-07/oss-cad-suite-linux-${asset_arch}-${OSS_CAD_SUITE_VERSION}.tgz"; \
37
+ top_level_dir="$(tar -tzf "${archive}" | head -n 1 | cut -d/ -f1)"; \
38
+ tar -xzf "${archive}" -C /opt; \
39
+ if [ "${top_level_dir}" != "oss-cad-suite" ]; then \
40
+ mv "/opt/${top_level_dir}" /opt/oss-cad-suite; \
41
+ fi; \
42
+ rm -f "${archive}"
43
+
44
+ # Build argument to control whether we're building standalone or in-repo
45
+ ARG BUILD_MODE=in-repo
46
+ ARG ENV_NAME=chipforge
47
+
48
+ # Copy environment code (always at root of build context)
49
+ COPY . /app/env
50
+
51
+ # For in-repo builds, openenv is already vendored in the build context
52
+ # For standalone builds, openenv will be installed via pyproject.toml
53
+ WORKDIR /app/env
54
+
55
+ # Ensure uv is available (for local builds where base image lacks it)
56
+ RUN if ! command -v uv >/dev/null 2>&1; then \
57
+ curl -LsSf https://astral.sh/uv/install.sh | sh && \
58
+ mv /root/.local/bin/uv /usr/local/bin/uv && \
59
+ mv /root/.local/bin/uvx /usr/local/bin/uvx; \
60
+ fi
61
+
62
+ # Install dependencies using uv sync
63
+ # If uv.lock exists, use it; otherwise resolve on the fly
64
+ RUN --mount=type=cache,target=/root/.cache/uv \
65
+ if [ -f uv.lock ]; then \
66
+ uv sync --frozen --no-install-project --no-editable; \
67
+ else \
68
+ uv sync --no-install-project --no-editable; \
69
+ fi
70
+
71
+ RUN --mount=type=cache,target=/root/.cache/uv \
72
+ if [ -f uv.lock ]; then \
73
+ uv sync --frozen --no-editable; \
74
+ else \
75
+ uv sync --no-editable; \
76
+ fi
77
+
78
+ # Final runtime stage
79
+ FROM ${BASE_IMAGE}
80
+
81
+ WORKDIR /app
82
+
83
+ # Install runtime Perl support for Verilator's wrapper script.
84
+ RUN apt-get update && \
85
+ apt-get install -y --no-install-recommends g++ make perl perl-modules-5.40 && \
86
+ rm -rf /var/lib/apt/lists/*
87
+
88
+ # Copy OSS CAD Suite into the runtime image.
89
+ COPY --from=builder /opt/oss-cad-suite /opt/oss-cad-suite
90
+
91
+ # Copy the virtual environment from builder
92
+ COPY --from=builder /app/env/.venv /app/.venv
93
+
94
+ # Copy the environment code
95
+ COPY --from=builder /app/env /app/env
96
+
97
+ # Set PATH to use the virtual environment
98
+ ENV PATH="/opt/oss-cad-suite/bin:/app/.venv/bin:$PATH"
99
+
100
+ # Set PYTHONPATH so imports work correctly
101
+ ENV PYTHONPATH="/app/env:$PYTHONPATH"
102
+
103
+ # Health check
104
+ HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
105
+ CMD curl -f http://localhost:8000/health || exit 1
106
+
107
+ # Run the FastAPI server
108
+ # Use the package-qualified module path so relative imports resolve correctly.
109
+ ENV ENABLE_WEB_INTERFACE=true
110
+ CMD ["sh", "-c", "cd /app/env && uvicorn chipforge.server.app:app --host 0.0.0.0 --port 8000"]
README.md CHANGED
@@ -1,10 +1,167 @@
1
  ---
2
- title: Chiforge
3
- emoji: 🏃
4
- colorFrom: pink
5
- colorTo: yellow
6
- sdk: static
7
  pinned: false
 
 
 
 
 
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: ChipForge RTL Debugging Environment
3
+ emoji: 🔧
4
+ colorFrom: purple
5
+ colorTo: green
6
+ sdk: docker
7
  pinned: false
8
+ app_port: 8000
9
+ base_path: /web
10
+ tags:
11
+ - openenv
12
+ - verilog
13
+ - rtl
14
+ - semiconductor
15
  ---
16
 
17
+ # ChipForge RTL Debugging Environment
18
+
19
+ An OpenEnv environment where an AI agent debugs buggy Verilog RTL code using real EDA tools (**Verilator** for simulation/lint, **Yosys** for synthesis).
20
+
21
+ The agent receives buggy Verilog, inspects code, runs tools, reads error logs, edits lines to fix bugs, and submits the corrected design for grading.
22
+
23
+ ## Quick Start
24
+
25
+ ```python
26
+ from chipforge import ChipforgeAction, ChipforgeEnv
27
+
28
+ try:
29
+ env = ChipforgeEnv.from_docker_image("chipforge-env:latest")
30
+
31
+ # Start a new episode (loads a random buggy RTL task)
32
+ result = env.reset()
33
+ print(f"Task: {result.observation.task_description}")
34
+
35
+ # View the buggy RTL
36
+ result = env.step(ChipforgeAction(action_type="view_rtl"))
37
+ print(result.observation.rtl_code)
38
+
39
+ # Run simulation to see errors
40
+ result = env.step(ChipforgeAction(action_type="run_simulation"))
41
+ print(f"Status: {result.observation.sim_status}")
42
+ print(f"Error: {result.observation.error_summary}")
43
+
44
+ # Fix the bug
45
+ result = env.step(ChipforgeAction(
46
+ action_type="edit_line",
47
+ line_number=13,
48
+ new_content="assign sum = x1 ^ cin;"
49
+ ))
50
+
51
+ # Verify the fix
52
+ result = env.step(ChipforgeAction(action_type="run_simulation"))
53
+ print(f"Status: {result.observation.sim_status}")
54
+
55
+ # Submit solution
56
+ result = env.step(ChipforgeAction(action_type="submit"))
57
+ print(f"Reward: {result.observation.reward}")
58
+
59
+ finally:
60
+ env.close()
61
+ ```
62
+
63
+ ## Action Space
64
+
65
+ | Action | Parameters | Description |
66
+ |--------|-----------|-------------|
67
+ | `view_rtl` | — | View current RTL code with line numbers |
68
+ | `view_testbench` | — | View the testbench code |
69
+ | `view_logs` | `log_type`: sim/synth/lint | View output from last tool run |
70
+ | `run_simulation` | — | Compile + simulate with Verilator |
71
+ | `run_synthesis` | — | Synthesize with Yosys |
72
+ | `run_lint` | — | Run Verilator lint checks |
73
+ | `edit_line` | `line_number`, `new_content` | Replace a single line of RTL |
74
+ | `submit` | — | Submit fix and get final reward |
75
+
76
+ ## Observation Space
77
+
78
+ | Field | Type | Description |
79
+ |-------|------|-------------|
80
+ | `rtl_code` | str | Current RTL (populated by `view_rtl`) |
81
+ | `testbench_code` | str | Testbench (populated by `view_testbench`) |
82
+ | `log_output` | str | Tool output (populated by `view_logs`) |
83
+ | `sim_status` | str | `not_run` / `pass` / `fail` / `error` |
84
+ | `synth_status` | str | `not_run` / `pass` / `warning` / `error` |
85
+ | `lint_status` | str | `not_run` / `clean` / `warning` / `error` |
86
+ | `error_summary` | str | One-line error hint |
87
+ | `task_description` | str | Description of the current task |
88
+ | `step_count` | int | Steps taken so far |
89
+ | `max_steps` | int | Maximum allowed steps (20) |
90
+
91
+ ## Reward
92
+
93
+ | Component | Value | Condition |
94
+ |-----------|-------|-----------|
95
+ | Compiles | +0.2 | No syntax errors |
96
+ | Simulation passes | +0.3 | Output matches expected truth table |
97
+ | Synthesis clean | +0.3 | No warnings (e.g., no latches) |
98
+ | Lint clean | +0.2 | No lint warnings |
99
+ | Step penalty | -0.01/step | Encourages efficiency |
100
+
101
+ Maximum reward: **1.0** (all checks pass, minimal steps).
102
+
103
+ ## Tasks
104
+
105
+ | # | Name | Difficulty | Bug Type |
106
+ |---|------|-----------|----------|
107
+ | 1 | `task_easy_syntax` | Easy | Incomplete XOR expression |
108
+ | 2 | `task_easy_missing_semicolon` | Easy | Missing semicolon on wire declaration |
109
+ | 3 | `task_medium_logic_bug` | Medium | Wrong operator in sum computation |
110
+ | 4 | `task_medium_wrong_operator` | Medium | XOR instead of AND in carry logic |
111
+ | 5 | `task_hard_latch_inference` | Hard | Missing else branch → latch inferred |
112
+
113
+ ## Tools Used
114
+
115
+ | Tool | Role | Installed via |
116
+ |------|------|--------------|
117
+ | **Verilator** | Simulation + Linting | OSS CAD Suite |
118
+ | **Yosys** | Synthesis | OSS CAD Suite |
119
+
120
+ Both tools are bundled in the Docker image via [OSS CAD Suite](https://github.com/YosysHQ/oss-cad-suite-build).
121
+
122
+ ## Building & Running
123
+
124
+ ```bash
125
+ # Build Docker image
126
+ docker build -t chipforge-env:latest -f server/Dockerfile .
127
+
128
+ # Run locally (for development)
129
+ uvicorn chipforge.server.app:app --reload
130
+
131
+ # Deploy to Hugging Face Spaces
132
+ openenv push
133
+ ```
134
+
135
+ ## Project Structure
136
+
137
+ ```
138
+ chipforge/
139
+ ├── __init__.py # Module exports
140
+ ├── models.py # Action + Observation models
141
+ ├── client.py # ChipforgeEnv client
142
+ ├── openenv.yaml # OpenEnv manifest
143
+ ├── pyproject.toml # Dependencies
144
+ └── server/
145
+ ├── app.py # FastAPI application
146
+ ├── chipforge_environment.py # Core environment logic
147
+ ├── Dockerfile # Container with Verilator + Yosys
148
+ └── tasks/ # RTL debugging tasks
149
+ ├── task_easy_syntax/
150
+ ├── task_easy_missing_semicolon/
151
+ ├── task_medium_logic_bug/
152
+ ├── task_medium_wrong_operator/
153
+ └── task_hard_latch_inference/
154
+ ```
155
+
156
+ ## Example Agent Episode
157
+
158
+ ```
159
+ reset() → Task: "Fix the syntax error in the full adder RTL"
160
+
161
+ view_rtl → see buggy code with line numbers
162
+ run_simulation → sim_status="error", error_summary="syntax error near '^'"
163
+ edit_line(13, "assign sum = x1 ^ cin;") → "Line 13 updated"
164
+ run_simulation → sim_status="pass"
165
+ run_synthesis → synth_status="pass"
166
+ submit → reward=0.93
167
+ ```
__init__.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ # All rights reserved.
3
+ #
4
+ # This source code is licensed under the BSD-style license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ """Chipforge Environment."""
8
+
9
+ from .client import ChipforgeEnv
10
+ from .models import ChipforgeAction, ChipforgeObservation
11
+
12
+ __all__ = [
13
+ "ChipforgeAction",
14
+ "ChipforgeObservation",
15
+ "ChipforgeEnv",
16
+ ]
client.py ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ # All rights reserved.
3
+ #
4
+ # This source code is licensed under the BSD-style license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ """ChipForge Environment Client."""
8
+
9
+ from typing import Dict
10
+
11
+ from openenv.core import EnvClient
12
+ from openenv.core.client_types import StepResult
13
+ from openenv.core.env_server.types import State
14
+
15
+ from .models import ChipforgeAction, ChipforgeObservation
16
+
17
+
18
+ class ChipforgeEnv(
19
+ EnvClient[ChipforgeAction, ChipforgeObservation, State]
20
+ ):
21
+ """
22
+ Client for the ChipForge RTL Debugging Environment.
23
+
24
+ This client maintains a persistent WebSocket connection to the environment
25
+ server, enabling efficient multi-step interactions with lower latency.
26
+
27
+ Example:
28
+ >>> with ChipforgeEnv(base_url="http://localhost:8000") as client:
29
+ ... result = client.reset()
30
+ ... print(result.observation.rtl_code) # RTL is always in observation
31
+ ...
32
+ ... # View the testbench code
33
+ ... result = client.step(ChipforgeAction(action_type="view_testbench"))
34
+ ... print(result.observation.testbench_code)
35
+ ...
36
+ ... # Run simulation and view the results
37
+ ... result = client.step(ChipforgeAction(action_type="run_simulation"))
38
+ ... result = client.step(ChipforgeAction(action_type="view_simulation_log"))
39
+ ... print(result.observation.log_output)
40
+ ...
41
+ ... # Edit a line
42
+ ... result = client.step(ChipforgeAction(
43
+ ... action_type="edit_line",
44
+ ... line_number=13,
45
+ ... new_content="assign sum = x1 ^ cin;"
46
+ ... ))
47
+
48
+ Example with Docker:
49
+ >>> client = ChipforgeEnv.from_docker_image("chipforge-env:latest")
50
+ >>> try:
51
+ ... result = client.reset()
52
+ ... print(result.observation.rtl_code) # RTL is always present
53
+ ... result = client.step(ChipforgeAction(action_type="run_simulation"))
54
+ ... finally:
55
+ ... client.close()
56
+ """
57
+
58
+ def _step_payload(self, action: ChipforgeAction) -> Dict:
59
+ """
60
+ Convert ChipforgeAction to JSON payload for step message.
61
+
62
+ Args:
63
+ action: ChipforgeAction instance
64
+
65
+ Returns:
66
+ Dictionary representation suitable for JSON encoding
67
+ """
68
+ payload = {"action_type": action.action_type}
69
+
70
+ if action.line_number is not None:
71
+ payload["line_number"] = action.line_number
72
+ if action.new_content is not None:
73
+ payload["new_content"] = action.new_content
74
+ return payload
75
+
76
+ def _parse_result(self, payload: Dict) -> StepResult[ChipforgeObservation]:
77
+ """
78
+ Parse server response into StepResult[ChipforgeObservation].
79
+
80
+ Args:
81
+ payload: JSON response data from server
82
+
83
+ Returns:
84
+ StepResult with ChipforgeObservation
85
+ """
86
+ obs_data = payload.get("observation", {})
87
+ observation = ChipforgeObservation(
88
+ rtl_code=obs_data.get("rtl_code", ""),
89
+ testbench_code=obs_data.get("testbench_code", ""),
90
+ log_output=obs_data.get("log_output", ""),
91
+ sim_status=obs_data.get("sim_status", "not_run"),
92
+ synth_status=obs_data.get("synth_status", "not_run"),
93
+ lint_status=obs_data.get("lint_status", "not_run"),
94
+ error_summary=obs_data.get("error_summary", ""),
95
+ task_description=obs_data.get("task_description", ""),
96
+ step_count=obs_data.get("step_count", 0),
97
+ max_steps=obs_data.get("max_steps", 20),
98
+ done=payload.get("done", False),
99
+ reward=payload.get("reward"),
100
+ metadata=obs_data.get("metadata", {}),
101
+ )
102
+
103
+ return StepResult(
104
+ observation=observation,
105
+ reward=payload.get("reward"),
106
+ done=payload.get("done", False),
107
+ )
108
+
109
+ def _parse_state(self, payload: Dict) -> State:
110
+ """
111
+ Parse server response into State object.
112
+
113
+ Args:
114
+ payload: JSON response from state request
115
+
116
+ Returns:
117
+ State object with episode_id and step_count
118
+ """
119
+ return State(
120
+ episode_id=payload.get("episode_id"),
121
+ step_count=payload.get("step_count", 0),
122
+ )
inference.py ADDED
@@ -0,0 +1,504 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ LLM inference runner for ChipForge RTL Debugging Environment.
4
+
5
+ This script lets a chat model debug buggy Verilog RTL by choosing actions
6
+ (view code, run simulation/synthesis, edit lines, submit) against the
7
+ ChipForge HTTP server.
8
+
9
+ Examples:
10
+ # HTTP mode against running server
11
+ python inference.py --mode http --env-url http://localhost:8000
12
+
13
+ # Local mode (requires Verilator + Yosys on PATH)
14
+ python inference.py --mode local --episodes 1
15
+ """
16
+ from __future__ import annotations
17
+
18
+ import argparse
19
+ import json
20
+ import os
21
+ import re
22
+ import urllib.error
23
+ import urllib.request
24
+ from typing import Any, Optional
25
+
26
+ from dotenv import load_dotenv
27
+
28
+ load_dotenv()
29
+
30
+ # ---------------------------------------------------------------------------
31
+ # Action definitions
32
+ # ---------------------------------------------------------------------------
33
+
34
+ VALID_ACTIONS = [
35
+ "view_testbench",
36
+ "view_synthesis_log",
37
+ "view_lint_log",
38
+ "view_simulation_log",
39
+ "run_simulation",
40
+ "run_synthesis",
41
+ "run_lint",
42
+ "edit_line",
43
+ "append_line",
44
+ "edit_testbench_line",
45
+ "append_testbench_line",
46
+ "submit",
47
+ ]
48
+
49
+ DEFAULT_LLM_MODEL = os.environ.get("LLM_MODEL", "mistral-medium-2505")
50
+
51
+ # ---------------------------------------------------------------------------
52
+ # System prompt
53
+ # ---------------------------------------------------------------------------
54
+
55
+ SYSTEM_PROMPT = """You are an expert Verilog/RTL debugging agent controlling the ChipForge environment.
56
+ Your goal is to fix buggy Verilog RTL code so it passes simulation, synthesis, and lint checks.
57
+
58
+ Available actions (return exactly ONE JSON action per turn):
59
+
60
+ 1. view_testbench — View the testbench code
61
+ 2. view_synthesis_log — View synthesis tool logs from last run
62
+ 3. view_lint_log — View lint tool logs from last run
63
+ 4. view_simulation_log — View simulation tool logs from last run
64
+ 5. run_simulation — Compile and simulate with Verilator
65
+ 6. run_synthesis — Synthesize with Yosys
66
+ 7. run_lint — Run Verilator lint checks
67
+ 8. edit_line — Replace a single line. Requires line_number (1-indexed) and new_content
68
+ 9. append_line — Append one RTL line. Requires new_content
69
+ 10. edit_testbench_line — Replace a single testbench line. Requires line_number and new_content
70
+ 11. append_testbench_line — Append one testbench line. Requires new_content
71
+ 12. submit — Submit current RTL as final solution (triggers grading)
72
+
73
+ Response format — return ONLY valid JSON:
74
+ {"action_type": "...", "line_number": null, "new_content": null, "reasoning": "..."}
75
+
76
+ Strategy:
77
+ 1. The observation always includes the current RTL code — you don't need to view it separately
78
+ 2. Run run_simulation to see compilation/output errors
79
+ 3. If there are errors, use view_simulation_log to read error details
80
+ 4. Use edit_line to fix the bug (one line at a time)
81
+ 5. Use append_line / append_testbench_line if a task starts with missing files
82
+ 6. Re-run simulation to verify the fix
83
+ 6. Run synthesis and lint to ensure clean results
84
+ 7. Use view_synthesis_log and view_lint_log to check for warnings/errors
85
+ 9. Submit when everything passes
86
+
87
+ Rules:
88
+ - Return valid JSON only, no markdown
89
+ - Use null for fields that don't apply to the chosen action
90
+ - Fix bugs methodically — read error logs before editing
91
+ - Minimize steps for a higher reward (step penalty of -0.02/step)
92
+ - Optimize cumulative_reward across the full episode, not only the immediate step reward
93
+ """
94
+
95
+
96
+ # ---------------------------------------------------------------------------
97
+ # LLM helpers
98
+ # ---------------------------------------------------------------------------
99
+
100
+
101
+ def build_prompt(observation: dict[str, Any]) -> str:
102
+ """Build user prompt from the current observation."""
103
+ parts = ["Fix the RTL bug."]
104
+
105
+ # Always show step information
106
+ parts.append(
107
+ f"Step: {observation.get('step_count', '?')}/{observation.get('max_steps', 20)}"
108
+ )
109
+
110
+ if observation.get("error_summary"):
111
+ parts.append(f"Error: {observation['error_summary']}")
112
+ if observation.get("last_action"):
113
+ parts.append(f"Last action: {observation['last_action']}")
114
+ if observation.get("action_result"):
115
+ parts.append(f"Action result: {observation['action_result']}")
116
+
117
+ status_line = (
118
+ f"Status: sim={observation.get('sim_status', 'not_run')}, "
119
+ f"synth={observation.get('synth_status', 'not_run')}, "
120
+ f"lint={observation.get('lint_status', 'not_run')}"
121
+ )
122
+ parts.append(status_line)
123
+
124
+ metadata = observation.get("metadata", {}) or {}
125
+ if "code_dirty" in metadata:
126
+ parts.append(f"Code dirty since last validation: {metadata.get('code_dirty')}")
127
+ tool_freshness = metadata.get("tool_freshness", {})
128
+ if tool_freshness:
129
+ parts.append(
130
+ "Tool freshness: "
131
+ f"sim={tool_freshness.get('simulation')}, "
132
+ f"synth={tool_freshness.get('synthesis')}, "
133
+ f"lint={tool_freshness.get('lint')}"
134
+ )
135
+
136
+ # Include content fields if populated
137
+ if observation.get("rtl_code"):
138
+ parts.append(f"\n--- RTL Code ---\n{observation['rtl_code']}")
139
+
140
+ if observation.get("testbench_code"):
141
+ parts.append(f"\n--- Testbench ---\n{observation['testbench_code']}")
142
+
143
+ if observation.get("log_output"):
144
+ # Truncate very long logs
145
+ log = observation["log_output"][:1500]
146
+ parts.append(f"\n--- Log Output ---\n{log}")
147
+
148
+ parts.append("\nReturn your next action as JSON:")
149
+ return "\n".join(parts)
150
+
151
+
152
+ def parse_action(text: str) -> Optional[dict[str, Any]]:
153
+ """Try to extract a JSON action from the LLM response."""
154
+ text = text.strip()
155
+
156
+ # Direct JSON
157
+ try:
158
+ return json.loads(text)
159
+ except Exception:
160
+ pass
161
+
162
+ # Fenced code block
163
+ match = re.search(r"```(?:json)?\s*(\{.*?\})\s*```", text, re.DOTALL)
164
+ if match:
165
+ try:
166
+ return json.loads(match.group(1))
167
+ except Exception:
168
+ pass
169
+
170
+ # Any JSON object
171
+ match = re.search(r"\{.*\}", text, re.DOTALL)
172
+ if match:
173
+ try:
174
+ return json.loads(match.group(0))
175
+ except Exception:
176
+ pass
177
+
178
+ return None
179
+
180
+
181
+ def validate_action(action: dict[str, Any]) -> dict[str, Any]:
182
+ """Validate and normalize the parsed action."""
183
+ action_type = action.get("action_type", "run_simulation")
184
+ if action_type not in VALID_ACTIONS:
185
+ action_type = "run_simulation"
186
+
187
+ payload: dict[str, Any] = {"action_type": action_type}
188
+
189
+ if action_type in ("edit_line", "edit_testbench_line"):
190
+ payload["line_number"] = action.get("line_number")
191
+ payload["new_content"] = action.get("new_content")
192
+ elif action_type in ("append_line", "append_testbench_line"):
193
+ payload["new_content"] = action.get("new_content")
194
+
195
+ return payload
196
+
197
+
198
+ # ---------------------------------------------------------------------------
199
+ # LLM client (Mistral)
200
+ # ---------------------------------------------------------------------------
201
+
202
+
203
+ def make_mistral_client(api_key: Optional[str] = None):
204
+ from mistralai.client import Mistral
205
+
206
+ return Mistral(
207
+ api_key=api_key or os.environ.get("MISTRAL_API_KEY"),
208
+ timeout_ms=120_000, # 120s — magistral is a reasoning model
209
+ )
210
+
211
+
212
+ def call_llm(client, model: str, prompt: str, temperature: float, max_retries: int = 3) -> str:
213
+ """Call the LLM with retry on timeout."""
214
+ import time as _time
215
+
216
+ for attempt in range(max_retries):
217
+ try:
218
+ response = client.chat.complete(
219
+ model=model,
220
+ messages=[
221
+ {"role": "system", "content": SYSTEM_PROMPT},
222
+ {"role": "user", "content": prompt},
223
+ ],
224
+ temperature=temperature,
225
+ )
226
+ content = response.choices[0].message.content
227
+ if not content:
228
+ raise RuntimeError("LLM response missing content")
229
+
230
+ # Some models (e.g. magistral) return content as a list of blocks
231
+ if isinstance(content, list):
232
+ parts = []
233
+ for block in content:
234
+ if isinstance(block, str):
235
+ parts.append(block)
236
+ elif hasattr(block, "text"):
237
+ parts.append(block.text)
238
+ elif isinstance(block, dict) and "text" in block:
239
+ parts.append(block["text"])
240
+ else:
241
+ parts.append(str(block))
242
+ content = "\n".join(parts)
243
+
244
+ return content
245
+
246
+ except Exception as e:
247
+ if attempt < max_retries - 1:
248
+ wait = 5 * (attempt + 1)
249
+ print(f" ⚠️ LLM call failed ({e.__class__.__name__}), retrying in {wait}s...")
250
+ _time.sleep(wait)
251
+ else:
252
+ raise
253
+
254
+
255
+ # ---------------------------------------------------------------------------
256
+ # HTTP helpers
257
+ # ---------------------------------------------------------------------------
258
+
259
+
260
+ def request_json(
261
+ url: str,
262
+ method: str = "GET",
263
+ payload: Optional[dict[str, Any]] = None,
264
+ ) -> dict[str, Any]:
265
+ """Make an HTTP request and return parsed JSON."""
266
+ data = None
267
+ headers = {}
268
+ if payload is not None:
269
+ data = json.dumps(payload).encode("utf-8")
270
+ headers["Content-Type"] = "application/json"
271
+ req = urllib.request.Request(url, data=data, headers=headers, method=method)
272
+ with urllib.request.urlopen(req, timeout=120) as resp:
273
+ return json.loads(resp.read().decode("utf-8"))
274
+
275
+
276
+ # ---------------------------------------------------------------------------
277
+ # Episode runners
278
+ # ---------------------------------------------------------------------------
279
+
280
+
281
+ def run_http_episode(args: argparse.Namespace) -> float:
282
+ """Run one episode against the server using WebSocket (persistent session)."""
283
+ import time
284
+ import websocket # pip install websocket-client
285
+
286
+ llm_client = make_mistral_client(args.api_key)
287
+
288
+ # Connect via WebSocket for persistent session state
289
+ ws_url = args.env_url.replace("http://", "ws://").replace("https://", "wss://") + "/ws"
290
+ ws = websocket.create_connection(ws_url, timeout=120)
291
+
292
+ def ws_send(msg_type: str, data: dict = None) -> dict:
293
+ """Send a WebSocket message and return the response."""
294
+ payload = {"type": msg_type}
295
+ if data is not None:
296
+ payload["data"] = data
297
+ ws.send(json.dumps(payload))
298
+ return json.loads(ws.recv())
299
+
300
+ # Reset
301
+ reset_payload: dict[str, Any] = {}
302
+ if args.seed is not None:
303
+ reset_payload["seed"] = args.seed
304
+ if args.task_name:
305
+ reset_payload["task_name"] = args.task_name
306
+ reset_resp = ws_send("reset", reset_payload if reset_payload else None)
307
+ obs = reset_resp.get("data", {})
308
+ total_reward = 0.0
309
+
310
+ print(f" Starting episode...")
311
+ print()
312
+
313
+ for step in range(args.max_steps):
314
+ # Build prompt and query LLM
315
+ prompt = build_prompt(obs)
316
+ raw_response = call_llm(
317
+ client=llm_client,
318
+ model=args.model,
319
+ prompt=prompt,
320
+ temperature=args.temperature,
321
+ )
322
+
323
+ # Parse and validate
324
+ parsed = parse_action(raw_response)
325
+ if parsed is None:
326
+ parsed = {"action_type": "run_simulation", "reasoning": "Failed to parse LLM response"}
327
+
328
+ action_dict = validate_action(parsed)
329
+
330
+ reasoning = parsed.get("reasoning", "")
331
+
332
+ # Step via WebSocket
333
+ step_resp = ws_send("step", action_dict)
334
+ obs = step_resp.get("data", {}).get("observation", step_resp.get("data", {}))
335
+ reward = float(step_resp.get("data", {}).get("reward", 0.0))
336
+ done = step_resp.get("data", {}).get("done", False)
337
+ total_reward += reward
338
+ obs_cumulative_reward = obs.get("cumulative_reward")
339
+
340
+ # Print step header
341
+ print(f"\n {'─'*56}")
342
+ print(f" STEP {step + 1}/{args.max_steps}")
343
+ print(f" {'─'*56}")
344
+
345
+ # Print full action object
346
+ print(f"\n ▶ ACTION:")
347
+ print(f" {json.dumps(action_dict, indent=4)}")
348
+ if reasoning:
349
+ print(f" reasoning: {reasoning}")
350
+
351
+ # Print observation
352
+ print(f"\n ◀ OBSERVATION:")
353
+ print(f" {json.dumps(obs, indent=4)}")
354
+
355
+ print(
356
+ f"\n Reward: step={reward:+.3f} episode_return={total_reward:+.3f} "
357
+ f"obs_cumulative={obs_cumulative_reward}"
358
+ )
359
+
360
+ if done:
361
+ print(f"\n 🏁 EPISODE DONE — Episode return: {total_reward:+.3f}")
362
+ break
363
+
364
+ # 10 second delay between steps
365
+ print(f"\n ⏳ Waiting 10 seconds...")
366
+ time.sleep(10)
367
+
368
+ ws.close()
369
+ print(f"\n Final episode return: {total_reward:+.3f}")
370
+ return total_reward
371
+
372
+
373
+ def run_local_episode(args: argparse.Namespace) -> float:
374
+ """Run one episode using the local environment (needs Verilator+Yosys)."""
375
+ import sys
376
+
377
+ sys.path.insert(0, os.path.dirname(__file__))
378
+
379
+ from models import ChipforgeAction
380
+ from server.chipforge_environment import ChipforgeEnvironment
381
+
382
+ client = make_mistral_client(args.api_key)
383
+ env = ChipforgeEnvironment()
384
+
385
+ reset_kwargs: dict[str, Any] = {}
386
+ if args.seed is not None:
387
+ reset_kwargs["seed"] = args.seed
388
+ if args.task_name:
389
+ reset_kwargs["task_name"] = args.task_name
390
+ obs = env.reset(**reset_kwargs)
391
+ total_reward = 0.0
392
+
393
+ print(f" Starting episode...")
394
+ print()
395
+
396
+ for step in range(args.max_steps):
397
+ # Build observation dict for prompt
398
+ obs_dict = {
399
+ "rtl_code": obs.rtl_code,
400
+ "testbench_code": obs.testbench_code,
401
+ "log_output": obs.log_output,
402
+ "sim_status": obs.sim_status,
403
+ "synth_status": obs.synth_status,
404
+ "lint_status": obs.lint_status,
405
+ "last_action": obs.last_action,
406
+ "action_result": obs.action_result,
407
+ "error_summary": obs.error_summary,
408
+ "metadata": obs.metadata,
409
+ "step_count": obs.step_count,
410
+ "max_steps": obs.max_steps,
411
+ }
412
+
413
+ prompt = build_prompt(obs_dict)
414
+ raw_response = call_llm(
415
+ client=client,
416
+ model=args.model,
417
+ prompt=prompt,
418
+ temperature=args.temperature,
419
+ )
420
+
421
+ parsed = parse_action(raw_response)
422
+ if parsed is None:
423
+ parsed = {"action_type": "run_simulation", "reasoning": "Failed to parse"}
424
+
425
+ action_dict = validate_action(parsed)
426
+ reasoning = parsed.get("reasoning", "")
427
+
428
+ action = ChipforgeAction(**action_dict)
429
+ obs = env.step(action)
430
+ step_reward = float(obs.reward or 0.0)
431
+ total_reward += step_reward
432
+
433
+ action_str = action_dict["action_type"]
434
+ if action_dict["action_type"] == "edit_line":
435
+ action_str += f"({action_dict.get('line_number', '?')})"
436
+
437
+ print(
438
+ f" step={step + 1:02d} action={action_str:25s} "
439
+ f"reward={step_reward:+.3f} return={total_reward:+.3f} done={obs.done}"
440
+ )
441
+ if reasoning:
442
+ print(f" reasoning: {reasoning[:80]}")
443
+
444
+ if obs.done:
445
+ break
446
+
447
+ env.close()
448
+ print(f"\n Final episode return: {total_reward:+.3f}")
449
+ return total_reward
450
+
451
+
452
+ # ---------------------------------------------------------------------------
453
+ # CLI
454
+ # ---------------------------------------------------------------------------
455
+
456
+
457
+ def build_arg_parser() -> argparse.ArgumentParser:
458
+ parser = argparse.ArgumentParser(
459
+ description="Run an LLM agent against ChipForge RTL Debugging Environment."
460
+ )
461
+ parser.add_argument("--mode", choices=["local", "http"], default="http")
462
+ parser.add_argument("--env-url", default="http://localhost:8000")
463
+ parser.add_argument("--model", default=DEFAULT_LLM_MODEL)
464
+ parser.add_argument("--api-key", default=os.environ.get("MISTRAL_API_KEY"))
465
+ parser.add_argument("--episodes", type=int, default=1)
466
+ parser.add_argument("--max-steps", type=int, default=20)
467
+ parser.add_argument("--seed", type=int, default=None)
468
+ parser.add_argument(
469
+ "--task-name",
470
+ default=None,
471
+ help="Optional task directory name under server/tasks (e.g. easy/03_write_testbench_from_prompt).",
472
+ )
473
+ parser.add_argument("--temperature", type=float, default=0.2)
474
+ return parser
475
+
476
+
477
+ def main() -> int:
478
+ args = build_arg_parser().parse_args()
479
+
480
+ total_rewards = []
481
+ for episode in range(args.episodes):
482
+ print(f"\n{'='*60}")
483
+ print(f" Episode {episode + 1}/{args.episodes}")
484
+ print(f"{'='*60}")
485
+
486
+ if args.mode == "local":
487
+ reward = run_local_episode(args)
488
+ else:
489
+ reward = run_http_episode(args)
490
+
491
+ total_rewards.append(reward)
492
+
493
+ # Summary
494
+ avg = sum(total_rewards) / len(total_rewards)
495
+ print(f"\n{'='*60}")
496
+ print(f" Summary: {len(total_rewards)} episodes, avg reward: {avg:+.3f}")
497
+ print(f" Rewards: {[f'{r:+.3f}' for r in total_rewards]}")
498
+ print(f"{'='*60}")
499
+
500
+ return 0
501
+
502
+
503
+ if __name__ == "__main__":
504
+ raise SystemExit(main())
models.py ADDED
@@ -0,0 +1,164 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ # All rights reserved.
3
+ #
4
+ # This source code is licensed under the BSD-style license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ """
8
+ Data models for the ChipForge RTL Debugging Environment.
9
+
10
+ Designed for RL training of LLMs:
11
+ - Observation is a self-contained Markov state (always includes RTL code)
12
+ - Reward uses potential-based shaping for dense per-step signal
13
+ - Action result feedback at every step
14
+ """
15
+
16
+ from typing import Any, Dict, Literal, Optional
17
+
18
+ from openenv.core.env_server.types import Action, Observation
19
+ from pydantic import Field, model_validator
20
+
21
+ ActionType = Literal[
22
+ "view_testbench",
23
+ "view_synthesis_log",
24
+ "view_lint_log",
25
+ "view_simulation_log",
26
+ "run_simulation",
27
+ "run_synthesis",
28
+ "run_lint",
29
+ "edit_line",
30
+ "append_line",
31
+ "edit_testbench_line",
32
+ "append_testbench_line",
33
+ "submit",
34
+ ]
35
+
36
+
37
+ class ChipforgeAction(Action):
38
+ """Action for the ChipForge environment.
39
+
40
+ Supported action_types:
41
+ - view_testbench: View the testbench code
42
+ - view_synthesis_log: View synthesis log (only if run_synthesis was executed)
43
+ - view_lint_log: View lint log (only if run_lint was executed)
44
+ - view_simulation_log: View simulation log (only if run_simulation was executed)
45
+ - run_simulation: Compile and simulate with Verilator
46
+ - run_synthesis: Synthesize with Yosys
47
+ - run_lint: Run Verilator lint checks
48
+ - edit_line: Replace a single line (requires line_number + new_content)
49
+ - append_line: Append one new RTL line (requires new_content)
50
+ - edit_testbench_line: Replace a single testbench line (requires line_number + new_content)
51
+ - append_testbench_line: Append one new testbench line (requires new_content)
52
+ - submit: Submit current RTL as the final solution
53
+ """
54
+
55
+ action_type: ActionType = Field(..., description="Type of action to execute")
56
+ line_number: Optional[int] = Field(
57
+ default=None,
58
+ description="Line number to edit (1-indexed). Required for edit_line.",
59
+ )
60
+ new_content: Optional[str] = Field(
61
+ default=None,
62
+ description="New content for the line. Required for edit_line.",
63
+ )
64
+ log_type: Optional[str] = Field(
65
+ default=None,
66
+ description="Deprecated. Use view_synthesis_log, view_lint_log, or view_simulation_log instead.",
67
+ )
68
+
69
+ @model_validator(mode="after")
70
+ def validate_action_payload(self) -> "ChipforgeAction":
71
+ is_edit = self.action_type == "edit_line"
72
+ is_append = self.action_type == "append_line"
73
+ is_tb_edit = self.action_type == "edit_testbench_line"
74
+ is_tb_append = self.action_type == "append_testbench_line"
75
+ has_line = self.line_number is not None
76
+ has_content = self.new_content is not None
77
+
78
+ if is_edit and (not has_line or not has_content):
79
+ raise ValueError("edit_line requires both line_number and new_content")
80
+
81
+ if is_tb_edit and (not has_line or not has_content):
82
+ raise ValueError("edit_testbench_line requires both line_number and new_content")
83
+
84
+ if (is_append or is_tb_append) and (not has_content or has_line):
85
+ raise ValueError(
86
+ "append_line/append_testbench_line require new_content only"
87
+ )
88
+
89
+ if (not is_edit and not is_tb_edit and not is_append and not is_tb_append) and (
90
+ has_line or has_content
91
+ ):
92
+ raise ValueError(
93
+ "line_number/new_content are only valid for edit_line, append_line, "
94
+ "edit_testbench_line, append_testbench_line"
95
+ )
96
+ return self
97
+
98
+
99
+ class ChipforgeObservation(Observation):
100
+ """Observation returned by the ChipForge environment.
101
+
102
+ Designed as a self-contained Markov state for RL training.
103
+ Always includes the current RTL code.
104
+ Tool logs are only populated when explicitly requested via:
105
+ - view_synthesis_log: Shows synthesis logs from last run
106
+ - view_lint_log: Shows lint logs from last run
107
+ - view_simulation_log: Shows simulation logs from last run
108
+ """
109
+
110
+ # ── Always populated (Markov state core) ─────────────────────────────
111
+ rtl_code: str = Field(
112
+ default="",
113
+ description="Current RTL design code with line numbers (always present)",
114
+ )
115
+ sim_status: Literal["not_run", "pass", "fail", "error"] = Field(
116
+ default="not_run",
117
+ description="Latest simulation status for current RTL snapshot",
118
+ )
119
+ synth_status: Literal["not_run", "pass", "warning", "error"] = Field(
120
+ default="not_run",
121
+ description="Latest synthesis status for current RTL snapshot",
122
+ )
123
+ lint_status: Literal["not_run", "clean", "warning", "error"] = Field(
124
+ default="not_run",
125
+ description="Latest lint status for current RTL snapshot",
126
+ )
127
+ error_summary: str = Field(
128
+ default="",
129
+ description="One-line summary of the most relevant diagnostic",
130
+ )
131
+ task_description: str = Field(
132
+ default="",
133
+ description="Natural language description of the loaded RTL debug task",
134
+ )
135
+
136
+ # Action feedback (what just happened)
137
+ last_action: str = Field(
138
+ default="reset", description="The action that produced this observation"
139
+ )
140
+ action_result: str = Field(
141
+ default="",
142
+ description="Human-readable result of the last action taken",
143
+ )
144
+
145
+ # ── Conditionally populated (verbose action-specific payload) ─────────
146
+ testbench_code: str = Field(
147
+ default="", description="Testbench code (populated by view_testbench)"
148
+ )
149
+ log_output: str = Field(
150
+ default="",
151
+ description="Tool output log, truncated to 2000 chars (populated by view_synthesis_log, view_lint_log, view_simulation_log, or tool runs)",
152
+ )
153
+ metadata: Dict[str, Any] = Field(
154
+ default_factory=dict,
155
+ description="Optional extra machine-readable fields for clients/prompts",
156
+ )
157
+
158
+ # ── RL signals ──────────────────────────────────────────────────────
159
+ step_count: int = Field(default=0, description="Steps taken so far")
160
+ max_steps: int = Field(default=20, description="Maximum allowed steps")
161
+ cumulative_reward: float = Field(
162
+ default=0.0,
163
+ description="Total quality score so far (0.0 to 1.0)",
164
+ )
obj_dir/Vsim ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e178e8ea680df686c13f65b6251df05731d0476c78554ebd1cb0bd52f28d0ef4
3
+ size 295160
obj_dir/Vsim.cpp ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Verilated -*- C++ -*-
2
+ // DESCRIPTION: Verilator output: Model implementation (design independent parts)
3
+
4
+ #include "Vsim__pch.h"
5
+ #include "verilated_vcd_c.h"
6
+
7
+ //============================================================
8
+ // Constructors
9
+
10
+ Vsim::Vsim(VerilatedContext* _vcontextp__, const char* _vcname__)
11
+ : VerilatedModel{*_vcontextp__}
12
+ , vlSymsp{new Vsim__Syms(contextp(), _vcname__, this)}
13
+ , rootp{&(vlSymsp->TOP)}
14
+ {
15
+ // Register model with the context
16
+ contextp()->addModel(this);
17
+ contextp()->traceBaseModelCbAdd(
18
+ [this](VerilatedTraceBaseC* tfp, int levels, int options) { traceBaseModel(tfp, levels, options); });
19
+ }
20
+
21
+ Vsim::Vsim(const char* _vcname__)
22
+ : Vsim(Verilated::threadContextp(), _vcname__)
23
+ {
24
+ }
25
+
26
+ //============================================================
27
+ // Destructor
28
+
29
+ Vsim::~Vsim() {
30
+ delete vlSymsp;
31
+ }
32
+
33
+ //============================================================
34
+ // Evaluation function
35
+
36
+ #ifdef VL_DEBUG
37
+ void Vsim___024root___eval_debug_assertions(Vsim___024root* vlSelf);
38
+ #endif // VL_DEBUG
39
+ void Vsim___024root___eval_static(Vsim___024root* vlSelf);
40
+ void Vsim___024root___eval_initial(Vsim___024root* vlSelf);
41
+ void Vsim___024root___eval_settle(Vsim___024root* vlSelf);
42
+ void Vsim___024root___eval(Vsim___024root* vlSelf);
43
+
44
+ void Vsim::eval_step() {
45
+ VL_DEBUG_IF(VL_DBG_MSGF("+++++TOP Evaluate Vsim::eval_step\n"); );
46
+ #ifdef VL_DEBUG
47
+ // Debug assertions
48
+ Vsim___024root___eval_debug_assertions(&(vlSymsp->TOP));
49
+ #endif // VL_DEBUG
50
+ vlSymsp->__Vm_activity = true;
51
+ vlSymsp->__Vm_deleter.deleteAll();
52
+ if (VL_UNLIKELY(!vlSymsp->__Vm_didInit)) {
53
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Initial\n"););
54
+ Vsim___024root___eval_static(&(vlSymsp->TOP));
55
+ Vsim___024root___eval_initial(&(vlSymsp->TOP));
56
+ Vsim___024root___eval_settle(&(vlSymsp->TOP));
57
+ vlSymsp->__Vm_didInit = true;
58
+ }
59
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Eval\n"););
60
+ Vsim___024root___eval(&(vlSymsp->TOP));
61
+ // Evaluate cleanup
62
+ Verilated::endOfEval(vlSymsp->__Vm_evalMsgQp);
63
+ }
64
+
65
+ //============================================================
66
+ // Events and timing
67
+ bool Vsim::eventsPending() { return !vlSymsp->TOP.__VdlySched.empty() && !contextp()->gotFinish(); }
68
+
69
+ uint64_t Vsim::nextTimeSlot() { return vlSymsp->TOP.__VdlySched.nextTimeSlot(); }
70
+
71
+ //============================================================
72
+ // Utilities
73
+
74
+ const char* Vsim::name() const {
75
+ return vlSymsp->name();
76
+ }
77
+
78
+ //============================================================
79
+ // Invoke final blocks
80
+
81
+ void Vsim___024root___eval_final(Vsim___024root* vlSelf);
82
+
83
+ VL_ATTR_COLD void Vsim::final() {
84
+ contextp()->executingFinal(true);
85
+ Vsim___024root___eval_final(&(vlSymsp->TOP));
86
+ contextp()->executingFinal(false);
87
+ }
88
+
89
+ //============================================================
90
+ // Implementations of abstract methods from VerilatedModel
91
+
92
+ const char* Vsim::hierName() const { return vlSymsp->name(); }
93
+ const char* Vsim::modelName() const { return "Vsim"; }
94
+ unsigned Vsim::threads() const { return 1; }
95
+ void Vsim::prepareClone() const { contextp()->prepareClone(); }
96
+ void Vsim::atClone() const {
97
+ contextp()->threadPoolpOnClone();
98
+ }
99
+ std::unique_ptr<VerilatedTraceConfig> Vsim::traceConfig() const {
100
+ return std::unique_ptr<VerilatedTraceConfig>{new VerilatedTraceConfig{false, false, false}};
101
+ };
102
+
103
+ //============================================================
104
+ // Trace configuration
105
+
106
+ void Vsim___024root__trace_decl_types(VerilatedVcd* tracep);
107
+
108
+ void Vsim___024root__trace_init_top(Vsim___024root* vlSelf, VerilatedVcd* tracep);
109
+
110
+ VL_ATTR_COLD static void trace_init(void* voidSelf, VerilatedVcd* tracep, uint32_t code) {
111
+ // Callback from tracep->open()
112
+ Vsim___024root* const __restrict vlSelf VL_ATTR_UNUSED = static_cast<Vsim___024root*>(voidSelf);
113
+ Vsim__Syms* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;
114
+ if (!vlSymsp->_vm_contextp__->calcUnusedSigs()) {
115
+ VL_FATAL_MT(__FILE__, __LINE__, __FILE__,
116
+ "Turning on wave traces requires Verilated::traceEverOn(true) call before time 0.");
117
+ }
118
+ vlSymsp->__Vm_baseCode = code;
119
+ tracep->pushPrefix(vlSymsp->name(), VerilatedTracePrefixType::SCOPE_MODULE);
120
+ Vsim___024root__trace_decl_types(tracep);
121
+ Vsim___024root__trace_init_top(vlSelf, tracep);
122
+ tracep->popPrefix();
123
+ }
124
+
125
+ VL_ATTR_COLD void Vsim___024root__trace_register(Vsim___024root* vlSelf, VerilatedVcd* tracep);
126
+
127
+ VL_ATTR_COLD void Vsim::traceBaseModel(VerilatedTraceBaseC* tfp, int levels, int options) {
128
+ (void)levels; (void)options;
129
+ VerilatedVcdC* const stfp = dynamic_cast<VerilatedVcdC*>(tfp);
130
+ if (VL_UNLIKELY(!stfp)) {
131
+ vl_fatal(__FILE__, __LINE__, __FILE__,"'Vsim::trace()' called on non-VerilatedVcdC object;"
132
+ " use --trace-fst with VerilatedFst object, and --trace-vcd with VerilatedVcd object");
133
+ }
134
+ stfp->spTrace()->addModel(this);
135
+ stfp->spTrace()->addInitCb(&trace_init, &(vlSymsp->TOP), name(), false, 6);
136
+ Vsim___024root__trace_register(&(vlSymsp->TOP), stfp->spTrace());
137
+ }
obj_dir/Vsim.h ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Verilated -*- C++ -*-
2
+ // DESCRIPTION: Verilator output: Primary model header
3
+ //
4
+ // This header should be included by all source files instantiating the design.
5
+ // The class here is then constructed to instantiate the design.
6
+ // See the Verilator manual for examples.
7
+
8
+ #ifndef VERILATED_VSIM_H_
9
+ #define VERILATED_VSIM_H_ // guard
10
+
11
+ #include "verilated.h"
12
+
13
+ class Vsim__Syms;
14
+ class Vsim___024root;
15
+ class VerilatedVcdC;
16
+
17
+ // This class is the main interface to the Verilated model
18
+ class alignas(VL_CACHE_LINE_BYTES) Vsim VL_NOT_FINAL : public VerilatedModel {
19
+ private:
20
+ // Symbol table holding complete model state (owned by this class)
21
+ Vsim__Syms* const vlSymsp;
22
+
23
+ public:
24
+
25
+ // CONSTEXPR CAPABILITIES
26
+ // Verilated with --trace?
27
+ static constexpr bool traceCapable = true;
28
+
29
+ // PORTS
30
+ // The application code writes and reads these signals to
31
+ // propagate new values into/out from the Verilated model.
32
+
33
+ // CELLS
34
+ // Public to allow access to /* verilator public */ items.
35
+ // Otherwise the application code can consider these internals.
36
+
37
+ // Root instance pointer to allow access to model internals,
38
+ // including inlined /* verilator public_flat_* */ items.
39
+ Vsim___024root* const rootp;
40
+
41
+ // CONSTRUCTORS
42
+ /// Construct the model; called by application code
43
+ /// If contextp is null, then the model will use the default global context
44
+ /// If name is "", then makes a wrapper with a
45
+ /// single model invisible with respect to DPI scope names.
46
+ explicit Vsim(VerilatedContext* contextp, const char* name = "TOP");
47
+ explicit Vsim(const char* name = "TOP");
48
+ /// Destroy the model; called (often implicitly) by application code
49
+ virtual ~Vsim();
50
+ private:
51
+ VL_UNCOPYABLE(Vsim); ///< Copying not allowed
52
+
53
+ public:
54
+ // API METHODS
55
+ /// Evaluate the model. Application must call when inputs change.
56
+ void eval() { eval_step(); }
57
+ /// Evaluate when calling multiple units/models per time step.
58
+ void eval_step();
59
+ /// Evaluate at end of a timestep for tracing, when using eval_step().
60
+ /// Application must call after all eval() and before time changes.
61
+ void eval_end_step() {}
62
+ /// Simulation complete, run final blocks. Application must call on completion.
63
+ void final();
64
+ /// Are there scheduled events to handle?
65
+ bool eventsPending();
66
+ /// Returns time at next time slot. Aborts if !eventsPending()
67
+ uint64_t nextTimeSlot();
68
+ /// Trace signals in the model; called by application code
69
+ void trace(VerilatedTraceBaseC* tfp, int levels, int options = 0) { contextp()->trace(tfp, levels, options); }
70
+ /// Retrieve name of this model instance (as passed to constructor).
71
+ const char* name() const;
72
+
73
+ // Abstract methods from VerilatedModel
74
+ const char* hierName() const override final;
75
+ const char* modelName() const override final;
76
+ unsigned threads() const override final;
77
+ /// Prepare for cloning the model at the process level (e.g. fork in Linux)
78
+ /// Release necessary resources. Called before cloning.
79
+ void prepareClone() const;
80
+ /// Re-init after cloning the model at the process level (e.g. fork in Linux)
81
+ /// Re-allocate necessary resources. Called after cloning.
82
+ void atClone() const;
83
+ std::unique_ptr<VerilatedTraceConfig> traceConfig() const override final;
84
+ private:
85
+ // Internal functions - trace registration
86
+ void traceBaseModel(VerilatedTraceBaseC* tfp, int levels, int options);
87
+ };
88
+
89
+ #endif // guard
obj_dir/Vsim.mk ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Verilated -*- Makefile -*-
2
+ # DESCRIPTION: Verilator output: Makefile for building Verilated archive or executable
3
+ #
4
+ # Execute this makefile from the object directory:
5
+ # make -f Vsim.mk
6
+
7
+ default: Vsim
8
+
9
+ ### Constants...
10
+ # Perl executable (from $PERL, defaults to 'perl' if not set)
11
+ PERL = perl
12
+ # Python3 executable (from $PYTHON3, defaults to 'python3' if not set)
13
+ PYTHON3 = python3
14
+ # Path to Verilator kit (from $VERILATOR_ROOT)
15
+ VERILATOR_ROOT = /opt/oss-cad-suite/share/verilator
16
+ # SystemC include directory with systemc.h (from $SYSTEMC_INCLUDE)
17
+ SYSTEMC_INCLUDE ?=
18
+ # SystemC library directory with libsystemc.a (from $SYSTEMC_LIBDIR)
19
+ SYSTEMC_LIBDIR ?=
20
+
21
+ ### Switches...
22
+ # C++ code coverage 0/1 (from --prof-c)
23
+ VM_PROFC = 0
24
+ # SystemC output mode? 0/1 (from --sc)
25
+ VM_SC = 0
26
+ # Legacy or SystemC output mode? 0/1 (from --sc)
27
+ VM_SP_OR_SC = $(VM_SC)
28
+ # Deprecated
29
+ VM_PCLI = 1
30
+ # Deprecated: SystemC architecture to find link library path (from $SYSTEMC_ARCH)
31
+ VM_SC_TARGET_ARCH = linux
32
+
33
+ ### Vars...
34
+ # Design prefix (from --prefix)
35
+ VM_PREFIX = Vsim
36
+ # Module prefix (from --prefix)
37
+ VM_MODPREFIX = Vsim
38
+ # User CFLAGS (from -CFLAGS on Verilator command line)
39
+ VM_USER_CFLAGS = \
40
+ -DVL_TIME_CONTEXT \
41
+
42
+ # User LDLIBS (from -LDFLAGS on Verilator command line)
43
+ VM_USER_LDLIBS = \
44
+
45
+ # User .cpp files (from .cpp's on Verilator command line)
46
+ VM_USER_CLASSES = \
47
+
48
+ # User .cpp directories (from .cpp's on Verilator command line)
49
+ VM_USER_DIR = \
50
+ .. \
51
+
52
+ ### Default rules...
53
+ # Include list of all generated classes
54
+ include Vsim_classes.mk
55
+ # Include global rules
56
+ include $(VERILATOR_ROOT)/include/verilated.mk
57
+
58
+ ### Executable rules... (from --exe)
59
+ VPATH += $(VM_USER_DIR)
60
+
61
+
62
+ ### Link rules... (from --exe)
63
+ Vsim: $(VK_USER_OBJS) $(VK_GLOBAL_OBJS) $(VM_PREFIX)__ALL.a
64
+ $(LINK) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) $(LIBS) $(SC_LIBS) -o $@
65
+
66
+ # Verilated -*- Makefile -*-
obj_dir/Vsim__ALL.a ADDED
Binary file (59.4 kB). View file
 
obj_dir/Vsim__ALL.cpp ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // DESCRIPTION: Generated by verilator_includer via makefile
2
+ #define VL_INCLUDE_OPT include
3
+ #include "Vsim.cpp"
4
+ #include "Vsim___024root__0.cpp"
5
+ #include "Vsim__main.cpp"
6
+ #include "Vsim__Trace__0.cpp"
7
+ #include "Vsim___024root__Slow.cpp"
8
+ #include "Vsim___024root__0__Slow.cpp"
9
+ #include "Vsim__Syms__Slow.cpp"
10
+ #include "Vsim__Trace__0__Slow.cpp"
11
+ #include "Vsim__TraceDecls__0__Slow.cpp"
obj_dir/Vsim__ALL.d ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Vsim__ALL.o: Vsim__ALL.cpp Vsim.cpp Vsim__pch.h \
2
+ /opt/oss-cad-suite/share/verilator/include/verilated.h \
3
+ /opt/oss-cad-suite/share/verilator/include/verilated_config.h \
4
+ /opt/oss-cad-suite/share/verilator/include/verilatedos.h \
5
+ /opt/oss-cad-suite/share/verilator/include/verilated_types.h \
6
+ /opt/oss-cad-suite/share/verilator/include/verilated_funcs.h \
7
+ Vsim__Syms.h Vsim.h Vsim___024root.h \
8
+ /opt/oss-cad-suite/share/verilator/include/verilated_timing.h \
9
+ /opt/oss-cad-suite/share/verilator/include/verilated.h \
10
+ /opt/oss-cad-suite/share/verilator/include/verilated_vcd_c.h \
11
+ /opt/oss-cad-suite/share/verilator/include/verilated_trace.h \
12
+ Vsim___024root__0.cpp Vsim__main.cpp Vsim__Trace__0.cpp \
13
+ Vsim___024root__Slow.cpp Vsim___024root__0__Slow.cpp \
14
+ Vsim__Syms__Slow.cpp Vsim__Trace__0__Slow.cpp \
15
+ Vsim__TraceDecls__0__Slow.cpp
obj_dir/Vsim__ALL.o ADDED
Binary file (54.2 kB). View file
 
obj_dir/Vsim__Syms.h ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Verilated -*- C++ -*-
2
+ // DESCRIPTION: Verilator output: Symbol table internal header
3
+ //
4
+ // Internal details; most calling programs do not need this header,
5
+ // unless using verilator public meta comments.
6
+
7
+ #ifndef VERILATED_VSIM__SYMS_H_
8
+ #define VERILATED_VSIM__SYMS_H_ // guard
9
+
10
+ #include "verilated.h"
11
+
12
+ // INCLUDE MODEL CLASS
13
+
14
+ #include "Vsim.h"
15
+
16
+ // INCLUDE MODULE CLASSES
17
+ #include "Vsim___024root.h"
18
+
19
+ // SYMS CLASS (contains all model state)
20
+ class alignas(VL_CACHE_LINE_BYTES) Vsim__Syms final : public VerilatedSyms {
21
+ public:
22
+ // INTERNAL STATE
23
+ Vsim* const __Vm_modelp;
24
+ bool __Vm_activity = false; ///< Used by trace routines to determine change occurred
25
+ uint32_t __Vm_baseCode = 0; ///< Used by trace routines when tracing multiple models
26
+ VlDeleter __Vm_deleter;
27
+ bool __Vm_didInit = false;
28
+
29
+ // MODULE INSTANCE STATE
30
+ Vsim___024root TOP;
31
+
32
+ // CONSTRUCTORS
33
+ Vsim__Syms(VerilatedContext* contextp, const char* namep, Vsim* modelp);
34
+ ~Vsim__Syms();
35
+
36
+ // METHODS
37
+ const char* name() const { return TOP.vlNamep; }
38
+ };
39
+
40
+ #endif // guard
obj_dir/Vsim__Syms__Slow.cpp ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Verilated -*- C++ -*-
2
+ // DESCRIPTION: Verilator output: Symbol table implementation internals
3
+
4
+ #include "Vsim__pch.h"
5
+
6
+ Vsim__Syms::Vsim__Syms(VerilatedContext* contextp, const char* namep, Vsim* modelp)
7
+ : VerilatedSyms{contextp}
8
+ // Setup internal state of the Syms class
9
+ , __Vm_modelp{modelp}
10
+ // Setup top module instance
11
+ , TOP{this, namep}
12
+ {
13
+ // Check resources
14
+ Verilated::stackCheck(256);
15
+ // Setup sub module instances
16
+ // Configure time unit / time precision
17
+ _vm_contextp__->timeunit(-9);
18
+ _vm_contextp__->timeprecision(-12);
19
+ // Setup each module's pointers to their submodules
20
+ // Setup each module's pointer back to symbol table (for public functions)
21
+ TOP.__Vconfigure(true);
22
+ // Setup scopes
23
+ }
24
+
25
+ Vsim__Syms::~Vsim__Syms() {
26
+ // Tear down scopes
27
+ // Tear down sub module instances
28
+ }
obj_dir/Vsim__TraceDecls__0__Slow.cpp ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Verilated -*- C++ -*-
2
+ // DESCRIPTION: Verilator output: Tracing declarations
3
+
4
+ #include "verilated_vcd_c.h"
5
+
6
+
7
+ void Vsim___024root__traceDeclTypesSub0(VerilatedVcd* tracep) {
8
+ }
9
+
10
+ void Vsim___024root__trace_decl_types(VerilatedVcd* tracep) {
11
+ Vsim___024root__traceDeclTypesSub0(tracep);
12
+ }
obj_dir/Vsim__Trace__0.cpp ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Verilated -*- C++ -*-
2
+ // DESCRIPTION: Verilator output: Tracing implementation internals
3
+
4
+ #include "verilated_vcd_c.h"
5
+ #include "Vsim__Syms.h"
6
+
7
+
8
+ void Vsim___024root__trace_chg_0_sub_0(Vsim___024root* vlSelf, VerilatedVcd::Buffer* bufp);
9
+
10
+ void Vsim___024root__trace_chg_0(void* voidSelf, VerilatedVcd::Buffer* bufp) {
11
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root__trace_chg_0\n"); );
12
+ // Body
13
+ Vsim___024root* const __restrict vlSelf VL_ATTR_UNUSED = static_cast<Vsim___024root*>(voidSelf);
14
+ Vsim__Syms* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;
15
+ if (VL_UNLIKELY(!vlSymsp->__Vm_activity)) return;
16
+ Vsim___024root__trace_chg_0_sub_0((&vlSymsp->TOP), bufp);
17
+ }
18
+
19
+ void Vsim___024root__trace_chg_0_sub_0(Vsim___024root* vlSelf, VerilatedVcd::Buffer* bufp) {
20
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root__trace_chg_0_sub_0\n"); );
21
+ Vsim__Syms* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;
22
+ auto& vlSelfRef = std::ref(*vlSelf).get();
23
+ // Body
24
+ uint32_t* const oldp VL_ATTR_UNUSED = bufp->oldp(vlSymsp->__Vm_baseCode + 0);
25
+ if (VL_UNLIKELY(((vlSelfRef.__Vm_traceActivity[1U]
26
+ | vlSelfRef.__Vm_traceActivity[2U])))) {
27
+ bufp->chgBit(oldp+0,(vlSelfRef.tb_full_adder__DOT__a));
28
+ bufp->chgBit(oldp+1,(vlSelfRef.tb_full_adder__DOT__b));
29
+ bufp->chgBit(oldp+2,(vlSelfRef.tb_full_adder__DOT__cin));
30
+ bufp->chgBit(oldp+3,(((IData)(vlSelfRef.tb_full_adder__DOT__cin)
31
+ ^ ((IData)(vlSelfRef.tb_full_adder__DOT__a)
32
+ ^ (IData)(vlSelfRef.tb_full_adder__DOT__b)))));
33
+ bufp->chgBit(oldp+4,((((IData)(vlSelfRef.tb_full_adder__DOT__a)
34
+ & (IData)(vlSelfRef.tb_full_adder__DOT__b))
35
+ | ((IData)(vlSelfRef.tb_full_adder__DOT__cin)
36
+ & ((IData)(vlSelfRef.tb_full_adder__DOT__a)
37
+ | (IData)(vlSelfRef.tb_full_adder__DOT__b))))));
38
+ bufp->chgBit(oldp+5,(((IData)(vlSelfRef.tb_full_adder__DOT__a)
39
+ ^ (IData)(vlSelfRef.tb_full_adder__DOT__b))));
40
+ }
41
+ }
42
+
43
+ void Vsim___024root__trace_cleanup(void* voidSelf, VerilatedVcd* /*unused*/) {
44
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root__trace_cleanup\n"); );
45
+ // Body
46
+ Vsim___024root* const __restrict vlSelf VL_ATTR_UNUSED = static_cast<Vsim___024root*>(voidSelf);
47
+ Vsim__Syms* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;
48
+ vlSymsp->__Vm_activity = false;
49
+ vlSymsp->TOP.__Vm_traceActivity[0U] = 0U;
50
+ vlSymsp->TOP.__Vm_traceActivity[1U] = 0U;
51
+ vlSymsp->TOP.__Vm_traceActivity[2U] = 0U;
52
+ }
obj_dir/Vsim__Trace__0__Slow.cpp ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Verilated -*- C++ -*-
2
+ // DESCRIPTION: Verilator output: Tracing implementation internals
3
+
4
+ #include "verilated_vcd_c.h"
5
+ #include "Vsim__Syms.h"
6
+
7
+
8
+ VL_ATTR_COLD void Vsim___024root__trace_init_sub__TOP__0(Vsim___024root* vlSelf, VerilatedVcd* tracep) {
9
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root__trace_init_sub__TOP__0\n"); );
10
+ Vsim__Syms* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;
11
+ auto& vlSelfRef = std::ref(*vlSelf).get();
12
+ // Body
13
+ const int c = vlSymsp->__Vm_baseCode;
14
+ VL_TRACE_PUSH_PREFIX(tracep, "tb_full_adder", VerilatedTracePrefixType::SCOPE_MODULE, 0, 0);
15
+ VL_TRACE_DECL_BIT(tracep,c+0,0,"a",-1, VerilatedTraceSigDirection::NONE, VerilatedTraceSigKind::VAR, VerilatedTraceSigType::LOGIC);
16
+ VL_TRACE_DECL_BIT(tracep,c+1,0,"b",-1, VerilatedTraceSigDirection::NONE, VerilatedTraceSigKind::VAR, VerilatedTraceSigType::LOGIC);
17
+ VL_TRACE_DECL_BIT(tracep,c+2,0,"cin",-1, VerilatedTraceSigDirection::NONE, VerilatedTraceSigKind::VAR, VerilatedTraceSigType::LOGIC);
18
+ VL_TRACE_DECL_BIT(tracep,c+3,0,"sum",-1, VerilatedTraceSigDirection::NONE, VerilatedTraceSigKind::WIRE, VerilatedTraceSigType::LOGIC);
19
+ VL_TRACE_DECL_BIT(tracep,c+4,0,"cout",-1, VerilatedTraceSigDirection::NONE, VerilatedTraceSigKind::WIRE, VerilatedTraceSigType::LOGIC);
20
+ VL_TRACE_PUSH_PREFIX(tracep, "uut", VerilatedTracePrefixType::SCOPE_MODULE, 0, 0);
21
+ VL_TRACE_DECL_BIT(tracep,c+0,0,"a",-1, VerilatedTraceSigDirection::INPUT, VerilatedTraceSigKind::WIRE, VerilatedTraceSigType::LOGIC);
22
+ VL_TRACE_DECL_BIT(tracep,c+1,0,"b",-1, VerilatedTraceSigDirection::INPUT, VerilatedTraceSigKind::WIRE, VerilatedTraceSigType::LOGIC);
23
+ VL_TRACE_DECL_BIT(tracep,c+2,0,"cin",-1, VerilatedTraceSigDirection::INPUT, VerilatedTraceSigKind::WIRE, VerilatedTraceSigType::LOGIC);
24
+ VL_TRACE_DECL_BIT(tracep,c+3,0,"sum",-1, VerilatedTraceSigDirection::OUTPUT, VerilatedTraceSigKind::WIRE, VerilatedTraceSigType::LOGIC);
25
+ VL_TRACE_DECL_BIT(tracep,c+4,0,"cout",-1, VerilatedTraceSigDirection::OUTPUT, VerilatedTraceSigKind::WIRE, VerilatedTraceSigType::LOGIC);
26
+ VL_TRACE_DECL_BIT(tracep,c+5,0,"x1",-1, VerilatedTraceSigDirection::NONE, VerilatedTraceSigKind::WIRE, VerilatedTraceSigType::LOGIC);
27
+ VL_TRACE_DECL_BIT(tracep,c+5,0,"x2",-1, VerilatedTraceSigDirection::NONE, VerilatedTraceSigKind::WIRE, VerilatedTraceSigType::LOGIC);
28
+ VL_TRACE_DECL_BIT(tracep,c+3,0,"x3",-1, VerilatedTraceSigDirection::NONE, VerilatedTraceSigKind::WIRE, VerilatedTraceSigType::LOGIC);
29
+ VL_TRACE_DECL_BIT(tracep,c+4,0,"x4",-1, VerilatedTraceSigDirection::NONE, VerilatedTraceSigKind::WIRE, VerilatedTraceSigType::LOGIC);
30
+ VL_TRACE_DECL_BIT(tracep,c+3,0,"temp",-1, VerilatedTraceSigDirection::NONE, VerilatedTraceSigKind::WIRE, VerilatedTraceSigType::LOGIC);
31
+ VL_TRACE_POP_PREFIX(tracep);
32
+ VL_TRACE_POP_PREFIX(tracep);
33
+ }
34
+
35
+ VL_ATTR_COLD void Vsim___024root__trace_init_top(Vsim___024root* vlSelf, VerilatedVcd* tracep) {
36
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root__trace_init_top\n"); );
37
+ Vsim__Syms* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;
38
+ auto& vlSelfRef = std::ref(*vlSelf).get();
39
+ // Body
40
+ Vsim___024root__trace_init_sub__TOP__0(vlSelf, tracep);
41
+ }
42
+
43
+ VL_ATTR_COLD void Vsim___024root__trace_const_0(void* voidSelf, VerilatedVcd::Buffer* bufp);
44
+ VL_ATTR_COLD void Vsim___024root__trace_full_0(void* voidSelf, VerilatedVcd::Buffer* bufp);
45
+ void Vsim___024root__trace_chg_0(void* voidSelf, VerilatedVcd::Buffer* bufp);
46
+ void Vsim___024root__trace_cleanup(void* voidSelf, VerilatedVcd* /*unused*/);
47
+
48
+ VL_ATTR_COLD void Vsim___024root__trace_register(Vsim___024root* vlSelf, VerilatedVcd* tracep) {
49
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root__trace_register\n"); );
50
+ Vsim__Syms* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;
51
+ auto& vlSelfRef = std::ref(*vlSelf).get();
52
+ // Body
53
+ tracep->addConstCb(&Vsim___024root__trace_const_0, 0, vlSelf);
54
+ tracep->addFullCb(&Vsim___024root__trace_full_0, 0, vlSelf);
55
+ tracep->addChgCb(&Vsim___024root__trace_chg_0, 0, vlSelf);
56
+ tracep->addCleanupCb(&Vsim___024root__trace_cleanup, vlSelf);
57
+ }
58
+
59
+ VL_ATTR_COLD void Vsim___024root__trace_const_0(void* voidSelf, VerilatedVcd::Buffer* bufp) {
60
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root__trace_const_0\n"); );
61
+ // Body
62
+ Vsim___024root* const __restrict vlSelf VL_ATTR_UNUSED = static_cast<Vsim___024root*>(voidSelf);
63
+ Vsim__Syms* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;
64
+ }
65
+
66
+ VL_ATTR_COLD void Vsim___024root__trace_full_0_sub_0(Vsim___024root* vlSelf, VerilatedVcd::Buffer* bufp);
67
+
68
+ VL_ATTR_COLD void Vsim___024root__trace_full_0(void* voidSelf, VerilatedVcd::Buffer* bufp) {
69
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root__trace_full_0\n"); );
70
+ // Body
71
+ Vsim___024root* const __restrict vlSelf VL_ATTR_UNUSED = static_cast<Vsim___024root*>(voidSelf);
72
+ Vsim__Syms* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;
73
+ Vsim___024root__trace_full_0_sub_0((&vlSymsp->TOP), bufp);
74
+ }
75
+
76
+ VL_ATTR_COLD void Vsim___024root__trace_full_0_sub_0(Vsim___024root* vlSelf, VerilatedVcd::Buffer* bufp) {
77
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root__trace_full_0_sub_0\n"); );
78
+ Vsim__Syms* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;
79
+ auto& vlSelfRef = std::ref(*vlSelf).get();
80
+ // Body
81
+ uint32_t* const oldp VL_ATTR_UNUSED = bufp->oldp(vlSymsp->__Vm_baseCode);
82
+ bufp->fullBit(oldp+0,(vlSelfRef.tb_full_adder__DOT__a));
83
+ bufp->fullBit(oldp+1,(vlSelfRef.tb_full_adder__DOT__b));
84
+ bufp->fullBit(oldp+2,(vlSelfRef.tb_full_adder__DOT__cin));
85
+ bufp->fullBit(oldp+3,(((IData)(vlSelfRef.tb_full_adder__DOT__cin)
86
+ ^ ((IData)(vlSelfRef.tb_full_adder__DOT__a)
87
+ ^ (IData)(vlSelfRef.tb_full_adder__DOT__b)))));
88
+ bufp->fullBit(oldp+4,((((IData)(vlSelfRef.tb_full_adder__DOT__a)
89
+ & (IData)(vlSelfRef.tb_full_adder__DOT__b))
90
+ | ((IData)(vlSelfRef.tb_full_adder__DOT__cin)
91
+ & ((IData)(vlSelfRef.tb_full_adder__DOT__a)
92
+ | (IData)(vlSelfRef.tb_full_adder__DOT__b))))));
93
+ bufp->fullBit(oldp+5,(((IData)(vlSelfRef.tb_full_adder__DOT__a)
94
+ ^ (IData)(vlSelfRef.tb_full_adder__DOT__b))));
95
+ }
obj_dir/Vsim___024root.h ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Verilated -*- C++ -*-
2
+ // DESCRIPTION: Verilator output: Design internal header
3
+ // See Vsim.h for the primary calling header
4
+
5
+ #ifndef VERILATED_VSIM___024ROOT_H_
6
+ #define VERILATED_VSIM___024ROOT_H_ // guard
7
+
8
+ #include "verilated.h"
9
+ #include "verilated_timing.h"
10
+
11
+
12
+ class Vsim__Syms;
13
+
14
+ class alignas(VL_CACHE_LINE_BYTES) Vsim___024root final {
15
+ public:
16
+
17
+ // DESIGN SPECIFIC STATE
18
+ CData/*0:0*/ tb_full_adder__DOT__a;
19
+ CData/*0:0*/ tb_full_adder__DOT__b;
20
+ CData/*0:0*/ tb_full_adder__DOT__cin;
21
+ CData/*0:0*/ tb_full_adder__DOT__uut__DOT__sum;
22
+ CData/*0:0*/ tb_full_adder__DOT__uut__DOT__cout;
23
+ CData/*0:0*/ __VstlFirstIteration;
24
+ CData/*0:0*/ __VstlPhaseResult;
25
+ CData/*0:0*/ __VactPhaseResult;
26
+ CData/*0:0*/ __VinactPhaseResult;
27
+ CData/*0:0*/ __VnbaPhaseResult;
28
+ IData/*31:0*/ __VactIterCount;
29
+ IData/*31:0*/ __VinactIterCount;
30
+ IData/*31:0*/ __Vi;
31
+ VlUnpacked<QData/*63:0*/, 1> __VstlTriggered;
32
+ VlUnpacked<QData/*63:0*/, 1> __VactTriggered;
33
+ VlUnpacked<QData/*63:0*/, 1> __VactTriggeredAcc;
34
+ VlUnpacked<QData/*63:0*/, 1> __VnbaTriggered;
35
+ VlUnpacked<CData/*0:0*/, 3> __Vm_traceActivity;
36
+ VlDelayScheduler __VdlySched;
37
+
38
+ // INTERNAL VARIABLES
39
+ Vsim__Syms* vlSymsp;
40
+ const char* vlNamep;
41
+
42
+ // CONSTRUCTORS
43
+ Vsim___024root(Vsim__Syms* symsp, const char* namep);
44
+ ~Vsim___024root();
45
+ VL_UNCOPYABLE(Vsim___024root);
46
+
47
+ // INTERNAL METHODS
48
+ void __Vconfigure(bool first);
49
+ };
50
+
51
+
52
+ #endif // guard
obj_dir/Vsim___024root__0.cpp ADDED
@@ -0,0 +1,323 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Verilated -*- C++ -*-
2
+ // DESCRIPTION: Verilator output: Design implementation internals
3
+ // See Vsim.h for the primary calling header
4
+
5
+ #include "Vsim__pch.h"
6
+
7
+ VlCoroutine Vsim___024root___eval_initial__TOP__Vtiming__0(Vsim___024root* vlSelf);
8
+
9
+ void Vsim___024root___eval_initial(Vsim___024root* vlSelf) {
10
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root___eval_initial\n"); );
11
+ Vsim__Syms* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;
12
+ auto& vlSelfRef = std::ref(*vlSelf).get();
13
+ // Body
14
+ Vsim___024root___eval_initial__TOP__Vtiming__0(vlSelf);
15
+ vlSelfRef.__Vm_traceActivity[1U] = 1U;
16
+ }
17
+
18
+ VlCoroutine Vsim___024root___eval_initial__TOP__Vtiming__0(Vsim___024root* vlSelf) {
19
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root___eval_initial__TOP__Vtiming__0\n"); );
20
+ Vsim__Syms* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;
21
+ auto& vlSelfRef = std::ref(*vlSelf).get();
22
+ // Body
23
+ VL_WRITEF_NX("a b cin | sum cout\n-------------------\n",0);
24
+ vlSelfRef.tb_full_adder__DOT__a = 0U;
25
+ vlSelfRef.tb_full_adder__DOT__b = 0U;
26
+ vlSelfRef.tb_full_adder__DOT__cin = 0U;
27
+ co_await vlSelfRef.__VdlySched.delay(0x0000000000002710ULL,
28
+ nullptr, "/workspace/.tmp_verilator/testbench.sv",
29
+ 26);
30
+ vlSelfRef.__Vm_traceActivity[2U] = 1U;
31
+ VL_WRITEF_NX("%b %b %b | %b %b\n",5, '#',1,vlSelfRef.tb_full_adder__DOT__a
32
+ , '#',1,(IData)(vlSelfRef.tb_full_adder__DOT__b)
33
+ , '#',1,vlSelfRef.tb_full_adder__DOT__cin
34
+ , '#',1,(IData)(vlSelfRef.tb_full_adder__DOT__uut__DOT__sum)
35
+ , '#',1,vlSelfRef.tb_full_adder__DOT__uut__DOT__cout);
36
+ vlSelfRef.tb_full_adder__DOT__a = 0U;
37
+ vlSelfRef.tb_full_adder__DOT__b = 0U;
38
+ vlSelfRef.tb_full_adder__DOT__cin = 1U;
39
+ co_await vlSelfRef.__VdlySched.delay(0x0000000000002710ULL,
40
+ nullptr, "/workspace/.tmp_verilator/testbench.sv",
41
+ 29);
42
+ vlSelfRef.__Vm_traceActivity[2U] = 1U;
43
+ VL_WRITEF_NX("%b %b %b | %b %b\n",5, '#',1,vlSelfRef.tb_full_adder__DOT__a
44
+ , '#',1,(IData)(vlSelfRef.tb_full_adder__DOT__b)
45
+ , '#',1,vlSelfRef.tb_full_adder__DOT__cin
46
+ , '#',1,(IData)(vlSelfRef.tb_full_adder__DOT__uut__DOT__sum)
47
+ , '#',1,vlSelfRef.tb_full_adder__DOT__uut__DOT__cout);
48
+ vlSelfRef.tb_full_adder__DOT__a = 0U;
49
+ vlSelfRef.tb_full_adder__DOT__b = 1U;
50
+ vlSelfRef.tb_full_adder__DOT__cin = 0U;
51
+ co_await vlSelfRef.__VdlySched.delay(0x0000000000002710ULL,
52
+ nullptr, "/workspace/.tmp_verilator/testbench.sv",
53
+ 32);
54
+ vlSelfRef.__Vm_traceActivity[2U] = 1U;
55
+ VL_WRITEF_NX("%b %b %b | %b %b\n",5, '#',1,vlSelfRef.tb_full_adder__DOT__a
56
+ , '#',1,(IData)(vlSelfRef.tb_full_adder__DOT__b)
57
+ , '#',1,vlSelfRef.tb_full_adder__DOT__cin
58
+ , '#',1,(IData)(vlSelfRef.tb_full_adder__DOT__uut__DOT__sum)
59
+ , '#',1,vlSelfRef.tb_full_adder__DOT__uut__DOT__cout);
60
+ vlSelfRef.tb_full_adder__DOT__a = 0U;
61
+ vlSelfRef.tb_full_adder__DOT__b = 1U;
62
+ vlSelfRef.tb_full_adder__DOT__cin = 1U;
63
+ co_await vlSelfRef.__VdlySched.delay(0x0000000000002710ULL,
64
+ nullptr, "/workspace/.tmp_verilator/testbench.sv",
65
+ 35);
66
+ vlSelfRef.__Vm_traceActivity[2U] = 1U;
67
+ VL_WRITEF_NX("%b %b %b | %b %b\n",5, '#',1,vlSelfRef.tb_full_adder__DOT__a
68
+ , '#',1,(IData)(vlSelfRef.tb_full_adder__DOT__b)
69
+ , '#',1,vlSelfRef.tb_full_adder__DOT__cin
70
+ , '#',1,(IData)(vlSelfRef.tb_full_adder__DOT__uut__DOT__sum)
71
+ , '#',1,vlSelfRef.tb_full_adder__DOT__uut__DOT__cout);
72
+ vlSelfRef.tb_full_adder__DOT__a = 1U;
73
+ vlSelfRef.tb_full_adder__DOT__b = 0U;
74
+ vlSelfRef.tb_full_adder__DOT__cin = 0U;
75
+ co_await vlSelfRef.__VdlySched.delay(0x0000000000002710ULL,
76
+ nullptr, "/workspace/.tmp_verilator/testbench.sv",
77
+ 38);
78
+ vlSelfRef.__Vm_traceActivity[2U] = 1U;
79
+ VL_WRITEF_NX("%b %b %b | %b %b\n",5, '#',1,vlSelfRef.tb_full_adder__DOT__a
80
+ , '#',1,(IData)(vlSelfRef.tb_full_adder__DOT__b)
81
+ , '#',1,vlSelfRef.tb_full_adder__DOT__cin
82
+ , '#',1,(IData)(vlSelfRef.tb_full_adder__DOT__uut__DOT__sum)
83
+ , '#',1,vlSelfRef.tb_full_adder__DOT__uut__DOT__cout);
84
+ vlSelfRef.tb_full_adder__DOT__a = 1U;
85
+ vlSelfRef.tb_full_adder__DOT__b = 0U;
86
+ vlSelfRef.tb_full_adder__DOT__cin = 1U;
87
+ co_await vlSelfRef.__VdlySched.delay(0x0000000000002710ULL,
88
+ nullptr, "/workspace/.tmp_verilator/testbench.sv",
89
+ 41);
90
+ vlSelfRef.__Vm_traceActivity[2U] = 1U;
91
+ VL_WRITEF_NX("%b %b %b | %b %b\n",5, '#',1,vlSelfRef.tb_full_adder__DOT__a
92
+ , '#',1,(IData)(vlSelfRef.tb_full_adder__DOT__b)
93
+ , '#',1,vlSelfRef.tb_full_adder__DOT__cin
94
+ , '#',1,(IData)(vlSelfRef.tb_full_adder__DOT__uut__DOT__sum)
95
+ , '#',1,vlSelfRef.tb_full_adder__DOT__uut__DOT__cout);
96
+ vlSelfRef.tb_full_adder__DOT__a = 1U;
97
+ vlSelfRef.tb_full_adder__DOT__b = 1U;
98
+ vlSelfRef.tb_full_adder__DOT__cin = 0U;
99
+ co_await vlSelfRef.__VdlySched.delay(0x0000000000002710ULL,
100
+ nullptr, "/workspace/.tmp_verilator/testbench.sv",
101
+ 44);
102
+ vlSelfRef.__Vm_traceActivity[2U] = 1U;
103
+ VL_WRITEF_NX("%b %b %b | %b %b\n",5, '#',1,vlSelfRef.tb_full_adder__DOT__a
104
+ , '#',1,(IData)(vlSelfRef.tb_full_adder__DOT__b)
105
+ , '#',1,vlSelfRef.tb_full_adder__DOT__cin
106
+ , '#',1,(IData)(vlSelfRef.tb_full_adder__DOT__uut__DOT__sum)
107
+ , '#',1,vlSelfRef.tb_full_adder__DOT__uut__DOT__cout);
108
+ vlSelfRef.tb_full_adder__DOT__a = 1U;
109
+ vlSelfRef.tb_full_adder__DOT__b = 1U;
110
+ vlSelfRef.tb_full_adder__DOT__cin = 1U;
111
+ co_await vlSelfRef.__VdlySched.delay(0x0000000000002710ULL,
112
+ nullptr, "/workspace/.tmp_verilator/testbench.sv",
113
+ 47);
114
+ vlSelfRef.__Vm_traceActivity[2U] = 1U;
115
+ VL_WRITEF_NX("%b %b %b | %b %b\n",5, '#',1,vlSelfRef.tb_full_adder__DOT__a
116
+ , '#',1,(IData)(vlSelfRef.tb_full_adder__DOT__b)
117
+ , '#',1,vlSelfRef.tb_full_adder__DOT__cin
118
+ , '#',1,(IData)(vlSelfRef.tb_full_adder__DOT__uut__DOT__sum)
119
+ , '#',1,vlSelfRef.tb_full_adder__DOT__uut__DOT__cout);
120
+ VL_FINISH_MT("/workspace/.tmp_verilator/testbench.sv", 50, "");
121
+ vlSelfRef.__Vm_traceActivity[2U] = 1U;
122
+ co_return;
123
+ }
124
+
125
+ void Vsim___024root___eval_triggers_vec__act(Vsim___024root* vlSelf) {
126
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root___eval_triggers_vec__act\n"); );
127
+ Vsim__Syms* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;
128
+ auto& vlSelfRef = std::ref(*vlSelf).get();
129
+ // Body
130
+ vlSelfRef.__VactTriggered[0U] = (QData)((IData)(vlSelfRef.__VdlySched.awaitingCurrentTime()));
131
+ }
132
+
133
+ bool Vsim___024root___trigger_anySet__act(const VlUnpacked<QData/*63:0*/, 1> &in) {
134
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root___trigger_anySet__act\n"); );
135
+ // Locals
136
+ IData/*31:0*/ n;
137
+ // Body
138
+ n = 0U;
139
+ do {
140
+ if (in[n]) {
141
+ return (1U);
142
+ }
143
+ n = ((IData)(1U) + n);
144
+ } while ((1U > n));
145
+ return (0U);
146
+ }
147
+
148
+ void Vsim___024root___act_sequent__TOP__0(Vsim___024root* vlSelf) {
149
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root___act_sequent__TOP__0\n"); );
150
+ Vsim__Syms* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;
151
+ auto& vlSelfRef = std::ref(*vlSelf).get();
152
+ // Body
153
+ vlSelfRef.tb_full_adder__DOT__uut__DOT__sum = ((IData)(vlSelfRef.tb_full_adder__DOT__cin)
154
+ ^
155
+ ((IData)(vlSelfRef.tb_full_adder__DOT__a)
156
+ ^ (IData)(vlSelfRef.tb_full_adder__DOT__b)));
157
+ vlSelfRef.tb_full_adder__DOT__uut__DOT__cout =
158
+ (((IData)(vlSelfRef.tb_full_adder__DOT__a)
159
+ & (IData)(vlSelfRef.tb_full_adder__DOT__b))
160
+ | ((IData)(vlSelfRef.tb_full_adder__DOT__cin)
161
+ & ((IData)(vlSelfRef.tb_full_adder__DOT__a)
162
+ | (IData)(vlSelfRef.tb_full_adder__DOT__b))));
163
+ }
164
+
165
+ void Vsim___024root___eval_act(Vsim___024root* vlSelf) {
166
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root___eval_act\n"); );
167
+ Vsim__Syms* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;
168
+ auto& vlSelfRef = std::ref(*vlSelf).get();
169
+ // Body
170
+ if ((1ULL & vlSelfRef.__VactTriggered[0U])) {
171
+ Vsim___024root___act_sequent__TOP__0(vlSelf);
172
+ }
173
+ }
174
+
175
+ void Vsim___024root___eval_nba(Vsim___024root* vlSelf) {
176
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root___eval_nba\n"); );
177
+ Vsim__Syms* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;
178
+ auto& vlSelfRef = std::ref(*vlSelf).get();
179
+ // Body
180
+ if ((1ULL & vlSelfRef.__VnbaTriggered[0U])) {
181
+ Vsim___024root___act_sequent__TOP__0(vlSelf);
182
+ }
183
+ }
184
+
185
+ void Vsim___024root___timing_resume(Vsim___024root* vlSelf) {
186
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root___timing_resume\n"); );
187
+ Vsim__Syms* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;
188
+ auto& vlSelfRef = std::ref(*vlSelf).get();
189
+ // Body
190
+ if ((1ULL & vlSelfRef.__VactTriggered[0U])) {
191
+ vlSelfRef.__VdlySched.resume();
192
+ }
193
+ }
194
+
195
+ void Vsim___024root___trigger_orInto__act_vec_vec(VlUnpacked<QData/*63:0*/, 1> &out, const VlUnpacked<QData/*63:0*/, 1> &in) {
196
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root___trigger_orInto__act_vec_vec\n"); );
197
+ // Locals
198
+ IData/*31:0*/ n;
199
+ // Body
200
+ n = 0U;
201
+ do {
202
+ out[n] = (out[n] | in[n]);
203
+ n = ((IData)(1U) + n);
204
+ } while ((0U >= n));
205
+ }
206
+
207
+ #ifdef VL_DEBUG
208
+ VL_ATTR_COLD void Vsim___024root___dump_triggers__act(const VlUnpacked<QData/*63:0*/, 1> &triggers, const std::string &tag);
209
+ #endif // VL_DEBUG
210
+
211
+ bool Vsim___024root___eval_phase__act(Vsim___024root* vlSelf) {
212
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root___eval_phase__act\n"); );
213
+ Vsim__Syms* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;
214
+ auto& vlSelfRef = std::ref(*vlSelf).get();
215
+ // Locals
216
+ CData/*0:0*/ __VactExecute;
217
+ // Body
218
+ Vsim___024root___eval_triggers_vec__act(vlSelf);
219
+ Vsim___024root___trigger_orInto__act_vec_vec(vlSelfRef.__VactTriggered, vlSelfRef.__VactTriggeredAcc);
220
+ #ifdef VL_DEBUG
221
+ if (VL_UNLIKELY(vlSymsp->_vm_contextp__->debug())) {
222
+ Vsim___024root___dump_triggers__act(vlSelfRef.__VactTriggered, "act"s);
223
+ }
224
+ #endif
225
+ Vsim___024root___trigger_orInto__act_vec_vec(vlSelfRef.__VnbaTriggered, vlSelfRef.__VactTriggered);
226
+ __VactExecute = Vsim___024root___trigger_anySet__act(vlSelfRef.__VactTriggered);
227
+ if (__VactExecute) {
228
+ vlSelfRef.__VactTriggeredAcc.fill(0ULL);
229
+ Vsim___024root___timing_resume(vlSelf);
230
+ Vsim___024root___eval_act(vlSelf);
231
+ }
232
+ return (__VactExecute);
233
+ }
234
+
235
+ bool Vsim___024root___eval_phase__inact(Vsim___024root* vlSelf) {
236
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root___eval_phase__inact\n"); );
237
+ Vsim__Syms* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;
238
+ auto& vlSelfRef = std::ref(*vlSelf).get();
239
+ // Locals
240
+ CData/*0:0*/ __VinactExecute;
241
+ // Body
242
+ __VinactExecute = vlSelfRef.__VdlySched.awaitingZeroDelay();
243
+ if (__VinactExecute) {
244
+ VL_FATAL_MT("/workspace/.tmp_verilator/testbench.sv", 3, "", "ZERODLY: Design Verilated with '--no-sched-zero-delay', but #0 delay executed at runtime");
245
+ }
246
+ return (__VinactExecute);
247
+ }
248
+
249
+ void Vsim___024root___trigger_clear__act(VlUnpacked<QData/*63:0*/, 1> &out) {
250
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root___trigger_clear__act\n"); );
251
+ // Locals
252
+ IData/*31:0*/ n;
253
+ // Body
254
+ n = 0U;
255
+ do {
256
+ out[n] = 0ULL;
257
+ n = ((IData)(1U) + n);
258
+ } while ((1U > n));
259
+ }
260
+
261
+ bool Vsim___024root___eval_phase__nba(Vsim___024root* vlSelf) {
262
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root___eval_phase__nba\n"); );
263
+ Vsim__Syms* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;
264
+ auto& vlSelfRef = std::ref(*vlSelf).get();
265
+ // Locals
266
+ CData/*0:0*/ __VnbaExecute;
267
+ // Body
268
+ __VnbaExecute = Vsim___024root___trigger_anySet__act(vlSelfRef.__VnbaTriggered);
269
+ if (__VnbaExecute) {
270
+ Vsim___024root___eval_nba(vlSelf);
271
+ Vsim___024root___trigger_clear__act(vlSelfRef.__VnbaTriggered);
272
+ }
273
+ return (__VnbaExecute);
274
+ }
275
+
276
+ void Vsim___024root___eval(Vsim___024root* vlSelf) {
277
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root___eval\n"); );
278
+ Vsim__Syms* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;
279
+ auto& vlSelfRef = std::ref(*vlSelf).get();
280
+ // Locals
281
+ IData/*31:0*/ __VnbaIterCount;
282
+ // Body
283
+ __VnbaIterCount = 0U;
284
+ do {
285
+ if (VL_UNLIKELY(((0x00002710U < __VnbaIterCount)))) {
286
+ #ifdef VL_DEBUG
287
+ Vsim___024root___dump_triggers__act(vlSelfRef.__VnbaTriggered, "nba"s);
288
+ #endif
289
+ VL_FATAL_MT("/workspace/.tmp_verilator/testbench.sv", 3, "", "DIDNOTCONVERGE: NBA region did not converge after '--converge-limit' of 10000 tries");
290
+ }
291
+ __VnbaIterCount = ((IData)(1U) + __VnbaIterCount);
292
+ vlSelfRef.__VinactIterCount = 0U;
293
+ do {
294
+ if (VL_UNLIKELY(((0x00002710U < vlSelfRef.__VinactIterCount)))) {
295
+ VL_FATAL_MT("/workspace/.tmp_verilator/testbench.sv", 3, "", "DIDNOTCONVERGE: Inactive region did not converge after '--converge-limit' of 10000 tries");
296
+ }
297
+ vlSelfRef.__VinactIterCount = ((IData)(1U)
298
+ + vlSelfRef.__VinactIterCount);
299
+ vlSelfRef.__VactIterCount = 0U;
300
+ do {
301
+ if (VL_UNLIKELY(((0x00002710U < vlSelfRef.__VactIterCount)))) {
302
+ #ifdef VL_DEBUG
303
+ Vsim___024root___dump_triggers__act(vlSelfRef.__VactTriggered, "act"s);
304
+ #endif
305
+ VL_FATAL_MT("/workspace/.tmp_verilator/testbench.sv", 3, "", "DIDNOTCONVERGE: Active region did not converge after '--converge-limit' of 10000 tries");
306
+ }
307
+ vlSelfRef.__VactIterCount = ((IData)(1U)
308
+ + vlSelfRef.__VactIterCount);
309
+ vlSelfRef.__VactPhaseResult = Vsim___024root___eval_phase__act(vlSelf);
310
+ } while (vlSelfRef.__VactPhaseResult);
311
+ vlSelfRef.__VinactPhaseResult = Vsim___024root___eval_phase__inact(vlSelf);
312
+ } while (vlSelfRef.__VinactPhaseResult);
313
+ vlSelfRef.__VnbaPhaseResult = Vsim___024root___eval_phase__nba(vlSelf);
314
+ } while (vlSelfRef.__VnbaPhaseResult);
315
+ }
316
+
317
+ #ifdef VL_DEBUG
318
+ void Vsim___024root___eval_debug_assertions(Vsim___024root* vlSelf) {
319
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root___eval_debug_assertions\n"); );
320
+ Vsim__Syms* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;
321
+ auto& vlSelfRef = std::ref(*vlSelf).get();
322
+ }
323
+ #endif // VL_DEBUG
obj_dir/Vsim___024root__0__Slow.cpp ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Verilated -*- C++ -*-
2
+ // DESCRIPTION: Verilator output: Design implementation internals
3
+ // See Vsim.h for the primary calling header
4
+
5
+ #include "Vsim__pch.h"
6
+
7
+ VL_ATTR_COLD void Vsim___024root___eval_static(Vsim___024root* vlSelf) {
8
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root___eval_static\n"); );
9
+ Vsim__Syms* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;
10
+ auto& vlSelfRef = std::ref(*vlSelf).get();
11
+ // Body
12
+ do {
13
+ vlSelfRef.__VactTriggeredAcc[vlSelfRef.__Vi]
14
+ = vlSelfRef.__VactTriggered[vlSelfRef.__Vi];
15
+ vlSelfRef.__Vi = ((IData)(1U) + vlSelfRef.__Vi);
16
+ } while ((0U >= vlSelfRef.__Vi));
17
+ }
18
+
19
+ VL_ATTR_COLD void Vsim___024root___eval_final(Vsim___024root* vlSelf) {
20
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root___eval_final\n"); );
21
+ Vsim__Syms* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;
22
+ auto& vlSelfRef = std::ref(*vlSelf).get();
23
+ }
24
+
25
+ #ifdef VL_DEBUG
26
+ VL_ATTR_COLD void Vsim___024root___dump_triggers__stl(const VlUnpacked<QData/*63:0*/, 1> &triggers, const std::string &tag);
27
+ #endif // VL_DEBUG
28
+ VL_ATTR_COLD bool Vsim___024root___eval_phase__stl(Vsim___024root* vlSelf);
29
+
30
+ VL_ATTR_COLD void Vsim___024root___eval_settle(Vsim___024root* vlSelf) {
31
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root___eval_settle\n"); );
32
+ Vsim__Syms* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;
33
+ auto& vlSelfRef = std::ref(*vlSelf).get();
34
+ // Locals
35
+ IData/*31:0*/ __VstlIterCount;
36
+ // Body
37
+ __VstlIterCount = 0U;
38
+ vlSelfRef.__VstlFirstIteration = 1U;
39
+ do {
40
+ if (VL_UNLIKELY(((0x00002710U < __VstlIterCount)))) {
41
+ #ifdef VL_DEBUG
42
+ Vsim___024root___dump_triggers__stl(vlSelfRef.__VstlTriggered, "stl"s);
43
+ #endif
44
+ VL_FATAL_MT("/workspace/.tmp_verilator/testbench.sv", 3, "", "DIDNOTCONVERGE: Settle region did not converge after '--converge-limit' of 10000 tries");
45
+ }
46
+ __VstlIterCount = ((IData)(1U) + __VstlIterCount);
47
+ vlSelfRef.__VstlPhaseResult = Vsim___024root___eval_phase__stl(vlSelf);
48
+ vlSelfRef.__VstlFirstIteration = 0U;
49
+ } while (vlSelfRef.__VstlPhaseResult);
50
+ }
51
+
52
+ VL_ATTR_COLD void Vsim___024root___eval_triggers_vec__stl(Vsim___024root* vlSelf) {
53
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root___eval_triggers_vec__stl\n"); );
54
+ Vsim__Syms* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;
55
+ auto& vlSelfRef = std::ref(*vlSelf).get();
56
+ // Body
57
+ vlSelfRef.__VstlTriggered[0U] = ((0xfffffffffffffffeULL
58
+ & vlSelfRef.__VstlTriggered[0U])
59
+ | (IData)((IData)(vlSelfRef.__VstlFirstIteration)));
60
+ }
61
+
62
+ VL_ATTR_COLD bool Vsim___024root___trigger_anySet__stl(const VlUnpacked<QData/*63:0*/, 1> &in);
63
+
64
+ #ifdef VL_DEBUG
65
+ VL_ATTR_COLD void Vsim___024root___dump_triggers__stl(const VlUnpacked<QData/*63:0*/, 1> &triggers, const std::string &tag) {
66
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root___dump_triggers__stl\n"); );
67
+ // Body
68
+ if ((1U & (~ (IData)(Vsim___024root___trigger_anySet__stl(triggers))))) {
69
+ VL_DBG_MSGS(" No '" + tag + "' region triggers active\n");
70
+ }
71
+ if ((1U & (IData)(triggers[0U]))) {
72
+ VL_DBG_MSGS(" '" + tag + "' region trigger index 0 is active: Internal 'stl' trigger - first iteration\n");
73
+ }
74
+ }
75
+ #endif // VL_DEBUG
76
+
77
+ VL_ATTR_COLD bool Vsim___024root___trigger_anySet__stl(const VlUnpacked<QData/*63:0*/, 1> &in) {
78
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root___trigger_anySet__stl\n"); );
79
+ // Locals
80
+ IData/*31:0*/ n;
81
+ // Body
82
+ n = 0U;
83
+ do {
84
+ if (in[n]) {
85
+ return (1U);
86
+ }
87
+ n = ((IData)(1U) + n);
88
+ } while ((1U > n));
89
+ return (0U);
90
+ }
91
+
92
+ void Vsim___024root___act_sequent__TOP__0(Vsim___024root* vlSelf);
93
+
94
+ VL_ATTR_COLD void Vsim___024root___eval_stl(Vsim___024root* vlSelf) {
95
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root___eval_stl\n"); );
96
+ Vsim__Syms* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;
97
+ auto& vlSelfRef = std::ref(*vlSelf).get();
98
+ // Body
99
+ if ((1ULL & vlSelfRef.__VstlTriggered[0U])) {
100
+ Vsim___024root___act_sequent__TOP__0(vlSelf);
101
+ }
102
+ }
103
+
104
+ VL_ATTR_COLD bool Vsim___024root___eval_phase__stl(Vsim___024root* vlSelf) {
105
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root___eval_phase__stl\n"); );
106
+ Vsim__Syms* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;
107
+ auto& vlSelfRef = std::ref(*vlSelf).get();
108
+ // Locals
109
+ CData/*0:0*/ __VstlExecute;
110
+ // Body
111
+ Vsim___024root___eval_triggers_vec__stl(vlSelf);
112
+ #ifdef VL_DEBUG
113
+ if (VL_UNLIKELY(vlSymsp->_vm_contextp__->debug())) {
114
+ Vsim___024root___dump_triggers__stl(vlSelfRef.__VstlTriggered, "stl"s);
115
+ }
116
+ #endif
117
+ __VstlExecute = Vsim___024root___trigger_anySet__stl(vlSelfRef.__VstlTriggered);
118
+ if (__VstlExecute) {
119
+ Vsim___024root___eval_stl(vlSelf);
120
+ }
121
+ return (__VstlExecute);
122
+ }
123
+
124
+ bool Vsim___024root___trigger_anySet__act(const VlUnpacked<QData/*63:0*/, 1> &in);
125
+
126
+ #ifdef VL_DEBUG
127
+ VL_ATTR_COLD void Vsim___024root___dump_triggers__act(const VlUnpacked<QData/*63:0*/, 1> &triggers, const std::string &tag) {
128
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root___dump_triggers__act\n"); );
129
+ // Body
130
+ if ((1U & (~ (IData)(Vsim___024root___trigger_anySet__act(triggers))))) {
131
+ VL_DBG_MSGS(" No '" + tag + "' region triggers active\n");
132
+ }
133
+ if ((1U & (IData)(triggers[0U]))) {
134
+ VL_DBG_MSGS(" '" + tag + "' region trigger index 0 is active: @([true] __VdlySched.awaitingCurrentTime())\n");
135
+ }
136
+ }
137
+ #endif // VL_DEBUG
138
+
139
+ VL_ATTR_COLD void Vsim___024root___ctor_var_reset(Vsim___024root* vlSelf) {
140
+ VL_DEBUG_IF(VL_DBG_MSGF("+ Vsim___024root___ctor_var_reset\n"); );
141
+ Vsim__Syms* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;
142
+ auto& vlSelfRef = std::ref(*vlSelf).get();
143
+ // Body
144
+ const uint64_t __VscopeHash = VL_MURMUR64_HASH(vlSelf->vlNamep);
145
+ vlSelf->tb_full_adder__DOT__a = VL_SCOPED_RAND_RESET_I(1, __VscopeHash, 13747735994981389321ull);
146
+ vlSelf->tb_full_adder__DOT__b = VL_SCOPED_RAND_RESET_I(1, __VscopeHash, 686105649783556071ull);
147
+ vlSelf->tb_full_adder__DOT__cin = VL_SCOPED_RAND_RESET_I(1, __VscopeHash, 4012772730186193120ull);
148
+ vlSelf->tb_full_adder__DOT__uut__DOT__sum = VL_SCOPED_RAND_RESET_I(1, __VscopeHash, 13287595272639865983ull);
149
+ vlSelf->tb_full_adder__DOT__uut__DOT__cout = VL_SCOPED_RAND_RESET_I(1, __VscopeHash, 13664396158812022014ull);
150
+ for (int __Vi0 = 0; __Vi0 < 1; ++__Vi0) {
151
+ vlSelf->__VstlTriggered[__Vi0] = 0;
152
+ }
153
+ for (int __Vi0 = 0; __Vi0 < 1; ++__Vi0) {
154
+ vlSelf->__VactTriggered[__Vi0] = 0;
155
+ }
156
+ for (int __Vi0 = 0; __Vi0 < 1; ++__Vi0) {
157
+ vlSelf->__VactTriggeredAcc[__Vi0] = 0;
158
+ }
159
+ for (int __Vi0 = 0; __Vi0 < 1; ++__Vi0) {
160
+ vlSelf->__VnbaTriggered[__Vi0] = 0;
161
+ }
162
+ vlSelf->__Vi = 0;
163
+ for (int __Vi0 = 0; __Vi0 < 3; ++__Vi0) {
164
+ vlSelf->__Vm_traceActivity[__Vi0] = 0;
165
+ }
166
+ }
obj_dir/Vsim___024root__Slow.cpp ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Verilated -*- C++ -*-
2
+ // DESCRIPTION: Verilator output: Design implementation internals
3
+ // See Vsim.h for the primary calling header
4
+
5
+ #include "Vsim__pch.h"
6
+
7
+ void Vsim___024root___ctor_var_reset(Vsim___024root* vlSelf);
8
+
9
+ Vsim___024root::Vsim___024root(Vsim__Syms* symsp, const char* namep)
10
+ : __VdlySched{*symsp->_vm_contextp__}
11
+ {
12
+ vlSymsp = symsp;
13
+ vlNamep = strdup(namep);
14
+ // Reset structure values
15
+ Vsim___024root___ctor_var_reset(this);
16
+ }
17
+
18
+ void Vsim___024root::__Vconfigure(bool first) {
19
+ (void)first; // Prevent unused variable warning
20
+ }
21
+
22
+ Vsim___024root::~Vsim___024root() {
23
+ VL_DO_DANGLING(std::free(const_cast<char*>(vlNamep)), vlNamep);
24
+ }
obj_dir/Vsim__main.cpp ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Verilated -*- C++ -*-
2
+ // DESCRIPTION: Verilator output: main() simulation loop, created with --main
3
+
4
+ #include "verilated.h"
5
+ #include "Vsim.h"
6
+
7
+ //======================
8
+
9
+ int main(int argc, char** argv, char**) {
10
+ // Setup context, defaults, and parse command line
11
+ Verilated::debug(0);
12
+ const std::unique_ptr<VerilatedContext> contextp{new VerilatedContext};
13
+ contextp->traceEverOn(true);
14
+ contextp->threads(1);
15
+ contextp->commandArgs(argc, argv);
16
+
17
+ // Construct the Verilated model, from Vtop.h generated from Verilating
18
+ const std::unique_ptr<Vsim> topp{new Vsim{contextp.get(), ""}};
19
+
20
+ // Simulate until $finish
21
+ while (VL_LIKELY(!contextp->gotFinish())) {
22
+ // Evaluate model
23
+ topp->eval();
24
+ // Advance time
25
+ if (!topp->eventsPending()) break;
26
+ contextp->time(topp->nextTimeSlot());
27
+ }
28
+
29
+ if (VL_LIKELY(!contextp->gotFinish())) {
30
+ VL_DEBUG_IF(VL_PRINTF("+ Exiting without $finish; no events left\n"););
31
+ }
32
+
33
+ // Execute 'final' processes
34
+ topp->final();
35
+
36
+ // Print statistical summary report
37
+ contextp->statsPrintSummary();
38
+
39
+ return 0;
40
+ }
obj_dir/Vsim__pch.h ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Verilated -*- C++ -*-
2
+ // DESCRIPTION: Verilator output: Precompiled header
3
+ //
4
+ // Internal details; most user sources do not need this header,
5
+ // unless using verilator public meta comments.
6
+ // Suggest use Vsim.h instead.
7
+
8
+ #ifndef VERILATED_VSIM__PCH_H_
9
+ #define VERILATED_VSIM__PCH_H_ // guard
10
+
11
+ // GCC and Clang only will precompile headers (PCH) for the first header.
12
+ // So, make sure this is the one and only PCH.
13
+ // If multiple module's includes are needed, use individual includes.
14
+ #ifdef VL_PCH_INCLUDED
15
+ # error "Including multiple precompiled header files"
16
+ #endif
17
+ #define VL_PCH_INCLUDED
18
+
19
+
20
+ #include "verilated.h"
21
+
22
+ #include "Vsim__Syms.h"
23
+ #include "Vsim.h"
24
+
25
+ // Additional include files added using '--compiler-include'
26
+
27
+ #endif // guard
obj_dir/Vsim__ver.d ADDED
@@ -0,0 +1 @@
 
 
1
+ obj_dir/Vsim.cpp obj_dir/Vsim.h obj_dir/Vsim.mk obj_dir/Vsim__Syms.h obj_dir/Vsim__Syms__Slow.cpp obj_dir/Vsim__TraceDecls__0__Slow.cpp obj_dir/Vsim__Trace__0.cpp obj_dir/Vsim__Trace__0__Slow.cpp obj_dir/Vsim___024root.h obj_dir/Vsim___024root__0.cpp obj_dir/Vsim___024root__0__Slow.cpp obj_dir/Vsim___024root__Slow.cpp obj_dir/Vsim__main.cpp obj_dir/Vsim__pch.h obj_dir/Vsim__ver.d obj_dir/Vsim_classes.mk : /opt/oss-cad-suite/libexec/verilator_bin /opt/oss-cad-suite/libexec/verilator_bin /opt/oss-cad-suite/share/verilator/include/verilated_std.sv /opt/oss-cad-suite/share/verilator/include/verilated_std_waiver.vlt /workspace/.tmp_verilator/design.sv /workspace/.tmp_verilator/testbench.sv
obj_dir/Vsim__verFiles.dat ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # DESCRIPTION: Verilator output: Timestamp data for --skip-identical. Delete at will.
2
+ C "--prefix Vsim --binary --build-jobs 0 --build --trace-vcd --quiet-build -Wno-fatal --timescale 1ns/1ns /workspace/.tmp_verilator/design.sv /workspace/.tmp_verilator/testbench.sv"
3
+ S 15470064 408335 1775589273 781926010 1775535881 0 "unhashed" "/opt/oss-cad-suite/libexec/verilator_bin"
4
+ S 7905 417104 1775589275 228926010 1775535881 0 "vaoJo7Sb62R3p7xvCJKmh57f4Cpmx2GHt7zuj5gO" "/opt/oss-cad-suite/share/verilator/include/verilated_std.sv"
5
+ S 3224 417105 1775589275 228926010 1775535881 0 "Hydzkv9X77JH03JyZeFi7tBFnQaHV7yknXQxBZFr" "/opt/oss-cad-suite/share/verilator/include/verilated_std_waiver.vlt"
6
+ S 508 23 1775588927 379763036 1775588927 379763036 "RzP0e7y9BjAWuxPxEHd8sMbLhVMBBykyireN9BO5" "/workspace/.tmp_verilator/design.sv"
7
+ S 994 22 1775588850 546387233 1775588850 546387233 "MJHSal6XoThtIDgaccnyRos1QWroJuR0B5ti7XBh" "/workspace/.tmp_verilator/testbench.sv"
8
+ T 5052 28 1775589279 970070246 1775589279 970070246 "unhashed" "obj_dir/Vsim.cpp"
9
+ T 3496 27 1775589279 969891205 1775589279 969891205 "unhashed" "obj_dir/Vsim.h"
10
+ T 1850 39 1775589279 972469243 1775589279 972469243 "unhashed" "obj_dir/Vsim.mk"
11
+ T 1100 26 1775589279 969740413 1775589279 969740413 "unhashed" "obj_dir/Vsim__Syms.h"
12
+ T 851 25 1775589279 969551330 1775589279 969551330 "unhashed" "obj_dir/Vsim__Syms__Slow.cpp"
13
+ T 291 34 1775589279 971867244 1775589279 971867244 "unhashed" "obj_dir/Vsim__TraceDecls__0__Slow.cpp"
14
+ T 2687 36 1775589279 972046036 1775589279 972046036 "unhashed" "obj_dir/Vsim__Trace__0.cpp"
15
+ T 6323 35 1775589279 971777952 1775589279 971777952 "unhashed" "obj_dir/Vsim__Trace__0__Slow.cpp"
16
+ T 1476 30 1775589279 970559246 1775589279 970559246 "unhashed" "obj_dir/Vsim___024root.h"
17
+ T 15367 33 1775589279 971426953 1775589279 971426953 "unhashed" "obj_dir/Vsim___024root__0.cpp"
18
+ T 6982 32 1775589279 971074662 1775589279 971074662 "unhashed" "obj_dir/Vsim___024root__0__Slow.cpp"
19
+ T 674 31 1775589279 970776829 1775589279 970776829 "unhashed" "obj_dir/Vsim___024root__Slow.cpp"
20
+ T 1137 37 1775589279 972180619 1775589279 972180619 "unhashed" "obj_dir/Vsim__main.cpp"
21
+ T 745 29 1775589279 970367704 1775589279 970367704 "unhashed" "obj_dir/Vsim__pch.h"
22
+ T 696 40 1775589279 972557452 1775589279 972557452 "unhashed" "obj_dir/Vsim__ver.d"
23
+ T 0 0 1775589279 972619952 1775589279 972619952 "unhashed" "obj_dir/Vsim__verFiles.dat"
24
+ T 1745 38 1775589279 972333494 1775589279 972333494 "unhashed" "obj_dir/Vsim_classes.mk"
obj_dir/Vsim_classes.mk ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Verilated -*- Makefile -*-
2
+ # DESCRIPTION: Verilator output: Make include file with class lists
3
+ #
4
+ # This file lists generated Verilated files, for including in higher level makefiles.
5
+ # See Vsim.mk for the caller.
6
+
7
+ ### Switches...
8
+ # C11 constructs required? 0/1 (always on now)
9
+ VM_C11 = 1
10
+ # Timing enabled? 0/1
11
+ VM_TIMING = 1
12
+ # Coverage output mode? 0/1 (from --coverage)
13
+ VM_COVERAGE = 0
14
+ # Parallel builds? 0/1 (from --output-split)
15
+ VM_PARALLEL_BUILDS = 0
16
+ # Tracing output mode? 0/1 (from --trace-fst/--trace-saif/--trace-vcd)
17
+ VM_TRACE = 1
18
+ # Tracing output mode in FST format? 0/1 (from --trace-fst)
19
+ VM_TRACE_FST = 0
20
+ # Tracing output mode in SAIF format? 0/1 (from --trace-saif)
21
+ VM_TRACE_SAIF = 0
22
+ # Tracing output mode in VCD format? 0/1 (from --trace-vcd)
23
+ VM_TRACE_VCD = 1
24
+
25
+ ### Object file lists...
26
+ # Generated module classes, fast-path, compile with highest optimization
27
+ VM_CLASSES_FAST += \
28
+ Vsim \
29
+ Vsim___024root__0 \
30
+ Vsim__main \
31
+
32
+ # Generated module classes, non-fast-path, compile with low/medium optimization
33
+ VM_CLASSES_SLOW += \
34
+ Vsim___024root__Slow \
35
+ Vsim___024root__0__Slow \
36
+
37
+ # Generated support classes, fast-path, compile with highest optimization
38
+ VM_SUPPORT_FAST += \
39
+ Vsim__Trace__0 \
40
+
41
+ # Generated support classes, non-fast-path, compile with low/medium optimization
42
+ VM_SUPPORT_SLOW += \
43
+ Vsim__Syms__Slow \
44
+ Vsim__Trace__0__Slow \
45
+ Vsim__TraceDecls__0__Slow \
46
+
47
+ # Global classes, need linked once per executable, fast-path, compile with highest optimization
48
+ VM_GLOBAL_FAST += \
49
+ verilated \
50
+ verilated_vcd_c \
51
+ verilated_timing \
52
+ verilated_threads \
53
+
54
+ # Global classes, need linked once per executable, non-fast-path, compile with low/medium optimization
55
+ VM_GLOBAL_SLOW += \
56
+
57
+ # Verilated -*- Makefile -*-
obj_dir/verilated.d ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ verilated.o: /opt/oss-cad-suite/share/verilator/include/verilated.cpp \
2
+ /opt/oss-cad-suite/share/verilator/include/verilated_config.h \
3
+ /opt/oss-cad-suite/share/verilator/include/verilatedos.h \
4
+ /opt/oss-cad-suite/share/verilator/include/verilated.h \
5
+ /opt/oss-cad-suite/share/verilator/include/verilated_types.h \
6
+ /opt/oss-cad-suite/share/verilator/include/verilated_funcs.h \
7
+ /opt/oss-cad-suite/share/verilator/include/verilated_imp.h \
8
+ /opt/oss-cad-suite/share/verilator/include/verilated_syms.h \
9
+ /opt/oss-cad-suite/share/verilator/include/verilated_sym_props.h \
10
+ /opt/oss-cad-suite/share/verilator/include/verilated_threads.h \
11
+ /opt/oss-cad-suite/share/verilator/include/verilated_trace.h \
12
+ /opt/oss-cad-suite/share/verilator/include/verilatedos_c.h
obj_dir/verilated.o ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c15e0086becf59dedb31cd5b4e20cfab3c618ecba86e0aeda2d5e8c2bf9c6177
3
+ size 254520
obj_dir/verilated_threads.d ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ verilated_threads.o: \
2
+ /opt/oss-cad-suite/share/verilator/include/verilated_threads.cpp \
3
+ /opt/oss-cad-suite/share/verilator/include/verilatedos.h \
4
+ /opt/oss-cad-suite/share/verilator/include/verilated_threads.h \
5
+ /opt/oss-cad-suite/share/verilator/include/verilated.h \
6
+ /opt/oss-cad-suite/share/verilator/include/verilated_config.h \
7
+ /opt/oss-cad-suite/share/verilator/include/verilated_types.h \
8
+ /opt/oss-cad-suite/share/verilator/include/verilated_funcs.h
obj_dir/verilated_threads.o ADDED
Binary file (64 kB). View file
 
obj_dir/verilated_timing.d ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ verilated_timing.o: \
2
+ /opt/oss-cad-suite/share/verilator/include/verilated_timing.cpp \
3
+ /opt/oss-cad-suite/share/verilator/include/verilated_timing.h \
4
+ /opt/oss-cad-suite/share/verilator/include/verilated.h \
5
+ /opt/oss-cad-suite/share/verilator/include/verilated_config.h \
6
+ /opt/oss-cad-suite/share/verilator/include/verilatedos.h \
7
+ /opt/oss-cad-suite/share/verilator/include/verilated_types.h \
8
+ /opt/oss-cad-suite/share/verilator/include/verilated_funcs.h
obj_dir/verilated_timing.o ADDED
Binary file (16.2 kB). View file
 
obj_dir/verilated_vcd_c.d ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ verilated_vcd_c.o: \
2
+ /opt/oss-cad-suite/share/verilator/include/verilated_vcd_c.cpp \
3
+ /opt/oss-cad-suite/share/verilator/include/verilatedos.h \
4
+ /opt/oss-cad-suite/share/verilator/include/verilated.h \
5
+ /opt/oss-cad-suite/share/verilator/include/verilated_config.h \
6
+ /opt/oss-cad-suite/share/verilator/include/verilated_types.h \
7
+ /opt/oss-cad-suite/share/verilator/include/verilated_funcs.h \
8
+ /opt/oss-cad-suite/share/verilator/include/verilated_vcd_c.h \
9
+ /opt/oss-cad-suite/share/verilator/include/verilated_trace.h \
10
+ /opt/oss-cad-suite/share/verilator/include/verilated_trace_imp.h \
11
+ /opt/oss-cad-suite/share/verilator/include/verilated_intrinsics.h \
12
+ /opt/oss-cad-suite/share/verilator/include/verilated_threads.h
obj_dir/verilated_vcd_c.o ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2669196c2cea7409e4fab856394490d9fab4a106e07737af067725680845979f
3
+ size 132968
openenv.yaml ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ spec_version: 1
2
+ name: chipforge
3
+ type: space
4
+ runtime: fastapi
5
+ app: server.app:app
6
+ port: 8000
7
+
openenv_chipforge.egg-info/PKG-INFO ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Metadata-Version: 2.4
2
+ Name: openenv-chipforge
3
+ Version: 0.1.0
4
+ Summary: Chipforge environment for OpenEnv
5
+ Requires-Python: >=3.10
6
+ Requires-Dist: openenv-core[core]>=0.2.2
7
+ Requires-Dist: mistralai>=1.0.0
8
+ Requires-Dist: python-dotenv>=1.0.0
9
+ Requires-Dist: websocket-client>=1.9.0
10
+ Provides-Extra: dev
11
+ Requires-Dist: pytest>=8.0.0; extra == "dev"
12
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
openenv_chipforge.egg-info/SOURCES.txt ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ README.md
2
+ __init__.py
3
+ client.py
4
+ inference.py
5
+ models.py
6
+ pyproject.toml
7
+ ./__init__.py
8
+ ./client.py
9
+ ./inference.py
10
+ ./models.py
11
+ openenv_chipforge.egg-info/PKG-INFO
12
+ openenv_chipforge.egg-info/SOURCES.txt
13
+ openenv_chipforge.egg-info/dependency_links.txt
14
+ openenv_chipforge.egg-info/entry_points.txt
15
+ openenv_chipforge.egg-info/requires.txt
16
+ openenv_chipforge.egg-info/top_level.txt
17
+ server/__init__.py
18
+ server/app.py
19
+ server/chipforge_environment.py
openenv_chipforge.egg-info/dependency_links.txt ADDED
@@ -0,0 +1 @@
 
 
1
+
openenv_chipforge.egg-info/entry_points.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ [console_scripts]
2
+ server = chipforge.server.app:main
openenv_chipforge.egg-info/requires.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ openenv-core[core]>=0.2.2
2
+ mistralai>=1.0.0
3
+ python-dotenv>=1.0.0
4
+ websocket-client>=1.9.0
5
+
6
+ [dev]
7
+ pytest>=8.0.0
8
+ pytest-cov>=4.0.0
openenv_chipforge.egg-info/top_level.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ chipforge
pyproject.toml ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ # All rights reserved.
3
+ #
4
+ # This source code is licensed under the BSD-style license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ [build-system]
8
+ requires = ["setuptools>=45", "wheel"]
9
+ build-backend = "setuptools.build_meta"
10
+
11
+ [project]
12
+ name = "openenv-chipforge"
13
+ version = "0.1.0"
14
+ description = "Chipforge environment for OpenEnv"
15
+ requires-python = ">=3.10"
16
+ dependencies = [
17
+ # Core OpenEnv runtime (provides FastAPI server + HTTP client types)
18
+ # install from github
19
+ # "openenv-core[core] @ git+https://github.com/meta-pytorch/OpenEnv.git",
20
+ "openenv-core[core]>=0.2.2",
21
+ # Environment-specific dependencies
22
+ # (none needed — Verilator + Yosys are installed in the Docker image)
23
+ "mistralai>=1.0.0",
24
+ "python-dotenv>=1.0.0",
25
+ "websocket-client>=1.9.0",
26
+ ]
27
+
28
+ [project.optional-dependencies]
29
+ dev = [
30
+ "pytest>=8.0.0",
31
+ "pytest-cov>=4.0.0",
32
+ ]
33
+
34
+ [project.scripts]
35
+ # Server entry point - enables running via: uv run --project . server
36
+ # or: python -m chipforge.server.app
37
+ server = "chipforge.server.app:main"
38
+
39
+ [tool.setuptools]
40
+ include-package-data = true
41
+ packages = ["chipforge", "chipforge.server"]
42
+ package-dir = { "chipforge" = ".", "chipforge.server" = "server" }
server/__init__.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ # All rights reserved.
3
+ #
4
+ # This source code is licensed under the BSD-style license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ """Chipforge environment server components."""
8
+
9
+ from .chipforge_environment import ChipforgeEnvironment
10
+
11
+ __all__ = ["ChipforgeEnvironment"]
server/app.py ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ # All rights reserved.
3
+ #
4
+ # This source code is licensed under the BSD-style license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ """
8
+ FastAPI application for the Chipforge Environment.
9
+
10
+ This module creates an HTTP server that exposes the ChipforgeEnvironment
11
+ over HTTP and WebSocket endpoints, compatible with EnvClient.
12
+
13
+ Endpoints:
14
+ - POST /reset: Reset the environment
15
+ - POST /step: Execute an action
16
+ - GET /state: Get current environment state
17
+ - GET /schema: Get action/observation schemas
18
+ - WS /ws: WebSocket endpoint for persistent sessions
19
+
20
+ Usage:
21
+ # Development (with auto-reload):
22
+ uvicorn server.app:app --reload --host 0.0.0.0 --port 8000
23
+
24
+ # Production:
25
+ uvicorn server.app:app --host 0.0.0.0 --port 8000 --workers 4
26
+
27
+ # Or run directly:
28
+ python -m server.app
29
+ """
30
+
31
+ try:
32
+ from openenv.core.env_server.http_server import create_app
33
+ except Exception as e: # pragma: no cover
34
+ raise ImportError(
35
+ "openenv is required for the web interface. Install dependencies with '\n uv sync\n'"
36
+ ) from e
37
+
38
+ try:
39
+ from ..models import ChipforgeAction, ChipforgeObservation
40
+ from .chipforge_environment import ChipforgeEnvironment
41
+ except ImportError:
42
+ from models import ChipforgeAction, ChipforgeObservation
43
+ from server.chipforge_environment import ChipforgeEnvironment
44
+
45
+
46
+ # Create the app with web interface and README integration
47
+ app = create_app(
48
+ ChipforgeEnvironment,
49
+ ChipforgeAction,
50
+ ChipforgeObservation,
51
+ env_name="chipforge",
52
+ max_concurrent_envs=1, # increase this number to allow more concurrent WebSocket sessions
53
+ )
54
+
55
+
56
+ def main(host: str = "0.0.0.0", port: int = 8000):
57
+ """
58
+ Entry point for direct execution via uv run or python -m.
59
+
60
+ This function enables running the server without Docker:
61
+ uv run --project . server
62
+ uv run --project . server --port 8001
63
+ python -m chipforge.server.app
64
+
65
+ Args:
66
+ host: Host address to bind to (default: "0.0.0.0")
67
+ port: Port number to listen on (default: 8000)
68
+
69
+ For production deployments, consider using uvicorn directly with
70
+ multiple workers:
71
+ uvicorn chipforge.server.app:app --workers 4
72
+ """
73
+ import uvicorn
74
+
75
+ uvicorn.run(app, host=host, port=port)
76
+
77
+
78
+ if __name__ == "__main__":
79
+ import argparse
80
+
81
+ parser = argparse.ArgumentParser()
82
+ parser.add_argument("--port", type=int, default=8000)
83
+ args = parser.parse_args()
84
+ main(port=args.port)
server/chipforge_environment.py ADDED
@@ -0,0 +1,789 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ # All rights reserved.
3
+ #
4
+ # This source code is licensed under the BSD-style license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ """
8
+ ChipForge RTL Debugging Environment — RL-optimized.
9
+
10
+ Key RL design decisions:
11
+ 1. OBSERVATION is a self-contained Markov state:
12
+ - RTL code always included (agent never wastes steps viewing)
13
+ - All tool statuses always present
14
+ - Action result feedback at every step
15
+
16
+ 2. REWARD uses potential-based shaping (Andrew Ng's theorem):
17
+ - per_step_reward = new_potential - old_potential - step_cost
18
+ - Potential = quality score based on tool statuses (0.0 to 1.0)
19
+ - Gives dense learning signal without changing optimal policy
20
+ - Terminal bonus on submit
21
+
22
+ 3. STATUS is NOT reset on edit:
23
+ - Prevents reward hacking (edit → artificially drop potential → re-run → gain)
24
+ - Agent must re-run tools to confirm fix worked
25
+ - On submit, all stale tools are automatically re-run
26
+ """
27
+
28
+ import json
29
+ import os
30
+ import random
31
+ import shutil
32
+ import subprocess
33
+ import tempfile
34
+ from pathlib import Path
35
+ from typing import Any, Dict, List, Optional
36
+ from uuid import uuid4
37
+
38
+ from openenv.core.env_server.interfaces import Environment
39
+ from openenv.core.env_server.types import State
40
+
41
+ try:
42
+ from ..models import ChipforgeAction, ChipforgeObservation
43
+ except ImportError:
44
+ from models import ChipforgeAction, ChipforgeObservation
45
+
46
+
47
+ # ---------------------------------------------------------------------------
48
+ # Constants
49
+ # ---------------------------------------------------------------------------
50
+
51
+ MAX_STEPS = 20
52
+ LOG_TRUNCATE = 2000 # max chars in observation logs
53
+ TOOL_TIMEOUT = 30 # seconds
54
+ STEP_COST = 0.02 # per-step penalty to encourage efficiency
55
+
56
+ # Tool paths — absolute for OSS CAD Suite in Docker
57
+ VERILATOR = os.environ.get("VERILATOR_PATH", "/opt/oss-cad-suite/bin/verilator")
58
+ YOSYS = os.environ.get("YOSYS_PATH", "/opt/oss-cad-suite/bin/yosys")
59
+
60
+ VALID_ACTIONS = {
61
+ "view_testbench",
62
+ "view_synthesis_log",
63
+ "view_lint_log",
64
+ "view_simulation_log",
65
+ "run_simulation",
66
+ "run_synthesis",
67
+ "run_lint",
68
+ "edit_line",
69
+ "append_line",
70
+ "edit_testbench_line",
71
+ "append_testbench_line",
72
+ "submit",
73
+ }
74
+
75
+ TASKS_DIR = Path(__file__).parent / "tasks"
76
+
77
+
78
+ # ---------------------------------------------------------------------------
79
+ # Helpers
80
+ # ---------------------------------------------------------------------------
81
+
82
+
83
+ def _discover_tasks() -> List[Path]:
84
+ """Return sorted list of task directories under TASKS_DIR (recursive)."""
85
+ if not TASKS_DIR.is_dir():
86
+ return []
87
+ return sorted(
88
+ p.parent
89
+ for p in TASKS_DIR.rglob("task.json")
90
+ if p.is_file() and p.parent.is_dir()
91
+ )
92
+
93
+
94
+ def _run_tool(cmd: List[str], cwd: str, timeout: int = TOOL_TIMEOUT) -> Dict[str, Any]:
95
+ """Run a shell command and return stdout, stderr, returncode."""
96
+ try:
97
+ result = subprocess.run(
98
+ cmd,
99
+ cwd=cwd,
100
+ capture_output=True,
101
+ text=True,
102
+ timeout=timeout,
103
+ )
104
+ return {
105
+ "stdout": result.stdout,
106
+ "stderr": result.stderr,
107
+ "returncode": result.returncode,
108
+ }
109
+ except subprocess.TimeoutExpired:
110
+ return {
111
+ "stdout": "",
112
+ "stderr": f"Command timed out after {timeout}s",
113
+ "returncode": -1,
114
+ }
115
+ except FileNotFoundError as e:
116
+ return {
117
+ "stdout": "",
118
+ "stderr": f"Tool not found: {e}",
119
+ "returncode": -1,
120
+ }
121
+
122
+
123
+ def _extract_error_summary(stderr: str, stdout: str = "") -> str:
124
+ """Extract a one-line error summary from tool output."""
125
+ combined = stderr + "\n" + stdout
126
+ for line in combined.splitlines():
127
+ line = line.strip()
128
+ if not line:
129
+ continue
130
+ lower = line.lower()
131
+ if any(kw in lower for kw in ("error", "syntax", "warning", "latch", "fail")):
132
+ return line[:200]
133
+ for line in stderr.splitlines():
134
+ line = line.strip()
135
+ if line:
136
+ return line[:200]
137
+ return ""
138
+
139
+
140
+ # ---------------------------------------------------------------------------
141
+ # Environment
142
+ # ---------------------------------------------------------------------------
143
+
144
+
145
+ class ChipforgeEnvironment(Environment):
146
+ """
147
+ RTL Debugging Environment for RL training.
148
+
149
+ Quality potential (φ) breakdown:
150
+ +0.2 code compiles (no syntax errors)
151
+ +0.3 simulation output matches expected
152
+ +0.3 synthesis clean (no warnings/errors)
153
+ +0.2 lint clean
154
+
155
+ Per-step reward = φ(s') - φ(s) - step_cost
156
+ Terminal bonus on submit = +0.1 if all pass, -0.2 if premature
157
+ """
158
+
159
+ SUPPORTS_CONCURRENT_SESSIONS: bool = False
160
+
161
+ def __init__(self) -> None:
162
+ self._state = State(episode_id=str(uuid4()), step_count=0)
163
+ self._tasks = _discover_tasks()
164
+ self._rng = random.Random()
165
+
166
+ # Episode state
167
+ self._rtl_lines: List[str] = []
168
+ self._testbench_code: str = ""
169
+ self._task_meta: Dict[str, Any] = {}
170
+ self._golden_code: str = ""
171
+ self._expected_output: str = ""
172
+
173
+ # Tool statuses & logs
174
+ self._sim_status: str = "not_run"
175
+ self._synth_status: str = "not_run"
176
+ self._lint_status: str = "not_run"
177
+ self._sim_log: str = ""
178
+ self._synth_log: str = ""
179
+ self._lint_log: str = ""
180
+ self._error_summary: str = ""
181
+
182
+ # Track if code has been edited since last tool run
183
+ self._code_dirty: bool = False
184
+ self._code_hash: str = ""
185
+ self._sim_validated_hash: str = ""
186
+ self._synth_validated_hash: str = ""
187
+ self._lint_validated_hash: str = ""
188
+
189
+ # Working directory
190
+ self._workdir: Optional[str] = None
191
+
192
+ # Episode signals
193
+ self._done: bool = False
194
+ self._potential: float = 0.0 # current quality potential
195
+ self._cumulative_reward: float = 0.0 # sum of per-step rewards
196
+
197
+ # -----------------------------------------------------------------------
198
+ # Potential-based reward
199
+ # -----------------------------------------------------------------------
200
+
201
+ def _compute_potential(self) -> float:
202
+ """
203
+ Quality potential φ(s) based on current tool statuses.
204
+ Range: [0.0, 1.0]. Only counts tools that have been run.
205
+ """
206
+ phi = 0.0
207
+
208
+ sim_fresh = self._sim_validated_hash == self._code_hash
209
+ synth_fresh = self._synth_validated_hash == self._code_hash
210
+ lint_fresh = self._lint_validated_hash == self._code_hash
211
+
212
+ # +0.2 if code compiles (sim ran and didn't error) on current code
213
+ if sim_fresh and self._sim_status in ("pass", "fail"):
214
+ phi += 0.2
215
+
216
+ # +0.3 if simulation passes on current code
217
+ if sim_fresh and self._sim_status == "pass":
218
+ phi += 0.3
219
+
220
+ # +0.3 if synthesis is clean on current code
221
+ if synth_fresh and self._synth_status == "pass":
222
+ phi += 0.3
223
+
224
+ # +0.2 if lint is clean on current code
225
+ if lint_fresh and self._lint_status == "clean":
226
+ phi += 0.2
227
+
228
+ return phi
229
+
230
+ def _current_code_hash(self) -> str:
231
+ return str(hash("\n".join(self._rtl_lines)))
232
+
233
+ # -----------------------------------------------------------------------
234
+ # OpenEnv Interface
235
+ # -----------------------------------------------------------------------
236
+
237
+ def reset(
238
+ self,
239
+ seed: Optional[int] = None,
240
+ episode_id: Optional[str] = None,
241
+ **kwargs: Any,
242
+ ) -> ChipforgeObservation:
243
+ """Load a task and return initial observation with RTL code."""
244
+
245
+ # Clean up
246
+ if self._workdir and os.path.isdir(self._workdir):
247
+ shutil.rmtree(self._workdir, ignore_errors=True)
248
+
249
+ if seed is not None:
250
+ self._rng.seed(seed)
251
+
252
+ if not self._tasks:
253
+ raise RuntimeError(f"No tasks found in {TASKS_DIR}")
254
+
255
+ # Pick task
256
+ task_name = kwargs.get("task_name")
257
+ if task_name:
258
+ task_dir = TASKS_DIR / task_name
259
+ if not task_dir.is_dir():
260
+ raise ValueError(f"Task not found: {task_name}")
261
+ else:
262
+ task_dir = self._rng.choice(self._tasks)
263
+
264
+ # Load files
265
+ with open(task_dir / "task.json") as f:
266
+ self._task_meta = json.load(f)
267
+
268
+ design_buggy = task_dir / "design_buggy.v"
269
+ if design_buggy.is_file():
270
+ with open(design_buggy) as f:
271
+ self._rtl_lines = f.read().splitlines()
272
+ else:
273
+ self._rtl_lines = []
274
+
275
+ testbench = task_dir / "testbench.v"
276
+ if testbench.is_file():
277
+ with open(testbench) as f:
278
+ self._testbench_code = f.read()
279
+ else:
280
+ self._testbench_code = ""
281
+
282
+ design_golden = task_dir / "design_golden.v"
283
+ if design_golden.is_file():
284
+ with open(design_golden) as f:
285
+ self._golden_code = f.read()
286
+ else:
287
+ self._golden_code = ""
288
+
289
+ self._expected_output = self._task_meta.get("expected_sim_output", "")
290
+
291
+ # Reset state
292
+ eid = episode_id or str(uuid4())
293
+ self._state = State(episode_id=eid, step_count=0)
294
+ self._sim_status = "not_run"
295
+ self._synth_status = "not_run"
296
+ self._lint_status = "not_run"
297
+ self._sim_log = ""
298
+ self._synth_log = ""
299
+ self._lint_log = ""
300
+ self._error_summary = ""
301
+ self._code_dirty = False
302
+ self._code_hash = self._current_code_hash()
303
+ self._sim_validated_hash = ""
304
+ self._synth_validated_hash = ""
305
+ self._lint_validated_hash = ""
306
+ self._done = False
307
+ self._potential = 0.0
308
+ self._cumulative_reward = 0.0
309
+
310
+ # Fresh workdir
311
+ self._workdir = tempfile.mkdtemp(prefix="chipforge_")
312
+
313
+ return self._make_obs(
314
+ last_action="reset",
315
+ action_result=f"Loaded task: {self._task_meta.get('description', '')}",
316
+ step_reward=0.0,
317
+ )
318
+
319
+ def step( # type: ignore[override]
320
+ self,
321
+ action: ChipforgeAction,
322
+ timeout_s: Optional[float] = None,
323
+ **kwargs: Any,
324
+ ) -> ChipforgeObservation:
325
+ """Execute one action and return observation with per-step reward."""
326
+
327
+ if self._done:
328
+ return self._make_obs(
329
+ last_action="none",
330
+ action_result="Episode already finished. Call reset().",
331
+ step_reward=0.0,
332
+ )
333
+
334
+ self._state.step_count += 1
335
+ timeout = TOOL_TIMEOUT if timeout_s is None else max(1, int(timeout_s))
336
+ action_type = action.action_type.strip().lower()
337
+
338
+ if action_type not in VALID_ACTIONS:
339
+ return self._make_obs(
340
+ last_action=action_type,
341
+ action_result=f"Unknown action. Valid: {sorted(VALID_ACTIONS)}",
342
+ step_reward=-STEP_COST,
343
+ )
344
+
345
+ # Snapshot potential BEFORE action
346
+ old_potential = self._potential
347
+
348
+ # Dispatch action
349
+ obs_extras: Dict[str, Any] = {}
350
+ action_result = ""
351
+
352
+ if action_type == "view_testbench":
353
+ obs_extras["testbench_code"] = self._testbench_code
354
+ action_result = f"Testbench loaded ({self._testbench_code.count(chr(10))+1} lines)."
355
+
356
+ elif action_type == "view_synthesis_log":
357
+ obs_extras["log_output"] = self._synth_log[:LOG_TRUNCATE]
358
+ action_result = f"Viewing synthesis log ({len(self._synth_log)} chars)."
359
+
360
+ elif action_type == "view_lint_log":
361
+ obs_extras["log_output"] = self._lint_log[:LOG_TRUNCATE]
362
+ action_result = f"Viewing lint log ({len(self._lint_log)} chars)."
363
+
364
+ elif action_type == "view_simulation_log":
365
+ obs_extras["log_output"] = self._sim_log[:LOG_TRUNCATE]
366
+ action_result = f"Viewing simulation log ({len(self._sim_log)} chars)."
367
+
368
+ elif action_type == "run_simulation":
369
+ self._do_simulation(timeout=timeout)
370
+ obs_extras["log_output"] = self._sim_log[:LOG_TRUNCATE]
371
+ action_result = f"Simulation: {self._sim_status}. {self._error_summary}"
372
+
373
+ elif action_type == "run_synthesis":
374
+ self._do_synthesis(timeout=timeout)
375
+ obs_extras["log_output"] = self._synth_log[:LOG_TRUNCATE]
376
+ action_result = f"Synthesis: {self._synth_status}. {self._error_summary}"
377
+
378
+ elif action_type == "run_lint":
379
+ self._do_lint(timeout=timeout)
380
+ obs_extras["log_output"] = self._lint_log[:LOG_TRUNCATE]
381
+ action_result = f"Lint: {self._lint_status}. {self._error_summary}"
382
+
383
+ elif action_type == "edit_line":
384
+ action_result = self._do_edit(action.line_number, action.new_content)
385
+
386
+ elif action_type == "append_line":
387
+ action_result = self._do_append(action.new_content)
388
+
389
+ elif action_type == "edit_testbench_line":
390
+ action_result = self._do_edit_testbench(action.line_number, action.new_content)
391
+
392
+ elif action_type == "append_testbench_line":
393
+ action_result = self._do_append_testbench(action.new_content)
394
+
395
+ elif action_type == "submit":
396
+ action_result = self._do_submit(timeout=timeout)
397
+
398
+ # Compute new potential
399
+ new_potential = self._compute_potential()
400
+ self._potential = new_potential
401
+
402
+ # Per-step reward = potential delta - step cost + terminal bonus
403
+ step_reward = (new_potential - old_potential) - STEP_COST
404
+
405
+ # Terminal bonus/penalty on submit
406
+ if action_type == "submit":
407
+ if new_potential >= 1.0:
408
+ step_reward += 0.1 # bonus for perfect fix
409
+ elif new_potential >= 0.5:
410
+ step_reward += 0.0 # partial fix, no bonus
411
+ else:
412
+ step_reward -= 0.2 # premature submit penalty
413
+
414
+ self._cumulative_reward += step_reward
415
+
416
+ # Check step limit
417
+ if self._state.step_count >= MAX_STEPS and not self._done:
418
+ self._done = True
419
+ action_result += " Step limit reached."
420
+
421
+ return self._make_obs(
422
+ last_action=action_type,
423
+ action_result=action_result.strip(),
424
+ step_reward=step_reward,
425
+ **obs_extras,
426
+ )
427
+
428
+ @property
429
+ def state(self) -> State:
430
+ return self._state
431
+
432
+ # -----------------------------------------------------------------------
433
+ # Action Handlers
434
+ # -----------------------------------------------------------------------
435
+
436
+ def _do_simulation(self, timeout: int = TOOL_TIMEOUT) -> None:
437
+ """Compile + run with Verilator."""
438
+ if not self._workdir:
439
+ self._error_summary = "No working directory."
440
+ return
441
+
442
+ if not self._rtl_lines:
443
+ self._sim_status = "error"
444
+ self._sim_log = "No RTL design present. Build design first."
445
+ self._error_summary = "No RTL design present. Add lines with append_line."
446
+ self._sim_validated_hash = self._code_hash
447
+ return
448
+
449
+ if not self._testbench_code.strip():
450
+ self._sim_status = "error"
451
+ self._sim_log = "No testbench present. Build testbench first."
452
+ self._error_summary = (
453
+ "No testbench present. Add lines with append_testbench_line."
454
+ )
455
+ self._sim_validated_hash = self._code_hash
456
+ return
457
+
458
+ # Write current files
459
+ design_path = os.path.join(self._workdir, "design.v")
460
+ tb_path = os.path.join(self._workdir, "testbench.v")
461
+ with open(design_path, "w") as f:
462
+ f.write("\n".join(self._rtl_lines) + "\n")
463
+ with open(tb_path, "w") as f:
464
+ f.write(self._testbench_code)
465
+
466
+ # Clean previous build
467
+ obj_dir = os.path.join(self._workdir, "obj_dir")
468
+ if os.path.isdir(obj_dir):
469
+ shutil.rmtree(obj_dir, ignore_errors=True)
470
+
471
+ # Compile
472
+ compile_result = _run_tool(
473
+ [
474
+ VERILATOR,
475
+ "--prefix", "Vsim",
476
+ "--binary",
477
+ "--build-jobs", "0",
478
+ "--build",
479
+ "--quiet-build",
480
+ "-Wno-fatal",
481
+ "--timescale", "1ns/1ns",
482
+ "design.v",
483
+ "testbench.v",
484
+ ],
485
+ cwd=self._workdir,
486
+ timeout=timeout,
487
+ )
488
+
489
+ if compile_result["returncode"] != 0:
490
+ self._sim_status = "error"
491
+ self._sim_log = (
492
+ "=== COMPILATION FAILED ===\n"
493
+ + compile_result["stderr"] + "\n"
494
+ + compile_result["stdout"]
495
+ )
496
+ self._error_summary = _extract_error_summary(
497
+ compile_result["stderr"], compile_result["stdout"]
498
+ )
499
+ self._code_dirty = False
500
+ self._sim_validated_hash = self._code_hash
501
+ return
502
+
503
+ # Run simulation
504
+ sim_binary = os.path.join(self._workdir, "obj_dir", "Vsim")
505
+ if not os.path.isfile(sim_binary):
506
+ self._sim_status = "error"
507
+ self._sim_log = "Simulation binary not found."
508
+ self._error_summary = "Simulation binary not found."
509
+ return
510
+
511
+ run_result = _run_tool([sim_binary], cwd=self._workdir, timeout=timeout)
512
+ self._sim_log = run_result["stdout"] + run_result["stderr"]
513
+ self._code_dirty = False
514
+ self._sim_validated_hash = self._code_hash
515
+
516
+ # Compare output
517
+ if self._expected_output:
518
+ actual = [
519
+ l.strip() for l in run_result["stdout"].splitlines()
520
+ if l.strip() and not l.strip().startswith("-")
521
+ ]
522
+ expected = [
523
+ l.strip() for l in self._expected_output.splitlines()
524
+ if l.strip() and not l.strip().startswith("-")
525
+ ]
526
+ if actual == expected:
527
+ self._sim_status = "pass"
528
+ self._error_summary = "Simulation passed — output matches expected."
529
+ else:
530
+ self._sim_status = "fail"
531
+ self._error_summary = "Simulation output does not match expected."
532
+ else:
533
+ self._sim_status = "pass" if run_result["returncode"] == 0 else "fail"
534
+ self._error_summary = ""
535
+
536
+ def _do_synthesis(self, timeout: int = TOOL_TIMEOUT) -> None:
537
+ """Run Yosys synthesis."""
538
+ if not self._workdir:
539
+ self._error_summary = "No working directory."
540
+ return
541
+
542
+ design_path = os.path.join(self._workdir, "design.v")
543
+ with open(design_path, "w") as f:
544
+ f.write("\n".join(self._rtl_lines) + "\n")
545
+
546
+ yosys_script = (
547
+ "read_verilog design.v; "
548
+ "hierarchy -auto-top; "
549
+ "proc; opt; memory; opt; fsm; opt; "
550
+ "write_verilog synth_out.v"
551
+ )
552
+
553
+ result = _run_tool(
554
+ [YOSYS, "-p", yosys_script],
555
+ cwd=self._workdir,
556
+ timeout=timeout,
557
+ )
558
+
559
+ full_log = result["stdout"] + "\n" + result["stderr"]
560
+ self._synth_log = full_log
561
+ self._code_dirty = False
562
+
563
+ if result["returncode"] != 0:
564
+ self._synth_status = "error"
565
+ self._error_summary = _extract_error_summary(
566
+ result["stderr"], result["stdout"]
567
+ )
568
+ self._synth_validated_hash = self._code_hash
569
+ else:
570
+ lower_log = full_log.lower()
571
+ warning_patterns = ["latch inferred", "found and reported", "warning:"]
572
+ has_warning = any(p in lower_log for p in warning_patterns)
573
+
574
+ if has_warning:
575
+ self._synth_status = "warning"
576
+ self._error_summary = _extract_error_summary(
577
+ result["stderr"], result["stdout"]
578
+ ) or "Synthesis completed with warnings."
579
+ else:
580
+ self._synth_status = "pass"
581
+ self._error_summary = "Synthesis clean."
582
+ self._synth_validated_hash = self._code_hash
583
+
584
+ def _do_lint(self, timeout: int = TOOL_TIMEOUT) -> None:
585
+ """Run Verilator lint."""
586
+ if not self._workdir:
587
+ self._error_summary = "No working directory."
588
+ return
589
+
590
+ design_path = os.path.join(self._workdir, "design.v")
591
+ with open(design_path, "w") as f:
592
+ f.write("\n".join(self._rtl_lines) + "\n")
593
+
594
+ result = _run_tool(
595
+ [VERILATOR, "--lint-only", "design.v"],
596
+ cwd=self._workdir,
597
+ timeout=timeout,
598
+ )
599
+
600
+ lint_output = result["stderr"] + "\n" + result["stdout"]
601
+ self._lint_log = lint_output
602
+ self._code_dirty = False
603
+
604
+ if result["returncode"] != 0:
605
+ lower = lint_output.lower()
606
+ self._lint_status = "error" if "error" in lower else "warning"
607
+ self._error_summary = _extract_error_summary(
608
+ result["stderr"], result["stdout"]
609
+ )
610
+ self._lint_validated_hash = self._code_hash
611
+ else:
612
+ if "warning" in lint_output.lower():
613
+ self._lint_status = "warning"
614
+ self._error_summary = _extract_error_summary(
615
+ result["stderr"], result["stdout"]
616
+ )
617
+ else:
618
+ self._lint_status = "clean"
619
+ self._error_summary = "Lint clean."
620
+ self._lint_validated_hash = self._code_hash
621
+
622
+ def _do_edit(self, line_number: Optional[int], new_content: Optional[str]) -> str:
623
+ """Edit a single line. Returns action_result string."""
624
+ if line_number is None or new_content is None:
625
+ self._error_summary = "edit_line requires line_number and new_content."
626
+ return self._error_summary
627
+
628
+ if line_number < 1 or line_number > len(self._rtl_lines):
629
+ self._error_summary = (
630
+ f"Invalid line_number {line_number}. "
631
+ f"Valid range: 1–{len(self._rtl_lines)}."
632
+ )
633
+ return self._error_summary
634
+
635
+ old_line = self._rtl_lines[line_number - 1]
636
+ self._rtl_lines[line_number - 1] = new_content
637
+ self._code_dirty = True
638
+ self._code_hash = self._current_code_hash()
639
+
640
+ result = (
641
+ f"Line {line_number} updated. "
642
+ f"Old: '{old_line.strip()}' → New: '{new_content.strip()}'"
643
+ )
644
+ self._error_summary = result
645
+
646
+ # NOTE: We do NOT reset tool statuses here.
647
+ # This is intentional for RL — the potential stays the same
648
+ # after edit, so reward delta = -step_cost. The agent must
649
+ # re-run tools to measure the impact of the edit.
650
+ return result
651
+
652
+ def _do_append(self, new_content: Optional[str]) -> str:
653
+ """Append a single RTL line."""
654
+ if new_content is None:
655
+ self._error_summary = "append_line requires new_content."
656
+ return self._error_summary
657
+
658
+ self._rtl_lines.append(new_content)
659
+ self._code_dirty = True
660
+ self._code_hash = self._current_code_hash()
661
+ result = f"RTL line appended at {len(self._rtl_lines)}."
662
+ self._error_summary = result
663
+ return result
664
+
665
+ def _do_edit_testbench(self, line_number: Optional[int], new_content: Optional[str]) -> str:
666
+ """Edit a single line in testbench.v."""
667
+ if line_number is None or new_content is None:
668
+ self._error_summary = (
669
+ "edit_testbench_line requires line_number and new_content."
670
+ )
671
+ return self._error_summary
672
+
673
+ tb_lines = self._testbench_code.splitlines()
674
+ if line_number < 1 or line_number > len(tb_lines):
675
+ self._error_summary = (
676
+ f"Invalid testbench line_number {line_number}. "
677
+ f"Valid range: 1–{len(tb_lines)}."
678
+ )
679
+ return self._error_summary
680
+
681
+ old_line = tb_lines[line_number - 1]
682
+ tb_lines[line_number - 1] = new_content
683
+ self._testbench_code = "\n".join(tb_lines) + "\n"
684
+ self._code_dirty = True
685
+ self._code_hash = self._current_code_hash()
686
+
687
+ result = (
688
+ f"Testbench line {line_number} updated. "
689
+ f"Old: '{old_line.strip()}' → New: '{new_content.strip()}'"
690
+ )
691
+ self._error_summary = result
692
+ return result
693
+
694
+ def _do_append_testbench(self, new_content: Optional[str]) -> str:
695
+ """Append one line to testbench.v."""
696
+ if new_content is None:
697
+ self._error_summary = "append_testbench_line requires new_content."
698
+ return self._error_summary
699
+
700
+ tb_lines = self._testbench_code.splitlines()
701
+ tb_lines.append(new_content)
702
+ self._testbench_code = "\n".join(tb_lines) + "\n"
703
+ self._code_dirty = True
704
+ self._code_hash = self._current_code_hash()
705
+ result = f"Testbench line appended at {len(tb_lines)}."
706
+ self._error_summary = result
707
+ return result
708
+
709
+ def _do_submit(self, timeout: int = TOOL_TIMEOUT) -> str:
710
+ """Submit solution. Re-runs any stale tools, then marks done."""
711
+ self._done = True
712
+
713
+ # Force re-run all tools on the current (possibly edited) code
714
+ self._do_simulation(timeout=timeout)
715
+ self._do_synthesis(timeout=timeout)
716
+ self._do_lint(timeout=timeout)
717
+
718
+ return (
719
+ f"Submitted. sim={self._sim_status}, "
720
+ f"synth={self._synth_status}, lint={self._lint_status}."
721
+ )
722
+
723
+ # -----------------------------------------------------------------------
724
+ # Observation builder
725
+ # -----------------------------------------------------------------------
726
+
727
+ def _numbered_rtl(self) -> str:
728
+ """Return RTL code with line numbers."""
729
+ if not self._rtl_lines:
730
+ return " 1: // RTL is currently empty. Use append_line to create it."
731
+ return "\n".join(f"{i:3d}: {line}" for i, line in enumerate(self._rtl_lines, 1))
732
+
733
+ def _make_obs(
734
+ self,
735
+ last_action: str,
736
+ action_result: str,
737
+ step_reward: float,
738
+ **extra: Any,
739
+ ) -> ChipforgeObservation:
740
+ """Build a self-contained observation."""
741
+ return ChipforgeObservation(
742
+ # Always included — the Markov state
743
+ rtl_code=self._numbered_rtl(),
744
+ sim_status=self._sim_status,
745
+ synth_status=self._synth_status,
746
+ lint_status=self._lint_status,
747
+ error_summary=self._error_summary,
748
+ task_description=self._task_meta.get("description", ""),
749
+
750
+ # Action feedback
751
+ last_action=last_action,
752
+ action_result=action_result,
753
+
754
+ # Conditionally populated
755
+ testbench_code=extra.get("testbench_code", ""),
756
+ log_output=extra.get("log_output", ""),
757
+
758
+ # RL signals
759
+ step_count=self._state.step_count,
760
+ max_steps=MAX_STEPS,
761
+ reward=step_reward,
762
+ cumulative_reward=self._cumulative_reward,
763
+ done=self._done,
764
+ metadata={
765
+ "task_mode": self._task_meta.get("task_type", "debug_rtl"),
766
+ "missing_files": {
767
+ "design_buggy.v": not bool(self._rtl_lines),
768
+ "testbench.v": not bool(self._testbench_code.strip()),
769
+ "design_golden.v": not bool(self._golden_code.strip()),
770
+ },
771
+ "code_dirty": self._code_dirty,
772
+ "tool_freshness": {
773
+ "simulation": self._sim_validated_hash == self._code_hash,
774
+ "synthesis": self._synth_validated_hash == self._code_hash,
775
+ "lint": self._lint_validated_hash == self._code_hash,
776
+ },
777
+ "logs_available": {
778
+ "simulation": bool(self._sim_log),
779
+ "synthesis": bool(self._synth_log),
780
+ "lint": bool(self._lint_log),
781
+ },
782
+ },
783
+ )
784
+
785
+ def close(self) -> None:
786
+ """Clean up."""
787
+ if self._workdir and os.path.isdir(self._workdir):
788
+ shutil.rmtree(self._workdir, ignore_errors=True)
789
+ self._workdir = None
server/tasks/easy/01_inverter_semicolon/design_buggy.v ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ module inverter (
2
+ input a,
3
+ output y
4
+ );
5
+
6
+ wire stage0;
7
+ wire stage1;
8
+ wire stage2;
9
+ wire stage3;
10
+ wire stage4;
11
+ wire stage5;
12
+ wire stage6;
13
+ wire stage7;
14
+ wire stage8;
15
+ wire stage9;
16
+
17
+ assign stage0 = a;
18
+ assign stage1 = stage0;
19
+ assign stage2 = stage1;
20
+ assign stage3 = stage2;
21
+ assign stage4 = stage3;
22
+ assign stage5 = stage4;
23
+ assign stage6 = stage5;
24
+ assign stage7 = stage6;
25
+ assign stage8 = stage7;
26
+ assign stage9 = stage8;
27
+
28
+ assign y = ~stage9
29
+
30
+ endmodule
server/tasks/easy/01_inverter_semicolon/design_golden.v ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ module inverter (
2
+ input a,
3
+ output y
4
+ );
5
+
6
+ wire stage0;
7
+ wire stage1;
8
+ wire stage2;
9
+ wire stage3;
10
+ wire stage4;
11
+ wire stage5;
12
+ wire stage6;
13
+ wire stage7;
14
+ wire stage8;
15
+ wire stage9;
16
+
17
+ assign stage0 = a;
18
+ assign stage1 = stage0;
19
+ assign stage2 = stage1;
20
+ assign stage3 = stage2;
21
+ assign stage4 = stage3;
22
+ assign stage5 = stage4;
23
+ assign stage6 = stage5;
24
+ assign stage7 = stage6;
25
+ assign stage8 = stage7;
26
+ assign stage9 = stage8;
27
+
28
+ assign y = ~stage9;
29
+
30
+ endmodule