Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutContactPrivacyTerms
Skip to lesson

Course contents

  • Start Here4
  • UVM Foundations14
  • UVM Phases & Simulation Lifecycle26
  • Factory & Configuration15
  • Transaction-Level Modeling (TLM)13
  • UVM Sequences & Stimulus21
  • UVM Agents & Protocol VIP21
  • Environment & Test Classes11
  • Checking & Coverage in UVM21
  • UVM Register Abstraction Layer (RAL)22
  • Advanced UVM in Practice13
  • Debug & Regression10
  • Coding Practice47
  • Verification in Industry Practice10
  • Senior Prep: Architecture, Leadership and Interviews32
    • Verification Architecture and Planning
    • UVM with SVA and Formal
    • Leadership and Senior Judgment
    • Interview Bank
      • Concept Round: Phases, Objections and End of Test
      • Concept Round: Factory and config_db
      • Concept Round: TLM and Analysis
      • Concept Round: Sequences, Sequencers and Drivers
      • Concept Round: Agents, Drivers and Monitors
      • Concept Round: Register Layer and Checking
      • Closure and Sign-off Questions
      • Behavioural Round
      • Coding Round: Whiteboard Drills
      • Debug Round: Find the Bug in This Log
      • Architecture Round: Design the Verification
      • High-Frequency Question Index
      • The Senior DV Interview Loop
Loading lesson

‹Interview Bank
  1. Topics
  2. UVM Verification
  3. Senior Prep: Architecture, Leadership and Interviews
  4. Interview Bank
  5. Coding Round: Whiteboard Drills

Part 13/Senior PrepIntermediate

Coding Round: Whiteboard Drills

Scoreboard, monitor, driver loop, register adapter and virtual sequence in 20 minutes each: what to write, what to say, and the bugs interviewers plant.

