1. Introduction

    As designers build larger and larger chips, it becomes more and more important for verification engineers to think about verification at higher level abstractions. Transactions can be recorded from low level details like clock edges and bus transfers all the way up the abstraction tree to system level interactions and tracking behavioral models in C or other high-level languages. This is important because most of this kind of debug needs to correlate two things.

    Perhaps two sets of transactions – one from the high level and one from the low level. Perhaps what needs correlated is the low-level signal changes with the top-level abstraction activity. Perhaps the entire abstraction tree must be correlated with itself – to understand who is causing what events and transactions.

    The waveform window in a traditional functional design and verification debugger is ideal for this kind of correlation – time-based correlation. The signals and transactions occupy the same timeline and can be reasoned about in the wave window. New views can also be created. Often the actual timing of the transaction is not important, but rather whether a transaction completes before another – the relative position of starting and ending transactions.

    This paper will review the various APIs and methods for transaction recording and demonstrate the concepts using an example. That example can be reused in reader code and is open source.

    Transaction Recording Basics

    A transaction recording interface is commonly available, including creating a transaction stream, beginning and ending a transaction, adding attributes, adding relationships and signal activity.

    • $create_transaction_stream
    • $begin_transaction
    • $end_transaction
    • $free_transaction
    • $add_attribute

    An example using such an interface is below. This example does nothing useful, except demonstrate using the API to model a channel with 4 out-of-order transactions in-flight at once.

    module M(input clk);
      int stream;
      
      initial begin
         stream = $create_transaction_stream("stream", "kind");
      end
      
      sub_channel s0(clk, 0, stream);
      sub_channel s1(clk, 1, stream);
      sub_channel s2(clk, 2, stream);
      sub_channel s3(clk, 3, stream);
    endmodule
    
    module sub_channel(input clk, input int inflight, int stream);
      always @(posedge clk) begin: LOOP
         ...
         begin
           req_rsp = REQ;
           tr = $begin_transaction(stream, $sformatf("tr%0d", tr_count));
           $add_attribute(tr, req_rsp, "req_rsp");
           $add_attribute(tr, addr, "addr");
           payload = 0;
           $add_attribute(tr, payload, "payload");
           $add_attribute(tr, id, "id");
           $add_attribute(tr, l_serial_number, "serial_number");
           #10;
           $end_transaction(tr);
           $free_transaction(tr);
         end
         ...
         begin
           req_rsp = RSP;
           tr = $begin_transaction(stream, $sformatf("tr%0d", tr_count));
           $add_attribute(tr, req_rsp, "req_rsp");
           $add_attribute(tr, addr, "addr");
           payload = $random() % 1024; // Fetch the payload
           $add_attribute(tr, payload, "payload");
           $add_attribute(tr, id, "id");
           $add_attribute(tr, l_serial_number, "serial_number");
           delay = 10;
           #delay;
           #10;
           $end_transaction(tr);
           $free_transaction(tr);
         end
      end
    endmodule
  2. Download Paper

  3. Download Slides