Register adaptor completing sequence problems

I am returning to have fun with the Register Layer and i seem to have a few problems. I am generating the register model with register assistant but only for uvm 1.1. However i don’t remember any incompatibilities between 1.1d and 1.2 for the register layer.

When running the test, questa reports the following errors:

UVM_FATAL | @ 0ns | SEQNOTITM: attempting to start a sequence using start_item() from sequence ‘uvm_test_top.tb.apb_env.master_agent.sequencer.elicia_config’. Use seq.start() instead.

** Note: $finish : /home/APPS/questasim/10.6b/questasim/linux/…/verilog_src/uvm-1.2/src/base/uvm_root.svh(135)

Time: 0 ps Iteration: 68 Region: /uvm_pkg::uvm_sequence_base::start

Break in Function uvm_pkg/uvm_root::die at /home/APPS/questasim/10.6b/questasim/linux/…/verilog_src/uvm-1.2/src/base/uvm_root.svh line 135

UVM_FATAL | @ 0ns | SNDREQ: Send request called without wait_for_grant

At the moment i have sequence in my test that makes calls to the register model. The register is connected to an adaptor and the adaptor to the appropriate sequencer in the agent. I am struggling to understand why the handshake is not working in the sequencer.

Can anyone offer me any investigatory advice? I am happy to provide additional code.

In reply to Phill_Ferg:

Could you please provide some code:
(1) body task of your test
(2) Body Task of the sequence you want to start

I have noticed something peculiar about the driver i am using. Previously i used something like:



    seq_item_port.get_next_item(req);
    $cast(rsp, req.clone());
    rsp.set_id_info(req);
    drive_transfer(rsp);
    seq_item_port.item_done(rsp);


however in this testbench the driver does something like:


DRIVER_ITEM_REQ transaction;
seq_item_port.get_next_item(transaction);
output_port.write(transaction);
drive_transaction(transaction);
seq_item_port.item_done();


I suspect there something going here. As it appears the the sequencer is waiting on part of the tlm transaction.

thoughts always welcome

In reply to Phill_Ferg:

I have noticed something peculiar about the driver i am using. Previously i used something like:


// loks a little bit strange with respect to the rsp
seq_item_port.get_next_item(req);
$cast(rsp, req.clone());
rsp.set_id_info(req);
drive_transfer(rsp);
seq_item_port.item_done(rsp);  //passes back your req to the sequencer

however in this testbench the driver does something like:


DRIVER_ITEM_REQ transaction;  // DRIVER_ITEM_REQ is your seq_item?
seq_item_port.get_next_item(transaction);
output_port.write(transaction);      // you are putting your transaction on an analysis port
drive_transaction(transaction);      // drive transaction is a task which drives your pins
seq_item_port.item_done();           // is indicating you are ready and the sequencer Can generate your next seq_item
// all things are fine

I suspect there something going here. As it appears the the sequencer is waiting on part of the tlm transaction.
thoughts always welcome

See my remarks above in your code.
The error message points you to the sequence.

In reply to chr_sue:

Christoph! We’ve met on a UVM training course in Ringwood! I hope you are well.

My apologies, i missed your first question and put down my own thoughts.

ok from my test



  RAL_test_seq_c chain_config;

...

  chain_config = RAL_test_seq_c::type_id::create("chain_config");

  // set the register block block in for the sequence
  chain_config.starting_phase= phase;
  chain_config.set_reg_model(tb.regmodel);

  // Set the same sequencer that the reg model uses
  elicia_config.start(tb.APB_mseqr);


Within the RAL_test_seq_c including the base class


