diff --git a/vvp/array.cc b/vvp/array.cc index 3e9144e0e..c76e2db41 100644 --- a/vvp/array.cc +++ b/vvp/array.cc @@ -35,7 +35,7 @@ static symbol_table_t array_table =0; class vvp_fun_arrayport; static void array_attach_port(vvp_array_t, vvp_fun_arrayport*); -vvp_array_t array_find(char*label) +vvp_array_t array_find(const char*label) { if (array_table == 0) return 0; @@ -667,43 +667,66 @@ void array_word_change(vvp_array_t array, unsigned long addr) cur->check_word_change(addr); } -void compile_array_port(char*label, char*array, char*addr) +class array_port_resolv_list_t : public resolv_list_s { + + public: + explicit array_port_resolv_list_t(char*label) : resolv_list_s(label) { } + + vvp_net_t*ptr; + bool use_addr; + long addr; + bool resolve(bool mes); + + private: +}; + +bool array_port_resolv_list_t::resolve(bool mes) { - vvp_array_t mem = array_find(array); - assert(mem); + vvp_array_t mem = array_find(label()); + if (mem == 0) { + assert(mem || !mes); + return false; + } - vvp_net_t*ptr = new vvp_net_t; - vvp_fun_arrayport*fun = new vvp_fun_arrayport(mem, ptr); + vvp_fun_arrayport*fun; + if (use_addr) + fun = new vvp_fun_arrayport(mem, ptr, addr); + else + fun = new vvp_fun_arrayport(mem, ptr); ptr->fun = fun; - define_functor_symbol(label, ptr); - // Connect the port-0 input as the address. - input_connect(ptr, 0, addr); - array_attach_port(mem, fun); + return true; +} + +void compile_array_port(char*label, char*array, char*addr) +{ + array_port_resolv_list_t*resolv_mem + = new array_port_resolv_list_t(array); + + resolv_mem->ptr = new vvp_net_t; + resolv_mem->use_addr = false; + define_functor_symbol(label, resolv_mem->ptr); free(label); - free(array); - // The input_connect arranges for the array string to be free'ed. + // Connect the port-0 input as the address. + input_connect(resolv_mem->ptr, 0, addr); + + resolv_submit(resolv_mem); } void compile_array_port(char*label, char*array, long addr) { - vvp_array_t mem = array_find(array); - assert(mem); - - vvp_net_t*ptr = new vvp_net_t; - vvp_fun_arrayport*fun = new vvp_fun_arrayport(mem, ptr, addr); - ptr->fun = fun; - - define_functor_symbol(label, ptr); - - // Other then the array itself, this kind of array port has no - // inputs. - array_attach_port(mem, fun); + array_port_resolv_list_t*resolv_mem + = new array_port_resolv_list_t(array); + resolv_mem->ptr = new vvp_net_t; + resolv_mem->use_addr = true; + resolv_mem->addr = addr; + define_functor_symbol(label, resolv_mem->ptr); free(label); - free(array); + + resolv_submit(resolv_mem); } void compile_array_alias(char*label, char*name, char*src) diff --git a/vvp/array.h b/vvp/array.h index f7ad35f70..c081a4eb6 100644 --- a/vvp/array.h +++ b/vvp/array.h @@ -28,7 +28,7 @@ typedef struct __vpiArray* vvp_array_t; * This function tries to find the array (by label) in the global * table of all the arrays in the design. */ -extern vvp_array_t array_find(char*label); +extern vvp_array_t array_find(const char*label); extern vpiHandle array_index_iterate(int code, vpiHandle ref); extern void array_word_change(vvp_array_t array, unsigned long addr); diff --git a/vvp/compile.cc b/vvp/compile.cc index 5d6e819a8..fe9c82f82 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -321,13 +321,12 @@ vvp_net_t* vvp_net_lookup(const char*label) */ static struct resolv_list_s*resolv_list = 0; -struct resolv_list_s { - virtual ~resolv_list_s() { } - struct resolv_list_s*next; - virtual bool resolve(bool mes = false) = 0; -}; +resolv_list_s::~resolv_list_s() +{ + free(label_); +} -static void resolv_submit(struct resolv_list_s*cur) +void resolv_submit(struct resolv_list_s*cur) { if (cur->resolve()) { delete cur; @@ -346,8 +345,8 @@ static void resolv_submit(struct resolv_list_s*cur) * put net->port[port] into the fan-out list for that node. */ struct vvp_net_resolv_list_s: public resolv_list_s { - // node to locate - char*source; + + vvp_net_resolv_list_s(char*l) : resolv_list_s(l) { } // port to be driven by the located node. vvp_net_ptr_t port; virtual bool resolve(bool mes); @@ -355,20 +354,18 @@ struct vvp_net_resolv_list_s: public resolv_list_s { bool vvp_net_resolv_list_s::resolve(bool mes) { - vvp_net_t*tmp = vvp_net_lookup(source); + vvp_net_t*tmp = vvp_net_lookup(label()); if (tmp) { // Link the input port to the located output. vvp_net_t*net = port.ptr(); net->port[port.port()] = tmp->out; tmp->out = port; - - free(source); return true; } if (mes) - fprintf(stderr, "unresolved vvp_net reference: %s\n", source); + fprintf(stderr, "unresolved vvp_net reference: %s\n", label()); return false; } @@ -376,10 +373,8 @@ bool vvp_net_resolv_list_s::resolve(bool mes) inline static void postpone_functor_input(vvp_net_ptr_t port, char*lab) { - struct vvp_net_resolv_list_s*res = new struct vvp_net_resolv_list_s; - + struct vvp_net_resolv_list_s*res = new struct vvp_net_resolv_list_s(lab); res->port = port; - res->source = lab; resolv_submit(res); } @@ -390,24 +385,22 @@ void postpone_functor_input(vvp_net_ptr_t port, char*lab) */ struct functor_gen_resolv_list_s: public resolv_list_s { - char*source; + explicit functor_gen_resolv_list_s(char*txt) : resolv_list_s(txt) { } vvp_net_t**ref; virtual bool resolve(bool mes); }; bool functor_gen_resolv_list_s::resolve(bool mes) { - vvp_net_t*tmp = vvp_net_lookup(source); + vvp_net_t*tmp = vvp_net_lookup(label()); if (tmp) { *ref = tmp; - - free(source); return true; } if (mes) - fprintf(stderr, "unresolved functor reference: %s\n", source); + fprintf(stderr, "unresolved functor reference: %s\n", label()); return false; } @@ -415,10 +408,9 @@ bool functor_gen_resolv_list_s::resolve(bool mes) void functor_ref_lookup(vvp_net_t**ref, char*lab) { struct functor_gen_resolv_list_s*res = - new struct functor_gen_resolv_list_s; + new struct functor_gen_resolv_list_s(lab); res->ref = ref; - res->source = lab; resolv_submit(res); } @@ -428,27 +420,27 @@ void functor_ref_lookup(vvp_net_t**ref, char*lab) */ struct vpi_handle_resolv_list_s: public resolv_list_s { - vpiHandle *handle; - char *label; + explicit vpi_handle_resolv_list_s(char*label) : resolv_list_s(label) { } virtual bool resolve(bool mes); + vpiHandle *handle; }; bool vpi_handle_resolv_list_s::resolve(bool mes) { - symbol_value_t val = sym_get_value(sym_vpi, label); + symbol_value_t val = sym_get_value(sym_vpi, label()); if (!val.ptr) { // check for thread vector T unsigned base, wid; unsigned n = 0; char ss[32]; - if (2 <= sscanf(label, "T<%u,%u>%n", &base, &wid, &n) - && n == strlen(label)) { + if (2 <= sscanf(label(), "T<%u,%u>%n", &base, &wid, &n) + && n == strlen(label())) { val.ptr = vpip_make_vthr_vector(base, wid, false); - sym_set_value(sym_vpi, label, val); + sym_set_value(sym_vpi, label(), val); - } else if (3 <= sscanf(label, "T<%u,%u,%[su]>%n", &base, + } else if (3 <= sscanf(label(), "T<%u,%u,%[su]>%n", &base, &wid, ss, &n) - && n == strlen(label)) { + && n == strlen(label())) { bool signed_flag = false; for (char*fp = ss ; *fp ; fp += 1) switch (*fp) { @@ -463,13 +455,13 @@ bool vpi_handle_resolv_list_s::resolve(bool mes) } val.ptr = vpip_make_vthr_vector(base, wid, signed_flag); - sym_set_value(sym_vpi, label, val); + sym_set_value(sym_vpi, label(), val); - } else if (2 == sscanf(label, "W<%u,%[r]>%n", &base, ss, &n) - && n == strlen(label)) { + } else if (2 == sscanf(label(), "W<%u,%[r]>%n", &base, ss, &n) + && n == strlen(label())) { val.ptr = vpip_make_vthr_word(base, ss); - sym_set_value(sym_vpi, label, val); + sym_set_value(sym_vpi, label(), val); } } @@ -480,12 +472,11 @@ bool vpi_handle_resolv_list_s::resolve(bool mes) if (val.ptr) { *handle = (vpiHandle) val.ptr; - free(label); return true; } if (mes) - fprintf(stderr, "unresolved vpi name lookup: %s\n", label); + fprintf(stderr, "unresolved vpi name lookup: %s\n", label()); return false; } @@ -517,10 +508,9 @@ void compile_vpi_lookup(vpiHandle *handle, char*label) } struct vpi_handle_resolv_list_s*res - = new struct vpi_handle_resolv_list_s; + = new struct vpi_handle_resolv_list_s(label); res->handle = handle; - res->label = label; resolv_submit(res); } @@ -529,27 +519,24 @@ void compile_vpi_lookup(vpiHandle *handle, char*label) */ struct code_label_resolv_list_s: public resolv_list_s { + code_label_resolv_list_s(char*label) : resolv_list_s(label) { } struct vvp_code_s *code; - char *label; virtual bool resolve(bool mes); }; bool code_label_resolv_list_s::resolve(bool mes) { - symbol_value_t val = sym_get_value(sym_codespace, label); + symbol_value_t val = sym_get_value(sym_codespace, label()); if (val.num) { if (code->opcode == of_FORK) code->cptr2 = reinterpret_cast(val.ptr); else code->cptr = reinterpret_cast(val.ptr); - free(label); return true; } if (mes) - fprintf(stderr, - "unresolved code label: %s\n", - label); + fprintf(stderr, "unresolved code label: %s\n", label()); return false; } @@ -557,10 +544,9 @@ bool code_label_resolv_list_s::resolve(bool mes) void code_label_lookup(struct vvp_code_s *code, char *label) { struct code_label_resolv_list_s *res - = new struct code_label_resolv_list_s; + = new struct code_label_resolv_list_s(label); res->code = code; - res->label = label; resolv_submit(res); } @@ -569,21 +555,20 @@ void code_label_lookup(struct vvp_code_s *code, char *label) * Lookup memories. */ struct memory_resolv_list_s: public resolv_list_s { + memory_resolv_list_s(char*label) : resolv_list_s(label) { } struct vvp_code_s *code; - char *label; virtual bool resolve(bool mes); }; bool memory_resolv_list_s::resolve(bool mes) { - code->mem = memory_find(label); + code->mem = memory_find(label()); if (code->mem != 0) { - free(label); return true; } if (mes) - fprintf(stderr, "Memory unresolved: %s\n", label); + fprintf(stderr, "Memory unresolved: %s\n", label()); return false; } @@ -591,41 +576,38 @@ bool memory_resolv_list_s::resolve(bool mes) static void compile_mem_lookup(struct vvp_code_s *code, char *label) { struct memory_resolv_list_s *res - = new struct memory_resolv_list_s; + = new struct memory_resolv_list_s(label); res->code = code; - res->label = label; resolv_submit(res); } -struct array_resolv_list_s: public resolv_list_s { +struct code_array_resolv_list_s: public resolv_list_s { + code_array_resolv_list_s(char*label) : resolv_list_s(label) { } struct vvp_code_s *code; - char *label; virtual bool resolve(bool mes); }; -bool array_resolv_list_s::resolve(bool mes) +bool code_array_resolv_list_s::resolve(bool mes) { - code->array = array_find(label); + code->array = array_find(label()); if (code->array != 0) { - free(label); return true; } if (mes) - fprintf(stderr, "Array unresolved: %s\n", label); + fprintf(stderr, "Array unresolved: %s\n", label()); return false; } static void compile_array_lookup(struct vvp_code_s*code, char*label) { - struct array_resolv_list_s *res - = new struct array_resolv_list_s; + struct code_array_resolv_list_s *res + = new struct code_array_resolv_list_s(label); res->code = code; - res->label = label; resolv_submit(res); } diff --git a/vvp/compile.h b/vvp/compile.h index 276af4ce1..1e95e48f3 100644 --- a/vvp/compile.h +++ b/vvp/compile.h @@ -243,6 +243,41 @@ extern void compile_param_logic(char*label, char*name, char*value, extern void compile_param_real(char*label, char*name, char*value, 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) { } + virtual ~resolv_list_s(); + virtual bool resolve(bool mes = false) = 0; + + protected: + const char*label() const { return label_; } + + private: + friend void ::resolv_submit(struct resolv_list_s*cur); + friend void ::compile_cleanup(void); + + char*label_; + struct 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 diff --git a/vvp/memory.cc b/vvp/memory.cc index 96f237eae..05f606aa9 100644 --- a/vvp/memory.cc +++ b/vvp/memory.cc @@ -62,7 +62,7 @@ struct vvp_memory_s static symbol_table_t memory_table = 0; -vvp_memory_t memory_find(char *label) +vvp_memory_t memory_find(const char *label) { if (memory_table == 0) return 0; diff --git a/vvp/memory.h b/vvp/memory.h index 3d3cf2e4e..85473ea30 100644 --- a/vvp/memory.h +++ b/vvp/memory.h @@ -152,7 +152,7 @@ class vvp_fun_memport : public vvp_net_fun_t { ** The memory_create function creates a new memory device with the given ** name. It is a fatal error to try to create a device that already exists. */ -vvp_memory_t memory_find(char *label); +vvp_memory_t memory_find(const char *label); vvp_memory_t memory_create(char *label); /*