#ifndef IVL_compile_H #define IVL_compile_H /* * Copyright (c) 2001-2021 Stephen Williams (steve@icarus.com) * * 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 # include # include # include # include "parse_misc.h" # include "sv_vpi_user.h" # include "vvp_net.h" /* * The file names are kept in this vector. Entry 0 is "N/A" and 1 is * for interactive commands. */ extern std::vector file_names; /* * The functions described here are the compile time support * functions. Various bits of the compile process are taken care of * here. What is called when is mostly controlled by the parser. * * Before compilation takes place, the compile_init function must be * called once to set stuff up. */ extern void compile_init(void); extern void compile_cleanup(void); extern bool verbose_flag; /* * If this file opened, then write debug information to this * file. This is used for debugging the VVP runtime itself. */ extern std::ofstream debug_file; /* * Connect a list of symbols to a contiguous set of ipoints. * Constants C are handled by setting the ival of the ipoint. */ extern void inputs_connect(vvp_net_t*fdx, unsigned argc, struct symb_s*argv); extern void input_connect(vvp_net_t*fdx, unsigned port, char*label); /* * This function is an expansion of the inputs_connect function. It * uses the inputs_connect function, but it creates vvp_wide_fun_t * nodes to handle arbitrary width nodes, and connects those nodes to * the vvp_wide_fun_core object passed in. */ extern void wide_inputs_connect(vvp_wide_fun_core*core, unsigned argc, struct symb_s*argv); extern vvp_net_t* vvp_net_lookup(const char*label); extern vpiHandle vvp_lookup_handle(const char*label); /* * Add a functor to the symbol table */ extern void define_functor_symbol(const char*label, vvp_net_t*ipt); /* * This is a count of errors encountered during compilation. If this * is non-zero, then simulation is not recommended. */ extern unsigned compile_errors; extern const char* module_path; extern void compile_load_vpi_module(char*name); extern void compile_vpi_time_precision(long pre); /* * This function is called by the parser to compile a functor * statement. The strings passed in are allocated by the lexor, but * this function will free them. (Or save them permanently.) This * includes the argv array and the strings it references. * * The argc and argv are a list of char* that are the port parameters * of the functor. The compile should match those port parameters up * to existing functors to manage the linking. */ extern void compile_functor(char*label, char*type, unsigned width, unsigned ostr0, unsigned ostr1, unsigned argc, struct symb_s*argv); /* * This is called by the parser to make a resolver. This is a special * kind of functor; a strength aware functor. It has up to 4 inputs * that are blended to make a resolved output. The type string selects * a resolution algorithm. */ extern void compile_resolver(char*label, char*type, unsigned argc, struct symb_s*argv); extern void compile_concat(char*label, unsigned w0, unsigned w1, unsigned w2, unsigned w3, unsigned argc, struct symb_s*argv); extern void compile_concat8(char*label, unsigned w0, unsigned w1, unsigned w2, unsigned w3, unsigned argc, struct symb_s*argv); extern void compile_substitute(char*label, unsigned width, unsigned soff, unsigned swidth, unsigned argc, struct symb_s*argv); /* * Arrange for the system task/function call to have its compiletf * function called. */ extern void compile_compiletf(struct __vpiSysTaskCall*); /* * Compile delay nodes of various form. */ extern void compile_delay(char*label, unsigned width, vvp_delay_t*del, struct symb_s input); extern void compile_delay(char*label, unsigned width, unsigned argc, struct symb_s*argv, bool ignore_decay); /* * This is called by the parser to create a part select node. * See the PART SELECT STATEMENT section in the README.txt */ extern void compile_part_select(char*label, char*src, unsigned base, unsigned wid); extern void compile_part_select_pv(char*label, char*src, unsigned base, unsigned wid, unsigned vec_wid); extern void compile_part_select_var(char*label, char*src, char*var, unsigned wid, bool is_signed); /* * This is called by the parser to make the various arithmetic and * comparison functors. */ extern void compile_arith_pow(char*label, long width, bool signed_flag, unsigned argc, struct symb_s*argv); extern void compile_arith_abs(char*label, unsigned argc, struct symb_s*argv); extern void compile_arith_cast_int(char*label, long width, unsigned argc, struct symb_s*argv); extern void compile_arith_cast_real(char*label, bool signed_flag, unsigned argc, struct symb_s*argv); extern void compile_arith_cast_vec2(char*label, long width, unsigned argc, struct symb_s*argv); extern void compile_arith_div(char*label, long width, bool signed_flag, unsigned argc, struct symb_s*argv); extern void compile_arith_mod(char*label, long width, bool signed_flag, unsigned argc, struct symb_s*argv); extern void compile_arith_mult(char*label, long width, unsigned argc, struct symb_s*argv); extern void compile_arith_sum(char*label, long width, unsigned argc, struct symb_s*argv); extern void compile_arith_sub(char*label, long width, unsigned argc, struct symb_s*argv); extern void compile_cmp_eeq(char*label, long width, unsigned argc, struct symb_s*argv); extern void compile_cmp_nee(char*label, long width, unsigned argc, struct symb_s*argv); extern void compile_cmp_eq(char*label, long width, unsigned argc, struct symb_s*argv); extern void compile_cmp_eqx(char*label, long width, unsigned argc, struct symb_s*argv); extern void compile_cmp_eqz(char*label, long width, unsigned argc, struct symb_s*argv); extern void compile_cmp_ne(char*label, long width, unsigned argc, struct symb_s*argv); extern void compile_cmp_ge(char*label, long width, bool signed_flag, unsigned argc, struct symb_s*argv); extern void compile_cmp_gt(char*label, long width, bool signed_flag, unsigned argc, struct symb_s*argv); extern void compile_cmp_weq(char*label, long width, unsigned argc, struct symb_s*argv); extern void compile_cmp_wne(char*label, long width, unsigned argc, struct symb_s*argv); extern void compile_arith_mult_r(char*label, unsigned argc, struct symb_s*argv); extern void compile_arith_pow_r(char*label, unsigned argc, struct symb_s*argv); extern void compile_arith_div_r(char*label, unsigned argc, struct symb_s*argv); extern void compile_arith_mod_r(char*label, unsigned argc, struct symb_s*argv); extern void compile_arith_sum_r(char*label, unsigned argc, struct symb_s*argv); extern void compile_arith_sub_r(char*label, unsigned argc, struct symb_s*argv); extern void compile_cmp_eq_r(char*label, unsigned argc, struct symb_s*argv); extern void compile_cmp_ne_r(char*label, unsigned argc, struct symb_s*argv); extern void compile_cmp_ge_r(char*label, unsigned argc, struct symb_s*argv); extern void compile_cmp_gt_r(char*label, unsigned argc, struct symb_s*argv); extern void compile_dff(char*label, unsigned width, bool negedge, struct symb_s arg_d, struct symb_s arg_c, struct symb_s arg_e); extern void compile_dff_aclr(char*label, unsigned width, bool negedge, struct symb_s arg_d, struct symb_s arg_c, struct symb_s arg_e, struct symb_s arg_a); extern void compile_dff_aset(char*label, unsigned width, bool negedge, struct symb_s arg_d, struct symb_s arg_c, struct symb_s arg_e, struct symb_s arg_a, char*asc_value); extern void compile_latch(char*label, unsigned width, struct symb_s arg_d, struct symb_s arg_e); extern void compile_enum2_type(char*label, long width, bool signed_flag, std::list*names); extern void compile_enum4_type(char*label, long width, bool signed_flag, std::list*names); struct __vpiModPath; extern __vpiModPath* compile_modpath(char*label, unsigned width, struct symb_s drv, struct symb_s dest); extern void compile_modpath_src(__vpiModPath*dst, char edge, const struct symb_s&src, struct numbv_s&vals, const struct symb_s&condit_src, const struct symb_s&path_term_in); extern void compile_modpath_src(__vpiModPath*dst, char edge, const struct symb_s&src, struct numbv_s&vals, int condit_src, /* match with '0' */ const struct symb_s&path_term_in, bool ifnone); extern void compile_reduce_and(char*label, const struct symb_s&arg); extern void compile_reduce_or(char*label, const struct symb_s&arg); extern void compile_reduce_xor(char*label, const struct symb_s&arg); extern void compile_reduce_nand(char*label, const struct symb_s&arg); extern void compile_reduce_nor(char*label, const struct symb_s&arg); extern void compile_reduce_xnor(char*label, const struct symb_s&arg); extern void compile_extend_signed(char*label, long width, struct symb_s arg); extern void compile_sfunc(char*label, char*name, char*format_string, long file_idx, long lineno, unsigned argc, struct symb_s*argv, char*trigger_label); extern void compile_repeat(char*label, long width, long repeat, struct symb_s arg); extern void compile_shiftl(char*label, long width, unsigned argc, struct symb_s*argv); extern void compile_shiftr(char*label, long width, bool signed_flag, unsigned argc, struct symb_s*argv); extern void compile_timescale(long units, long precision); extern void compile_vpi_symbol(const char*label, vpiHandle obj); extern void compile_vpi_lookup(vpiHandle *objref, char*label); extern void compile_param_string(char*label, char*name, char*value, bool local_flag, long file_idx, long lineno); extern void compile_param_logic(char*label, char*name, char*value, bool signed_flag, bool local_flag, long file_idx, long lineno); extern void compile_param_real(char*label, char*name, char*value, bool local_flag, long file_idx, long lineno); /* * The resolv_list_s is the base class for a symbol resolve * action. Some function creates an instance of a resolv_list_s object * that contains the data pertinent to that resolution request, and * executes it with the resolv_submit function. If the operation can * complete, then the resolv_submit deletes the object. Otherwise, it * pushes it onto the resolv_list for later processing. * * Derived classes implement the resolve function to perform the * actual binding or resolution that the instance requires. If the * function succeeds, the resolve method returns true and the object * can be deleted any time. * * The mes parameter of the resolve method tells the resolver that * this call is its last chance. If it cannot complete the operation, * it must print an error message and return false. */ class resolv_list_s { public: explicit resolv_list_s(char*lab) : label_(lab) { next = NULL; } virtual ~resolv_list_s(); virtual bool resolve(bool mes = false) = 0; protected: const char*label() const { return label_; } private: friend void resolv_submit(class resolv_list_s*cur); friend void compile_cleanup(void); char*label_; class resolv_list_s*next; }; /* * This function schedules a lookup of an indexed label. The ref * points to the vvp_net_t that receives the result. The result may * be assigned later, if the symbol is defined later in the source * file, so the memory that ref points to must persist. * * The text for the label will be deleted by this function, or the * cleanup that completes the binding. */ extern void functor_ref_lookup(vvp_net_t**ref, char*lab); /* * This function schedules a lookup of the labeled instruction. The * code points to a code structure that points to the instruction * field that receives the result, and the label is the name to * lookup. The lookup will free the label text when it is done. * * The cptr2 flag tells the lookup to write the code pointer into the * cptr2 member of the code, instead of the cptr member. */ extern void code_label_lookup(struct vvp_code_s *code, char *label, bool cptr2); /* * The `compile_udp_def' function creates a UDP. The `table' is a * NULL terminated array of char*, as assembled by `compile_udp_table'. * `compile_udp_table' is called with `table'==NULL to create a new * table, or with an existing table to append to. * * `compile_udp_functor' creates a mode-3 functor referring to the * labeled UDP. */ extern void compile_udp_def(int sequ, char*label, char *name, unsigned nin, unsigned init, char **table); extern void compile_udp_functor(char*label, char*type, unsigned argc, struct symb_s*argv); extern char **compile_udp_table(char **table, char *row); /* * Memory Instances, Ports, and Initialization */ extern void compile_var_array(char*label, char*name, int last, int first, int msb, int lsb, char signed_flag); extern void compile_var2_array(char*label, char*name, int last, int first, int msb, int lsb, bool signed_flag); extern void compile_real_array(char*label, char*name, int last, int first); extern void compile_string_array(char*label, char*name, int last, int first); extern void compile_object_array(char*label, char*name, int last, int first); extern void compile_net_array(char*label, char*name, int last, int first); extern void compile_array_alias(char*label, char*name, char*src); /* Index is a net. */ extern void compile_array_port(char*label, char*name, char*addr); /* Index is a constant address */ extern void compile_array_port(char*label, char*name, long addr); extern void compile_array_cleanup(void); /* * Compile the .ufunc statement. */ extern void compile_ufunc_real(char*label, char*code, unsigned wid, unsigned argc, struct symb_s*argv, unsigned portc, struct symb_s*portv, char*scope_label, char*trigger_label); extern void compile_ufunc_vec4(char*label, char*code, unsigned wid, unsigned argc, struct symb_s*argv, unsigned portc, struct symb_s*portv, char*scope_label, char*trigger_label); /* * The compile_event function takes the parts of the event statement * and makes the various objects needed to simulate it. This includes * the functor that receives the signals and the event_t that holds * the threads. */ extern void compile_event(char*label, char*type, unsigned argc, struct symb_s*argv); extern void compile_named_event(char*label, char*type, bool local_flag=false); /* * A code statement is a label, an opcode and up to 3 operands. There * are a few lexical types that the parser recognizes of the operands, * given by the ltype_e enumeration. The compile_code function takes * the label, mnemonic and parsed operands and writes a properly * formed instruction into the code space. The label is set into the * symbol table with the address of the instruction. */ #define OPERAND_MAX 3 enum ltype_e { L_NUMB, L_SYMB, L_STRING }; struct comp_operands_s { unsigned argc; struct { enum ltype_e ltype; union { unsigned long numb; struct symb_s symb; const char *text; }; } argv[OPERAND_MAX]; }; typedef struct comp_operands_s*comp_operands_t; extern void compile_code(char*label, char*mnem, comp_operands_t opa); extern void compile_file_line(char*label, long file_idx, long lineno, char*description); extern void compile_vpi_call(char*label, char*name, bool func_as_task_err, bool func_as_task_warn, long file_idx, long lineno, unsigned argc, vpiHandle*argv, unsigned vec4_stack, unsigned real_stack, unsigned string_stack); /* Compile a function call. The vbit and vwid encode the return type. If the vwid >0, the return type is a vector. If the vwid is <0, the return type is -vpiRealConst or some other constant subtype code that represents the function type. */ extern void compile_vpi_func_call(char*label, char*name, int val_type, unsigned val_wid, long file_idx, long lineno, unsigned argc, vpiHandle*argv, unsigned vec4_stack, unsigned real_stack, unsigned string_stack); extern void print_vpi_call_errors(); extern void compile_codelabel(char*label); /* * The parser uses these functions to compile .scope statements. * The implementations of these live in the vpi_scope.cc file. */ extern void compile_scope_decl(char*typ, char*lab, char*nam, char*tnam, char*par, long file_idx, long lineno, long def_file_idx, long def_lineno, long is_cell); extern void compile_scope_recall(char*sym); /* * The parser uses this function to declare a thread. The start_sym is * the start instruction, and must already be defined. */ extern void compile_thread(char*start_sym, char*flag); /* * This function is called to create a var vector with the given name. * * The vpi_type_code argument of compile_variable() is one of the vpi * object codes that identify the type: vpiReg, vpiIntegerVar, * vpiIntVar, etc. */ extern void compile_variable(char*label, char*name, int msb, int lsb, int vpi_type_code, bool signed_flag, bool local_flag); extern void compile_var_real(char*label, char*name); extern void compile_var_string(char*label, char*name); extern void compile_var_darray(char*label, char*name, unsigned size); extern void compile_var_cobject(char*label, char*name); extern void compile_var_queue(char*label, char*name, unsigned size); /* * This function is used to create a scope port * Current ONLY module ports are supported and ports exist purely * as meta-data for VPI queries (i.e. there is NO corresponding net etc) * as elaboration internally eliminates port-nets by directly connecting * nets connected through module ports. */ extern void compile_port_info( unsigned index, int vpi_port_type, unsigned width, const char *name ); /* * The compile_net function is called to create a .net vector with a * given name. * * The vpi_type_code argument of compile_net() is one of the vpi * object codes for the equivalent variable types. The supported codes * are: * vpiLogic -- 4-value logic * vpiIntVar -- 2-value logic * -vpiLogic -- 8-value (i.e. strength aware) logic */ extern void compile_net(char*label, char*name, int msb, int lsb, int vpi_type_code, bool signed_flag, bool local_flag, unsigned argc, struct symb_s*argv); extern void compile_net_real(char*label, char*name, int msb, int lsb, bool local_flag, unsigned argc, struct symb_s*argv); extern void compile_netw(char*label, char*array_label, unsigned long array_addr, int msb, int lsb, int vpi_type_code, bool signed_flag, unsigned argc, struct symb_s*argv); extern void compile_netw_real(char*label, char*array_symbol, unsigned long array_addr, int msb, int lsb, unsigned argc, struct symb_s*argv); extern void compile_island(char*label, char*type); extern void compile_island_port(char*label, char*island, char*src); extern void compile_island_import(char*label, char*island, char*src); extern void compile_island_export(char*label, char*island); extern void compile_island_cleanup(void); extern void compile_island_tran(char*label); extern void compile_island_tranif(int sense, char*island, char*ba, char*bb, char*src, bool resistive); extern void compile_island_tranvp(char*island, char*ba, char*bb, unsigned width, unsigned part, unsigned off); extern void delete_udp_symbols(void); extern void compile_class_start(char*lab, char*nam, unsigned nprop); extern void compile_class_property(unsigned idx, char*nam, char*typ, uint64_t array_size); extern void compile_class_done(void); #endif /* IVL_compile_H */