SV学习笔记(八)

文章目录

  • SV入门练习
    • 基本数据类型
    • 字符串类型
    • 数组类型
    • 接口的定义与例化
    • 类的封装
    • 类的继承
    • package的使用
    • 随机约束
    • 线程的同步
    • 线程的控制
    • 虚方法
    • 方法(任务与函数)
    • SV用于设计
  • 参考资料

SV入门练习

基本数据类型

  • 有符号无符号、四状态双状态、枚举类型、结构体

module data_bytebit b_signed_vs_unsigned = 1;
bit b_bit_vs_logic = 1;
bit b_enum_type = 1;
bit b_struct_type = 1;// TODO-1: distinguish signed and unsigned type
initial begin: signed_vs_unsignedbyte b0;bite[7:0] b1;wait(b_signed_vs_unsigned == 1);$display("signed_vs_unsigned process block started");b0 = 'b1000_0000;$display("byte variable b0 = %d", b0);b1 = b0;$display("bit vector variable b1 = %d", b1)
end// TODO-2: distinguish bit and logic
initial initial begin: bit_vs_logicbit v1;logic v2;wait(b_bit_vs_logic == 1); $display("bit_vs_logic process block started");v2 = 'b1;$display("logic variable v2 = %d", v2);v1 = v2;$display("bit variable v1 = %d", v1);v2 = 'b0;$display("logic variable v2 = %d", v2);v1 = v2;$display("bit variable v1 = %d", v1);v2 = 'bx;$display("logic variable v2 = %d", v2);v1 = v2;$display("bit variable v1 = %d", v1);v2 = 'bz;$display("logic variable v2 = %d", v2);v1 = v2;$display("bit variable v1 = %d", v1);
end// TODO-3: enum type
initial begin: enum_typetypedef enum {IDLE, START, PROC, END} state_t;state_t st1, st2;wait(b_enum_type == 1); $display("enum_type process block started");st1 = IDLE;$display("st1 value = %0d (int)", st1);$display("st1 value = %s (string)", st1); // implicit conversion$display("st1 value = %s (string)", st1.name());st2 = state_t'(1);$display("st1 value = %0d (int)", st2);$display("st1 value = %s (string)", st2.name());
end// TODO-4: struct type
initial begin: struct_typetypedef struct {bit[7:0] addr;bit[31:0] data;bit is_write;int id;} trans_t;trans_t t1, t2, t3;wait(b_struct_type == 1); $display("struct_type process block started");t1 = '{'h10, 'h1122_3344, 'b1, 'h1000};$display("t1 data content is %p", t1);t2.addr = 'h20;t2.data = 'h5566_7788;t2.is_write = 'b0;t2.id = 'h2000;$display("t2 data content is %p", t2);t3 = t2;t3.data = 'h99AA_BBCC;t3.id = 'h3000;$display("t3 data content is %p", t3);$display("t2 data content is %p", t2);
endendmodule

字符串类型

  • 构建字符串和字符串拼接 (一般常用$sformatf函数)
module string_type;bit b_string_format = 1;
bit b_string_builtin_function = 1;// TODO-1 understand how to formulate a new string
initial begin: string_formatstring s1, s2, s3, s4;wait(b_string_format == 1);$display("string_format process block started");s1 = "Welcome";s2 = "www.rockeric.com";s3 = {s1, " to ", s2}; // concatenation operator '{...}'$display("s3 content: %s", s3);s4 = $sformatf("%s to %s", s1, s2); // system format function$display("s4 content: %s", s4);
end// TODO-2  understand how s3 is composed with s1 and s2
initial begin: string_builtin_functionstring s1, s2, s3;int i1;wait(b_string_builtin_function == 1); $display("string_builtin_function process block started");s1 = "RockerIC is established in ";i1 = 2015;s2.itoa(i1); // integer converted to strings3 = {s1.len()+s2.len(){" "}}; // try to comment this line and check the resultfor(int i=0; i<s1.len()+s2.len(); i++) begins3[i] = i < s1.len() ? s1[i] : s2[i-s1.len()];end$display("s3 content: %s", s3);
endendmodule

数组类型

  • 合并非合并、赋值与循环、动态数组、队列、关联数组
