From 22543f3e197730c4e479435e87ce459fc03bcfeb Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 17 Sep 2008 22:22:46 -0400 Subject: [PATCH] Support arbitrary characters in identifiers and tracing. --- Changes | 2 + src/V3Ast.cpp | 69 +++++++++++++++++++++++++--------- src/verilog.l | 15 +------- test_regress/t/t_var_escape.pl | 25 ++++++++++++ test_regress/t/t_var_escape.v | 59 +++++++++++++++++++++++++++++ 5 files changed, 139 insertions(+), 31 deletions(-) create mode 100755 test_regress/t/t_var_escape.pl create mode 100644 test_regress/t/t_var_escape.v diff --git a/Changes b/Changes index da48087e5..215f5493a 100644 --- a/Changes +++ b/Changes @@ -20,6 +20,8 @@ indicates the contributor was also the author of the fix; Thanks! **** Fix stack overflow on large ? : trees. [John Sanguinetti] +**** Support arbitrary characters in identifiers. [Stephane Laurent] + * Verilator 3.670 2008/07/23 ** Add --x-assign=fast option, and make it the default. diff --git a/src/V3Ast.cpp b/src/V3Ast.cpp index 0e22a0746..3c16fed10 100644 --- a/src/V3Ast.cpp +++ b/src/V3Ast.cpp @@ -85,12 +85,27 @@ void AstNode::init() { string AstNode::encodeName(const string& namein) { string name2 = namein; string out; - for (string::iterator pos = name2.begin(); pos != name2.end(); pos++) { - if (pos[0]=='_' && pos[1]=='_') { - out += "__ULUL_"; - pos++; - } else { + const char* start = name2.c_str(); + for (const char* pos = start; *pos; pos++) { + if ((pos==start) ? isalpha(pos[0]) // digits can't lead identifiers + : isalnum(pos[0])) { out += pos[0]; + } else if (pos[0]=='_') { + if (pos[1]=='_') { + out += "_"; out += "__5F"; // hex(_) = 0x5F + pos++; + } else { + out += pos[0]; + } + } else if (pos[0]=='.') { + out += "__DOT__"; + } else if (pos[0]=='[') { + out += "__BRA__"; + } else if (pos[0]==']') { + out += "__KET__"; + } else { + char hex[10]; sprintf(hex,"%02X",pos[0]); + out += "__"; out += hex; } } return out; @@ -116,19 +131,37 @@ string AstNode::dedotName(const string& namein) { } string AstNode::prettyName(const string& namein) { - string pretty = namein; - string::size_type pos; - while ((pos=pretty.find("__BRA__")) != string::npos) { - pretty.replace(pos, 7, "["); - } - while ((pos=pretty.find("__KET__")) != string::npos) { - pretty.replace(pos, 7, "]"); - } - while ((pos=pretty.find("__PVT__")) != string::npos) { - pretty.replace(pos, 7, ""); - } - while ((pos=pretty.find("__ULUL_")) != string::npos) { - pretty.replace(pos, 7, ""); + string pretty; + string name2 = namein; + pretty = ""; + for (const char* pos = name2.c_str(); *pos; ) { + if (0==strncmp(pos,"__BRA__",7)) { + pretty += "["; + pos += 7; + } + else if (0==strncmp(pos,"__KET__",7)) { + pretty += "]"; + pos += 7; + } + else if (0==strncmp(pos,"__DOT__",7)) { + pretty += "."; + pos += 7; + } + else if (0==strncmp(pos,"__PVT__",7)) { + pretty += ""; + pos += 7; + } + else if (pos[0]=='_' && pos[1]=='_' && isxdigit(pos[2]) && isxdigit(pos[3])) { + char value = 0; + value += 16*(isdigit(pos[2]) ? (pos[2]-'0') : (tolower(pos[2])-'a'+10)); + value += (isdigit(pos[3]) ? (pos[3]-'0') : (tolower(pos[3])-'a'+10)); + pretty += value; + pos += 4; + } + else { + pretty += pos[0]; + pos++; + } } return AstNode::dedotName(pretty); } diff --git a/src/verilog.l b/src/verilog.l index 72cd3be2b..ce67edf0d 100644 --- a/src/verilog.l +++ b/src/verilog.l @@ -654,19 +654,8 @@ escid \\[^ \t\f\r\n]+ /* Identifiers and numbers */ { - {escid} { int i; - for (i=0; yytext[i] != 0; i++) - if (!isalnum(yytext[i])) - yytext[i] = '_'; - if (isalpha(yytext[1])) { - yylval.strp = V3Read::newString( - AstNode::encodeName( - string(yytext+1))); // +1 to skip the backslash - } else { - yylval.strp = V3Read::newString( - AstNode::encodeName( - yytext)); // Need _ as "6..." isn't legal ID - } + {escid} { yylval.strp = V3Read::newString + (AstNode::encodeName(string(yytext+1))); // +1 to skip the backslash return yaID; } diff --git a/test_regress/t/t_var_escape.pl b/test_regress/t/t_var_escape.pl new file mode 100755 index 000000000..829bc9f46 --- /dev/null +++ b/test_regress/t/t_var_escape.pl @@ -0,0 +1,25 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003-2007 by Wilson Snyder. This program is free software; you can +# redistribute it and/or modify it under the terms of either the GNU +# General Public License or the Perl Artistic License. + +compile ( + # Access is so we can dump waves + v_flags2 => [$Last_Self->{v3}?'-trace':' +access+rwc'], + ); + +execute ( + check_finished=>1, + ); + +if ($Last_Self->{v3}) { + file_grep ("obj_dir/$Last_Self->{name}_simx.vcd", qr/\$enddefinitions/x); + my $sig = quotemeta("bra[ket]slash/dash-colon:9"); + file_grep ("obj_dir/$Last_Self->{name}_simx.vcd", qr/$sig/); +} + +ok(1); +1; diff --git a/test_regress/t/t_var_escape.v b/test_regress/t/t_var_escape.v new file mode 100644 index 000000000..ad841f7bf --- /dev/null +++ b/test_regress/t/t_var_escape.v @@ -0,0 +1,59 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2005 by Wilson Snyder. + +module t (/*AUTOARG*/ + // Outputs + \escaped_normal , double__underscore, \9num , \bra[ket]slash/dash-colon:9 , + // Inputs + clk + ); + + input clk; + + integer cyc; initial cyc=1; + + output \escaped_normal ; + wire \escaped_normal = cyc[0]; + + output double__underscore ; + wire double__underscore = cyc[0]; + + // C doesn't allow leading non-alpha, so must escape + output \9num ; + wire \9num = cyc[0]; + + output \bra[ket]slash/dash-colon:9 ; + wire \bra[ket]slash/dash-colon:9 = cyc[0]; + + wire \check_alias = cyc[0]; + wire \check:alias = cyc[0]; + wire \check;alias = !cyc[0]; + +`ifndef verilator + initial begin + $dumpfile("obj_dir/t_var_escape_dump.vcd"); + $dumpvars( 0, t ); + $dumpon; + end +`endif + + always @ (posedge clk) begin + cyc <= cyc + 1; + if (escaped_normal != cyc[0]) $stop; + if (\escaped_normal != cyc[0]) $stop; + if (double__underscore != cyc[0]) $stop; + if (\9num != cyc[0]) $stop; + if (\bra[ket]slash/dash-colon:9 != cyc[0]) $stop; + if (\check_alias != cyc[0]) $stop; + if (\check:alias != cyc[0]) $stop; + if (\check;alias != !cyc[0]) $stop; + + if (cyc==10) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + +endmodule