Principles of PLI VPI Verilog Procedural InterfaceVPI PLI

  • Slides: 23
Download presentation
Principles of PLI

Principles of PLI

VPI • Verilog Procedural Interface(VPI) – PLI 2. 0: the third generation of PLI

VPI • Verilog Procedural Interface(VPI) – PLI 2. 0: the third generation of PLI library function – Remove the inconsistency and incompleteness in both tf and acc routines in PLI 1. 0 • Can not use tf or acc routines to read the condition that makes a while loop to terminate. – Functions in PLI 1. 0 and PLI 2. 0 are independent of each other and can co-exist in the same user application.

A PLI Routine Using VPI • User C functions: applications – – The main

A PLI Routine Using VPI • User C functions: applications – – The main body of a PLI routine Implement the functionality of the corresponding system call Include a header file called “vpi_user. h” A set of pre-specified but user-defined functions • sizetf, calltf, compiletf: The actual name is completely user-defined. – sizetf • Returns an integer which is same as the number of bits in the returned value of the system call – calltf • The main function which implements the functionality of the system call – compiletf • Initialize a set of variables which can be used later during the entire simulation

A PLI Routine Using VPI • The registration function – Registering the associated functions

A PLI Routine Using VPI • The registration function – Registering the associated functions and other properties of a system call • First: the names of the associated functions and other properties of the system call are assigned to different fields of a structure of type “s_vpi_systf_data” • Second: using the library function “vpi_register_systf()” typedef struct t_vpi_systf_data { PLI_INT 32 type; /* vpi. Sys. Task, vpi. Sys. Func */ PLI_INT 32 sysfunctype; /* vpi. Sys. Task, vpi[Int, Real, Time, Sized. Signed]Func */ PLI_BYTE 8 *tfname; /* first character must be `$' */ PLI_INT 32 (*calltf)(PLI_BYTE 8 *); /* the calltf function name */ PLI_INT 32 (*compiletf)(PLI_BYTE 8 *); /* the compiletf function name */ PLI_INT 32 (*sizetf)(PLI_BYTE 8 *); /* for sized function callbacks only */ PLI_BYTE 8 *user_data; } s_vpi_systf_data, *p_vpi_systf_data;

A PLI Routine Using VPI • The start-up array vlog_startup_routines[] – Lists all the

A PLI Routine Using VPI • The start-up array vlog_startup_routines[] – Lists all the registration functions – Presents them to the simulator – An array of pointers to functions returning void types – The last element in this array should be zero.

A simple example$add_int() /**************** * The registration function * ****************/ void registration(); void registration()

A simple example$add_int() /**************** * The registration function * ****************/ void registration(); void registration() /* Place all the function registration here */ { s_vpi_systf_data task_data_s; /*declare the structure */ task_data_s. type = vpi. Sys. Task; /* No return value for out system call */ task_data_s. tfname =“$add_int”; /* HDL task name */ task_data_s. calltf = add_int_call_tf; /* The calltf routine */ task_data_s. compiletf = NULL; /* No function, enter NULL */ vpi_register_systf(&task_data_s); /* Registering the task */ } /* ***************************** The start-up array, the last element must be a zero. * *******************************/ void (*vlog_startup_routines[]) () = {registration, 0}; #include <stdio. h> #include "vpi_user. h" #include "vpi_user_cds. h" /********************** * The user C function add_int_calltf() * **********************/ int add_int_calltf(); int add_int_calltf() { pintrf(“Enter the first integer: ”; scanf(“%d”, &n 1); printf(“Enter the second integer: ”); scanf(“%d”, &n 2); printf(“The sum of two integers: %dn”, n 1+n 2); }

A simple example- $set_values() #include "vpi_user. h" #include "vpi_user_cds. h" #include "set_values. h" static

A simple example- $set_values() #include "vpi_user. h" #include "vpi_user_cds. h" #include "set_values. h" static s_vpi_systf_data systf. List[] = { {vpi. Sys. Task, 0, "$set_values", set_values_calltf, set_values_checktf, 0, 0}, {0}, }; void setup_set_value_callbacks() { p_vpi_systf_data_p = &(systf. List[0]); while (systf_data_p->type) { vpi_register_systf(systf_data_p++); if (vpi_chk_error(NULL)) { vpi_printf("Error occurred while setting up user %sn", "defined system tasks and functions. "); return; } } } void (*vlog_startup_routines[VPI_MAXARRAY])() = { setup_set_value_callbacks, 0 /*** final entry must be 0 ***/ };

