Bind checker: đúng target, đúng tham số và đúng tín hiệu
Tiên quyết
Sau bài này bạn sẽ
- Chọn module type hoặc instance làm đích gắn checker
- Truy tham số và tín hiệu về đúng target
- Phát hiện lỗi mất carry mà không sửa mã logic DUT
Gắn phép kiểm vào thiết kế có sẵn
Bạn nhận một bộ cộng đã dùng ở nhiều nơi. Bạn muốn kiểm kết quả của từng instance, kể cả bit carry, nhưng giữ phép kiểm trong một file riêng để dễ tái sử dụng.
bind cho phép gắn thêm một instance checker vào target đã chọn khi elaboration. DUT giữ phần logic cộng; checker nhận tín hiệu và kiểm điều kiện đúng ở clock quan sát. Đây không phải một task gọi giữa simulation để gắn checker tùy lúc.
Một bit đầu vào vẫn cần hai bit kết quả
Bắt đầu với bộ cộng có hai đầu vào không dấu, mỗi đầu vào rộng 1 bit. Bảng sau dùng giá trị ngay tại cổng DUT; kết quả viết ở dạng nhị phân 2 bit.
| a | b | Tổng đúng | Tổng nếu làm mất carry | Có vi phạm? |
|---|---|---|---|---|
| 0 | 0 | 00 | 00 | Không |
| 0 | 1 | 01 | 01 | Không |
| 1 | 0 | 01 | 01 | Không |
| 1 | 1 | 10 | 00 | Có |
Chỉ kiểm bit thấp sẽ bỏ lọt dòng cuối: bit thấp vẫn bằng 0 trong cả hai kết quả. Checker cần so cả kết quả rộng 2 bit.
Với đầu vào rộng W bit, mỗi toán hạng được mở rộng thêm một bit trước phép cộng. Biểu thức so trong checker là sum == ({1'b0,a} + {1'b0,b}), với sum rộng W+1 bit.
Một câu bind, mỗi target một checker
Ví dụ có bốn instance của bind_adder: hai instance rộng 4 bit và hai instance rộng 1 bit. Câu bind theo module type là:
bind bind_adder bound_sum_checker #(.W(W)) type_check(.clk(clk),.a(a),.b(b),.sum(sum));
Đọc từ trái sang phải: bind_adder là loại target, bound_sum_checker là loại module được gắn, type_check là tên instance checker mới. Mỗi target có một type_check riêng; không phải bốn DUT cùng dùng một checker trung tâm.
Bộ ví dụ cần biên dịch đủ rtl.sv, checker.sv và tb.sv. Chỉ lấy câu bind sẽ chưa có định nghĩa DUT và checker.
Độ rộng đi theo target
Trong #(.W(W)), .W bên trái là parameter của checker; W bên phải lấy theo target. Vì vậy checker trong big_good dùng 4, còn checker trong mini_good dùng 1. Hai instance cùng loại module vẫn có thể nhận cấu hình khác nhau.
Các tên a, b, sum và clk ở kết nối cũng phải trỏ về tín hiệu của target tương ứng. Chẳng hạn big_bad nhận a đã đảo bit so với big_good; checker của nó phải kiểm đầu vào đã đảo tại chính cổng DUT.
Nếu viết #(.W(4)) cho mọi target, checker ở DUT nhỏ có thể bị mở rộng đầu vào ngoài ý muốn. Một số giá trị vẫn so đúng nên chỉ nhìn một lần pass chưa đủ phát hiện cấu hình sai. Hãy kiểm parameter thực và độ rộng cổng trước khi tin kết quả.
Khi chỉ muốn kiểm một instance
Nếu chỉ cần kiểm big_bad, dạng bind theo đường dẫn instance chọn riêng target đó. Nó khác bind theo type, vốn chọn cả bốn instance của bind_adder trong ví dụ.
Tên checker mới nằm trong target đã chọn. Nếu chỉ gắn single_check vào big_bad, không thể mặc định big_good cũng có tên ấy.
Dạng theo instance trong bộ ví dụ hiện chỉ được parser chấp nhận; công cụ mô phỏng đã ghim chưa build được. Kết quả của dạng theo type không thay cho bằng chứng chạy dạng theo instance. Source và diagnostic nằm trong phần bằng chứng cuối bài.
Nếu bật cả hai cách gắn vào cùng target, target đó có thể nhận hai checker. Hai báo cáo cho cùng vi phạm chưa chắc là hai lỗi DUT khác nhau.
Quan sát tín hiệu mà không làm đổi DUT
Checker của bài chỉ có input port, không assign hoặc force tín hiệu DUT. Nó đếm mẫu và vi phạm bằng biến nội bộ. Đó là lựa chọn thiết kế của checker này; từ khóa bind không tự bảo đảm mọi module được gắn đều chỉ đọc.
Bộ cộng là logic tổ hợp. Clock chỉ chọn lúc quan sát, không biến nó thành bộ cộng có thanh ghi. Testbench đổi đầu vào ở cạnh xuống rồi checker lấy mẫu ở cạnh lên, sau khi logic có thời gian ổn định.
Hai nhóm DUT có clock riêng và checker riêng. Việc này chưa minh họa một property chuyển từ clock này sang clock khác.
Bốn lỗi khi gắn checker
- Chọn một instance trong khi yêu cầu cần kiểm mọi instance của một loại module.
- Gán cứng độ rộng checker thay vì dùng cấu hình của target.
- Nối nhầm tín hiệu hoặc clock dù công thức so sánh đúng.
- Chỉ kiểm bit thấp và bỏ qua carry, hoặc vô tình làm checker drive DUT.
Khi chưa thấy vi phạm, kiểm checker đã được tạo và đã lấy mẫu chưa. Giữ một tình huống DUT sai có chủ đích để biết phép kiểm thực sự hoạt động.
Tự lần theo target, cổng và clock
- Với bốn DUT trong ví dụ, bind theo type tạo bao nhiêu checker? Mỗi checker có parameter W nào?
- Với DUT rộng 1 bit, vì sao so riêng bit thấp vẫn cho qua phép cộng sai ở dòng cuối bảng?
- Nếu
big_badnhận a đã đảo bit nhưng checker nhận a chưa đảo, phép so đang kiểm điều gì? - Nếu chỉ bind vào
big_bad, tênsingle_checkcó tồn tại trongbig_goodkhông? - Nếu sửa DUT cố ý sai thành đúng, số vi phạm dự kiến của bài thực hành cần thay đổi thế nào?
Kiểm tra
Bằng chứng kiểm chứng
Expected tính trước chạy: BIND TYPE CHECK targets=4 type_samples4=256 type_samples1=4 good4=0 bad4=120 good1=0 bad1=1 mini_end_ns=40 time_ns=2560.
Main type-bind quét toàn bộ 256 cặp đầu vào ở W=4 và 4 cặp ở W=1. DUT bad giữ W bit thấp rồi mở rộng 0, cố ý làm mất carry. Với W=4, số cặp overflow là 1+2+...+15=120; với W=1 chỉ có 1+1. Đảo a chỉ hoán vị miền đầu vào nên không đổi số trường hợp này.
| Target | W thực của checker | Số mẫu | Số vi phạm dự kiến |
|---|---|---|---|
| big_good | 4 | 256 | 0 |
| big_bad | 4 | 256 | 120 |
| mini_good | 1 | 4 | 0 |
| mini_bad | 1 | 4 | 1 |
Guard kiểm trực tiếp cả bốn parameter, sample/failure counter và thời gian thật. Nhóm nhỏ dừng ở 40 ns, toàn bộ bài chạy tới 2560 ns. Tắt checker làm counter của DUT bad sai kỳ vọng và oracle phải từ chối; không lấy zero failure làm bằng chứng checker hoạt động.
Bốn mutant parse/build được rồi bị bắt ở runtime: ép mọi checker về W=4, đảo predicate bằng thành khác, chỉ so bit thấp, hoặc sửa DUT bad thành đúng nhưng giữ kỳ vọng cũ của lab. Mutant cuối kiểm tính nhất quán của lab; không nói rằng sửa lỗi DUT là lỗi sản phẩm.
Source instance-specific giữ nguyên kỳ vọng của cả năm checker. Pyslang chấp nhận source; probe đọc nhầm single_check ở target không được chọn bị từ chối khi giải hierarchy. Verilator 5.050 từ chối đường dẫn instance tại dấu chấm và báo unsupported với dạng instance-list. Không xóa assertion hay hạ kỳ vọng để gọi source này đã simulated PASS.
Giới hạn: type-bind chỉ chạy trên mô hình 2-state và hai độ rộng W=1/W=4; vét cạn hữu hạn không chứng minh mọi cấu hình. Hai clock của các checker độc lập không phải một multiclocked property. Nguồn training có mô tả DFF chưa rõ timing/reset nên không sao chép property demo; checker cộng và phép kiểm trong bài được viết riêng. IEEE vẫn chờ đối chiếu.
Nguồn và mức độ đối chiếu
- IEEE 1800-2023 SystemVerilog LRM, Bind directives, elaboration and scope resolution — chưa đối chiếu LRM. Chưa đối chiếu với văn bản nguồn (chưa mở).
- Binding with Assertions — bản chụp resources.zip, Binding with Assertions; Why Bind Assertions?; bind example; Selecting the Bind Target; Where to Place the Bind Statement. Trích dẫn; nguồn đã đọc các mục liên quan.
- Thí nghiệm nguyên bản B8.bind, Module-type binding across W1/W4 targets, four runtime mutants and retained instance-binding failures. Trích dẫn; nguồn đã đọc toàn văn.
- IEEE 1800-2023 SystemVerilog LRM, Bind directives and target scope — chưa đối chiếu LRM. Chưa đối chiếu với văn bản nguồn (chưa mở).
- IEEE 1800-2023 SystemVerilog LRM, Instance-specific bind syntax/scope — chưa đối chiếu LRM. Chưa đối chiếu với văn bản nguồn (chưa mở).