在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
查看: 751|回复: 3

[求助] uvm寄存器模型,sequence_item类型转换的问题

[复制链接]
发表于 2023-7-16 21:53:41 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x

问题:

UVM_FATAL @ 1000: uvm_test_top.b_env.b_agt.b_sqr [b_sqr] send_request failed to cast sequence item

找不到哪里有问题,特发出来路过的大佬帮帮忙


代码如下:


class base_agent_configure extends uvm_object;

  uvm_active_passive_enum active = UVM_ACTIVE;

  `uvm_object_utils_begin(base_agent_configure)
     `uvm_field_enum(uvm_active_passive_enum , active ,  UVM_ALL_ON )
  `uvm_object_utils_end
  
  function new(string name = "base_agent_configure");
    super.new(name);
  endfunction:new

endclass:base_agent_configure
class base_agent extends uvm_agent;

  `uvm_component_utils(base_agent)
   uvm_analysis_port#( base_transaction ) agt_ap;

  base_agent_configure b_agt_cfg;
  base_monitor    b_mon;
  base_driver     b_drv;
  base_sequencer  b_sqr;
  base_reg_adapter b_adp;

  function new(string name = "base_agent", uvm_component parent);
    super.new(name,parent);
    b_agt_cfg  =  base_agent_configure ::type_id::create( .name( "b_agt_cfg" ), .parent( this ) );
  endfunction:new


  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    if ( ! uvm_config_db#( base_agent_configure )::get( .cntxt( this ),
                                                           .inst_name ( "" ),
                                                           .field_name( "b_agt_cfg" ),
                                                           .value( b_agt_cfg )))
    begin
       `uvm_error( "base_agent", "b_agt_cfg not found" )
    end
    agt_ap = new(.name("agt_ap"),.parent(this));
   
    if(b_agt_cfg.active == UVM_ACTIVE) begin
      b_drv = base_driver   ::type_id::create( .name( "b_drv" ), .parent( this ) );
      b_sqr = base_sequencer::type_id::create( .name( "b_sqr" ), .parent( this ) );
    end
      b_mon = base_monitor  ::type_id::create( .name( "b_mon" ), .parent( this ) );
      b_adp = base_reg_adapter::type_id::create( .name( "b_adp" ), .parent( this ) );
  endfunction:build_phase

  function void connect_phase(uvm_phase phase);
    super.connect_phase(phase);
    if(b_agt_cfg.active == UVM_ACTIVE) begin
      b_drv.seq_item_port.connect(b_sqr.seq_item_export);
    end
      b_mon.mon_ap.connect(agt_ap);
  endfunction:connect_phase

endclass:base_agent
   


class base_driver extends uvm_driver#(base_transaction);

  `uvm_component_utils(base_driver)

  virtual dut_if vif;

  function new(string name = "base_driver", uvm_component parent);
    super.new(name,parent);
  endfunction:new

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
   
    if ( ! uvm_config_db#(  virtual dut_if  )::get( .cntxt( this ),
                                                           .inst_name ( "" ),
                                                           .field_name( "vif" ),
                                                           .value( vif )))
    begin
       `uvm_error( "base_driver", "vif not found" )
    end

  endfunction:build_phase

  task run_phase(uvm_phase phase);
    base_transaction b_tr;
    super.run_phase(phase);
    forever begin
      b_tr = base_transaction::type_id::create( .name( "b_tr" ) );
      @vif.master_cb;
      vif.master_cb.command <= base_transaction::NO_OP;
      vif.master_cb.din <= 0;

      seq_item_port.get_next_item(b_tr);
      @vif.master_cb;
      vif.master_cb.command <= b_tr.command;
      if(b_tr.command == base_transaction::WRITE)
        vif.master_cb.din <= b_tr.data_in;
      else if (b_tr.command == base_transaction::READ) begin
        @vif.master_cb;
        b_tr.data_out = vif.master_cb.dout;
      end

      seq_item_port.item_done();
    end
  endtask:run_phase

endclass:base_driver


typedef  uvm_reg_predictor#(base_transaction) base_reg_predictor;
class base_env extends uvm_env;

  `uvm_component_utils(base_env)

  base_agent         b_agt;
  base_fc_subscriber b_fc ;
  base_sb_subscriber b_sb ;
  base_reg_predictor b_prd;
  base_reg_block     b_blk;

  function new( string name, uvm_component parent );
    super.new( name, parent );
    b_blk = base_reg_block     ::type_id::create( .name( "b_blk " ), .parent( this ) );
  endfunction: new

  function void build_phase( uvm_phase phase );
    super.build_phase( phase );
    b_agt = base_agent         ::type_id::create( .name( "b_agt" ), .parent( this ) );
    b_fc  = base_fc_subscriber ::type_id::create( .name( "b_fc " ), .parent( this ) );
    b_sb  = base_sb_subscriber ::type_id::create( .name( "b_sb " ), .parent( this ) );
    b_prd = base_reg_predictor ::type_id::create( .name( "b_prd " ), .parent( this ) );
  endfunction: build_phase

  function void connect_phase( uvm_phase phase );
    super.connect_phase( phase );
    b_agt.agt_ap.connect(b_fc.analysis_export );
    b_agt.agt_ap.connect(b_sb.analysis_export );
    b_blk.reg_map.set_sequencer( .sequencer( b_agt.b_sqr ),.adapter( b_agt.b_adp) );
    b_blk.reg_map.set_auto_predict( .on( 0 ) );
    b_prd.map     = b_blk.reg_map;
    b_prd.adapter = b_agt.b_adp;
    b_agt.agt_ap.connect( b_prd.bus_in );
  endfunction: connect_phase

