data/full_repos/permissive/214858095/FPGA_Exploration/spartan6/B205mini/ISE_Project/lib/rfnoc/blocks/rfnoc_block_axi_ram_fifo/sim_axi_ram.sv
[Errno 2] No such file or directory: 'preprocess.output'
1: b"%Error: data/full_repos/permissive/214858095/FPGA_Exploration/spartan6/B205mini/ISE_Project/lib/rfnoc/blocks/rfnoc_block_axi_ram_fifo/sim_axi_ram.sv:114: syntax error, unexpected '=', expecting ',' or ';'\n  mailbox #(req_t) read_req   = new();   \n                              ^\n%Error: data/full_repos/permissive/214858095/FPGA_Exploration/spartan6/B205mini/ISE_Project/lib/rfnoc/blocks/rfnoc_block_axi_ram_fifo/sim_axi_ram.sv:115: syntax error, unexpected '=', expecting ',' or ';'\n  mailbox #(req_t) write_req  = new();   \n                              ^\n%Error: data/full_repos/permissive/214858095/FPGA_Exploration/spartan6/B205mini/ISE_Project/lib/rfnoc/blocks/rfnoc_block_axi_ram_fifo/sim_axi_ram.sv:116: syntax error, unexpected '=', expecting ',' or ';'\n  mailbox #(req_t) write_resp = new();   \n                              ^\n%Error: data/full_repos/permissive/214858095/FPGA_Exploration/spartan6/B205mini/ISE_Project/lib/rfnoc/blocks/rfnoc_block_axi_ram_fifo/sim_axi_ram.sv:291: syntax error, unexpected '@'\n      @(posedge s_aclk);\n      ^\n%Error: data/full_repos/permissive/214858095/FPGA_Exploration/spartan6/B205mini/ISE_Project/lib/rfnoc/blocks/rfnoc_block_axi_ram_fifo/sim_axi_ram.sv:313: Unsupported or unknown PLI call: $cast\n          assert ($cast(burst, s_axi_awburst)) else begin\n                  ^~~~~\n%Error: data/full_repos/permissive/214858095/FPGA_Exploration/spartan6/B205mini/ISE_Project/lib/rfnoc/blocks/rfnoc_block_axi_ram_fifo/sim_axi_ram.sv:331: Unsupported or unknown PLI call: $urandom_range\n        s_axi_awready <= $urandom_range(99) < waddr_stall_prob ? 0 : 1;\n                         ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/214858095/FPGA_Exploration/spartan6/B205mini/ISE_Project/lib/rfnoc/blocks/rfnoc_block_axi_ram_fifo/sim_axi_ram.sv:348: syntax error, unexpected '@'\n      @(posedge s_aclk);\n      ^\n%Error: data/full_repos/permissive/214858095/FPGA_Exploration/spartan6/B205mini/ISE_Project/lib/rfnoc/blocks/rfnoc_block_axi_ram_fifo/sim_axi_ram.sv:370: Unsupported or unknown PLI call: $cast\n          assert ($cast(burst, s_axi_awburst)) else begin\n                  ^~~~~\n%Error: data/full_repos/permissive/214858095/FPGA_Exploration/spartan6/B205mini/ISE_Project/lib/rfnoc/blocks/rfnoc_block_axi_ram_fifo/sim_axi_ram.sv:388: Unsupported or unknown PLI call: $urandom_range\n        s_axi_arready <= $urandom_range(99) < raddr_stall_prob ? 0 : 1;\n                         ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/214858095/FPGA_Exploration/spartan6/B205mini/ISE_Project/lib/rfnoc/blocks/rfnoc_block_axi_ram_fifo/sim_axi_ram.sv:409: syntax error, unexpected '@'\n        @(posedge s_aclk);\n        ^\n%Error: data/full_repos/permissive/214858095/FPGA_Exploration/spartan6/B205mini/ISE_Project/lib/rfnoc/blocks/rfnoc_block_axi_ram_fifo/sim_axi_ram.sv:421: syntax error, unexpected '@'\n        @(posedge s_aclk);\n        ^\n%Error: data/full_repos/permissive/214858095/FPGA_Exploration/spartan6/B205mini/ISE_Project/lib/rfnoc/blocks/rfnoc_block_axi_ram_fifo/sim_axi_ram.sv:462: Unsupported or unknown PLI call: $urandom_range\n          s_axi_wready <= $urandom_range(99) < wdata_stall_prob ? 0 : 1;\n                          ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/214858095/FPGA_Exploration/spartan6/B205mini/ISE_Project/lib/rfnoc/blocks/rfnoc_block_axi_ram_fifo/sim_axi_ram.sv:504: syntax error, unexpected '@'\n      @(posedge s_aclk);\n      ^\n%Error: data/full_repos/permissive/214858095/FPGA_Exploration/spartan6/B205mini/ISE_Project/lib/rfnoc/blocks/rfnoc_block_axi_ram_fifo/sim_axi_ram.sv:513: Unsupported or unknown PLI call: $urandom_range\n      if ($urandom_range(99) < wresp_stall_prob) begin\n          ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/214858095/FPGA_Exploration/spartan6/B205mini/ISE_Project/lib/rfnoc/blocks/rfnoc_block_axi_ram_fifo/sim_axi_ram.sv:515: syntax error, unexpected '@'\n          @(posedge s_aclk);\n          ^\n%Error: data/full_repos/permissive/214858095/FPGA_Exploration/spartan6/B205mini/ISE_Project/lib/rfnoc/blocks/rfnoc_block_axi_ram_fifo/sim_axi_ram.sv:517: Unsupported or unknown PLI call: $urandom_range\n        end while ($urandom_range(99) < wresp_stall_prob);\n                   ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/214858095/FPGA_Exploration/spartan6/B205mini/ISE_Project/lib/rfnoc/blocks/rfnoc_block_axi_ram_fifo/sim_axi_ram.sv:537: syntax error, unexpected '@'\n        @(posedge s_aclk);\n        ^\n%Error: data/full_repos/permissive/214858095/FPGA_Exploration/spartan6/B205mini/ISE_Project/lib/rfnoc/blocks/rfnoc_block_axi_ram_fifo/sim_axi_ram.sv:576: syntax error, unexpected '@'\n        @(posedge s_aclk);\n        ^\n%Error: data/full_repos/permissive/214858095/FPGA_Exploration/spartan6/B205mini/ISE_Project/lib/rfnoc/blocks/rfnoc_block_axi_ram_fifo/sim_axi_ram.sv:588: Unsupported or unknown PLI call: $urandom_range\n        if ($urandom_range(99) < rdata_stall_prob) begin\n            ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/214858095/FPGA_Exploration/spartan6/B205mini/ISE_Project/lib/rfnoc/blocks/rfnoc_block_axi_ram_fifo/sim_axi_ram.sv:590: syntax error, unexpected '@'\n            @(posedge s_aclk);\n            ^\n%Error: data/full_repos/permissive/214858095/FPGA_Exploration/spartan6/B205mini/ISE_Project/lib/rfnoc/blocks/rfnoc_block_axi_ram_fifo/sim_axi_ram.sv:592: Unsupported or unknown PLI call: $urandom_range\n          end while ($urandom_range(99) < rdata_stall_prob);\n                     ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/214858095/FPGA_Exploration/spartan6/B205mini/ISE_Project/lib/rfnoc/blocks/rfnoc_block_axi_ram_fifo/sim_axi_ram.sv:628: syntax error, unexpected '@'\n          @(posedge s_aclk);\n          ^\n%Error: Exiting due to 22 error(s)\n"
module sim_axi_ram #(
  parameter AWIDTH     = 32,
  parameter DWIDTH     = 64,
  parameter IDWIDTH    = 2,
  parameter BIG_ENDIAN = 0,
  parameter STALL_PROB = 25
) (
  input logic s_aclk,
  input logic s_aresetn,


  input  logic [IDWIDTH-1:0] s_axi_awid,
  input  logic [ AWIDTH-1:0] s_axi_awaddr,
  input  logic [        7:0] s_axi_awlen,
  input  logic [        2:0] s_axi_awsize,
  input  logic [        1:0] s_axi_awburst,
  input  logic               s_axi_awvalid,
  output logic               s_axi_awready,


  input  logic [  DWIDTH-1:0] s_axi_wdata,
  input  logic [DWIDTH/8-1:0] s_axi_wstrb,
  input  logic                s_axi_wlast,
  input  logic                s_axi_wvalid,
  output logic                s_axi_wready,


  output logic [IDWIDTH-1:0] s_axi_bid,
  output logic [        1:0] s_axi_bresp,
  output logic               s_axi_bvalid,
  input  logic               s_axi_bready,


  input  logic [IDWIDTH-1:0] s_axi_arid,
  input  logic [ AWIDTH-1:0] s_axi_araddr,
  input  logic [        7:0] s_axi_arlen,
  input  logic [        2:0] s_axi_arsize,
  input  logic [        1:0] s_axi_arburst,
  input  logic               s_axi_arvalid,
  output logic               s_axi_arready,


  output logic [       0:0] s_axi_rid,
  output logic [DWIDTH-1:0] s_axi_rdata,
  output logic [       1:0] s_axi_rresp,
  output logic              s_axi_rlast,
  output logic              s_axi_rvalid,
  input  logic              s_axi_rready
);

  localparam DEBUG = 0;


  localparam [AWIDTH-1:0] MASK_4K = {AWIDTH{1'b1}} << 12;





  
  typedef enum logic [1:0] { FIXED, INCR, WRAP }            burst_t;
  typedef enum logic [1:0] { OKAY, EXOKAY, SLVERR, DECERR } resp_t;

  typedef struct packed {
    longint             count;
    logic [IDWIDTH-1:0] id;
    logic [AWIDTH-1:0]  addr;
    logic [8:0]         len;
    logic [7:0]         size;
    burst_t             burst;
  } req_t;



  typedef bit [AWIDTH:0] addr_t;


  typedef logic [DWIDTH-1:0] data_t;


  typedef bit [DWIDTH/8-1:0] mask_t;






  byte             memory [addr_t];
  mailbox #(req_t) read_req   = new();
  mailbox #(req_t) write_req  = new();
  mailbox #(req_t) write_resp = new();

  longint req_count;
  longint compl_count;






  int waddr_stall_prob = STALL_PROB;
  int wdata_stall_prob = STALL_PROB;
  int wresp_stall_prob = STALL_PROB;
  int raddr_stall_prob = STALL_PROB;
  int rdata_stall_prob = STALL_PROB;


  function void set_stall_prob(int probability);
    assert(probability >= 0 && probability <= 100) else begin
      $error("Probability must be from 0 to 100");
    end
    waddr_stall_prob = probability;
    wdata_stall_prob = probability;
    wresp_stall_prob = probability;
    raddr_stall_prob = probability;
    rdata_stall_prob = probability;
  endfunction : set_stall_prob


  function void set_write_stall_prob(int probability);
    assert(probability >= 0 && probability <= 100) else begin
      $error("Probability must be from 0 to 100");
    end
    waddr_stall_prob = probability;
    wdata_stall_prob = probability;
    wresp_stall_prob = probability;
  endfunction : set_write_stall_prob


  function void set_read_stall_prob(int probability);
    assert(probability >= 0 && probability <= 100) else begin
      $error("Probability must be from 0 to 100");
    end
    raddr_stall_prob = probability;
    rdata_stall_prob = probability;
  endfunction : set_read_stall_prob


  function void set_waddr_stall_prob(int probability);
    assert(probability >= 0 && probability <= 100) else begin
      $error("Probability must be from 0 to 100");
    end
    waddr_stall_prob = probability;
  endfunction : set_waddr_stall_prob


  function void set_wdata_stall_prob(int probability);
    assert(probability >= 0 && probability <= 100) else begin
      $error("Probability must be from 0 to 100");
    end
    wdata_stall_prob = probability;
  endfunction : set_wdata_stall_prob


  function void set_wresp_stall_prob(int probability);
    assert(probability >= 0 && probability <= 100) else begin
      $error("Probability must be from 0 to 100");
    end
    wresp_stall_prob = probability;
  endfunction : set_wresp_stall_prob


  function void set_raddr_stall_prob(int probability);
    assert(probability >= 0 && probability <= 100) else begin
      $error("Probability must be from 0 to 100");
    end
    raddr_stall_prob = probability;
  endfunction : set_raddr_stall_prob


  function void set_rdata_stall_prob(int probability);
    assert(probability >= 0 && probability <= 100) else begin
      $error("Probability must be from 0 to 100");
    end
    rdata_stall_prob = probability;
  endfunction : set_rdata_stall_prob


  function int get_waddr_stall_prob();
    return waddr_stall_prob;
  endfunction : get_waddr_stall_prob


  function int get_wdata_stall_prob();
    return wdata_stall_prob;
  endfunction : get_wdata_stall_prob


  function int get_wresp_stall_prob();
    return wresp_stall_prob;
  endfunction : get_wresp_stall_prob


  function int get_raddr_stall_prob();
    return raddr_stall_prob;
  endfunction : get_raddr_stall_prob


  function int get_rdata_stall_prob();
    return rdata_stall_prob;
  endfunction : get_rdata_stall_prob







  function data_t read_mem(addr_t byte_addr, int num_bytes);
    data_t data;
    addr_t incr;

    if (BIG_ENDIAN) begin
      byte_addr = byte_addr + num_bytes-1;
      incr      = -1;
    end else begin
      incr      = 1;
    end

    for (int i = 0; i < num_bytes; i++) begin
      if (byte_addr >= 2**AWIDTH) begin
        $fatal(1, "Read extends beyond memory range");
      end
      if (memory.exists(byte_addr)) data[i*8 +: 8] = memory[byte_addr];
      else data[i*8 +: 8] = 'X;
      byte_addr += incr;
    end

    return data;
  endfunction : read_mem


  function void write_mem(addr_t byte_addr, int num_bytes, data_t data, mask_t mask);
    addr_t incr;

    if (BIG_ENDIAN) begin
      byte_addr = byte_addr + num_bytes-1;
      incr      = -1;
    end else begin
      incr      = 1;
    end

    for (int i = 0; i < num_bytes; i++) begin
      if (mask[i]) begin
        if (byte_addr >= 2**AWIDTH) begin
          $fatal(1, "Write extends beyond memory range");
        end
        memory[byte_addr] = data[i*8 +: 8];
      end
      byte_addr += incr;
    end
  endfunction : write_mem






  initial begin : write_req_proc
    req_t   req;
    burst_t burst;

    s_axi_awready <= 0;

    forever begin
      @(posedge s_aclk);
      if (!s_aresetn) continue;

      if (s_axi_awvalid) begin
        if (s_axi_awready) begin
          req.count = req_count;
          req.id    = s_axi_awid;
          req.addr  = s_axi_awaddr;
          req.len   = s_axi_awlen + 1;
          req.size  = 2**s_axi_awsize;
          req.burst = burst_t'(s_axi_awburst);


          assert (!$isunknown(req)) else begin
            $fatal(1, "Write request signals are unknown");
          end
          assert (s_axi_araddr % (DWIDTH/8) == 0) else begin
            $warning("Unaligned memory write");
          end
          assert (2**s_axi_awsize <= DWIDTH/8) else begin
            $fatal(1, "AWSIZE must not be larger than DWIDTH");
          end
          assert ($cast(burst, s_axi_awburst)) else begin
            $fatal(1, "Invalid AWBURST value");
          end
          assert ((s_axi_awaddr & MASK_4K) ==
            ((s_axi_awaddr + (s_axi_awlen+1)*(2**s_axi_awsize) - 1) & MASK_4K)) else begin
            $fatal(1, "Memory write burst crosses 4 KiB boundary");
          end

          if (DEBUG) begin
            $display("WRITE REQ: id=%X, addr=%X, len=%X, size=%X, burst=%s, %t, %m", 
              req.id, req.addr, req.len, req.size, req.burst.name, $realtime);
          end

          req_count++;
          write_req.put(req);
        end


        s_axi_awready <= $urandom_range(99) < waddr_stall_prob ? 0 : 1;
      end
    end
  end : write_req_proc






  initial begin : read_req_proc
    req_t   req;
    burst_t burst;

    s_axi_arready <= 0;

    forever begin
      @(posedge s_aclk);
      if (!s_aresetn) continue;

      if (s_axi_arvalid) begin
        if (s_axi_arready) begin
          req.count = req_count;
          req.id    = s_axi_arid;
          req.addr  = s_axi_araddr;
          req.len   = s_axi_arlen + 1;
          req.size  = 2**s_axi_arsize;
          req.burst = burst_t'(s_axi_arburst);


          assert(!$isunknown(req)) else begin
            $fatal(1, "Read request signals are unknown");
          end
          assert(s_axi_araddr % (DWIDTH/8) == 0) else begin
            $warning("Unaligned memory read");
          end
          assert(2**s_axi_arsize <= DWIDTH/8) else begin
            $fatal(1, "ARSIZE must not be larger than DWIDTH");
          end
          assert ($cast(burst, s_axi_awburst)) else begin
            $fatal(1, "Invalid ARBURST value");
          end
          assert ((s_axi_araddr & MASK_4K) ==
            ((s_axi_araddr + (s_axi_arlen+1)*(2**s_axi_arsize) - 1) & MASK_4K)) else begin
            $fatal(1, "Memory read burst crosses 4 KiB boundary");
          end

          if (DEBUG) begin
            $display("READ REQ:  id=%X, addr=%X, len=%X, size=%X, burst=%s, %t, %m", 
              req.id, req.addr, req.len, req.size, req.burst.name, $realtime);
          end

          req_count++;
          read_req.put(req);
        end


        s_axi_arready <= $urandom_range(99) < raddr_stall_prob ? 0 : 1;
      end
    end
  end : read_req_proc






  initial begin : write_data_proc
    req_t req;
    bit [AWIDTH-1:0] addr;

    forever begin

      s_axi_wready <= 0;
      write_req.get(req);


      while (compl_count < req.count) begin
        @(posedge s_aclk);
        if (!s_aresetn) break;
      end


      if (!s_aresetn) begin
        while(write_req.try_get(req));
        continue;
      end


      for (int i = 0; i < req.len; ) begin
        @(posedge s_aclk);
        if (!s_aresetn) break;


        if (s_axi_wvalid) begin
          if (s_axi_wready) begin

            if ($isunknown(s_axi_wstrb)) begin
              $fatal(1, "WSTRB is unknown");
            end
            if ($isunknown(s_axi_wdata)) begin
              $warning(1, "WDATA is unknown; data will be changed to zero");
            end

            case (req.burst)
              FIXED : begin
                addr = req.addr;
              end
              INCR : begin


                addr = req.addr + i*req.size;
                if (addr < req.addr) break;
              end
              WRAP : begin

                addr = req.addr + i*req.size;
              end
            endcase

            write_mem(addr, req.size, s_axi_wdata, s_axi_wstrb);

            if (DEBUG) begin
              $display("WRITE: count=%3X, ADDR=%X, DATA=%X, SIZE=%X, STRB=%X, %t, %m", 
                i, addr, s_axi_wdata, req.size, s_axi_wstrb, $realtime);
            end

            i++;
          end


          s_axi_wready <= $urandom_range(99) < wdata_stall_prob ? 0 : 1;
        end
      end


      if (!s_aresetn) begin
        while(write_req.try_get(req));
        continue;
      end

      compl_count++;


      write_resp.put(req);



      if (s_axi_wlast != 1'b1) begin
        $error("WLAST not asserted on last word of burst");
      end

    end
  end : write_data_proc






  initial begin : write_resp_proc
    req_t resp;
    bit [AWIDTH-1:0] addr;

    forever begin
      s_axi_bid    <= 'X;
      s_axi_bresp  <= 'X;
      s_axi_bvalid <= 0;


      write_resp.get(resp);
      @(posedge s_aclk);


      if (!s_aresetn) begin
        while(write_resp.try_get(resp));
        continue;
      end


      if ($urandom_range(99) < wresp_stall_prob) begin
        do begin
          @(posedge s_aclk);
          if (!s_aresetn) break;
        end while ($urandom_range(99) < wresp_stall_prob);


        if (!s_aresetn) begin
          while(write_resp.try_get(resp));
          continue;
        end
      end


      s_axi_bid    <= resp.id;
      s_axi_bresp  <= OKAY;
      s_axi_bvalid <= 1;

      if (DEBUG) begin
        $display("WRITE RESP: ID=%X, %t, %m", resp.id, $realtime);
      end


      do begin
        @(posedge s_aclk);
        if (!s_aresetn) break;
      end while (!s_axi_bready);


      s_axi_bid    <= 'X;
      s_axi_bresp  <= 'X;
      s_axi_bvalid <= 0;


      if (!s_aresetn) begin
        while(write_resp.try_get(resp));
        continue;
      end
    end
  end : write_resp_proc






  initial begin : read_data_proc
    req_t req;
    bit   [AWIDTH-1:0] addr;
    logic [DWIDTH-1:0] data;

    forever begin
      s_axi_rid    <= 'X;
      s_axi_rdata  <= 'X;
      s_axi_rresp  <= 'X;
      s_axi_rlast  <= 'X;
      s_axi_rvalid <= 0;


      read_req.get(req);


      do begin
        @(posedge s_aclk);
        if (!s_aresetn) break;
      end while (compl_count < req.count);


      if (!s_aresetn) begin
        while(read_req.try_get(req));
        continue;
      end

      for (int i = 0; i < req.len; i++) begin

        if ($urandom_range(99) < rdata_stall_prob) begin
          do begin
            @(posedge s_aclk);
            if (!s_aresetn) break;
          end while ($urandom_range(99) < rdata_stall_prob);
          if (!s_aresetn) break;
        end

        case (req.burst)
          FIXED : begin
            addr = req.addr;
          end
          INCR : begin


            addr = req.addr + i*req.size;
            if (addr < req.addr) break;
          end
          WRAP : begin

            addr = req.addr + i*req.size;
          end
        endcase


        data = read_mem(addr, req.size);


        s_axi_rid    <= req.id;
        s_axi_rdata  <= data;
        s_axi_rresp  <= OKAY;
        s_axi_rlast  <= (i == req.len-1);
        s_axi_rvalid <= 1;

        if (DEBUG) begin
          $display("READ:  count=%3X, ADDR=%X, DATA=%X, SIZE=%X, %t, %m", i, addr, data, req.size, $realtime);
        end


        do begin
          @(posedge s_aclk);
          if (!s_aresetn) break;
        end while (!s_axi_rready);

        s_axi_rid    <= 'X;
        s_axi_rdata  <= 'X;
        s_axi_rresp  <= 'X;
        s_axi_rlast  <= 'X;
        s_axi_rvalid <= 0;
      end


      if (!s_aresetn) begin
        while(read_req.try_get(req));
      end

      compl_count++;

    end
  end : read_data_proc

endmodule
module sim_axi_ram #(
  parameter AWIDTH     = 32,
  parameter DWIDTH     = 64,
  parameter IDWIDTH    = 2,
  parameter BIG_ENDIAN = 0,
  parameter STALL_PROB = 25
) (
  input logic s_aclk,
  input logic s_aresetn,


  input  logic [IDWIDTH-1:0] s_axi_awid,
  input  logic [ AWIDTH-1:0] s_axi_awaddr,
  input  logic [        7:0] s_axi_awlen,
  input  logic [        2:0] s_axi_awsize,
  input  logic [        1:0] s_axi_awburst,
  input  logic               s_axi_awvalid,
  output logic               s_axi_awready,


  input  logic [  DWIDTH-1:0] s_axi_wdata,
  input  logic [DWIDTH/8-1:0] s_axi_wstrb,
  input  logic                s_axi_wlast,
  input  logic                s_axi_wvalid,
  output logic                s_axi_wready,


  output logic [IDWIDTH-1:0] s_axi_bid,
  output logic [        1:0] s_axi_bresp,
  output logic               s_axi_bvalid,
  input  logic               s_axi_bready,


  input  logic [IDWIDTH-1:0] s_axi_arid,
  input  logic [ AWIDTH-1:0] s_axi_araddr,
  input  logic [        7:0] s_axi_arlen,
  input  logic [        2:0] s_axi_arsize,
  input  logic [        1:0] s_axi_arburst,
  input  logic               s_axi_arvalid,
  output logic               s_axi_arready,


  output logic [       0:0] s_axi_rid,
  output logic [DWIDTH-1:0] s_axi_rdata,
  output logic [       1:0] s_axi_rresp,
  output logic              s_axi_rlast,
  output logic              s_axi_rvalid,
  input  logic              s_axi_rready
);


  localparam DEBUG = 0;


  localparam [AWIDTH-1:0] MASK_4K = {AWIDTH{1'b1}} << 12;





  
  typedef enum logic [1:0] { FIXED, INCR, WRAP }            burst_t;
  typedef enum logic [1:0] { OKAY, EXOKAY, SLVERR, DECERR } resp_t;

  typedef struct packed {
    longint             count;
    logic [IDWIDTH-1:0] id;
    logic [AWIDTH-1:0]  addr;
    logic [8:0]         len;
    logic [7:0]         size;
    burst_t             burst;
  } req_t;



  typedef bit [AWIDTH:0] addr_t;


  typedef logic [DWIDTH-1:0] data_t;


  typedef bit [DWIDTH/8-1:0] mask_t;






  byte             memory [addr_t];
  mailbox #(req_t) read_req   = new();
  mailbox #(req_t) write_req  = new();
  mailbox #(req_t) write_resp = new();

  longint req_count;
  longint compl_count;






  int waddr_stall_prob = STALL_PROB;
  int wdata_stall_prob = STALL_PROB;
  int wresp_stall_prob = STALL_PROB;
  int raddr_stall_prob = STALL_PROB;
  int rdata_stall_prob = STALL_PROB;


  function void set_stall_prob(int probability);
    assert(probability >= 0 && probability <= 100) else begin
      $error("Probability must be from 0 to 100");
    end
    waddr_stall_prob = probability;
    wdata_stall_prob = probability;
    wresp_stall_prob = probability;
    raddr_stall_prob = probability;
    rdata_stall_prob = probability;
  endfunction : set_stall_prob


  function void set_write_stall_prob(int probability);
    assert(probability >= 0 && probability <= 100) else begin
      $error("Probability must be from 0 to 100");
    end
    waddr_stall_prob = probability;
    wdata_stall_prob = probability;
    wresp_stall_prob = probability;
  endfunction : set_write_stall_prob


  function void set_read_stall_prob(int probability);
    assert(probability >= 0 && probability <= 100) else begin
      $error("Probability must be from 0 to 100");
    end
    raddr_stall_prob = probability;
    rdata_stall_prob = probability;
  endfunction : set_read_stall_prob


  function void set_waddr_stall_prob(int probability);
    assert(probability >= 0 && probability <= 100) else begin
      $error("Probability must be from 0 to 100");
    end
    waddr_stall_prob = probability;
  endfunction : set_waddr_stall_prob


  function void set_wdata_stall_prob(int probability);
    assert(probability >= 0 && probability <= 100) else begin
      $error("Probability must be from 0 to 100");
    end
    wdata_stall_prob = probability;
  endfunction : set_wdata_stall_prob


  function void set_wresp_stall_prob(int probability);
    assert(probability >= 0 && probability <= 100) else begin
      $error("Probability must be from 0 to 100");
    end
    wresp_stall_prob = probability;
  endfunction : set_wresp_stall_prob


  function void set_raddr_stall_prob(int probability);
    assert(probability >= 0 && probability <= 100) else begin
      $error("Probability must be from 0 to 100");
    end
    raddr_stall_prob = probability;
  endfunction : set_raddr_stall_prob


  function void set_rdata_stall_prob(int probability);
    assert(probability >= 0 && probability <= 100) else begin
      $error("Probability must be from 0 to 100");
    end
    rdata_stall_prob = probability;
  endfunction : set_rdata_stall_prob


  function int get_waddr_stall_prob();
    return waddr_stall_prob;
  endfunction : get_waddr_stall_prob


  function int get_wdata_stall_prob();
    return wdata_stall_prob;
  endfunction : get_wdata_stall_prob


  function int get_wresp_stall_prob();
    return wresp_stall_prob;
  endfunction : get_wresp_stall_prob


  function int get_raddr_stall_prob();
    return raddr_stall_prob;
  endfunction : get_raddr_stall_prob


  function int get_rdata_stall_prob();
    return rdata_stall_prob;
  endfunction : get_rdata_stall_prob







  function data_t read_mem(addr_t byte_addr, int num_bytes);
    data_t data;
    addr_t incr;

    if (BIG_ENDIAN) begin
      byte_addr = byte_addr + num_bytes-1;
      incr      = -1;
    end else begin
      incr      = 1;
    end

    for (int i = 0; i < num_bytes; i++) begin
      if (byte_addr >= 2**AWIDTH) begin
        $fatal(1, "Read extends beyond memory range");
      end
      if (memory.exists(byte_addr)) data[i*8 +: 8] = memory[byte_addr];
      else data[i*8 +: 8] = 'X;
      byte_addr += incr;
    end

    return data;
  endfunction : read_mem


  function void write_mem(addr_t byte_addr, int num_bytes, data_t data, mask_t mask);
    addr_t incr;

    if (BIG_ENDIAN) begin
      byte_addr = byte_addr + num_bytes-1;
      incr      = -1;
    end else begin
      incr      = 1;
    end

    for (int i = 0; i < num_bytes; i++) begin
      if (mask[i]) begin
        if (byte_addr >= 2**AWIDTH) begin
          $fatal(1, "Write extends beyond memory range");
        end
        memory[byte_addr] = data[i*8 +: 8];
      end
      byte_addr += incr;
    end
  endfunction : write_mem






  initial begin : write_req_proc
    req_t   req;
    burst_t burst;

    s_axi_awready <= 0;

    forever begin
      @(posedge s_aclk);
      if (!s_aresetn) continue;

      if (s_axi_awvalid) begin
        if (s_axi_awready) begin
          req.count = req_count;
          req.id    = s_axi_awid;
          req.addr  = s_axi_awaddr;
          req.len   = s_axi_awlen + 1;
          req.size  = 2**s_axi_awsize;
          req.burst = burst_t'(s_axi_awburst);


          assert (!$isunknown(req)) else begin
            $fatal(1, "Write request signals are unknown");
          end
          assert (s_axi_araddr % (DWIDTH/8) == 0) else begin
            $warning("Unaligned memory write");
          end
          assert (2**s_axi_awsize <= DWIDTH/8) else begin
            $fatal(1, "AWSIZE must not be larger than DWIDTH");
          end
          assert ($cast(burst, s_axi_awburst)) else begin
            $fatal(1, "Invalid AWBURST value");
          end
          assert ((s_axi_awaddr & MASK_4K) ==
            ((s_axi_awaddr + (s_axi_awlen+1)*(2**s_axi_awsize) - 1) & MASK_4K)) else begin
            $fatal(1, "Memory write burst crosses 4 KiB boundary");
          end

          if (DEBUG) begin
            $display("WRITE REQ: id=%X, addr=%X, len=%X, size=%X, burst=%s, %t, %m", 
              req.id, req.addr, req.len, req.size, req.burst.name, $realtime);
          end

          req_count++;
          write_req.put(req);
        end


        s_axi_awready <= $urandom_range(99) < waddr_stall_prob ? 0 : 1;
      end
    end
  end : write_req_proc






  initial begin : read_req_proc
    req_t   req;
    burst_t burst;

    s_axi_arready <= 0;

    forever begin
      @(posedge s_aclk);
      if (!s_aresetn) continue;

      if (s_axi_arvalid) begin
        if (s_axi_arready) begin
          req.count = req_count;
          req.id    = s_axi_arid;
          req.addr  = s_axi_araddr;
          req.len   = s_axi_arlen + 1;
          req.size  = 2**s_axi_arsize;
          req.burst = burst_t'(s_axi_arburst);


          assert(!$isunknown(req)) else begin
            $fatal(1, "Read request signals are unknown");
          end
          assert(s_axi_araddr % (DWIDTH/8) == 0) else begin
            $warning("Unaligned memory read");
          end
          assert(2**s_axi_arsize <= DWIDTH/8) else begin
            $fatal(1, "ARSIZE must not be larger than DWIDTH");
          end
          assert ($cast(burst, s_axi_awburst)) else begin
            $fatal(1, "Invalid ARBURST value");
          end
          assert ((s_axi_araddr & MASK_4K) ==
            ((s_axi_araddr + (s_axi_arlen+1)*(2**s_axi_arsize) - 1) & MASK_4K)) else begin
            $fatal(1, "Memory read burst crosses 4 KiB boundary");
          end

          if (DEBUG) begin
            $display("READ REQ:  id=%X, addr=%X, len=%X, size=%X, burst=%s, %t, %m", 
              req.id, req.addr, req.len, req.size, req.burst.name, $realtime);
          end

          req_count++;
          read_req.put(req);
        end


        s_axi_arready <= $urandom_range(99) < raddr_stall_prob ? 0 : 1;
      end
    end
  end : read_req_proc






  initial begin : write_data_proc
    req_t req;
    bit [AWIDTH-1:0] addr;

    forever begin

      s_axi_wready <= 0;
      write_req.get(req);


      while (compl_count < req.count) begin
        @(posedge s_aclk);
        if (!s_aresetn) break;
      end


      if (!s_aresetn) begin
        while(write_req.try_get(req));
        continue;
      end


      for (int i = 0; i < req.len; ) begin
        @(posedge s_aclk);
        if (!s_aresetn) break;


        if (s_axi_wvalid) begin
          if (s_axi_wready) begin

            if ($isunknown(s_axi_wstrb)) begin
              $fatal(1, "WSTRB is unknown");
            end
            if ($isunknown(s_axi_wdata)) begin
              $warning(1, "WDATA is unknown; data will be changed to zero");
            end

            case (req.burst)
              FIXED : begin
                addr = req.addr;
              end
              INCR : begin


                addr = req.addr + i*req.size;
                if (addr < req.addr) break;
              end
              WRAP : begin

                addr = req.addr + i*req.size;
              end
            endcase

            write_mem(addr, req.size, s_axi_wdata, s_axi_wstrb);

            if (DEBUG) begin
              $display("WRITE: count=%3X, ADDR=%X, DATA=%X, SIZE=%X, STRB=%X, %t, %m", 
                i, addr, s_axi_wdata, req.size, s_axi_wstrb, $realtime);
            end

            i++;
          end


          s_axi_wready <= $urandom_range(99) < wdata_stall_prob ? 0 : 1;
        end
      end


      if (!s_aresetn) begin
        while(write_req.try_get(req));
        continue;
      end

      compl_count++;


      write_resp.put(req);



      if (s_axi_wlast != 1'b1) begin
        $error("WLAST not asserted on last word of burst");
      end

    end
  end : write_data_proc






  initial begin : write_resp_proc
    req_t resp;
    bit [AWIDTH-1:0] addr;

    forever begin
      s_axi_bid    <= 'X;
      s_axi_bresp  <= 'X;
      s_axi_bvalid <= 0;


      write_resp.get(resp);
      @(posedge s_aclk);


      if (!s_aresetn) begin
        while(write_resp.try_get(resp));
        continue;
      end


      if ($urandom_range(99) < wresp_stall_prob) begin
        do begin
          @(posedge s_aclk);
          if (!s_aresetn) break;
        end while ($urandom_range(99) < wresp_stall_prob);


        if (!s_aresetn) begin
          while(write_resp.try_get(resp));
          continue;
        end
      end


      s_axi_bid    <= resp.id;
      s_axi_bresp  <= OKAY;
      s_axi_bvalid <= 1;

      if (DEBUG) begin
        $display("WRITE RESP: ID=%X, %t, %m", resp.id, $realtime);
      end


      do begin
        @(posedge s_aclk);
        if (!s_aresetn) break;
      end while (!s_axi_bready);


      s_axi_bid    <= 'X;
      s_axi_bresp  <= 'X;
      s_axi_bvalid <= 0;


      if (!s_aresetn) begin
        while(write_resp.try_get(resp));
        continue;
      end
    end
  end : write_resp_proc






  initial begin : read_data_proc
    req_t req;
    bit   [AWIDTH-1:0] addr;
    logic [DWIDTH-1:0] data;

    forever begin
      s_axi_rid    <= 'X;
      s_axi_rdata  <= 'X;
      s_axi_rresp  <= 'X;
      s_axi_rlast  <= 'X;
      s_axi_rvalid <= 0;


      read_req.get(req);


      do begin
        @(posedge s_aclk);
        if (!s_aresetn) break;
      end while (compl_count < req.count);


      if (!s_aresetn) begin
        while(read_req.try_get(req));
        continue;
      end

      for (int i = 0; i < req.len; i++) begin

        if ($urandom_range(99) < rdata_stall_prob) begin
          do begin
            @(posedge s_aclk);
            if (!s_aresetn) break;
          end while ($urandom_range(99) < rdata_stall_prob);
          if (!s_aresetn) break;
        end

        case (req.burst)
          FIXED : begin
            addr = req.addr;
          end
          INCR : begin


            addr = req.addr + i*req.size;
            if (addr < req.addr) break;
          end
          WRAP : begin

            addr = req.addr + i*req.size;
          end
        endcase


        data = read_mem(addr, req.size);


        s_axi_rid    <= req.id;
        s_axi_rdata  <= data;
        s_axi_rresp  <= OKAY;
        s_axi_rlast  <= (i == req.len-1);
        s_axi_rvalid <= 1;

        if (DEBUG) begin
          $display("READ:  count=%3X, ADDR=%X, DATA=%X, SIZE=%X, %t, %m", i, addr, data, req.size, $realtime);
        end


        do begin
          @(posedge s_aclk);
          if (!s_aresetn) break;
        end while (!s_axi_rready);

        s_axi_rid    <= 'X;
        s_axi_rdata  <= 'X;
        s_axi_rresp  <= 'X;
        s_axi_rlast  <= 'X;
        s_axi_rvalid <= 0;
      end


      if (!s_aresetn) begin
        while(read_req.try_get(req));
      end

      compl_count++;

    end
  end : read_data_proc

endmodule