1.task 与 functions
(1.1)task
任务可以包含参数声明、输入参数、输出参数、输入参数、寄存器、事件和零或多个行为语句。任务可以是static(静态的)也可以是automatic(动态的) 。静态任务为所有任务调用共享相同的存储空间,动态任务为每个任务调用分配唯一的堆叠存储空间。
SV允许:
- 在静态任务中声明动态变量,也可以在动态任务中声明静态变量;
- 声明端口的更多功能;
- 在任务结束前使用return返回; (返回值是什么???)
- 通过引用、值、名称和位置传递参数值;
- 存在默认的参数值;
- 默认的参数方向是input;
- 默认的参数类型是logic
看下面例子:
(1)在方法名的括号内部声明参数,并标明输入输出方向
module sv_task;
int x;
//task to add two integer numbers.
task sum(input int a,b,output int c);
c = a+b;
endtask
initial begin
sum(10,5,x);
$display("\tValue of x = %0d",x);
end
endmodule
(2)在方法体内部声明参数和方向
module sv_task;
int x;
//task to add two integer numbers.
task sum;
input int a,b;
output int c;
c = a+b;
endtask
initial begin
sum(10,5,x);
$display("\tValue of x = %0d",x);
end
endmodule
(1.2)function
函数可以包含范围声明、返回类型声明、参数声明、输入参数声明、寄存器声明和事件声明.和任务一样,函数分为静态的和动态的。
- 没有范围或返回类型声明的函数返回一个1bit的值;
- 任何表达式都可以用作函数参数;
- 函数不能包含任何时间控制的语句,也不能调用任务;
- 函数只能返回一个值
SV允许:
- 在静态函数中声明动态变量,也可以在动态函数中声明静态变量;
- 声明端口的更多功能;
- 在函数结束前使用return返回;
- 通过引用、值、名称和位置传递参数值;
- 存在默认的参数值;
- 默认的参数方向是input;
- 默认的参数类型是logic;
-
SV中的Task和Function不需要,必须加一个begin..end来指明body,但是需要加入标识符。
task muliple_line;
......body...
endtask :multiple_line
看下面例子:
(1)在函数名的括号内部声明参数
module sv_function;
int x;
//function to add two integer numbers.
function int sum(input int a,b);
sum = a+b;
endfunction
initial begin
x=sum(10,5);
$display("\tValue of x = %0d",x);
end
endmodule
(2)在函数体内部声明参数
module sv_function;
int x;
//function to add two integer numbers.
function int sum;
input int a,b;
sum = a+b;
endfunction
initial begin
x=sum(10,5);
$display("\tValue of x = %0d",x);
end
endmodule
(3)带return关键字的函数
module sv_function;
int x;
//function to add two integer numbers.
function int sum;
input int a,b;
return a+b;
endfunction
initial begin
x=sum(10,5);
$display("\tValue of x = %0d",x);
end
endmodule
(4) Void 函数,无返回值
module sv_function;
int x;
//void function to display current simulation time
function void current_time;
$display("\tCurrent simulation time is %0d",$time);
endfunction
initial begin
#10;
current_time();
#20;
current_time();
end
endmodule
(5)丢弃函数的返回值,用关键字void
module sv_function;
int x;
//function to add two integer numbers.
function int sum;
input int a,b;
return a+b;
endfunction
initial begin
$display("Calling function with void");
void'(sum(10,5));//丢弃返回值
end
endmodule
(6)函数作为表达式的一部分
module sv_function;
int x;
//function to add two integer numbers.
function int sum;
input int a,b;
return a+b;
endfunction
initial begin
x = 10 + sum(10,5);
$display("\tValue of x = %0d",x);
end
endmodule
(1.3) function 和task 的区别
区别有传参种类、ref类型、传参缺省值、传参方向
a:函数与任务的主要区别是任务可以带时序,函数不能。
函数和任务的传参可以在名字后的小括号里,也可以在函数和任务体内。传参是默认顺序,也可以使用.in(addr)这种形参方式。
函数和任务的参数缺省值为方向为input,类型为logic。建议不缺省。一旦指定一个参数的方向,那它就成为后面参数的缺省方向。
参数方向可以为input、output、inout(函数开始时复制,结束时输出)、ref(传递引用,传递句柄或指针),如果传参为const ref,这函数内部不会改变此参数。ref只能用在automatic的子程序。
传参默认值时,调用此函数时,可以缺少传参。否则,不能缺少传参。
void’( func1()); 忽略func1函数的返回值,仿真器不会告警。
module和program,package的函数和任务默认是静态的,可以使用automatic改为动态的。而在class中的函数和任务默认是动态automatic的。可以在静态函数中,指定变量或者形参为自动的;也可以在自动函数中,将形参和变相声明称静态的。
2.fork .. join / begin .. end
fork join 中的语句是并行执行的,维并行语句块。语句之间并行执行,同时开始;
begin end是串行执行既顺序执行语句。
2.1 fork join 用来标识并行执行的语句,用它的标识的块称为 并行块;
示例:
fork
语句1;
语句2;
....
语句n;
join
特点:
- 块内语句同时执行的,程序流程控制进入该模块时刻,块内语句即开始同时并行执行;
- 当耗时最长的语句执行完成后,程序才跳出该并行模块;
2.2 begin end 用来标识顺序执行的语句,用它标识的块称作顺序块;
示例
begin
语句1;
语句2;
....
语句n;
end
特点:
- 块内语句顺序执行的,即只有上面一条语句执行完后下面的语句才能执行;
- 最后一条语句执行完,程序才跳出该语句块
2.3 fork join / fork join_any / fork join_none
这三个兄弟虽然长的比较像,但是其实性格是不一样的!他们的主要性格区别是他们对待称为“线程”的小朋友的态度上。“线程”小朋友是轻量级的“进程”,是程序调度的基本单位。假如某一时段同时来了好几个线程小朋友去他们家吃饭,三兄弟性格可以表现的非常明显。其中fork-join的性格是最温和耐心的,他会静静等待所有线程小朋友全部吃完饭才去做别的事情。而fork-join_any性格是最健忘和丢三落四的,当他看到其中某个线程小朋友吃完后会直接忘了别的小朋友还在吃,以为都完成了,直接去做自己的事情。至于fork-join_none则是脾气最暴躁的,他不会等待任何一个线程小朋友吃饭,会直接去搞自己的事情.
.
.贴代码
.
.
.
3.mailbox
前言:mailboxe是一种通信机制,允许进程之间交换消息。希望与另一个进程通信的进程将消息发送到mailboxe,mailboxe将消息临时存储在系统定义的内存对象中,以便将消息传递给所需的进程。
Mailboxes赋值:new()
放数据:put()
非阻塞放数据:try_put()
获取数据:get()或peek()
非阻塞获取数据:try_get()或try_peek()
获取Mailboxes中的数据数:num()
....
.
.
.
.lizi
.
4.semaphore 旗语
作用
信号是通过初始化一定数量的许可证,通过限制获得许可证的线程数量来阻塞未获取许可证达的线程,达到限制对特定资源访问的线程数量。
接口函数
new(): Creat a semaphore with a specified number kerys;
get(): OBtian one or more keys from the busket;
put(): Return one or more kyes into the bucker;
try_get(): Try to obtian one or maor keys without blocking;
使用举例
单许可证,两线程竞争:
sem = new(1)
process 1:
sem.get(1);
....
sem.put(1);
process 1:
sem.get(1);
....
sem.put(1);
多许可证,多线程竞争
sem = new(5)
process 1:
sem.get(2);
....
sem.put(2);
process 1:
sem.get(2);
....
sem.put(2);
process 2:
sem.get(2);
....
sem.put(2);
5.events
6.interface