在Verilog里面采用module/endmodule 来组成整个design的hierarchy结构, 比如, 如下的代码:
会产生如下的hierarchy结构:
目前在Verilog的LRM, 有如下几种scope类型:
- Module
- Task
- Funcion
- Named block
在IVerilog 里面, 定义了如下6中scope以及相关的定义如下:
-
vpiModule
-
vpiTask
-
vpiFunction
上述3中, 比较常见, 忽略例子; -
vpiNamedBegin
begin … end之间的语句是串行执行的;begin: scope_name declaration; state1 state2 ... stateN end
-
vpiNamedFork
fork … join之间的语句是并行执行的;fork: scope_name declaration; state1 state2 ... stateN join
-
vpiGenScope
1 、generate-for语句必需用genvar关键字定义for的索引变量;
2、 for的内容必须用begin…end块包起来,哪怕只有一句;
3、 begin…end块必须起个名字;module gray2bin1 (bin, gray); parameter SIZE = 8; // this module is parameterizable output [SIZE-1:0] bin; input [SIZE-1:0] gray; genvar i;generate for(i=0; i<SIZE; i=i+1) begin:bit assign bin[i] = ^gray[SIZE-1:i]; end endgenerate endmodule
在vvp/vpi_scope.cc里面, 对于上述6中类型的scope, 每一种定义了一个class, 继承自__vpiScope积累。
在Iverilog的整个流程里面, IVerilog负责产生一个xx.vvp 文件, 这是一个网表结构的文件, vvp程序会读取该文件, 产生vvp内存的信号;
从*.v scope的产生
在verilog .v文件里面,每次碰到一个scope, 在parser.y文件定义了每一种label对应的处理函数:
void
compile_scope_decl(char*label, char*type, char*name, char*tname,
char*parent, long file_idx, long lineno,
long def_file_idx, long def_lineno, long is_cell)
{
count_vpi_scopes += 1;
char vec_type;
char sign_flag;
unsigned wid;
__vpiScope*scope;
if (strcmp(type,"module") == 0) {
scope = new vpiScopeModule(name, tname);
} else if ( sscanf(type, "function.vec%c.%c%u", &vec_type, &sign_flag, &wid) == 3 ) {
int type_code;
if (sign_flag=='s') {
type_code = vpiSizedSignedFunc;
} else if (sign_flag=='u') {
type_code = vpiSizedFunc;
} else if (sign_flag=='i') {
type_code = vpiIntFunc;
} else {
assert(0);
type_code = vpiSizedFunc;
}
vvp_bit4_t init_val = vec_type == '4' ? BIT4_X : BIT4_0;
scope = new vpiScopeFunction(name, tname, false, type_code, wid, init_val);
} else if ( sscanf(type, "autofunction.vec%c.%c%u", &vec_type, &sign_flag, &wid) == 3 ) {
int type_code;
switch (sign_flag) {
case 's':
type_code = vpiSizedSignedFunc;
break;
case 'u':
type_code = vpiSizedFunc;
break;
default:
assert(0);
type_code = vpiSizedFunc;
break;
}
vvp_bit4_t init_val = vec_type == '4' ? BIT4_X : BIT4_0;
scope = new vpiScopeFunction(name, tname, true, type_code, wid, init_val);
} else if (strcmp(type,"function.obj") == 0) {
scope = new vpiScopeFunction(name, tname, false, vpiSizedFunc, 0, BIT4_0);
} else if (strcmp(type,"autofunction.obj") == 0) {
scope = new vpiScopeFunction(name, tname, true, vpiSizedFunc, 0, BIT4_0);
} else if (strcmp(type,"function.real") == 0) {
scope = new vpiScopeFunction(name, tname, false, vpiRealFunc, 0, BIT4_0);
} else if (strcmp(type,"autofunction.real") == 0) {
scope = new vpiScopeFunction(name, tname, true, vpiRealFunc, 0, BIT4_0);
} else if (strcmp(type,"function.str") == 0) {
scope = new vpiScopeFunction(name, tname, false, vpiOtherFunc, 0, BIT4_0);
} else if (strcmp(type,"autofunction.str") == 0) {
scope = new vpiScopeFunction(name, tname, true, vpiOtherFunc, 0, BIT4_0);
} else if (strcmp(type,"function.void") == 0) {
scope = new vpiScopeFunction(name, tname, false, vpiOtherFunc, 0, BIT4_0);
} else if (strcmp(type,"autofunction.void") == 0) {
scope = new vpiScopeFunction(name, tname, true, vpiOtherFunc, 0, BIT4_0);
} else if (strcmp(type,"task") == 0) {
scope = new vpiScopeTask(name, tname);
} else if (strcmp(type,"autotask") == 0) {
scope = new vpiScopeTaskAuto(name, tname);
} else if (strcmp(type,"fork") == 0) {
scope = new vpiScopeFork(name, tname);
} else if (strcmp(type,"autofork") == 0) {
scope = new vpiScopeForkAuto(name, tname);
} else if (strcmp(type,"begin") == 0) {
scope = new vpiScopeBegin(name, tname);
} else if (strcmp(type,"autobegin") == 0) {
scope = new vpiScopeBeginAuto(name, tname);
} else if (strcmp(type,"generate") == 0) {
scope = new vpiScopeGenerate(name, tname);
} else if (strcmp(type,"package") == 0) {
scope = new vpiScopePackage(name, tname);
} else if (strcmp(type,"class") == 0) {
scope = new vpiScopeClass(name, tname);
} else {
scope = new vpiScopeModule(name, tname);
assert(0);
}
scope->file_idx = (unsigned) file_idx;
scope->lineno = (unsigned) lineno;
scope->def_file_idx = (unsigned) def_file_idx;
scope->def_lineno = (unsigned) def_lineno;
scope->item = 0;
scope->nitem = 0;
scope->live_contexts = 0;
scope->free_contexts = 0;
if (is_cell) scope->is_cell = true;
else scope->is_cell = false;
current_scope = scope;
compile_vpi_symbol(label, scope);
free(label);
free(type);
delete[] name;
delete[] tname;
if (parent) {
static vpiHandle obj;
compile_vpi_lookup(&obj, parent);
assert(obj);
__vpiScope*sp = dynamic_cast<__vpiScope*>(obj);
vpip_attach_to_scope(sp, scope);
scope->scope = dynamic_cast<__vpiScope*>(obj);
/* Inherit time units and precision from the parent scope. */
scope->time_units = sp->time_units;
scope->time_precision = sp->time_precision;
} else {
scope->scope = 0x0;
vpip_root_table.push_back(scope);
/* Root scopes inherit time_units and precision from the
system precision. */
scope->time_units = vpip_get_time_precision();
scope->time_precision = vpip_get_time_precision();
}
}
添加scope的自对象
current_scope是一个全局变量, 指到当前正在处理的scope:
__vpiScope* vpip_peek_current_scope(void)
{
return current_scope;
}
void vpip_attach_to_scope(__vpiScope*scope, vpiHandle obj)
{
assert(scope);
scope->intern.push_back(obj);
}