Is it possible to map 2 different sequencers to a reg_map one for read one for write?

Hi,
I’m working on validating an IP which has AXI as main interface. TB has two different sequencers one for AXI read channel and one for AXI write channel to drive txns independently.
So, i want reg model to select appropriate rd_sequencer or wr_sequencer based on whether its a read access or write access. is this possible ?
should i create two different reg maps one for read and one for write and do connections as below or is there a better way?

axi_reg_blk.rd_reg_map.set_sequencer(rd_sequencer,rd_adapter);
axi_reg_blk.wr_reg_map.set_sequencer(wr_sequencer,wr_adapter);

In reply to srikanthvvs1:

As per my ( current ) understanding ::

A register map can be mapped to a Single Sequencer .

You would need 2 register maps since you have 2 different sequencer / interface for write and read .

I am curios about following ::

**For a “RW” register would you map it to both register maps ( with same offset address ) ?

Eg : rd_reg_map with “RO” access and wr_reg_map with “RW” access .**

In reply to srikanthvvs1:

Hi,
I’m working on validating an IP which has AXI as main interface. TB has two different sequencers one for AXI read channel and one for AXI write channel to drive txns independently.
So, i want reg model to select appropriate rd_sequencer or wr_sequencer based on whether its a read access or write access. is this possible ?
should i create two different reg maps one for read and one for write and do connections as below or is there a better way?

axi_reg_blk.rd_reg_map.set_sequencer(rd_sequencer,rd_adapter);
axi_reg_blk.wr_reg_map.set_sequencer(wr_sequencer,wr_adapter);

The key question is if your UVM architecture is correct. You need only 2 agent when you have a dual-port memory.
Is this really the case?

In reply to MICRO_91:

My understanding is, for a single set of registers(instances), multiple reg_maps can exists.
reg_maps are used to calculate final adress (map_base_addr+reg_offset).Ex., if an IP has multiple interfaces, and base address of IP could be different through different interfaces. This requires two different reg_maps. You can write through one interface and read through other interface, read will reflect write value even though maps are different.

I realized in this scenario its better to use uvm_frontdoor_seq instead of ral adapter. Any ral access invocation will call user defined seq extended from uvm_frontdoor_seq, where we can perform the register access normally through frontdoor.

In reply to srikanthvvs1:

I realized in this scenario its better to use uvm_frontdoor_seq instead of ral adapter.

You ALWAYS need an adapter for Frontdoor Access

In reply to chr_sue:

Only reason to separate out rd and wr sequencer is to maintain the independent nature of AXI Wr and Rd channels. I think this can be achieved through single sequencer by forking off(join_none) driver code for Wr and Rd tasks and using semaphores to block task reentry until previous Rd/Wr are done. In this case there wont be any issue with RAL.

In reply to srikanthvvs1:

If you have 2 separate interfaces for Write and Read then you would have 2 sequencer , one sequencer for each interface .

Generally the built-in sequencer is used as it is , how do you intend to add semaphore to it ? . Also this won’t duplicate the independent nature of the channels

In reply to MICRO_91:

In reply to srikanthvvs1:
You ALWAYS need an adapter for Frontdoor Access

I think not necessary. Adapter is used by RAL to convert write/read calls to specific sequence item and execute that on the registered sequencer. This is one method to do it.

ral_model.apb_map.set_sequencer(apb_vip.apb_seqr, apb_reg_adapter);

In second method(which i just came to know) you register the user defined frontdoor sequence with ral. When read/write task is invoked on a register, ral will directly execute frontdoor sequence. In this sequence you will explicitly do what adapter does(usign rw_info variable available in uvm_frontoor_seq). After that call uvm_do on the sequence items, if write select wr_sequencer if read select read_sequencer.

my_vreg_frontdoor_sequence frontdoor;
frontdoor = my_vreg_frontdoor_sequence::type_id::create(“frontdoor”);
regmodel.reg0.set_frontdoor(frontdoor);

In reply to MICRO_91:

