diff --git a/vvp/compile.cc b/vvp/compile.cc index def82b3d2..394fd834b 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -727,12 +727,27 @@ void compile_vpi_time_precision(long pre) * * The real value is sign * (mant ** exp). */ -double crstring_to_double(char*label) +bool crstring_test(const char*str) { - char*cp = label+3; + if (strncmp(str, "Cr<", 3) != 0) return false; + const char*tp = strchr(str, '>'); + if (tp == 0) return false; + if (tp[1] != 0) return false; + + if ((strspn(str+3, "0123456789abcdefmg")+3) != (tp - str)) + return false; + + return true; +} + +double crstring_to_double(const char*label) +{ + const char*cp = label+3; assert(*cp == 'm'); cp += 1; - uint64_t mant = strtoull(cp, &cp, 16); + char*ep; + uint64_t mant = strtoull(cp, &ep, 16); + cp = ep; assert(*cp == 'g'); cp += 1; int exp = strtoul(cp, 0, 16); @@ -774,10 +789,7 @@ void input_connect(vvp_net_t*fdx, unsigned port, char*label) char*tp; /* Is this a vvp_vector4_t constant value? */ - if ((strncmp(label, "C4<", 3) == 0) - && ((tp = strchr(label,'>'))) - && (tp[1] == 0) - && (strspn(label+3, "01xz")+3 == (unsigned)(tp-label))) { + if (c4string_test(label)) { vvp_vector4_t tmp = c4string_to_vector4(label); @@ -837,10 +849,7 @@ void input_connect(vvp_net_t*fdx, unsigned port, char*label) /* Handle the Cr<> constant driver, which is a real-value driver. */ - if ((strncmp(label, "Cr<", 3) == 0) - && ((tp = strchr(label,'>'))) - && (tp[1] == 0) - && (strspn(label+3, "0123456789abcdefmg")+3 == (unsigned)(tp-label))) { + if (crstring_test(label)) { double tmp = crstring_to_double(label); diff --git a/vvp/vvp_net.cc b/vvp/vvp_net.cc index 2ca0c67f9..99565d8e0 100644 --- a/vvp/vvp_net.cc +++ b/vvp/vvp_net.cc @@ -2370,6 +2370,19 @@ vvp_vector4_t vector2_to_vector4(const vvp_vector2_t&that, unsigned wid) return res; } +bool c4string_test(const char*str) +{ + if (strncmp(str, "C4<", 3) != 0) + return false; + size_t value_size = strspn(str+3, "01xz"); + if (str[3+value_size] != '>') + return false; + if (str[3+value_size+1] != 0) + return false; + + return true; +} + vvp_vector4_t c4string_to_vector4(const char*str) { assert((str[0]=='C') && (str[1]=='4') && (str[2]=='<')); @@ -2519,6 +2532,24 @@ vvp_vector8_t part_expand(const vvp_vector8_t&that, unsigned wid, unsigned off) return tmp; } +bool c8string_test(const char*str) +{ + const char*cp; + if (str[0] != 'C') return false; + if (str[1] != '8') return false; + if (str[2] != '<') return false; + + cp = str+3; + for (;; cp += 1) { + if (cp[0] == '>' && cp[1] == 0) return true; + if (cp[0] >= '0' && cp[0] <= '9') continue; + if (cp[0] == 'x') continue; + if (cp[0] == 'z') continue; + return false; + } + return false; +} + ostream& operator<<(ostream&out, const vvp_vector8_t&that) { out << "C8<"; diff --git a/vvp/vvp_net.h b/vvp/vvp_net.h index 8bad4e378..b42eafb49 100644 --- a/vvp/vvp_net.h +++ b/vvp/vvp_net.h @@ -639,9 +639,15 @@ extern vvp_vector2_t operator % (const vvp_vector2_t&, const vvp_vector2_t&); vvp_vector2_t pow(const vvp_vector2_t&, vvp_vector2_t&); extern vvp_vector4_t vector2_to_vector4(const vvp_vector2_t&, unsigned wid); + /* A c4string is of the form C4<...> where ... are bits. */ +extern bool c4string_test(const char*str); extern vvp_vector4_t c4string_to_vector4(const char*str); +/* A crstring is of the form Cr<...> where ... defines are real. */ +extern bool crstring_test(const char*str); +extern double crstring_to_double(const char*str); + extern ostream& operator<< (ostream&, const vvp_vector2_t&); /* Inline some of the vector2_t methods. */ @@ -830,6 +836,11 @@ extern vvp_vector8_t resistive_reduction(const vvp_vector8_t&a); strength information in the process. */ extern vvp_vector4_t reduce4(const vvp_vector8_t&that); extern vvp_vector8_t part_expand(const vvp_vector8_t&a, unsigned wid, unsigned off); + + /* A c8string is of the form C8<...> where ... are bits. */ +extern bool c8string_test(const char*str); +extern vvp_vector8_t c8string_to_vector8(const char*str); + /* Print a vector8 value to a stream. */ extern ostream& operator<< (ostream&, const vvp_vector8_t&); diff --git a/vvp/words.cc b/vvp/words.cc index 9983a9976..bfe6c34e5 100644 --- a/vvp/words.cc +++ b/vvp/words.cc @@ -21,6 +21,7 @@ # include "vpi_priv.h" # include "array.h" # include "vvp_net_sig.h" +# include "logic.h" # include "schedule.h" # include # include @@ -146,6 +147,58 @@ void compile_variablew(char*label, vvp_array_t array, __compile_var(label, 0, array, array_addr, msb, lsb, signed_flag, false); } +vvp_net_t* create_constant_node(const char*label, const char*val_str) +{ + if (c4string_test(val_str)) { + vvp_net_t*net = new vvp_net_t; + net->fun = new vvp_fun_bufz; + schedule_init_vector(vvp_net_ptr_t(net,0), c4string_to_vector4(val_str)); + return net; + } + + if (c8string_test(val_str)) { + vvp_net_t*net = new vvp_net_t; + net->fun = new vvp_fun_bufz; + assert(0); // XXXX Don't know how to init a vvp_vector8_t? */ + return net; + } + + if (crstring_test(val_str)) { + vvp_net_t*net = new vvp_net_t; + net->fun = new vvp_fun_bufz; + schedule_init_vector(vvp_net_ptr_t(net,0), crstring_to_double(val_str)); + return net; + } + + return 0; +} + +class __compile_net_resolv : public resolv_list_s { + + public: + explicit __compile_net_resolv(char*ref_label, char*my_label, char*name, + int msb, int lsb, + bool signed_flag, bool net8_flag, bool local_flag) + : resolv_list_s(ref_label) + { my_label_ = my_label; + name_ = name; + msb_ = msb; + lsb_ = lsb; + signed_flag_ = signed_flag; + local_flag_ = local_flag; + } + + ~__compile_net_resolv() { } + + bool resolve(bool message_flag); + + private: + char*my_label_; + char*name_; + int msb_, lsb_; + bool signed_flag_, net8_flag_, local_flag_; +}; + /* * Here we handle .net records from the vvp source: * @@ -157,23 +210,12 @@ void compile_variablew(char*label, vvp_array_t array, * Create a VPI handle to represent it, and fill that handle in with * references into the net. */ -static void __compile_net(char*label, - char*name, char*array_label, unsigned long array_addr, - int msb, int lsb, - bool signed_flag, bool net8_flag, bool local_flag, - unsigned argc, struct symb_s*argv) + +static void __compile_net2(vvp_net_t*node, char*my_label, char*name, + int msb, int lsb, + bool signed_flag, bool net8_flag, bool local_flag) { unsigned wid = ((msb > lsb)? msb-lsb : lsb-msb) + 1; - - // XXXX Forgot how to implement net arrays... - assert(array_label == 0); - - assert(argc == 1); - vvp_net_t*node = vvp_net_lookup(argv[0].text); - if (node == 0) { - cerr << "Internal error: vvp_net_lookup fails: " - << argv[0].text << endl; - } assert(node); vvp_wire_base*vsig = dynamic_cast(node->fil); @@ -191,18 +233,66 @@ static void __compile_net(char*label, /* Make the vpiHandle for the reg. */ obj = vpip_make_net(name, msb, lsb, signed_flag, node); /* This attaches the label to the vpiHandle */ - compile_vpi_symbol(label, obj); + compile_vpi_symbol(my_label, obj); } - if (obj) - vpip_attach_to_current_scope(obj); + if (obj) vpip_attach_to_current_scope(obj); + + free(my_label); + delete[] name; +} + +static void __compile_net(char*label, + char*name, char*array_label, unsigned long array_addr, + int msb, int lsb, + bool signed_flag, bool net8_flag, bool local_flag, + unsigned argc, struct symb_s*argv) +{ + // XXXX Forgot how to implement net arrays... + assert(array_label == 0); + + assert(argc == 1); + vvp_net_t*node = vvp_net_lookup(argv[0].text); + if (node == 0) { + /* No existing net, but the string value may be a + constant. In that case, we will wind up generating a + bufz node that can carry the constant value. */ + node = create_constant_node(label, argv[0].text); + } + if (node == 0) { + __compile_net_resolv*res = new __compile_net_resolv(argv[0].text, + label, name, msb, lsb, + signed_flag, net8_flag, local_flag); + resolv_submit(res); + return; + cerr << __FILE__ << ":" << __LINE__ << ": Internal error: " + << "vvp_net_lookup fails: " << argv[0].text << endl; + } + assert(node); + + if (name) { + __compile_net2(node, label, name, msb, lsb, + signed_flag, net8_flag, local_flag); + } else { + free(label); + if (name) delete[] name; + if (array_label) free(array_label); + } - free(label); - if (name) delete[] name; - if (array_label) free(array_label); free(argv); } +bool __compile_net_resolv::resolve(bool msg_flag) +{ + vvp_net_t*node = vvp_net_lookup(label()); + if (node == 0) { + return false; + } + + __compile_net2(node, my_label_, name_, msb_, lsb_, signed_flag_, net8_flag_, local_flag_); + return true; +} + void compile_net(char*label, char*name, int msb, int lsb, bool signed_flag, bool net8_flag, bool local_flag, unsigned argc, struct symb_s*argv)