diff --git a/comp/ver/axi/axi4s_rq_meter.sv b/comp/ver/axi/axi4s_rq_meter.sv new file mode 100644 index 000000000..41feec1d9 --- /dev/null +++ b/comp/ver/axi/axi4s_rq_meter.sv @@ -0,0 +1,235 @@ +/*! + * \file axi4s_rq_stats.sv + * \brief Get statistic from axi4s + * \author Radek Iša + * \date 2018 + * \copyright CESNET, z. s. p. o. + */ + +/* SPDX-License-Identifier: BSD-3-Clause */ + +class Axi4S_RQ_meter #(DATA_WIDTH = 512, USER_WIDTH = 137, ITEM_WIDTH_IN = 8, ST_COUNT = 4) extends Monitor; + + localparam REGIONS = ST_COUNT; + localparam REGION_SIZE = 1; + localparam ITEM_WIDTH = 8; + localparam BLOCK_SIZE = DATA_WIDTH/REGIONS/ITEM_WIDTH; + + protected int sof_pos[REGIONS]; + protected int eof_pos[REGIONS]; + + localparam ITEMS = REGIONS * REGION_SIZE * BLOCK_SIZE; + localparam REGION_ITEMS = REGION_SIZE * BLOCK_SIZE; + localparam WORD_BLOCKS = REGIONS * REGION_SIZE; + localparam SOF_POS_WIDTH = $clog2(REGION_SIZE); + localparam EOF_POS_WIDTH = $clog2(REGION_SIZE * BLOCK_SIZE); + + protected virtual iAxi4STx#(DATA_WIDTH, USER_WIDTH, ITEM_WIDTH_IN) vif; + protected sv_common_pkg::stats speed; + protected int unsigned speed_curr; + protected logic inframe; + protected int old_inframe = 0; + + function new(string i, virtual iAxi4STx#(DATA_WIDTH, USER_WIDTH, ITEM_WIDTH_IN) v); + super.new(i); + speed = new(); + vif = v; + endfunction + + virtual task setEnabled(); + enabled = 1; + fork + run(); + join_none; + endtask + + function int hasSOF(); + if (USER_WIDTH==137) // ULTRASCALE + return vif.cb.TUSER[21:20]; + else begin // 7SERIES + if (!inframe) + return vif.cb.TVALID; + else + return 0; + end + endfunction + + function int hasEOF(); + if (USER_WIDTH==137) // ULTRASCALE + return vif.cb.TUSER[27:26]; + else begin // 7SERIES + return vif.cb.TLAST; + end + endfunction + + function logic [3:0] fbe(int unsigned index); + if(USER_WIDTH== 137) begin + return vif.cb.TUSER[(index+1)*4-1 -: 4]; + end else if (USER_WIDTH == 60) begin + return vif.cb.TUSER[3:0]; + end else begin + $write("NOT SUPPORTED AXI USER_WIDTH\n"); + $stop(); + end + endfunction + + function logic [3:0] lbe(int unsigned index); + if(USER_WIDTH== 137) begin + return vif.cb.TUSER[(index+1)*4+7 -: 4]; + end else if (USER_WIDTH == 60) begin + return vif.cb.TUSER[7:4]; + end else begin + $write("NOT SUPPORTED AXI USER_WIDTH\n"); + $stop(); + end + endfunction + + function int sofPos(int index); + if(SOF_POS_WIDTH == 0) begin + return 0; + end + + if (USER_WIDTH==137) // ULTRASCALE + return index; + else begin // 7SERIES + return 0; + end + endfunction + + function int eofPos(int index); + int pos = 0; + int j = 0; + + if (EOF_POS_WIDTH == 0) begin + return 0; + end + + if (USER_WIDTH==137) begin // ULTRASCALE + if ((vif.cb.TUSER[26] && vif.cb.TUSER[31:31] == index)) + return vif.cb.TUSER[30:28]; + if ((vif.cb.TUSER[27] && vif.cb.TUSER[35:35] == index)) + return vif.cb.TUSER[34:32]; + end else begin // 7SERIES + for (j = 0; j < REGION_ITEMS; j++) begin + if (vif.cb.TKEEP[j]==1'b0) + break; + pos = j; + end + return pos; + end + return -1; + endfunction + + function int isSOF(int index); + if (USER_WIDTH==137) begin // ULTRASCALE + if ((vif.cb.TUSER[20] && vif.cb.TUSER[23:23] == index) || + (vif.cb.TUSER[21] && vif.cb.TUSER[25:25] == index)) + return 1; + end else begin // 7SERIES + if (!old_inframe) + return vif.cb.TVALID; + end + return 0; + endfunction + + function int isEOF(int index); + if (USER_WIDTH==137) begin // ULTRASCALE + if ((vif.cb.TUSER[26] && vif.cb.TUSER[31:31] == index) || + (vif.cb.TUSER[27] && vif.cb.TUSER[35:35] == index)) + return 1; + end else begin // 7SERIES + return hasEOF(); // only 1 region + end + return 0; + endfunction + + task run_meter(); + speed_curr = 0; + while (enabled) begin + time speed_start_time; + time speed_end_time; + const int unsigned mesures = 100; + string msg; + + speed_end_time = $time(); + forever begin + time step_speed_end_time = speed_end_time; + time step_speed_start_time; + + for (int unsigned it = 0; it < mesures; it++) begin + step_speed_start_time = step_speed_end_time; + + #(1us); + step_speed_end_time = $time(); + speed.next_val(real'(speed_curr)/((step_speed_end_time-step_speed_start_time)/1ns)); + + speed_curr = 0; + end + + begin + real min, max, avg, std_dev; + + speed_start_time = speed_end_time; + speed_end_time = step_speed_end_time; + speed.count(min, max, avg, std_dev); + msg = $sformatf("\n\tSpeed [%0dns:%0dns]\n\t\tAverage : %0.2fGb/s std_dev %0.2fGb/s\n\t\tmin : %0.2fGb/s max %0.2fGb/s", + speed_start_time/1ns, speed_end_time/1ns, avg*ITEM_WIDTH, std_dev*ITEM_WIDTH, min*ITEM_WIDTH, max*ITEM_WIDTH); + $write({"\n", this.inst , "\n", msg, "\n"}); + speed.reset(); + end + end + end + endtask + + + virtual task run(); + inframe = 0; + + fork + run_meter(); + join_none + + + while (enabled) begin + int unsigned data_frame_size = 0; + + do begin + @(vif.monitor_cb); + end while (enabled && !(vif.monitor_cb.TVALID && vif.monitor_cb.TREADY)); + + if (!enabled) + break; + + for (int unsigned it = 0; it < REGIONS; it++) begin + if (inframe == 1) begin + if (isEOF(it)) begin + data_frame_size += eofPos(it)+1; + inframe = 0; + if (isSOF(it)) begin + data_frame_size += (REGION_SIZE - sofPos(it))*BLOCK_SIZE; + inframe = 1; + end + old_inframe = inframe; + end else begin + data_frame_size += REGION_SIZE*BLOCK_SIZE; + end + end else begin + if (isSOF(it)) begin + if (isEOF(it)) begin + data_frame_size += (eofPos(it)+1 - sofPos(it)*BLOCK_SIZE); + inframe = 0; + end else begin + data_frame_size += (REGION_SIZE - sofPos(it))*BLOCK_SIZE; + inframe = 1; + end + old_inframe = inframe; + end else begin + data_frame_size += 0; + end + end + end + speed_curr += data_frame_size; + end + endtask + +endclass diff --git a/comp/ver/axi/sv_axi_pcie_pkg.sv b/comp/ver/axi/sv_axi_pcie_pkg.sv index 7cc4cbc82..be22177eb 100644 --- a/comp/ver/axi/sv_axi_pcie_pkg.sv +++ b/comp/ver/axi/sv_axi_pcie_pkg.sv @@ -15,6 +15,7 @@ package sv_axi_pcie_pkg; import sv_axi_pkg::*; `include "axi4s_rc_agent.sv" + `include "axi4s_rq_meter.sv" `include "axi4s_rq_agent.sv" endpackage diff --git a/comp/ver/pcie/avalon_rq_monitor.sv b/comp/ver/pcie/avalon_rq_monitor.sv index 2831b1bd5..ae605fd18 100644 --- a/comp/ver/pcie/avalon_rq_monitor.sv +++ b/comp/ver/pcie/avalon_rq_monitor.sv @@ -14,20 +14,65 @@ class avalon_rq_monitor extends sv_common_pkg::Monitor; logic [31:0] data[$]; PcieRequest hl_tr; + protected sv_common_pkg::stats speed; + protected int unsigned speed_curr; - function new (string inst = ""); - super.new(inst); - avalon_rq_cbs = new(); - endfunction + function new (string inst = ""); + super.new(inst); + avalon_rq_cbs = new(); + speed = new(); + endfunction function void verbosity_set(int unsigned level); verbosity = level; endfunction + task run_meter(); + speed_curr = 0; + while (enabled) begin + time speed_start_time; + time speed_end_time; + const int unsigned mesures = 100; + string msg; + + speed_end_time = $time(); + forever begin + time step_speed_end_time = speed_end_time; + time step_speed_start_time; + + for (int unsigned it = 0; it < mesures; it++) begin + step_speed_start_time = step_speed_end_time; + + #(1us); + step_speed_end_time = $time(); + speed.next_val(real'(speed_curr)/((step_speed_end_time-step_speed_start_time)/1ns)); + + speed_curr = 0; + end + + begin + real min, max, avg, std_dev; + + speed_start_time = speed_end_time; + speed_end_time = step_speed_end_time; + speed.count(min, max, avg, std_dev); + msg = $sformatf("\n\tSpeed [%0dns:%0dns]\n\t\tAverage : %0.2fGb/s std_dev %0.2fGb/s\n\t\tmin : %0.2fGb/s max %0.2fGb/s", + speed_start_time/1ns, speed_end_time/1ns, avg*32, std_dev*32, min*32, max*32); + $write({"\n", this.inst , "\n", msg, "\n"}); + speed.reset(); + end + end + end + endtask + virtual task run(); sv_common_pkg::Transaction common_tr; avst_rx::transaction tr; + fork + run_meter(); + join_none; + while(enabled) begin avalon_rq_cbs.get(common_tr); $cast(tr, common_tr); @@ -84,6 +129,7 @@ class avalon_rq_monitor extends sv_common_pkg::Monitor; for (int i = 0; i < m_end; i++) begin data.push_back(tr.data[(i+1)*32-1 -:32]); end + speed_curr += m_end; end if(tr.eop == 1'b1) begin diff --git a/comp/ver/pcie/axi_agent.sv b/comp/ver/pcie/axi_agent.sv index 92d3aebbd..8a7aff296 100644 --- a/comp/ver/pcie/axi_agent.sv +++ b/comp/ver/pcie/axi_agent.sv @@ -71,6 +71,7 @@ class axi_agent #(RCB, MPS, DEVICE, DATA_WIDTH) extends agent #(RCB, MPS); //AXI AGENTS sv_axi_pcie_pkg::Axi4S_RQ_agent #(DATA_WIDTH, RQ_TUSER_WIDTH, 32, RQ_ST_COUNT) axiRQ; + sv_axi_pcie_pkg::Axi4S_RQ_meter #(DATA_WIDTH, RQ_TUSER_WIDTH, 32, RQ_ST_COUNT) axiRQ_meter; AxiResponder #(DATA_WIDTH, RQ_TUSER_WIDTH, 32) axiRQ_responder; AxiDriver #(DATA_WIDTH, RC_TUSER_WIDTH, 32, RC_ST_COUNT) axiRC; string inst; @@ -82,6 +83,7 @@ class axi_agent #(RCB, MPS, DEVICE, DATA_WIDTH) extends agent #(RCB, MPS); rq_monitor = new(); rq_monitor.setCallbacks(this.tags_req_cbs); axiRQ = new({inst, "AXI Request "}, vif_rx); + axiRQ_meter = new({inst, "AXI Meter "}, vif_rx); axiRQ.setCallbacks(rq_monitor.axi_rq_cbs); axiRQ_responder = new({inst, " AXI Responder"}, vif_rx); @@ -94,6 +96,7 @@ class axi_agent #(RCB, MPS, DEVICE, DATA_WIDTH) extends agent #(RCB, MPS); task setEnabled(); axiRQ.setEnabled(); + axiRQ_meter.setEnabled(); rq_monitor.setEnabled(); super.setEnabled(); axiRQ_responder.setEnabled(); @@ -103,6 +106,7 @@ class axi_agent #(RCB, MPS, DEVICE, DATA_WIDTH) extends agent #(RCB, MPS); task setDisabled(); axiRQ.setDisabled(); + axiRQ_meter.setDisabled(); rq_monitor.setDisabled(); super.setDisabled(); axiRQ_responder.setDisabled(); diff --git a/comp/ver/stats.sv b/comp/ver/stats.sv new file mode 100644 index 000000000..073a9568c --- /dev/null +++ b/comp/ver/stats.sv @@ -0,0 +1,68 @@ +/* + * file : stats.sv + * Copyright (C) 2024 CESNET z. s. p. o. + * description: this class count statistics + * date : 2024 + * author : Radek Iša + * + * SPDX-License-Identifier: BSD-3-Clause +*/ + +class stats; + + local real min; + local real max; + local real sum; + local real sum2; + + int unsigned values; + + function new(); + reset(); + endfunction + + + function void count(output real min, real max, real avg, real std_dev); + real avg_local; + + min = this.min; + max = this.max; + + avg_local = sum/values; + avg = avg_local; + + if (values > 1) begin + std_dev = (1.0/(values-1)*(sum2 - values*(avg_local**2)))**0.5; + end else begin + std_dev = 0; + end + endfunction + + function void reset(); + values = 0; + sum = 0; + sum2 = 0; + endfunction + + function void next_val(real val); + if (values == 0) begin + min = val; + max = val; + end else begin + if (min > val) begin + min = val; + end + + if (max < val) begin + max = val; + end + end + + sum += val; + sum2 += val**2; + + values++; + endfunction +endclass + + diff --git a/comp/ver/sv_common_pkg.sv b/comp/ver/sv_common_pkg.sv index 634d531c1..33c934962 100644 --- a/comp/ver/sv_common_pkg.sv +++ b/comp/ver/sv_common_pkg.sv @@ -25,4 +25,5 @@ package sv_common_pkg; `include "transaction_table.sv" `include "sequence.sv" `include "sequencer.sv" + `include "stats.sv" endpackage : sv_common_pkg