module array_type;bit b_unpacked_vs_packed = 1;
bit b_array_assigment_and_loop = 1;
bit b_dynamic_array = 1;
bit b_queue_use = 1;
bit b_associate_array = 1;// TODO-1 learn the difference between unpacked and packed data storage and
// assignment
initial begin: unpacked_vs_packedbit [7:0] unpacked_word [3:0];bit [3:0] [7:0] packed_word;wait(b_unpacked_vs_packed == 1); $display("unpacked_vs_packed process block started");// legal assignmentunpacked_word[0] = 10;unpacked_word[1] = 32;unpacked_word[2] = 54;unpacked_word[3] = 76;$display("unpacked_word = %p", unpacked_word);// legal assignment with '{}unpacked_word = '{76, 54, 32, 10};$display("unpacked_word = %p", unpacked_word);// legal assignmentpacked_word[0] = 10;packed_word[1] = 32;packed_word[2] = 54;packed_word[3] = 76;$display("packed_word = %p", packed_word);// legal assignment with {} but without 'packed_word = {76, 54, 32, 10};$display("packed_word = %p", packed_word);// legal assignment directly like a vector packedt_word[31:0]packed_word = (76<<24) + (54<<16) + (32<<8) + 10;$display("packed_word = %p", packed_word);// illegal assignment// packed_word = unpacked_word [X]// unpacked_word = packed_word [X]// illegal assignment between packed and unpacked arrayforeach(packed_word[i])packed_word[i] = unpacked_word[i];foreach(unpacked_word[i])unpacked_word[i] = packed_word[i];
end// TODO-2 learn the array assignment and foreach loop indexing method
initial begin: array_assigment_and_loopinteger sum [4][2]; // 8*4 size arraywait(b_array_assigment_and_loop == 1); $display("array_assigment_and_loop process block started");// concatenation and default valuesum = '{0:'{'h21, 'h43}, default:'{default:'x}};// foreach loop indexingforeach(sum[i, j]) begin$display("sum[%0d][%0d] = 'h%0x", i, j, sum[i][j]);end
end// TODO-3 learn the dynamic array basics
initial begin: dynamic_arrayint dyn1[], dyn2[];wait(b_dynamic_array == 1); $display("dynamic_array process block started");dyn1 = '{1, 2, 3, 4};$display("dyn1 = %p", dyn1);// copp method option-1dyn2 = dyn1;$display("dyn2 = %p", dyn2);$display("dyn2 size is %0d", dyn2.size());// copp method option-2dyn2 = new[dyn1.size()](dyn1);$display("dyn2 = %p", dyn2);$display("dyn2 size is %0d", dyn2.size());dyn2.delete();$display("dyn2 size is %0d", dyn2.size());
end// TODO-4: learn queue use
initial begin: queue_useint que1[$], que2[$];wait(b_queue_use == 1); $display("queue_use process block started");que1 = {10, 30, 40};$display("que1 = %p", que1);que2 = que1;$display("que2 = %p", que1);que1.insert(1, 20);$display("que1 = %p", que1);que1.delete(3); // delete que1[3]==40void'(que1.pop_front()); // pop que[0]==10$display("que1 = %p", que1);que1.delete();$display("que1 = %p", que1);
end// TODO-5 learn associate array use
initial begin: associate_arrayint id_score1[int], id_score2[int]; // key ID, value SCOREwait(b_associate_array == 1); $display("associate_array process block started");id_score1[101] = 111;id_score1[102] = 222;id_score1[103] = 333;id_score1[104] = 444;id_score1[105] = 555;// associate array copyid_score2 = id_score1;id_score2[101] = 101;id_score2[102] = 102;id_score2[103] = 103;id_score2[104] = 104;id_score2[105] = 105;foreach(id_score1[id]) begin$display("id_score1[%0d] = %0d", id, id_score1[id]);endforeach(id_score2[id]) begin$display("id_score2[%0d] = %0d", id, id_score2[id]);end
endendmodule

接口的定义与例化

  • 接口里也可以定义方法
// TODO-1 understand how the interface is defined and instantied
// TODO-2 check how to define methods inside interface and call them internally or externally
// TODO-3 understand how to prepare transactions, drive them and monitor them
module interface_type;typedef struct {bit[7:0] addr;bit[31:0] data;bit write;int id;} trans_t;// struct print utility functionfunction void trans_print(trans_t t, string name = "trans");string s;s  = $sformatf("%s struct content is as below \n", name);s  = $sformatf("%s\taddr  = 'h%2x \n", s, t.addr);s  = $sformatf("%s\tdata  = 'h%8x \n", s, t.data);s  = $sformatf("%s\twrite = 'b%0b \n", s, t.write);s  = $sformatf("%s\tid    = 'h%8x \n", s, t.id);$display("%s", s);endfunctioninterface intf1;logic [7:0] addr;logic [31:0] data;logic write;int id;// transaction drive tasktask drive_trans(trans_t t);addr  <= t.addr ;data  <= t.data ;write <= t.write;id    <= t.id   ;endtask// transaction monitor tasktask mon_trans(output trans_t t);t.addr  = addr ;t.data  = data ;t.write = write;t.id    = id   ;endtaskendinterface// interface instantiationintf1 if1();initial begintrans_t trans_in[3], trans_mon[3];// stimulus preparationtrans_in = '{'{'h10, 'h1122_3344, 'b1, 'h1000},'{'h14, 'h5566_7788, 'b0, 'h1001},'{'h18, 'h99AA_BBCC, 'b1, 'h1002}};foreach(trans_in[i]) begin#10;// stimulus driveif1.drive_trans(trans_in[i]);trans_print(trans_in[i], $sformatf("trans_in[%0d]",i));#10;// stimulus monitorif1.mon_trans(trans_mon[i]);trans_print(trans_mon[i], $sformatf("trans_mon[%0d]",i));// transaction comparisonif(trans_in[i] === trans_mon[i])$display("trans_in[%0d] === trans_mon[%0d]", i, i);else$error("trans_in[%0d] !== trans_mon[%0d]", i, i);endendendmodule