In reply to srikanthvvs1:
If you have 2 separate interfaces for Write and Read then you would have 2 sequencer , one sequencer for each interface .
Generally the built-in sequencer is used as it is , how do you intend to add semaphore to it ? . Also this won’t duplicate the independent nature of the channels

I mean in the driver task not in sequencer.

task drive_wr_txn(txn t);
   wr_sema.get(); 
   fork
   begin
     //driver code
     wr_sema.put()
   end
   join_none //if a read pkt exists in driver tlm fifo this wont block that
endtask

Just a general idea. Should see if it really works.

In reply to srikanthvvs1:

I think not necessary. Adapter is used by RAL to convert write/read calls to specific sequence item and execute that on the registered sequencer. This is one method to do it.
ral_model.apb_map.set_sequencer(apb_vip.apb_seqr, apb_reg_adapter);

What’s the second argument to set_sequencer ? Isn’t that the adapter ?

Regarding the User-defined Frontdoor I am not aware on it’s internal working so won’t be able to comment on it .

Just a general idea. Should see if it really works.

Do update us once you have a complete working code .

In reply to MICRO_91:

Using 1 sequencer/driver pair supports the independent RD/WR channels.
Depending on the access type you can either execute the WR or the RD part in the driver. Tere ios no metaphore needed, because you cannot WR and RD at the same time.

In reply to chr_sue:

Yes , I do agree with that . Since the Write and Read channel are independent , there should be 2 Driver - Sequencer pair ( one pair for each channel ) .

In reply to MICRO_91:

I do not understand why you think we need 2 sequencer/driver pairs. The independence will be controlled by the sequences.

In reply to chr_sue:

Oh sorry I didn’t read your previous reply correctly .
I was of the belief that via 2 driver-sequencer pair we could initiate Write and Read transfers in parallel .
Write could target a different register and read could target a different register at the same time thereby replicating the independent channel behavior.

The independence will be controlled by the sequences.

I didn’t get this . Do you intend to send read and write transactions in sequence via fork join ? The driver on receiving a sequence item would either send a write OR read transaction on the channel .
With a single pair how can we replicate a scenario where both accesses are initiated at same time

In reply to MICRO_91:

In my understanding AXI does not allow concurrent RD and WR accesses. Do you agree?

In reply to chr_sue:

AXI does not allow concurrent RD and WR accesses

I believe this is incorrect ( Feel free to correct me ) .
The AXI Specification doesn’t restrict such concurrent accesses .

I discussed this with a few friends ( one of them used to work in VIP team for AXI ) and both of them agreed with concurrent write and read access being legal .

After all they are called independent channels in the specification .

The following is from AXI 3 Specification .


9.1 About the data buses 

The AXI protocol has two independent data buses, one for read data and one for write data.
Because these data buses have their own individual handshake signals, it is possible for data
transfers to occur on both buses at the same time.

In reply to MICRO_91:

I’m not so familiar with the AXI. But I was asking earlier if a concurrent access is possible and did not get a clear answer.
Wrt to the spec you are showing here we need definitely 2 agents with independent sequencer/driver pairs.

In reply to chr_sue:

While discussing with the friend with VIP experience he pointed to a few things ::

(1) If we go with multiple driver-sequencer pair approach ::

 (a)  There  would  be  different  sequence items  for  write  and  read . 
      So  write channels driver-sequencer  pair  would  use  write  sequence item .

 (b)  Write and read sequence  would  be  different  and  they  would  be  started  in  parallel  from  test .

(2) If we go with single driver-sequencer pair ::

 (a)  Single  sequence_item  would  encapsulate  all  write and read  properties 
       The  single  driver-sequencer  pair  would  use  it  for  parameterization .           

 (b)  Single  sequence  would  exist  for  write and read  and  it  would  be  started  in  test ( unlike  parallel  sequences  (1)(b) )

Post-discussion I agree that we can go with single driver-sequencer pair as well.

In reply to MICRO_91:

Looks like it is a question of taste. Of course, you need different seq_items or 1 combined.