Integrating user application with Verilog simulator • The same as what has been described

Integrating user application with Verilog simulator • The same as what has been described in Chapter 2, Section 6. 1 • Verilog-XL – vconfig generate a shell script generate the compiled binary

Handle and its declaration • handle: the basic data structure for all data access

Handle and its declaration • handle: the basic data structure for all data access – – Set up a handle to that object to access the properties of an object An equivalent of a C language pointing to the data structure of the object A way to use indirect addressing All references to that object such as getting its value, traversing a relationship etc. using its handle – Whenever an object is required to be passed to a function, its handle is passed as an argument • The data type of a handle – Defined in vpi_user. h as vpi. Hande – Irrespective of the nature of the object • Handle declaration – vpi. Handle net. Handle, mod_Handle, some_Handle, yet_another_Handle

Associating a handle to an object • Associate the handle with the object •

Associating a handle to an object • Associate the handle with the object • If we know the name of the object and the handle to its scope – Vpi_handle_by_name() – Ex) handle my_handle; my_handle = vpi_handle_by_name(“my_reg”, scope_handle); • If find out a handle to an object which is in some way related to a given object – Given object: the top level module, an argument to the system call – If a handle is available to an object, it is possible to get a handle to any other object related to it. – Ex) If a handle is available to a net or a register, it is possible to retrieve a handle pointing to its parent module instance.

Relationship between two objects • Relationship between two objects – Not related – One-to-one.

Relationship between two objects • Relationship between two objects – Not related – One-to-one. – One-to-many – Many-to-one • VPI handles the one-to-one and the one-to-many relationships • vpi_handle_multi(): the many-to-one relation

One-to-one relationship • Ex) a register and its parent module instance – There can

One-to-one relationship • Ex) a register and its parent module instance – There can be only one module containing that particular register. • • A handle to the second object can be obtained using the library function vpi_handle() and the handle to the first object vpi_handle() – Take the type of relationship and the handle to the first object as its arguments and returns the handle to the second object parent_module_of_a_reg(reg. Handle) vpi. Handle reg. Handle; { vpi. Handle module. Handle; module. Handle = vpi_handle(vpi. Module, reg. Handle); /* module. Handle can be used here for other purpose */ } handle. Dest = vpi_handle(vpi. Obj, handle. Start); the handle. Dest to the destination object the starting object handle. Start, the symbol for the destination object with a prefix vpi

One-to-many relationship • • EX) the relationship between a module and the registers(or nets),

One-to-many relationship • • EX) the relationship between a module and the registers(or nets), a port and its bits, a module and primitive instances within it vpi_iterate() and vpi_scan() – vpi_iterate() • take the type of one-to-many relationship to traverse and a handle to a reference object as its arguments. • Return an iterator handle. – vpi_scan() • Use an iterator handle as its argument in a loop to return a handle to the next object related to the reference object. • When all such objects are traversed, it returns a NULL. itr. Dest = vpi_iterate(vpi. Obj, handle. Start); /*The handle to the starting object handle. Start The iterator handle itr. Dest to the destination objects with obj The symbol for the destination object with a prefix vpi */ While(handle. Dest = vpi_scan(itr. Dest)) { /* process handle. Dest */ }

Example int regs_in_a_module(module. Handle) vpi. Handle module. Handle; { vpi. Handle reg. Itr, reg.

Example int regs_in_a_module(module. Handle) vpi. Handle module. Handle; { vpi. Handle reg. Itr, reg. Handle; reg. Itr = vpi_iterate(vpi. Reg, module. Handle); /* reg. Itr is the iterator handle to all registers inside this module */ if(!reg. Itr) { printf(“No reg inside modulen”); return – 1; } else { /* In each iteration the following while loop returns a handle to the next register instantiate within the module */ while(reg. Handle = vpi_scan(reg. Itr)) { /* Use reg. Handle here to process anything related to the register */ } } return 0; }

Class and method • Class: objects of similar nature – A class named primitive:

Class and method • Class: objects of similar nature – A class named primitive: object types gate, switch and UDPs • Method – Access a class from a given object or another class • How to get a handle to a member of a class starting from an object – The class regs • comprises of register and individual bit of a register array. • The relationship between a register bit and its parent array of registers is one-to-one. • To obtain a handle to the register array from the handle to the register bit – reg_array_handle = vpi_handle(vpi. Parent, reg_bit_handle); – The method vpi. Parent is used to get the handle reg_array_handle to the parent object within the class regs. – Unlike a type such as vpi. Module, a method is applicable to a general class of objects and does not depend on the type of the returned handle.

Tagged relationship • tag: predefined keyword used as the first argument for the vpi_handle()

Tagged relationship • tag: predefined keyword used as the first argument for the vpi_handle() or vpi_iterate() – Allow accessing properties of the destination objects(or class) of a specific type – Ex) an object of type memory: left and right ranges accessed by using the tags vpi. Left. Range and vpi. Right. Range

