⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tb_env.sv

📁 VMM 文档加源码, synopsys公司很好的验证资料
💻 SV
📖 第 1 页 / 共 3 页
字号:
                  this.wait_if_stopped_or_empty(this.tx_chan);         this.tx_chan.activate(fr);         `vmm_callback(sw_emulator_callbacks,                       pre_frame_tx(this, fr, drop));         if (!drop) begin            bit   [31:0] bd_addr = this.avail_txbd.pop_front();            bit   [31:0] tx_pnt = this.cfg.txrx_pnt[bd_addr];            wb_cycle cyc = new(this.cfg.wb);            bit        wrap = 0;            this.tx_chan.start();            // Write the frame in the RAM            // Example 4-27            `vmm_trace(this.log, $psprintf("Buffering TX Frame at 'h%h:\n%s",                                           tx_pnt, fr.psdisplay("   ")));                        // We need full DWORDs            begin               int len = fr.byte_size();               bytes = new [len + (4 - len % 4)];               fr.byte_pack(bytes);               for (int i = 0; i < len; i += 4) begin                  this.ram.write(tx_pnt + i, {bytes[i], bytes[i+1], bytes[i+2], bytes[i+3]});               end            end            // Set the TxBD accordingly            if (this.avail_txbd.size() > 0) begin               if (this.avail_txbd[0] == 32'hFFFF_FFFF) begin                  wrap = 1;                  this.avail_txbd.pop_front();               end            end                        `vmm_debug(this.log, $psprintf("Updating TxBD at 'h%h",                                           bd_addr));                        tx_pnt[31:16] = fr.byte_size();            tx_pnt[15: 0] = 16'hD400;            tx_pnt[13] = wrap;            ok = cyc.randomize() with {kind == wb_cycle::WRITE;                                       addr == bd_addr;                                       data == tx_pnt;                                       sel  == 4'hF;};            if (!ok) begin               `vmm_fatal(this.log, "Unable to create WRITE cycle to TxBD");            end            this.host.exec_chan.put(cyc);            if (cyc.status !== wb_cycle::ACK) begin               `vmm_error(this.log, "Unable to write to TxBD");            end            this.busy_txbd.push_back(bd_addr);            if (wrap) this.busy_txbd.push_back(32'hFFFF_FFFF);            this.tx_chan.complete();            this.sb.sent_from_mac_side(fr);         end         this.tx_chan.remove();      end   endtask: tx_driver         local task int_serv();      wb_cycle cyc = new(this.cfg.wb);      bit [31:0] isr;      bit [31:0] val;      bit        ok;      bit ignore_fr;      // Interrupt service routine      while (1) begin         wait(tb_top.wb_int === 1'b1);         ignore_fr = 0;         ok = cyc.randomize() with {kind == wb_cycle::READ;                                    addr == 32'h0000_0004;  // INT_SOURCE                                    sel  == 4'hF;};         if (!ok) begin            `vmm_fatal(this.log, "Unable to create READ cycle to INT_SOURCE");         end         this.host.exec_chan.put(cyc);         if (cyc.status !== wb_cycle::ACK) begin            `vmm_error(this.log, "Unable to read INT_SOURCE");         end         // Do an immediate write-back to clear the interrupts         // so we won't miss one         cyc.kind = wb_cycle::WRITE;         this.host.exec_chan.put(cyc);         if (cyc.status !== wb_cycle::ACK) begin            `vmm_error(this.log, "Unable to write to INT_SOURCE");         end         // Analyze the cause(s) for the interrupt         isr = cyc.data;         if (isr[1]) begin // TXE            `vmm_error(this.log, "An error occured during the transmission of a frame");         end                  if (isr[1] || isr[0]) begin // TXB            integer n = 0;            `vmm_trace(this.log, "A frame has been transmitted...");            isr[1:0] = 2'b00;            if (this.busy_txbd.size() == 0) begin               `vmm_error(this.log, "Internal error: No busy TXBD");            end                        // A frame has been transmitted, check the transmit buffers...            while (this.busy_txbd.size() > 0) begin               bit [31:0] bd_addr = this.busy_txbd[0];               // Check if that TxBD has been transmitted               ok = cyc.randomize() with {kind == wb_cycle::READ;                                          addr == bd_addr;                                          sel  == 4'hF;};               if (!ok) begin                  `vmm_fatal(this.log, "Unable to create READ cycle to TxBD");               end               this.host.exec_chan.put(cyc);               if (cyc.status !== wb_cycle::ACK) begin                  `vmm_error(this.log, "Unable to read TxBD");               end               // Has this frame been transmitted?               if (cyc.data[15]) begin                  // No. This implies the subsequent frames have not                  // been transmitted either                  if (n == 0) `vmm_error(this.log, "No transmitted TxBD were found");                  break;               end               `vmm_trace(this.log, $psprintf("Frame from TxBD @ 'h%h was transmitted",                                              bd_addr));               // What errors happened when the frame was transmitted?               if (cyc.data[8]                   || cyc.data[3]                   || cyc.data[2]) begin                  string descr = "";                  string separator = " ";                  if (cyc.data[8]) begin                     descr = " Under-run";                     separator = "/";                  end                  if (cyc.data[3]) begin                     descr = {descr, separator, "Retry Limit"};                     separator = "/";                  end                  if (cyc.data[2]) descr = {descr, separator, "Late Coll"};                  `vmm_warning(this.log, {"Frame was transmitted with following errors:", descr});               end                                  // What non-errors happened?               `vmm_trace(this.log, $psprintf("Frame was transmitted with %0d attempts%s%s",                                              cyc.data[7:4],                                              (cyc.data[1]) ? ", deferred" : "",                                              (cyc.data[0]) ? ", carrier lost" : ""));                              // Indicate this TxBD is now available               n++;               this.avail_txbd.push_back(bd_addr);               this.busy_txbd.pop_front();               // Check if the wrap indicator comes next               if (this.busy_txbd.size() > 0 &&                   this.busy_txbd[0] == 32'hFFFF_FFFF) begin                  this.avail_txbd.push_back(32'hFFFF_FFFF);                  this.busy_txbd.pop_front();               end               -> this.avail_txbd_e;            end         end // TXB         if (isr[3]) begin // RXE`ifndef OC_ETHERNET_BUG            `vmm_error(this.log, "An error occured during the reception of a frame");`endif         end                  if (isr[3] || isr[2]) begin // RXB            integer n = 0;            `vmm_trace(this.log, "A frame has been received...");            isr[3:2] = 2'b00;                        // A frame has been received, check the receive buffers...            forever begin               bit [31:0] bd_addr = this.next_rxbd;               bit [31:0] rx_pnt;               bit [15:0] len;               logic [7:0] bytes[];               // Check if that RxBD contains a received frame               ok = cyc.randomize() with {kind == wb_cycle::READ;                                          addr == bd_addr;                                          sel  == 4'hF;};               if (!ok) begin                  `vmm_fatal(this.log, "Unable to create READ cycle to RxBD");               end               this.host.exec_chan.put(cyc);               if (cyc.status !== wb_cycle::ACK) begin                  `vmm_error(this.log, "Unable to read RxBD");               end               // Is there a frame in there?               if (cyc.data[15]) begin                  // No. This implies the subsequent buffers are empty as well                  if (n == 0) `vmm_error(this.log, "No received RxBD were found");                  break;               end               n++;               len = cyc.data[31:16];                              `vmm_trace(this.log, $psprintf("Frame from RxBD @ 'h%h was received",                                              bd_addr));               // What errors happened when the frame was transmitted?               if (cyc.data[6:0]) begin                  string descr = "";                  string separator = " ";                  if (cyc.data[0]) begin                     descr = " Late Collision";                     separator = "/";                  end                  if (cyc.data[1]) begin                     descr = {descr, separator, "Bad CRC"};                     separator = "/";                  end                  if (cyc.data[2]) begin                     descr = {descr, separator, "Too Short"};                     separator = "/";                  end                  if (cyc.data[3]) begin                     descr = {descr, separator, "Too Long"};                     separator = "/";                  end                  if (cyc.data[4]) begin                     descr = {descr, separator, "Dribble"};                     separator = "/";                  end                  if (cyc.data[5]) begin                     descr = {descr, separator, "Bad Symbol"};`ifdef OC_ETHERNET_BUG                     ignore_fr = 1;`endif                     separator = "/";                  end                  if (cyc.data[6]) begin                     descr = {descr, separator, "OverRun"};                     separator = "/";                  end                  `vmm_warning(this.log, {"Frame was received with following errors:", descr});               end                                  // Indicate this RxBD is now free               val = cyc.data;               val[15] = 1;               ok = cyc.randomize() with {kind == wb_cycle::WRITE;                                          addr == bd_addr;                                          data == val;                                          sel  == 4'hF;};               if (!ok) begin                  `vmm_fatal(this.log, "Unable to create WRITE cycle to RxBD");               end               this.host.exec_chan.put(cyc);               if (cyc.status !== wb_cycle::ACK) begin                  `vmm_error(this.log, "Unable to write RxBD");               end               // Get the frame from the buffer               rx_pnt = this.cfg.txrx_pnt[bd_addr];                           // We'll be recovering full DWORDs               bytes = new [len + (4 - len % 4)];               for (int i = 0; i < len; i += 4) begin                  {bytes[i], bytes[i+1], bytes[i+2], bytes[i+3]} = this.ram.read(rx_pnt + i);               end               begin                  eth_frame fr = new;                  fr.byte_unpack(bytes, 0, len-4); // Do not unpack FCS                  if (val[1]) fr.fcs = 32'hFFFF_FFFF;                  `vmm_trace(this.log, $psprintf("Retreived RX Frame from 'h%h:\n%s",                                                 rx_pnt, fr.psdisplay("   ")));                  if (!ignore_fr) begin                     this.sb.received_by_mac_side(fr);                  end               end               // Move on to the next RxBD               next_rxbd += 8;               if (val[13]) next_rxbd = 32'h0000_0400 + this.cfg.rx_bd_offset * 8;            end         end // RXB         if (isr[4]) begin // BUSY`ifndef OC_ETHERNET_BUG            `vmm_error(this.log, "Out of Rx buffers!");`endif            isr[4] = 0;         end         if (isr) begin            `vmm_error(this.log, $psprintf("Unserviced interrupts: %h", isr));         end      end   endtask: int_servendclassclass wb_cycle_resp_no_wss extends wb_cycle_resp;   function new(wb_cycle     req,                wb_slave_cfg cfg);      super.new(req, cfg);   endfunction   constraint no_wss {      n_wss == 0;   }   function vmm_data copy(vmm_data to);      wb_cycle_resp_no_wss tr;      if (to == null) tr = new(null, null);      else if (!$cast(tr, to)) begin         `vmm_fatal(this.log, "Unable to copy to non-wb_cycle_resp_no_wss instance");         return null;      end      copy = super.copy(tr);   endfunction: copyendclass// Example 5-37class dut_eth_frame extends eth_frame;   test_cfg cfg;   constraint match_dut_address {      if (!cfg.mac.promiscuous) dst == cfg.dut_addr;   }   constraint valid_src_address {      src == cfg.mac.addr;   }   function new(test_cfg cfg);      this.cfg = cfg;   endfunction: newendclass: dut_eth_frame// Example 4-13// Example 4-18class tb_env extends vmm_env;   test_cfg cfg;   // Example 4-20   eth_frame_atomic_gen host_src;   eth_frame_atomic_gen phy_src;   eth_mac       mac;   mii_phy_layer phy;   mii_monitor   mon;   wb_master host;   wb_slave  slv;   wb_ram    ram;   sw_emulator swem;   // Example 5-47   scoreboard sb;   // Example 4-18   // Example 4-19   function new();      super.new();      this.cfg = new;      $timeformat(-9, 0, "ns", 1);   endfunction: new   virtual function void gen_cfg();      super.gen_cfg();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -