1.52k likes | 1.61k Views
Prinsiples of Verilog PLI. Chaper 1-2. 2000.1.3 VLSI&CAD Lab. 이세환. What is a PLI?. PLI - Programming Language Interface: The mechanism that makes the resources of programs written in one languages accessible to programs using another language.
E N D
Prinsiples of Verilog PLI Chaper 1-2 2000.1.3 VLSI&CAD Lab. 이세환
What is a PLI? • PLI - Programming Language Interface: • The mechanism that makes the resources of programs written in one languages accessible to programs using another language. • the specialized language : the special portion • Verilog PLI: • To extend the capabilities of a Verilog simulator, A mechanism to invoke a C(or C++) function from a Verilog code • System call ( built-in to the simulator ) • $display, $monitor, $finish etc. • User-defined task or function
The Capabilities of Verilog PLI • Not possible using Verilog syntax • C-language model • to optimize the performance of simulation • Access to programming language libraries • Delay calculation • can modify the Verilog simulation data structure - more accurate delays • Custom output displays • Co-simulation • Design debug utilities • Simulation analysis
Accessing information • Data structure in the Verilog simulator • for variables ( reg, wire etc ) • for simulating the events • Accessing information on variables • inside simulator, a register bit : { real field, control field } • Accessing information on events • event queue : the ordering of execution of these events
Quick Steps for writing a PLI • create a system call $print_reg module my_module; reg [3:0] r1; initial begin r1 = 4’ha; #100 $print_reg(r1); #100 r1 = 4’h3; #100 $print_reg(r1); #100 $finish; end endmodule
The essential data structure (1) • The file name containing a PLI routine : veriuser.c #include <veriuser.h> // < vcsuser.h> #include <vxl_veriuser.h> // in VCS int my_calltf(), my_checktf(); char *veriuser_version_str=“\n\ ============================\n\ VERILOG PLI FIRST_ATTEMPT \n\ ============================\n”; int (*endofcompile_routines[])() = { 0 }; bool err_intercept(level, facility, code) int level; char *facility; char *code; { return (true); } …………
The essential data structure (2) • The main interaction between the PLI and the Verilog simulator is done through a table veriusertfs s_tfcell veriusertfs[] = { /*** Template { usertask | userfunction, data, checktf(), sizetf(), calltf(), misctf(), “$tfname” } ***/ { usertask, 0, my_checktf, 0, my_calltf, 0, “$print_reg” }, {0} } In VCS environment pli.tab $print_reg check=my_checktf call=my_calltf
Program structure of a PLI • A PLI routine of a system call consists of several function • calltf • checktf • sizetf • misctf • invoked only by simulator itself. • not invoked each other
calltf() • similar to the function main()in a C program • the central program unit of a PLI routine • executed when simulation is running start initial begin r1 = 4’ha; #100 $print_reg(r1); ……… call the C library io_print() function return
calltf() int my_calltf() { io_print(“$print_reg : Value of the reg=%d”, tf_getp(1)); }
checktf() • In C, the number of parameter and their data types are checked during compilation • checktf routine is to verify that a system call is being used correctly • called by the simulator before simulation starts start Is there exactly 1 arguments? initial begin r1 = 4’ha; #100 $print_reg(r1); ……… no yes Is r1 is a register? no yes error ok
checktf() int my_checktf() { if ( tf_nump() !=1 ) { tf_error(“$print_reg:”); tf_error(“Usage: $print_reg(register_name); \n”); } if ( tf_typep(1) != tf_readwrite ) { tf_error(“$print_reg:”); tf_error(“The argument must be a register type\n”); } }
sizetf() • Only used with system call which return scalar or vector values • A mechanism to pass the return size to the Verilog simulator from the PLI routine • Only called once reg [n:0] result; result = $foo(<parameter>);
misctf() • Performs a number of miscellaneous jobs • Can be called multiple number of times during simulation • Can be asked to do different tasks on the condition for which it it called • condition, or miscellaneous events : reasons • ex.) • End of Verilog source compilation • Entering debug mode ( $stop ) • End of simulation ( $finish ) • Change of value on a user-defined system call • End of a simulation time step • Simulation has reached a specified simulation time step
misctf() always @(posedge clock) $read_test_vector(“vectors.pat”, in1); int PLIbook_read_test_vector_misctf(int data, int reason); { FILE *in_file; char *file_name; if (reason == REASON_ENDOFCOMPILE) { …… if (reason == REASON_FINISH) { …… }
Parameters to the Constituent function in A PLI routine • The fixed number of pre-defined parameters • data: • A constant parameter which the user asks the simulator to pass to the functions • reason, paramvc: • A parameter indicating various states of the simulation • read-only • optional
data int my_calltf(data, reason) int data, reason; { switch (data) { case ‘b’ : io_printf(“$print_regb: \n”); io_printf(“%d: register=%s”, tf_gettime(), to_binary(tf_getp(1))); break; case ‘h’ : io_printf(“$print_regh: \n”); io_printf(“%d: register=%h”, tf_gettime(), tf_getp(1)); break; default: tf_error(“Trouble!!! You shold not be here …”); } }
reason • reason tells the reason why system call causes the activation of a function • to indicate why the simulator called the misctf() • pre-defined set inveriuser.h • miscellaneous simulation event • compilation or loading of the simulation is complete • the simulation entered interactive debug mode • the simulation finished • simulation has reached a specific future simulation time step • ……
reason • reason_reactivate • Ex. ) $read_stimulus(“read_stimulus.pat”, input_vector); int PLIbook_readstimulus_calltf() { tf_setdelay(0); return(0); } int PLIbook_readstimulus_misctf( int data, int reason ) { … switch(reason) { case REASON_ENDOFCOMPILE: …… // Open stimulus file case REASON_REACTIVATE: // misctf called by tf_setdelay; …… // Read stimulus data tf_setdelay(delay); }
reason • reason_disable module reason_disable_example(clk, interrupt); input clk, interrupt; reg r1; always @(posedge clk) begin: main_job $process_reg(r1); end always @(posedge interrupt) begin disable main_job; // misctf of $process_reg be called interrupt_subroutine(); end …
reason • reason_paramvc • with tf_asynchon() • whenever there is a change in value in any of the arguments passed to the system call, • misctf() will be invoked with reason_paramvc • this effect can be disabled by tf_asynchoff()
paramvc • with the function tf_asynchon() • paramvc indicates the position of the changed parameter in the argument list • to model any asynchronous event ( interrupt )
Integrating the PLI routine into the simulator • The interface between the PLI routine and the simulator : A table • veriusertfs[] - Cadence Verilog-XL s_tfcell veriusertfs[] = { { usertask|userfunction, data, checktf(), sizetf(), calltf(), misctf(), “$tfname” }, { usertask, 0, my_checktf1, 0, my_calltf1, 0, “$rtn1” }, { usertask, ‘h’, my_checktf2, 0, my_calltf2, 0, “$fn_h” }, { usertask, ‘b’, my_checktf2, 0, my_calltf2, 0, “$fn_b” }, { 0 } }
Integrating the PLI routine into the simulator • pli.tab - VCS $rtn1 check=my_checktf1 call=my_calltf1 $rtn2 size=16 call=my_calltf2 misc=my_misctf2 $fn_b data=‘b’ check=my_checktf3 call=my_calltf3 $fn_h data=‘h’ check=my_checktf3 call=my_calltf3
Linking the PLI routine with the simulator • Verliog-XL • vconfig : generate a shell script ( cr_vlog ) • setting up the path for C compiler and environment • compilation command for veriuser.c • command for binding all the object codes generated with the basic simulator binary( vlog.o ) Verilog code veriusertfs[] Modified Simulator Verilog-XL binary(vlog.o) cr_vlog run PLI routine
Linking the PLI routine with the simulator • VCS $ vcs –M –o my_vcs –P my_pli_table.file input.v pli1.c pli2.c pli3.c
Verilog PLI SeminarCH. 3 Woong Jeong VLSI & CAD Lab., Yonsei University
Reference • Swapnajit Mittra*, “Principles of Verilog PLI”, Kluwer Academic Publishers, 1999 * Silicon Graphics Incorporated
What are utility routines? • Library functions defined in PLI1.0 • Perform a wide variety of operations on the parameters passed to the system call • is used to do a simulation synchronization or to implement conditional program breakpoint • tf routines
Using Utility Routines • Instead of passing it by its actual symbol, a parameter is passed to a utility routine by its parameter index number (PIN) • PIN : position in the parameter list of the corresponding system call with the leftmost parameter numbered as 1 $my_pli_routine (some_signal, another_signal, a_register); int val_param1; val_param1 = tf_getp(1);
Modifying the Value of a Design Object • We cannot modify the value of any arbitrary design object • Writable • It can be used on the LHS of a procedural assignment statement of Verilog • Register : reg, integer, real or time • Read-only • Nets and names of objects
Handling Data Types in Utility Routines • All utility routines assume a 32-bit implementation of the C int data type • time : 64-bit two 32-bit integers • real : treated as double in C
Classification of Utility Routines • Reading or modifying parameter value • To detect parameter value change • Getting simulation time and related things • Synchronizing simulation • Displaying message • Getting instance pointer, module and scope instance name • Saving information between calls • Getting parameter related information • Stopping or finishing simulation • Getting plus argument from the environment • Arithmetic and conversion • Save or restore • Scaling/Unscaling delay
Examle) int lower_32, upper_32; lower_32 = tf_getlongp (upper_32, 1) Reading and modifying parameter values • Accessing 2-state values : Not allow X or Z int tf_getp(pin) int pin; int tf_getlongp (higher_32, pin) int higher_32, pin; double tf_getrealp(pin) int pin; void tf_putp(pin, value) int pin , value; void tf_putlongp (pin, lower_32, higher_32) int pin, lower_32, higher_32; void tf_putrealp(pin,value) int pin; double value; get : reading a parameter put : modifying a parameter
(Continued) • Accessing 4-state values char *tf_strgetp(pin, format) int pin, format; char *tf_getcstringp (pin) int pin; tf_strgetp() : returns the value of the passed parameter as a string in one of the binary, octal, decimal, or hexadecimal formats tf_getcstringp() : returns a string, but all leading zeroes are dropped and each 8 bits starting from the LSB are converted to corresponding ASCII characters
(Continued) • Accessing 4-state values (cont’d) int tf_strdelputp(pin, bitlength, format, val_str, delay, delay_type) int pin, bitlength, format,delay_type; int delay; char *val_str int tf_strlongdelputp(pin, bitlength, format, val_str, delay_lo32, delay_hi32, delay_type) int pin, bitlength, format,delay_type; int delay_lo32, delay_hi32; char *val_str int tf_strrealdelputp(pin, bitlength, format, val_str, delay, delay_type) int pin, bitlength, format,delay_type; double delay; char *val_str data type: depends on delay val_str : the new value which is used to modify • delay_type : • 0 : Inertial delay • : Modified transport delay • : Pure transport delay
(Continued) • Reading generic object value
(Continued) • Getting nude information
Value Change Detection tf_asynchon () : Whenever any parameter or its driver changes value, misctf fuction is called with a reason of reason_paramvc or reason_paramdrc respectively void tf_asynchon () void tf_asynchoff () int tf_copypvc_flag (pin) int pin; int tf_movepvc_flag (pin) int pin; int tf_testpvc_flag (pin) int pin; int tf_getpchange (pin) int pin; pvc : Parameter Value Change - current pvc flag - saved pvc flag if pin = -1, all parameter pvc flags are copied/moved/tested, and the logical OR of all saved flags are returned tf_getpchange () : Searches for any other changed parameter with a parameter index number greater than this and returns its pin, otherwise it returns 0
Simulation Time int tf_gettime () int tf_getlongtime (time_hi32) int time_hi32; double tf_getrealtime () char tf_strgettime() () • Getting simulation time • Timescale and precision of a module • Conversion between scaled delay and internal simulation time will be discussed in CH.6 int tf_gettimeunit () int tf_gettimeprecision ()
Simulation Time (Cont’d) • Simulation synchronization • provide the user two different means to control the event queue in a simulation • user control within the same simulation time slot • flexibility to schedule an event in the future time slot • Callback mechanism • The misctf function of the same PLI routine is executed after all the scheduled events in that simulation time slot complete their execution
Simulation Time (Cont’d) tf_rosynchronize () : Guarantees that no event from the called misctf function can be scheduled at a future simulation time void tf_synchronize () void tf_rosynchronize () int tf_getnextlongtime (time_lo32, time_hi32) int *time_lo32, *time_hi32; int tf_setdelay (delay) int delay; int tf_setlongdelay (delay_lo32, delay_hi32) int delay_lo32, delay_hi32; int tf_setrealdelay (delay) double delay; void tf_clearalldelays (pin)
Displaying Messages void io_printf (format, arg1, ..... , arg12) void io_mcdprintf (format, arg1, ..... , arg12) void tf_warning (format, arg1, ..... , arg5) void tf_error (format, arg1, ..... , arg5) void tf_text (format, arg1, ..... , arg5) void tf_message (level, facility, code, message, arg1, ..... , arg5) Examle) tf_message (ERR_WARNING, “my_verilog”, “TFARGMISS”, “Null argument passed for the %dth argument”, arg_number) ;
Instance Pointer, module & scope instance name char *tf_getinstance () char *tf_mipname () char *tf_spname () Examle) io_printf (“Module and scope pathname are %s\n”, tf_mipname(), tf_spname() ) ;
Saving information between calls char *tf_getworkarea () void tf_setworkarea (workarea) char *workarea; Examle) int myChecktf() { FILE *myFile; : tf_setworkarea ((char *)myFile) ; /* store file pointer */ : } int myCalltf() { FILE *lastFile; : lastFile = (FILE *) tf_getworkarea () ; /* get file pointer opened in myChecktfr */ }
Miscellaneous Parameter Related Functions int tf_nump () int tf_typed (pin) int pin; int tf_sized (pin) int pin; Parameter type : tf_nullparam, tf_string, tf_readonly, tf_readwrite, tf_readonlyreal, tf_readwritereal
Stopping and Finishing the Simulation void tf_dostop () void tf_dofinish () $stop, $finish
Getting Plus arguments from the environment char *mc_scan_plusargs (start_arg) char *start_arg; Examle) myVerilog test.v +useCycle mc_scan_plusargs(“use”); will return “Cycle”
Arithmetic and Conversion Functions int tf_compare_long (op1_lo32, op1_hi32, op2_lo32, op2_hi32) int op1_lo32, op1_hi32, op2_lo32, op2_hi32; int tf_add_long (final_lo32, final_hi32, op1_lo32, op_hi32) int *final_lo32, *final_hi32; int op1_lo32, op1_hi32; int tf_subtract_long (final_lo32, final_hi32, op1_lo32, op_hi32) int *final_lo32, *final_hi32; int op1_lo32, op1_hi32; int tf_multiply_long (final_lo32, final_hi32, op1_lo32, op_hi32) int *final_lo32, *final_hi32; int op1_lo32, op1_hi32; int tf_divide_long (final_lo32, final_hi32, op1_lo32, op_hi32) int *final_lo32, *final_hi32; int op1_lo32, op1_hi32;
Conversion between Data Types void tf_long_to_real (val_lo32, val_hi32, val_real) int val_lo32, val_hi32; double *val_real; char *tf_longtime_tostr (val_lo32, val_hi32) int val_lo32, val_hi32; void tf_real_tf_long (val_real, val_lo32, val_hi32) double val_real; int *val_lo32, *val_hi32;