#ifndef IVL_vpi_priv_H #define IVL_vpi_priv_H /* * Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com) * Copyright (c) 2016 CERN Michele Castellana (michele.castellana@cern.ch) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU * General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ # include "sv_vpi_user.h" # include "vvp_net.h" # include "config.h" # include # include # include # include /* * Added to use some "vvp_fun_modpath_src" * and "vvp_fun_modpath" classes definitions */ #include "delay.h" class class_type; class vvp_darray; class vvp_fun_arrayport; typedef struct __vpiArray* vvp_array_t; /* * This header file contains the internal definitions that the vvp * program uses to implement the public interface in the vpi_user.h * header file elsewhere. */ /* * Routines/definitions used to build the file/line number tracing object. */ #define _vpiFileLine 0x1000003 #define _vpiDescription 0x1000004 extern bool show_file_line; extern bool code_is_instrumented; extern vpiHandle vpip_build_file_line(char*description, long file_idx, long lineno); /* * Private VPI properties that are only used in the cleanup code. */ #if defined(CHECK_WITH_VALGRIND) && !defined(BR916_STOPGAP_FIX) #define _vpiFromThr 0x1000001 # define _vpiNoThr 0 # define _vpiString 1 # define _vpiVThr 2 # define _vpiWord 3 # define _vpi_at_PV 4 # define _vpi_at_A 5 # define _vpi_at_APV 6 #endif /* * The vpi_mode_flag contains the major mode for VPI use. This is used * to generate error messages when vpi functions are called * incorrectly. */ enum vpi_mode_t { VPI_MODE_NONE =0, /* The compiler is calling a register function. */ VPI_MODE_REGISTER, /* The compiler is calling a compiletf function. */ VPI_MODE_COMPILETF, /* The compiler is calling a calltf function. */ VPI_MODE_CALLTF, /* We are in the midst of a RWSync callback. */ VPI_MODE_RWSYNC, /* We are in a ROSync callback. */ VPI_MODE_ROSYNC }; extern vpi_mode_t vpi_mode_flag; /* * This structure is the very base of a vpiHandle. Every handle * structure is derived from this class so that the library can * internally pass the derived types as pointers to one of these. */ class __vpiHandle { public: inline __vpiHandle() { } // The destructor is virtual so that dynamic types will work. virtual ~__vpiHandle(); virtual int get_type_code(void) const =0; virtual int vpi_get(int code); virtual char* vpi_get_str(int code); virtual void vpi_get_value(p_vpi_value val); virtual vpiHandle vpi_put_value(p_vpi_value val, int flags); virtual vpiHandle vpi_handle(int code); virtual vpiHandle vpi_iterate(int code); virtual vpiHandle vpi_index(int idx); virtual void vpi_get_delays(p_vpi_delay del); virtual void vpi_put_delays(p_vpi_delay del); // Objects may have destroyer functions of their own. If so, // then this virtual method will return a POINTER to that // function. The pointer is used to "delete" the object, which // is why the function itself cannot be a method. typedef int (*free_object_fun_t)(vpiHandle); virtual free_object_fun_t free_object_fun(void); }; /* * The vpiHandle for an iterator has this structure. The definition of * the methods lives in vpi_iter.c * * The args and nargs members point to the array of vpiHandle objects * that are to be iterated over. The next member is the index of the * next item to be returned by a vpi_scan. * * The free_args_flag member is true if when this iterator object is * released it must also free the args array. */ struct __vpiIterator : public __vpiHandle { __vpiIterator(); int get_type_code(void) const; free_object_fun_t free_object_fun(void); vpiHandle *args; unsigned nargs; unsigned next; bool free_args_flag; }; extern vpiHandle vpip_make_iterator(unsigned nargs, vpiHandle*args, bool free_args_flag); class __vpiDecConst : public __vpiHandle { public: explicit __vpiDecConst(int val =0); __vpiDecConst(const __vpiDecConst&that); int get_type_code(void) const; int vpi_get(int code); void vpi_get_value(p_vpi_value val); public: inline int get_value() const { return value; } inline void set_value(int val) { value = val; } private: int value; }; /* * This represents callback handles. There are some private types that * are defined and used in vpi_callback.cc. The __vpiCallback are * always used in association with vvp_vpi_callback objects. */ struct __vpiCallback : public __vpiHandle { __vpiCallback(); ~__vpiCallback(); int get_type_code(void) const; // Used for listing callbacks. struct __vpiCallback*next; // user supplied callback data struct t_cb_data cb_data; }; class value_callback : public __vpiCallback { public: explicit value_callback(p_cb_data data); // Return true if the callback really is ready to be called virtual bool test_value_callback_ready(void); public: // user supplied callback data struct t_vpi_time cb_time; struct t_vpi_value cb_value; }; extern void callback_execute(struct __vpiCallback*cur); struct __vpiSystemTime : public __vpiHandle { __vpiSystemTime(); int get_type_code(void) const; int vpi_get(int code); char*vpi_get_str(int code); void vpi_get_value(p_vpi_value val); vpiHandle vpi_handle(int code); __vpiScope*scope; }; struct __vpiScopedTime : public __vpiSystemTime { __vpiScopedTime(); char*vpi_get_str(int code); void vpi_get_value(p_vpi_value val); }; struct __vpiScopedSTime : public __vpiSystemTime { __vpiScopedSTime(); int vpi_get(int code); char*vpi_get_str(int code); void vpi_get_value(p_vpi_value val); }; struct __vpiScopedRealtime : public __vpiSystemTime { __vpiScopedRealtime(); int vpi_get(int code); char*vpi_get_str(int code); void vpi_get_value(p_vpi_value val); }; /* * Scopes are created by .scope statements in the source. These * objects hold the items and properties that are knowingly bound to a * scope. */ class __vpiScope : public __vpiHandle { public: int vpi_get(int code); char* vpi_get_str(int code); vpiHandle vpi_handle(int code); vpiHandle vpi_iterate(int code); public: // Return the BASE name of the scope. This does not include // any of the parent hierarchy. inline const char*scope_name() const { return name_; } inline const char*scope_def_name() const { return tname_; } // TRUE if this is an automatic func/task/block inline bool is_automatic() const { return is_automatic_; } public: __vpiScope *scope; unsigned file_idx; unsigned lineno; unsigned def_file_idx; unsigned def_lineno; bool is_cell; /* The scope has a system time of its own. */ __vpiScopedTime scoped_time; struct __vpiScopedSTime scoped_stime; struct __vpiScopedRealtime scoped_realtime; /* Keep an array of internal scope items. */ std::vector intern; /* Set of types */ std::map classes; /* Keep an array of items to be automatically allocated */ struct automatic_hooks_s**item; unsigned nitem; /* Keep a list of live contexts. */ vvp_context_t live_contexts; /* Keep a list of freed contexts. */ vvp_context_t free_contexts; /* Keep a list of threads in the scope. */ std::set threads; signed int time_units :8; signed int time_precision :8; protected: __vpiScope(const char*nam, const char*tnam, bool is_auto_flag =false); private: /* The scope has a name. */ const char*name_; const char*tname_; /* the scope may be "automatic" */ bool is_automatic_; }; class vpiScopeFunction : public __vpiScope { public: inline vpiScopeFunction(const char*nam, const char*tnam, bool auto_flag, int func_type, unsigned func_wid) : __vpiScope(nam,tnam, auto_flag), func_type_(func_type), func_wid_(func_wid) { } int get_type_code(void) const { return vpiFunction; } int vpi_get(int code) { switch (code) { case vpiFuncType: return func_type_; default: return __vpiScope::vpi_get(code); } } public: inline unsigned get_func_width(void) const { return func_wid_; } private: int func_type_; unsigned func_wid_; }; extern __vpiScope* vpip_peek_current_scope(void); extern void vpip_attach_to_scope(__vpiScope*scope, vpiHandle obj); extern void vpip_attach_to_current_scope(vpiHandle obj); extern __vpiScope* vpip_peek_context_scope(void); extern unsigned vpip_add_item_to_context(automatic_hooks_s*item, __vpiScope*scope); extern vpiHandle vpip_make_root_iterator(void); extern void vpip_make_root_iterator(class __vpiHandle**&table, unsigned&ntable); /* * Signals include the variable types (reg, integer, time) and are * distinguished by the vpiType code. They also have a parent scope, * a declared name and declaration indices. */ struct __vpiSignal : public __vpiHandle { int vpi_get(int code); char* vpi_get_str(int code); void vpi_get_value(p_vpi_value val); vpiHandle vpi_put_value(p_vpi_value val, int flags); vpiHandle vpi_handle(int code); vpiHandle vpi_iterate(int code); vpiHandle vpi_index(int idx); public: unsigned width() const; public: union { // The scope or parent array that contains me. vpiHandle parent; __vpiScope* scope; } within; union { // The name of this reg/net, or the index for array words. const char*name; vpiHandle index; } id; /* The indices that define the width and access offset. */ __vpiDecConst msb, lsb; /* Flags */ unsigned signed_flag : 1; unsigned is_netarray : 1; // This is word of a net array /* The represented value is here. */ vvp_net_t*node; public: static void*operator new(std::size_t size); static void operator delete(void*); // not implemented protected: inline __vpiSignal() { } private: // Not implemented static void*operator new[] (std::size_t size); static void operator delete[](void*); }; extern unsigned vpip_size(__vpiSignal *sig); extern __vpiScope* vpip_scope(__vpiSignal*sig); extern vpiHandle vpip_make_int2(const char*name, int msb, int lsb, bool signed_flag, vvp_net_t*vec); extern vpiHandle vpip_make_int4(const char*name, int msb, int lsb, vvp_net_t*vec); extern vpiHandle vpip_make_var4(const char*name, int msb, int lsb, bool signed_flag, vvp_net_t*net); extern vpiHandle vpip_make_net4(__vpiScope*scope, const char*name, int msb, int lsb, bool signed_flag, vvp_net_t*node); /* * This is used by system calls to represent a bit/part select of * a simple variable or constant array word. */ struct __vpiPV : public __vpiHandle { __vpiPV(); int get_type_code(void) const; int vpi_get(int code); char* vpi_get_str(int code); void vpi_get_value(p_vpi_value val); vpiHandle vpi_put_value(p_vpi_value val, int flags); vpiHandle vpi_handle(int code); vpiHandle parent; vvp_net_t*net; vpiHandle sbase; int tbase; unsigned width; }; extern vpiHandle vpip_make_PV(char*name, int base, int width); extern vpiHandle vpip_make_PV(char*name, char*symbol, int width); extern vpiHandle vpip_make_PV(char*name, vpiHandle handle, int width); struct __vpiModPathTerm : public __vpiHandle { __vpiModPathTerm(); int get_type_code(void) const; int vpi_get(int code); vpiHandle vpi_handle(int code); vpiHandle expr; /* The value returned by vpi_get(vpiEdge, ...); */ int edge; }; struct __vpiModPathSrc : public __vpiHandle { __vpiModPathSrc(); int get_type_code(void) const; int vpi_get(int code); void vpi_get_value(p_vpi_value val); vpiHandle vpi_put_value(p_vpi_value val, int flags); vpiHandle vpi_handle(int code); vpiHandle vpi_iterate(int code); vpiHandle vpi_index(int idx); void vpi_get_delays(p_vpi_delay del); void vpi_put_delays(p_vpi_delay del); free_object_fun_t free_object_fun(void); struct __vpiModPath *dest; int type; /* This is the input expression for this modpath. */ struct __vpiModPathTerm path_term_in; /* This is the input net for the modpath. signals on this net are used to determine the modpath. They are *not* propagated anywhere. */ vvp_net_t *net; } ; /* * * The vpiModPath vpiHandle will define * a vpiModPath of record .modpath as defined * in the IEEE 1364 * */ struct __vpiModPath { __vpiScope *scope ; class vvp_fun_modpath*modpath; struct __vpiModPathTerm path_term_out; vvp_net_t *input_net ; }; /* * The Function is used to create the vpiHandle * for vpiModPath && vpiModPathIn objects */ extern struct __vpiModPathSrc* vpip_make_modpath_src(struct __vpiModPath*path, vvp_net_t *net) ; extern struct __vpiModPath* vpip_make_modpath(vvp_net_t *net) ; /* * These methods support the vpi creation of events. The name string * passed in will be saved, so the caller must allocate it (or not * free it) after it is handed to this function. */ class __vpiNamedEvent : public __vpiHandle { public: __vpiNamedEvent(__vpiScope*scope, const char*name); ~__vpiNamedEvent(); int get_type_code(void) const; __vpiScope*get_scope(void) const { return scope_; } int vpi_get(int code); char* vpi_get_str(int code); vpiHandle vpi_put_value(p_vpi_value val, int flags); vpiHandle vpi_handle(int code); inline void add_vpi_callback(__vpiCallback*cb) { cb->next = callbacks_; callbacks_ = cb; } void run_vpi_callbacks(void); /* The functor, used for %set operations. */ vvp_net_t*funct; private: /* base name of the event object */ const char*name_; /* Parent scope of this object. */ __vpiScope*scope_; /* List of callbacks interested in this event. */ __vpiCallback*callbacks_; }; extern vpiHandle vpip_make_named_event(const char*name, vvp_net_t*f); /* * Memory is an array of bits that is accessible in N-bit chunks, with * N being the width of a word. The memory word handle just points * back to the memory and uses an index to identify its position in * the memory. */ extern bool is_net_array(vpiHandle obj); /* * These are the various variable types. */ struct __vpiRealVar : public __vpiHandle { __vpiRealVar(); int get_type_code(void) const; int vpi_get(int code); char* vpi_get_str(int code); void vpi_get_value(p_vpi_value val); vpiHandle vpi_put_value(p_vpi_value val, int flags); vpiHandle vpi_handle(int code); vpiHandle vpi_iterate(int code); union { // The scope or parent array that contains me. vpiHandle parent; __vpiScope* scope; } within; /* The name of this variable, or the index for array words. */ union { const char*name; vpiHandle index; } id; unsigned is_netarray : 1; // This is word of a net array unsigned is_wire : 1; // This is a wire, not a variable vvp_net_t*net; }; extern __vpiScope* vpip_scope(__vpiRealVar*sig); extern vpiHandle vpip_make_real_var(const char*name, vvp_net_t*net); extern vpiHandle vpip_make_real_net(__vpiScope*scope, const char*name, vvp_net_t*net); class __vpiBaseVar : public __vpiHandle { public: __vpiBaseVar(__vpiScope*scope, const char*name, vvp_net_t*net); #ifdef CHECK_WITH_VALGRIND ~__vpiBaseVar(); #endif inline vvp_net_t* get_net() const { return net_; } protected: __vpiScope* scope_; const char*name_; private: vvp_net_t*net_; }; class __vpiStringVar : public __vpiBaseVar { public: __vpiStringVar(__vpiScope*scope, const char*name, vvp_net_t*net); int get_type_code(void) const; int vpi_get(int code); void vpi_get_value(p_vpi_value val); vpiHandle vpi_put_value(p_vpi_value val, int flags); }; extern vpiHandle vpip_make_string_var(const char*name, vvp_net_t*net); struct __vpiArrayBase { __vpiArrayBase() : vals_words(NULL) {} virtual ~__vpiArrayBase() {} virtual unsigned get_size(void) const = 0; virtual vpiHandle get_left_range() = 0; virtual vpiHandle get_right_range() = 0; virtual __vpiScope*get_scope() const = 0; virtual int get_word_size() const = 0; virtual char*get_word_str(struct __vpiArrayWord*word, int code) = 0; virtual void get_word_value(struct __vpiArrayWord*word, p_vpi_value vp) = 0; virtual void put_word_value(struct __vpiArrayWord*word, p_vpi_value vp, int flags) = 0; virtual vpiHandle get_iter_index(struct __vpiArrayIterator*iter, int idx) = 0; // vpi_iterate is already defined by vpiHandle, so to avoid problems with // classes inheriting from vpiHandle and vpiArrayBase just share the common // code in the following function vpiHandle vpi_array_base_iterate(int code); virtual void make_vals_words(); struct __vpiArrayWord*vals_words; }; /* * The vpiArray object holds an array of vpi objects that themselves * represent the words of the array. The vpi_array_t is a pointer to * a struct __vpiArray. * * The details of the implementation depends on what this is an array * of. The easiest case is if this is an array of nets. * * - Array of Nets: * If this represents an array of nets, then the nets member points to * an array of vpiHandle objects. Each vpiHandle is a word. This is * done because typically each word of a net array is simultaneously * driven and accessed by other means, so there is no advantage to * compacting the array in any other way. * * - Array of vector4 words. * In this case, the nets pointer is nil, and the vals4 member points * to a vvl_vector4array_t object that is a compact representation of * an array of vvp_vector4_t vectors. * * - Array of real variables * The vals member points to a dynamic array objects that has an * array of double variables. This is very much like the way the * vector4 array works. */ struct __vpiArray : public __vpiArrayBase, public __vpiHandle { int get_type_code(void) const { return vpiMemory; } unsigned get_size() const { return array_count; } vpiHandle get_left_range() { assert(nets == 0); return &msb; } vpiHandle get_right_range() { assert(nets == 0); return &lsb; } __vpiScope*get_scope() const { return scope; } int get_word_size() const; char*get_word_str(struct __vpiArrayWord*word, int code); void get_word_value(struct __vpiArrayWord*word, p_vpi_value vp); void put_word_value(struct __vpiArrayWord*word, p_vpi_value vp, int flags); vpiHandle get_iter_index(struct __vpiArrayIterator*iter, int idx); int vpi_get(int code); char* vpi_get_str(int code); vpiHandle vpi_handle(int code); inline vpiHandle vpi_iterate(int code) { return vpi_array_base_iterate(code); } vpiHandle vpi_index(int idx); void set_word(unsigned idx, unsigned off, const vvp_vector4_t&val); void set_word(unsigned idx, double val); void set_word(unsigned idx, const std::string&val); void set_word(unsigned idx, const vvp_object_t&val); vvp_vector4_t get_word(unsigned address); double get_word_r(unsigned address); void get_word_obj(unsigned address, vvp_object_t&val); std::string get_word_str(unsigned address); void alias_word(unsigned long addr, vpiHandle word, int msb, int lsb); void attach_word(unsigned addr, vpiHandle word); void word_change(unsigned long addr); const char*name; /* Permanently allocated string */ __vpiDecConst first_addr; __vpiDecConst last_addr; __vpiDecConst msb; __vpiDecConst lsb; unsigned vals_width; // If this is a net array, nets lists the handles. vpiHandle*nets; // If this is a var array, then these are used instead of nets. vvp_vector4array_t*vals4; vvp_darray *vals; vvp_fun_arrayport*ports_; struct __vpiCallback *vpi_callbacks; bool signed_flag; bool swap_addr; private: unsigned array_count; __vpiScope*scope; friend vpiHandle vpip_make_array(char*label, const char*name, int first_addr, int last_addr, bool signed_flag); friend void compile_array_alias(char*label, char*name, char*src); }; class __vpiDarrayVar : public __vpiBaseVar, public __vpiArrayBase { public: __vpiDarrayVar(__vpiScope*scope, const char*name, vvp_net_t*net); int get_type_code() const { return vpiArrayVar; } unsigned get_size() const; vpiHandle get_left_range(); vpiHandle get_right_range(); __vpiScope*get_scope() const { return scope_; } int get_word_size() const; char*get_word_str(struct __vpiArrayWord*word, int code); void get_word_value(struct __vpiArrayWord*word, p_vpi_value vp); void put_word_value(struct __vpiArrayWord*word, p_vpi_value vp, int flags); vpiHandle get_iter_index(struct __vpiArrayIterator*iter, int idx); inline vpiHandle vpi_iterate(int code) { return vpi_array_base_iterate(code); } int vpi_get(int code); char* vpi_get_str(int code); vpiHandle vpi_handle(int code); vpiHandle vpi_index(int index); void vpi_get_value(p_vpi_value val); protected: vvp_darray*get_vvp_darray() const; __vpiDecConst left_range_, right_range_; }; extern vpiHandle vpip_make_darray_var(const char*name, vvp_net_t*net); class __vpiQueueVar : public __vpiBaseVar { public: __vpiQueueVar(__vpiScope*scope, const char*name, vvp_net_t*net); int get_type_code(void) const; int vpi_get(int code); void vpi_get_value(p_vpi_value val); }; extern vpiHandle vpip_make_queue_var(const char*name, vvp_net_t*net); class __vpiCobjectVar : public __vpiBaseVar { public: __vpiCobjectVar(__vpiScope*scope, const char*name, vvp_net_t*net); int get_type_code(void) const; int vpi_get(int code); void vpi_get_value(p_vpi_value val); }; extern vpiHandle vpip_make_cobject_var(const char*name, vvp_net_t*net); /* * When a loaded VPI module announces a system task/function, one * __vpiUserSystf object is created to hold the definition of that * task/function. The distinction between task and function is stored * in the vpi_systf_data structure data that was supplied by the * external module. * * When the compiler encounters a %vpi_call statement, it creates a * __vpiSysTaskCall to represent that particular call. The call refers * to the definition handle so that when the %vpi_call instruction is * encountered at run-time, the definition can be located and used. * * The vpiSysTaskCall handles both functions and tasks, as the two are * extremely similar. The different VPI type is reflected in a * different vpi_type pointer in the base structure. The only * additional part is the vbit/vwid that is used by the put of the * system function call to place the values in the vthread bit space. */ struct __vpiUserSystf : public __vpiHandle { __vpiUserSystf(); int get_type_code(void) const; s_vpi_systf_data info; bool is_user_defn; }; extern vpiHandle vpip_make_systf_iterator(void); extern struct __vpiUserSystf* vpip_find_systf(const char*name); struct __vpiSysTaskCall : public __vpiHandle { __vpiScope* scope; struct __vpiUserSystf*defn; unsigned nargs; vpiHandle*args; /* Stack consumed by this call */ unsigned vec4_stack; unsigned real_stack; unsigned string_stack; /* Support for vpi_get_userdata. */ void*userdata; // This is set if this is a structural call to a function class vvp_net_t*fnet; unsigned file_idx; unsigned lineno; bool put_value; protected: inline __vpiSysTaskCall() { vec4_stack = 0; real_stack = 0; string_stack = 0; } }; extern struct __vpiSysTaskCall*vpip_cur_task; /* * The persistent flag to vpip_make_string_const causes the created * handle to be persistent. This is necessary for cases where the * string handle may be reused, which is the normal case. * * When constructing with a string, the class takes possession of the * text value string, and will delete it in the constructor. */ vpiHandle vpip_make_string_const(char*text, bool persistent =true); vpiHandle vpip_make_string_param(char*name, char*value, bool local_flag, long file_idx, long lineno); struct __vpiBinaryConst : public __vpiHandle { __vpiBinaryConst(); int get_type_code(void) const; int vpi_get(int code); void vpi_get_value(p_vpi_value val); vvp_vector4_t bits; /* TRUE if this constant is signed. */ int signed_flag :1; /* TRUE if this constant has an explicit size (i.e. 19'h0 vs. 'h0) */ int sized_flag :1; }; vpiHandle vpip_make_binary_const(unsigned wid, const char*bits); vpiHandle vpip_make_binary_param(char*name, const vvp_vector4_t&bits, bool signed_flag, bool local_flag, long file_idx, long lineno); class __vpiRealConst : public __vpiHandle { public: explicit __vpiRealConst(double); int get_type_code(void) const; int vpi_get(int code); void vpi_get_value(p_vpi_value val); double value; }; vpiHandle vpip_make_real_const(double value); vpiHandle vpip_make_real_param(char*name, double value, bool local_flag, long file_idx, long lineno); /* * This one looks like a constant, but really is a vector in the current * thread. */ vpiHandle vpip_make_vthr_word(unsigned base, const char*type); vpiHandle vpip_make_vthr_str_stack(unsigned depth); vpiHandle vpip_make_vthr_vec4_stack(unsigned depth, bool signed_flag, unsigned wid); vpiHandle vpip_make_vthr_A(char*label, unsigned index); vpiHandle vpip_make_vthr_A(char*label, char*symbol); vpiHandle vpip_make_vthr_A(char*label, vpiHandle handle); vpiHandle vpip_make_vthr_APV(char*label, unsigned index, unsigned bit, unsigned wid); /* * This function is called before any compilation to load VPI * modules. This gives the modules a chance to announce their * contained functions before compilation commences. It is called only * once per module. */ extern void vpip_load_module(const char*name); # define VPIP_MODULE_PATH_MAX 64 extern const char* vpip_module_path[VPIP_MODULE_PATH_MAX]; extern unsigned vpip_module_path_cnt; /* * The vpip_build_vpi_call function creates a __vpiSysTaskCall object * and returns the handle. The compiler uses this function when it * encounters a %vpi_call or %vpi_func statement. * * The %vpi_call instruction has as its only parameter the handle that * is returned by the vpip_build_vpi_call. This includes all the * information needed by vpip_execute_vpi_call to actually execute the * call. However, the vpiSysTaskCall that is the returned handle, * holds a parameter argument list that is passed in here. * * The val_type and return_width fields are used if this turns out to * be a system function. In that case, the val_type encodes the return * type (-vpiRealVal, -vpiVectorVal) and if a vector the return_width * has the vector width. * * Note that the argv array is saved in the handle, and should should * not be released by the caller. */ extern vpiHandle vpip_build_vpi_call(const char*name, int val_type, unsigned return_width, class vvp_net_t*fnet, bool func_as_task_err, bool func_as_task_warn, unsigned argc, vpiHandle*argv, unsigned vec4_stack, unsigned real_stack, unsigned string_stack, long file_idx, long lineno); extern vthread_t vpip_current_vthread; extern void vpip_execute_vpi_call(vthread_t thr, vpiHandle obj); /* * These are functions used by the compiler to prepare for compilation * and to finish compilation in preparation for execution. */ vpiHandle vpip_sim_time(__vpiScope*scope, bool is_stime); vpiHandle vpip_sim_realtime(__vpiScope*scope); extern int vpip_get_time_precision(void); extern void vpip_set_time_precision(int pres); extern int vpip_time_units_from_handle(vpiHandle obj); extern int vpip_time_precision_from_handle(vpiHandle obj); extern void vpip_time_to_timestruct(struct t_vpi_time*ts, vvp_time64_t ti); extern vvp_time64_t vpip_timestruct_to_time(const struct t_vpi_time*ts); extern double vpip_time_to_scaled_real(vvp_time64_t ti, __vpiScope*sc); extern vvp_time64_t vpip_scaled_real_to_time64(double val, __vpiScope*sc); /* * These functions are used mostly as compile time to strings into * permallocated memory. The vpip_string function is the most general, * it allocates a fresh string no matter what. The vpip_name_string * allocates a string and keeps a pointer in the hash, and tries to * reuse it if it can. This us useful for handle names, which may be * reused in different scopes. */ extern const char* vpip_string(const char*str); extern const char* vpip_name_string(const char*str); /* * This function is used to make decimal string versions of various * vectors. The input format is a vvp_vector4_t, and the result is * written into buf, without overflowing nbuf. */ extern unsigned vpip_vec4_to_dec_str(const vvp_vector4_t&vec4, char *buf, unsigned int nbuf, int signed_flag); extern void vpip_vec4_to_hex_str(const vvp_vector4_t&bits, char*buf, unsigned nbuf); extern void vpip_vec4_to_oct_str(const vvp_vector4_t&bits, char*buf, unsigned nbuf); extern void vpip_bin_str_to_vec4(vvp_vector4_t&val, const char*buf); extern void vpip_oct_str_to_vec4(vvp_vector4_t&val, const char*str); extern void vpip_dec_str_to_vec4(vvp_vector4_t&val, const char*str); extern void vpip_hex_str_to_vec4(vvp_vector4_t&val, const char*str); extern vvp_vector4_t vec4_from_vpi_value(s_vpi_value*vp, unsigned wid); extern double real_from_vpi_value(s_vpi_value*vp); extern void vpip_vec4_get_value(const vvp_vector4_t&word_val, unsigned width, bool signed_flag, s_vpi_value*vp); extern void vpip_vec2_get_value(const vvp_vector2_t&word_val, unsigned width, bool signed_flag, s_vpi_value*vp); extern void vpip_real_get_value(double real, s_vpi_value*vp); extern void vpip_string_get_value(const std::string&val, s_vpi_value*vp); /* * Function defined in vpi_signal.cc to manage vpi_get_* persistent * storage. */ enum vpi_rbuf_t { RBUF_VAL =0, /* Storage for *_get_value() */ RBUF_STR, /* Storage for *_get_str() */ RBUF_DEL /* Delete the storage for both buffers. */ }; extern void *need_result_buf(unsigned cnt, vpi_rbuf_t type); /* following two routines use need_result_buf(, RBUF_STR) */ extern char *simple_set_rbuf_str(const char *s1); extern char *generic_get_str(int code, vpiHandle ref, const char *name, const char *index); /* A routine to find the enclosing module. */ extern vpiHandle vpip_module(__vpiScope*scope); extern int vpip_delay_selection; #endif /* IVL_vpi_priv_H */