Week 5 · Day 22 · 7 hours

Day 22 — SystemVerilog Language: Collections

Implement safe dynamic arrays, queues, associative maps, enum/struct/union models, and a packet database.

01

Concept lesson

Understand the language feature before coding

Day 22 — SystemVerilog Collections

Simulation status (28 Oct 2026): The full tb/day22_collections.sv passes on Verilator 5.052; Icarus Verilog 12 runs only the tb/day22_collections_icarus.sv subset. Details: Week 5 validation record (VALIDATION.md).

Schedule: 2h theory + 2h guided + 2h independent + 1h debug. Deliverable: SV collections utility.

Choose a collection by its access pattern

Collection Use it when Boundary to check
Fixed unpacked array The number of elements is known and stable. The declared index range may not start at zero.
Dynamic array The size is decided or changed at run time. Allocate before indexing; check size() after resize or delete.
Queue Items are added and removed in order, such as expected transactions. Check size() before indexing or popping an empty queue.
Associative array Sparse keys need direct lookup, such as address-to-value state. Use exists(key) before treating a missing entry as valid data.

Packed dimensions form one bit vector; unpacked dimensions hold separate elements. A packed struct is useful when fields form one bit-level record, while an unpacked array or queue is useful when the testbench needs a collection of records. Prefer foreach when iterating declared dimensions, and guard collection methods whose result depends on an empty or missing element. The exercises below demonstrate these operations; they are not a claim that every simulator supports every collection method.

Workspace

project_workspace/week5_systemverilog/day22_collections

Guided (1–5)

  1. Dynamic array allocation/resizing.
  2. Queue push/pop/insert/delete.
  3. Queue search/sort.
  4. Associative address map.
  5. foreach traversal.

Independent (6–11)

  1. enum opcode; 7. struct packet; 8. union storage; 9. reductions; 10. transaction queue; 11. scoreboard-style associative store.

Additional XLS lab catalog

20 exercises are enumerated in WEEK5_DAY22_LAB_CATALOG including dynamic delete, queue reverse, associative exists/delete, array min/max, unique/find, and empty-queue debug. These are requirements; the supplied demonstration is not proof that all 20 are executed.

Demo

Run .venv/bin/python scripts/check_week5_simulator.py --simulator iverilog --run for the Icarus-compatible queue/packed-struct subset. Icarus does not support all dynamic-array, associative-array and array-ordering features in the full tb/day22_collections.sv. Run the full exercise on Verilator 5: verilator --binary --timing --top-module day22_collections tb/day22_collections.sv -o day22_sim, then ./obj_dir/day22_sim. Capture version, compilation log, PASS/FAIL output and debug evidence.

Debug

Show unsafe empty-queue access, then correct it with size() guard; document index-range checks for dynamic arrays.

Boundary

No UVM, SVA, constrained random or Week 6 interfaces.

02

Visual explanation

Connect syntax with simulator behavior

SystemVerilog collections: Dynamic array: new[N], resize; Queue: push_back / pop_front; Associative array: index by key / exists
SystemVerilog collections
Iteration and array methods: foreach(collection[i]); find / sort / unique where supported; Guard empty queue and missing keys
Iteration and array methods
03

Worked example

Read and run the supplied SystemVerilog source

Example source · Day 22
module day22_collections;
  typedef enum int {OP_READ=0, OP_WRITE=1} opcode_t;
  typedef struct packed {logic [7:0] addr; logic [7:0] data;} packet_t;
  typedef union packed {logic [15:0] raw; packet_t packet;} packet_union_t;
  int dyn[];
  int q[$];
  int address_map[int];
  packet_t transactions[$];
  packet_union_t u;
  int errors=0;
  initial begin
    dyn = new[3]; foreach (dyn[i]) dyn[i] = i+1;
    dyn = new[5](dyn);
    if (dyn.size()!=5 || dyn[0]!=1) errors++;
    dyn.delete(); if (dyn.size()!=0) errors++;
    q.push_back(3); q.push_front(1); q.insert(1,2);
    if(q.size()!=3 || q[1]!=2) errors++;
    q.sort(); if(q[0]!=1 || q[2]!=3) errors++;
    if(q.size()>0) void'(q.pop_front());
    if(q.size()>0) void'(q.pop_front());
    if(q.size()>0) void'(q.pop_front());
    if(q.size()!=0) errors++;
    if(q.size()==0) $display("EMPTY_QUEUE_GUARD PASS");
    else errors++;
    address_map[32'h1000] = 42;
    if(!address_map.exists(32'h1000) || address_map[32'h1000]!=42) errors++;
    foreach(address_map[key]) $display("MAP[%0d]=%0d",key,address_map[key]);
    address_map.delete(32'h1000);
    if(address_map.exists(32'h1000)) errors++;
    transactions.push_back('{addr:8'h10,data:8'hA5});
    if(transactions.size()!=1 || transactions[0].data!=8'hA5) errors++;
    u.raw=16'h1234;
    if(u.packet.addr!=8'h12) errors++;
    if(errors==0) $display("DAY22 PASS");
    else $fatal(1,"DAY22 FAIL errors=%0d",errors);
    $finish;
  end
endmodule

Compile and run

  1. mkdir -p sim logs
  2. verilator --binary --timing --top-module day22_collections tb/day22_collections.sv -o day22_sim
  3. ./obj_dir/day22_sim | tee logs/day22.log

What to verify

  • dynamic allocate/resize/delete
  • queue push/pop/insert/delete
  • queue sort/search
  • associative map exists/delete
  • foreach
  • enum/struct/union
  • reductions
  • transaction queue
  • scoreboard store
  • empty queue guard

Pass condition: Simulation terminates with PASS, zero errors and explicit empty-queue guard evidence.

04

Hands-on practice

Complete the exercises in order

    Written assignment

    1. Explain dynamic-array resize and preservation of elements.
    2. Compare queue and associative-array lookup semantics.
    3. Show empty-queue guard with failing and corrected behavior.
    4. Provide transaction database output, simulator command and limitations.

    Debug challenge

    Detect and handle empty-queue and out-of-range access; build packet database utility.

    Completion criteria

    Eleven daily-plan activities plus 20 XLS SystemVerilog lab mappings documented; guarded queue and packet database demonstrated.

    05

    Knowledge check

    Check your understanding

    How is a dynamic array resized while retaining existing elements?

    Use new[new_size](old_array) to copy existing elements into resized storage.

    Why check queue size before pop_front()?

    An empty queue has no valid element to remove; guard with size() > 0.

    How do you check whether an associative-array key exists?

    Use array.exists(key) before reading or deleting that key.

    How do packed structs differ from unpacked structs?

    Packed structs have contiguous packed bit representation; unpacked structs are collections of separately typed members.

    When is a queue preferable to a dynamic array?

    When elements are frequently inserted or removed at either end.

    Why is an associative array useful for a sparse address model?

    It allocates entries only for keys that are used.

    Evidence to retain

    • SV sources
    • simulator/version compatibility matrix
    • PASS/FAIL log
    • packet database output
    • debug before/after