shinoyarin commited on
Commit
100c906
·
verified ·
1 Parent(s): 8bde04c

Release Tesla-Pro-TPI

Browse files
README.md CHANGED
@@ -1,4 +1,6 @@
1
  ---
 
 
2
  license: apache-2.0
3
  library_name: peft
4
  base_model: Qwen/Qwen2.5-Coder-7B-Instruct
@@ -6,63 +8,242 @@ pipeline_tag: text-generation
6
  tags:
7
  - peft
8
  - lora
 
9
  - verilog
10
  - eda
11
  - dft
12
  - test-point-insertion
 
 
13
  ---
14
 
15
- # Tesla-Pro-TPI
16
 
17
- Tesla-Pro-TPI is a LoRA adapter for RTL test point insertion (TPI). Given
18
- Verilog RTL, the scan-cell list produced by PSS, a TPI bit budget, and the TPI
19
- insertion rules, it selects legal nonscan register bits and generates modified
20
- RTL containing control points, observation points, or both.
21
 
22
- The model is based on `Qwen/Qwen2.5-Coder-7B-Instruct` and was trained with
23
- SFT, static legality/budget GRPO, and DC/TMAX coverage-aware GRPO. This
24
- repository contains the PEFT adapter and tokenizer files, not a merged copy of
25
- the base model.
26
 
27
- ## Model checkpoint
28
 
29
- - Release checkpoint: `grpo_model_tmax_coverage_from_budgetaware_ckpt237_5gpu_full_e1/checkpoint-2656`
30
- - Adapter type: LoRA, rank 16, alpha 32
31
- - Intended input: RTL, forbidden PSS scan-cell bits, TPI budget, and insertion rules
32
- - Intended output: reasoning plus complete TPI-modified RTL in `<total_design>`
 
 
 
 
 
 
 
33
 
34
- ## Evaluation
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
 
36
- In the matched DC/TMAX comparison over 116 designs with five rollouts per
37
- design, this checkpoint obtained 45.7% coverage-gain Pass@1 and 61.2%
38
- coverage-gain Pass@5. Among 346 strict and EDA-comparable candidates, 72.0%
39
- improved coverage, with a mean coverage delta of 0.97 percentage points.
40
- These results are specific to the corresponding synthesis, ATPG, prompt, and
41
- static-validation protocol.
42
 
43
- ## Loading
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
 
45
  ```python
 
 
 
46
  from peft import AutoPeftModelForCausalLM
47
  from transformers import AutoTokenizer
48
 
49
  model_id = "SKLP-EDA-LAB/Tesla-Pro-TPI"
 
50
  tokenizer = AutoTokenizer.from_pretrained(model_id)
51
  model = AutoPeftModelForCausalLM.from_pretrained(
52
  model_id,
53
  torch_dtype="auto",
54
  device_map="auto",
55
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  ```
57
 
58
- Use the same prompt rules and parser as the Tesla-Pro TPI evaluation pipeline.
59
- Before synthesis, verify the exact physical-bit budget, scan-cell exclusion,
60
- top-module preservation, CP/OP structure, and original-functional-logic
61
- retention. DC and ATPG validation remain required.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
 
63
  ## Limitations
64
 
65
- The model can emit syntactically or semantically invalid RTL and does not
66
- guarantee coverage improvement for every rollout. Results depend on the cell
67
- library, constraints, fault model, ATPG mode, and register-name mapping.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
 
 
 
1
  ---
2
+ language:
3
+ - en
4
  license: apache-2.0
5
  library_name: peft
6
  base_model: Qwen/Qwen2.5-Coder-7B-Instruct
 
8
  tags:
9
  - peft
10
  - lora
11
+ - qwen2.5-coder
12
  - verilog
13
  - eda
14
  - dft
15
  - test-point-insertion
16
+ - reinforcement-learning
17
+ - grpo
18
  ---
19
 
20
+ # TESLA-Pro-TPI
21
 
22
+ TESLA-Pro-TPI is the RTL test point insertion model from **TESLA-Pro: Testability Enhancement for Shift Left Automation via GRPO-aligned LLMs**. Given complete Verilog RTL, the scan-cell bits selected by PSS, an exact TPI budget, and the insertion contract, it selects legal nonscan register bits and emits the complete TPI-modified RTL.
 
 
 
23
 
24
+ This repository contains a PEFT LoRA adapter and tokenizer files. It does not contain a merged copy of the base model.
 
 
 
25
 
26
+ ## Model Details
27
 