类的封装

module class_encapsulation;bit b_object_instantiation = 1;class chnl_trans;bit[31:0] data[];int ch_id;int pkt_id;int data_nidles;int pkt_nidles;bit rsp;int obj_id;static int global_obj_id = 0;function new();global_obj_id++;obj_id = global_obj_id;endfunctionfunction chnl_trans clone();chnl_trans c = new();c.data = this.data;c.ch_id = this.ch_id;c.pkt_id = this.pkt_id;c.data_nidles = this.data_nidles;c.pkt_nidles = this.pkt_nidles;c.rsp = this.rsp;return c;endfunctionfunction string sprint();string s;s = {s, $sformatf("obj_id = %0d: \n", this.obj_id)};foreach(data[i]) s = {s, $sformatf("data[%0d] = %8x \n", i, this.data[i])};s = {s, $sformatf("ch_id = %0d: \n", this.ch_id)};s = {s, $sformatf("pkt_id = %0d: \n", this.pkt_id)};s = {s, $sformatf("data_nidles = %0d: \n", this.data_nidles)};s = {s, $sformatf("pkt_nidles = %0d: \n", this.pkt_nidles)};s = {s, $sformatf("rsp = %0d: \n", this.rsp)};return s;endfunctionendclass: chnl_trans// TODO-1 learn the object instantiation
// TODO-2 learn the handle pointting to an object
// TODO-3 learn the class function clone()/sprint()
// TODO-4 compare if t1, t2 and t3 are pointting to the same object?
// TODO-5 check if the t1 pointted object data is exactly the same with the t3
//        pointted object?
// TODO-6 learn how to call STATIC member variable/function, and their
//        difference with local member variable/function
initial begin: object_instantiationchnl_trans t1, t2, t3;wait(b_object_instantiation == 1); $display("b_object_instantiation process block started");t1 = new();t1.data = '{1, 2, 3, 4};t1.ch_id = 2;t1.pkt_id = 100;t2 = t1;$display("t1 object content is as below:\n%s", t1.sprint());$display("t2 object content is as below:\n%s", t2.sprint());t3 = t1.clone();$display("t3 object content is as below:\n%s", t3.sprint());$display("t1 object ID is [%0d]", t1.obj_id);$display("t2 object ID is [%0d]", t2.obj_id);$display("t3 object ID is [%0d]", t3.obj_id);$display("the latest chnl_trans object iD is [%0d]", chnl_trans::global_obj_id);
endendmodule

类的继承

module class_inheritance;bit b_member_override = 1;class trans;bit[31:0] data[];int pkt_id;int data_nidles;int pkt_nidles;bit rsp;function trans clone(trans t = null);if(t == null) t = new();t.data = data;t.pkt_id = pkt_id;t.data_nidles = data_nidles;t.pkt_nidles = pkt_nidles;t.rsp = rsp;return t;endfunctionendclassclass chnl_trans extends trans;int ch_id; // new member in child class// member function override with// same function name, arguments, and return type// TODO-1 seperately enable the clone function-1 and function-2, and check// if both of them works, and compare which is better, and why?// clone function-1function trans clone(trans t = null);chnl_trans ct;if(t == null)ct = new();elsevoid'($cast(ct, t));ct.data = data;ct.pkt_id = pkt_id;ct.data_nidles = data_nidles;ct.pkt_nidles = pkt_nidles;ct.rsp = rsp;ct.ch_id = ch_id; // new memberreturn ct;endfunction// clone function-2// function trans clone(trans t = null);//   chnl_trans ct;//   if(t == null)//     ct = new();//   else//     void'($cast(ct, t));//   void'(super.clone(ct));//   ct.ch_id = ch_id; // new member//   return ct;// endfunctionendclassinitial begin: member_overridetrans t1, t2;chnl_trans ct1, ct2;wait(b_member_override == 1); $display("b_member_override process block started");ct1 = new();ct1.pkt_id = 200;ct1.ch_id = 2;// t1 pointed to ct1's trans class data baset1 = ct1;// t2 copied ct1's trans class data baset2 = ct1.clone();void'($cast(ct2, t2));// TODO-2 why could not clone t1(->ct1) to t2?// t2 = t1.clone(); // ERROR clone call// void'($cast(ct2, t2));$display("ct1.pkt_id = %0d, ct1.ch_id = %0d", ct1.pkt_id, ct1.ch_id);// TODO-3 uncomment the statement below and consider//        why t1 could not point to ct1.ch_id?// $display("ct1.pkt_id = %0d, ct1.ch_id = %0d", t1.pkt_id, t1.ch_id);$display("ct2.pkt_id = %0d, ct2.ch_id = %0d", ct2.pkt_id, ct2.ch_id);endendmodule

package的使用