Getting Handles to basic objects • How a handle can be obtained to some

Getting Handles to basic objects • How a handle can be obtained to some of the most commonly referenced objects(basic objects) without taking the help of any other handle. • These objects provide a starting point for traversing a relationship.

Getting handles to the top level modules int get_top_mods() { vpi. Handle top_mod_iterator, top_mod_handle;

Getting handles to the top level modules int get_top_mods() { vpi. Handle top_mod_iterator, top_mod_handle; top_mod_iterator = vpi_iterate(vpi. Module, NULL); if(!top_mod)iterator) { printf(“No top-level module foundn”); return – 1; } else while(top_mod_handle = vpi_scan(top_mod_iterator)) printf(“Top module: %sn”, vpi_get_str(vpi. Name, top_mod_handle)); return 0 }

Getting handle to the parameters passed to the current system int list_param() { vpi.

Getting handle to the parameters passed to the current system int list_param() { vpi. Handle tf_param_iterator, tf_param_handle; vpi. Handle syscall_handle; int pin = 1; syscall_handle = vpi_handle(vpi. Sys. Tf. Call, NULL); if(!syscall_handle) { printf(“No handle to the system call…n”); return – 1; } else { tf_param_iterator = vpi_iterate(vpi. Argument, syscall_handle); if(!tf_param_iterator) { printf(“No arg. to the system calln”); return – 1; } else while(tf_param_handle = vpi_scan(tf_param_iterator)) printf(“Parameter %d: %sn”, pin++, vpi_get_str(vpi. Name, tf_param_handle)); return 0; }

Design Objects-Properties and Relationships • Properties – Three categories • Boolean and integer: vpi_get()

Design Objects-Properties and Relationships • Properties – Three categories • Boolean and integer: vpi_get() • String: vpi_string_get() • Complex – The data access interface can be defined in terms of the properties associated with that object or class and the relations it has with other objects/classes – The property name and the handle to the current object are passed as arguments. int curr. Net. Type; curr. Net. Type = vpi_get(vpi. Def. Net. Type, mod. Handle); modhandle: the handle to the current module vpi. Def. Net. Type: an integer property • Relationships – vpi_handle(), vpi_iterate(): one-to-one, one-to-many – The type of the destination object(or, a tag or, in the case of a class, the method)

Remainders: each type of object and class defined in Verilog HDL • Describe the

Remainders: each type of object and class defined in Verilog HDL • Describe the properties and relations associated with it using a tabular format – The type/method for each object/class is mentioned in parenthesis along with its name in the header – Ex) object Module: associated with a type vpi. Module The first argument of the vpi_handle() or vpi_iterate()

Summary of functions and their properties Purpose Accessing an object from its properties Accessing

Summary of functions and their properties Purpose Accessing an object from its properties Accessing properties of an object Getting simulation time Simulation related callbacks User-defined system call routines Traversing relationships File related activities Displaying messages Getting product invocation information Comparing objects Getting error information Freeing allocated memory VPI function vpi_handle_by_name() vpi_handle_by_index() vpi_get_str() vpi_get_value() vpi_put_value() vpi_get_delays() vpi_put_delays() vpi_get_time() vpi_register_cb() vpi_remove_cb() vpi_register_systf() vpi_get_systf_info() vpi_handle() vpi_iterate() vpi_scan() vpi_handle_multi() vpi_mcd_open() vpi_mcd_close() vpi_mcd_print() vpi_mcd_name() vpi_printf() vpi_get_vlog_info() vpi_compare_objects() vpi_chk_error() vpi_free_objects()

Sources SUNGHO KWAK

Sources SUNGHO KWAK