Event scheduling: cùng timestamp chưa chắc cùng giá trị

Khoảng 35 phútMức 3/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 simulation time với các lượt xử lý event trong một time slot
  • Dự đoán phép đọc Active, sau #0 và khi $strobe xuất dữ liệu
  • Giải thích NBA có thể đánh thức process khác ngay trong cùng timestamp
  • Nêu đúng phạm vi của mô hình Verilog module trước khi học các SV region khác

Timestamp giống nhau, ảnh chụp khác nhau

Bạn thấy hai dòng log đều ghi t=5 nhưng q lần lượt bằng 0 và 3. Chưa thể kết luận simulator sai hoặc q đã đổi trong thời gian âm. Một timestamp có thể chứa nhiều lượt thực thi process và cập nhật tín hiệu; mỗi lần đọc nằm ở một điểm khác nhau trong lượt xử lý đó.

Hãy tưởng tượng danh sách công việc ở t=5: thực thi process, đưa một phép ghi vào hàng đợi, xử lý phép ghi ấy rồi đánh thức process nhạy với tín hiệu vừa đổi. Những công việc này có thể hoàn tất mà đồng hồ mô phỏng vẫn ghi 5 ns. Đây là mô hình thực thi mô phỏng; nó không cho ta propagation delay của silicon. [1]

Đổi giá trị và đánh thức process

Trong thí nghiệm, q ban đầu 0. Khi NBA cập nhật q thành 3, sự thay đổi đánh thức always @(q). Process này đọc q mới và lên lịch follower <= q + 4'd1, nên follower cuối cùng thành 4.

Tách hai việc: update làm giá trị thay đổi; evaluation cho process chạy và có thể tạo update tiếp theo. Không phải mỗi lần một statement chạy đều tạo một cạnh tín hiệu. Nếu q được gán lại cùng giá trị, không được mặc định nó đánh thức @(q) thêm một lần chỉ vì có một statement gán. [2]

Ở TB này ta đếm đúng một lần thức dậy tại t=5. Không suy từ đó rằng mọi mạch tổ hợp đều chỉ cần một lượt xử lý hoặc mỗi timestamp có số lượt cố định.

Bốn điểm quan sát cho module process

Đối với các process nằm trong module của ví dụ, dùng sơ đồ đọc sau:

Active: chạy statement, đọc RHS, $display
   -> xử lý continuation sau #0 (Inactive)
   -> cập nhật NBA
   -> process được đánh thức có thể tạo công việc tiếp
   -> $strobe xuất giá trị cuối time slot

Sơ đồ có vòng quay lại, không phải bốn pha chỉ đi qua đúng một lần. Nguồn Verilog gọi điểm xuất $strobe/$monitor là Monitor; trong thuật ngữ SystemVerilog nó liên quan Postponed. Bài chỉ dùng những thao tác module đã kiểm, không xem bốn nhãn này là toàn bộ hệ scheduling SV. [3]

Các region cho assertion, program và clocking block cần học riêng. Thứ tự và thuật ngữ chuẩn đầy đủ còn [4].

Lấy RHS trước, cập nhật LHS sau

Tại t=5, process chính thực hiện q <= 4'd3. Nó đã đi qua statement và lên lịch ghi 3, nhưng câu kế tiếp active_sample = q vẫn lấy 0. $display ngay sau đó cũng thấy q 0, follower 1.

Đừng suy ra nonblocking “chưa chạy câu lệnh”. Phần lên lịch đã chạy; phần cập nhật LHS đang chờ. Trong bài timing control, sự tách biệt này còn giúp giải thích delayed NBA không chặn writer.

Giá trị khởi tạo đã ổn định từ t=0, không có writer thứ hai ghi q ở t=5. Phạm vi đó làm phép đọc này xác định; thêm một blocking writer cạnh tranh sẽ đổi bài toán. [5]

Vì sao #0 vẫn đọc giá trị cũ?

Ngay sau phép đọc Active, TB gặp #0 rồi đọc q vào inactive_sample. Delay bằng 0 không tiến simulation time; continuation được bố trí sau công việc Active đang xét nhưng trước NBA đang chờ. Kết quả vẫn q 0, follower 1 tại t=5.

Vậy hai lần đọc 0 không có nghĩa q sẽ giữ 0 suốt timestamp. Cũng không thể thêm nhiều #0 rồi mặc định có một hàng rào chờ mọi NBA. Cần chỉ rõ producer cập nhật ở đâu và consumer cần giá trị trước hay sau cập nhật. [6]

NBA chưa phải dấu chấm hết của time slot