package sky_pkg;class sun;typedef enum {RISE, FALL} state_e;state_e state = RISE;endclasssun apollo = new();class cloud;endclass
endpackagepackage sea_pkg;class fish;endclassclass island;string name;function new(string name = "island");this.name = name;endfunctionendclassisland hainan = new("hainan");
endpackagemodule package_usage;import sky_pkg::cloud;import sea_pkg::*;import sea_pkg::hainan;// TODO-2 why hainan could not be delcared here?// island hainan;initial begin// TODO-1 why sun type is not recognized? how to make it recognizable?// sun s;// TODO-2 why hainan could be declared here?island hainan;// TODO-3 why apollo is not recognized?// $display("sun state is %s", apollo.state);hainan = new("HAINAN");$display("hainan name is %s", hainan.name);$display("sea_pkg::hainan name is %s", sea_pkg::hainan.name);end
endmodule

随机约束

module constrained_random;bit b_system_random_func = 1;
bit b_class_randomization = 1;// TODO-1 understand how to use system random function, and its advanced
// method such as to generate unique values
initial begin: system_random_funcint unsigned rval;int unsigned gen_vals[$];wait(b_system_random_func == 1); $display("b_system_random_func process block started");// randomize 10 times, and each rand value doesnot care previous generated// valuerepeat(10) beginrval = $urandom_range(0, 9);$display("$urandom_range(0, 9) generated rand value is %0d", rval);end// Do you have other ways to generate unique number each time which should// not be duplicated with previously generate ones?repeat(10) begin$display("gen_vals queue content is %p", gen_vals);std::randomize(rval) with {foreach(gen_vals[i]) rval != gen_vals[i]; rval inside {[0:9]};};gen_vals.push_back(rval);$display("std::randomize with inline constrait generated rand value %0d", rval);end
endclass chnl_trans;rand bit[31:0] data[];rand int ch_id;rand int pkt_id;rand int data_nidles;rand int pkt_nidles;bit rsp;constraint cstr{data.size inside {[4:8]};foreach(data[i]) data[i] == 'hC000_0000 + (this.ch_id<<24) + (this.pkt_id<<8) + i;ch_id == 1;pkt_id == 1;data_nidles inside {[0:2]};pkt_nidles inside {[1:10]};};endclass// TODO-2 learn basic constraint format, class randomization method, soft
// constraint, and how to avolid constraint conflict?
initial begin: class_randomizationchnl_trans ct1, ct2;wait(b_class_randomization == 1); $display("b_class_randomization process block started");ct1 = new();// is ct1 already randomized?$display("ct1.data.size = %0d, ct1.ch_id = %0d, ct1.pkt_id = %0d", ct1.data.size(), ct1.ch_id, ct1.pkt_id);ct2 = new();// is ct2 already randomized?$display("ct2.data.size = %0d, ct2.ch_id = %0d, ct2.pkt_id = %0d", ct2.data.size(), ct2.ch_id, ct2.pkt_id);// why ct2.ch_id and ct2.pkt_id kept the same number even though it has been// randomized several times?repeat(5) beginvoid'(ct2.randomize());$display("ct2.data.size = %0d, ct2.ch_id = %0d, ct2.pkt_id = %0d", ct2.data.size(), ct2.ch_id, ct2.pkt_id);end// the randomization with inline constraint would meets randomization// failure, how to modify?// if(!ct1.randomize() with {ch_id == 2;})//   $error("ct1 randomization failure!");// else//   $display("ct1.data.size = %0d, ct1.ch_id = %0d, ct1.pkt_id = %0d", ct1.data.size(), ct1.ch_id, ct1.pkt_id);
endendmodule

线程的同步

module thread_sync;bit b_event_use = 0;
bit b_mailbox_use = 1;
bit b_mailbox_user_define = 1;// TODO-1.1 event does not new()
// TODO-1.2 learn event copy (direct assignment between two events)
// TODO-1.3 compare @ operator and triggered() method
initial begin: event_useevent e1, e2, e3a, e3b;wait(b_event_use == 1); $display("b_event_use process block started");e3b = e3a; // event copy, e3b and e3a are the same event->e1; // trigger e1 before @e1;->e2; // trigger e2 before e2.triggered();forkbegin @e1;  $display("@%0t, @e1 finished" , $time); endbegin wait(e2.triggered());  $display("@%0t, wait(e2.triggered()) finished" , $time); endbegin @e3a; $display("@%0t, @e3a finished", $time); endbegin @e3b; $display("@%0t, @e3b finished", $time); endjoin_none#10ns;-> e3a;#10ns;-> e1; // trigger e1 again
endclass box;int id;function new(int id);this.id = id;endfunction
endclass// TODO-2 learn the parameterized mailbox and general storage method
initial begin: mailbox_usemailbox #(int) mb_id;mailbox #(box) mb_handle;box bx[5];wait(b_mailbox_use == 1); $display("b_mailbox_use process block started");// mailbox need new(N) for instantiationmb_id = new();mb_handle = new();// mailbox storageforeach(bx[i]) beginbx[i] = new(i);mb_id.put(i);mb_handle.put(bx[i]);end$display("box handles array bx content is %p", bx);// mailbox extraction$display("extracting ID and HANDLE from the TWO mailboxes");repeat(mb_id.num()) beginint id;box handle;mb_id.get(id);mb_handle.get(handle);$display("ID:%0d, HANDLE:%p", id, handle);end// check mailbox size$display("ID mailbox size is %0d", mb_id.num());$display("HANDLE mailbox size is %0d", mb_handle.num());
end// TODO-3 learn how to maximal utilize the mailbox storage with user defined
// type, we modify the 'mailbox_use' block and give a new block
// 'mailbox_user_define'
typedef struct{int id;box handle;
} mb_pair_element_t;initial begin: mailbox_user_definemailbox #(mb_pair_element_t) mb_pair;box bx[5];wait(b_mailbox_user_define == 1); $display("b_mailbox_user_define process block started");// mailbox need new(N) for instantiationmb_pair = new();// mailbox storageforeach(bx[i]) beginbx[i] = new(i);mb_pair.put('{i, bx[i]});end$display("box handles array bx content is %p", bx);// mailbox extraction$display("extracting ID and HANDLE from the ONE mailbox");repeat(mb_pair.num()) beginmb_pair_element_t pair;mb_pair.get(pair);$display("ID:%0d, HANDLE:%p", pair.id, pair.handle);end// check mailbox size$display("PAIR mailbox size is %0d", mb_pair.num);
endendmodule

线程的控制

module thread_control;bit b_fork_join = 1;
bit b_fork_join_any = 0;
bit b_fork_join_none = 0;class box;int id;function new(int id);this.id = id;endfunction
endclassbox bx[3];task automatic thread(int id = 1, int t = 10);$display("@%0t, thread id:%0d entered", $time, id);bx[id] = new(id); // allocate space#(t*1ns);bx[id] = null; // deallocate space$display("@%0t, thread id:%0d exited", $time, id);
endtask// TODO-1 learn fork-join thread exited when all sub-thread exit.
initial begin: fork_joinwait(b_fork_join == 1); $display("b_fork_join process block started");bx = '{null, null, null};$display("@%0t, fork_join_thread entered", $time);fork: fork_join_threadthread(0, 10);thread(1, 20);thread(2, 30);join$display("@%0t, fork_join_thread exited", $time);$display("@%0t, box handles array is %p", $time, bx);#10;b_fork_join = 0;b_fork_join_any = 1;
end// TODO-2.1 learn fork-join_any thread exited when just one sub-thread exites,
// but all other sub-thread are still running.
// TODO-2.2 learn disable BLOCK/fork statement, and check if the running
// sub-threads haven been disabled.
initial begin: fork_join_anywait(b_fork_join_any == 1); $display("b_fork_join_any process block started");bx = '{null, null, null};$display("@%0t, fork_join_any_thread entered", $time);fork: fork_join_any_threadthread(0, 10);thread(1, 20);thread(2, 30);join_any$display("@%0t, fork_join_any_thread exited", $time);$display("@%0t, box handles array is %p", $time, bx);disable fork_join_any_thread;$display("@%0t, disabled fork_join_any_thread", $time);#100ns;$display("@%0t, box handles array is %p", $time, bx);#10ns;b_fork_join_any = 0;b_fork_join_none = 1;
end// TODO-3.1 learn fork-join_none thread exited directly without calling any
// sub-thread, and continue executing other statements. Then the
// fork-join_none sub-threads would be still running.
// TODO-3.2 learn the wait fork statement, and check the time after it is
// satisified. The time should be the point when all fork sub-thread finished.
initial begin: fork_join_nonewait(b_fork_join_none == 1); $display("b_fork_join_none process block started");bx = '{null, null, null};$display("@%0t, fork_join_none_thread entered", $time);fork: fork_join_none_threadthread(0, 10);thread(1, 20);thread(2, 30);join_none$display("@%0t, fork_join_none_thread exited", $time);$display("@%0t, box handles array is %p", $time, bx);#15ns;$display("@%0t, box handles array is %p", $time, bx);wait fork;$display("@%0t, fork_join_none_thread's all sub-threads finished", $time);$display("@%0t, box handles array is %p", $time, bx);
endendmodule

虚方法

// This example is referred to the lec2/class_inheritance
// The purpose is to learn the convenience of virtual method
module virtual_methods;class trans;bit[31:0] data[];int pkt_id;int data_nidles;int pkt_nidles;bit rsp;virtual function trans clone(trans t = null);if(t == null) t = new();t.data = data;t.pkt_id = pkt_id;t.data_nidles = data_nidles;t.pkt_nidles = pkt_nidles;t.rsp = rsp;return t;endfunctionendclassclass chnl_trans extends trans;int ch_id; // new member in child classvirtual function trans clone(trans t = null);chnl_trans ct;if(t == null)ct = new();elsevoid'($cast(ct, t));void'(super.clone(ct));ct.ch_id = ch_id; // new memberreturn ct;endfunctionendclassinitial begintrans t1, t2;chnl_trans ct1, ct2;ct1 = new();ct1.pkt_id = 200;ct1.ch_id = 2;// t1 pointed to ct1's trans class data baset1 = ct1;$display("before cloning ct1 object");$display("ct1.pkt_id = %0d, ct1.ch_id = %0d", ct1.pkt_id, ct1.ch_id);// TODO-1 compare with lec2/class_inheritance TODO-2// why it is legal to call t1.clone() here?// TODO-2 via this example, please summarize the virtual method// conveniencet2 = t1.clone();void'($cast(ct2, t2));// TODO-3 to access ct2.ch_id, could we directly use t2.ch_id?// is it possible to add modified virtual before chnl_trans::ch_id, and// then access it by 't2.ch_id'? and why?$display("after cloning ct1 object");$display("ct1.pkt_id = %0d, ct1.ch_id = %0d", ct1.pkt_id, ct1.ch_id);$display("ct2.pkt_id = %0d, ct2.ch_id = %0d", ct2.pkt_id, ct2.ch_id);endendmodule

方法(任务与函数)

module task_and_function;bit b_function_define = 1;
bit b_task_define = 1;
bit b_inout_vs_ref = 1;function int double_f0(int a);return 2*a;
endfunctionfunction void double_f1(input int a, output int b);b = 2*a;
endfunctionfunction void double_f2(inout int a);a = 2*a;
endfunctionfunction automatic void double_f3(ref int a);a = 2*a;
endfunctiontask double_t1(input int a, output int b);b = 2*a;
endtasktask double_t2(inout int a);a = 2*a;
endtasktask automatic double_t3(ref int a);a = 2*a;
endtasktask double_t2_delay(inout int a);a = 2*a;#10ns;
endtasktask automatic double_t3_delay(ref int a);a = 2*a;#10ns;
endtask// TODO-1 lear the function definition possible ways
initial begin: function_defineint v1, v2;wait(b_function_define == 1); $display("b_function_define process block started");v1 = 10;v2 = double_f0(v1);$display("v1 = %0d, double function result is %0d", v1, v2);v1 = 10;double_f1(v1, v2);$display("v1 = %0d, double function result is %0d", v1, v2);v1 = 10;$display("v1 is %0d before calling double_f2(v1)", v1);double_f2(v1);$display("v1 is %0d (result) after calling double_f2(v1)", v1);v1 = 10;$display("v1 is %0d before calling double_f3(v1)", v1);double_f3(v1);$display("v1 is %0d (result) after calling double_f3(v1)", v1);
end// TODO-2 learn the task definition possible ways
initial begin: task_defineint v1, v2;wait(b_task_define == 1); $display("b_task_define process block started");v1 = 10;double_t1(v1, v2);$display("v1 = %0d, double task result is %0d", v1, v2);v1 = 10;$display("v1 is %0d before calling double_t2(v1)", v1);double_t2(v1);$display("v1 is %0d (result) after calling double_t2(v1)", v1);v1 = 10;$display("v1 is %0d before calling double_t3(v1)", v1);double_t3(v1);$display("v1 is %0d (result) after calling double_t3(v1)", v1);
end// TODO-3 compare the inout and ref argument between function and task use
initial begin: inout_vs_refint v1, v2;wait(b_inout_vs_ref == 1); $display("b_inout_vs_ref process block started");v1 = 10;$display("v1 is %0d before calling double_t2_delay(v1)", v1);forkdouble_t2_delay(v1);begin #5ns; $display("@%0t v1 = %0d in task call double_t2_delay(v1)", $time, v1); endjoin$display("v1 is %0d (result) after calling double_t2_delay(v1)", v1);v1 = 10;$display("v1 is %0d before calling double_t3_delay(v1)", v1);forkdouble_t3_delay(v1);begin #5ns; $display("@%0t v1 = %0d in task call double_t3_delay(v1)", $time, v1); endjoin$display("v1 is %0d (result) after calling double_t3_delay(v1)", v1);
endendmodule

SV用于设计

module sv_for_design;bit b_always_compare = 1;
bit b_compare_operator = 1;
bit b_inside_operator = 1;
bit b_case_statement = 1;// TODO-1 why l2 != l3 at time 0 ?
logic l1 = 0, l2, l3;
always @(l1) l2 <= l1;
always_comb l3 = l1;
initial begin: always_comparewait(b_always_compare == 1); $display("always_compare process block started");#0;$display("@%0t, l2 = %b", $time, l2);$display("@%0t, l3 = %b", $time, l3);#10;l1 <= 1;#1;$display("@%0t, l2 = %b", $time, l2);$display("@%0t, l3 = %b", $time, l3);
end// TODO-2 learn the compare operators' difference
initial begin: compare_operatorlogic [3:0] v1, v2;wait(b_compare_operator == 1); $display("compare_operator process block started");v1 = 'b111x;v2 = 'b1110;if(v1 != v2) // binary logical equality operator$display("v1 %b != v2 %b", v1, v2);else$display("v1 %b == v2 %b", v1, v2);$display("the operator result (v1 != v2) is %b", (v1 != v2));if(v1 !== v2) // binary case equality operator$display("v1 %b !== v2 %b", v1, v2);else$display("v1 %b === v2 %b", v1, v2);$display("the operator result (v1 !== v2) is %b", (v1 !== v2));end// TODO-3 learn the inside operator
initial begin: inside_operatorbit [2:0] v1;wait(b_inside_operator == 1); $display("inside_operator process block started");v1 = 'b100;if(v1 == 'b100 || v1 == 'b010 || v1 == 'b001)$display("v1: %0b meets onehot vector requirement!", v1);else$display("v1: %0b does not meet onehot vector requirement!", v1);if(v1 inside {'b100, 'b010, 'b001})$display("v1: %0b meets onehot vector requirement!", v1);else$display("v1: %0b does not meet onehot vector requirement!", v1);if($onehot(v1) == 1)$display("v1: %0b meets onehot vector requirement!", v1);else$display("v1: %0b does not meet onehot vector requirement!", v1);
end// TODO-4 learn {unique, priority} case{ ,x, z} statement
initial begin: case_statementparameter width_p = 4;bit [width_p-1:0] v_arr[3];wait(b_case_statement == 1); $display("case_statement process block started");v_arr = '{'b1000, 'b1111, 'b0110};foreach(v_arr[i]) beginunique case(v_arr[i])'b0001, 'b0010, 'b0100, 'b1000: $display("v1: %0b meets onehot vector requirement!", v_arr[i]);0: $display("v1: %0b is ZERO", v_arr[i]);'b1111: $display("v1: %0b is ALL ONES", v_arr[i]);default: $display("v1: %0b has [2~%0d] ones", v_arr[i], width_p-1);endcaseend
endendmodule

参考资料

  • Wenhui’s Rotten Pen
  • SystemVerilog
  • chipverify

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/800585.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STM32 F401/411外设内部互联矩阵摘要

STM32 F401/411外设内部互联矩阵摘要 &#x1f4cd;参考文档AN4646&#xff1a;https://www.stmcu.com.cn/Designresource/detail/localization_document/709908(中译) -&#x1f4cc; 相关工程案例《HAL STM32主从定时器联级使用》、《STM32G4 TIM1触发ADC转换》 &#x1f4d…

24考研-东南大学916经验贴

文章目录 一、个人情况二、初试备考经验1.政治 67&#xff0c;客观382.英语 60&#xff0c;客观大概40左右3.数学 136&#xff0c;客观应该满分4.专业课 数据结构计网 114小分不清楚 三、复试备考经验笔试&#xff1a;C面试复试流程 附一下成绩单&#xff1a; 一、个人情况 本…

如何给自己的网站添加 https

文章目录 一、简介二、申请 ssl 证书三、下载 ssl 证书四、配置 nginx五、开放 443 端口六、常见问题解决(一)、配置后&#xff0c;访问 https 无法连接成功(二) 证书配置成功&#xff0c;但是访问 https 还是报不安全 总结参考资料 一、简介 相信大家都知道 https 是更加安全…

【利器篇】前端40+精选VSCode插件,总有几个你未拥有!

前言 姊妹篇&#xff1a; 【利器篇】35精选chrome插件&#xff0c;含15前端插件&#xff0c;总有一款值得你停留 关于关于 【前端工具系列】&#xff1a; 有句话&#xff0c;事半功倍&#xff0c;其必然是借助了某些思想和工具。 VSCode是我们前端开发的武器&#xff0c;本文…

Python学习从0开始——专栏汇总

Python学习从0开始——000参考 一、推荐二、基础三、项目一 一、推荐 Hello World in Python - 这个项目列出了用Python实现的各种"Hello World"程序。 Python Tricks - 这个项目包含了Python中的高级技巧和技术。 Think Python - 这是一本教授Python的在线书籍&…

嵌入式Linux系统调用执行基本流程

内核态与用户态 什么是系统调用 系统调用是怎么实现的 库函数write 库函数扩展汇编宏 int 0x80中断 调用对应的中断处理函数 检索系统调用函数表 最终执行sys_write 内核态与用户态数据交互 内核态与用户态 早期工程师们在操作系统上编写程序的时候,自己写个程序可以访问别人…

面试算法-150-缺失的第一个正数

题目 给你一个未排序的整数数组 nums &#xff0c;请你找出其中没有出现的最小的正整数。 请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,0] 输出&#xff1a;3 解释&#xff1a;范围 [1,2] 中的数字都…

90天玩转Python—07—基础知识篇:Python中运算符详解

90天玩转Python系列文章目录 90天玩转Python—01—基础知识篇:C站最全Python标准库总结 90天玩转Python--02--基础知识篇:初识Python与PyCharm 90天玩转Python—03—基础知识篇:Python和PyCharm(语言特点、学习方法、工具安装) 90天玩转Python—04—基础知识篇:Pytho…

创建型模式--2.简单工厂模式【人造恶魔果实工厂1】

1. 工厂模式的特点 在海贼王中&#xff0c;作为原王下七武海之一的多弗朗明哥&#xff0c;可以说是新世界最大的流氓头子&#xff0c;拥有无上的权利和无尽的财富。他既是德雷斯罗萨国王又是地下世界的中介&#xff0c;控制着世界各地的诸多产业&#xff0c;人造恶魔果实工厂就…

windows10系统下TP-LINK万兆网卡属性配置高级说明

文章目录 打开配置属性说明ARP Offload&#xff1a;ARP地址解析协议卸载Downshift retries:降档重试次数Energy-Efficient Ethernet:高能效以太网Flow Control:流量控制Interrupt Moderation:中断调整Interrupt Moderation Rate:中断调节率IPv4 Checksum Offload:IPv4校验和卸载…

2024/4/2—力扣—连续数列

代码实现&#xff1a; 思路&#xff1a;最大子数组和 解法一&#xff1a;动态规划 #define max(a, b) ((a) > (b) ? (a) : (b))int maxSubArray(int* nums, int numsSize) {if (numsSize 0) { // 特殊情况return 0;}int dp[numsSize];dp[0] nums[0];int result dp[0];fo…

three.js零基础入门超全超细的教程整理(一)

事情是这样的&#xff1a; 有一天 我干完活 看技术文章 发现了three.js 诶&#xff01;这玩应挺有意思 盘盘 于是第一天找教程 上官网 初上手 第二天 找案例 渲模型 试VR 第三天 捋文档 然后来活了 没时间捋了 下面是集百家精华教程的整理总结 涉及到教程方面有加源作者和地址…

企业3D数字化网络展馆成为企业文化传承与发扬的圣地

在河北这片古老而富饶的土地上&#xff0c;文明的火种薪火相传&#xff0c;燕赵之风历久弥新。河北企业也多年持续稳居我国第五的宝座&#xff0c;企业文化展馆不仅是企业形象的展示窗口&#xff0c;更是企业文化传承与发扬的圣地。 与短暂的行业展会不同&#xff0c;企业展馆是…

JWT身份验证是什么

JWT(JSON Web Token)是一种用于安全传输信息的开放标准(RFC 7519),它可以作为 JSON 对象在各方之间安全地传输信息。JWT通常用于身份验证和声明传递,并且经常用于在客户端和服务器之间进行身份验证和授权。 JWT 的结构 一个 JWT 由三部分组成,每部分之间使用点号 . 分…

用户登录时md5加密源码解析

首先&#xff0c;在登录的时候&#xff0c;将页面提交的密码password加密处理&#xff0c;即password DigestUtils.md5DigestAsHex(password.getBytes()); 接着按ctrl鼠标左键&#xff0c;进入md5DigestAsHex函数中进行查看&#xff1a; 可以发现&#xff0c;md5DigestAsHex函…

xen虚拟机不支持hugepage

今天在xen虚拟机的/etc/sysctl.conf cat /etc/sysctl.conf | grep -i huge vm.nr_hugepages189440 vm.nr_overcommit_hugepages 7500 然后运行sysctl -p使之生效的时候碰到了如下错误 sysctl: setting key “vm.nr_hugepages”: Operation not supported vm.nr_hugepages 18…

顺序表实战——基于顺序表的通讯录

前言&#xff1a;本篇文章主要是利用顺序表作为底层&#xff0c; 实现一个通讯录。偏向于应用&#xff0c; 对于已经学习过c的友友们可能没有难度了已经。没有学习过c的友友&#xff0c; 如果顺序表不会写&#xff0c; 或者说没有自己实现过&#xff0c; 请移步学习顺序表相关内…

ElasticSearch基础及面经

ElasticSearch基础及面经 Elaticsearch&#xff0c;简称为es&#xff0c; es是一个开源的高扩展的分布式全文检索引擎&#xff0c;它可以近乎实时的存储、检索数据&#xff1b;本身扩展性很好&#xff0c;可以扩展到上百台服务器&#xff0c;处理PB级别的数据。es也使用Java开…

【CVE复现计划】CVE-2024-0195

CVE-2024-0195 简介&#xff1a; SpiderFlow是新一代开源爬虫平台&#xff0c;以图形化方式定义爬虫流程&#xff0c;不写代码即可完成爬虫。基于springbootlayui开发的前后端不分离,也可以进行二次开发。该系统/function/save接口存在RCE漏洞&#xff0c;攻击者可以构造恶意命…

C++语言学习(四)—— 字符串处理函数

目录 一、字符串处理函数 1.1 输入字符串函数 scanf_s函数和get_s函数 1.2 字符串长度计算函数 strlen 1.3 字符串复制函数 strcpy_s 1.4 字符串连接函数 strcat_s 1.5 字符串比较函数 strcmp 1.6 其他字符串处理函数 一、字符串处理函数 在C中&#xff0c;字符串是一串…