Implementing priority in registers access task

Hi,

In our ENV so far we are using semaphore to serialize access to AXI bus for register interface of our SOC. Due to a specific need I need to implement priority based selection and give importance to certain caller like ISR. Due to large number of threads supported there can be 100’s of semaphore request sitting at any given point, the need is to have a high priority request to get executed ahead of all outstanding thread callers.

I played around with semaphore keys and got a simple solution working but I am sure it can be done in better way. Following is the link to what I have implemented using semaphore:


class a;
  semaphore sem;
  
  function new();
    sem = new(2);
  endfunction
  
  task call(int pri, string in);
    $display("Time:%0t Calling Task %s Priority:%0d", $realtime, in, pri);
    if (pri) begin
      sem.get(1);
      sem.get(1);
    end
    else begin
      sem.get(2);
      sem.put(1);
    end
    #50ns;
    $display("Time:%0t Completed Task %s Priority:%0d", $realtime, in, pri);
    if (pri) begin
      sem.put(2);
    end
    else begin
      sem.put(1);
    end
  endtask
endclass
    
module top;
  
  initial begin
    a aa;
    aa = new();
    
    for (int i=0; i<5; i++) begin
      #1ns;
      fork
        automatic int th = i;
        begin
          aa.call(0, $psprintf("LO_PRI_%0d",th));
        end
      join_none
    end   
    aa.call(1, $psprintf("HI_PRI_%0d",0));  
    wait fork;
  end

Following is the output of the above code:


Compiler version P-2019.06-1; Runtime version P-2019.06-1;  Mar 23 14:39 2020
Time:1 Calling Task LO_PRI_0 Priority:0
Time:2 Calling Task LO_PRI_1 Priority:0
Time:3 Calling Task LO_PRI_2 Priority:0
Time:4 Calling Task LO_PRI_3 Priority:0
Time:5 Calling Task HI_PRI_0 Priority:1
Time:5 Calling Task LO_PRI_4 Priority:0
Time:51 Completed Task LO_PRI_0 Priority:0
Time:101 Completed Task HI_PRI_0 Priority:1
Time:151 Completed Task LO_PRI_1 Priority:0
Time:201 Completed Task LO_PRI_2 Priority:0
Time:251 Completed Task LO_PRI_3 Priority:0
Time:301 Completed Task LO_PRI_4 Priority:0

Kindly let me know if any better way to achieve the same. The ENV is conventional SystemVerilog based otherwise UVM sequencer grab or lock was the perfect answer.

Thanks in Advance !

In reply to rohitk:

The output behavior you’re seeing does not match the LRM. get() has FIFO ordering. If the specified number of keys is not available, the process blocks until the keys become available.

Since LO_PRI_1 is next in order waiting for 2 keys, the simulation gets dead-locked because only one key is available.

In reply to dave_59:

Thanks for Response Dave. Surprisingly it works with Synopsys Tool on EDA Playground. Other approach I am thinking would be to use two separate semaphore and priority base selection. Any suggestions please as I am not convinced if that is the best idea.

Best Regards,
Rohit

In reply to dave_59:

Another method I tried is changing semaphore .get call to .try_get and simulation is going through for both VCS and Cadence tool.


// Code your testbench here
// or browse Examples
class a;
  semaphore sem;  
  function new();
    sem = new(2);
  endfunction
  
  task call(int pri, string in);
    $display("Time:%0t Calling Task %s Priority:%0d", $realtime, in, pri);
    if (pri) begin
      sem.get(1);
      sem.get(1);
    end
    else begin
      while (!sem.try_get(2)) begin
        #1ns;
      end
      sem.put(1);
    end
    #50ns;
    $display("Time:%0t Completed Task %s Priority:%0d", $realtime, in, pri);
    if (pri) begin
      sem.put(2);
    end
    else begin
      sem.put(1);
    end
  endtask
endclass
    
module top; 
  initial begin
    a aa = new();
 
    for (int i=0; i<5; i++) begin
      #1ns;
      fork
        automatic int th = i;
        begin
          aa.call(0, $psprintf("LO_PRI_%0d",th));
        end
      join_none
    end   
    aa.call(1, $psprintf("HI_PRI_%0d",0));  
    wait fork;
  end       
endmodule

OUTPUT :

ncsim> run
Time:1 Calling Task LO_PRI_0 Priority:0
Time:2 Calling Task LO_PRI_1 Priority:0
Time:3 Calling Task LO_PRI_2 Priority:0
Time:4 Calling Task LO_PRI_3 Priority:0
Time:5 Calling Task HI_PRI_0 Priority:1
Time:5 Calling Task LO_PRI_4 Priority:0
Time:51 Completed Task LO_PRI_0 Priority:0
Time:101 Completed Task HI_PRI_0 Priority:1
Time:151 Completed Task LO_PRI_4 Priority:0
Time:201 Completed Task LO_PRI_3 Priority:0
Time:251 Completed Task LO_PRI_2 Priority:0
Time:301 Completed Task LO_PRI_1 Priority:0
ncsim: *W,RNQUIE: Simulation is complete.