programming language interface
play

Programming Language Interface Sayed Amirhossein Mirhosseini Uses - PowerPoint PPT Presentation

Programming Language Interface Sayed Amirhossein Mirhosseini Uses of PLI PLI can be used to define additional system tasks and functions e.g. monitoring tasks , stimulus tasks , PLI can be used to extract design information such


  1. Programming Language Interface Sayed Amirhossein Mirhosseini

  2. Uses of PLI  PLI can be used to define additional system tasks and functions  e.g. monitoring tasks , stimulus tasks , …  PLI can be used to extract design information such as hierarchy, connectivity, fanout, and number of logic elements of a certain type.  PLI can be used to write special-purpose or customized output display routines.  General Verilog-based application software can be written with PLI routines.  This software will work with all Verilog simulators because of the uniform access provided by the PLI interface.

  3. A simple PLI Task #include "veriuser.h" /*include the file provided in release dir */ int hello_verilog() { io_printf("Hello Verilog World\n"); }  The io_printf is a PLI library routine that works exactly like printf.

  4. Linking PLI Tasks  Whenever the task $hello_verilog is invoked in the Verilog code, the C routine hello_verilog must be executed.  The simulator needs to be aware that a new system task called $hello_verilog exists and is linked to the C routine hello_verilog  This process is called linking the PLI routines into the Verilog simulator.  Different simulators provide different mechanisms to link PLI routines.

  5. Invoking PLI Tasks  Once the user-defined task has been linked into the Verilog simulator, it can be invoked like any Verilog system task by the keyword $hello_verilog: module hello_top; initial $hello_verilog; //Invoke the user-defined task hello_verilog endmodule

  6. General Flow

  7. Access Routines  Access routines can read information about objects in the design.  Objects can be one of the following types:  Module instances, module ports, module pin-to-pin paths, and intermodule paths  Top-level modules  Primitive instances, primitive terminals  Nets, registers, parameters, specparams  Integer, time, and real variables  Timing checks  Named events

  8. Mechanics of access routines  Access routines always start with the prefix acc_.  A user-defined C routine that uses access routines must first initialize the environment by calling the routine acc_initialize().  When exiting, the user-defined C routine must call acc_close().  #include "acc_user.h"  Access routines use the concept of a handle to access an object.  Handles are predefined data types that point to specific objects in the design.  handle top_handle;

  9. Types of access routines  Handle routines:  They return handles to objects in the design.  acc_handle_.  Next routines :  They return the handle to the next object in the set of a given object type in a design.  acc_next_  Value Change Link (VCL) routines :  They allow the user system task to add and delete objects from the list of objects that are monitored .  acc_vcl_  Fetch routines :  They can extract a variety of information about objects (e.g. hierarchical path name, relative name)  acc_fetch_.

  10. Example 1: Get Module Port List #include "acc_user.h" int get_ports() { handle mod, port; int input_ctr = 0; int output_ctr = 0; int inout_ctr = 0; acc_initialize(); mod = acc_handle_tfarg(1); /* get a handle to the module instance first argument in the system task argument list */ port = acc_handle_port(mod, 0); /* get the first port of the module */ while( port != null ) /* loop for all ports */ { if (acc_fetch_direction(port) == accInput) /* Input port */ { io_printf("Input Port %s \n", acc_fetch_fullname(port)); /* full hierarchical name */ input_ctr++; }

  11. Example 1 (cont.) else if (acc_fetch_direction(port) == accOutput) /* Output port */ { io_printf("Output Port %s \n", acc_fetch_fullname(port)); output_ctr++; } else if (acc_fetch_direction(port) == accInout) /* Inout port */ { io_printf("Inout Port %s \n", acc_fetch_fullname(port)); inout_ctr++; } port = acc_next_port(mod, port); /* go to the next port */ } io_printf("Input Ports = %d Output Ports = %d, Inout ports = %d\n\n", input_ctr, output_ctr, inout_ctr); acc_close(); }

  12. Example 1 (cont.) module top; wire OUT; reg I0, I1, S; mux2_to_1 my_mux(OUT, I0, I1, S); /*Instantiatethe 2-to-1 mux*/ initial begin $get_ports("top.my_mux"); /*invoke task $get_ports to get port list*/ end endmodule  Output : Output Port top.my_mux.out Input Port top.my_mux.i0 Input Port top.my_mux.i1 Input Port top.my_mux.s Input Ports = 3 Output Ports = 1, Inout ports = 0

  13. Example 2: Monitor Nets #include "acc_user.h" int my_monitor() { handle net; char *netname ; /*pointer to store names of nets*/ char *malloc(); acc_initialize(); /*initialize environment*/ net = acc_handle_tfarg(1); /*get a handle to the net to be monitored*/ netname = malloc(strlen(acc_fetch_fullname(net))); strcpy(netname, acc_fetch_fullname(net)); /* Call the VCL routine to add a signal to the monitoring list*/ /* Pass four arguments to acc_vcl_add task*/ /* 1st : handle to the monitored object (net) 2nd : Consumer C routine to call when the object value changes (display_net) 3rd : String to be passed to consumer C routine (netname) 4th : Predefined VCL flags: vcl_verilog_logic or vcl_verilog_strength */ acc_vcl_add(net, display_net, netname, vcl_verilog_logic); acc_close(); }

  14. Example 2 (cont.)  Whenever the value of the net changes, the acc_vcl_add calls the consumer routine display_net and passes a pointer to a data structure of the type p_vc_record typedef struct t_vc_record{ int vc_reason; /*reason for value change*/ int vc_hightime; /*Higher 32 bits of 64-bit simulation time*/ int vc_lowtime; /*Lower 32 bits of 64-bit simulation time*/ char *user_data; /*String passed as the argument of acc_vcl_add*/ union { /*New value of the monitored signal*/ unsigned char logic_value; double real_value; handle vector_handle; s_strengths strengths_s; } out_value; } *p_vc_record;

  15. Example 2 (cont.) display_net(p_vc_record vc_record)  { io_printf("%d New value of net %s is %c \n", vc_record->vc_lowtime, vc_record->user_data, convert_to_char(vc_record->out_value.logic_value)); } char convert_to_char(char logic_val)  { char temp; switch(logic_val) { case vcl0: temp='0'; break; case vcl1: temp='1'; break; case vclX: temp='X'; break; case vclZ: temp='Z'; break; } return(temp); }

  16. Example 2 (cont.) module top; wire OUT; reg I0, I1, S; mux2_to_1 my_mux(OUT, I0, I1, S); //Instantiate the module mux2_to_1 initial //Add nets to the monitoring list begin $my_monitor("top.my_mux.sbar"); $my_monitor("top.my_mux.y1"); end initial //Apply Stimulus begin I0=1'b0; I1=1'b1; S = 1'b0; #5 I0=1'b1; I1=1'b1; S = 1'b1; #5 I0=1'b0; I1=1'b1; S = 1'bx; #5 I0=1'b1; I1=1'b1; S = 1'b1; end endmodule

  17. Example 2 (cont.)  Output : 0 New value of net top.my_mux.y1 is 0 0 New value of net top.my_mux.sbar is 1 5 New value of net top.my_mux.y1 is 1 5 New value of net top.my_mux.sbar is 0 5 New value of net top.my_mux.y1 is 0 10 New value of net top.my_mux.sbar is X 15 New value of net top.my_mux.y1 is X 15 New value of net top.my_mux.sbar is 0 15 New value of net top.my_mux.y1 is 0

  18. Utility Routines  Utility routines are miscellaneous PLI routines that pass data in both directions across the Verilog/user C routine boundary.  Do long arithmetic  Display messages  Halt, terminate, save, and restore simulation  …  Utility routines are also popularly called "tf" routines.  Always start with the prefix tf_.  #include "veriuser.h"

  19. Example 3: my_stop_finish  Verilog provides the system tasks $stop and $finish that suspend and terminate the simulation.  my_stop_finish does both based on its arguments : 1st Argument 2nd Argument Action 0 none Stop simulation. Display simulation time and message. 1 none Finish simulation. Display simulation time and message. 0 any value Stop simulation. Display simulation time, module instance from which stop was called, and message. 1 any value Finish simulation. Display simulation time, module instance from which stop was called, and message.

  20. Example 3 (cont.) #include "veriuser.h" int my_stop_finish() { if(tf_nump() == 1) /* if 1 argument is passed , display only simulation time */ { if(tf_getp(1) == 0) /* if the argument is 0, then stop the simulation*/ { io_printf("Mymessage: Simulation stopped at time %d\n", tf_gettime()); tf_dostop(); /*stop the simulation*/ } else if(tf_getp(1) == 1) /* if the argument is 0 , terminate the simulation*/ { io_printf("Mymessage: Simulation finished at time %d\ n“, tf_gettime()); tf_dofinish(); /*terminate the simulation*/ } else /* Pass warning message */ tf_warning("Bad arguments to \$my_stop_finish at time%d\ n“, tf_gettime()); }

Recommend


More recommend