AMBA总线-结合axi-vip对axi4协议的理解2

在开始新的内容之前想强调一下上篇文章中的tvip_axi_payload_store类,它主要是其到一个item中间缓存的作用,基于此,内部会有一些地址、数据、响应的队列,除此以外内部还定义了一些函数;

上篇文章分析axi-vip的master driver和item,接下来继续分析monitor的部分,先看第一个大类,tvip_axi_monitor_base,后续的其他monitor都是继承与他的。

整体框架也是类似于driver的框架:

protected task main();
    fork
      address_monitor_thread();
      write_data_monitor_thread();
      response_mointor_thread();
    join
  endtask

第一个任务,address_monitor_thread任务,具体代码如下:

protected task address_monitor_thread();
    tvip_axi_item item;

    forever begin
      wait_for_address_valid();
      sample_address(item);

      wait_for_address_ready();
      finish_address(item);
    end
  endtask

wait_for_address_valid任务主要是等aw通道或者ar通道的valid信号;wait_for_address_ready任务主要是等aw通道或者ar通道的ready信号;finish_address任务主要执行end_address任务和将item赋值为null的任务,对于end_address来说,主要做的是往端口里送数据,主要任务如下:

task end_address(tvip_axi_item item);
    super.end_address(item);
    address_item_port.write(item);
    if (item.request_ended()) begin
      request_item_port.write(item);
    end
  endtask

下面重点分析sample_address任务:

需要注意的是,这里分析需要把sample address任务和write_data_monitor_thread任务中的get_write_data_store任务一起分析。两个任务之间的信息交互是通过write_data_store[0][$]和write_data_store[1][$]两个队列进行交互的,整体结构如下:

protected virtual task sample_address(ref tvip_axi_item item);
    tvip_axi_payload_store  store;

    if (is_write_component() && (write_data_stores[1].size() > 0)) begin
      store = write_data_stores[1].pop_front();
      item  = store.item;
    end
    if (item == null) begin
      item  = create_monitor_item();
      store = tvip_axi_payload_store::create(item);
      if (is_write_component()) begin
        write_data_stores[0].push_back(store);
      end
    end

    item.access_type  = (is_write_component()) ? TVIP_AXI_WRITE_ACCESS : TVIP_AXI_READ_ACCESS;
    item.id           = get_address_id();
    item.address      = get_address();
    item.burst_length = get_burst_length();
    item.burst_size   = get_burst_size();
    item.burst_type   = get_burst_type();
    item.protection   = get_protection();
    item.qos          = get_qos();

    begin_address(item);
    response_stores[item.id].push_back(store);
  endtask

接下来看write_data_monitor_thread,整个任务主要执行的内容就是:(1)等写数据的valid(2)store为null的时候,拿store,也就是前面框架图中的任务(3)等ready信号(4)采集写数据。

get_write_data_store任务主要执行的内容如下(也就是语句 store = get_write_data_store()):

protected function tvip_axi_payload_store get_write_data_store();
    if (write_data_stores[0].size() > 0) begin
      return write_data_stores[0].pop_front();
    end
    else begin
      tvip_axi_item           item;
      tvip_axi_payload_store  store;
      item  = create_monitor_item();
      store = tvip_axi_payload_store::create(item);
      write_data_stores[1].push_back(store);
      return store;
    end
  endfunction

采集store的任务,sample_write_data(store),如下:

protected virtual task sample_write_data(ref tvip_axi_payload_store store);
    store.store_write_data(get_write_data(), get_strobe());
    if (get_write_data_last()) begin
      store.pack_write_data();
      end_write_data(store.item);
      store = null;
    end
  endtask

其中end_write_data就是相当于从通道发送store中的item给别的组件。

最后看response_mointor_thread线程,这个线程和driver中的关于response的线程是类似的,但是需要注意这里的部分需要和sample address任务中的第七点任务(框图中的第七点)对应,框图中的第七点任务表示的是:

response_stores[item.id].push_back(store);

接下来看response_mointor_thread线程的整体任务是:

protected task response_mointor_thread();
    bit         busy;
    tvip_axi_id id;
    tvip_axi_id current_id;

    forever begin
      wait_for_response_valid();

      id  = get_response_id();
      if ((!busy) || (id != current_id)) begin
        if (is_valid_response(id)) begin
          busy        = 1;
          current_id  = id;
          if (!response_stores[current_id][0].item.response_began()) begin
            begin_response(response_stores[current_id][0].item);
          end
        end
        else begin
          busy  = 0;
          `uvm_warning("UNEXPECTED_RESPONSE", $sformatf("unexpected response: id %h", id))
          continue;
        end
      end

      wait_for_response_ready();
      sample_response(current_id, busy);
    end
  endtask

注意这里的is_valid_response任务,这里执行的内容如下:

 protected function bit is_valid_response(tvip_axi_id id);
    return
      response_stores.exists(id) &&
      response_stores[id].size() > 0;
  endfunction

而这里的response_stores和sample address中的response_stores是一样的,也就是说这个id的response是否有效的前提是前面已经经历过针对这个id的地址采集。

下面是sample_response的内容

protected virtual task sample_response(
    input tvip_axi_id id,
    ref   bit         busy
  );
    tvip_axi_payload_store  store;

    store = response_stores[id][0];
    store.store_response(get_response(), get_read_data());
    if (get_response_last()) begin
      store.pack_response();
      end_response(store.item);
      void'(response_stores[id].pop_front());
      busy  = 0;
    end
  endtask

核心的点在于store.store_response(get_response(), get_read_data());store_response表示的就是存取response和read data到store内部的队列中。另外,get_response任务如下:

protected function tvip_axi_response get_response();
    return (write_component) ? vif.monitor_cb.bresp : vif.monitor_cb.rresp;
  endfunction
protected function tvip_axi_data get_read_data();
    return (write_component) ? '0 : vif.monitor_cb.rdata;
  endfunction

如果执行get_response_last,也就是最后一次的response的数据pack_response(也就是把store中的response放到item中去存储),然后发送出去。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值