Randomize và constraints: inside, dist, implication, inline with

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

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

  • Tính tập nghiệm trước khi chạy solver
  • Kiểm nhiều constraint cùng áp dụng và inline pinning không thay hard constraint
  • Phân biệt randomize thất bại với một mẫu mới hợp lệ

Tập hợp hợp lệ phải có trước lời gọi randomize

Rectangle có width/height 4 bit. Hai kích thước được giới hạn 1..4 và tích không quá 6. Trước khi dùng solver, hãy liệt kê những hình chữ nhật hợp lệ: một thông báo randomize thành công chưa cho biết hợp đồng của test đã viết đúng.

Constraint là điều kiện, không phải lệnh gán

Các hard constraint đang bật phải cùng đúng. Block dimensions và area_limit được giải cùng nhau; thứ tự viết không làm block sau ghi đè block trước. Bài dùng quan hệ số học nguyên bản, không đưa thêm quy tắc protocol hoặc coi ví dụ là đặc tả bus.

[1]

Đếm giao của hai miền thay vì cộng hai điều kiện

Width 1 cho height 1..4; width 2 cho 1..3; width 3 cho 1..2; width 4 chỉ height 1. Tổng 4+3+2+1=10 cặp. Constraint không yêu cầu solver sinh theo thứ tự bảng này hoặc mỗi cặp có cùng tần suất trong một mẫu nhỏ.

Width của biểu thức vẫn ảnh hưởng cả solver lẫn checker

Area_limit dùng intcast trước multiplication để phép tính không vô tình bị giới hạn trong width 4 bit. TB kiểm theo bảng chiều cao hợp lệ theo từng width, không dùng output DUT để tạo expected. Vấn đề width trong B1 vẫn áp dụng dù biểu thức nằm trong constraint.

Inline pinning bổ sung điều kiện cho một call

Main ép từng cặp width/height bằng inline with và local qualifier, quét đủ 256 cặp của miền 4 bit. Đúng 10 cặp phải thành công và 246 cặp phải thất bại. Inline không ghi đè dimensions; yêu cầu width 0 vẫn không hợp lệ dù call đã chỉ định nó.

Return 0 không phải một mẫu mới

Trước mỗi pinned call, main đặt hai field thành 9. Với 246 call vô nghiệm, cả hai field phải giữ 9; TB không gửi chúng như dữ liệu hợp lệ chỉ vì đã gọi randomize. Sau đó 64 call bình thường đều phải thoả oracle, không yêu cầu một histogram cụ thể.

Kiểm đủ tập nghiệm và phép inside dùng trong quiz

Expected trước chạy: 256 pin,10 accept/246 reject,64 sample hợp lệ,246 failure giữ field; thêm 64 địa chỉ 0..63 kiểm inside 0..60 và căn 4, có 16 giá trị được chọn. Phần địa chỉ chỉ là bài toán số học, không khẳng định quy tắc bus. Hai question ID cũ được giữ nguyên nghĩa để bảo toàn lịch sử làm bài.

Constraint: inside, dist, implication, inline with

Expected tính trước chạy: CONSTRAINT CHECK pinned=256 accepted=10 rejected=246 sampled=64 unchanged_on_failure=246 aligned=16

tb.sv testbench
`timescale 1ns/1psclass Rectangle;  rand bit[3:0] width,height;  constraint dimensions {width inside {[1:4]};height inside {[1:4]};}  constraint area_limit {int'(width)*int'(height)<=6;}endclassmodule tb_constraints;  Rectangle shape;  int wi,hi,result,accepted=0,rejected=0,sampled=0,aligned=0;  bit legal;  function automatic bit oracle(input int w,h);    return (w==1&&h>=1&&h<=4)||(w==2&&h>=1&&h<=3)||(w==3&&h>=1&&h<=2)||(w==4&&h==1);  endfunction  initial begin    shape=new();shape.srandom(53);    for(wi=0;wi<16;wi++)for(hi=0;hi<16;hi++)begin      legal=oracle(wi,hi);shape.width=9;shape.height=9;      result=shape.randomize() with {width==local::wi;height==local::hi;};      if(result!=int'(legal))$fatal(1,"constraint legal-set oracle w=%0d h=%0d",wi,hi);      if(result)begin        if(int'(shape.width)!=wi||int'(shape.height)!=hi)$fatal(1,"inline pin ignored");accepted++;      end else begin        if(shape.width!=9||shape.height!=9)$fatal(1,"failed randomization changed fields");rejected++;      end    end    repeat(64)begin      if(!shape.randomize())$fatal(1,"normal randomization failed");      if(!oracle(int'(shape.width),int'(shape.height)))$fatal(1,"sample outside legal set");sampled++;    end    for(int address=0;address<64;address++)begin      bit selected;      selected=(8'(address) inside {[8'h00:8'h3c]})&&((address&3)==0);      if(selected!=(address<=60&&address%4==0))$fatal(1,"inside/alignment oracle");      if(selected)aligned++;    end    if(aligned!=16)$fatal(1,"inside/alignment accounting");    if(accepted!=10||rejected!=246||sampled!=64)$fatal(1,"constraint accounting");    $display("CONSTRAINT CHECK pinned=256 accepted=10 rejected=246 sampled=64 unchanged_on_failure=246 aligned=16");    $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: CONSTRAINT CHECK pinned=256 accepted=10 rejected=246 sampled=64 unchanged_on_failure=246 aligned=16

Verilator 2-state với SMT solver; không claim X/Z hoặc synthesis.

256 pin đầy đủ 4 bit dimensions,10 legal/246 illegal,64 normal samples và 64 alignment arithmetic cases. UNSATCONSTR dự kiến cho vô nghiệm; không claim dist+inline supported, fairness hoặc protocol compliance.

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]

Dist là trọng số, còn hỗ trợ tool phải được đo riêng

Dist không thay hard legality. Repo đã ghi hạn chế lịch sử của Verilator 5.050 khi ghép dist và inline trên cùng field trong docs/toolchain.md; đây không phải yêu cầu LRM hay một phép đo vừa chạy lại. Ví dụ chính dùng inside/hard constraints, không gọi dist+inline unsupported là đã simulated. Code APB cũ chỉ giữ nguyên làm regression, không được nâng trạng thái hoặc dùng để nghiên cứu protocol mới.

Giữ nguyên embed cũ bên dưới để tài nguyên hiện có không biến mất khỏi bài. Source, expected và proof của nó không đổi; phần phát triển mới dùng Rectangle ở section code.

Transaction APB ngẫu nhiên có ràng buộc

inside, dist, implication và inline with; kiểm tra mọi mẫu thoả ràng buộc và tỉ lệ dist xấp xỉ 3:1.

tb_rand.sv testbench
class apb_txn;  rand bit       write;  rand bit [7:0] addr;  rand bit [31:0] data;  constraint c_addr { addr inside {[8'h00:8'h3C]}; addr[1:0] == 2'b00; }  // word-aligned, 16 thanh ghi  constraint c_rw   { write dist {1 := 3, 0 := 1}; }                        // 75% write  constraint c_data { !write -> data == 0; }                                // read: data không quan trọng → 0endclass module tb_rand;  initial begin    automatic apb_txn t = new;    automatic int writes = 0, bad = 0;    repeat (400) begin      if (!t.randomize()) bad++;      if (t.addr > 8'h3C || t.addr[1:0] != 2'b00 || (!t.write && t.data != 0)) bad++;      writes += t.write;    end    if (!t.randomize() with { addr == 8'h10; }) bad++;                 // inline: không ràng buộc biến có dist    if (t.addr != 8'h10 || (!t.write && t.data != 0)) bad++;    $display("RAND RESULT writes=%0d/400 violations=%0d", writes, bad);    $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: violations=0writes=(2[6-9][0-9]|3[0-3][0-9])/400

Verilator cần SMT solver (Z 3) lúc chạy; phân phối ngẫu nhiên phụ thuộc solver/seed.

Verilator 5.050 chọn bucket của dist TRƯỚC rồi mới giải, không quay lui: thêm ràng buộc inline lên chính biến có dist (vd with { write == 0; }) làm randomize() fail ~75% (đo 143/200). Không dùng Verilator để minh hoạ tổ hợp này.

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.

Tự kiểm tra

Tự kiểm tra: constraints

  1. Với constraint !write -> data == 0;, khi write = 1 thì data bị ràng buộc thế nào?
  2. Giá trị addr nào thoả c_addr = { addr inside {[8'h00:8'h3C]}; addr[1:0] == 2'b00; } ?

    Chọn tất cả đáp án đúng.

  3. Width/height 1..4, area không quá 6 có bao nhiêu cặp hợp lệ?
  4. Main đặt field 9/9 rồi pin một cặp vô nghiệm. Return và fields phải thế nào?
  5. 64 sample hợp lệ trong main chứng minh gì về histogram?

Dùng oracle tập nghiệm để debug constraint

Liệt kê miền, width và giao các điều kiện; kiểm return của mỗi call trước khi dùng field. Với miền nhỏ hãy pin mọi điểm để kiểm cả legal/illegal, rồi thêm sample bình thường. Giữ scope của source, solver và đặc tả tách rõ; parse hoặc compile được chưa chứng minh solver sinh đúng.

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

  1. SystemVerilog Constraint Blocks — bản chụp resources.zip, Nguồn đào tạo đã đọc theo section. Trích dẫn; nguồn đã đọc các mục liên quan.
  2. Thí nghiệm nguyên bản ex.b6.constraints, 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 randomization and constraint expressions. Chưa đối chiếu với văn bản nguồn (chưa mở).
  4. ChipVerify — SystemVerilog tutorial, §8 Constraints. Trích dẫn; nguồn mới xem mục lục. danh mục chủ đề
  5. Thí nghiệm nguyên bản ex.b6.constraints, Source, self-checks, verification.json và mutation probes. Trích dẫn; nguồn đã đọc toàn văn.
  6. IEEE 1800-2023 SystemVerilog LRM, Class randomization, constraint expressions and randomization methods. Chưa đối chiếu với văn bản nguồn (chưa mở).
  7. SystemVerilog Constraint Blocks — bản chụp resources.zip, Syntax; Multiple Constraint Blocks; How the Solver Handles Multiple Blocks. Trích dẫn; nguồn đã đọc các mục liên quan.
  8. SystemVerilog Constraint 'inside' — bản chụp resources.zip, Used in Constraints; Inverted inside. Trích dẫn; nguồn đã đọc các mục liên quan.
  9. Kết quả thực nghiệm toolchain của dự án (docs/toolchain.md), Hạn chế dist+inline đã ghi trong docs/toolchain.md. Trích dẫn; nguồn đã đọc toàn văn.