virtual class RAL_base_seq_vc extends uvm_reg_sequence #();

  registers_pkg::register_block  model      ;

  function new(string name="RAL_base_seq_vc");
    super.new(name);
  endfunction

  // Raise objection in pre_body
  virtual task pre_body();
    if (starting_phase!=null) begin
      `uvm_info("RAL_BASE_SEQ",$sformatf("%s pre_body() raising %s objection", get_sequence_path(), starting_phase.get_name()), UVM_MEDIUM);
      starting_phase.raise_objection(this);
    end
  endtask

  // Drop objection in post_body
  virtual task post_body();
    if (starting_phase!=null) begin
      `uvm_info("RAL_BASE_SEQ", $sformatf("%s post_body() dropping %s objection", get_sequence_path(), starting_phase.get_name()), UVM_MEDIUM);
      starting_phase.drop_objection(this);
    end
  endtask

  function match(string s1,s2);
    int l1,l2    ;
    l1 = s1.len()  ;
    l2 = s2.len()  ;
    match = 0    ;

    if( l2 > l1 ) return 0;

    for(int i = 0;i < l1 - l2 + 1; i ++)
      if( s1.substr(i,i+l2 -1) == s2) return 1;
  endfunction

    //function for getting the value of model field
    //@return model field value
  virtual function registers_pkg::register_block model get_reg_model();
    return model;
  endfunction

      //function for setting a new value for modele field
      //@param model - new value of the model field
  virtual function void set_reg_model(registers_pkg::register_block model);
    this.model = model;
  endfunction

endclass:RAL_base_seq_vc