endclass: base_env

class base_fc_subscriber extends uvm_subscriber#(base_transaction);

  `uvm_component_utils(base_fc_subscriber)

  base_transaction b_tr;
  
   covergroup cg;
      DIN:     coverpoint b_tr.data_in;
      DOUT:     coverpoint b_tr.data_out;
   endgroup: cg

  function new(string name, uvm_component parent);
    super.new(name,parent);
    cg = new;
  endfunction:new

  function void write(base_transaction t);
    b_tr = t;
    cg.sample();
  endfunction:write

endclass:base_fc_subscriber
class base_monitor extends uvm_monitor;

  `uvm_component_utils(base_monitor)

  uvm_analysis_port #(base_transaction) mon_ap;

  virtual dut_if vif;

  function new(string name = "base_monitor", uvm_component parent);
    super.new(name,parent);
  endfunction:new

  function void build_phase( uvm_phase phase );
    super.build_phase( phase );
    if ( ! uvm_config_db#(  virtual dut_if  )::get( .cntxt( this ),
                                                           .inst_name ( "" ),
                                                           .field_name( "vif" ),
                                                           .value( vif )))
    begin
       `uvm_error( "base_monitor", "vif not found" )
    end
    mon_ap = new(.name("mon_ap"),.parent(this));
   endfunction: build_phase

  task run_phase (uvm_phase phase);
    base_transaction b_tr;
    forever begin
      b_tr = base_transaction::type_id::create( .name( "b_tr" ) );

      @vif.slave_cb;
      if (vif.command == base_transaction::WRITE) begin
        b_tr.command = vif.command;
        @vif.slave_cb;
        b_tr.data_in = vif.slave_cb.din;
        mon_ap.write(b_tr);
      end else if (vif.command == base_transaction::READ) begin
        b_tr.command = vif.command;
        @vif.slave_cb;
        b_tr.data_out = vif.slave_cb.dout;
        mon_ap.write(b_tr);
      end
    end
  endtask:run_phase

endclass:base_monitor

class base_reg_adapter extends uvm_reg_adapter;

  `uvm_object_utils(base_reg_adapter)

  function new(string name = "base_reg_adapter");
    super.new(name);
        supports_byte_enable = 0;
        provides_responses = 0;
  endfunction:new

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

        if(rw.kind == UVM_READ)        b_tr.command = base_transaction::READ;
        else if (rw.kind == UVM_WRITE) b_tr.command = base_transaction::WRITE;
        else                           b_tr.command = base_transaction::NO_OP;

        if (rw.kind == UVM_WRITE)      b_tr.data_in = rw.data;

        return b_tr;
  endfunction:reg2bus

  virtual function void bus2reg (uvm_sequence_item bus_item,ref uvm_reg_bus_op rw);
    base_transaction b_tr;

      if ( ! $cast( b_tr, bus_item ) ) begin
         `uvm_fatal( get_name(),
                     "bus_item is not of the jelly_bean_transaction type." )
         return;
      end

      rw.kind = ( b_tr.command == base_transaction::READ ) ? UVM_READ : UVM_WRITE;

      if ( b_tr.command == base_transaction::READ )
        rw.data = b_tr.data_out;
      else if ( b_tr.command == base_transaction::WRITE )
        rw.data = b_tr.data_in;
      rw.status = UVM_IS_OK;
   endfunction: bus2reg
   
endclass: base_reg_adapter
class base_reg_block extends uvm_reg_block;
  `uvm_object_utils(base_reg_block)

  rand base_din_reg b_din_reg;
  rand base_dout_reg b_dout_reg;
  uvm_reg_map reg_map;

  function new(string name="base_reg_block");
    super.new(.name(name),.has_coverage(UVM_NO_COVERAGE));
    reg_map = create_map( .name( "reg_map" ), .base_addr( 8'h00 ), .n_bytes( 2 ), .endian( UVM_LITTLE_ENDIAN ) );
  endfunction:new

  virtual function void build();
    b_din_reg = base_din_reg::type_id::create("b_din_reg");
        b_din_reg.configure(.blk_parent(this));
        b_din_reg.build();

    b_dout_reg = base_dout_reg::type_id::create("b_dout_reg");
        b_dout_reg.configure(.blk_parent(this));
        b_dout_reg.build();


    reg_map.add_reg( .rg( b_din_reg ), .offset( 8'h00 ), .rights( "WO" ) );
    reg_map.add_reg( .rg( b_dout_reg  ), .offset( 8'h01 ), .rights( "RO" ) );
    lock_model(); // finalize the address mapping
   endfunction: build
   
endclass: base_reg_block   

class base_din_reg extends uvm_reg;

  `uvm_object_utils(base_din_reg)

  rand uvm_reg_field din;

  function new (string name = "base_din_reg");
    super.new(.name(name),.n_bits(8),.has_coverage(UVM_NO_COVERAGE ));
  endfunction:new

  virtual function void build();
    din = uvm_reg_field::type_id::create("din");
        din.configure(.parent                 ( this ),
                  .size                   ( 8    ),
                  .lsb_pos                ( 0    ),
                  .access                 ( "WO" ),
                  .volatile               ( 0    ),
                  .reset                  ( 0    ),
                  .has_reset              ( 1    ),
                  .is_rand                ( 1    ),
                  .individually_accessible( 1    ) );
   endfunction: build
endclass: base_din_reg

class base_dout_reg extends uvm_reg;

  `uvm_object_utils(base_dout_reg)

  rand uvm_reg_field dout;

  function new (string name = "base_dout_reg");
    super.new(.name(name),.n_bits(8),.has_coverage(UVM_NO_COVERAGE));
  endfunction:new

  virtual function void build();
    dout = uvm_reg_field::type_id::create("dout");
        dout.configure(.parent                 ( this ),
                  .size                   ( 8    ),
                  .lsb_pos                ( 0    ),
                  .access                 ( "RO" ),
                  .volatile               ( 0    ),
                  .reset                  ( 0    ),
                  .has_reset              ( 1    ),
                  .is_rand                ( 1    ),
                  .individually_accessible( 1    ) );
   endfunction: build
endclass: base_dout_reg

class base_sb_subscriber extends uvm_subscriber#(base_transaction);

  `uvm_component_utils(base_sb_subscriber)
  base_transaction b_tr;

  function new( string name, uvm_component parent );
      super.new( name, parent );
  endfunction: new

   function void write(base_transaction  t );
     uvm_table_printer p = new;
     b_tr = t;
     if (b_tr.data_in == b_tr.data_out) begin
         `uvm_info( "base_sb_subscriber",{ "\nYou got a good dut.\n", b_tr.sprint( p ) },UVM_LOW );
      end else begin
         `uvm_error( "base_sb_subscriber", { "\nYou got a bad dut!\n", b_tr.sprint( p ) } );
      end
   endfunction: write
endclass: base_sb_subscriber

class base_sequencer extends uvm_sequencer #(base_transaction);

  `uvm_component_utils(base_sequencer)

  function new(string name = "base_sequencer", uvm_component parent);
    super.new(name,parent);
  endfunction

endclass:base_sequencer

class base_sequence extends uvm_reg_sequence ;

  `uvm_object_utils(base_sequence)

  base_reg_block   b_blk;
  base_transaction b_tr;

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

  task body();
    uvm_status_e    status;
    uvm_reg_data_t  value;

    b_tr = base_transaction::type_id::create(.name("b_tr"));

    if ( !$cast(b_blk, model))
         `uvm_error( "base_sequence", " reg model cast field" )
    b_tr.randomize();
//    write_reg(b_blk.b_din_reg,status,b_tr.data_in);
    read_reg (b_blk.b_dout_reg,status,value);

  endtask:body

endclass:base_sequence
class base_test extends uvm_test;

  `uvm_component_utils(base_test)

  base_env b_env;
  base_agent_configure b_agt_cfg;
  base_reg_block b_blk;

   function new( string name, uvm_component parent );
      super.new( name, parent );
      b_agt_cfg  =  base_agent_configure ::type_id::create( .name( "b_agt_cfg" ), .parent( this ) );
          b_blk = base_reg_block::type_id::create( .name( "b_blk" ), .parent( this ) );
   endfunction: new

   function void build_phase( uvm_phase phase );
      super.build_phase( phase );
              uvm_config_db#( base_agent_configure )::set
           ( .cntxt( this ), .inst_name( "*" ), .field_name( "b_agt_cfg" ), .value( b_agt_cfg ) );
         b_env = base_env::type_id::create( .name( "b_env" ), .parent( this ) );
     b_blk.build();
   endfunction: build_phase
   
   virtual function void start_of_simulation_phase( uvm_phase phase );
      super.start_of_simulation_phase( phase );
      uvm_top.print_topology();
      b_env.b_blk.set_coverage(UVM_CVR_ALL);
   endfunction: start_of_simulation_phase

   task main_phase(uvm_phase phase);
     base_sequence b_seq;
     super.main_phase(phase);
     phase.raise_objection(this);
         b_seq = base_sequence::type_id::create( .name( "b_seq" ), .parent( this ) );
     b_seq.model = b_blk;
     `uvm_info( "base_test", { "\n", b_seq.sprint() }, UVM_LOW )
     b_seq.start( b_env.b_agt.b_sqr );     
     phase.drop_objection(this);
   endtask: main_phase
   
endclass: base_test
class base_transaction extends uvm_sequence_item;

  typedef enum bit[1:0] {NO_OP,READ , WRITE} command_e;
  rand bit[7:0] data_in;
  rand bit[7:0] data_out;
  rand command_e command;
   constraint data_in_con {
      data_in dist {[0:100]:=40, [100:500]:=60};
   }

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

  `uvm_object_utils_begin(base_transaction)
    `uvm_field_int ( data_in,       UVM_ALL_ON )
    `uvm_field_int ( data_out,       UVM_ALL_ON )
    `uvm_field_enum( command_e,command,UVM_ALL_ON)
  `uvm_object_utils_end

endclass:base_transaction
module dut(dut_if.slave_mp dut_slave_if);

import tb_pkg::*;

  reg[7:0] din;
  reg[7:0] dout;

  always @(posedge dut_slave_if.clk)
  begin
    dout <= din;
  end

  always @(posedge dut_slave_if.clk)begin
    if(dut_slave_if.command == base_transaction::WRITE)begin
      din <= dut_slave_if.din;
    end else if(dut_slave_if.command == base_transaction::READ)begin
      dut_slave_if.dout <= dout;
    end
  end

endmodule:dut
  

interface dut_if(input bit clk);

  logic[7:0] din;  
  logic[7:0] dout;
  logic[1:0] command;

  clocking master_cb @(posedge clk);
    default input #1step output #1ns;
    output din,command;
    input  dout;
  endclocking

  clocking slave_cb @(posedge clk);
    default input #1step output #1ns;
    input  din,dout,command;
endclocking

  modport master_mp (input clk,dout,output din,command);
  modport slave_mp  (input clk,din,command, output dout);
  modport master_sync_mp(clocking master_cb);
  modport slave_sync_mp (clocking slave_cb);

endinterface:dut_if
package tb_pkg;
  import uvm_pkg::*;
`include "./src/base_transaction.sv"

`include "./src/base_reg.sv"
`include "./src/base_reg_block.sv"
`include "./src/base_reg_adpter.sv"

`include "./src/base_sequence.sv"
`include "./src/base_sequencer.sv"
`include "./src/base_driver.sv"
`include "./src/base_monitor.sv"
`include "./src/base_agent_configure.sv"
`include "./src/base_agent.sv"
`include "./src/base_fc_subscriber.sv"
`include "./src/base_sb_subscriber.sv"
`include "./src/base_env.sv"
`include "./src/base_test.sv"

endpackage: tb_pkg

module top;
  import uvm_pkg::*;
  import tb_pkg::*;

  reg clk;
  dut_if u_dut_if(clk);
  dut    u_dut(u_dut_if);

  initial begin $fsdbDumpfile("tb_top.fsdb");end
  initial begin
     clk = 0;
    #5ns ;
     forever #5ns clk = ! clk;
  end
  
  initial begin
   uvm_config_db#( virtual dut_if  )::set( .cntxt( null ),
                                                           .inst_name ( "uvm_test_top.*" ),
                                                           .field_name( "vif" ),
                                                           .value( u_dut_if ));
     run_test();
  end
   
endmodule: top


 楼主| 发表于 2023-7-17 10:24:53 | 显示全部楼层
在env和test中错误的创建了两个寄存器模型,应该只创建一次,其他的使用句柄的方式调用。
发表于 2023-7-17 17:41:13 | 显示全部楼层
帮顶
 楼主| 发表于 2023-7-20 10:02:50 | 显示全部楼层


多谢,问题原因和解决办法我已经给出了


您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /2 下一条

×

小黑屋| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-4-30 22:36 , Processed in 0.024049 second(s), 8 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表