Access control, extern và forward class: tổ chức API có ranh giới

Khoảng 45 phútMức 2/3Bản nháp: một số khẳng định chưa đối chiếu spec

Sau bài này bạn sẽ

  • Phân biệt local/protected với API public
  • Tách extern declaration và implementation mà giữ đúng scope
  • Dùng typedef class trước định nghĩa trong cùng source

Caller cần API thay vì sửa mọi field

Vault giữ secret và đếm updates cho derived class. Cho module sửa trực tiếp hai field làm mất ranh giới trách nhiệm. Example dùng method public để đọc secret, method derived để cập nhật counter và compiler để kiểm các truy cập bị cấm.

Local secret thuộc phần triển khai của Vault

Secret khai local và chỉ được gán trong Vault.new rồi đọc qua read_secret. Main gọi getter được 17, không đọc vault.secret trực tiếp. Derived class gọi API base cũng khác với tự truy cập member local của base.

[1]

Protected cho derived method, vẫn chặn caller ngoài

Updates khai protected. CountedVault.bump tăng nó, count trả giá trị để TB quan sát. Hai lần bump cho 2. Negative probes thử module đọc secret hoặc updates phải bị parser từ chối; không đổi member sang public chỉ để test compile.

Extern tách declaration khỏi body

Holder khai extern function int read_value();, body viết ngoài class bằng Holder::read_value. Nó vẫn là method của Holder và đọc item. Extern không tự biến method thành function tự do, không tìm source file bị thiếu hoặc thay namespace package.

Forward declaration chỉ báo tên class sẽ được định nghĩa

typedef class Data; cho Holder khai một handle Data trước khi body class Data xuất hiện. Tất cả nằm trong cùng source/file list của ví dụ. Forward declaration không tạo Data object, không cấp quyền truy cập private hoặc thay việc cung cấp định nghĩa hoàn chỉnh.

API vẫn cần chính sách cho handle chưa có object

Holder mới tạo có item=null, read_value trả sentinel-1 theo contract riêng. Sau khi gán item=new(12), method trả 12. Sentinel không phải cách biểu diễn chung của null hoặc rule ngôn ngữ; production API có thể cần status riêng để phân biệt giá trị hợp lệ.

Body ngoài class vẫn phải thực hiện đúng contract

Mutation trả item.value+1 bị symptom extern or access contract bắt. Access control không kiểm công thức hộ bạn; compiler chỉ ngăn một số truy cập bất hợp lệ. Tách kiểm quyền, null path và dữ liệu trả về.

Public API và ba phần tổ chức class

Expected trước chạy: empty-1, extern_value12, secret qua getter 17, protected_updates2. Main không claim mọi separate compilation, friend semantics hoặc mọi extern signature; negative parser probes được ghi riêng với diagnostic thực.

Access control, extern và forward class: tổ chức API có ranh giới

Expected tính trước chạy: ACCESS CHECK empty=-1 extern_value=12 local_secret=17 protected_updates=2

tb.sv testbench
`timescale 1ns/1pstypedef class Data;class Holder;  Data item;  extern function int read_value();endclassclass Data;  int value;  function new(int value);this.value=value;endfunctionendclassfunction int Holder::read_value();  if(item==null)return -1;  return item.value;endfunctionclass Vault;  local int secret;  protected int updates=0;  function new(int secret);this.secret=secret;endfunction  function int read_secret();return secret;endfunctionendclassclass CountedVault extends Vault;  function new(int secret);super.new(secret);endfunction  function void bump();updates++;endfunction  function int count();return updates;endfunctionendclassmodule tb_access;  Holder holder;  CountedVault vault;  initial begin    holder=new();    if(holder.read_value()!=-1)$fatal(1,"forward handle should start null");    holder.item=new(12);vault=new(17);vault.bump();vault.bump();    if(holder.read_value()!=12||vault.read_secret()!=17||vault.count()!=2)$fatal(1,"extern or access contract");    $display("ACCESS CHECK empty=-1 extern_value=12 local_secret=17 protected_updates=2");    $finish;  endendmodule

Đã kiểm chứng thế nào

  • Phân tích và elaborate theo LRM (pyslang 12.1.0)
  • Mô phỏng, exit 0 và output khớp kỳ vọng tính tay (Verilator 5.050, 2-state)

Output phải khớp: ACCESS CHECK empty=-1 extern_value=12 local_secret=17 protected_updates=2

Verilator 2-state, không claim X/Z hoặc synthesis.

Local/protected qua API, extern body và forward declaration cùng file; không claim mọi separate compilation hoặc mọi extern signature.

Các kiểm tra chạy lúc xây dựng nội dung (2026-11-06), không chạy trong trình duyệt. Kỳ vọng được tính tay trước khi chạy.

[2]

Tự kiểm tra

Tự kiểm tra: access

  1. Sau hai lần vault.bump, protected count qua API bằng bao nhiêu?
  2. Holder.read_value sau item=new(12) trả gì?
  3. Module có thể đọc vault.secret trực tiếp trong scope đã kiểm không?
  4. Vì sao CountedVault.bump dùng updates nhưng module đọc thẳng bị chặn?
  5. Typedef class Data trước Holder làm gì?

Ẩn dữ liệu cần bảo vệ, để API diễn đạt contract

Chọn local cho implementation detail, protected cho extension point thật sự cần ở subclass. Dùng extern/forward declaration để sắp xếp source rõ, không coi chúng là cách bỏ dependency. Test cả hành vi API và các truy cập compiler phải từ chối.

Nguồn và mức độ đối chiếu

  1. SystemVerilog local vs protected — bản chụp resources.zip, Nguồn đào tạo đã đọc. Trích dẫn; nguồn đã đọc các mục liên quan.
  2. Thí nghiệm nguyên bản ex.b5.access, Bằng chứng thực nghiệm. Trích dẫn; nguồn đã đọc toàn văn.
  3. IEEE 1800-2023 SystemVerilog LRM, Class handles, inheritance, virtual methods, access and parameterization. Chưa đối chiếu với văn bản nguồn (chưa mở).
  4. Thí nghiệm nguyên bản ex.b5.access, Source, self-checks, verification.json và mutation/capability probes. Trích dẫn; nguồn đã đọc toàn văn.
  5. SystemVerilog local vs protected — bản chụp resources.zip, Accessing a local Member From Outside the Class; Accessing a local Member From a Child Class; Accessing a protected Member From Outside the Class; Accessing a protected Member From a Child Class. Trích dẫn; nguồn đã đọc các mục liên quan.
  6. SystemVerilog 'extern' — bản chụp resources.zip, Basic Syntax. Trích dẫn; nguồn đã đọc các mục liên quan.
  7. SystemVerilog Typedef Class — bản chụp resources.zip, The Problem: A Chicken-and-Egg Reference; The Fix: Forward Declaration With typedef. Trích dẫn; nguồn đã đọc các mục liên quan.