class RAL_test_seq_c extends RAL_base_seq_vc;

  `uvm_object_utils(RAL_test_seq_c)

  function new(string name="RAL_test_seq_c");
    super.new(name);
  endfunction

  virtual task body();

  uvm_status_e status;
  uvm_reg_data_t data;

  assert (model != null) else
    `uvm_fatal("RAL_TEST_SEQ","Cannot get reg model");

      model.CONFIG_STREAM_r.write(status, 'h05010501, .parent(this) , .path(UVM_FRONTDOOR) );
    `uvm_info("RAL_TEST_SEQ", {$sformatf("Front door write: %0h with status %0s",'h05010501 ,status)} , UVM_LOW);

  endtask : body

endclass: RAL_test_seq_c


I will also include my test bench linkage between my register model, the adaptor and the sequencer.



function void block_C_tb_c::build_phase(uvm_phase phase);
  super.build_phase(phase);

...


  reg2apb_adapter = amiq_apb_ex_reg_pkg::amiq_apb_ex_reg_reg2apb_adapter::type_id::create("reg2adb_adapter", this);
  `uvm_info("block_C_TB", {$sformatf("Created: %0s",reg2apb_adapter.get_full_name())} , UVM_LOW)

  apb2reg_predictor = amiq_apb_ex_reg_pkg::amiq_apb_ex_reg_apb2reg_predictor::type_id::create("apb2reg_predictor", this);
  `uvm_info("block_C_TB", {$sformatf("Created: %0s",apb2reg_predictor.get_full_name())} , UVM_LOW)

  regmodel = registers_pkg::register_block::type_id::create("regmodel",this);
  regmodel.build();
  regmodel.reset("HARD");
  `uvm_info("block_C_TB", {$sformatf("Created: %0s",regmodel.get_full_name())} , UVM_LOW)

...
end function

function void block_C_tb_c::connect_phase(uvm_phase phase);
  super.connect_phase(phase);

...

  if($cast(APB_mseqr, apb_env.master_agent.sequencer) == 0) begin
    `uvm_fatal("block_C_TB", "Could not cast to amiq_apb_master_sequencer")
  end
  `uvm_info("block_C_TB", {$sformatf("Set Sequencer in the top testbench : %0s",APB_mseqr.get_full_name())} , UVM_LOW)

  // Connect up the register model
  if(regmodel.get_parent()== null) begin

    // Set the frontdoor sequencer and register adapter on the default_map member of the serial register model.
    regmodel.default_map.set_sequencer(APB_mseqr, reg2apb_adapter);

    apb_env.master_agent.monitor.output_port.connect(apb2reg_predictor.bus_in);

    //Setup Register prediction
    apb2reg_predictor.map = regmodel.default_map;

    // Set the predictor adapter:
    apb2reg_predictor.adapter = reg2apb_adapter;

    // Set the base address in the system
    regmodel.default_map.set_base_addr('h0);

    // Set the auto predict off since a predictor needs to be used for coverage
    regmodel.default_map.set_auto_predict(0);
  end

...

end function

At the moment i am struggling to understand exactly what is not being set correctly. As you might have gathered i am using my register model with this APB code. I have executed normal sequences to read and write across the interface but the register layer link is a quite mysterious.

In reply to Phill_Ferg:

Hi Phill, yes I remember :-)

Two things I see:
(1) virtual class RAL_base_seq_vc extends uvm_reg_sequence #(); is missing the parameter uvm_sequence_item
(2) You are starting another sequence as you are creating: elicia_config.start(tb.APB_mseqr);

I don’t believe your Problem is in the testbench hierarchy.

In reply to chr_sue:

I thought since this was of type uvm_reg_sequence already has a default parameters


class uvm_reg_sequence #(type BASE=uvm_sequence #(uvm_reg_item)) extends BASE;

  `uvm_object_param_utils(uvm_reg_sequence #(BASE))

ok so here is my question, what kind of sequencer do i run a uvm_reg_sequence on?
At the moment i am running it on the sequencer that connects to the adaptor.

Also, when i look at the call stack it appears that my sequence is fine - the register block is processing the request and communicating to the adaptor. The problem appears to be the adaptor translation between the *_item coming from the register block and the *_item going to the driver.

Call Stack window

# In Line File Address
0 Function uvm_pkg/uvm_root::die 135 /home/APPS/questasim/10.6b/questasim/linux/../verilog_src/uvm-1.2/src/base/uvm_root.svh return 0x59138991
1 Function uvm_pkg/uvm_default_report_server::execute_report_message 732 /home/APPS/questasim/10.6b/questasim/linux/../verilog_src/uvm-1.2/src/base/uvm_report_server.svh return 0x590a8131
2 Function uvm_pkg/uvm_default_report_server::process_report_message 628 /home/APPS/questasim/10.6b/questasim/linux/../verilog_src/uvm-1.2/src/base/uvm_report_server.svh return 0x590a624c
3 Function uvm_pkg/uvm_report_handler::process_report_message 333 /home/APPS/questasim/10.6b/questasim/linux/../verilog_src/uvm-1.2/src/base/uvm_report_handler.svh return 0x590b58f8
4 Function uvm_pkg/uvm_report_object::uvm_process_report_message 251 /home/APPS/questasim/10.6b/questasim/linux/../verilog_src/uvm-1.2/src/base/uvm_report_object.svh return 0x590c3d5a
5 Function uvm_pkg/uvm_report_object::uvm_report 146 /home/APPS/questasim/10.6b/questasim/linux/../verilog_src/uvm-1.2/src/base/uvm_report_object.svh return 0x590c1cb2
6 Function uvm_pkg/uvm_report_object::uvm_report_fatal 239 /home/APPS/questasim/10.6b/questasim/linux/../verilog_src/uvm-1.2/src/base/uvm_report_object.svh return 0x590c372d
7 Function uvm_pkg/uvm_sequencer_param_base::send_request 277 /home/APPS/questasim/10.6b/questasim/linux/../verilog_src/uvm-1.2/src/seq/uvm_sequencer_param_base.svh return 0x593ed8b2
8 Task uvm_pkg/uvm_sequence_base::finish_item 1027 /home/APPS/questasim/10.6b/questasim/linux/../verilog_src/uvm-1.2/src/seq/uvm_sequence_base.svh return 0x591a0778
9 NamedBeginStat uvm_pkg/uvm_reg_map::do_bus_write/foreach_value 1941 /home/APPS/questasim/10.6b/questasim/linux/../verilog_src/uvm-1.2/src/reg/uvm_reg_map.svh return 0x592b08e6
10 Task uvm_pkg/uvm_reg_map::do_write 1784 /home/APPS/questasim/10.6b/questasim/linux/../verilog_src/uvm-1.2/src/reg/uvm_reg_map.svh return 0x592b590a
11 NamedBeginStat uvm_pkg/uvm_reg::do_write/built_in_frontdoor 2278 /home/APPS/questasim/10.6b/questasim/linux/../verilog_src/uvm-1.2/src/reg/uvm_reg.svh return 0x59216731
12 Task uvm_pkg/uvm_reg::write 2146 /home/APPS/questasim/10.6b/questasim/linux/../verilog_src/uvm-1.2/src/reg/uvm_reg.svh return 0x59209e74
13 Task block_C_tests_pkg/RAL_test_seq_c::body 138 ../tb/tests/RAL_seq_lib.svh return 0x597ceea1
14 Task uvm_pkg/uvm_sequence_base::start 347 /home/APPS/questasim/10.6b/questasim/linux/../verilog_src/uvm-1.2/src/seq/uvm_sequence_base.svh return 0x59198f07

In reply to Phill_Ferg:

I think i am a little close to understanding the code adaptor. When i look at the example code in a sequence that is not using the register model. The body task looks like this…

#
virtual task body();
			amiq_apb_master_drv_item master_seq_item = amiq_apb_master_drv_item::type_id::create("master_seq_item");

			start_item(master_seq_item);

			if(!(master_seq_item.randomize() with {
							master_seq_item.selected_slave < p_sequencer.agent_config.get_number_of_slaves();
							address == master_address;
							rw == master_rw;
							data == master_data;
						})) begin
				`uvm_fatal("AMIQ_APB_NOSEQITEM_MSEQ_ERR", "The sequence item could not be generated");
			end

			finish_item(master_seq_item);
		endtask


however in the adaptor i am dealing with the reg2bus function there is this.


  virtual function uvm_sequence_item reg2bus(const ref uvm_reg_bus_op rw);
    amiq_apb_master_simple_seq transaction = amiq_apb_master_simple_seq::type_id::create("transaction");

    `uvm_info(get_id(), $sformatf("running inside the adaptor"), UVM_LOW)

    assert (transaction.randomize() with {
      master_address == rw.addr;
      master_data == rw.data;
    }) else
    `uvm_fatal(get_id(), "Could not randomize amiq_apb_drv_item_master");

    if(rw.kind == UVM_WRITE) begin
      transaction.master_rw = WRITE;
    end
    else begin
      transaction.master_rw = READ;
    end

    return transaction;
  endfunction

I realise this is being doing in the uvm_reg_map class. So i am at a loss as to why the tlm handshake isn’t completing. If the sequencer appears ok, am i looking at the driver again?

In reply to Phill_Ferg:

Hi Phill, it is not easy to investigate your Problem without seeing the whole Picture. There are different approaches possible.
Could you share your code with me privately? christoph@christoph-suehnel.de

In reply to chr_sue:

Christoph, thanks for your offer, but i am afriad with nds’s etc i will have to resort to the formal support from mentor.

I still believe there is something fundamental between the register model and the adaptors.

Thanks again

In reply to Phill_Ferg:

Hi Phill,

I understand.
But another Topic regarding your function reg2bus. There is nothing to randomize. This provides only an Adapter between the generic UVM bus interface and the bus interface you are using to access physically the registers in your DUT:
It has to be changed like this:

 virtual function uvm_sequence_item reg2bus(const ref uvm_reg_bus_op rw);
    amiq_apb_master_simple_seq transaction = amiq_apb_master_simple_seq::type_id::create("transaction");
 
    `uvm_info(get_type_id(), $sformatf("running inside the adaptor"), UVM_LOW)
     transaction.address  = rw.addr;
     if(rw.kind == UVM_READ) begin
      transaction.master_rw = READ;
    end else if (rw.kind == UVM_WRITE) begin
      transaction.master_rw = WRITE;
      transaction.data  = rw.data;
    end
    return transaction;
  endfunction

amiq_apb_master_simple_seq is an extension of a uvm_se_item.