Miscellaneous updates
This commit is contained in:
		| @@ -2,6 +2,10 @@ | ||||
| // AXI Manager Driver | ||||
| // ---------------------------------------------------------------------- | ||||
| class axi_manager_driver extends axi_driver; | ||||
|     axi_transaction txn_trk[axi_transaction_id_t]; | ||||
|  | ||||
|     semaphore write_request_sem; | ||||
|     semaphore read_request_sem; | ||||
|  | ||||
|     `uvm_component_utils(axi_manager_driver) | ||||
|  | ||||
| @@ -9,6 +13,9 @@ class axi_manager_driver extends axi_driver; | ||||
|     // Constructor | ||||
|     function new(string name = "axi_manager_driver", uvm_component parent = null); | ||||
|         super.new(name, parent); | ||||
|  | ||||
|         write_request_sem = new(1); | ||||
|         read_request_sem = new(1); | ||||
|     endfunction | ||||
|  | ||||
|     // -------------------------------------------------- | ||||
| @@ -33,7 +40,7 @@ class axi_manager_driver extends axi_driver; | ||||
|             `uvm_info("run_phase", $sformatf("Starting to drive transactions for %s (rst_n = %0b)", | ||||
|                 get_full_name(), m_if.ARESETn), UVM_LOW) | ||||
|  | ||||
|             // Drive transactions until reset is asserted | ||||
|              // Drive transactions until reset is asserted | ||||
|             while (m_if.ARESETn != 0) begin | ||||
|                 uvm_sequence_item txn; | ||||
|                 axi_transaction req; | ||||
| @@ -45,7 +52,14 @@ class axi_manager_driver extends axi_driver; | ||||
|                 if (!$cast(req, txn)) begin | ||||
|                     `uvm_fatal("drive_txn", "Invalid transaction type") | ||||
|                 end | ||||
|                 drive_txn(req); | ||||
|                 while (txn_trk.size() > (3-1)) begin | ||||
|                     `uvm_info("run_phase", $sformatf("Waiting for next transaction Txn-trk size=%0d to be under 3", txn_trk.size()), UVM_LOW) | ||||
|                     @(txn_trk.size()); | ||||
|                     `uvm_info("run_phase", $sformatf("Txn-trk size changed to %0d to be under 3", txn_trk.size()), UVM_LOW) | ||||
|                 end | ||||
|                 fork | ||||
|                     drive_txn(req); | ||||
|                 join_none | ||||
|                 seq_item_port.item_done(); | ||||
|             end | ||||
|         end | ||||
| @@ -54,7 +68,12 @@ class axi_manager_driver extends axi_driver; | ||||
|     // ------------------------------------------------------------ | ||||
|     task drive_txn(axi_transaction req); | ||||
|         int dly = cfg.get_pre_transaction_delay(); | ||||
|         `uvm_info("drive_txn", $sformatf("Driving AXI transaction:\n%s", req.sprint()), UVM_LOW) | ||||
|         axi_transaction_id_t tid = req.get_tid(); | ||||
|  | ||||
|         `uvm_info("drive_txn", $sformatf("Driving AXI transaction ID=%s:\n%s", | ||||
|             req.show_tid(), req.sprint()), UVM_LOW) | ||||
|  | ||||
|         txn_trk[tid] = req; | ||||
|  | ||||
|         // Pre transaction delay | ||||
|         `uvm_info("drive_txn", $sformatf("Waiting pre_transaction_delay = %0d cycles", | ||||
| @@ -69,39 +88,120 @@ class axi_manager_driver extends axi_driver; | ||||
|             `uvm_error("drive_txn", $sformatf("Unknown transaction type: %s", req.txn_type.name())) | ||||
|         end | ||||
|         `uvm_info("drive_txn", $sformatf("Driving AXI transaction done."), UVM_LOW) | ||||
|  | ||||
|         finish_tr(req); | ||||
|  | ||||
|         txn_trk.delete(tid); | ||||
|     endtask | ||||
|  | ||||
|     // ------------------------------------------------------------ | ||||
|     // Drive a write transaction | ||||
|     task drive_write_txn(axi_transaction req); | ||||
|         bit done = 0; | ||||
|         bit a_done = 0; | ||||
|         bit w_done = 0; | ||||
|         bit b_done = 0; | ||||
|  | ||||
|         `uvm_info("drive_write_txn", $sformatf("[%s] Waiting for semaphore to drive", | ||||
|             req.show_tag()), UVM_LOW) | ||||
|         write_request_sem.get(); | ||||
|  | ||||
|         // Drive address channel information | ||||
|         // TODO: Sometimes drive after delay | ||||
|         // TODO: Sometimes drive after waiting for AWREADY | ||||
|         @(posedge m_if.ACLK); | ||||
|         m_if.AWVALID = 1; | ||||
|         m_if.AWADDR  = req.addr; | ||||
|         @(posedge m_if.ACLK); | ||||
|         m_if.AWID    = 0; | ||||
|  | ||||
|         // Drive data channel information | ||||
|         // TODO: Sometimes drive after delay | ||||
|         // TODO: Sometimes drive after waiting for WREADY | ||||
|         m_if.WVALID = 1; | ||||
|         m_if.WDATA  = req.data; | ||||
|         m_if.WSTRB  = req.strb; | ||||
|  | ||||
|         while (m_if.AWREADY != 1) begin | ||||
|         // Wait for write response | ||||
|         @(posedge m_if.ACLK); | ||||
|         m_if.BREADY = 1; | ||||
|         while (!done) begin | ||||
|             @(posedge m_if.ACLK); | ||||
|  | ||||
|             if (m_if.AWREADY == 1) begin | ||||
|                 a_done = 1; | ||||
|                 m_if.AWVALID = 0; | ||||
|             end | ||||
|             if (m_if.WREADY == 1) begin | ||||
|                 w_done = 1; | ||||
|                 m_if.WVALID = 0; | ||||
|             end | ||||
|  | ||||
|             if (m_if.BVALID == 1) begin | ||||
|                 b_done = 1; | ||||
|                 m_if.BREADY = 0; | ||||
|             end | ||||
|  | ||||
|             // Write is done when Address, Data and Response phases are done | ||||
|             done = (a_done && w_done && b_done); | ||||
|             `uvm_info("drive_write_txn", $sformatf("[%s] Waiting for transaction to be done (%b - a%b w%b b%b)", | ||||
|                 req.show_tag(), done, a_done, w_done, b_done), UVM_LOW) | ||||
|         end | ||||
|         `uvm_info("drive_write_txn", $sformatf("Address phase accepted (AWREADY=1)"), UVM_LOW) | ||||
|         m_if.AWVALID = 0; | ||||
|         `uvm_info("drive_write_txn", $sformatf("Done."), UVM_LOW) | ||||
|  | ||||
|         write_request_sem.put(); | ||||
|     endtask | ||||
|  | ||||
|     // ------------------------------------------------------------ | ||||
|     // Drive a read transaction | ||||
|     task drive_read_txn(axi_transaction req); | ||||
|         bit done = 0; | ||||
|         bit a_done = 0; | ||||
|         bit r_done = 0; | ||||
|  | ||||
|         `uvm_info("drive_read_txn", $sformatf("[%s] Waiting for semaphore to drive", | ||||
|             req.show_tag()), UVM_LOW) | ||||
|         read_request_sem.get(); | ||||
|  | ||||
|         // Drive address channel information | ||||
|         // TODO: Sometimes drive after delay | ||||
|         // TODO: Sometimes drive after waiting for AWREADY | ||||
|         @(posedge m_if.ACLK); | ||||
|         m_if.ARVALID = 1; | ||||
|         m_if.ARADDR  = req.addr; | ||||
|         @(posedge m_if.ACLK); | ||||
|         m_if.ARID    = 0; | ||||
|  | ||||
|         while (m_if.ARREADY != 1) begin | ||||
|         // Wait for write response | ||||
|         @(posedge m_if.ACLK); | ||||
|         m_if.RREADY = 1; | ||||
|         while (!done) begin | ||||
|             @(posedge m_if.ACLK); | ||||
|  | ||||
|             if (m_if.ARREADY == 1) begin | ||||
|                 a_done = 1; | ||||
|                 m_if.ARVALID = 0; | ||||
|             end | ||||
|  | ||||
|             if (m_if.RVALID == 1) begin | ||||
|                 r_done = 1; | ||||
|                 m_if.RREADY = 0; | ||||
|             end | ||||
|  | ||||
|             // Write is done when Address, Data and Response phases are done | ||||
|             done = (a_done && r_done); | ||||
|             `uvm_info("drive_read_txn", $sformatf("[%s] Waiting for transaction to be done (Data=0x%h) (%b - a%b r%b)", | ||||
|                 req.show_tag(), m_if.RDATA, done, a_done, r_done), UVM_LOW) | ||||
|         end | ||||
|         `uvm_info("drive_read_txn", $sformatf("Address phase accepted (ARREADY=1)"), UVM_LOW) | ||||
|         m_if.ARVALID = 0; | ||||
|         `uvm_info("drive_read_txn", $sformatf("Done."), UVM_LOW) | ||||
|  | ||||
|         read_request_sem.put(); | ||||
|     endtask | ||||
|  | ||||
|     // ------------------------------------------------------------ | ||||
|     // Mark transaction done | ||||
|     function void finish_tr(axi_transaction txn); | ||||
|         uvm_event finished_event; | ||||
|  | ||||
|         finished_event = txn.get_event_pool().get("finished"); | ||||
|         finished_event.trigger(); | ||||
|         `uvm_info("finish_tr", $sformatf("[%s] Marked transaction done", | ||||
|             txn.show_tag()), UVM_LOW) | ||||
|     endfunction | ||||
| endclass : axi_manager_driver | ||||
|   | ||||
| @@ -71,13 +71,13 @@ class axi_monitor extends uvm_monitor; // #(axi_transaction); | ||||
|         forever begin | ||||
|             @(posedge mon_if.ACLK); | ||||
|             if (mon_if.ARESETn != 0) begin | ||||
|                 if (mon_if.AWVALID == 1) begin | ||||
|                     $fwrite(trk_file, "AXI WRITE - ADDR=0x%h DATA=0x%h STRB=%h\n", | ||||
|                         mon_if.AWADDR, mon_if.WDATA, mon_if.WSTRB); | ||||
|                 if ((mon_if.AWVALID == 1) && (mon_if.AWREADY == 1)) begin | ||||
|                     $fwrite(trk_file, "%10t: AXI WRITE - ADDR=0x%h DATA=0x%h STRB=%h\n", | ||||
|                         $time, mon_if.AWADDR, mon_if.WDATA, mon_if.WSTRB); | ||||
|                 end | ||||
|                 if (mon_if.ARVALID == 1) begin | ||||
|                     $fwrite(trk_file, "AXI READ - ADDR=0x%h\n", | ||||
|                         mon_if.ARADDR); | ||||
|                 if ((mon_if.ARVALID == 1) && (mon_if.ARREADY == 1)) begin | ||||
|                     $fwrite(trk_file, "%10t: AXI READ - ADDR=0x%h\n", | ||||
|                         $time, mon_if.ARADDR); | ||||
|                 end | ||||
|             end | ||||
|         end | ||||
|   | ||||
| @@ -1,5 +1,10 @@ | ||||
| // ---------------------------------------------------------------------- | ||||
| class axi_subordinate_driver extends axi_driver; | ||||
|     int rd_txn_id = 0; | ||||
|     int wr_txn_id = 0; | ||||
|  | ||||
|     semaphore write_request_sem; | ||||
|     semaphore read_request_sem; | ||||
|  | ||||
|     `uvm_component_utils(axi_subordinate_driver) | ||||
|  | ||||
| @@ -7,6 +12,9 @@ class axi_subordinate_driver extends axi_driver; | ||||
|     // Constructor | ||||
|     function new(string name = "axi_subordinate_driver", uvm_component parent = null); | ||||
|         super.new(name, parent); | ||||
|  | ||||
|         write_request_sem = new(1); | ||||
|         read_request_sem = new(1); | ||||
|     endfunction | ||||
|  | ||||
|     // -------------------------------------------------- | ||||
| @@ -19,21 +27,22 @@ class axi_subordinate_driver extends axi_driver; | ||||
|         end | ||||
|  | ||||
|         forever begin | ||||
|             @(posedge s_if.ARESETn); | ||||
|             @(s_if.ARESETn or s_if.ACLK); | ||||
|  | ||||
|             while (s_if.ARESETn != 0) begin | ||||
|                 @(posedge s_if.ACLK); | ||||
|             if (s_if.ARESETn == 0) continue; | ||||
|  | ||||
|                 // Following could happen on the same cycle | ||||
|             if (s_if.ACLK == 1) begin | ||||
|                 if (s_if.AWVALID == 1'b1) begin | ||||
|                     respond_to_write_txn(); | ||||
|                     fork | ||||
|                         respond_to_write_txn(); | ||||
|                     join_none | ||||
|                 end | ||||
|  | ||||
|                 if (s_if.ARVALID == 1'b1) begin | ||||
|                     respond_to_read_txn(); | ||||
|                     fork | ||||
|                         respond_to_read_txn(); | ||||
|                     join_none | ||||
|                 end | ||||
|  | ||||
|                 @(negedge s_if.ACLK); | ||||
|             end | ||||
|         end | ||||
|     endtask | ||||
| @@ -43,22 +52,73 @@ class axi_subordinate_driver extends axi_driver; | ||||
|         axi_transaction req; | ||||
|         int dly = cfg.get_pre_response_delay(); | ||||
|  | ||||
|         while (s_if.AWVALID != 1) begin | ||||
|             `uvm_info("respond_to_write_txn", $sformatf("Waiting for AWVALID to set (%0b)", | ||||
|                 s_if.AWVALID), UVM_LOW) | ||||
|             @(posedge s_if.ACLK); | ||||
|         end | ||||
|  | ||||
|         if (!write_request_sem.try_get()) begin | ||||
|             `uvm_info("respond_to_write_txn", $sformatf("Already taken write semaphore"), UVM_LOW) | ||||
|             return; | ||||
|         end | ||||
|         // `uvm_info("respond_to_write_txn", $sformatf("Waiting for write semaphore"), UVM_LOW) | ||||
|         // write_request_sem.get(); | ||||
|         `uvm_info("respond_to_write_txn", $sformatf("Got write semaphore"), UVM_LOW) | ||||
|  | ||||
|         req = axi_transaction::type_id::create("req"); | ||||
|         req.set_sequence_id(1); | ||||
|         req.set_transaction_id(wr_txn_id); | ||||
|         wr_txn_id += 1; | ||||
|         req.txn_type = AXI_WRITE; | ||||
|         req.addr = s_if.AWADDR; | ||||
|         req.data = s_if.WDATA; | ||||
|         req.strb = s_if.WSTRB; | ||||
|  | ||||
|         // Pre response delay | ||||
|         `uvm_info("drive_txn", $sformatf("Waiting pre_response_delay = %0d cycles", | ||||
|             dly), UVM_LOW) | ||||
|         `uvm_info("respond_to_write_txn", $sformatf("[%s] Waiting pre_response_delay = %0d cycles", | ||||
|             req.show_tag(), dly), UVM_LOW) | ||||
|         repeat(dly) @(posedge s_if.ACLK); | ||||
|  | ||||
|         `uvm_info("respond_to_write_txn", $sformatf("Responding to AXI write transaction:\n%s", req.sprint()), UVM_LOW) | ||||
|         `uvm_info("respond_to_write_txn", $sformatf("[%s] Responding to AXI write transaction:\n%s", | ||||
|             req.show_tag(), req.sprint()), UVM_LOW) | ||||
|  | ||||
|         s_if.AWREADY = 1'b1; | ||||
|         req.addr = s_if.AWADDR; | ||||
|         @(posedge s_if.ACLK); | ||||
|         while (s_if.AWVALID != 0) begin | ||||
|             @(posedge s_if.ACLK); | ||||
|         end | ||||
|         s_if.AWREADY = 1'b0; | ||||
|  | ||||
|         `uvm_info("respond_to_write_txn", $sformatf("[%s] Request phase done. Waiting data phase", | ||||
|             req.show_tag()), UVM_LOW) | ||||
|         while (s_if.WVALID != 1) begin | ||||
|             `uvm_info("respond_to_write_txn", $sformatf("[%s] Waiting for WVALID to set (%0b)", | ||||
|                 req.show_tag(), s_if.WVALID), UVM_LOW) | ||||
|             @(posedge s_if.ACLK); | ||||
|         end | ||||
|         s_if.WREADY = 1'b1; | ||||
|         req.data = s_if.WDATA; | ||||
|         req.strb = s_if.WSTRB; | ||||
|         @(posedge s_if.ACLK); | ||||
|         while (s_if.WVALID != 0) begin | ||||
|             `uvm_info("respond_to_write_txn", $sformatf("[%s] Waiting for WVALID to clear (%0b)", | ||||
|                 req.show_tag(), s_if.WVALID), UVM_LOW) | ||||
|             @(posedge s_if.ACLK); | ||||
|         end | ||||
|         s_if.WREADY = 1'b0; | ||||
|  | ||||
|         `uvm_info("respond_to_write_txn", $sformatf("[%s] Data phase done. Waiting response phase", | ||||
|             req.show_tag()), UVM_LOW) | ||||
|         s_if.BVALID = 1; | ||||
|         @(posedge s_if.ACLK); | ||||
|         while (s_if.BREADY != 1) begin | ||||
|             `uvm_info("respond_to_write_txn", $sformatf("[%s] Waiting for BREADY to set (%0b)", | ||||
|                 req.show_tag(), s_if.BREADY), UVM_LOW) | ||||
|             @(posedge s_if.ACLK); | ||||
|         end | ||||
|         s_if.BVALID = 0; | ||||
|         `uvm_info("respond_to_write_txn", $sformatf("[%s] Response phase done", | ||||
|             req.show_tag()), UVM_LOW) | ||||
|         write_request_sem.put(); | ||||
|     endtask | ||||
|  | ||||
|     // ------------------------------------------------------------ | ||||
| @@ -66,19 +126,57 @@ class axi_subordinate_driver extends axi_driver; | ||||
|         axi_transaction req; | ||||
|         int dly = cfg.get_pre_response_delay(); | ||||
|  | ||||
|         while (s_if.ARVALID != 1) begin | ||||
|             `uvm_info("respond_to_read_txn", $sformatf("Waiting for ARVALID to be set (%0b)", | ||||
|                 s_if.ARVALID), UVM_LOW) | ||||
|             @(posedge s_if.ACLK); | ||||
|         end | ||||
|  | ||||
|         if (!read_request_sem.try_get()) begin | ||||
|             `uvm_info("respond_to_read_txn", $sformatf("Already taken read semaphore"), UVM_LOW) | ||||
|             return; | ||||
|         end | ||||
|         //  `uvm_info("respond_to_read_txn", $sformatf("Waiting for read semaphore"), UVM_LOW) | ||||
|         //  read_request_sem.get(); | ||||
|         `uvm_info("respond_to_read_txn", $sformatf("Got read semaphore"), UVM_LOW) | ||||
|  | ||||
|         req = axi_transaction::type_id::create("req"); | ||||
|         req.set_sequence_id(0); | ||||
|         req.set_transaction_id(rd_txn_id); | ||||
|         rd_txn_id += 1; | ||||
|         req.txn_type = AXI_READ; | ||||
|         req.addr = s_if.ARADDR; | ||||
|  | ||||
|         // Pre response delay | ||||
|         `uvm_info("respond_to_write_txn", $sformatf("Waiting pre_response_delay = %0d cycles", | ||||
|         `uvm_info("respond_to_read_txn", $sformatf("Waiting pre_response_delay = %0d cycles", | ||||
|             dly), UVM_LOW) | ||||
|         repeat(dly) @(posedge s_if.ACLK); | ||||
|  | ||||
|         `uvm_info("respond_to_write_txn", $sformatf("Responding to AXI write transaction:\n%s", req.sprint()), UVM_LOW) | ||||
|         `uvm_info("respond_to_read_txn", $sformatf("Responding to AXI read transaction:\n%s", | ||||
|             req.sprint()), UVM_LOW) | ||||
|  | ||||
|         s_if.ARREADY = 1'b1; | ||||
|         @(posedge s_if.ACLK); | ||||
|         while (s_if.ARVALID != 0) begin | ||||
|             `uvm_info("respond_to_read_txn", $sformatf("[%s] Waiting for ARVALID to clear (%0b)", | ||||
|                 req.show_tag(), s_if.ARVALID), UVM_LOW) | ||||
|             @(posedge s_if.ACLK); | ||||
|         end | ||||
|         s_if.ARREADY = 1'b0; | ||||
|  | ||||
|         `uvm_info("respond_to_read_txn", $sformatf("[%s] Data phase done. Waiting response phase", | ||||
|             req.show_tag()), UVM_LOW) | ||||
|         s_if.RVALID = 1; | ||||
|         @(posedge s_if.ACLK); | ||||
|         while (s_if.RREADY != 1) begin | ||||
|             `uvm_info("respond_to_read_txn", $sformatf("[%s] Waiting for RREADY to set (%0b)", | ||||
|                 req.show_tag(), s_if.RREADY), UVM_LOW) | ||||
|             @(posedge s_if.ACLK); | ||||
|         end | ||||
|         s_if.RVALID = 0; | ||||
|         `uvm_info("respond_to_read_txn", $sformatf("[%s] Response phase done", | ||||
|             req.show_tag()), UVM_LOW) | ||||
|  | ||||
|         read_request_sem.put(); | ||||
|     endtask | ||||
| endclass : axi_subordinate_driver | ||||
|   | ||||
| @@ -1,16 +1,20 @@ | ||||
| // ---------------------------------------------------------------------- | ||||
| class axi_transaction extends uvm_sequence_item; | ||||
|     // Declare AXI transaction fields | ||||
|     rand axi_transaction_type_t     txn_type; // Transaction type (read/write) | ||||
|     rand bit [`ADDR_WIDTH-1:0]        addr; // Address | ||||
|     rand bit [`DATA_WIDTH-1:0]        data; // Data | ||||
|     rand bit [`DATA_WIDTH_DIV_8-1:0]  strb; // Byte enable | ||||
|     rand axi_transaction_type_t         txn_type; // Transaction type (read/write) | ||||
|     rand bit [`ADDR_WIDTH-1:0]          addr; // Address | ||||
|     rand bit [`DATA_WIDTH-1:0]          data; // Data | ||||
|     rand bit [`DATA_WIDTH_DIV_8-1:0]    strb; // Byte enable | ||||
|     rand bit [2:0]                      size; // Size | ||||
|     rand bit [7:0]                      length; // Length | ||||
|  | ||||
|     `uvm_object_utils_begin(axi_transaction) | ||||
|         `uvm_field_enum(axi_transaction_type_t, txn_type, UVM_DEFAULT) | ||||
|         `uvm_field_int(addr, UVM_DEFAULT) | ||||
|         `uvm_field_int(data, UVM_DEFAULT) | ||||
|         `uvm_field_int(strb, UVM_DEFAULT) | ||||
|         `uvm_field_int(size, UVM_DEFAULT) | ||||
|         `uvm_field_int(length, UVM_DEFAULT) | ||||
|     `uvm_object_utils_end | ||||
|  | ||||
|     // Constructor | ||||
| @@ -18,6 +22,34 @@ class axi_transaction extends uvm_sequence_item; | ||||
|         super.new(name); | ||||
|     endfunction | ||||
|  | ||||
|     // Get transaction id - made up of sequence ID and trasacton ID | ||||
|     function axi_transaction_id_t get_tid(); | ||||
|         axi_transaction_id_t tid; | ||||
|  | ||||
|         tid.seq_id = this.get_sequence_id(); | ||||
|         tid.txn_id = this.get_transaction_id(); | ||||
|  | ||||
|         return tid; | ||||
|     endfunction | ||||
|  | ||||
|     // Show transaction id - sequence ID:trasacton ID | ||||
|     function string show_tid(); | ||||
|         return $sformatf("%0h:%0h", this.get_sequence_id(), this.get_transaction_id()); | ||||
|     endfunction | ||||
|  | ||||
|     // Show transaction tag - Transaction type:sequence ID:trasacton ID | ||||
|     function string show_tag(); | ||||
|         return $sformatf("%s:%0h:%0h", this.txn_type.name(), this.get_sequence_id(), this.get_transaction_id()); | ||||
|     endfunction | ||||
|  | ||||
|     // Wait for transaction to be done | ||||
|     task wait_for_done(); | ||||
|         uvm_event finished_event; | ||||
|  | ||||
|         finished_event = get_event_pool().get("finished"); | ||||
|         finished_event.wait_on(); | ||||
|     endtask | ||||
|  | ||||
|     // Copy method for cloning | ||||
|     virtual function uvm_object clone(); | ||||
|         axi_transaction copy; | ||||
| @@ -26,6 +58,8 @@ class axi_transaction extends uvm_sequence_item; | ||||
|         copy.addr = this.addr; | ||||
|         copy.data = this.data; | ||||
|         copy.strb = this.strb; | ||||
|         copy.size = this.size; | ||||
|         copy.length = this.length; | ||||
|         return copy; | ||||
|     endfunction | ||||
|  | ||||
| @@ -36,7 +70,9 @@ class axi_transaction extends uvm_sequence_item; | ||||
|         return (this.txn_type == other.txn_type) && | ||||
|                (this.addr == other.addr) && | ||||
|                (this.data == other.data) && | ||||
|                (this.strb == other.strb); | ||||
|                (this.strb == other.strb) && | ||||
|                (this.size == other.size) && | ||||
|                (this.length == other.length); | ||||
|     endfunction | ||||
|  | ||||
| endclass : axi_transaction | ||||
|   | ||||
| @@ -1,13 +1,18 @@ | ||||
| // AXI Types | ||||
| package axi_types; | ||||
|     typedef struct { | ||||
|         int seq_id; | ||||
|         int txn_id; | ||||
|     } axi_transaction_id_t; | ||||
|  | ||||
|     // Agent type | ||||
|     typedef enum { | ||||
|         MANAGER, | ||||
|         SUBORDINATE | ||||
|     typedef enum bit { | ||||
|         MANAGER     = 1'b0, | ||||
|         SUBORDINATE = 1'b1 | ||||
|     } axi_agent_type_t; | ||||
|  | ||||
|     typedef enum { | ||||
|         AXI_READ, | ||||
|         AXI_WRITE | ||||
|     typedef enum bit { | ||||
|         AXI_READ    = 1'b0, | ||||
|         AXI_WRITE   = 1'b1 | ||||
|     } axi_transaction_type_t; | ||||
| endpackage | ||||
|   | ||||
| @@ -36,6 +36,7 @@ class axi_simple_seq extends axi_m_seq_base; | ||||
|  | ||||
|     // Task to start the sequence | ||||
|     virtual task body(); | ||||
|         axi_transaction txns[$]; | ||||
|         axi_transaction txn; | ||||
|  | ||||
|         super.body(); | ||||
| @@ -48,6 +49,16 @@ class axi_simple_seq extends axi_m_seq_base; | ||||
|                 data != {`DATA_WIDTH{1'b0}}; | ||||
|                 strb == 'hf; // Example byte enable | ||||
|             }); | ||||
|             `uvm_info("axi_simple_seq", $sformatf("Starting %s transaction [%0s]", | ||||
|                 txn.txn_type.name(), txn.show_tag()), UVM_LOW) | ||||
|             txns.push_back(txn); | ||||
|         end | ||||
|  | ||||
|         `uvm_info("axi_simple_seq", $sformatf("Waiting for %0d txns", txns.size()), UVM_LOW) | ||||
|         foreach (txns[i]) begin | ||||
|             `uvm_info("axi_simple_seq", $sformatf("Waiting for txn %s", txns[i].show_tag()), UVM_LOW) | ||||
|             txns[i].wait_for_done(); | ||||
|             `uvm_info("axi_simple_seq", $sformatf("Done waiting for txn %s", txns[i].show_tag()), UVM_LOW) | ||||
|         end | ||||
|     endtask | ||||
| endclass : axi_simple_seq | ||||
|   | ||||
| @@ -12,8 +12,12 @@ class test_base extends uvm_test; | ||||
|  | ||||
|     // ------------------------------------------------------------ | ||||
|     function void build_phase(uvm_phase phase); | ||||
|         uvm_root ur; | ||||
|         super.build_phase(phase); | ||||
|  | ||||
|         ur = uvm_root::get(); | ||||
|         ur.set_timeout(10us); | ||||
|  | ||||
|         env = tb_env::type_id::create("env", this); | ||||
|         tb_printer = new("tb_printer"); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user