Compiler directives: macro tồn tại khác tín hiệu bằng1
Tiên quyết
Sau bài này bạn sẽ
- Phân biệt conditional compilation với nhánh if chạy trong mô phỏng
- Đọc macro như text expansion và kiểm precedence
- Giải thích include guard, undef và phạm vi compilation
- Dùng default_nettype để giảm lỗi implicit net với giới hạn rõ
Có những nhánh không bao giờ được đưa vào simulation
Bạn tắt một feature bằng cách define macro thành 0 nhưng log vẫn cho biết nhánh feature được chọn. Nguyên nhân thường nằm ở câu hỏi mà ifdef kiểm: macro có tồn tại không, chứ không phải giá trị số của nó có khác 0 không.
Thí nghiệm đặt cùng hai con số 7/3 cho compile-time và runtime để làm khác biệt rõ: macro tồn tại dù mang text 0 chọn 7; runtime flag 0 chọn else 3. Đây là hai cơ chế khác nhau.
Preprocess, elaboration và runtime
Directive bắt đầu bằng backtick và tác động tới cách compiler xử lý source. Macro được thay và conditional compilation chọn phần source trước khi process mô phỏng chạy. Parameter/localparam cấu hình theo phạm vi và elaboration; if procedural chọn statement lúc process thực thi.
Vì vậy một tín hiệu thay đổi trong simulation không thể làm phần code bị ifdef loại bỏ tự xuất hiện lại. Khi debug, xác định câu hỏi thuộc giai đoạn nào trước khi nhìn waveform. [1]
Macro được define 0 vẫn là đã định nghĩa
Source define RDVA_FEATURE thành 0 rồi khai báo feature_on. Điều kiện ifdef đúng nên module này có assign 7. Sau undef macro, feature_off dùng else và assign 3. Hai module được instantiate trong cùng TB nhưng giữ phần source đã chọn ở nơi định nghĩa.
Runtime flag cũng bằng 0; procedural if lấy else 3. Muốn kiểm một giá trị số, đừng đọc ifdef như biểu thức if. Tên macro và nội dung expansion cần được xem tách nhau. [2]
Macro là thay thế văn bản, phải giữ ngoặc
Macro an toàn của bài bọc cả argument và toàn biểu thức: ((v) + (v)). Khi dùng argument 1+2 rồi nhân 3, kết quả là 18. Macro cố ý lỗi chỉ có v + v; expansion trở thành 1 + 2 + 1 + 2 * 3, kết quả 10 theo precedence.
Không phải simulator tính nhầm phép nhân; ta đã đưa cho nó một biểu thức khác. Macro có tác dụng lặp argument cũng không nên nhận biểu thức có side effect nếu chưa xét số lần evaluation. TB chỉ dùng hằng số, không kiểm side effect.
Parameter W 5 trong TB độc lập với macro width 4. Macro không tự có kiểu, phạm vi instance hay cơ chế override giống parameter. [3]
Include guard và cleanup có mục tiêu khác nhau
Include đưa nội dung file vào chỗ include. Header config.svh được include hai lần; guard ifndef/define ngăn phần định nghĩa được đưa lại khi guard còn tồn tại. Nó không tạo package hay scope riêng cho macro.
Cuối ví dụ, các macro demo được undef để hạn chế ảnh hưởng tới source đọc tiếp. Guard bảo vệ khỏi include lặp; cleanup giới hạn phần tiếp theo còn nhìn thấy macro. Nếu undef guard rồi include lại, guard không còn ngăn lần include ấy.
Tác động giữa các file phụ thuộc compilation-unit/tool invocation; bài chỉ kiểm cấu hình pipeline đã chạy. Không suy “macro luôn global qua mọi lần compiler chạy”. [4]
Default nettype kiểm lỗi implicit net
Ví dụ dùng default_nettype none và khai báo đầy đủ dây/port. Mục tiêu là không để một số lỗi gõ tên tạo implicit wire mà không có chủ ý. Sau vùng demo, source phục hồi wire để không áp chính sách lên code tiếp theo một cách bất ngờ.
Đây không phải spell checker cho mọi identifier. Gõ nhầm sang một tên đã khai báo vẫn có thể hợp lệ nhưng sai chức năng. Cần cả compile diagnostic lẫn test dữ liệu. Các quy tắc chính xác của directive còn [5]. [6]
Đối chiếu nhánh 7/3 và biểu thức 18/10
Kỳ vọng trước chạy: defined-zero chọn 7, sau undef chọn 3, runtime-zero chọn 3; macro width 4, parameter 5; expression có ngoặc 18 và thiếu ngoặc 10.
TB assert mọi giá trị thay vì chỉ in lời “feature enabled”. Parser và Icarus đã thực chạy với header; không claim synthesis hoặc mọi tùy chọn preprocess của simulator khác. [7]
Đừng dùng macro thay mọi cấu hình có kiểu
- Define FEATURE 0 rồi mong ifdef false.
- Quên ngoặc quanh argument hoặc toàn macro biểu thức.
- Nghĩ include giống instantiate module và tự tạo scope.
- Coi include guard là cơ chế khóa phiên bản header.
- Để macro demo hoặc default_nettype ảnh hưởng source tiếp theo ngoài ý định.
- Dùng macro cho cấu hình từng instance rồi ngạc nhiên vì chúng không độc lập.
- Cho rằng compile được chứng minh đúng thứ tự ưu tiên hay đúng chức năng.
Khi cần debug, xem expansion và file list thực tế, giảm ví dụ xuống một biểu thức có expected tính tay như 18/10. Với cấu hình số theo instance, ưu tiên xem parameter phù hợp hơn không.
Tự kiểm tra
Xem code sau preprocess khi nghi macro
Hỏi macro có được định nghĩa không, expansion thành text gì, và phần text ấy được đọc trong compilation context nào. Chỉ sau đó mới phân tích process runtime.
Bài giữ draft/LRM needs-spec-check; ví dụ cố ý có macro lỗi để so sánh, không dùng macro ấy trong RTL sản phẩm.
Nguồn và mức độ đối chiếu
- Verilog Compiler Directives — bản chụp trong resources.zip, Compiler directives. Trích dẫn; nguồn đã đọc các mục liên quan.
- Verilog Compiler Directives — bản chụp trong resources.zip, ifdef/ifndef và undef. Trích dẫn; nguồn đã đọc các mục liên quan.
- Verilog Compiler Directives — bản chụp trong resources.zip, define. Trích dẫn; nguồn đã đọc các mục liên quan.
- Verilog Compiler Directives — bản chụp trong resources.zip, include và undef. Trích dẫn; nguồn đã đọc các mục liên quan.
- IEEE 1800-2023 SystemVerilog LRM, cần đối chiếu LRM. Chưa đối chiếu với văn bản nguồn (chưa mở).
- Verilog Compiler Directives — bản chụp trong resources.zip, default_nettype. Trích dẫn; nguồn đã đọc các mục liên quan.
- Thí nghiệm nguyên bản ex.a7.directives, Bằng chứng nguyên bản. Trích dẫn; nguồn đã đọc toàn văn.
- IEEE 1800-2023 SystemVerilog LRM, directives language and system task semantics. Chưa đối chiếu với văn bản nguồn (chưa mở).
- Thí nghiệm nguyên bản ex.a7.directives, Source, assertions và verification.json của TB nguyên bản. Trích dẫn; nguồn đã đọc toàn văn.
- IEEE 1800-2023 SystemVerilog LRM, Compiler directives; text macros; conditional compilation; default nettype. Chưa đối chiếu với văn bản nguồn (chưa mở).
- Verilog Compiler Directives — bản chụp trong resources.zip, define; include; ifdef/ifndef; undef; default_nettype. Trích dẫn; nguồn đã đọc các mục liên quan.
- Thí nghiệm nguyên bản ex.a7.directives, config.svh, tb_directives.sv và verification.json. Trích dẫn; nguồn đã đọc toàn văn.