diff --git a/ivl_target.h b/ivl_target.h index 95b7eab3f..e19466032 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: ivl_target.h,v 1.176 2007/02/02 04:33:00 steve Exp $" +#ident "$Id: ivl_target.h,v 1.177 2007/02/25 23:08:24 steve Exp $" #endif # include @@ -612,6 +612,18 @@ extern ivl_nexus_t ivl_event_pos(ivl_event_t net, unsigned idx); * * Bit and part selects are not done here. The IVL_EX_SELECT * expression does bit/part selects on the word read from the signal. + * + * - IVL_EX_STRING + * This expression refers to a string constant. The ivl_expr_string + * function returns a pointer to the first byte of the string. The + * compiler has translated it to a "vvp escaped string" which has + * quoting and escapes eliminated. The string may contain octal + * escapes (\) so that the string text returned by + * ivl_expr_string will only contain graphical characters. It is up to + * the target to change the escaped \NNN to the proper byte value when + * using this string. No other escape sequences will appear in the + * string. Quote (") and slash (\) characters will be delivered in + * \NNN form. */ extern ivl_expr_type_t ivl_expr_type(ivl_expr_t net); @@ -1756,6 +1768,9 @@ _END_DECL /* * $Log: ivl_target.h,v $ + * Revision 1.177 2007/02/25 23:08:24 steve + * Process Verilog escape sequences much earlier. + * * Revision 1.176 2007/02/02 04:33:00 steve * Use inttypes.h instead of stdint.h for portability. * diff --git a/verinum.cc b/verinum.cc index 4ed2c95b5..4c60fc144 100644 --- a/verinum.cc +++ b/verinum.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: verinum.cc,v 1.51 2007/01/27 05:36:11 steve Exp $" +#ident "$Id: verinum.cc,v 1.52 2007/02/25 23:08:24 steve Exp $" #endif # include "config.h" @@ -41,9 +41,63 @@ verinum::verinum(const V*bits, unsigned nbits, bool has_len) } } -verinum::verinum(const string&str) +static string process_verilog_string_quotes(const string&str) +{ + string res; + + int idx = 0; + int str_len = str.length(); + + while (idx < str_len) { + if (str[idx] == '\\') { + idx += 1; + assert(idx < str_len); + switch (str[idx]) { + case 'n': + res = res + '\n'; + idx += 1; + break; + case 't': + res = res + '\t'; + idx += 1; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': { + char byte_val = 0; + int odx = 0; + while (odx < 3 && idx+odx < str_len + && str[idx+odx] >= '0' + && str[idx+odx] <= '7') { + byte_val = 8*byte_val + str[idx+odx]-'0'; + odx += 1; + } + idx += odx; + res = res + byte_val; + break; + } + default: + res = res + str[idx]; + idx += 1; + break; + } + } else { + res = res + str[idx]; + idx += 1; + } + } + return res; +} + +verinum::verinum(const string&s) : has_len_(true), has_sign_(false), string_flag_(true) { + string str = process_verilog_string_quotes(s); nbits_ = str.length() * 8; // Special case: The string "" is 8 bits of 0. @@ -284,29 +338,37 @@ string verinum::as_string() const if (nbits_ == 0) return ""; - char*tmp = new char[nbits_/8+1]; - char*cp = tmp; + string res; + bool leading_nuls = true; for (unsigned idx = nbits_ ; idx > 0 ; idx -= 8) { + char char_val = 0; V*bp = bits_+idx; - *cp = 0; - if (*(--bp) == V1) *cp |= 0x80; - if (*(--bp) == V1) *cp |= 0x40; - if (*(--bp) == V1) *cp |= 0x20; - if (*(--bp) == V1) *cp |= 0x10; - if (*(--bp) == V1) *cp |= 0x08; - if (*(--bp) == V1) *cp |= 0x04; - if (*(--bp) == V1) *cp |= 0x02; - if (*(--bp) == V1) *cp |= 0x01; - if (*cp != 0) { - cp += 1; - *cp = 0; + + if (*(--bp) == V1) char_val |= 0x80; + if (*(--bp) == V1) char_val |= 0x40; + if (*(--bp) == V1) char_val |= 0x20; + if (*(--bp) == V1) char_val |= 0x10; + if (*(--bp) == V1) char_val |= 0x08; + if (*(--bp) == V1) char_val |= 0x04; + if (*(--bp) == V1) char_val |= 0x02; + if (*(--bp) == V1) char_val |= 0x01; + if (char_val == 0 && leading_nuls) + continue; + + if (char_val == '"' || char_val == '\\') { + char tmp[5]; + snprintf(tmp, sizeof tmp, "\\\%03o", char_val); + res = res + tmp; + } else if (char_val == ' ' || isgraph(char_val)) { + res = res + char_val; + + } else { + char tmp[5]; + snprintf(tmp, sizeof tmp, "\\\%03o", char_val); + res = res + tmp; } } - - tmp[nbits_/8] = 0; - string result = string(tmp); - delete[]tmp; - return result; + return res; } bool verinum::is_before(const verinum&that) const @@ -1062,6 +1124,9 @@ verinum::V operator ^ (verinum::V l, verinum::V r) /* * $Log: verinum.cc,v $ + * Revision 1.52 2007/02/25 23:08:24 steve + * Process Verilog escape sequences much earlier. + * * Revision 1.51 2007/01/27 05:36:11 steve * Fix padding of x when literal is sized and unsigned. * diff --git a/vvp/vpi_const.cc b/vvp/vpi_const.cc index 1ae9719f4..a37343ef8 100644 --- a/vvp/vpi_const.cc +++ b/vvp/vpi_const.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: vpi_const.cc,v 1.36 2006/06/18 04:15:50 steve Exp $" +#ident "$Id: vpi_const.cc,v 1.37 2007/02/25 23:08:24 steve Exp $" #endif # include "vpi_priv.h" @@ -168,6 +168,30 @@ static const struct __vpirt vpip_string_temp_rt = { free_temp_string }; +static void vpip_process_string(struct __vpiStringConst*obj) +{ + char*chr = obj->value; + char*dp = obj->value; + + while (*chr) { + char next_char = *chr; + + /* Process octal escapes that I might find. */ + if (*chr == '\\') { + for (int idx = 1 ; idx <= 3 ; idx += 1) { + assert(chr[idx] != 0); + assert(chr[idx] < '8'); + assert(chr[idx] >= '0'); + next_char = next_char*8 + chr[idx] - '0'; + } + chr += 3; + } + *dp++ = next_char; + chr += 1; + } + *dp = 0; + obj->value_len = dp - obj->value; +} vpiHandle vpip_make_string_const(char*text, bool persistent_flag) { @@ -179,6 +203,8 @@ vpiHandle vpip_make_string_const(char*text, bool persistent_flag) ? &vpip_string_rt : &vpip_string_temp_rt; obj->value = text; + obj->value_len = 0; + vpip_process_string(obj); return &obj->base; } @@ -244,9 +270,12 @@ vpiHandle vpip_make_string_param(char*name, char*text) malloc(sizeof (struct __vpiStringParam)); obj->base.vpi_type = &vpip_string_param_rt; obj->value = text; + obj->value_len = 0; obj->basename = name; obj->scope = vpip_peek_current_scope(); + vpip_process_string(obj); + return &obj->base; } @@ -589,6 +618,9 @@ vpiHandle vpip_make_real_const(double value) /* * $Log: vpi_const.cc,v $ + * Revision 1.37 2007/02/25 23:08:24 steve + * Process Verilog escape sequences much earlier. + * * Revision 1.36 2006/06/18 04:15:50 steve * Add support for system functions in continuous assignments. * diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index c559ec23d..475e8425a 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: vpi_priv.h,v 1.72 2007/01/16 05:44:16 steve Exp $" +#ident "$Id: vpi_priv.h,v 1.73 2007/02/25 23:08:24 steve Exp $" #endif # include "vpi_user.h" @@ -293,6 +293,7 @@ extern struct __vpiSysTaskCall*vpip_cur_task; struct __vpiStringConst { struct __vpiHandle base; char*value; + size_t value_len; }; vpiHandle vpip_make_string_const(char*text, bool persistent =true); @@ -450,6 +451,9 @@ extern char *need_result_buf(unsigned cnt, vpi_rbuf_t type); /* * $Log: vpi_priv.h,v $ + * Revision 1.73 2007/02/25 23:08:24 steve + * Process Verilog escape sequences much earlier. + * * Revision 1.72 2007/01/16 05:44:16 steve * Major rework of array handling. Memories are replaced with the * more general concept of arrays. The NetMemory and NetEMemory