6.1 sequence基礎(chǔ)
6.2 sequence的仲裁機(jī)制
(1)通過(guò) uvm_do_pri 和 uvm_do_pri_with 改變所產(chǎn)生的transaction的優(yōu)先級(jí):
? ? ? ? ? ? "my_case0.sv"
? ? ? ? ? ? class sequence0 extends uvm_sequence #(my_transaction);
? ? ? ? ? ? ? ? ...
? ? ? ? ? ? ? ? virtual task body();
????????????????????`uvm_do_pri(m_trans, 100)
? ? ? ? ? ? ? ? ? ?? or
????????????????????`uvm_do_pri_with(m_trans, 200, {m_trans.pload.size < 500;})
? ? ? ? ? ? 第二個(gè)參數(shù)是優(yōu)先級(jí)溶褪,這個(gè)數(shù)必須是一個(gè)大于等于-1的整數(shù)矾柜,數(shù)字越大肮柜,優(yōu)先級(jí)越高。
(2)sequencer的仲裁算法:
? ? ? ? ? ? SEQ_ARB_FIFO(默認(rèn)仲裁算法,遵循先入先出,不考慮優(yōu)先級(jí))
? ? ? ? ? ? SEQ_ARB_WEIGHTED(加權(quán)的仲裁)
? ? ? ? ? ? SEQ_ARB_RANDOM(完全隨機(jī)選擇)
? ? ? ? ? ? SEQ_ARB_STRICT_FIFO(嚴(yán)格按照優(yōu)先級(jí),當(dāng)有多個(gè)同一優(yōu)先級(jí)的sequence時(shí)行施,按照先入先出的順序選擇)
? ? ? ? ? ? SEQ_ARB_STRICT_RANDOM(嚴(yán)格按照優(yōu)先級(jí),當(dāng)有多個(gè)同一優(yōu)先級(jí)的sequence時(shí)魂那,隨即從最高優(yōu)先級(jí)中選擇)
? ? ? ? ? ? SEQ_ARB_USER(用戶(hù)自定義的仲裁算法)
? ? ? ? 若想要優(yōu)先級(jí)起作用蛾号,應(yīng)該設(shè)置仲裁算法為SEQ_ARB_STRICT或者SEQ_ARB_STRICT_RANDOM:
? ? ? ? ? ? env.i_agt.sqr.set_arbitration(SEQ_ARB_STRICT_FIFO);
? ? ? ? ? ? fork
? ? ? ? ? ? ? ? seq0.start(env.i_agt_sqr);
? ? ? ? ? ? ? ? seq1.start(env.i_agt_sqr);
? ? ? ? ? ? join
(3)lock 操作
? ? ? ?? grab 操作(比lock優(yōu)先級(jí)更高,放入sequencer仲裁隊(duì)列的最前面)
? ? ? ?? is_relevent() 函數(shù)(1說(shuō)明此sequence有效涯雅,否則無(wú)效)
? ? ? ?? wait_for_relevent() 函數(shù)
6.3 sequence相關(guān)宏及其實(shí)現(xiàn)
(1)uvm_do系列
(2)uvm_create 與 uvm_send
(3)uvm_rand_send鲜结,與uvm_send類(lèi)似,唯一區(qū)別是它會(huì)對(duì)transaction進(jìn)行隨機(jī)化
? ? ? ? ? ? ? ? m_trans = new("m_trans");
? ? ? ? ? ? ? ? `uvm_rand_send(m_trans);
(4)`uvm_do系列宏其實(shí)是將下述動(dòng)作封裝在了一個(gè)宏中:
? ? ? ? ? ? ? ? tr = new("tr");
? ? ? ? ? ? ? ? start_item(tr);
? ? ? ? ? ? ? ? assert(tr.randomize() with {tr.pload.size() == 200;});
? ? ? ? ? ? ? ? finish_item(tr);
(5)pre_do (task), mid_do (function), post_do (function)
6.4 sequence進(jìn)階應(yīng)用
(1)嵌套的sequence:在一個(gè)sequence的body中活逆,除了可以使用uvm_do宏產(chǎn)生transaction外精刷,該可以啟動(dòng)其他的sequence,直接在新的sequence的body中調(diào)用定義好的sequence蔗候。
(2)uvm_do, uvm_send, uvm_rand_send, uvm_create宏怒允,其第一個(gè)參數(shù)除了可以是transaction的指針外,還可以是sequence的指針锈遥。start_item & finish_item纫事,這兩個(gè)任務(wù)的參數(shù)必須是transaction的指針。
(3)sequence與transaction都可以調(diào)用randomize進(jìn)行隨機(jī)話(huà)所灸,都可以由rand修飾符的成員變量儿礼。在sequence中定義的rand類(lèi)型變量以向產(chǎn)生的transaction傳遞約束時(shí),變量的名字一定要與transaction中相應(yīng)字段的名字不同庆寺。
(4)`uvm_declare_p_sequencer(my_sequencer) == (my_sequencer p_sequencer);這個(gè)過(guò)程在pre_body()之前就完成了诉字,因此在sequence中可以直接使用成員變量p_sequencer來(lái)訪問(wèn)sequencer中的成員變量懦尝。
6.5 virtual sequence的使用
(1)實(shí)現(xiàn)sequence之間同步最好的方式就是使用virtual sequence知纷。virtual sequence不發(fā)送transaction,它只是控制其他的sequence陵霉,起統(tǒng)一調(diào)度的作用琅轧。為了使用virtual sequence,一般需要一個(gè)virtual sequencer踊挠,其里面包含指向其他真實(shí)sequencer的指針乍桂。
(2)一般來(lái)說(shuō)。只在最頂層的virtual sequence中控制objection效床。
6.6 在sequence中使用config_db
(1)在sequence中獲取參數(shù)
????????????sequence的路徑:uvm_test_top.env.i_agt.sqr.case0_sequence
? ? ? ? ? ? 【uvm_config_db#(int)::set(this, "env.i_agt.sqr.*", "count", 9);】
? ? ? ? ? ? 因?yàn)閟equence在實(shí)例化時(shí)名字一般是不固定的睹酌,而且有時(shí)時(shí)未知的(比如使用default_sequence啟動(dòng)的sequence的名字就是未知的),所i使用通配符剩檀。
? ? ? ? ? ? uvm_config_db#(int)::get(null, get_full_name(), "count", count));
? ? ? ? ? ? 在get函數(shù)原型中憋沿,第一個(gè)參數(shù)必須是component,而sequence不是一個(gè)component沪猴,所以這里不能使用this指針辐啄,只能使用null或uvm_root::get()。
(2)在sequence中設(shè)置參數(shù)
? ? ? ? ? ? uvm_config_db#(bit)::set(uvm_root::get(), "uvm_test_top.env0.scb", "cmp_en", 0);
? ? ? ? ? ? uvm_config_db#(bit)::set(uvm_root::get(), "uvm_test_top.v_sqr.*", "first_start", 0);
(3)一個(gè)sequence是在task phase中運(yùn)行的运嗜,當(dāng)其設(shè)置一個(gè)參數(shù)的時(shí)候壶辜,起事件往往是不固定的。針對(duì)這種不固定的設(shè)置參數(shù)的方式担租,UVM提供了wait_modified任務(wù)砸民。當(dāng)它檢測(cè)當(dāng)?shù)谌齻€(gè)參數(shù)的值被更新過(guò)后,它就返回翩活,否則一直等待在那里:
? ? ? ? ? ? uvm_config_db#(bit)::wait_modified(this, "", "cmp_en");
6.7 response的使用
(1)在driver中阱洪,
? ? ? ? ? ? ? ? rsp = new("rsp"); ??
? ? ? ? ? ? ? ? rsp.set_id_info(req);
? ? ? ? ? ? ? ? seq_item_port.put_response(rsp);
? ? ? ? ? ? ? ? seq_item_port.item_done();
? ? ? ? or
? ? ? ? ? ? ? ? rsp = new("rsp"); ????
? ? ? ? ? ? ? ? rsp.set_id_info(req);
? ? ? ? ? ? ? ? seq_item_port.item_done(rsp);
? ? ? ?? 在sequence中,
? ? ? ? ? ? ? ? virtual task body();
? ? ? ? ? ? ? ? ? ? ?? ...
? ? ? ? ? ? ? ? ? ? ?? get_response(rsp);
6.8 sequence library
(1)隨機(jī)選擇sequence
? ? ? ? class simple_seq_library extends uvm_sequence_library #(my_transaction);
? ? ? ? ? ? function new(string name = "simple_seq_library");
? ? ? ? ? ? ? ? supre.new(name);
? ? ? ? ? ? ? ? init_sequence_library();
? ? ? ? ? ? endfunction
? ? ? ? ? ? `uvm_object_utils(simple_seq_library)
? ? ? ? ? ? `uvm_sequence_library_utils(simple_seq_library);
? ? ? ? endclass
? ? ? ? 一個(gè)sequence在定義時(shí)使用宏uvm_add_to_seq_lib(seq0, simple_seq_library)來(lái)將其加入某個(gè)sequence library中菠镇。一個(gè)sequence可以加入多個(gè)sequence library中冗荸。
(2)控制選擇算法
? ? ? ? typedef enum {UVM_SEQ_LIB_RAND, UVM_SEQ_LIB_RANDC, UVM_SEQ_LIB_ITEM, UVM_SEQ_LIB_USER} uvm_sequence_lib_mode;
? ? ? ? UVM_SEQ_LIB_RAND:完全隨機(jī)。
? ? ? ? UVM_SEQ_LIB_RANDC:將加入其中的sequence隨機(jī)排一個(gè)順序利耍,然后按照此順序執(zhí)行蚌本,可以保證每個(gè)sequence執(zhí)行一遍。配置方式:
? ? ? ? ? ? ? ? ?? uvm_config_db#(uvm_sequence_lib_mode)::set(this, "env.i_agt.sqr.main_phase", "default_sequence.selection_mode", UVM_SEQ_LIB_RANDC);
? ? ? ? UVM_SEQ_LIB_ITEM:sequence library并不執(zhí)行其sequence隊(duì)列中的sequence隘梨,而是自己產(chǎn)生transaction程癌。
? ? ? ? UVM_SEQ_LIB_USER:用戶(hù)自定義選擇的算法。此時(shí)需要用戶(hù)重載select_sequence參數(shù):
? ? ? ? ? ? ? ? ? ? virtual function int unsigned select_sequence(int unsigned max);
? ? ? ? ? ? ? ? ? ? ?? ...
? ? ? ? ? ? ? ? ? ? endfunction
(3)控制執(zhí)行次數(shù)
? ? ? ? ? ? ? ? ? ? min_random_count, max_random_count
(4)UVM提供了一個(gè)類(lèi)uvm_sequence_library_cfg來(lái)對(duì)sequence library進(jìn)行配置:
? ? ? ? ? ? ? ? ? ? uvm_sequence_library_cfg ?? cfg;
? ? ? ? ? ? ? ? ? ? super.build_phase(phase);
? ? ? ? ? ? ? ? ? ? cfg = new("cfg", UVM_SEQ_LIB_RANDC, 5, 20);
? ? ? ? ? ? ? ? ? ? uvm_config_db#(uvm_object_wrapper)::set(this, "env.i_agt.sqr.main_phase", "default_sequence", simple_seq_library::type_id::get());
? ? ? ? ? ? ? ? ? ? uvm_config_db#(uvm_sequence_library_cfg)::set(this. "env.i_agt.sqr.main_phase", "default_sequence.config", cfg);
? ? ? ? or
? ? ? ? ? ? ? ? ? ? simple_seq_library?????seq_lib;
? ? ? ? ? ? ? ? ? ? super.build_phase(phase);
? ? ? ? ? ? ? ? ? ? seq_lib = new("seq_lib");
? ? ? ? ? ? ? ? ? ? seq_lib.selection_mode = UVM_SEQ_LIB_RANDC;
? ? ? ? ? ? ? ? ? ? seq_lib.min_random_count = 10;
? ? ? ? ? ? ? ? ? ? seq_lib.max_random_count = 15;
? ? ? ? ? ? ? ? ? ? uvm_config_db#(uvm_sequence_base)::set(this, "env.i_agt.sqr.main_phase", "default_sequence", seq_lib);