OpenCores
URL https://opencores.org/ocsvn/qaz_libs/qaz_libs/trunk

Subversion Repositories qaz_libs

[/] [qaz_libs/] [trunk/] [axi4_lib/] [sim/] [src/] [axi4_models/] [axi4_arbiter_pkg.sv] - Rev 31

Compare with Previous | Blame | View Log

//////////////////////////////////////////////////////////////////////
////                                                              ////
//// Copyright (C) 2015 Authors and OPENCORES.ORG                 ////
////                                                              ////
//// This source file may be used and distributed without         ////
//// restriction provided that this copyright statement is not    ////
//// removed from the file and that any derivative work contains  ////
//// the original copyright notice and the associated disclaimer. ////
////                                                              ////
//// This source file is free software; you can redistribute it   ////
//// and/or modify it under the terms of the GNU Lesser General   ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any   ////
//// later version.                                               ////
////                                                              ////
//// This source is distributed in the hope that it will be       ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
//// PURPOSE.  See the GNU Lesser General Public License for more ////
//// details.                                                     ////
////                                                              ////
//// You should have received a copy of the GNU Lesser General    ////
//// Public License along with this source; if not, download it   ////
//// from http://www.opencores.org/lgpl.shtml                     ////
////                                                              ////
//////////////////////////////////////////////////////////////////////


