当前位置: 首页 > news >正文

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

相关文章:

SV学习笔记(八)

文章目录 SV入门练习基本数据类型字符串类型数组类型接口的定义与例化类的封装类的继承package的使用随机约束线程的同步线程的控制虚方法方法&#xff08;任务与函数&#xff09;SV用于设计 参考资料 SV入门练习 基本数据类型 有符号无符号、四状态双状态、枚举类型、结构体…...

Java反射常用方法

反射 作用&#xff1a; 对于任意一个对象&#xff0c;把对象所有的字段名和值&#xff0c;保存到文件中去利用反射动态的创造对象和运行方法 1. 获取字节码文件对象 方法描述Class.forName(String)通过类的全限定名字符串获取字节码文件对象。类字面量直接使用类的字面量获…...

go语言实现无头单向链表

什么是无头单向链表 无头单向链表是一种线性数据结构&#xff0c;它的每个元素都是一个节点&#xff0c;每个节点都有一个指向下一个节点的指针。"无头"意味着这个链表没有一个特殊的头节点&#xff0c;链表的第一个节点就是链表的头。 优点&#xff1a; 动态大小&…...

SpringBoot快速入门笔记(5)

文章目录 一、elemetnUI1、main.js2、App.vue3、fontAwesome 一、elemetnUI 开源前端框架&#xff0c;安装 npm i element-ui -S 建议查看官方文档 Element组件&#xff0c;这里是Vue2搭配elementUI&#xff0c;如果是vue3就搭配elementPlus&#xff0c;这里初学就以Vue2为例子…...

solidity(3)

