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);
/*