Subroutine SV: ref nhìn thấy ngay, output chép khi trả về
Tiên quyết
Sau bài này bạn sẽ
- Phân biệt input copy, output copy-out và ref alias trong task có thời gian
- Dùng automatic, default và named argument với expected rõ
- Giới hạn ý nghĩa const ref vào dữ liệu được tham chiếu, không suy deep immutability
Cùng giá trị cuối chưa chứng minh cùng cách truyền
Hai task đều sửa một số rồi chờ 3 ns. Với ref, caller có thể thấy lần sửa đầu trước khi task xong; với output, caller nhận kết quả khi task trả về. Nếu chỉ đọc sau join, bạn có thể bỏ lỡ khác biệt rất quan trọng cho monitor hoặc driver.
Input copy và output copy-out là hai kênh khác nhau
Change_copy nhận original 10, tính target 12 rồi 14 với delta 2. Caller copy_value vẫn-1 tại 1 ns và thành 14 khi task xong 3 ns. Giá trị target nội bộ không tự trở thành một alias của biến caller. Hãy xem direction từng argument, không suy từ tên task. [1]
Ref trỏ vào biến của caller
Change_ref nhận ref_value10, dùng delta mặc định 1: ghi 11 ngay đầu call rồi 12 sau 3 ns. Quan sát tại 1 ns thấy 11 dù task chưa trả về. Actual phải là biến phù hợp về type/lifetime; không coi một expression bất kỳ như storage có thể ghi. [2]
Automatic là lựa chọn có ý nghĩa với ref
Task/function trong example đều automatic. Ref formal gắn với một call và một biến caller; đừng dùng static subroutine như một đường tắt để chia sẻ trạng thái giữa các caller. Main chỉ có hai task trên hai target khác nhau, không claim mọi aliasing/concurrency/lifetime edge case.
Default và named call phải được đọc tại call site
Change_ref bỏ delta nên dùng 1. Change_copy chỉ định original/target/delta theo tên nên lấy delta 2. Nếu sửa default, các call bỏ argument có thể đổi hành vi dù call site không đổi. Test kiểm cả caller dùng default và caller override; không có benchmark về overhead.
Const ref cho read-only view của array int
Function total nhận const ref array ba int 6/7/8, trả 21 và không đổi phần tử đầu 6. Probe viết values[0]=99 bị pyslang từ chối với AssignmentToConstVar. Đó là bằng chứng về direct assignment trong trường hợp này, không nói const handle sẽ deep-freeze class object hoặc tự clone transaction.
Kiểm trong lúc task đang chạy, không chỉ sau join
Observer tại 1 ns tách ref 11 với output-1; join tại 3 kiểm 12/14. Function total trong ví dụ không có timing control; task mang #3. Watchdog 10 ns bắt call không kết thúc. Không suy mọi rule về fork trong function hoặc callback phức tạp từ subset đang chạy.
Hai thời điểm quan sát và một const-ref sum
Expected trước chạy: ref 11/output-1 ở 1 ns; ref 12/output 14 ở 3 ns; constsum 21 và datafirst 6.
Verilator 2-state thực thi cả task có thời gian, default/named args và kiểm copy-out; không claim X/Z hoặc synthesis. [3]
Tự kiểm tra
Vẽ đường đọc và ghi qua argument
Chốt caller variable nào đổi, đổi lúc nào và ai sở hữu lifetime. Thử đọc trước return để phân biệt alias với copy-out. Với dữ liệu chỉ đọc, kiểm const rule bằng compiler và giữ scope claim đúng element type đang dùng.
Nguồn và mức độ đối chiếu
- SystemVerilog Functions & Tasks — bản chụp resources.zip, Value và directions. Trích dẫn; nguồn đã đọc các mục liên quan.
- SystemVerilog Functions & Tasks — bản chụp resources.zip, Reference passing. Trích dẫn; nguồn đã đọc các mục liên quan.
- Thí nghiệm nguyên bản ex.b3.subroutines, Bằng chứng. Trích dẫn; nguồn đã đọc toàn văn.
- IEEE 1800-2023 SystemVerilog LRM, subroutines procedural/package 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.b3.subroutines, Source, self-checks, metadata, verification.json và mutation probes. Trích dẫn; nguồn đã đọc toàn văn.
- IEEE 1800-2023 SystemVerilog LRM, subroutines procedural semantics. Chưa đối chiếu với văn bản nguồn (chưa mở).
- SystemVerilog Functions & Tasks — bản chụp resources.zip, Default Argument Values; Passing Arguments by Value; Passing Arguments by Reference; const ref: Reference Efficiency Without the Mutability Risk. Trích dẫn; nguồn đã đọc các mục liên quan.