package axi4_arbiter_pkg;

  // --------------------------------------------------------------------
  //
  import axi4_models_pkg::*;
  import bfm_pkg::*;
  import logger_pkg::*;


  // --------------------------------------------------------------------
  //
  virtual class base_request_class #(A, N, I);

    string kind;
    int id = -1;

    //--------------------------------------------------------------------
    //
    pure virtual function void write_ax_if(axi4_channel_if_class #(A, N, I) channel);
    pure virtual function void copy_ax_if(axi4_channel_if_class #(A, N, I) channel);


  // --------------------------------------------------------------------
  //
  endclass: base_request_class


  // --------------------------------------------------------------------
  //
  class write_request_class #(A, N, I)
    extends base_request_class #(A, N, I);

    logic [(A-1):0]    awaddr;
    logic [1:0]        awburst;
    logic [(I-1):0]    awid;
    logic [7:0]        awlen;
    logic [2:0]        awsize;
    logic [3:0]        awcache;
    logic              awlock;
    logic [2:0]        awprot;
    logic [3:0]        awqos;
    logic [3:0]        awregion;


    // --------------------------------------------------------------------
    //
    function void write_ax_if(axi4_channel_if_class #(A, N, I) channel);
      axi4_aw_if_class #(A, N, I) aw_if_h;
      $cast(aw_if_h, channel);
      aw_if_h.awaddr    = awaddr;
      aw_if_h.awburst   = awburst;
      aw_if_h.awid      = awid;
      aw_if_h.awlen     = awlen;
      aw_if_h.awsize    = awsize;
      aw_if_h.awcache   = awcache;
      aw_if_h.awlock    = awlock;
      aw_if_h.awprot    = awprot;
      aw_if_h.awqos     = awqos;
      aw_if_h.awregion  = awregion;
    endfunction: write_ax_if


    // --------------------------------------------------------------------
    //
    function void copy_ax_if(axi4_channel_if_class #(A, N, I) channel);
      axi4_aw_if_class #(A, N, I) aw_if_h;
      $cast(aw_if_h, channel);
      awaddr    = aw_if_h.awaddr;
      awburst   = aw_if_h.awburst;
      awid      = aw_if_h.awid;
      awlen     = aw_if_h.awlen;
      awsize    = aw_if_h.awsize;
      awcache   = aw_if_h.awcache;
      awlock    = aw_if_h.awlock;
      awprot    = aw_if_h.awprot;
      awqos     = aw_if_h.awqos;
      awregion  = aw_if_h.awregion;
    endfunction: copy_ax_if


    //--------------------------------------------------------------------
    function new(int id);
      super.new;
      this.kind = "WRITE";
      this.id = id;
    endfunction: new


  // --------------------------------------------------------------------
  //
  endclass: write_request_class


  // --------------------------------------------------------------------
  //
  class read_request_class #(A, N, I)
    extends base_request_class #(A, N, I);

    logic [(A-1):0]    araddr;
    logic [1:0]        arburst;
    logic [(I-1):0]    arid;
    logic [7:0]        arlen;
    logic [2:0]        arsize;
    logic [3:0]        arcache;
    logic              arlock;
    logic [2:0]        arprot;
    logic [3:0]        arqos;
    logic [3:0]        arregion;

    // --------------------------------------------------------------------
    //
    function void write_ax_if(axi4_channel_if_class #(A, N, I) channel);
      axi4_ar_if_class #(A, N, I) ar_if_h;
      $cast(ar_if_h, channel);
      ar_if_h.araddr    = araddr;
      ar_if_h.arburst   = arburst;
      ar_if_h.arid      = arid;
      ar_if_h.arlen     = arlen;
      ar_if_h.arsize    = arsize;
      ar_if_h.arcache   = arcache;
      ar_if_h.arlock    = arlock;
      ar_if_h.arprot    = arprot;
      ar_if_h.arqos     = arqos;
      ar_if_h.arregion  = arregion;
    endfunction: write_ax_if


    // --------------------------------------------------------------------
    //
    function void copy_ax_if(axi4_channel_if_class #(A, N, I) channel);
      axi4_ar_if_class #(A, N, I) ar_if_h;
      $cast(ar_if_h, channel);
      araddr    = ar_if_h.araddr;
      arburst   = ar_if_h.arburst;
      arid      = ar_if_h.arid;
      arlen     = ar_if_h.arlen;
      arsize    = ar_if_h.arsize;
      arcache   = ar_if_h.arcache;
      arlock    = ar_if_h.arlock;
      arprot    = ar_if_h.arprot;
      arqos     = ar_if_h.arqos;
      arregion  = ar_if_h.arregion;
    endfunction: copy_ax_if


    //--------------------------------------------------------------------
    function new(int id);
      super.new;
      this.kind = "READ";
      this.id = id;
    endfunction: new


  // --------------------------------------------------------------------
  //
  endclass: read_request_class


  // --------------------------------------------------------------------
  //
  class requester_class #(A, N, I)
    extends axi4_slave_model_class #(A, N, I);

    mailbox #(base_request_class #(A, N, I)) q;
    semaphore read_done;
    semaphore write_done;
    int id = -1;
    logger_class log;


    // --------------------------------------------------------------------
    //
    task automatic run_read_interface;
      read_request_class #(A, N, I) r_req_h;
      read_done = new;
      forever
        @(axi4_s.cb_s)
        begin
          ar_q_h.q.get(ar_if_h);
          log.debug($sformatf("%m | start"));
          log.debug($sformatf("%m | araddr = 0x%h", ar_if_h.araddr));
          log.debug($sformatf("%m | arlen  = 0x%h", ar_if_h.arlen));
          r_req_h = new(id);
          r_req_h.copy_ax_if(ar_if_h);
          q.put(r_req_h);
          read_done.get();
          log.debug($sformatf("%m | done"));
        end
    endtask: run_read_interface


    // --------------------------------------------------------------------
    //
    task run_write_interface;
      write_request_class #(A, N, I) w_req_h;
      write_done = new;
      forever
        @(axi4_s.cb_s)
        begin
          aw_q_h.q.get(aw_if_h);
          log.debug($sformatf("%m | start"));
          log.debug($sformatf("%m | awaddr = 0x%h", aw_if_h.awaddr));
          log.debug($sformatf("%m | awlen  = 0x%h", aw_if_h.awlen));
          w_req_h = new(id);
          w_req_h.copy_ax_if(aw_if_h);
          q.put(w_req_h);
          write_done.get();
          log.debug($sformatf("%m | done"));
        end
    endtask: run_write_interface


    // --------------------------------------------------------------------
    //
    task run_model;
      wait(axi4_s.cb_s.aresetn);
      axi4_s.zero_cycle_delay();

      aw_q_h.run_q();
      w_q_h.run_q();
      b_q_h.run_q();
      ar_q_h.run_q();
      r_q_h.run_q();

      fork
        run_read_interface();
      join_none

      fork
        run_write_interface();
      join_none

    endtask: run_model


    //--------------------------------------------------------------------
    function new(int id, virtual axi4_if  #(.A(A), .N(N), .I(I)) axi4_s);
      super.new(axi4_s);
      this.aw_q_h = new(axi4_s, 2);
      this.w_q_h = new(axi4_s, 16);
      this.b_q_h = new(axi4_s, 2);
      this.ar_q_h = new(axi4_s, 2);
      this.r_q_h = new(axi4_s, 16);
      this.id = id;
      this.q = new(1);
      this.log = new();
    endfunction: new


  // --------------------------------------------------------------------
  //
  endclass: requester_class


  // --------------------------------------------------------------------
  //
  class axi4_granter_class #(A, N, I)
    extends axi4_master_model_class #(A, N, I);

    logger_class log;


    // --------------------------------------------------------------------
    //
    task run_model;
      wait(axi4_m.cb_s.aresetn);
      axi4_m.zero_cycle_delay();

      aw_q_h.run_q();
      w_q_h.run_q();
      b_q_h.run_q();
      ar_q_h.run_q();
      r_q_h.run_q();
    endtask: run_model


    //--------------------------------------------------------------------
    function new(virtual axi4_if  #(.A(A), .N(N), .I(I)) axi4_m);
      super.new(axi4_m);
      this.aw_q_h = new(axi4_m, 2);
      this.w_q_h = new(axi4_m, 16);
      this.b_q_h = new(axi4_m, 2);
      this.ar_q_h = new(axi4_m, 2);
      this.r_q_h = new(axi4_m, 16);
      this.log = new();
    endfunction: new


  // --------------------------------------------------------------------
  //
  endclass: axi4_granter_class


  // --------------------------------------------------------------------
  //
  class axi4_arbiter_class #(A, N, I);

    axi4_granter_class #(A, N, I) g_h;
    requester_class #(A, N, I) r_h[];
    mailbox #(int) grant;
    int count = -1;
    int current = 0, previous;
    logger_class log;


    // --------------------------------------------------------------------
    //
    task automatic do_read(requester_class #(A, N, I) r_h);
      int id;
      read_request_class #(A, N, I) r_req_h;
      base_request_class #(A, N, I) request;
      log.debug($sformatf("%m | read grant for %d", r_h.id));
      r_h.q.get(request);
      $cast(r_req_h, request);

      g_h.ar_if_h = new(g_h.axi4_m);
      r_req_h.write_ax_if(g_h.ar_if_h);
      g_h.ar_q_h.q.put(g_h.ar_if_h);

      for(int i = 0; i < r_h.ar_if_h.arlen + 1; i++)
      begin
        g_h.r_if_h = new(g_h.axi4_m);
        r_h.r_if_h = new(r_h.axi4_s);
        g_h.r_q_h.q.get(g_h.r_if_h);
        r_h.r_if_h.copy(g_h.r_if_h);
        r_h.r_q_h.q.put(r_h.r_if_h);
        @(r_h.axi4_s.cb_s);
      end

      r_h.read_done.put();
      grant.get(id);
      log.debug($sformatf("%m | read grant for %d done", id));
    endtask: do_read


    // --------------------------------------------------------------------
    //
    task automatic do_write(requester_class #(A, N, I) r_h);
      int id;
      write_request_class #(A, N, I) w_req_h;
      base_request_class #(A, N, I) request;
      log.debug($sformatf("%m | write grant for %d", r_h.id));
      r_h.q.get(request);
      $cast(w_req_h, request);

      g_h.aw_if_h = new(g_h.axi4_m);
      w_req_h.write_ax_if(g_h.aw_if_h);
      g_h.aw_q_h.q.put(g_h.aw_if_h);

      for(int i = 0; i < r_h.aw_if_h.awlen + 1; i++)
      begin
        r_h.w_if_h = new(r_h.axi4_s);
        g_h.w_if_h = new(g_h.axi4_m);
        r_h.w_q_h.q.get(r_h.w_if_h);
        g_h.w_if_h.copy(r_h.w_if_h);
        g_h.w_q_h.q.put(g_h.w_if_h);
        @(r_h.axi4_s.cb_s);
      end

      g_h.b_q_h.q.get(g_h.b_if_h);
      r_h.b_if_h = new(r_h.axi4_s);
      r_h.b_if_h.copy(g_h.b_if_h);
      r_h.b_q_h.q.put(r_h.b_if_h);
      r_h.write_done.put();
      grant.get(id);
      log.debug($sformatf("%m | write grant for %d done", id));
    endtask: do_write


    // --------------------------------------------------------------------
    //
    task automatic give_grant(requester_class #(A, N, I) r_h);
      base_request_class #(A, N, I) request;
      grant.put(r_h.id);
      r_h.q.peek(request);
      log.debug($sformatf("%m | %d got grant for %s", r_h.id, request.kind));

      if(request.kind.toupper == "WRITE")
        do_write(r_h);
      else if(request.kind.toupper == "READ")
        do_read(r_h);
      else
        $stop;

      current = (current + count + 1) % count;
      log.debug($sformatf("%m | new current = %d", current));
    endtask: give_grant


    // --------------------------------------------------------------------
    //
    task automatic do_arbitration;
      wait(g_h.axi4_m.cb_m.aresetn);
      g_h.axi4_m.zero_cycle_delay();
      forever
        @(g_h.axi4_m.cb_m)
        begin
          for(int i = current; i < current + count; i++)
            if(r_h[i % count].q.num > 0)
            begin
              give_grant(r_h[i % count]);
              break;
            end
        end
    endtask: do_arbitration


    //--------------------------------------------------------------------
    function void debug_enable;
      log.debug_enable();
      g_h.log.debug_enable();
      foreach(r_h[i])
        r_h[i].log.debug_enable();
    endfunction: debug_enable


    //--------------------------------------------------------------------
    function new
      (
        virtual axi4_if  #(A, N, I) axi4_s[],
        virtual axi4_if  #(.A(A), .N(N), .I(I)) axi4_m
      );
      this.grant = new(1);
      this.g_h = new(axi4_m);
      this.count = axi4_s.size;
      this.r_h = new[axi4_s.size];
      this.log = new;

      foreach(axi4_s[i])
        r_h[i] = new(i, axi4_s[i]);

      fork
        do_arbitration();
      join_none
    endfunction: new


  // --------------------------------------------------------------------
  //
  endclass: axi4_arbiter_class


// --------------------------------------------------------------------
//
endpackage: axi4_arbiter_pkg

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2019 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.