Sau hai lần đọc, q nhận 3 ở NBA. always @(q) thức dậy ngay tại t=5, đọc 3, tính 4 và lên lịch NBA cho follower. Đến lúc $strobe xuất dữ liệu, cả q 3 và follower 4 đều đã ổn định trong thí nghiệm này.

Nếu dùng một danh sách đơn giản “Active xong một lần → NBA xong một lần → tăng thời gian”, bạn sẽ bỏ sót process được q đánh thức và lần cập nhật follower. TB kiểm cả wakeups=1 lẫn awakened_at=5, không chỉ nhìn dữ liệu cuối. [7]

Đây là một chuỗi hữu hạn. Một mô hình có vòng lặp zero-time không hội tụ có thể không tiến tới timestamp tiếp theo; không nên coi scheduler như bảo đảm mọi code đều kết thúc.

Dự đoán rồi kiểm tại 5 và 6 ns

Kỳ vọng được viết trước khi chạy:

t5 Active       q0 follower1
t5 sau #0       q0 follower1
t5 khi strobe   q3 follower4
t6 assertion    q3 follower4, một wakeup tại t5

Một timestamp, nhiều lượt xử lý event

Đối chiếu Active/#0/NBA/$strobe và NBA đánh thức process rồi lên lịch NBA tiếp, bằng TB nguyên bản.

tb_regions.sv testbench
module tb_regions;  timeunit 1ns;  timeprecision 1ps;  reg [3:0] q = 0, follower = 1;  reg [3:0] active_sample, inactive_sample;  int wakeups = 0, awakened_at = -1;   // A q NBA update wakes this module process in the same time slot.  // It schedules another NBA; no simulation-time delay is required.  always @(q) begin    if ($time == 5) begin      wakeups = wakeups + 1;      awakened_at = int'($time);      follower <= q + 4'd1;    end  end   initial begin    #5;    q <= 4'd3;    active_sample = q;    if (active_sample !== 0 || follower !== 1)      $fatal(1, "active read unexpectedly saw NBA data");    $display("REGION ACTIVE at=%0d q=%0d follower=%0d", int'($time), q, follower);    #0;    inactive_sample = q;    if (inactive_sample !== 0 || follower !== 1)      $fatal(1, "inactive read unexpectedly saw NBA data");    $display("REGION INACTIVE at=%0d q=%0d follower=%0d", int'($time), q, follower);    $strobe("REGION STROBE at=%0d q=%0d follower=%0d", $time, q, follower);    #1; // Assert after the entire t5 slot, not at another active read at t5.    if (q !== 3 || follower !== 4 || wakeups != 1 || awakened_at != 5 ||        active_sample !== 0 || inactive_sample !== 0)      $fatal(1, "NBA re-entry or captured values mismatch");    $display("REGION CHECK at=%0d q=%0d follower=%0d wakeups=%0d awakened_at=%0d",             int'($time), q, follower, wakeups, awakened_at);    $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 (Icarus Verilog 11.0, 4-state)

Output phải khớp: REGION ACTIVE at=5 q=0 follower=1REGION INACTIVE at=5 q=0 follower=1REGION STROBE at=5 q=3 follower=4REGION CHECK at=6 q=3 follower=4 wakeups=1 awakened_at=5

Chỉ các module process/delay/NBA/system task đã viết; không kiểm đủ SystemVerilog regions, assertions, program hoặc clocking block.

Không suy ra độ trễ silicon, số delta cố định, synthesis hoặc hiệu năng scheduler.

$strobe được kiểm qua output kỳ vọng; các giá trị ổn định và số lần thức dậy còn có assertion tại t 6.

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.

$strobe được gọi ở t=5 và xuất giá trị cuối slot ấy. Assertion t=6 kiểm dữ liệu ổn định, hai sample đã lưu và số lần thức dậy. Chờ 1 ns ở checker là bố trí riêng để quan sát sau slot đang thử; nó không phải bản sửa race cho RTL hoặc công thức chờ mọi DUT.

Parser và Icarus chạy code này; output thực nằm trong bằng chứng. Không claim synthesis, waveform trích xuất hoặc hỗ trợ mọi SV region. [8]

Giới hạn của mô hình và cách đọc log

  • Chỉ ghi timestamp rồi cho rằng mọi log ở thời điểm đó nhìn cùng state.
  • Đọc ngay sau <= và mong thấy LHS mới.
  • Dùng #0 làm cách chờ NBA tổng quát.
  • Quên rằng NBA có thể đánh thức process, tạo thêm công việc trong cùng timestamp.
  • Dùng thứ tự khai báo hai always để suy ra thứ tự thực thi.
  • Gọi mọi lượt event là một delay vật lý hay một chu kỳ clock.
  • Áp dụng sơ đồ module này nguyên xi cho concurrent assertion hoặc clocking block chưa học.