地址类型 pragma solidity ^0.8.0;contract AddressExample {// 地址address public _address 0x7A58c0Be72BE218B41C608b7Fe7C5bB630736C71;address payable public _address1 payable(_address); // payable address&#xff0c;可以转账、查余额// 地址类型的成员uint256…...

笔记 | 编译原理L1

重点关注过程式程序设计语言编译程序的构造原理和技术 1 程序设计语言 1.1 依据不同范型 过程式(Procedural programming languages–imperative)函数式(Functional programming languages–declarative)逻辑式(Logical programming languages–declarative)对象式(Object-or…...

k8s存储卷 PV与PVC 理论学习

介绍 存储的管理是一个与计算实例的管理完全不同的问题。PersistentVolume 子系统为用户和管理员提供了一组 API&#xff0c;将存储如何制备的细节从其如何被使用中抽象出来。为了实现这点&#xff0c;我们引入了两个新的 API 资源&#xff1a;PersistentVolume 和 Persistent…...

【WPF应用32】WPF中的DataGrid控件详解与示例

在WPF&#xff08;Windows Presentation Foundation&#xff09;开发中&#xff0c;DataGrid控件是一个强大的数据绑定工具&#xff0c;它以表格的形式展示数据&#xff0c;并支持复杂的编辑、排序、过滤和分组等操作。在本文中&#xff0c;我们将详细介绍DataGrid控件的功能、…...

numpy,matplotilib学习(菜鸟教程)

所有内容均来自于&#xff1a; NumPy 教程 | 菜鸟教程 Matplotlib 教程 | 菜鸟教程 numpy模块 numpy.nditer NumPy 迭代器对象 numpy.nditer 提供了一种灵活访问一个或者多个数组元素的方式。 for x in np.nditer(a, orderF):Fortran order&#xff0c;即是列序优先&#x…...

Web API(四)之日期对象节点操作js插件重绘和回流

Web API(四)之日期对象&节点操作&js插件&重绘和回流 日期对象实例化方法时间戳DOM 节点插入节点删除节点查找节点父子关系兄弟关系M端事件js插件重绘和回流进一步学习 DOM 相关知识,实现可交互的网页特效 能够插入、删除和替换元素节点能够依据元素节点关系查找…...

27.WEB渗透测试-数据传输与加解密(1)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;26.WEB渗透测试-BurpSuite&#xff08;五&#xff09; BP抓包网站网址&#xff1a;http:…...

山寨windows

我的目标是能够运行windows 下的大部分PE格式的程序&#xff0c;这一点通过实验已经证明完全是可行的。 PE格式主要有exe dll sys等文件&#xff0c;这三个文件可以用相同的函数解析&#xff0c; 主要有以下段组成&#xff0c; 1、文件头&#xff0c;包含DOS文件头、PE文件头…...

unity工程输出的log在哪里?

在编辑器里进行活动输出的log位置&#xff1a; C:\Users\username\AppData\Local\Unity\Editor\Editor.log ------------------------------------ 已经打包完成&#xff0c;形成的exe运行后的log位置&#xff1a; C:\Users\xxx用户\AppData\LocalLow\xx公司\xx项目...

【力扣】7. 整数反转

7. 整数反转 题目描述 给你一个 32 位的有符号整数 x &#xff0c;返回将 x 中的数字部分反转后的结果。 如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] &#xff0c;就返回 0。 假设环境不允许存储 64 位整数&#xff08;有符号或无符号&#xff09;。 …...

Android Apk签名算法使用SHA256

Android apk签名算法使用SHA256 本文不介绍复杂的签名过程&#xff0c;说一下Android签名算法使用SHA256。 但是SHA1不是相对安全签名算法&#xff0c;SHA256更加安全一些。 一般大公司才会有这种细致的安全要求。 如何查看apk签名是否是SHA1还是SHA256 1、拿到apk文件&…...

2024.3.13力扣每日一题——最大二进制奇数

2024.3.13 题目来源我的题解方法一 贪心 题目来源 力扣每日一题&#xff1b;题序&#xff1a;2864 我的题解 方法一 贪心 统计1的个数&#xff0c;满足要求的字符串的末尾一位一定是1&#xff0c;所以需要将一位1放到末尾&#xff0c;然后将剩余的1从最高位开始放&#xff0…...

2024.4.1力扣每日一题——故障键盘

2024.4.1 题目来源我的题解方法一 直接利用StringBuilder的反转函数方法二 字符数组 题目来源 力扣每日一题&#xff1b;题序&#xff1a;2810 我的题解 方法一 直接利用StringBuilder的反转函数 使用StringBuilder构造结果&#xff0c;并利用其反转函数进行翻转 时间复杂度…...

第十四届蓝桥杯C/C++大学B组题解(一)

1、日期统计 #include <bits/stdc.h> using namespace std; int main() {int array[100] {5, 6, 8, 6, 9, 1, 6, 1, 2, 4, 9, 1, 9, 8, 2, 3, 6, 4, 7, 7,5, 9, 5, 0, 3, 8, 7, 5, 8, 1, 5, 8, 6, 1, 8, 3, 0, 3, 7, 9,2, 7, 0, 5, 8, 8, 5, 7, 0, 9, 9, 1, 9, 4, 4, 6,…...

4.网络编程-websocket(golang)

目录 什么是websocket golang中使用websocket Server端 Client端 什么是websocket WebSocket是一种在互联网上提供全双工通信的协议&#xff0c;即允许服务器和客户端之间进行双向实时通信的网络技术。它是作为HTML5的一部分标准化的&#xff0c;旨在解决传统HTTP协议在实…...

docker安装部署mysql后忘记root密码

应用场景是&#xff1a;用docker安装完mysql后&#xff0c;使用安装时候设置的密码登录不上MySQL&#xff1b; 1、修改docker映射出mysql的配置文件&#xff1a;my.cnf 在mysqld最下方添加skip-grant-tables进入安全模式&#xff08;随意一个密码即可登录mysql&#xff09; [m…...

c++的学习之路:14、list(1)

本章讲一下如何使用list&#xff0c;代码在文章末 目录 一、list介绍 二、增 三、删 四、查和改 五、交换 六、代码 一、list介绍 首先还是看一看官方文档的介绍如下图&#xff0c;如下方五点&#xff1a; 1. list是可以在常数范围内在任意位置进行插入和删除的序列式…...

huawei 华为交换机 配置 VLAN 聚合示例

组网需求 某公司拥有多个部门且位于同一网段&#xff0c;为了提升业务安全性&#xff0c;将不同部门的用户划分到不同VLAN 中&#xff0c;如 图 5-7 所示&#xff0c; VLAN2 和 VLAN3 属于不同部门。各部门均有访问Internet需求&#xff0c;同时由于业务需要&#xff0c;不同部…...

【QT+QGIS跨平台编译】056:【pdal-dimbuilder+Qt跨平台编译】(一套代码、一套框架,跨平台编译)

点击查看专栏目录 文章目录 一、pdal介绍二、dimbuilder介绍三、pdal下载四、文件分析五、pro文件六、编译实践七、生成Dimension.hpp八、生成pdal_features.hpp一、pdal介绍 PDAL(Point Data Abstraction Library)是一个开源库,用于处理点云数据的获取、过滤、转换、分析和…...

【Python】探索Python中的aiohttp:构建高效并发爬虫

后来 我总算学会了 如何去爱 可惜你 早已远去 消失在人海 后来 终于在眼泪中明白 有些人 一旦错过就不再 &#x1f3b5; HouZ/杨晓雨TuTu《后来》 在数据密集和网络密集的任务中&#xff0c;提高程序的执行效率是非常重要的。Python作为一门强大的编程语言…...

创建真实项目vue2项目

1. 创建 vue create 项目名 2. 选择自定义 3. 勾选以下必备选项 4.选择使用vue2 5. 选择哈希模式&#xff08;n&#xff09;; css选择Less 6. ESLint校验 选择 7. 保存&#xff08;按照默认&#xff09; 8. 在哪里添加ESLint文件 9. 要不要把这个改成将来的预设&am…...

【大数据】安装hive-3.1.2

1、上传HIVE包到/opt/software目录并解压到/opt/modules/ tar -zxvf apache-hive-3.1.2-bin.tar.gz -C /opt/modules/ 2、修改路径 mv /opt/modules/apache-hive-3.1.2-bin/ /opt/modules/hive 3、将hIVE下的bin目录加入到/etc/profile中 export HIVE_HOME/opt/module…...

STM32工程 如何设置堆栈大小(Heap和Stack)

方法1&#xff1a;通过CubeMX、CubeIDE 配置 方法2&#xff1a;直接在启动文件中修改 &#xff08;适合所有Keil工程&#xff09; Heap、Stack的值大小&#xff0c;不管使用哪种开发环境&#xff0c;它俩都肯定在启动文件中。 可以通过CtrlF&#xff0c;搜索: Heap&#xff0…...

光纤资源运维管理升级方案,让您的网络资产价值倍增!

光纤资源管理的现状与风险 1. 管理现状 ▌▶ 排查难 ▌▶ 跟踪难 2. 潜在风险 故障隐患 资源丢失 增加业务中断时长 纤心占用不清 障排查复杂 运维压力巨大 基于数字孪生物联网技术的数字化管理升级方案 1. 快速创建光纤资源数字孪生空间 市级 区级 街道 光缆 机房 机柜 2…...

【深度学习】最强算法之:深度Q网络(DQN)

深度Q网络 1、引言2、深度Q网络2.1 定义2.2 原理2.3 实现方式2.4 算法公式2.5 代码示例 3、总结 1、引言 小屌丝&#xff1a;鱼哥&#xff0c; 马上清明小长假了&#xff0c; 你这准备去哪里玩啊&#xff1f; 小鱼&#xff1a;哪也不去&#xff0c;在家待着 小屌丝&#xff1a…...

微软文本转语音和语音转文本功能更新,效果显著!

今天我要和大家分享一个新功能更新——微软的文本转语音和语音转文本功能。最近&#xff0c;微软对其AI语音识别和语音合成技术进行了重大升级&#xff0c;效果非常好&#xff0c;现在我将分别为大家介绍这两个功能。 先来听下这个效果吧 微软文本转语音和语音转文本功能更新 …...

怎么做一个商城网站/域名138查询网

在Java中&#xff0c;我们可以对List集合进行如下几种方式的遍历&#xff1a;List list new ArrayList<>();list.add(5);list.add(23);list.add(42);for (int i 0; i < list.size(); i) {System.out.print(list.get(i) ",");}Iterator it list.iterator…...

网站开发技术文章/seo推广怎么入门

一、前言在前文中&#xff0c;【4.3 修改端口】涉及了修改nginx 端口的问题&#xff0c;这里做一个补充。问题说明&#xff1a;LNMPA 中的是Apache &#xff0c;也就是前文中安装的httpd 服务。而该服务的默认端口就是80 端口&#xff0c;nginx 的默认端口也是80 端口&#xff…...

秦皇岛网站建设哪里有/深圳网站优化推广

先说一下自己的个人情况&#xff0c;大专生&#xff0c;15年通过校招进入湖南某软件公司&#xff0c;干了接近7年的点点点&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了七年的功能测…...

网站怎样恶意刷/北京seo培训机构

虚拟局域网VLAN(Virtual LAN)是交换机端口的逻辑组合。VLAN 工作在OSI 的第2 层&#xff0c;一个VLAN 就是一个广播域&#xff0c;VLAN 之间的通信是通过第3 层的路由器来完成的。 VLAN 有以下优点&#xff1a; (1) 控制网络的广播问题&#xff1a;每一个VLAN是一个广播域&…...

ps怎么做网站分隔线/域名注册服务网站

题目 题目描述 给你两个二进制字符串&#xff0c;返回它们的和&#xff08;用二进制表示&#xff09;。 输入为 非空 字符串且只包含数字 1 和 0。 示例 1 输入: a “11”, b “1” 输出: “100” 示例 2 输入: a “1010”, b “1011” 输出: “10101” 提示 每个字符串…...

华为官方手表网站/天津网络广告公司

上一回&#xff0c;咱们实现了从后台传递数据&#xff0c;在图表中展现&#xff0c;而图表的大部分配置都实在JS中控制的&#xff0c;javascript我的有个想法&#xff0c;咱们应该能够将图表的配置都拿到后台去&#xff0c;没有在实际开发中使用过&#xff0c;不知道是否好用&a…...