28
+ | Item | Value |
29
+ |---|---|
30
+ | Developer | SKLP-EDA-LAB |
31
+ | Base model | [Qwen/Qwen2.5-Coder-7B-Instruct](https://huggingface.co/Qwen/Qwen2.5-Coder-7B-Instruct) |
32
+ | Task | RTL test point insertion (TPI) |
33
+ | Training stages | SFT, static legality/budget GRPO, and DC/TMAX coverage-aware GRPO |
34
+ | Adapter | LoRA, rank 16, alpha 32, dropout 0.10 |
35
+ | Release checkpoint | `grpo_model_tmax_coverage_from_budgetaware_ckpt237_5gpu_full_e1/checkpoint-2656` |
36
+ | Input | Complete RTL, exact PSS scan-cell list, exact TPI bit budget, and insertion rules |
37
+ | Output | `<think>` reasoning and complete modified RTL inside `<total_design>` |
38
+ | Upstream model | [TESLA-Pro-PSS](https://huggingface.co/SKLP-EDA-LAB/Tesla-Pro-PSS) |
39
 
40
+ ## Intended Use
41
+
42
+ TESLA-Pro-TPI is intended for research on shift-left DFT and RTL-level testability optimization. It supports control points (CP), observation points (OP), and CP+OP, subject to the published prompt contract.
43
+
44
+ Each intervention site is counted at the physical register-bit level. Every selected bit must be a real nonscan register bit; the PSS scan-cell list is a strict forbidden set. The complete generated design must preserve the original top module and functional RTL except for the required TPI additions.
45
+
46
+ Generated RTL is a candidate, not sign-off output. Static checks, synthesis, and ATPG remain mandatory.
47
+
48
+ ## Required Prompt Format
49
+
50
+ **Do not send raw RTL or an informal request such as "insert three test points."** The model was fine-tuned with a fixed prompt that defines scan-cell exclusion, register-name normalization, exact intervention-site counting, CP/OP syntax, port style, complete-RTL preservation, and output tags. Omitting this contract changes the task distribution and can make paper results unreproducible.
51
+
52
+ The repository provides the exact input-only `gen_sync` prompt in two forms:
53
+
54
+ - [`examples/gen_sync_messages.json`](examples/gen_sync_messages.json): system/user messages ready for `apply_chat_template`;
55
+ - [`examples/gen_sync_prompt.txt`](examples/gen_sync_prompt.txt): the same complete prompt in human-readable form;
56
+ - [`examples/gen_sync.v`](examples/gen_sync.v): the original circuit by itself.
57
 
58
+ For a new design, retain all fixed rules and replace only:
 
 
 
 
 
59
 
60
+ - `#Required TPI Count#` and its repeated budget references;
61
+ - `#Forbidden Scan Cell Bits#` / `#Scan Cell Bits#` with the exact PSS output;
62
+ - `#RTL CODE#` with the complete target RTL;
63
+ - the declared RTL port-style statement when the target is non-ANSI.
64
+
65
+ The output contract is:
66
+
67
+ ```text
68
+ <think>
69
+ scan exclusion, legal candidate derivation, testability scoring,
70
+ budget/mode allocation, and implementation checks
71
+ </think>
72
+ <total_design>
73
+ complete TPI-modified Verilog RTL only
74
+ </total_design>
75
+ ```
76
+
77
+ ## Input-Only Circuit Example
78
+
79
+ The published example receives `counter[0]` from PSS as a forbidden scan-cell bit and requests **three** TPI bits. No reference TPI response is included.
80
+
81
+ ```text
82
+ Required TPI Count: 3
83
+ Forbidden Scan Cell Bits:
84
+ counter[0]
85
+ ```
86
+
87
+ ```verilog
88
+ module gen_sync ( input clock,input reset,input enable,input [7:0] rate,output wire sync );
89
+
90
+ reg [7:0] counter;
91
+ assign sync = |(((rate+1)>>1)& counter);
92
+ always @(posedge clock)
93
+ if(reset || ~enable)
94
+ counter <= #1 0;
95
+ else if(counter == rate)
96
+ counter <= #1 0;
97
+ else
98
+ counter <= #1 counter + 8'd1;
99
+ endmodule
100
+ ```
101
+
102
+ The full fixed prompt is intentionally preserved in [`examples/gen_sync_messages.json`](examples/gen_sync_messages.json). It includes the bit-normalization rule that removes only the final synthesized `_reg` suffix, the CP/OP templates, and the exact scan-bit exclusion contract.
103
+
104
+ ## Quickstart
105
+
106
+ Install recent versions of the required libraries:
107
+
108
+ ```bash
109
+ pip install "transformers>=4.37" peft accelerate huggingface_hub
110
+ ```
111
+
112
+ Run the exact input-only example:
113
 
114
  ```python
115
+ import json
116
+ import torch
117
+ from huggingface_hub import hf_hub_download
118
  from peft import AutoPeftModelForCausalLM
119
  from transformers import AutoTokenizer
120
 
121
  model_id = "SKLP-EDA-LAB/Tesla-Pro-TPI"
122
+
123
  tokenizer = AutoTokenizer.from_pretrained(model_id)
124
  model = AutoPeftModelForCausalLM.from_pretrained(
125
  model_id,
126
  torch_dtype="auto",
127
  device_map="auto",
128
  )
129
+ model.eval()
130
+
131
+ messages_path = hf_hub_download(
132
+ repo_id=model_id,
133
+ filename="examples/gen_sync_messages.json",
134
+ )
135
+ with open(messages_path, encoding="utf-8") as f:
136
+ messages = json.load(f)
137
+
138
+ text = tokenizer.apply_chat_template(
139
+ messages,
140
+ tokenize=False,
141
+ add_generation_prompt=True,
142
+ )
143
+ inputs = tokenizer(text, return_tensors="pt").to(model.device)
144
+
145
+ with torch.inference_mode():
146
+ generated = model.generate(
147
+ **inputs,
148
+ max_new_tokens=8192,
149
+ do_sample=True,
150
+ temperature=0.25,
151
+ top_p=0.90,
152
+ )
153
+
154
+ new_tokens = generated[:, inputs.input_ids.shape[1]:]
155
+ print(tokenizer.decode(new_tokens[0], skip_special_tokens=True))
156
  ```
157
 
158
+ For Pass@5-style evaluation, sample five independent completions with the same prompt, then parse and validate each generated `<total_design>` separately.
159
+
160
+ ## Evaluation
161
+
162
+ ### Paper Results
163
+
164
+ The paper evaluates five sampled outputs per circuit. For TPI, a sample passes when it inserts the requested number of test points and completes synthesis and equivalence checking successfully. The best valid rollout per circuit is then used for TC, PC, and DAT comparison.
165
+
166
+ | Model | P@5 (%) | Best in TC Imp. (%) | Best in PC (%) | Best in DAT (%) |
167
+ |---|---:|---:|---:|---:|
168
+ | **TESLA-Pro-TPI** | **94.3** | **65.0** | **64.0** | **71.0** |
169
+ | TESLA (SFT + DPO) | 89.8 | 49.5 | 55.5 | 66.5 |
170
+ | Qwen2.5-Coder-7B | 7.5 | 1.25 | 6.25 | 6.25 |
171
+
172
+ `TC Imp.` is test-coverage improvement, `PC` is ATPG pattern count, and `DAT` is data arrival time. These results depend on the paper's prompt, output parser, synthesis libraries, equivalence flow, constraints, and ATPG setup.
173
+
174
+ ### Stricter Coverage-Gain Audit
175
+
176
+ The release checkpoint was also evaluated under a stricter matched DC/TMAX protocol in which a pass requires a positive coverage delta:
177
+
178
+ | Designs | Rollouts/design | Coverage-gain Pass@1 | Coverage-gain Pass@5 |
179
+ |---:|---:|---:|---:|
180
+ | 116 | 5 | 45.7% | 61.2% |
181
+
182
+ Among 346 candidates that passed strict static checks and had comparable EDA reports, 72.0% improved test coverage. Their mean coverage delta was +0.97 percentage points. This stricter metric is different from the paper's task-validity P@5 and should not be compared as if they were the same denominator or pass condition.
183
+
184
+ ### Input-Only Case Validation
185
+
186
+ For the held-out `gen_sync` example bundled here:
187
+
188
+ - the PSS-to-TPI handoff supplied `counter[0]` as the exact forbidden scan bit;
189
+ - strict TPI static validation passed;
190
+ - DC and TMAX completed under stuck-at, full-sequential ATPG;
191
+ - baseline coverage was 9.41%, and TPI coverage was 9.73% (+0.32 percentage points);
192
+ - pattern count decreased from 7 to 5.
193
+
194
+ The reference TPI RTL was not supplied to the model. The example was checked against the TPI training inputs by normalized RTL hash; no matching training input was found.
195
+
196
+ ## Training
197
+
198
+ The manuscript reports the following common experimental recipe:
199
+
200
+ - base model: Qwen2.5-Coder-7B-Instruct (7.61B parameters);
201
+ - LoRA fine-tuning;
202
+ - learning rate: `5e-6`;
203
+ - batch size: `8`;
204
+ - instruction-tuning bootstrap: 3 epochs;
205
+ - GRPO: 2 epochs, group size `G=7`, KL coefficient `beta=0.02`, clipping range `epsilon=0.2`;
206
+ - software: PyTorch, Transformers, and TRL;
207
+ - hardware: 8 NVIDIA A100 80 GB GPUs connected with NVLink.
208
+
209
+ The paper reports a corpus of 7,842 single-module RTL samples, with 800 selected complex samples transformed for TPI supervision. PSS outputs are supplied as scan-cell constraints to AutoTPI-Pro, and the data are split 7:2:1 for training, validation, and testing.
210
+
211
+ GRPO combines structural feedback for syntax, budget, and legal register selection with functional feedback from synthesis and ATPG metrics. Test coverage is prioritized, followed by pattern count and data arrival time.
212
+
213
+ The adapter configuration shipped in this repository is authoritative for LoRA structure; the manuscript describes the paper-level training setup.
214
+
215
+ ## Validation Requirements
216
+
217
+ Before accepting generated RTL, at minimum:
218
+
219
+ 1. extract exactly one `<total_design>` block and parse the Verilog;
220
+ 2. verify the original top module and all original functional logic are retained;
221
+ 3. derive actual CP/OP target bits from RTL constructs, not from reasoning text;
222
+ 4. normalize identifiers conservatively and reject every PSS scan-cell intersection;
223
+ 5. require the unique physical intervention-site count to equal the budget;
224
+ 6. check CP active-high force-0 semantics and OP width/port consistency;
225
+ 7. run synthesis, equivalence checking, and ATPG against a matched baseline.
226
 
227
  ## Limitations
228
 
229
+ - The model can produce malformed, truncated, or functionally incorrect RTL.
230
+ - A legal candidate does not guarantee positive coverage improvement on every rollout.
231
+ - Hierarchical RTL, escaped identifiers, arrays, generated logic, and synthesis renaming require careful handling.
232
+ - Coverage and timing depend on the cell library, constraints, fault model, ATPG mode/depth, reset protocol, and timeout policy.
233
+ - Generated reasoning is not a formal proof. Parsed RTL and EDA reports are the source of truth.
234
+ - This research model is not suitable for unattended production sign-off.
235
+
236
+ ## Citation
237
+
238
+ ```bibtex
239
+ @misc{chao2026teslapro,
240
+ title = {TESLA-Pro: Testability Enhancement for Shift Left Automation via GRPO-aligned LLMs},
241
+ author = {Zhiteng Chao and Jingjie Xia and Rengang Zhang and Feng Gu and Hongqin Lyu and Bin Sun and Wenxing Li and Jianan Mu and Zizhen Liu and Jing Ye and Xiaowei Li and Huawei Li},
242
+ year = {2026},
243
+ note = {Manuscript}
244
+ }
245
+ ```
246
+
247
+ ## License
248
 
249
+ The adapter files in this repository are released under the Apache License 2.0. Use of the base model is also subject to its own repository terms.
examples/gen_sync.v ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ module gen_sync ( input clock,input reset,input enable,input [7:0] rate,output wire sync );
2
+
3
+ reg [7:0] counter;
4
+ assign sync = |(((rate+1)>>1)& counter);
5
+ always @(posedge clock)
6
+ if(reset || ~enable)
7
+ counter <= #1 0;
8
+ else if(counter == rate)
9
+ counter <= #1 0;
10
+ else
11
+ counter <= #1 counter + 8'd1;
12
+ endmodule
examples/gen_sync_messages.json ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "role": "system",
4
+ "content": "Respond in the following format:\n\n<think>\n...\n</think>\n<total_design>\n...\n</total_design>"
5
+ },
6
+ {
7
+ "role": "user",
8
+ "content": "## RULE #1: KEEP EVERY LINE OF THE ORIGINAL RTL\nThis is the most important rule. The #RTL CODE# section below contains the complete RTL.\nYou MUST output the FULL module -- every line stays exactly as it is, except for additions required by the chosen TPI mode:\n (a) CP or CP+OP: add `cp_en` using the same port declaration style as the original RTL. OP-only: do NOT add `cp_en`.\n (b) OP or CP+OP: add `tp_xxx` ports using the same port declaration style as the original RTL. CP-only: no `tp_*` port is required for that bit.\n (c) CP or CP+OP: add CP function definitions at the TOP of the module body.\n (d) CP or CP+OP: modify the target register assignment inside always blocks by wrapping the next value with the CP function call.\n (e) OP or CP+OP: add OP instantiations inside the module body (before `endmodule`).\n (f) OP or CP+OP: add only the required TestPointOBType_* module definitions AFTER the top module's `endmodule`.\n DO NOT remove, rewrite, reformat, or regenerate any original RTL code.\n DO NOT touch the module name, port list (except adding required cp_en/tp_* ports), parameters, reg/wire declarations,\n always blocks, assign statements, or any other original code.\n\nPORT STYLE: The original RTL uses ANSI-style ports.\n - Add new ports directly in the module port list with direction/type.\n - CP/CP+OP example: `input wire cp_en, output wire tp_sig1`.\n - OP-only example: `output wire tp_sig1`.\n - Do NOT add separate `input cp_en;` / `output tp_sig1;` declarations in the module body.\n\n## ACTUAL TASK INPUT SUMMARY (READ THIS BEFORE ANY TESTABILITY SCORING)\n#Required TPI Count#: 3\n#Forbidden Scan Cell Bits for THIS sample#:\ncounter[0]\n\nLegality equation for this sample:\n chosen_tpi_bits ∩ forbidden_scan_bits MUST be empty.\n If even one chosen CP-only, OP-only, or CP+OP bit is in the forbidden list, the answer is invalid.\nCRITICAL LOW-BIT WARNING for this sample:\n The following attractive low-order bits are FORBIDDEN here: counter[0]\n Do not choose them even if they toggle frequently. Start scoring only after removing them.\n\nHow to derive legal non-scan candidates from the RTL and scan-cell list:\n 1) Parse the ORIGINAL RTL declarations and sequential assignments to identify real register bits only.\n Legal targets must be declared as `reg`, `output reg`, or be assigned in a clocked always block.\n Do NOT choose plain `wire`, `input`, combinational temporary wires, or invented signal names.\n 2) Expand vectors bit-by-bit. Example: `reg [7:0] data_reg;` creates `data_reg[7]` ... `data_reg[0]`.\n Scalar registers keep their exact scalar name unless the RTL itself uses an indexed form.\n Unpacked register arrays are allowed only with exact static indices: `reg [31:0] stack [7:0];` creates\n bits such as `stack[7][8]`. Do NOT select dynamic elements such as `stack[write_ptr]`.\n 3) Normalize scan-cell names conservatively: remove a leading backslash, remove ONLY the final `_reg` suffix,\n keep every other part of the RTL name, and keep the bit index.\n Example: `\\data_reg_reg[8]` -> `data_reg[8]`, NOT `data[8]`.\n Example: `\\cc_reg[31]` -> `cc[31]`.\n 4) Compute: legal_non_scan_register_bits = RTL_declared_register_bits - normalized_forbidden_scan_bits.\n 5) Choose TPI bits only from legal_non_scan_register_bits. If a chosen name is not an exact RTL register bit,\n the answer is invalid even if the name looks semantically reasonable.\n\nYour first reasoning step must remove these exact forbidden bits from consideration.\nNever say the scan-cell list is empty unless the list above is literally empty.\n\n## MANDATORY RULES\n\n1. SCAN-CELL EXCLUSION CONSTRAINT (HIGHEST PRIORITY after Rule #1)\n #Scan Cell Bits# are scan cells selected by AutoPSS.\n These bits are already scan-controllable/observable and MUST NOT be selected for TPI.\n Treat #Scan Cell Bits# as an exact FORBIDDEN bit list, not as a recommendation.\n All test points MUST be inserted on non-scan register bits, i.e. register bits NOT listed in #Scan Cell Bits#.\n If a vector is partially scanned, legality is bit-specific: if cnt[0], cnt[1], cnt[2], cnt[3] are scan cells, then cnt[4] may be legal but cnt[0]..cnt[3] are forbidden.\n Low-order bits such as cnt[0], Q[0], state[0], filter[0], data[0] are often attractive because they toggle frequently, but they are STILL ILLEGAL if listed in #Scan Cell Bits#.\n Do not select a scan bit for CP-only, OP-only, or CP+OP under any circumstance.\n WRONG: Selecting a register bit that appears in #Scan Cell Bits#, even if it has high activity or strong testability.\n RIGHT: First remove every scan-cell bit from the candidate set, then choose TPI only from the remaining non-scan bits.\n\n1b. RTL REGISTER-BIT GROUNDING CONSTRAINT\n Before selecting TPI, explicitly derive legal candidates as:\n RTL_declared_register_bits - normalized_forbidden_scan_bits.\n Use the exact RTL signal name. Do not shorten, singularize, or rename registers.\n WRONG: RTL declares `data_reg`; selecting `data`.\n WRONG: scan cell `\\data_reg_reg[8]` is normalized to `data[8]`.\n RIGHT: scan cell `\\data_reg_reg[8]` is normalized to `data_reg[8]` because only the final `_reg` is removed.\n If the RTL declares `state`, do not select `state_reg` unless that exact register exists in the RTL.\n Every selected bit must be visible in the original RTL declaration or clocked assignment.\n\n Register arrays/memories are legal only when the target is bit-precise and statically indexed.\n RIGHT: `stack[7][8]` if RTL declares `reg [31:0] stack [7:0];`.\n WRONG: `stack[write_ptr]`, `stack[7]` as a whole row when the budget is for single bits, or any dynamic index.\n\n2. TPI Counting (IS = Intervention Site = 1 bit)\n - 1-bit CP-only = 1 IS | 1-bit OP-only = 1 IS | 1-bit CP+OP = 1 IS\n - N-bit OP = N IS (must use `TestPointOBType_Nbit`)\n - `output [7:0] tp_a;` = 8 IS. You CANNOT pack multiple IS into one vector.\n - Total IS MUST equal exactly 3.\n Counting EXAMPLES (CRITICAL -- same bit shared by CP+OP counts as 1 IS):\n Ex-A: cnt[3:0] OP (4 IS) + cnt[2] CP+OP (same bit, already counted) = 4 IS total (NOT 5!)\n Ex-B: result[15:0] OP (16 IS) + result[0] CP (same bit) = 16 IS total\n Ex-C: state[1] CP-only (1 IS) + state[0] OP-only (1 IS) = 2 IS total\n\n3. Port Declaration: Match the original RTL style exactly\n Add `cp_en` only if at least one selected bit uses CP or CP+OP.\n OP-only designs must not add `cp_en`.\n ANSI-style original: add directed ports in the module header, e.g. `input wire cp_en, output wire tp_sig1`.\n Non-ANSI-style original: add bare names in the port list and add `input cp_en;` / `output tp_sig1;` declarations in the body.\n Never mix ANSI declarations into a non-ANSI port list.\n\n4. CP Function: Use only for CP or CP+OP. Define at TOP of module body, call inside always-block with <=\n WRONG: CP on wire/assign. WRONG: function outside module.\n WRONG: `assign sig = sig_in & ~cp_en;` (never use assign for CP)\n WRONG: `sig = InsertCP_1bit(sig, cp_en);` (forgot <=)\n WRONG: `InsertCP_8bit = sig_in & {8{~cp_en}};` when only some bits are selected (this zeroes ALL bits!)\n CORRECT: `reg <= InsertCP_1bit(sig_next, cp_en);` (inside always block)\n CP Semantics: cp_en=0 means NORMAL (pass-through), cp_en=1 means FORCE-0.\n Partial mask (RECOMMENDED): `InsertCP_8bit = {sig_in[7:1], sig_in[0] & ~cp_en};`\n Full-vector mask is allowed only when EVERY bit of that vector is selected for CP.\n\n5. OP Instantiation: Use only for OP or CP+OP. Inside module body (before endmodule). NEVER use assign.\n CORRECT: `TestPointOBType_1bit op_sig1 (.funcin(signal1[0]), .tp_out(tp_sig1));`\n CORRECT: `TestPointOBType_8bit op_sig8 (.funcin(signal[7:0]), .tp_out(tp_sig8));`\n Width MUST match: N-bit signal -> `TestPointOBType_Nbit`\n\n6. Module Definition Order:\n (a) Original ports + required new ports (`cp_en` only for CP/CP+OP, `tp_*` only for OP/CP+OP)\n (b) CP function definitions only if CP/CP+OP exists (at TOP, before always blocks)\n (c) OP instantiations only if OP/CP+OP exists (before endmodule)\n (d) Original always/assign blocks (UNCHANGED except CP wrapping)\n (e) endmodule\n (f) `module TestPointOBType_* ... endmodule` definitions only for used OP widths\n\n7. Comments: Do not add new comments. Preserve comments that already exist in the original RTL.\n\n8. Directives: Do not add new `timescale or `include directives. Preserve directives that already exist in the original RTL.\n\n9. Chain-of-Thought (inside <think>):\n Step 1: Circuit Analysis + Scan-Cell Exclusion Filtering\n - Explicitly identify the scan-cell bits as FORBIDDEN.\n - List the real RTL register bits or register-bit groups that can be considered.\n - Normalize the scan-cell list using the rule above.\n - Build the legal candidate set by computing RTL_declared_register_bits - normalized_forbidden_scan_bits before scoring testability.\n - Never justify choosing a forbidden scan bit because it toggles often or looks useful.\n Step 2: Testability Scoring for non-scan register bits\n Step 3: Budget Allocation and mode choice (CP-only, OP-only, or CP+OP; prove sum of bits = 3)\n - Include a compact allocation table: bit | mode | count contribution | implementation line.\n - The table must use the exact RTL bit names that will appear in <total_design>.\n Step 4: Syntax Pre-simulation\n Step 5: Final Engineering Check\n - Every bit listed in your allocation table MUST be physically implemented in <total_design>.\n - Do not claim a bit such as filter[2] in <think> and then omit its CP/OP construct in RTL.\n - Recount physical RTL bits from actual InsertCP/TestPointOBType constructs, not from the prose table.\n - Write this exact legality check in words: `chosen_tpi_bits ∩ forbidden_scan_bits = empty`.\n - If the intersection is non-empty, you MUST replace the offending bit before writing <total_design>.\n - This is especially important for state[0], cnt[0], Q[0], filter[0], received[2], and other attractive low bits.\n Inside <total_design>: ONLY modified RTL. No markdown fences, no text.\n Stop immediately after </total_design>. Nothing after it.\n\n## STYLE EXAMPLE (follow the syntax style; choose CP/OP/CP+OP according to the actual design)\n\nExample input RTL -- simple state machine with 2 test points:\n`timescale 1ns/1ps\nmodule fsm_example #(parameter WIDTH=8) (\n input wire clk, rst_n,\n input wire [WIDTH-1:0] data_in,\n output reg [WIDTH-1:0] data_out,\n output wire ready\n);\n localparam IDLE=2'b00, WORK=2'b01, DONE=2'b10;\n reg [1:0] state, next_state;\n reg [WIDTH-1:0] buffer;\n assign ready = (state == DONE);\n always @(posedge clk or negedge rst_n)\n if (!rst_n) state <= IDLE;\n else state <= next_state;\n always @* begin\n next_state = state;\n case (state)\n IDLE: if (data_in[0]) next_state = WORK;\n WORK: next_state = DONE;\n DONE: next_state = IDLE;\n endcase\n end\n always @(posedge clk or negedge rst_n)\n if (!rst_n) buffer <= {WIDTH{1'b0}};\n else if (state == WORK) buffer <= data_in;\n always @(posedge clk or negedge rst_n)\n if (!rst_n) data_out <= {WIDTH{1'b0}};\n else data_out <= buffer;\nendmodule\n\nCORRECT output -- original RTL fully preserved, CP+OP example added:\n`timescale 1ns/1ps\nmodule fsm_example #(parameter WIDTH=8) (\n input wire clk, rst_n,\n input wire [WIDTH-1:0] data_in,\n output reg [WIDTH-1:0] data_out,\n output wire ready,\n input wire cp_en,\n output wire tp_state_1,\n output wire tp_buffer_7\n);\n localparam IDLE=2'b00, WORK=2'b01, DONE=2'b10;\n reg [1:0] state, next_state;\n reg [WIDTH-1:0] buffer;\n assign ready = (state == DONE);\n function [1:0] InsertCP_2bit_state;\n input [1:0] sig_in;\n input cp_en;\n begin\n InsertCP_2bit_state = {sig_in[1] & ~cp_en, sig_in[0]};\n end\n endfunction\n function [WIDTH-1:0] InsertCP_Wbit_buffer;\n input [WIDTH-1:0] sig_in;\n input cp_en;\n begin\n InsertCP_Wbit_buffer = {sig_in[WIDTH-1:8], sig_in[7] & ~cp_en, sig_in[6:0]};\n end\n endfunction\n TestPointOBType_1bit op_state_1 (.funcin(state[1]), .tp_out(tp_state_1));\n TestPointOBType_1bit op_buffer_7 (.funcin(buffer[7]), .tp_out(tp_buffer_7));\n always @(posedge clk or negedge rst_n)\n if (!rst_n) state <= IDLE;\n else state <= InsertCP_2bit_state(next_state, cp_en);\n always @* begin\n next_state = state;\n case (state)\n IDLE: if (data_in[0]) next_state = WORK;\n WORK: next_state = DONE;\n DONE: next_state = IDLE;\n endcase\n end\n always @(posedge clk or negedge rst_n)\n if (!rst_n) buffer <= {WIDTH{1'b0}};\n else if (state == WORK) buffer <= InsertCP_Wbit_buffer(data_in, cp_en);\n always @(posedge clk or negedge rst_n)\n if (!rst_n) data_out <= {WIDTH{1'b0}};\n else data_out <= buffer;\nendmodule\nmodule TestPointOBType_1bit (input funcin, output tp_out);\n assign tp_out = funcin;\nendmodule\nmodule TestPointOBType_2bit (input [1:0] funcin, output [1:0] tp_out);\n assign tp_out = funcin;\nendmodule\n\n## CP/OP SYNTAX REFERENCE\n\nUse only the syntax needed by your selected modes. OP-only samples do not need `cp_en` or CP functions.\n\n### CP Function (ONLY for CP or CP+OP; AND-type: cp_en=0=normal/pass-through, cp_en=1=force target bit to 0)\nThe key principle: only the masked bits are forced to 0; ALL other bits PASS THROUGH unchanged.\n\nMode A -- Single bit CP (most common):\n function InsertCP_1bit;\n input sig_in; input cp_en;\n begin InsertCP_1bit = sig_in & ~cp_en; end\n endfunction\n\nMode B -- Multi-bit, only bit[0] controlled, rest PASS THROUGH:\n function [7:0] InsertCP_8bit_bit0;\n input [7:0] sig_in; input cp_en;\n begin\n InsertCP_8bit_bit0 = {sig_in[7:1], sig_in[0] & ~cp_en};\n end\n endfunction\n\nMode C -- Multi-bit, specific bits controlled (bit[7] + bit[3]), rest PASS THROUGH:\n function [7:0] InsertCP_8bit_bit73;\n input [7:0] sig_in; input cp_en;\n begin\n InsertCP_8bit_bit73 = {\n sig_in[7] & ~cp_en, sig_in[6:4],\n sig_in[3] & ~cp_en, sig_in[2:0]\n };\n end\n endfunction\n\nMode D -- Full-vector mask is usually wrong:\n Do NOT write `sig_in & {N{~cp_en}}` unless all N bits are selected for CP.\n\n### CP Usage (inside always block, use <= non-blocking)\n reg <= InsertCP_1bit(reg_next, cp_en);\n reg <= InsertCP_8bit_bit0(reg_next, cp_en);\n reg <= InsertCP_8bit_bit73(reg_next, cp_en);\nFull-vector mask is rarely correct -- it zeroes every bit of the vector!\n\n### OP Instantiation\n TestPointOBType_1bit op_sig1 (.funcin(signal1), .tp_out(tp_sig1));\n TestPointOBType_8bit op_sig8 (.funcin(signal[7:0]), .tp_out(tp_sig8));\n\n For unpacked register arrays, use exact static bit indices:\n TestPointOBType_1bit op_stack_7_8 (.funcin(stack[7][8]), .tp_out(tp_stack_7_8));\n Do not use dynamic array indices for TPI targets.\n\n### Port Declaration\n Preserve the original port declaration style.\n ANSI original: add directed ports in the header.\n Non-ANSI original: add bare names in the header and declarations in the body.\n `cp_en` is only for CP or CP+OP. `tp_*` is only for OP or CP+OP.\n\n### Module Definition Order\n 1) Original ports + required added ports\n 2) CP function definitions, only if CP/CP+OP exists (at TOP of module body)\n 3) OP instantiations, only if OP/CP+OP exists (before endmodule)\n 4) Original logic (unchanged)\n 5) endmodule\n 6) TestPointOBType_* module definitions, only for used OP widths\n\n#RTL CODE#:\nmodule gen_sync ( input clock,input reset,input enable,input [7:0] rate,output wire sync );\n \n reg [7:0] counter; \n assign sync = |(((rate+1)>>1)& counter); \n always @(posedge clock) \n if(reset || ~enable) \n counter <= #1 0; \n else if(counter == rate) \n counter <= #1 0; \n else \n counter <= #1 counter + 8'd1; \n endmodule\n\n#Scan Cell Bits (DO NOT select):\ncounter[0]\n\n#Required TPI Count: 3"
9
+ }
10
+ ]
examples/gen_sync_prompt.txt ADDED
@@ -0,0 +1,324 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ===== SYSTEM =====
2
+ Respond in the following format:
3
+
4
+ <think>
5
+ ...
6
+ </think>
7
+ <total_design>
8
+ ...
9
+ </total_design>
10
+
11
+ ===== USER =====
12
+ ## RULE #1: KEEP EVERY LINE OF THE ORIGINAL RTL
13
+ This is the most important rule. The #RTL CODE# section below contains the complete RTL.
14
+ You MUST output the FULL module -- every line stays exactly as it is, except for additions required by the chosen TPI mode:
15
+ (a) CP or CP+OP: add `cp_en` using the same port declaration style as the original RTL. OP-only: do NOT add `cp_en`.
16
+ (b) OP or CP+OP: add `tp_xxx` ports using the same port declaration style as the original RTL. CP-only: no `tp_*` port is required for that bit.
17
+ (c) CP or CP+OP: add CP function definitions at the TOP of the module body.
18
+ (d) CP or CP+OP: modify the target register assignment inside always blocks by wrapping the next value with the CP function call.
19
+ (e) OP or CP+OP: add OP instantiations inside the module body (before `endmodule`).
20
+ (f) OP or CP+OP: add only the required TestPointOBType_* module definitions AFTER the top module's `endmodule`.
21
+ DO NOT remove, rewrite, reformat, or regenerate any original RTL code.
22
+ DO NOT touch the module name, port list (except adding required cp_en/tp_* ports), parameters, reg/wire declarations,
23
+ always blocks, assign statements, or any other original code.
24
+
25
+ PORT STYLE: The original RTL uses ANSI-style ports.
26
+ - Add new ports directly in the module port list with direction/type.
27
+ - CP/CP+OP example: `input wire cp_en, output wire tp_sig1`.
28
+ - OP-only example: `output wire tp_sig1`.
29
+ - Do NOT add separate `input cp_en;` / `output tp_sig1;` declarations in the module body.
30
+
31
+ ## ACTUAL TASK INPUT SUMMARY (READ THIS BEFORE ANY TESTABILITY SCORING)
32
+ #Required TPI Count#: 3
33
+ #Forbidden Scan Cell Bits for THIS sample#:
34
+ counter[0]
35
+
36
+ Legality equation for this sample:
37
+ chosen_tpi_bits ∩ forbidden_scan_bits MUST be empty.
38
+ If even one chosen CP-only, OP-only, or CP+OP bit is in the forbidden list, the answer is invalid.
39
+ CRITICAL LOW-BIT WARNING for this sample:
40
+ The following attractive low-order bits are FORBIDDEN here: counter[0]
41
+ Do not choose them even if they toggle frequently. Start scoring only after removing them.
42
+
43
+ How to derive legal non-scan candidates from the RTL and scan-cell list:
44
+ 1) Parse the ORIGINAL RTL declarations and sequential assignments to identify real register bits only.
45
+ Legal targets must be declared as `reg`, `output reg`, or be assigned in a clocked always block.
46
+ Do NOT choose plain `wire`, `input`, combinational temporary wires, or invented signal names.
47
+ 2) Expand vectors bit-by-bit. Example: `reg [7:0] data_reg;` creates `data_reg[7]` ... `data_reg[0]`.
48
+ Scalar registers keep their exact scalar name unless the RTL itself uses an indexed form.
49
+ Unpacked register arrays are allowed only with exact static indices: `reg [31:0] stack [7:0];` creates
50
+ bits such as `stack[7][8]`. Do NOT select dynamic elements such as `stack[write_ptr]`.
51
+ 3) Normalize scan-cell names conservatively: remove a leading backslash, remove ONLY the final `_reg` suffix,
52
+ keep every other part of the RTL name, and keep the bit index.
53
+ Example: `\data_reg_reg[8]` -> `data_reg[8]`, NOT `data[8]`.
54
+ Example: `\cc_reg[31]` -> `cc[31]`.
55
+ 4) Compute: legal_non_scan_register_bits = RTL_declared_register_bits - normalized_forbidden_scan_bits.
56
+ 5) Choose TPI bits only from legal_non_scan_register_bits. If a chosen name is not an exact RTL register bit,
57
+ the answer is invalid even if the name looks semantically reasonable.
58
+
59
+ Your first reasoning step must remove these exact forbidden bits from consideration.
60
+ Never say the scan-cell list is empty unless the list above is literally empty.
61
+
62
+ ## MANDATORY RULES
63
+
64
+ 1. SCAN-CELL EXCLUSION CONSTRAINT (HIGHEST PRIORITY after Rule #1)
65
+ #Scan Cell Bits# are scan cells selected by AutoPSS.
66
+ These bits are already scan-controllable/observable and MUST NOT be selected for TPI.
67
+ Treat #Scan Cell Bits# as an exact FORBIDDEN bit list, not as a recommendation.
68
+ All test points MUST be inserted on non-scan register bits, i.e. register bits NOT listed in #Scan Cell Bits#.
69
+ If a vector is partially scanned, legality is bit-specific: if cnt[0], cnt[1], cnt[2], cnt[3] are scan cells, then cnt[4] may be legal but cnt[0]..cnt[3] are forbidden.
70
+ Low-order bits such as cnt[0], Q[0], state[0], filter[0], data[0] are often attractive because they toggle frequently, but they are STILL ILLEGAL if listed in #Scan Cell Bits#.
71
+ Do not select a scan bit for CP-only, OP-only, or CP+OP under any circumstance.
72
+ WRONG: Selecting a register bit that appears in #Scan Cell Bits#, even if it has high activity or strong testability.
73
+ RIGHT: First remove every scan-cell bit from the candidate set, then choose TPI only from the remaining non-scan bits.
74
+
75
+ 1b. RTL REGISTER-BIT GROUNDING CONSTRAINT
76
+ Before selecting TPI, explicitly derive legal candidates as:
77
+ RTL_declared_register_bits - normalized_forbidden_scan_bits.
78
+ Use the exact RTL signal name. Do not shorten, singularize, or rename registers.
79
+ WRONG: RTL declares `data_reg`; selecting `data`.
80
+ WRONG: scan cell `\data_reg_reg[8]` is normalized to `data[8]`.
81
+ RIGHT: scan cell `\data_reg_reg[8]` is normalized to `data_reg[8]` because only the final `_reg` is removed.
82
+ If the RTL declares `state`, do not select `state_reg` unless that exact register exists in the RTL.
83
+ Every selected bit must be visible in the original RTL declaration or clocked assignment.
84
+
85
+ Register arrays/memories are legal only when the target is bit-precise and statically indexed.
86
+ RIGHT: `stack[7][8]` if RTL declares `reg [31:0] stack [7:0];`.
87
+ WRONG: `stack[write_ptr]`, `stack[7]` as a whole row when the budget is for single bits, or any dynamic index.
88
+
89
+ 2. TPI Counting (IS = Intervention Site = 1 bit)
90
+ - 1-bit CP-only = 1 IS | 1-bit OP-only = 1 IS | 1-bit CP+OP = 1 IS
91
+ - N-bit OP = N IS (must use `TestPointOBType_Nbit`)
92
+ - `output [7:0] tp_a;` = 8 IS. You CANNOT pack multiple IS into one vector.
93
+ - Total IS MUST equal exactly 3.
94
+ Counting EXAMPLES (CRITICAL -- same bit shared by CP+OP counts as 1 IS):
95
+ Ex-A: cnt[3:0] OP (4 IS) + cnt[2] CP+OP (same bit, already counted) = 4 IS total (NOT 5!)
96
+ Ex-B: result[15:0] OP (16 IS) + result[0] CP (same bit) = 16 IS total
97
+ Ex-C: state[1] CP-only (1 IS) + state[0] OP-only (1 IS) = 2 IS total
98
+
99
+ 3. Port Declaration: Match the original RTL style exactly
100
+ Add `cp_en` only if at least one selected bit uses CP or CP+OP.
101
+ OP-only designs must not add `cp_en`.
102
+ ANSI-style original: add directed ports in the module header, e.g. `input wire cp_en, output wire tp_sig1`.
103
+ Non-ANSI-style original: add bare names in the port list and add `input cp_en;` / `output tp_sig1;` declarations in the body.
104
+ Never mix ANSI declarations into a non-ANSI port list.
105
+
106
+ 4. CP Function: Use only for CP or CP+OP. Define at TOP of module body, call inside always-block with <=
107
+ WRONG: CP on wire/assign. WRONG: function outside module.
108
+ WRONG: `assign sig = sig_in & ~cp_en;` (never use assign for CP)
109
+ WRONG: `sig = InsertCP_1bit(sig, cp_en);` (forgot <=)
110
+ WRONG: `InsertCP_8bit = sig_in & {8{~cp_en}};` when only some bits are selected (this zeroes ALL bits!)
111
+ CORRECT: `reg <= InsertCP_1bit(sig_next, cp_en);` (inside always block)
112
+ CP Semantics: cp_en=0 means NORMAL (pass-through), cp_en=1 means FORCE-0.
113
+ Partial mask (RECOMMENDED): `InsertCP_8bit = {sig_in[7:1], sig_in[0] & ~cp_en};`
114
+ Full-vector mask is allowed only when EVERY bit of that vector is selected for CP.
115
+
116
+ 5. OP Instantiation: Use only for OP or CP+OP. Inside module body (before endmodule). NEVER use assign.
117
+ CORRECT: `TestPointOBType_1bit op_sig1 (.funcin(signal1[0]), .tp_out(tp_sig1));`
118
+ CORRECT: `TestPointOBType_8bit op_sig8 (.funcin(signal[7:0]), .tp_out(tp_sig8));`
119
+ Width MUST match: N-bit signal -> `TestPointOBType_Nbit`
120
+
121
+ 6. Module Definition Order:
122
+ (a) Original ports + required new ports (`cp_en` only for CP/CP+OP, `tp_*` only for OP/CP+OP)
123
+ (b) CP function definitions only if CP/CP+OP exists (at TOP, before always blocks)
124
+ (c) OP instantiations only if OP/CP+OP exists (before endmodule)
125
+ (d) Original always/assign blocks (UNCHANGED except CP wrapping)
126
+ (e) endmodule
127
+ (f) `module TestPointOBType_* ... endmodule` definitions only for used OP widths
128
+
129
+ 7. Comments: Do not add new comments. Preserve comments that already exist in the original RTL.
130
+
131
+ 8. Directives: Do not add new `timescale or `include directives. Preserve directives that already exist in the original RTL.
132
+
133
+ 9. Chain-of-Thought (inside <think>):
134
+ Step 1: Circuit Analysis + Scan-Cell Exclusion Filtering
135
+ - Explicitly identify the scan-cell bits as FORBIDDEN.
136
+ - List the real RTL register bits or register-bit groups that can be considered.
137
+ - Normalize the scan-cell list using the rule above.
138
+ - Build the legal candidate set by computing RTL_declared_register_bits - normalized_forbidden_scan_bits before scoring testability.
139
+ - Never justify choosing a forbidden scan bit because it toggles often or looks useful.
140
+ Step 2: Testability Scoring for non-scan register bits
141
+ Step 3: Budget Allocation and mode choice (CP-only, OP-only, or CP+OP; prove sum of bits = 3)
142
+ - Include a compact allocation table: bit | mode | count contribution | implementation line.
143
+ - The table must use the exact RTL bit names that will appear in <total_design>.
144
+ Step 4: Syntax Pre-simulation
145
+ Step 5: Final Engineering Check
146
+ - Every bit listed in your allocation table MUST be physically implemented in <total_design>.
147
+ - Do not claim a bit such as filter[2] in <think> and then omit its CP/OP construct in RTL.
148
+ - Recount physical RTL bits from actual InsertCP/TestPointOBType constructs, not from the prose table.
149
+ - Write this exact legality check in words: `chosen_tpi_bits ∩ forbidden_scan_bits = empty`.
150
+ - If the intersection is non-empty, you MUST replace the offending bit before writing <total_design>.
151
+ - This is especially important for state[0], cnt[0], Q[0], filter[0], received[2], and other attractive low bits.
152
+ Inside <total_design>: ONLY modified RTL. No markdown fences, no text.
153
+ Stop immediately after </total_design>. Nothing after it.
154
+
155
+ ## STYLE EXAMPLE (follow the syntax style; choose CP/OP/CP+OP according to the actual design)
156
+
157
+ Example input RTL -- simple state machine with 2 test points:
158
+ `timescale 1ns/1ps
159
+ module fsm_example #(parameter WIDTH=8) (
160
+ input wire clk, rst_n,
161
+ input wire [WIDTH-1:0] data_in,
162
+ output reg [WIDTH-1:0] data_out,
163
+ output wire ready
164
+ );
165
+ localparam IDLE=2'b00, WORK=2'b01, DONE=2'b10;
166
+ reg [1:0] state, next_state;
167
+ reg [WIDTH-1:0] buffer;
168
+ assign ready = (state == DONE);
169
+ always @(posedge clk or negedge rst_n)
170
+ if (!rst_n) state <= IDLE;
171
+ else state <= next_state;
172
+ always @* begin
173
+ next_state = state;
174
+ case (state)
175
+ IDLE: if (data_in[0]) next_state = WORK;
176
+ WORK: next_state = DONE;
177
+ DONE: next_state = IDLE;
178
+ endcase
179
+ end
180
+ always @(posedge clk or negedge rst_n)
181
+ if (!rst_n) buffer <= {WIDTH{1'b0}};
182
+ else if (state == WORK) buffer <= data_in;
183
+ always @(posedge clk or negedge rst_n)
184
+ if (!rst_n) data_out <= {WIDTH{1'b0}};
185
+ else data_out <= buffer;
186
+ endmodule
187
+
188
+ CORRECT output -- original RTL fully preserved, CP+OP example added:
189
+ `timescale 1ns/1ps
190
+ module fsm_example #(parameter WIDTH=8) (
191
+ input wire clk, rst_n,
192
+ input wire [WIDTH-1:0] data_in,
193
+ output reg [WIDTH-1:0] data_out,
194
+ output wire ready,
195
+ input wire cp_en,
196
+ output wire tp_state_1,
197
+ output wire tp_buffer_7
198
+ );
199
+ localparam IDLE=2'b00, WORK=2'b01, DONE=2'b10;
200
+ reg [1:0] state, next_state;
201
+ reg [WIDTH-1:0] buffer;
202
+ assign ready = (state == DONE);
203
+ function [1:0] InsertCP_2bit_state;
204
+ input [1:0] sig_in;
205
+ input cp_en;
206
+ begin
207
+ InsertCP_2bit_state = {sig_in[1] & ~cp_en, sig_in[0]};
208
+ end
209
+ endfunction
210
+ function [WIDTH-1:0] InsertCP_Wbit_buffer;
211
+ input [WIDTH-1:0] sig_in;
212
+ input cp_en;
213
+ begin
214
+ InsertCP_Wbit_buffer = {sig_in[WIDTH-1:8], sig_in[7] & ~cp_en, sig_in[6:0]};
215
+ end
216
+ endfunction
217
+ TestPointOBType_1bit op_state_1 (.funcin(state[1]), .tp_out(tp_state_1));
218
+ TestPointOBType_1bit op_buffer_7 (.funcin(buffer[7]), .tp_out(tp_buffer_7));
219
+ always @(posedge clk or negedge rst_n)
220
+ if (!rst_n) state <= IDLE;
221
+ else state <= InsertCP_2bit_state(next_state, cp_en);
222
+ always @* begin
223
+ next_state = state;
224
+ case (state)
225
+ IDLE: if (data_in[0]) next_state = WORK;
226
+ WORK: next_state = DONE;
227
+ DONE: next_state = IDLE;
228
+ endcase
229
+ end
230
+ always @(posedge clk or negedge rst_n)
231
+ if (!rst_n) buffer <= {WIDTH{1'b0}};
232
+ else if (state == WORK) buffer <= InsertCP_Wbit_buffer(data_in, cp_en);
233
+ always @(posedge clk or negedge rst_n)
234
+ if (!rst_n) data_out <= {WIDTH{1'b0}};
235
+ else data_out <= buffer;
236
+ endmodule
237
+ module TestPointOBType_1bit (input funcin, output tp_out);
238
+ assign tp_out = funcin;
239
+ endmodule
240
+ module TestPointOBType_2bit (input [1:0] funcin, output [1:0] tp_out);
241
+ assign tp_out = funcin;
242
+ endmodule
243
+
244
+ ## CP/OP SYNTAX REFERENCE
245
+
246
+ Use only the syntax needed by your selected modes. OP-only samples do not need `cp_en` or CP functions.
247
+
248
+ ### CP Function (ONLY for CP or CP+OP; AND-type: cp_en=0=normal/pass-through, cp_en=1=force target bit to 0)
249
+ The key principle: only the masked bits are forced to 0; ALL other bits PASS THROUGH unchanged.
250
+
251
+ Mode A -- Single bit CP (most common):
252
+ function InsertCP_1bit;
253
+ input sig_in; input cp_en;
254
+ begin InsertCP_1bit = sig_in & ~cp_en; end
255
+ endfunction
256
+
257
+ Mode B -- Multi-bit, only bit[0] controlled, rest PASS THROUGH:
258
+ function [7:0] InsertCP_8bit_bit0;
259
+ input [7:0] sig_in; input cp_en;
260
+ begin
261
+ InsertCP_8bit_bit0 = {sig_in[7:1], sig_in[0] & ~cp_en};
262
+ end
263
+ endfunction
264
+
265
+ Mode C -- Multi-bit, specific bits controlled (bit[7] + bit[3]), rest PASS THROUGH:
266
+ function [7:0] InsertCP_8bit_bit73;
267
+ input [7:0] sig_in; input cp_en;
268
+ begin
269
+ InsertCP_8bit_bit73 = {
270
+ sig_in[7] & ~cp_en, sig_in[6:4],
271
+ sig_in[3] & ~cp_en, sig_in[2:0]
272
+ };
273
+ end
274
+ endfunction
275
+
276
+ Mode D -- Full-vector mask is usually wrong:
277
+ Do NOT write `sig_in & {N{~cp_en}}` unless all N bits are selected for CP.
278
+
279
+ ### CP Usage (inside always block, use <= non-blocking)
280
+ reg <= InsertCP_1bit(reg_next, cp_en);
281
+ reg <= InsertCP_8bit_bit0(reg_next, cp_en);
282
+ reg <= InsertCP_8bit_bit73(reg_next, cp_en);
283
+ Full-vector mask is rarely correct -- it zeroes every bit of the vector!
284
+
285
+ ### OP Instantiation
286
+ TestPointOBType_1bit op_sig1 (.funcin(signal1), .tp_out(tp_sig1));
287
+ TestPointOBType_8bit op_sig8 (.funcin(signal[7:0]), .tp_out(tp_sig8));
288
+
289
+ For unpacked register arrays, use exact static bit indices:
290
+ TestPointOBType_1bit op_stack_7_8 (.funcin(stack[7][8]), .tp_out(tp_stack_7_8));
291
+ Do not use dynamic array indices for TPI targets.
292
+
293
+ ### Port Declaration
294
+ Preserve the original port declaration style.
295
+ ANSI original: add directed ports in the header.
296
+ Non-ANSI original: add bare names in the header and declarations in the body.
297
+ `cp_en` is only for CP or CP+OP. `tp_*` is only for OP or CP+OP.
298
+
299
+ ### Module Definition Order
300
+ 1) Original ports + required added ports
301
+ 2) CP function definitions, only if CP/CP+OP exists (at TOP of module body)
302
+ 3) OP instantiations, only if OP/CP+OP exists (before endmodule)
303
+ 4) Original logic (unchanged)
304
+ 5) endmodule
305
+ 6) TestPointOBType_* module definitions, only for used OP widths
306
+
307
+ #RTL CODE#:
308
+ module gen_sync ( input clock,input reset,input enable,input [7:0] rate,output wire sync );
309
+
310
+ reg [7:0] counter;
311
+ assign sync = |(((rate+1)>>1)& counter);
312
+ always @(posedge clock)
313
+ if(reset || ~enable)
314
+ counter <= #1 0;
315
+ else if(counter == rate)
316
+ counter <= #1 0;
317
+ else
318
+ counter <= #1 counter + 8'd1;
319
+ endmodule
320
+
321
+ #Scan Cell Bits (DO NOT select):
322
+ counter[0]
323
+
324
+ #Required TPI Count: 3