Khi debug, ghi thêm tín hiệu vừa đọc, statement đọc và điểm quan sát. $strobe hữu ích để in cuối slot; bản thân một dòng in không thay cho assertion kiểm yêu cầu thiết kế.

Tự kiểm tra

Tự kiểm tra: event scheduling

  1. Trong TB, q ban đầu 0. Tại t 5 thực hiện q<=3 rồi #0; sample=q. Sample bằng gì?
  2. $strobe của TB tại t 5 xuất cặp q/follower nào?
  3. Process always@(q) của thí nghiệm ghi awakened_at bằng bao nhiêu?
  4. Sau q<=3, tại sao câu active_sample=q trong cùng process vẫn lấy 0?
  5. Từ kết quả thí nghiệm, có thể kết luận điều gì?

Ghi cả thời gian lẫn điểm quan sát

Trước một kết quả bất ngờ, hỏi ba việc: statement nào lấy dữ liệu, phép ghi nào còn đang chờ, và thay đổi đó đánh thức process nào tiếp theo. Cùng t=5, TB đọc 0 rồi in 3 là phù hợp với chuỗi event đã thử.

Mô hình và nguồn đào tạo giúp suy luận; bằng chứng chỉ phủ code đã chạy. Bài giữ draft và LRM needs-spec-check cho tới khi đối chiếu đặc tả.

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

  1. Verilog Scheduling Semantics — bản chụp trong resources.zip, Event Queue. Trích dẫn; nguồn đã đọc các mục liên quan.
  2. Verilog Scheduling Semantics — bản chụp trong resources.zip, Event Types. Trích dẫn; nguồn đã đọc các mục liên quan.
  3. Verilog Scheduling semantics — bản chụp trong resources.zip, Phân loại event trong tài liệu Verilog. Trích dẫn; nguồn đã đọc các mục liên quan.
  4. 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ở).
  5. Verilog Scheduling Semantics — bản chụp trong resources.zip, Active và NBA. Trích dẫn; nguồn đã đọc các mục liên quan.
  6. Verilog Scheduling semantics — bản chụp trong resources.zip, Inactive events. Trích dẫn; nguồn đã đọc các mục liên quan.
  7. Verilog Scheduling Semantics — bản chụp trong resources.zip, Vòng xử lý event. Trích dẫn; nguồn đã đọc các mục liên quan.
  8. Thí nghiệm nguyên bản ex.a7.scheduling, Thí nghiệm nguyên bản. Trích dẫn; nguồn đã đọc toàn văn.
  9. IEEE 1800-2023 SystemVerilog LRM, Scheduling semantics; module Active/Inactive/NBA; postponed observation. Chưa đối chiếu với văn bản nguồn (chưa mở).
  10. Thí nghiệm nguyên bản ex.a7.scheduling, inactive_sample assertion và REGION INACTIVE. Trích dẫn; nguồn đã đọc toàn văn.
  11. Thí nghiệm nguyên bản ex.a7.scheduling, REGION STROBE và t6 assertions. Trích dẫn; nguồn đã đọc toàn văn.
  12. Thí nghiệm nguyên bản ex.a7.scheduling, awakened_at=5 và wakeups=1. Trích dẫn; nguồn đã đọc toàn văn.
  13. Thí nghiệm nguyên bản ex.a7.scheduling, active_sample assertion và REGION CHECK. Trích dẫn; nguồn đã đọc toàn văn.
  14. Thí nghiệm nguyên bản ex.a7.scheduling, meta.yaml limitations và verification.json. Trích dẫn; nguồn đã đọc toàn văn.
  15. IEEE 1800-2023 SystemVerilog LRM, Scheduling semantics; Active/Inactive/NBA/Postponed regions; determinism. Chưa đối chiếu với văn bản nguồn (chưa mở).
  16. Verilog Scheduling Semantics — bản chụp trong resources.zip, Event Types; Event Queue; Event Processing Flow. Trích dẫn; nguồn đã đọc các mục liên quan.
  17. Verilog Scheduling semantics — bản chụp trong resources.zip, Event Simulation; Active/Inactive/NBA/Monitor events; Nondeterminism. Trích dẫn; nguồn đã đọc các mục liên quan.
  18. Thí nghiệm nguyên bản ex.a7.scheduling, tb_regions.sv và verification.json: Active/#0/NBA re-entry/$strobe. Trích dẫn; nguồn đã đọc toàn văn.