On this page

    The interviewer slides the marker across. Here is a stream DMA: words come in, each one is XORed with a key register, words go out. Write me the scoreboard. Twenty minutes. Ten minutes later you have a tidy class with a queue and a compare. Then the questions start. What happens when an output word arrives with nothing expected? When the test ends with words still in flight? When the test sends nothing at all? How would a colleague extend this through a factory override? The code compiled in your head. It just did not answer any of the questions that decide the grade.

    This lesson covers the five pieces senior coding rounds ask for most: a scoreboard, a monitor, a driver loop, a register adapter and a virtual sequence. For each one: what to write in twenty minutes, what to say while you write, and the bugs interviewers plant or wait for you to make. The reference solutions are the real classes from the course bench, compiled and run by every test in this course. When you can produce them from memory, practise against the clock in UVM Coding Practice.

    The idea: the whiteboard grades decisions, not syntax

    A driving examiner already knows you can turn the wheel. They watch your mirror checks, your speed at junctions and what you do when a child runs out. A coding interviewer already knows you can write a class. They watch for the decisions: where the expected value comes from, what happens at the edges (empty queue, end of test, reset), whether the protocol handshake is right, and whether you say why as you go. A missing semicolon is forgiven at once. A scoreboard that predicts from the stimulus sequence is not.

    So narrate. Say the contract before you write the code ("this monitor publishes one new item per accepted beat"), write the skeleton, fill the core, then spend the last minutes on the edges and on naming what you left out. The Whiteboard Delivery Framework drills that rhythm.

    Flowchart of a 20-minute drill: restate and ask questions, write the skeleton, fill the core logic, handle edges and errors, then name what was left out.
    Twenty minutes in five slices. The edges slice is where the grade is decided, so protect it.

    Drill

    Write in 20 minutes

    Say while writing

    Bugs interviewers plant

    Scoreboard

    Three inputs, a prediction queue, in-order compare, end-of-test checks

    "Predict from observed traffic, never from the sequence"

    Non-virtual write, != on four-state data, pop from an empty queue, no empty-test check

    Monitor

    vif from config_db, clocking-block sampling, handshake-qualified capture, new item per beat

    "Fresh object every time; monitors never raise objections"

    One reused item, sampling on VALID alone, sampling outside the clocking block

    Driver loop

    Reset wait, get_next_item, hold VALID until READY, item_done exactly once

    "item_done on every path, with no argument unless someone reads responses"

    Missing item_done on a drop path, VALID dropped without READY, item_done(req)

    Reg adapter

    Constructor, reg2bus, bus2reg with read data and status

    "provides_responses is 0 because the driver fills the request"

    Reads returning the write-data field, status always OK, no constructor

    Virtual sequence

    Handles to agent sequencers, fork of parallel children, interrupt handler with grab

    "No virtual sequencer needed; the test hands me the handles"

    No stop for the background poller, no ungrab, join_none then return

    Drill 1: the scoreboard predicts from what the bus saw

    Write three inputs, because the expected output depends on two things the bench observes: the KEY register write on APB and each input word on the stream. Each input word becomes a prediction, data ^ key, on a queue; each output word pops the oldest prediction and compares. Then two end-of-test checks that most candidates forget: words still expected, and nothing compared at all. The three uvm_analysis_imp_decl(_apb), (_in) and (_out) lines sit above the class in the bench; mention them as you draw the inputs.

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    // snippet: from the course DMA bench
    // Predicts every output word from the input word and the KEY register the
    // DUT was programmed with, then compares in order. The write_* methods are
    // virtual so a derived scoreboard (a factory override) can extend them.
    class dma_scoreboard extends uvm_scoreboard;
      `uvm_component_utils(dma_scoreboard)
      uvm_analysis_imp_apb #(apb_item,  dma_scoreboard) apb_export;
      uvm_analysis_imp_in  #(axis_item, dma_scoreboard) in_export;
      uvm_analysis_imp_out #(axis_item, dma_scoreboard) out_export;
    
      bit [31:0]   key;
      bit [31:0]   expected[$];
      int unsigned n_match, n_mismatch;
    
      function new(string name, uvm_component parent);
        super.new(name, parent);
        apb_export = new("apb_export", this);
        in_export  = new("in_export", this);
        out_export = new("out_export", this);
      endfunction
    
      virtual function void write_apb(apb_item t);
        if (t.write && !t.slverr && t.addr == KEY) key = t.data;
      endfunction
    
      virtual function void write_in(axis_item t);
        expected.push_back(t.data ^ key);
      endfunction
    
      virtual function void write_out(axis_item t);
        bit [31:0] exp;
        if (expected.size() == 0) begin
          `uvm_error("SB_UNEXP", $sformatf("output word %08h with nothing expected", t.data))
          n_mismatch++;
          return;
        end
        exp = expected.pop_front();
        if (t.data !== exp) begin
          `uvm_error("SB_MISMATCH", $sformatf("expected %08h, got %08h", exp, t.data))
          n_mismatch++;
        end else begin
          n_match++;
        end
      endfunction
    
      function void check_phase(uvm_phase phase);
        if (expected.size() != 0)
          `uvm_error("SB_LEFTOVER", $sformatf("%0d expected word(s) never came out", expected.size()))
        if (n_match == 0)
          `uvm_error("SB_EMPTY", "no words were compared: the test checked nothing")
      endfunction
    
      function void report_phase(uvm_phase phase);
        `uvm_info("SB", $sformatf("%0d words matched, %0d mismatched", n_match, n_mismatch), UVM_LOW)
      endfunction
    endclass
    • Say: "KEY comes from the APB monitor, filtered on write, no error and the right address, so a write that failed on the bus does not change the prediction."

    • Say: "write_* are virtual, so a derived scoreboard installed with a factory override can extend them."

    • Say: "SB_EMPTY turns a test that checked nothing into a failure. Zero compares usually means the stimulus never ran or the test ended early."

    The bugs interviewers plant

    design.sv
    1
    2
    3
    4
    5
    6
    // bad-example: three planted bugs in a scoreboard
    function void write_out(axis_item t);        // not virtual: a factory override's version never runs
      bit [31:0] exp = expected.pop_front();     // an extra output word pops an empty queue
      if (t.data != exp)                         // != with an X operand is X, and if (X) takes the else
        `uvm_error("SB_MISMATCH", "mismatch")
    endfunction

    Each one hides a failure. The non-virtual method is war story 2 of this course: an overridden scoreboard whose extra checks never ran, because the analysis imp calls the method through the base class type. Popping an empty queue returns zero (a simulator may warn), so an unexpected word is compared against garbage instead of being reported as unexpected. And != on four-state data lets an X output word pass as a match; !== compares X and Z exactly.

    Drill 2: the monitor publishes a fresh object per accepted beat

    The monitor gets its virtual interface from config_db with a fatal if it is missing, samples through the interface's monitor clocking block, and publishes only on a beat that really moved: TVALID and TREADY. It creates a new item for every beat, because subscribers store what they receive.

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    // snippet: from the course DMA bench
    class axis_monitor extends uvm_monitor;
      `uvm_component_utils(axis_monitor)
      virtual axis_if vif;
      uvm_analysis_port #(axis_item) ap;
    
      function new(string name, uvm_component parent);
        super.new(name, parent);
        ap = new("ap", this);
      endfunction
    
      function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        if (!uvm_config_db#(virtual axis_if)::get(this, "", "vif", vif))
          `uvm_fatal("NOVIF", "axis_if not set for this monitor")
      endfunction
    
      task run_phase(uvm_phase phase);
        forever begin
          @(vif.mon_cb);
          if (vif.mon_cb.tvalid && vif.mon_cb.tready) begin
            axis_item it = axis_item::type_id::create("it");
            it.data = vif.mon_cb.tdata;
            it.last = vif.mon_cb.tlast;
            `uvm_info("AXIS_MON", it.convert2string(), UVM_HIGH)
            ap.write(it);
          end
        end
      endtask
    endclass
    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // bad-example: a monitor with three planted bugs
    task run_phase(uvm_phase phase);
      axis_item it = axis_item::type_id::create("it");   // one object for the whole run
      forever begin
        @(posedge vif.clk);                              // samples outside the clocking block
        if (vif.tvalid) begin                            // no TREADY: a stalled beat is published every clock
          it.data = vif.tdata;
          ap.write(it);                                  // every stored copy now changes on the next beat
        end
      end
    endtask

    If the interviewer upgrades the drill to an AXI write-data monitor, the same rules apply with two more: index by beat and mask by strobe. The snippet below is the core loop; a narrow transfer would also offset by the address lane.

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    // snippet
    do begin
      @(posedge vif.aclk iff (vif.wvalid && vif.wready));       // accepted beats only
      for (int i = 0; i < BUS_BYTES; i++)
        if (vif.wstrb[i]) t.data[(beat*BUS_BYTES + i)*8 +: 8] = vif.wdata[i*8 +: 8];
      last = vif.wlast;
      beat++;
    end while (!last);

    Drill 3: the driver loop completes every item exactly once

    The driver waits for reset to end, then loops: get an item, drive it at the clock edge with nonblocking assignments, hold TVALID until TREADY, and call item_done() on every path, including the path where a derived driver drops the beat. The pre_drive hook is what lets a factory override inject errors without copying this loop.

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    // snippet: from the course DMA bench
    class axis_driver extends uvm_driver #(axis_item);
      `uvm_component_utils(axis_driver)
      virtual axis_if vif;
    
      function new(string name, uvm_component parent);
        super.new(name, parent);
      endfunction
    
      function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        if (!uvm_config_db#(virtual axis_if)::get(this, "", "vif", vif))
          `uvm_fatal("NOVIF", "axis_if not set for this driver")
      endfunction
    
      task run_phase(uvm_phase phase);
        vif.tvalid <= 1'b0;
        @(posedge vif.rst_n);
        forever begin
          axis_item beat;
          seq_item_port.get_next_item(req);
          beat = pre_drive(req);
          if (beat != null) begin
            repeat (beat.idle) @(posedge vif.clk);
            @(posedge vif.clk);
            vif.tdata  <= beat.data;
            vif.tlast  <= beat.last;
            vif.tvalid <= 1'b1;
            do @(posedge vif.clk); while (!vif.tready);   // the beat moves on TVALID && TREADY
            vif.tvalid <= 1'b0;
          end
          seq_item_port.item_done();
        end
      endtask
    
      // Hook for derived drivers: return the beat to drive (the sequence's item, or a
      // modified copy), or null to drop it. The base driver drives every item as is.
      virtual function axis_item pre_drive(axis_item it);
        return it;
      endfunction
    endclass
    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // bad-example: a driver loop with three planted bugs
    forever begin
      seq_item_port.get_next_item(req);
      if (req.idle > 15) continue;               // dropped beat: no item_done, the next call errors
      @(posedge vif.clk);
      vif.tdata  <= req.data;
      vif.tvalid <= 1'b1;
      @(posedge vif.clk);                        // one clock, whether or not TREADY was high
      vif.tvalid <= 1'b0;
      seq_item_port.item_done(req);              // queues a response nobody reads
    end

    The first bug produces the log in the Debug Round: "Get_next_item called twice without item_done". The second loses beats whenever the DUT applies backpressure. The third fills the sequence's response queue, which holds 8 by default: UVM 1.2 reports an overflow error from the ninth item, while the IEEE 1800.2 reference library drops the extras silently unless the report is switched on.

    Expect the follow-up can this driver send back-to-back beats? Honestly, no: the reference driver drops TVALID after every beat, so a zero-gap stream never happens. The course's coverage model exposed exactly that (the gap=0 hole in Closure and Sign-off Questions). The fix is to keep TVALID high when the next item is already waiting, for example by checking with try_next_item before dropping it.

    Drill 4: the register adapter is two small translations and one contract

    Write the constructor first, because it carries the contract: provides_responses = 0, since the APB driver writes rdata and slverr back into the request item and there is no separate response. reg2bus turns a register operation into an APB item. bus2reg turns an observed or completed item back into an operation, taking read data from rdata and turning PSLVERR into UVM_NOT_OK.

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    // snippet: from the course DMA bench
    // Translates between register operations and APB items. The APB driver writes
    // read data and PSLVERR back into the request item, so there is no separate
    // response: provides_responses = 0.
    class apb_reg_adapter extends uvm_reg_adapter;
      `uvm_object_utils(apb_reg_adapter)
    
      function new(string name = "apb_reg_adapter");
        super.new(name);
        supports_byte_enable = 0;
        provides_responses   = 0;
      endfunction
    
      virtual function uvm_sequence_item reg2bus(const ref uvm_reg_bus_op rw);
        apb_item it = apb_item::type_id::create("it");
        it.addr  = rw.addr;
        it.write = (rw.kind == UVM_WRITE) || (rw.kind == UVM_BURST_WRITE);
        it.data  = rw.data;
        return it;
      endfunction
    
      virtual function void bus2reg(uvm_sequence_item bus_item, ref uvm_reg_bus_op rw);
        apb_item it;
        if (!$cast(it, bus_item))
          `uvm_fatal("NOT_APB", "bus2reg got an item that is not an apb_item")
        rw.kind   = it.write ? UVM_WRITE : UVM_READ;
        rw.addr   = it.addr;
        rw.data   = it.write ? it.data : it.rdata;
        rw.status = it.slverr ? UVM_NOT_OK : UVM_IS_OK;   // a bus error is a status, not a fatal
      endfunction
    endclass
    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    // bad-example: bus2reg with three planted bugs
    virtual function void bus2reg(uvm_sequence_item bus_item, ref uvm_reg_bus_op rw);
      apb_item it;
      void'($cast(it, bus_item));                // a wrong item type passes silently
      rw.kind   = it.write ? UVM_WRITE : UVM_READ;
      rw.addr   = it.addr;
      rw.data   = it.data;                       // reads return the request's data field, not rdata
      rw.status = UVM_IS_OK;                     // PSLVERR never reaches the register model
    endfunction

    Say why the cast failure is a fatal and the slave error is not: the adapter only ever receives APB items, so a different type is a wiring bug that must stop the run, while PSLVERR is a legal bus outcome that the register model reports as a status. If the interviewer asks for provides_responses = 1, explain that the driver would then return a separate response with put_response, and without it the register sequence waits forever.

    Drill 5: the virtual sequence coordinates agents it does not own

    The bench's job sequence has no virtual sequencer. The test hands it the two agent sequencers and the interrupt interface, then starts it with start(null). Inside, three children run in parallel: a background poller on APB, the data packet on the stream, and an interrupt handler that grabs the APB sequencer so its accesses jump ahead of queued polls.

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    // snippet: from the course DMA bench
    // The interrupt handler: grab the APB sequencer so the handler's accesses go
    // ahead of any queued polling, read STATUS, clear DONE/ERR, then let go.
    class dma_irq_seq extends uvm_sequence #(apb_item);
      `uvm_object_utils(dma_irq_seq)
      bit [31:0] status;
    
      function new(string name = "dma_irq_seq");
        super.new(name);
      endfunction
    
      task access(bit [7:0] addr, bit wr, bit [31:0] data, output bit [31:0] rdata);
        apb_item it = apb_item::type_id::create("it");
        start_item(it);
        if (!it.randomize() with { addr == local::addr; write == wr; data == local::data; })
          `uvm_fatal("RAND", "apb_item randomize failed")
        finish_item(it);
        rdata = it.rdata;
      endtask
    
      task body();
        bit [31:0] unused;
        grab();                                  // jump the queue, hold the sequencer
        `uvm_info("IRQ", "handler has the APB sequencer", UVM_MEDIUM)
        access(STATUS, 0, 0, status);
        access(STATUS, 1, 32'h6, unused);        // write 1 to clear DONE and ERR
        ungrab();
      endtask
    endclass
    
    // One whole DMA job across two agents. It has no sequencer of its own: the
    // test hands it the two agent sequencers and the interrupt interface, and
    // starts it with start(null).
    class dma_vseq extends uvm_sequence;
      `uvm_object_utils(dma_vseq)
      apb_sequencer  apb_sqr;
      axis_sequencer axis_sqr;
      virtual irq_if irq_vif;
      rand bit [31:0]   key;
      rand int unsigned len;
      constraint len_c { len inside {[2:16]}; }
      bit [31:0] status;                         // STATUS as read by the interrupt handler
    
      function new(string name = "dma_vseq");
        super.new(name);
      endfunction
    
      task write_reg(bit [7:0] addr, bit [31:0] data);
        apb_rw_seq s = apb_rw_seq::type_id::create("s");
        s.addr = addr; s.write = 1; s.data = data;
        s.start(apb_sqr, this);                  // this vseq is the parent
      endtask
    
      task body();
        apb_poll_seq poll = apb_poll_seq::type_id::create("poll");
        axis_pkt_seq pkt  = axis_pkt_seq::type_id::create("pkt");
        dma_irq_seq  isr  = dma_irq_seq::type_id::create("isr");
        if (apb_sqr == null || axis_sqr == null)
          `uvm_fatal("VSEQ", "set apb_sqr and axis_sqr before starting")
    
        write_reg(KEY, key);
        write_reg(LEN, len);
        write_reg(CTRL, 32'h3);                  // IRQ_EN | GO
        if (!pkt.randomize() with { n == len; }) `uvm_fatal("RAND", "axis_pkt_seq randomize failed")
        fork
          poll.start(apb_sqr, this);             // background polling
          pkt.start(axis_sqr, this);             // the data, in parallel
          begin                                  // the interrupt handler
            wait (irq_vif.irq === 1'b1);
            isr.start(apb_sqr, this);
            status   = isr.status;
            poll.stop = 1;
          end
        join
        `uvm_info("VSEQ", $sformatf("job done: STATUS=%08h after %0d polls", status, poll.polls), UVM_LOW)
      endtask
    endclass
    • Planted bug: no `poll.stop = 1`. The poller loops forever, so join never completes and the test hangs until the timeout.

    • Planted bug: no `ungrab()`. In the UVM reference library the lock is removed when the handler sequence ends, with a SEQFINERR error. If the handler waited for anything after its accesses, every poll would be frozen for that time.

    • Planted bug: `join_none` and return. The virtual sequence returns before the job is done, and the test drops its objection with words still in flight.

    Watch it run

    Diagram
    +UVM_TESTNAME=dma_vseq_test   (+UVM_VERBOSITY=UVM_MEDIUM)
    UVM_INFO dma_tb.sv(572) @ 405000: uvm_test_top.env.apb.sqr@@vseq.isr [IRQ] handler has the APB sequencer
    UVM_INFO dma_tb.sv(623) @ 575000: reporter@@vseq [VSEQ] job done: STATUS=00000002 after 4 polls
    UVM_INFO dma_tb.sv(411) @ 675000: uvm_test_top.env.sb [SB] 6 words matched, 0 mismatched
    UVM_ERROR :    0
    • `apb.sqr@@vseq.isr` is the handler running on the APB sequencer as a child of vseq, because each child was started with this as its parent.

    • `reporter@@vseq`: the virtual sequence was started on a null sequencer, so its messages come from the global reporter.

    • STATUS=00000002 after 4 polls: DONE was set, and the poller ran four times before the handler stopped it.

    "Now make your scoreboard work for an AXI slave that returns responses out of order."

    A weak answer keys an associative array by ID with one entry per ID: "look up the ID, compare, delete." A second outstanding transaction with the same ID overwrites the first.

    A strong answer keys a queue per ID: AXI allows several outstanding transactions with one ID, and responses for the same ID return in order, so you push on the request and compare at the head of that ID's queue on the response. Different IDs can complete in any order. Report a response whose ID has an empty queue as unexpected, and at end of test sweep every queue for leftovers.

    Follow-ups: Write data can arrive before the address. Where do you hold it? (a write-data queue matched to addresses in order, since AXI4 has no write-data ID). How deep can the queues get? (bounded by the maximum outstanding count; an assertion on that bound catches a lost response early).

    Check yourself A reviewer notices your monitor creates the item once, before the forever loop. The scoreboard sometimes reports every stored word as equal to the last one. Why?

    Every write() passes the same handle. Subscribers that store it all point at one object, which the monitor overwrites on each beat, so stored entries change after the fact. Create a new item per beat (or clone before writing).

    Check yourself Register reads through the model always return 0, yet the waveform shows the right PRDATA. Where do you look first?

    bus2reg. It most likely copies it.data (the request's write-data field) into rw.data for reads instead of it.rdata. The bus is right, the translation back is wrong.

    Check yourself Your driver passes every test, but the coverage plan says back-to-back beats never happen. Is that a test problem or a driver problem?

    A driver problem. If the driver always drops VALID between beats, no seed and no constraint can produce a zero gap. Fix the agent so it keeps VALID high when another item is ready, then the coverage hole can close.

    Next: these bugs produce real logs. In Debug Round: Find the Bug in This Log the interviewer hands you the tail of one and asks what happened.

    Related topics

    • Up: Interview Bank

    • Whiteboard delivery framework (timed)

    • Out-of-order matching: a queue per ID

    • The adapter contract

    Previous

    276 / 280

    Next: Debug Round: Find the Bug in This Log

    Up next

    Up nextDebug Round: Find the Bug in This Log

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Concept Round: Phases, Objections and End of Test
    • Concept Round: Factory and config_db
    • Concept Round: TLM and Analysis