From 5fc236accc43bd1ca5f5b08fb5a78d5b07a948ec Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 25 May 2009 10:35:55 -0700 Subject: [PATCH 01/12] Use strchr() instead of index(). strchr() is more portable and index() is not available under MinGW so replace index() with strchr(). --- lexor.lex | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lexor.lex b/lexor.lex index ad0df6906..0b53eb5fd 100644 --- a/lexor.lex +++ b/lexor.lex @@ -481,6 +481,7 @@ S [afpnumkKMGT] NetNet::Type net_type; size_t wordlen = strcspn(yytext, " \t\f\r\n"); yytext[wordlen] = 0; + /* Add support for other wire types and better error detection. */ if (strcmp(yytext,"wire") == 0) { net_type = NetNet::WIRE; @@ -994,6 +995,7 @@ static void process_timescale(const char*txt) char*tmp; const char*ctmp; +// Add beetter error detection. Look at `line int unit = 0; int prec = 0; @@ -1101,7 +1103,7 @@ static void line_directive() { char *cpr; /* Skip any leading space. */ - char *cp = index(yytext, '#'); + char *cp = strchr(yytext, '#'); /* Skip the #line directive. */ assert(strncmp(cp, "#line", 5) == 0); cp += 5; @@ -1170,7 +1172,7 @@ static void line_directive2() { char *cpr; /* Skip any leading space. */ - char *cp = index(yytext, '`'); + char *cp = strchr(yytext, '`'); /* Skip the `line directive. */ assert(strncmp(cp, "`line", 5) == 0); cp += 5; From 62974224276530b415022911647d2892ee65fd85 Mon Sep 17 00:00:00 2001 From: Cary R Date: Tue, 26 May 2009 14:15:02 -0700 Subject: [PATCH 02/12] Rework the `timescale directive and cleanup `line a bit. This patch reworks the `timescale directive to do a better job of parsing the line, it refactors some of the code and should produce better error messages. It also tightens up parsing the numeric constant, etc. to better match the Verilog standard. The parsing of `line has been enhanced to only allow 0, 1 or 2 for the level and a single line comment at the end of the line is ignored. --- lexor.lex | 194 +++++++++++++++++++++++++++++------------------------- 1 file changed, 105 insertions(+), 89 deletions(-) diff --git a/lexor.lex b/lexor.lex index 0b53eb5fd..49c403405 100644 --- a/lexor.lex +++ b/lexor.lex @@ -983,6 +983,83 @@ static verinum*make_unsized_dec(const char*ptr) return res; } +/* + * Convert the string to a time unit or precision. + * Returns true on failure. + */ +static bool get_timescale_const(const char *&cp, int &res, bool is_unit) +{ + /* Check for the 1 digit. */ + if (*cp != '1') { + if (is_unit) { + VLerror(yylloc, "Invalid `timescale unit constant " + "(1st digit)"); + } else { + VLerror(yylloc, "Invalid `timescale precision constant " + "(1st digit)"); + } + return true; + } + cp += 1; + + /* Check the number of zeros after the 1. */ + res = strspn(cp, "0"); + if (res > 2) { + if (is_unit) { + VLerror(yylloc, "Invalid `timescale unit constant " + "(number of zeros)"); + } else { + VLerror(yylloc, "Invalid `timescale precision constant " + "(number of zeros)"); + } + return true; + } + cp += res; + + /* Skip any space between the digits and the scaling string. */ + cp += strspn(cp, " \t"); + + /* Now process the scaling string. */ + if (strncmp("s", cp, 1) == 0) { + res -= 0; + cp += 1; + return false; + + } else if (strncmp("ms", cp, 2) == 0) { + res -= 3; + cp += 2; + return false; + + } else if (strncmp("us", cp, 2) == 0) { + res -= 6; + cp += 2; + return false; + + } else if (strncmp("ns", cp, 2) == 0) { + res -= 9; + cp += 2; + return false; + + } else if (strncmp("ps", cp, 2) == 0) { + res -= 12; + cp += 2; + return false; + + } else if (strncmp("fs", cp, 2) == 0) { + res -= 15; + cp += 2; + return false; + + } + + if (is_unit) { + VLerror(yylloc, "Invalid `timescale unit scale"); + } else { + VLerror(yylloc, "Invalid `timescale precision scale"); + } + return true; +} + /* * The timescale parameter has the form: @@ -990,99 +1067,39 @@ static verinum*make_unsized_dec(const char*ptr) */ static void process_timescale(const char*txt) { - unsigned num; const char*cp = txt + strspn(txt, " \t"); - char*tmp; - const char*ctmp; -// Add beetter error detection. Look at `line + /* Skip the space after the `timescale directive. */ + if (cp == txt) { + VLerror(yylloc, "Space required after `timescale directive."); + return; + } + int unit = 0; int prec = 0; - num = strtoul(cp, &tmp, 10); - if (num == 0) { - VLerror(yylloc, "Invalid timescale string."); - return; - } + /* Get the time units. */ + if (get_timescale_const(cp, unit, true)) return; - while (num >= 10) { - unit += 1; - num /= 10; - } - if (num != 1) { - VLerror(yylloc, "Invalid timescale unit number."); - return; - } - - cp = tmp; + /* Skip any space after the time units, the '/' and any + * space after the '/'. */ cp += strspn(cp, " \t"); - ctmp = cp + strcspn(cp, " \t/"); - - if (strncmp("s", cp, ctmp-cp) == 0) { - unit -= 0; - - } else if (strncmp("ms", cp, ctmp-cp) == 0) { - unit -= 3; - - } else if (strncmp("us", cp, ctmp-cp) == 0) { - unit -= 6; - - } else if (strncmp("ns", cp, ctmp-cp) == 0) { - unit -= 9; - - } else if (strncmp("ps", cp, ctmp-cp) == 0) { - unit -= 12; - - } else if (strncmp("fs", cp, ctmp-cp) == 0) { - unit -= 15; - - } else { - VLerror(yylloc, "Invalid timescale unit of measurement"); + if (*cp != '/') { + VLerror(yylloc, "`timescale separator '/' appears to be missing."); return; } - - cp = ctmp; - cp += strspn(cp, " \t/"); - - num = strtoul(cp, &tmp, 10); - if (num == 0) { - VLerror(yylloc, "Invalid timescale string."); - return; - } - assert(num); - while (num >= 10) { - prec += 1; - num /= 10; - } - if (num != 1) { - VLerror(yylloc, "Invalid timescale precision number."); - return; - } - - cp = tmp; + cp += 1; cp += strspn(cp, " \t"); - ctmp = cp + strcspn(cp, " \t\r"); - if (strncmp("s", cp, ctmp-cp) == 0) { - prec -= 0; + /* Get the time precision. */ + if (get_timescale_const(cp, prec, false)) return; - } else if (strncmp("ms", cp, ctmp-cp) == 0) { - prec -= 3; - - } else if (strncmp("us", cp, ctmp-cp) == 0) { - prec -= 6; - - } else if (strncmp("ns", cp, ctmp-cp) == 0) { - prec -= 9; - - } else if (strncmp("ps", cp, ctmp-cp) == 0) { - prec -= 12; - - } else if (strncmp("fs", cp, ctmp-cp) == 0) { - prec -= 15; - - } else { - VLerror(yylloc, "Invalid timescale precision units of measurement"); + /* Verify that only space and/or a single line comment is left. */ + cp += strspn(cp, " \t"); + if (strncmp(cp, "//", 2) != 0 && + (size_t)(cp-yytext) != strlen(yytext)) { + VLerror(yylloc, "Invalid `timescale directive (extra garbage " + "after precision)."); return; } @@ -1211,8 +1228,7 @@ static void line_directive2() } /* Skip the space after the file name. */ - cp = fn_end; - cp += 1; + cp = fn_end + 1; cpr = cp; cpr += strspn(cp, " \t"); if (cp == cpr) { @@ -1223,16 +1239,16 @@ static void line_directive2() cp = cpr; /* Check that the level is correct, we do not need the level. */ - strtoul(cp, &cpr, 10); - if (cp == cpr) { + if (strspn(cp, "012") != 1) { VLerror(yylloc, "Invalid level for `line directive."); return; } - cp = cpr; + cp += 1; - /* Verify that only space is left. */ - cpr += strspn(cp, " \t"); - if ((size_t)(cpr-yytext) != strlen(yytext)) { + /* Verify that only space and/or a single line comment is left. */ + cp += strspn(cp, " \t"); + if (strncmp(cp, "//", 2) != 0 && + (size_t)(cp-yytext) != strlen(yytext)) { VLerror(yylloc, "Invalid `line directive (extra garbage after " "level)."); return; From 364cf99a672c7dbadf1e197e6cff84249d0c30cd Mon Sep 17 00:00:00 2001 From: Cary R Date: Tue, 26 May 2009 16:45:22 -0700 Subject: [PATCH 03/12] Add more default net types Previously Icarus only supported a default net type of wire or none. This patch adds the rest of the supported net types (all except uwire and trireg) to the `default_nettype directive. It also fixes make_implicit_net_() to use the default_nettype instead of always using implicit (the same as wire). --- elab_net.cc | 2 +- lexor.lex | 23 ++++++++++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/elab_net.cc b/elab_net.cc index 143674c6e..719173b69 100644 --- a/elab_net.cc +++ b/elab_net.cc @@ -179,7 +179,7 @@ NetNet* PEIdent::make_implicit_net_(Design*des, NetScope*scope) const assert(nettype != NetNet::NONE); NetNet*sig = new NetNet(scope, peek_tail_name(path_), - NetNet::IMPLICIT, 1); + nettype, 1); sig->set_line(*this); /* Implicit nets are always scalar logic. */ sig->data_type(IVL_VT_LOGIC); diff --git a/lexor.lex b/lexor.lex index 49c403405..1d991563e 100644 --- a/lexor.lex +++ b/lexor.lex @@ -485,13 +485,34 @@ S [afpnumkKMGT] if (strcmp(yytext,"wire") == 0) { net_type = NetNet::WIRE; + } else if (strcmp(yytext,"tri") == 0) { + net_type = NetNet::TRI; + + } else if (strcmp(yytext,"tri0") == 0) { + net_type = NetNet::TRI0; + + } else if (strcmp(yytext,"tri1") == 0) { + net_type = NetNet::TRI1; + + } else if (strcmp(yytext,"wand") == 0) { + net_type = NetNet::WAND; + + } else if (strcmp(yytext,"triand") == 0) { + net_type = NetNet::TRIAND; + + } else if (strcmp(yytext,"wor") == 0) { + net_type = NetNet::WOR; + + } else if (strcmp(yytext,"trior") == 0) { + net_type = NetNet::TRIOR; + } else if (strcmp(yytext,"none") == 0) { net_type = NetNet::NONE; } else { cerr << yylloc.text << ":" << yylloc.first_line << ": error: Net type " << yytext - << " is not a valid (and supported)" + << " is not a valid (or supported)" << " default net type." << endl; net_type = NetNet::WIRE; error_count += 1; From d06f6dfc516b5958da5d1501486fa219bebea2b5 Mon Sep 17 00:00:00 2001 From: Cary R Date: Wed, 27 May 2009 13:41:54 -0700 Subject: [PATCH 04/12] Add support for unconnected_drive. Icarus has recognized this directive, but it did not do anything with the information. This patch adds the functionality for most common cases. It adds this by changing the input net type from wire/tri to tri1 or tri0 depending on the pull. The issue is that if the input net is not a wire or tri this is not safe and should really be done as an external pull gate connected to the input. We will need to handle this is it ever comes up. For now a sorry message is printed. --- Module.cc | 1 + Module.h | 3 +++ elaborate.cc | 74 +++++++++++++++++++++++++++++++++++++++++----------- lexor.lex | 74 +++++++++++++++++++++++++++++++++++++++++++++++++--- parse.y | 15 ++++++++++- parse_misc.h | 2 ++ pform.cc | 4 ++- pform.h | 3 ++- 8 files changed, 155 insertions(+), 21 deletions(-) diff --git a/Module.cc b/Module.cc index e608a6401..774dfdbf7 100644 --- a/Module.cc +++ b/Module.cc @@ -30,6 +30,7 @@ Module::Module(perm_string n) { library_flag = false; is_cell = false; + uc_drive = UCD_NONE; default_nettype = NetNet::NONE; timescale_warn_done = false; } diff --git a/Module.h b/Module.h index a2960bc74..80d43031a 100644 --- a/Module.h +++ b/Module.h @@ -76,6 +76,9 @@ class Module : public PScope, public LineInfo { bool is_cell; + enum UCDriveType { UCD_NONE, UCD_PULL0, UCD_PULL1 }; + UCDriveType uc_drive; + NetNet::Type default_nettype; /* specparams are simpler then other params, in that they have diff --git a/elaborate.cc b/elaborate.cc index e5674c474..3dec83463 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -978,6 +978,28 @@ static bool need_bufz_for_input_port(const vector&prts) return false; } +/* + * Convert a wire or tri to a tri0 or tri1 as needed to make + * an unconnected drive pull for floating inputs. + */ +static void convert_net(Design*des, const LineInfo *line, + NetNet *net, NetNet::Type type) +{ + // If the types already match just return. + if (net->type() == type) return; + + // We can only covert a wire or tri to have a default pull. + if (net->type() == NetNet::WIRE || net->type() == NetNet::TRI) { + net->type(type); + return; + } + + // We may have to support this at some point in time! + cerr << line->get_fileline() << ": sorry: Can not pull floating " + "input type '" << net->type() << "'." << endl; + des->errors += 1; +} + /* * Instantiate a module by recursively elaborating it. Set the path of * the recursive elaboration so that signal names get properly @@ -1105,28 +1127,50 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const // null parameter is passed in. if (pins[idx] == 0) { + // We need this information to support the + // unconnected_drive directive and for a + // unconnected input warning when asked for. + vector mport = rmod->get_port(idx); + if (mport.size() == 0) continue; - // While we're here, look to see if this - // unconnected (from the outside) port is an - // input. If so, consider printing a port binding - // warning. - if (warn_portbinding) { - vector mport = rmod->get_port(idx); - if (mport.size() == 0) - continue; + perm_string pname = peek_tail_name(mport[0]->path()); - perm_string pname = peek_tail_name(mport[0]->path()); + NetNet*tmp = instance[0]->find_signal(pname); + assert(tmp); - NetNet*tmp = instance[0]->find_signal(pname); - assert(tmp); + if (tmp->port_type() == NetNet::PINPUT) { + // If we have an unconnected input convert it + // as needed if an unconnected_drive directive + // was given. This only works for tri or wire! + switch (rmod->uc_drive) { + case Module::UCD_PULL0: + convert_net(des, this, tmp, NetNet::TRI0); + break; + case Module::UCD_PULL1: + convert_net(des, this, tmp, NetNet::TRI1); + break; + case Module::UCD_NONE: + break; + } - if (tmp->port_type() == NetNet::PINPUT) { + // Print a waring for an unconnected input. + if (warn_portbinding) { cerr << get_fileline() << ": warning: " << "Instantiating module " << rmod->mod_name() - << " with dangling input port " - << rmod->ports[idx]->name - << "." << endl; + << " with dangling input port '" + << rmod->ports[idx]->name; + switch (rmod->uc_drive) { + case Module::UCD_PULL0: + cerr << "' (pulled low)." << endl; + break; + case Module::UCD_PULL1: + cerr << "' (pulled high)." << endl; + break; + case Module::UCD_NONE: + cerr << "' (floating)." << endl; + break; + } } } diff --git a/lexor.lex b/lexor.lex index 1d991563e..6f3aa2176 100644 --- a/lexor.lex +++ b/lexor.lex @@ -80,6 +80,7 @@ static verinum*make_unsized_hex(const char*txt); static int dec_buf_div2(char *buf); static void process_timescale(const char*txt); +static void process_ucdrive(const char*txt); static list keyword_mask_stack; @@ -87,6 +88,7 @@ static int comment_enter; static bool in_module = false; static bool in_UDP = false; bool in_celldefine = false; +UCDriveType uc_drive = UCD_NONE; %} %x CCOMMENT @@ -95,6 +97,7 @@ bool in_celldefine = false; %x CSTRING %s UDPTABLE %x PPTIMESCALE +%x PPUCDRIVE %x PPDEFAULT_NETTYPE %x PPBEGIN_KEYWORDS %s EDGES @@ -392,16 +395,36 @@ S [afpnumkKMGT] pform_set_default_nettype(NetNet::WIRE, yylloc.text, yylloc.first_line); in_celldefine = false; + uc_drive = UCD_NONE; pform_set_timescale(def_ts_units, def_ts_prec, 0, 0); - /* Add `nounconnected_drive when implemented. */ } } + /* Notice and handle the `unconnected_drive directive. */ +^{W}?`unconnected_drive { BEGIN(PPUCDRIVE); } +.* { process_ucdrive(yytext); } +\n { + if (in_module) { + cerr << yylloc.text << ":" << yylloc.first_line << ": error: " + "`unconnected_drive directive can not be inside a " + "module definition." << endl; + error_count += 1; + } + yylloc.first_line += 1; + BEGIN(0); } + +^{W}?`nounconnected_drive{W}? { + if (in_module) { + cerr << yylloc.text << ":" << yylloc.first_line << ": error: " + "`nounconnected_drive directive can not be inside a " + "module definition." << endl; + error_count += 1; + } + uc_drive = UCD_NONE; } + /* These are directives that I do not yet support. I think that IVL should handle these, not an external preprocessor. */ /* From 1364-2005 Chapter 19. */ -^{W}?`nounconnected_drive{W}?.* { } ^{W}?`pragme{W}?.* { } -^{W}?`unconnected_drive{W}?.* { } /* From 1364-2005 Annex D. */ ^{W}?`default_decay_time{W}?.* { } @@ -1082,6 +1105,51 @@ static bool get_timescale_const(const char *&cp, int &res, bool is_unit) } +/* + * process either a pull0 or a pull1. + */ +static void process_ucdrive(const char*txt) +{ + UCDriveType ucd = UCD_NONE; + const char*cp = txt + strspn(txt, " \t"); + + /* Skip the space after the `unconnected_drive directive. */ + if (cp == txt) { + VLerror(yylloc, "Space required after `unconnected_drive " + "directive."); + return; + } + + /* Check for the pull keyword. */ + if (strncmp("pull", cp, 4) != 0) { + VLerror(yylloc, "pull required for `unconnected_drive " + "directive."); + return; + } + cp += 4; + if (*cp == '0') ucd = UCD_PULL0; + else if (*cp == '1') ucd = UCD_PULL1; + else { + cerr << yylloc.text << ":" << yylloc.first_line << ": error: " + "`unconnected_drive does not support 'pull" << *cp + << "'." << endl; + error_count += 1; + return; + } + cp += 1; + + /* Verify that only space and/or a single line comment is left. */ + cp += strspn(cp, " \t"); + if (strncmp(cp, "//", 2) != 0 && + (size_t)(cp-yytext) != strlen(yytext)) { + VLerror(yylloc, "Invalid `unconnected_dirve directive (extra " + "garbage after precision)."); + return; + } + + uc_drive = ucd; +} + /* * The timescale parameter has the form: * " xs / xs" diff --git a/parse.y b/parse.y index e24d67bbc..ce7f66a70 100644 --- a/parse.y +++ b/parse.y @@ -1923,7 +1923,20 @@ module : attribute_list_opt module_start IDENTIFIER { pform_module_set_ports($6); } module_item_list_opt K_endmodule - { pform_endmodule($3, in_celldefine); + { Module::UCDriveType ucd; + switch (uc_drive) { + case UCD_NONE: + default: + ucd = Module::UCD_NONE; + break; + case UCD_PULL0: + ucd = Module::UCD_PULL0; + break; + case UCD_PULL1: + ucd = Module::UCD_PULL1; + break; + } + pform_endmodule($3, in_celldefine, ucd); delete[]$3; } diff --git a/parse_misc.h b/parse_misc.h index 6aa623a13..0a33c6999 100644 --- a/parse_misc.h +++ b/parse_misc.h @@ -66,5 +66,7 @@ extern unsigned error_count, warn_count; extern unsigned long based_size; extern bool in_celldefine; +enum UCDriveType { UCD_NONE, UCD_PULL0, UCD_PULL1 }; +extern UCDriveType uc_drive; #endif diff --git a/pform.cc b/pform.cc index 52dfed03c..69ca9de36 100644 --- a/pform.cc +++ b/pform.cc @@ -467,12 +467,14 @@ void pform_module_set_ports(vector*ports) } } -void pform_endmodule(const char*name, bool in_celldefine) +void pform_endmodule(const char*name, bool in_celldefine, + Module::UCDriveType uc_drive) { assert(pform_cur_module); perm_string mod_name = pform_cur_module->mod_name(); assert(strcmp(name, mod_name) == 0); pform_cur_module->is_cell = in_celldefine; + pform_cur_module->uc_drive = uc_drive; map::const_iterator test = pform_modules.find(mod_name); diff --git a/pform.h b/pform.h index 92166d41b..53e56f38e 100644 --- a/pform.h +++ b/pform.h @@ -159,7 +159,8 @@ extern void pform_module_define_port(const struct vlltype&li, extern Module::port_t* pform_module_port_reference(perm_string name, const char*file, unsigned lineno); -extern void pform_endmodule(const char*, bool in_celldefine); +extern void pform_endmodule(const char*, bool in_celldefine, + Module::UCDriveType uc_drive); extern void pform_make_udp(perm_string name, list*parms, svector*decl, list*table, From 80c21adb4aa428a21efc6cdf42db4e5b5e2b4c60 Mon Sep 17 00:00:00 2001 From: Cary R Date: Fri, 29 May 2009 14:57:04 -0700 Subject: [PATCH 05/12] Allow devel to parse a .scope statements with out the `celldefine info. This change allows us to test V0.9 files under V0.10.devel. --- vvp/parse.y | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/vvp/parse.y b/vvp/parse.y index 03cf2dccf..47e0d5e5b 100644 --- a/vvp/parse.y +++ b/vvp/parse.y @@ -580,6 +580,12 @@ statement T_NUMBER T_NUMBER T_NUMBER ',' T_SYMBOL ';' { compile_scope_decl($1, $3, $5, $6, $14, $7, $8, $10, $11, $12); } + /* Legacy declaration that does not have `celldefine information. */ + + | T_LABEL K_SCOPE T_SYMBOL ',' T_STRING T_STRING T_NUMBER T_NUMBER ',' + T_NUMBER T_NUMBER ',' T_SYMBOL ';' + { compile_scope_decl($1, $3, $5, $6, $13, $7, $8, $10, $11, 0); } + /* XXXX Legacy declaration has no type name. */ | T_LABEL K_SCOPE T_SYMBOL ',' T_STRING ';' From c842cdbdc4d5962993350e4cdbbf33d5b35dea43 Mon Sep 17 00:00:00 2001 From: nog Date: Sun, 31 May 2009 19:25:37 +0200 Subject: [PATCH 06/12] Avoid stepping on free'd memory during recursive macro expansion During macro expansion (with arguments), there is one global buffer (exp_buf) that keeps getting reallocated to fit all the macro's text that's currently being expanded. The problem with this scheme is that if a macro with arguments needs to be expanded from the macro text of another macro with arguments, it may happen that the second expansion forces the above exp_buf buffer to be reallocated. Which is fine until the previous macro processing resumes where (struct include_stack_t *)->str now points to uninitialised memory. Basically, the code that can trigger such behaviour is as follows: `define FOO(a) (a+3) `define BAR(b) (`FOO(b)+2) `BAR(x) Ofcourse, you need to get lucky to get the exp_buf to be realloced at the right point, but it's possible. I don't see the advantage in keeping all the expanding macro's text together, so my solution is to simply allocate a new buffer and pass it as (struct include_stack_t *)->str to the flex parsing function and free it at the end. --- ivlpp/lexor.lex | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/ivlpp/lexor.lex b/ivlpp/lexor.lex index 875e40050..e96ecf3e7 100644 --- a/ivlpp/lexor.lex +++ b/ivlpp/lexor.lex @@ -64,13 +64,8 @@ struct include_stack_t /* If we are reparsing a macro expansion, file is 0 and this * member points to the string in progress */ - const char* str; - - /* If we are reparsing a macro expansion, this member indicates - * the amount of space it occupies in the macro expansion buffer. - * This will be zero for macros without arguments. - */ - int ebs; + char* str; + char* orig_str; int stringify_flag; @@ -1372,6 +1367,7 @@ static void do_expand(int use_args) head = exp_buf_size - exp_buf_free; expand_using_args(); tail = exp_buf_size - exp_buf_free; + exp_buf_free += tail - head; if (tail == head) return; @@ -1384,12 +1380,10 @@ static void do_expand(int use_args) if (use_args) { isp->str = &exp_buf[head]; - isp->ebs = tail - head; } else { isp->str = cur_macro->value; - isp->ebs = 0; } /* Escape some characters if we are making a string version. */ @@ -1419,16 +1413,14 @@ static void do_expand(int use_args) } str_buf[idx] = 0; idx += 1; - if (use_args) exp_buf_free += isp->ebs; - exp_buf_grow_to_fit(idx); - head = exp_buf_size - exp_buf_free; - exp_buf_free -= idx; - strcpy(&exp_buf[head], str_buf); - isp->str = &exp_buf[head]; - isp->ebs = idx; - free(str_buf); - } + exp_buf_free -= idx; + + isp->str = str_buf; + } else + isp->str = strdup(isp->str); + + isp->orig_str = isp->str; isp->next = istack; istack->yybs = YY_CURRENT_BUFFER; istack = isp; @@ -1617,7 +1609,7 @@ static int load_next_input() else line_mask_flag = 1; - exp_buf_free += isp->ebs; + free(isp->orig_str); } if (isp->stringify_flag) { @@ -1794,7 +1786,6 @@ void reset_lexor(FILE* out, char* paths[]) isp->path = strdup(paths[0]); isp->file = fopen(paths[0], "r"); isp->str = 0; - isp->ebs = 0; isp->lineno = 0; isp->stringify_flag = 0; isp->comment = NULL; @@ -1824,7 +1815,6 @@ void reset_lexor(FILE* out, char* paths[]) isp->path = strdup(paths[idx]); isp->file = 0; isp->str = 0; - isp->ebs = 0; isp->next = 0; isp->lineno = 0; isp->stringify_flag = 0; From ca7e64afaf6426ca8874e37e21c77a61de87fdc8 Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 1 Jun 2009 17:19:56 -0700 Subject: [PATCH 07/12] Fix some keywords, add -g2001-noconfig and fix up uwire/wone. This patch adds -g2001-noconfig command line flag. The compiler already supported this with `begin_keywords. Document this in the manual page and fix a few other issues. Fix endgenerate to be a 2001 keyword and add a few missing keywords at the appropriate standard level e.g.(unsigned). Add uwire and deprecate wone. wone used to just convert without a warning to a wire. uwire will display a warning that it is being converted to a wire without a check. wone is converted to a uwire with a warning and then prints the uwire message. The uwire message will be replaced with a real check fairly soon. --- compiler.h | 7 +- driver/iverilog.man | 21 +-- driver/main.c | 3 + lexor_keyword.gperf | 336 +++++++++++++++++++++++--------------------- main.cc | 9 +- netlist.cc | 4 +- netlist.h | 2 +- parse.y | 84 ++++++----- t-dll.cc | 4 + 9 files changed, 264 insertions(+), 206 deletions(-) diff --git a/compiler.h b/compiler.h index e604e4da2..5ced0b0b0 100644 --- a/compiler.h +++ b/compiler.h @@ -113,9 +113,10 @@ extern int build_library_index(const char*path, bool key_case_sensitive); specific language features. */ enum generation_t { GN_VER1995 = 1, - GN_VER2001 = 2, - GN_VER2005 = 3, - GN_DEFAULT = 3 + GN_VER2001_NOCONFIG = 2, + GN_VER2001 = 3, + GN_VER2005 = 4, + GN_DEFAULT = 4 }; extern generation_t generation_flag; diff --git a/driver/iverilog.man b/driver/iverilog.man index a7a4f743e..e739aed2f 100644 --- a/driver/iverilog.man +++ b/driver/iverilog.man @@ -1,4 +1,4 @@ -.TH iverilog 1 "April 17th, 2009" "" "Version 0.10.devel" +.TH iverilog 1 "May 28th, 2009" "" "Version 0.10.devel" .SH NAME iverilog - Icarus Verilog compiler @@ -55,20 +55,20 @@ is the Verilog input, but with file inclusions and macro references expanded and removed. This is useful, for example, to preprocess Verilog source for use by other compilers. .TP 8 -.B -g1995\fI|\fP-g2001\fI|\fP-g2005 +.B -g1995\fI|\fP-g2001\fI|\fP-g2001-noconfig\fI|\fP-g2005 Select the Verilog language \fIgeneration\fP to support in the compiler. This selects between \fIIEEE1364-1995\fP, -\fIIEEE1364-2001\fP(2), or \fIIEEE1364-2005\fP. Normally, +\fIIEEE1364-2001\fP, or \fIIEEE1364-2005\fP. Normally, Icarus Verilog defaults to the latest known generation of the language. This flag is most useful to restrict the language to a set supported by tools of specific generations, for compatibility with other tools. .TP 8 -.B -gverilog-ams\fI|-fP-gno-verilog-ams +.B -gverilog-ams\fI|\fP-gno-verilog-ams Enable or disable (default) support for Verilog-AMS. Very little Verilog-AMS specific functionality is currently supported. .TP 8 -.B -gsystem-verilog\fI|-fP-gno-system-verilog +.B -gsystem-verilog\fI|\fP-gno-system-verilog Enable or disable (default) support for SystemVerilog. Very little SystemVerilog specific functionality is currently supported. .TP 8 @@ -115,9 +115,9 @@ expression changes value, the entire expression is re-evaluated. By default, parts of the expression that do not depend on the changed input value(s) are not re-evaluated. If an expression contains a call to a function that doesn't depend solely on its input values or that -has side effects, the resulting behaviour will differ from that +has side effects, the resulting behavior will differ from that required by the standard. Using \fI-gstrict-ca-eval\fP will force -standard compliant behaviour (with some loss in performance). +standard compliant behavior (with some loss in performance). .TP 8 .B -I\fIincludedir\fP Append directory \fIincludedir\fP to list of directories searched @@ -203,6 +203,11 @@ all the requested classes. Append the directory to the library module search path. When the compiler finds an undefined module, it looks in these directories for files with the right name. +.TP 8 +.B -Y\fIsuffix\fP +Add suffix to the list of accepted file name suffixes used when +searching a library for cells. The list defaults to the single +entry \fI.v\fP. .SH MODULE LIBRARIES @@ -448,7 +453,7 @@ Tips on using, debugging, and developing the compiler can be found at .SH COPYRIGHT .nf -Copyright \(co 2002-2008 Stephen Williams +Copyright \(co 2002-2009 Stephen Williams This document can be freely redistributed according to the terms of the GNU General Public License version 2.0 diff --git a/driver/main.c b/driver/main.c index 66e451397..bf322d77d 100644 --- a/driver/main.c +++ b/driver/main.c @@ -557,6 +557,9 @@ int process_generation(const char*name) else if (strcmp(name,"2001") == 0) generation = "2001"; + else if (strcmp(name,"2001-noconfig") == 0) + generation = "2001-noconfig"; + else if (strcmp(name,"2005") == 0) generation = "2005"; diff --git a/lexor_keyword.gperf b/lexor_keyword.gperf index c58be638f..5ba577a71 100644 --- a/lexor_keyword.gperf +++ b/lexor_keyword.gperf @@ -11,165 +11,183 @@ %} struct lexor_keyword { const char*name; int mask; int tokenType; }; %% -abs, GN_KEYWORDS_VAMS_2_3, K_abs -abstol, GN_KEYWORDS_VAMS_2_3, K_abstol -access, GN_KEYWORDS_VAMS_2_3, K_access -acos, GN_KEYWORDS_VAMS_2_3, K_acos -acosh, GN_KEYWORDS_VAMS_2_3, K_acosh -always, GN_KEYWORDS_1364_1995, K_always -always_comb, GN_KEYWORDS_1800_2005, K_always_comb -always_ff, GN_KEYWORDS_1800_2005, K_always_ff -always_latch, GN_KEYWORDS_1800_2005, K_always_latch -analog, GN_KEYWORDS_VAMS_2_3, K_analog -and, GN_KEYWORDS_1364_1995, K_and -asin, GN_KEYWORDS_VAMS_2_3, K_asin -asinh, GN_KEYWORDS_VAMS_2_3, K_asinh -assert, GN_KEYWORDS_1800_2005, K_assert -assign, GN_KEYWORDS_1364_1995, K_assign -atan, GN_KEYWORDS_VAMS_2_3, K_atan -atan2, GN_KEYWORDS_VAMS_2_3, K_atan2 -atanh, GN_KEYWORDS_VAMS_2_3, K_atanh -automatic, GN_KEYWORDS_1364_2001, K_automatic -begin, GN_KEYWORDS_1364_1995, K_begin -bool, GN_KEYWORDS_ICARUS, K_bool -buf, GN_KEYWORDS_1364_1995, K_buf -bufif0, GN_KEYWORDS_1364_1995, K_bufif0 -bufif1, GN_KEYWORDS_1364_1995, K_bufif1 -case, GN_KEYWORDS_1364_1995, K_case -casex, GN_KEYWORDS_1364_1995, K_casex -casez, GN_KEYWORDS_1364_1995, K_casez -ceil, GN_KEYWORDS_VAMS_2_3, K_ceil -cmos, GN_KEYWORDS_1364_1995, K_cmos -continuous, GN_KEYWORDS_VAMS_2_3, K_continuous -cos, GN_KEYWORDS_VAMS_2_3, K_cos -cosh, GN_KEYWORDS_VAMS_2_3, K_cosh -ddt_nature, GN_KEYWORDS_VAMS_2_3, K_ddt_nature -deassign, GN_KEYWORDS_1364_1995, K_deassign -default, GN_KEYWORDS_1364_1995, K_default -defparam, GN_KEYWORDS_1364_1995, K_defparam -disable, GN_KEYWORDS_1364_1995, K_disable -discipline, GN_KEYWORDS_VAMS_2_3, K_discipline -discrete, GN_KEYWORDS_VAMS_2_3, K_discrete -domain, GN_KEYWORDS_VAMS_2_3, K_domain -edge, GN_KEYWORDS_1364_1995, K_edge -else, GN_KEYWORDS_1364_1995, K_else -end, GN_KEYWORDS_1364_1995, K_end -endcase, GN_KEYWORDS_1364_1995, K_endcase -enddiscipline, GN_KEYWORDS_VAMS_2_3, K_enddiscipline -endfunction, GN_KEYWORDS_1364_1995, K_endfunction -endgenerate, GN_KEYWORDS_1364_1995, K_endgenerate -endmodule, GN_KEYWORDS_1364_1995, K_endmodule -endnature, GN_KEYWORDS_VAMS_2_3, K_endnature -endprimitive, GN_KEYWORDS_1364_1995, K_endprimitive -endspecify, GN_KEYWORDS_1364_1995, K_endspecify -endtable, GN_KEYWORDS_1364_1995, K_endtable -endtask, GN_KEYWORDS_1364_1995, K_endtask -event, GN_KEYWORDS_1364_1995, K_event -exclude, GN_KEYWORDS_VAMS_2_3, K_exclude -exp, GN_KEYWORDS_VAMS_2_3, K_exp -floor, GN_KEYWORDS_VAMS_2_3, K_floor -flow, GN_KEYWORDS_VAMS_2_3, K_flow -for, GN_KEYWORDS_1364_1995, K_for -force, GN_KEYWORDS_1364_1995, K_force -forever, GN_KEYWORDS_1364_1995, K_forever -fork, GN_KEYWORDS_1364_1995, K_fork -from, GN_KEYWORDS_VAMS_2_3, K_from -function, GN_KEYWORDS_1364_1995, K_function -generate, GN_KEYWORDS_1364_2001, K_generate -genvar, GN_KEYWORDS_1364_2001, K_genvar -ground, GN_KEYWORDS_VAMS_2_3, K_ground -highz0, GN_KEYWORDS_1364_1995, K_highz0 -highz1, GN_KEYWORDS_1364_1995, K_highz1 -hypot, GN_KEYWORDS_VAMS_2_3, K_hypot -idt_nature, GN_KEYWORDS_VAMS_2_3, K_idt_nature -if, GN_KEYWORDS_1364_1995, K_if -ifnone, GN_KEYWORDS_1364_1995, K_ifnone -inf, GN_KEYWORDS_VAMS_2_3, K_inf -initial, GN_KEYWORDS_1364_1995, K_initial -inout, GN_KEYWORDS_1364_1995, K_inout -input, GN_KEYWORDS_1364_1995, K_input -integer, GN_KEYWORDS_1364_1995, K_integer -join, GN_KEYWORDS_1364_1995, K_join -large, GN_KEYWORDS_1364_1995, K_large -ln, GN_KEYWORDS_VAMS_2_3, K_ln -localparam, GN_KEYWORDS_1364_2001, K_localparam -log, GN_KEYWORDS_VAMS_2_3, K_log -logic, GN_KEYWORDS_ICARUS, K_logic -macromodule, GN_KEYWORDS_1364_1995, K_macromodule -max, GN_KEYWORDS_VAMS_2_3, K_max -medium, GN_KEYWORDS_1364_1995, K_medium -min, GN_KEYWORDS_VAMS_2_3, K_min -module, GN_KEYWORDS_1364_1995, K_module -nand, GN_KEYWORDS_1364_1995, K_nand -nature, GN_KEYWORDS_VAMS_2_3, K_nature -negedge, GN_KEYWORDS_1364_1995, K_negedge -nmos, GN_KEYWORDS_1364_1995, K_nmos -nor, GN_KEYWORDS_1364_1995, K_nor -not, GN_KEYWORDS_1364_1995, K_not -notif0, GN_KEYWORDS_1364_1995, K_notif0 -notif1, GN_KEYWORDS_1364_1995, K_notif1 -or, GN_KEYWORDS_1364_1995, K_or -output, GN_KEYWORDS_1364_1995, K_output -parameter, GN_KEYWORDS_1364_1995, K_parameter -pmos, GN_KEYWORDS_1364_1995, K_pmos -posedge, GN_KEYWORDS_1364_1995, K_posedge -potential, GN_KEYWORDS_VAMS_2_3, K_potential -pow, GN_KEYWORDS_VAMS_2_3, K_pow -primitive, GN_KEYWORDS_1364_1995, K_primitive -pull0, GN_KEYWORDS_1364_1995, K_pull0 -pull1, GN_KEYWORDS_1364_1995, K_pull1 -pulldown, GN_KEYWORDS_1364_1995, K_pulldown -pullup, GN_KEYWORDS_1364_1995, K_pullup -rcmos, GN_KEYWORDS_1364_1995, K_rcmos -real, GN_KEYWORDS_1364_1995, K_real -realtime, GN_KEYWORDS_1364_1995, K_realtime -reg, GN_KEYWORDS_1364_1995, K_reg -release, GN_KEYWORDS_1364_1995, K_release -repeat, GN_KEYWORDS_1364_1995, K_repeat -rnmos, GN_KEYWORDS_1364_1995, K_rnmos -rpmos, GN_KEYWORDS_1364_1995, K_rpmos -rtran, GN_KEYWORDS_1364_1995, K_rtran -rtranif0, GN_KEYWORDS_1364_1995, K_rtranif0 -rtranif1, GN_KEYWORDS_1364_1995, K_rtranif1 -scalared, GN_KEYWORDS_1364_1995, K_scalared -signed, GN_KEYWORDS_1364_2001, K_signed -sin, GN_KEYWORDS_VAMS_2_3, K_sin -sinh, GN_KEYWORDS_VAMS_2_3, K_sinh -small, GN_KEYWORDS_1364_1995, K_small -specify, GN_KEYWORDS_1364_1995, K_specify -specparam, GN_KEYWORDS_1364_1995, K_specparam -sqrt, GN_KEYWORDS_VAMS_2_3, K_sqrt -string, GN_KEYWORDS_VAMS_2_3, K_string -strong0, GN_KEYWORDS_1364_1995, K_strong0 -strong1, GN_KEYWORDS_1364_1995, K_strong1 -supply0, GN_KEYWORDS_1364_1995, K_supply0 -supply1, GN_KEYWORDS_1364_1995, K_supply1 -table, GN_KEYWORDS_1364_1995, K_table -tan, GN_KEYWORDS_VAMS_2_3, K_tan -tanh, GN_KEYWORDS_VAMS_2_3, K_tanh -task, GN_KEYWORDS_1364_1995, K_task -time, GN_KEYWORDS_1364_1995, K_time -tran, GN_KEYWORDS_1364_1995, K_tran -tranif0, GN_KEYWORDS_1364_1995, K_tranif0 -tranif1, GN_KEYWORDS_1364_1995, K_tranif1 -tri, GN_KEYWORDS_1364_1995, K_tri -tri0, GN_KEYWORDS_1364_1995, K_tri0 -tri1, GN_KEYWORDS_1364_1995, K_tri1 -triand, GN_KEYWORDS_1364_1995, K_triand -trior, GN_KEYWORDS_1364_1995, K_trior -trireg, GN_KEYWORDS_1364_1995, K_trireg -units, GN_KEYWORDS_VAMS_2_3, K_units -vectored, GN_KEYWORDS_1364_1995, K_vectored -wait, GN_KEYWORDS_1364_1995, K_wait -wand, GN_KEYWORDS_1364_1995, K_wand -weak0, GN_KEYWORDS_1364_1995, K_weak0 -weak1, GN_KEYWORDS_1364_1995, K_weak1 -while, GN_KEYWORDS_1364_1995, K_while -wire, GN_KEYWORDS_1364_1995, K_wire -wone, GN_KEYWORDS_1364_1995, K_wone -wor, GN_KEYWORDS_1364_1995, K_wor -xnor, GN_KEYWORDS_1364_1995, K_xnor -xor, GN_KEYWORDS_1364_1995, K_xor +abs, GN_KEYWORDS_VAMS_2_3, K_abs +abstol, GN_KEYWORDS_VAMS_2_3, K_abstol +access, GN_KEYWORDS_VAMS_2_3, K_access +acos, GN_KEYWORDS_VAMS_2_3, K_acos +acosh, GN_KEYWORDS_VAMS_2_3, K_acosh +always, GN_KEYWORDS_1364_1995, K_always +always_comb, GN_KEYWORDS_1800_2005, K_always_comb +always_ff, GN_KEYWORDS_1800_2005, K_always_ff +always_latch, GN_KEYWORDS_1800_2005, K_always_latch +analog, GN_KEYWORDS_VAMS_2_3, K_analog +and, GN_KEYWORDS_1364_1995, K_and +asin, GN_KEYWORDS_VAMS_2_3, K_asin +asinh, GN_KEYWORDS_VAMS_2_3, K_asinh +assert, GN_KEYWORDS_1800_2005, K_assert +assign, GN_KEYWORDS_1364_1995, K_assign +atan, GN_KEYWORDS_VAMS_2_3, K_atan +atan2, GN_KEYWORDS_VAMS_2_3, K_atan2 +atanh, GN_KEYWORDS_VAMS_2_3, K_atanh +automatic, GN_KEYWORDS_1364_2001, K_automatic +begin, GN_KEYWORDS_1364_1995, K_begin +bool, GN_KEYWORDS_ICARUS, K_bool +buf, GN_KEYWORDS_1364_1995, K_buf +bufif0, GN_KEYWORDS_1364_1995, K_bufif0 +bufif1, GN_KEYWORDS_1364_1995, K_bufif1 +case, GN_KEYWORDS_1364_1995, K_case +casex, GN_KEYWORDS_1364_1995, K_casex +casez, GN_KEYWORDS_1364_1995, K_casez +ceil, GN_KEYWORDS_VAMS_2_3, K_ceil +cell, GN_KEYWORDS_1364_2001_CONFIG, K_cell +cmos, GN_KEYWORDS_1364_1995, K_cmos +config, GN_KEYWORDS_1364_2001_CONFIG, K_config +continuous, GN_KEYWORDS_VAMS_2_3, K_continuous +cos, GN_KEYWORDS_VAMS_2_3, K_cos +cosh, GN_KEYWORDS_VAMS_2_3, K_cosh +ddt_nature, GN_KEYWORDS_VAMS_2_3, K_ddt_nature +deassign, GN_KEYWORDS_1364_1995, K_deassign +default, GN_KEYWORDS_1364_1995, K_default +defparam, GN_KEYWORDS_1364_1995, K_defparam +design, GN_KEYWORDS_1364_2001_CONFIG, K_design +disable, GN_KEYWORDS_1364_1995, K_disable +discipline, GN_KEYWORDS_VAMS_2_3, K_discipline +discrete, GN_KEYWORDS_VAMS_2_3, K_discrete +domain, GN_KEYWORDS_VAMS_2_3, K_domain +edge, GN_KEYWORDS_1364_1995, K_edge +else, GN_KEYWORDS_1364_1995, K_else +end, GN_KEYWORDS_1364_1995, K_end +endcase, GN_KEYWORDS_1364_1995, K_endcase +endconfig, GN_KEYWORDS_1364_2001_CONFIG, K_endconfig +enddiscipline, GN_KEYWORDS_VAMS_2_3, K_enddiscipline +endfunction, GN_KEYWORDS_1364_1995, K_endfunction +endgenerate, GN_KEYWORDS_1364_2001, K_endgenerate +endmodule, GN_KEYWORDS_1364_1995, K_endmodule +endnature, GN_KEYWORDS_VAMS_2_3, K_endnature +endprimitive, GN_KEYWORDS_1364_1995, K_endprimitive +endspecify, GN_KEYWORDS_1364_1995, K_endspecify +endtable, GN_KEYWORDS_1364_1995, K_endtable +endtask, GN_KEYWORDS_1364_1995, K_endtask +event, GN_KEYWORDS_1364_1995, K_event +exclude, GN_KEYWORDS_VAMS_2_3, K_exclude +exp, GN_KEYWORDS_VAMS_2_3, K_exp +floor, GN_KEYWORDS_VAMS_2_3, K_floor +flow, GN_KEYWORDS_VAMS_2_3, K_flow +for, GN_KEYWORDS_1364_1995, K_for +force, GN_KEYWORDS_1364_1995, K_force +forever, GN_KEYWORDS_1364_1995, K_forever +fork, GN_KEYWORDS_1364_1995, K_fork +from, GN_KEYWORDS_VAMS_2_3, K_from +function, GN_KEYWORDS_1364_1995, K_function +generate, GN_KEYWORDS_1364_2001, K_generate +genvar, GN_KEYWORDS_1364_2001, K_genvar +ground, GN_KEYWORDS_VAMS_2_3, K_ground +highz0, GN_KEYWORDS_1364_1995, K_highz0 +highz1, GN_KEYWORDS_1364_1995, K_highz1 +hypot, GN_KEYWORDS_VAMS_2_3, K_hypot +idt_nature, GN_KEYWORDS_VAMS_2_3, K_idt_nature +if, GN_KEYWORDS_1364_1995, K_if +ifnone, GN_KEYWORDS_1364_1995, K_ifnone +incdir, GN_KEYWORDS_1364_2001_CONFIG, K_incdir +include, GN_KEYWORDS_1364_2001_CONFIG, K_include +inf, GN_KEYWORDS_VAMS_2_3, K_inf +initial, GN_KEYWORDS_1364_1995, K_initial +inout, GN_KEYWORDS_1364_1995, K_inout +input, GN_KEYWORDS_1364_1995, K_input +instance, GN_KEYWORDS_1364_2001_CONFIG, K_instance +integer, GN_KEYWORDS_1364_1995, K_integer +join, GN_KEYWORDS_1364_1995, K_join +large, GN_KEYWORDS_1364_1995, K_large +liblist, GN_KEYWORDS_1364_2001_CONFIG, K_liblist +library, GN_KEYWORDS_1364_2001_CONFIG, K_library +ln, GN_KEYWORDS_VAMS_2_3, K_ln +localparam, GN_KEYWORDS_1364_2001, K_localparam +log, GN_KEYWORDS_VAMS_2_3, K_log +logic, GN_KEYWORDS_ICARUS, K_logic +macromodule, GN_KEYWORDS_1364_1995, K_macromodule +max, GN_KEYWORDS_VAMS_2_3, K_max +medium, GN_KEYWORDS_1364_1995, K_medium +min, GN_KEYWORDS_VAMS_2_3, K_min +module, GN_KEYWORDS_1364_1995, K_module +nand, GN_KEYWORDS_1364_1995, K_nand +nature, GN_KEYWORDS_VAMS_2_3, K_nature +negedge, GN_KEYWORDS_1364_1995, K_negedge +nmos, GN_KEYWORDS_1364_1995, K_nmos +nor, GN_KEYWORDS_1364_1995, K_nor +noshowcancelled, GN_KEYWORDS_1364_2001, K_noshowcancelled +not, GN_KEYWORDS_1364_1995, K_not +notif0, GN_KEYWORDS_1364_1995, K_notif0 +notif1, GN_KEYWORDS_1364_1995, K_notif1 +or, GN_KEYWORDS_1364_1995, K_or +output, GN_KEYWORDS_1364_1995, K_output +parameter, GN_KEYWORDS_1364_1995, K_parameter +pmos, GN_KEYWORDS_1364_1995, K_pmos +posedge, GN_KEYWORDS_1364_1995, K_posedge +potential, GN_KEYWORDS_VAMS_2_3, K_potential +pow, GN_KEYWORDS_VAMS_2_3, K_pow +primitive, GN_KEYWORDS_1364_1995, K_primitive +pull0, GN_KEYWORDS_1364_1995, K_pull0 +pull1, GN_KEYWORDS_1364_1995, K_pull1 +pulldown, GN_KEYWORDS_1364_1995, K_pulldown +pullup, GN_KEYWORDS_1364_1995, K_pullup +pulsestyle_onevent, GN_KEYWORDS_1364_2001, K_pulsestyle_onevent +pulsestyle_ondetect, GN_KEYWORDS_1364_2001, K_pulsestyle_ondetect +rcmos, GN_KEYWORDS_1364_1995, K_rcmos +real, GN_KEYWORDS_1364_1995, K_real +realtime, GN_KEYWORDS_1364_1995, K_realtime +reg, GN_KEYWORDS_1364_1995, K_reg +release, GN_KEYWORDS_1364_1995, K_release +repeat, GN_KEYWORDS_1364_1995, K_repeat +rnmos, GN_KEYWORDS_1364_1995, K_rnmos +rpmos, GN_KEYWORDS_1364_1995, K_rpmos +rtran, GN_KEYWORDS_1364_1995, K_rtran +rtranif0, GN_KEYWORDS_1364_1995, K_rtranif0 +rtranif1, GN_KEYWORDS_1364_1995, K_rtranif1 +scalared, GN_KEYWORDS_1364_1995, K_scalared +showcancelled, GN_KEYWORDS_1364_2001, K_showcancelled +signed, GN_KEYWORDS_1364_2001, K_signed +sin, GN_KEYWORDS_VAMS_2_3, K_sin +sinh, GN_KEYWORDS_VAMS_2_3, K_sinh +small, GN_KEYWORDS_1364_1995, K_small +specify, GN_KEYWORDS_1364_1995, K_specify +specparam, GN_KEYWORDS_1364_1995, K_specparam +sqrt, GN_KEYWORDS_VAMS_2_3, K_sqrt +string, GN_KEYWORDS_VAMS_2_3, K_string +strong0, GN_KEYWORDS_1364_1995, K_strong0 +strong1, GN_KEYWORDS_1364_1995, K_strong1 +supply0, GN_KEYWORDS_1364_1995, K_supply0 +supply1, GN_KEYWORDS_1364_1995, K_supply1 +table, GN_KEYWORDS_1364_1995, K_table +tan, GN_KEYWORDS_VAMS_2_3, K_tan +tanh, GN_KEYWORDS_VAMS_2_3, K_tanh +task, GN_KEYWORDS_1364_1995, K_task +time, GN_KEYWORDS_1364_1995, K_time +tran, GN_KEYWORDS_1364_1995, K_tran +tranif0, GN_KEYWORDS_1364_1995, K_tranif0 +tranif1, GN_KEYWORDS_1364_1995, K_tranif1 +tri, GN_KEYWORDS_1364_1995, K_tri +tri0, GN_KEYWORDS_1364_1995, K_tri0 +tri1, GN_KEYWORDS_1364_1995, K_tri1 +triand, GN_KEYWORDS_1364_1995, K_triand +trior, GN_KEYWORDS_1364_1995, K_trior +trireg, GN_KEYWORDS_1364_1995, K_trireg +units, GN_KEYWORDS_VAMS_2_3, K_units +# Reserved for future use! +unsigned, GN_KEYWORDS_1364_2001, K_unsigned +use, GN_KEYWORDS_1364_2001_CONFIG, K_use +uwire, GN_KEYWORDS_1364_2005, K_uwire +vectored, GN_KEYWORDS_1364_1995, K_vectored +wait, GN_KEYWORDS_1364_1995, K_wait +wand, GN_KEYWORDS_1364_1995, K_wand +weak0, GN_KEYWORDS_1364_1995, K_weak0 +weak1, GN_KEYWORDS_1364_1995, K_weak1 +while, GN_KEYWORDS_1364_1995, K_while +wire, GN_KEYWORDS_1364_1995, K_wire +# This is the name originally proposed for uwire and is deprecated! +wone, GN_KEYWORDS_1364_2005, K_wone +wor, GN_KEYWORDS_1364_1995, K_wor +xnor, GN_KEYWORDS_1364_1995, K_xnor +xor, GN_KEYWORDS_1364_1995, K_xor %% int lexor_keyword_mask = 0; diff --git a/main.cc b/main.cc index b3f1201c0..ad4de617a 100644 --- a/main.cc +++ b/main.cc @@ -224,6 +224,9 @@ static void process_generation_flag(const char*gen) } else if (strcmp(gen,"2001") == 0) { generation_flag = GN_VER2001; + } else if (strcmp(gen,"2001-noconfig") == 0) { + generation_flag = GN_VER2001_NOCONFIG; + } else if (strcmp(gen,"2005") == 0) { generation_flag = GN_VER2005; @@ -660,9 +663,10 @@ int main(int argc, char*argv[]) lexor_keyword_mask |= GN_KEYWORDS_1364_1995; break; case GN_VER2001: + lexor_keyword_mask |= GN_KEYWORDS_1364_2001_CONFIG; + case GN_VER2001_NOCONFIG: lexor_keyword_mask |= GN_KEYWORDS_1364_1995; lexor_keyword_mask |= GN_KEYWORDS_1364_2001; - lexor_keyword_mask |= GN_KEYWORDS_1364_2001_CONFIG; break; case GN_VER2005: lexor_keyword_mask |= GN_KEYWORDS_1364_1995; @@ -690,6 +694,9 @@ int main(int argc, char*argv[]) case GN_VER1995: cout << "IEEE1364-1995"; break; + case GN_VER2001_NOCONFIG: + cout << "IEEE1364-2001-noconfig"; + break; case GN_VER2001: cout << "IEEE1364-2001"; break; diff --git a/netlist.cc b/netlist.cc index 4a69c5e80..8f2940316 100644 --- a/netlist.cc +++ b/netlist.cc @@ -78,8 +78,8 @@ ostream& operator<< (ostream&o, NetNet::Type t) case NetNet::WIRE: o << "wire"; break; - case NetNet::WONE: - o << "wone"; + case NetNet::UWIRE: + o << "uwire"; } return o; } diff --git a/netlist.h b/netlist.h index 387adffc8..05c57ebfd 100644 --- a/netlist.h +++ b/netlist.h @@ -542,7 +542,7 @@ class NetNet : public NetObj { public: enum Type { NONE, IMPLICIT, IMPLICIT_REG, INTEGER, WIRE, TRI, TRI1, SUPPLY0, SUPPLY1, WAND, TRIAND, TRI0, WOR, TRIOR, REG, - WONE }; + UWIRE }; enum PortType { NOT_A_PORT, PIMPLICIT, PINPUT, POUTPUT, PINOUT }; diff --git a/parse.y b/parse.y index ce7f66a70..c533b03ac 100644 --- a/parse.y +++ b/parse.y @@ -229,40 +229,55 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2) %token K_PO_POS K_PO_NEG K_POW %token K_PSTAR K_STARP %token K_LOR K_LAND K_NAND K_NOR K_NXOR K_TRIGGER -%token K_abs K_abstol K_access K_acos K_acosh K_asin K_analog K_asinh -%token K_atan K_atanh K_atan2 K_automatic -%token K_always K_and K_assign K_begin K_bool K_buf K_bufif0 K_bufif1 K_case -%token K_casex K_casez K_ceil K_cmos K_continuous K_cos K_cosh -%token K_ddt_nature K_deassign K_default K_defparam K_disable K_discrete -%token K_domain K_edge K_edge_descriptor K_discipline -%token K_else K_end K_endcase K_enddiscipline K_endfunction K_endgenerate -%token K_endmodule K_endnature -%token K_endprimitive K_endspecify K_endtable K_endtask K_event -%token K_exclude K_exp K_floor K_flow K_from -%token K_for K_force K_forever K_fork K_function K_generate K_genvar -%token K_ground K_highz0 K_highz1 K_hypot K_idt_nature K_if K_ifnone K_inf -%token K_initial K_inout K_input K_integer K_join K_large K_ln K_localparam -%token K_log K_logic K_macromodule K_max -%token K_medium K_min K_module K_nand K_nature K_negedge -%token K_nmos K_nor K_not K_notif0 -%token K_notif1 K_or K_output K_parameter K_pmos K_posedge K_potential -%token K_pow K_primitive -%token K_pull0 K_pull1 K_pulldown K_pullup K_rcmos K_real K_realtime -%token K_reg K_release K_repeat -%token K_rnmos K_rpmos K_rtran K_rtranif0 K_rtranif1 K_scalared -%token K_signed K_sin K_sinh K_small K_specify -%token K_specparam K_sqrt K_string K_strong0 K_strong1 K_supply0 K_supply1 -%token K_table -%token K_tan K_tanh K_task -%token K_time K_tran K_tranif0 K_tranif1 K_tri K_tri0 K_tri1 K_triand -%token K_trior K_trireg K_units K_vectored K_wait K_wand K_weak0 K_weak1 -%token K_while K_wire -%token K_wone K_wor K_xnor K_xor -%token K_Shold K_Speriod K_Srecovery K_Srecrem K_Ssetup K_Swidth K_Ssetuphold +%token K_edge_descriptor + /* The base tokens from 1364-1995. */ +%token K_always K_and K_assign K_begin K_buf K_bufif0 K_bufif1 K_case +%token K_casex K_casez K_cmos K_deassign K_default K_defparam K_disable +%token K_edge K_else K_end K_endcase K_endfunction K_endmodule +%token K_endprimitive K_endspecify K_endtable K_endtask K_event K_for +%token K_force K_forever K_fork K_function K_highz0 K_highz1 K_if +%token K_ifnone K_initial K_inout K_input K_integer K_join K_large +%token K_macromodule K_medium K_module K_nand K_negedge K_nmos K_nor +%token K_not K_notif0 K_notif1 K_or K_output K_parameter K_pmos K_posedge +%token K_primitive K_pull0 K_pull1 K_pulldown K_pullup K_rcmos K_real +%token K_realtime K_reg K_release K_repeat K_rnmos K_rpmos K_rtran +%token K_rtranif0 K_rtranif1 K_scalared K_small K_specify K_specparam +%token K_strong0 K_strong1 K_supply0 K_supply1 K_table K_task K_time +%token K_tran K_tranif0 K_tranif1 K_tri K_tri0 K_tri1 K_triand K_trior +%token K_trireg K_vectored K_wait K_wand K_weak0 K_weak1 K_while K_wire +%token K_wor K_xnor K_xor + +%token K_Shold K_Speriod K_Srecovery K_Ssetup K_Swidth K_Ssetuphold + + /* Icarus specific tokens. */ +%token KK_attribute K_bool K_logic + + /* The new tokens from 1364-2001. */ +%token K_automatic K_endgenerate K_generate K_genvar K_localparam +%token K_noshowcancelled K_pulsestyle_onevent K_pulsestyle_ondetect +%token K_showcancelled K_signed K_unsigned + +%token K_Srecrem + + /* The 1364-2001 configuration tokens. */ +%token K_cell K_config K_design K_endconfig K_incdir K_include K_instance +%token K_liblist K_library K_use + + /* The new tokens from 1364-2005. */ +%token K_wone K_uwire + + /* The new tokens from 1800-2005. */ %token K_always_comb K_always_ff K_always_latch K_assert -%token KK_attribute + /* The new tokens for Verilog-AMS 2.3. */ +%token K_abs K_abstol K_access K_acos K_acosh K_analog K_asin K_asinh +%token K_atan K_atan2 K_atanh K_ceil K_continuous K_cos K_cosh +%token K_ddt_nature K_discipline K_discrete K_domain K_enddiscipline +%token K_endnature K_exclude K_exp K_floor K_flow K_from K_ground +%token K_hypot K_idt_nature K_inf K_ln K_log K_max K_min K_nature +%token K_potential K_pow K_sin K_sinh K_sqrt K_string K_tan K_tanh +%token K_units %type from_exclude %type number @@ -2494,7 +2509,12 @@ net_type | K_supply1 { $$ = NetNet::SUPPLY1; } | K_wor { $$ = NetNet::WOR; } | K_trior { $$ = NetNet::TRIOR; } - | K_wone { $$ = NetNet::WONE; } + | K_wone { $$ = NetNet::UWIRE; + cerr << @1.text << ":" << @1.first_line << ": warning: " + "'wone' is deprecated, please use 'uwire' " + "instead." << endl; + } + | K_uwire { $$ = NetNet::UWIRE; } ; var_type diff --git a/t-dll.cc b/t-dll.cc index f1b18f857..1e9a28602 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -2511,6 +2511,10 @@ void dll_target::signal(const NetNet*net) assert(0); break; + case NetNet::UWIRE: + cerr << net->get_fileline() + << ": warning: uwire is not currently supported, converting " + "it to a wire!" << endl; case NetNet::TRI: case NetNet::WIRE: case NetNet::IMPLICIT: From 4479471278322b12121f3dc1fe9b1449d3977885 Mon Sep 17 00:00:00 2001 From: Cary R Date: Wed, 3 Jun 2009 15:02:32 -0700 Subject: [PATCH 08/12] Parse all the 1364-1995 and 1364-2001 timing checks. This patch adds code to parse and ignore the following timing checks: $nochange 1364-1995 $skew 1364-1995 $fullskew 1364-2001 $removal 1364-2001 $timeskew 1364-2001 The other checks were already supported. These have not been tested, but they use the same basic terms as the other checks. We can fully test these when we actually implement them. --- lexor.lex | 25 +++++++++++++++++++------ parse.y | 33 ++++++++++++++++++++++++++++----- 2 files changed, 47 insertions(+), 11 deletions(-) diff --git a/lexor.lex b/lexor.lex index 6f3aa2176..d62325d87 100644 --- a/lexor.lex +++ b/lexor.lex @@ -274,22 +274,35 @@ S [afpnumkKMGT] return IDENTIFIER; } \$([a-zA-Z0-9$_]+) { - if (strcmp(yytext,"$setuphold") == 0) - return K_Ssetuphold; - if (strcmp(yytext,"$attribute") == 0) - return KK_attribute; + /* The 1364-1995 timing checks. */ if (strcmp(yytext,"$hold") == 0) return K_Shold; + if (strcmp(yytext,"$nochange") == 0) + return K_Snochange; if (strcmp(yytext,"$period") == 0) return K_Speriod; if (strcmp(yytext,"$recovery") == 0) return K_Srecovery; - if (strcmp(yytext,"$recrem") == 0) - return K_Srecrem; if (strcmp(yytext,"$setup") == 0) return K_Ssetup; + if (strcmp(yytext,"$setuphold") == 0) + return K_Ssetuphold; + if (strcmp(yytext,"$skew") == 0) + return K_Sskew; if (strcmp(yytext,"$width") == 0) return K_Swidth; + /* The new 1364-2001 timing checks. */ + if (strcmp(yytext,"$fullskew") == 0) + return K_Sfullskew; + if (strcmp(yytext,"$recrem") == 0) + return K_Srecrem; + if (strcmp(yytext,"$removal") == 0) + return K_Sremoval; + if (strcmp(yytext,"$timeskew") == 0) + return K_Stimeskew; + + if (strcmp(yytext,"$attribute") == 0) + return KK_attribute; yylval.text = strdupnew(yytext); return SYSTEM_IDENTIFIER; } diff --git a/parse.y b/parse.y index c533b03ac..9ecf12849 100644 --- a/parse.y +++ b/parse.y @@ -248,7 +248,8 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2) %token K_trireg K_vectored K_wait K_wand K_weak0 K_weak1 K_while K_wire %token K_wor K_xnor K_xor -%token K_Shold K_Speriod K_Srecovery K_Ssetup K_Swidth K_Ssetuphold +%token K_Shold K_Snochange K_Speriod K_Srecovery K_Ssetup K_Ssetuphold +%token K_Sskew K_Swidth /* Icarus specific tokens. */ %token KK_attribute K_bool K_logic @@ -258,7 +259,7 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2) %token K_noshowcancelled K_pulsestyle_onevent K_pulsestyle_ondetect %token K_showcancelled K_signed K_unsigned -%token K_Srecrem +%token K_Sfullskew K_Srecrem K_Sremoval K_Stimeskew /* The 1364-2001 configuration tokens. */ %token K_cell K_config K_design K_endconfig K_incdir K_include K_instance @@ -3199,10 +3200,20 @@ specify_item } pform_module_specify_path(tmp); } + | K_Sfullskew '(' spec_reference_event ',' spec_reference_event + ',' delay_value ',' delay_value spec_notifier_opt ')' ';' + { delete $7; + delete $9; + } | K_Shold '(' spec_reference_event ',' spec_reference_event ',' delay_value spec_notifier_opt ')' ';' { delete $7; } + | K_Snochange '(' spec_reference_event ',' spec_reference_event + ',' delay_value ',' delay_value spec_notifier_opt ')' ';' + { delete $7; + delete $9; + } | K_Speriod '(' spec_reference_event ',' delay_value spec_notifier_opt ')' ';' { delete $5; @@ -3211,6 +3222,15 @@ specify_item ',' delay_value spec_notifier_opt ')' ';' { delete $7; } + | K_Srecrem '(' spec_reference_event ',' spec_reference_event + ',' delay_value ',' delay_value spec_notifier_opt ')' ';' + { delete $7; + delete $9; + } + | K_Sremoval '(' spec_reference_event ',' spec_reference_event + ',' delay_value spec_notifier_opt ')' ';' + { delete $7; + } | K_Ssetup '(' spec_reference_event ',' spec_reference_event ',' delay_value spec_notifier_opt ')' ';' { delete $7; @@ -3220,10 +3240,13 @@ specify_item { delete $7; delete $9; } - | K_Srecrem '(' spec_reference_event ',' spec_reference_event - ',' delay_value ',' delay_value spec_notifier_opt ')' ';' + | K_Sskew '(' spec_reference_event ',' spec_reference_event + ',' delay_value spec_notifier_opt ')' ';' + { delete $7; + } + | K_Stimeskew '(' spec_reference_event ',' spec_reference_event + ',' delay_value spec_notifier_opt ')' ';' { delete $7; - delete $9; } | K_Swidth '(' spec_reference_event ',' delay_value ',' expression spec_notifier_opt ')' ';' From 17decb3bb770f0c616a0809ca45b2c1be2e448b8 Mon Sep 17 00:00:00 2001 From: Cary R Date: Thu, 4 Jun 2009 11:02:59 -0700 Subject: [PATCH 09/12] Fix bugs in &= and |= for vvp_vector4_t Someone got a bit too creative in reducing the original equations I wrote to handle this. This patch reverts the previous code and uses my original equations. This passes for both wide and narrow vectors. The equations are slightly more complicated, but the old z2x conversion had some overhead. I would expect the time to be about the same, but you now get the correct results. --- vvp/vvp_net.cc | 73 +++++++++++++++++++++++--------------------------- 1 file changed, 34 insertions(+), 39 deletions(-) diff --git a/vvp/vvp_net.cc b/vvp/vvp_net.cc index 088ff6024..f4792eebf 100644 --- a/vvp/vvp_net.cc +++ b/vvp/vvp_net.cc @@ -1106,26 +1106,26 @@ void vvp_vector4_t::invert() vvp_vector4_t& vvp_vector4_t::operator &= (const vvp_vector4_t&that) { - // Make sure that all Z bits are turned into X bits. - change_z2x(); - - // This is sneaky. The truth table is: - // 00 01 11 - // 00 00 00 00 - // 01 00 01 11 - // 11 00 11 11 + // The truth table is: + // 00 01 11 10 + // 00 00 00 00 00 + // 01 00 01 11 11 + // 11 00 11 11 11 + // 10 00 11 11 11 if (size_ <= BITS_PER_WORD) { - // Each tmp bit is true if that is 1, X or Z. - unsigned long tmp = that.abits_val_ | that.bbits_val_; - abits_val_ &= that.abits_val_; - bbits_val_ = (bbits_val_ & tmp) | (abits_val_&that.bbits_val_); - + unsigned long tmp1 = abits_val_ | bbits_val_; + unsigned long tmp2 = that.abits_val_ | that.bbits_val_; + abits_val_ = tmp1 & tmp2; + bbits_val_ = (tmp1 & that.bbits_val_) | (tmp2 & bbits_val_); } else { unsigned words = (size_ + BITS_PER_WORD - 1) / BITS_PER_WORD; for (unsigned idx = 0; idx < words ; idx += 1) { - unsigned long tmp = that.abits_ptr_[idx]|that.bbits_ptr_[idx]; - abits_ptr_[idx] &= that.abits_ptr_[idx]; - bbits_ptr_[idx] = (bbits_ptr_[idx]&tmp) | (abits_ptr_[idx]&that.bbits_ptr_[idx]); + unsigned long tmp1 = abits_ptr_[idx] | bbits_ptr_[idx]; + unsigned long tmp2 = that.abits_ptr_[idx] | + that.bbits_ptr_[idx]; + abits_ptr_[idx] = tmp1 & tmp2; + bbits_ptr_[idx] = (tmp1 & that.bbits_ptr_[idx]) | + (tmp2 & bbits_ptr_[idx]); } } @@ -1134,34 +1134,29 @@ vvp_vector4_t& vvp_vector4_t::operator &= (const vvp_vector4_t&that) vvp_vector4_t& vvp_vector4_t::operator |= (const vvp_vector4_t&that) { - // Make sure that all Z bits are turned into X bits. - change_z2x(); - - // This is sneaky. - // The OR is 1 if either operand is 1. - // The OR is 0 if both operants are 0. - // Otherwise, the AND is X. The truth table is: - // - // 00 01 11 - // 00 00 01 11 - // 01 01 01 01 - // 11 11 01 11 + // The truth table is: + // 00 01 11 10 + // 00 00 01 11 11 + // 01 01 01 01 01 + // 11 11 01 11 11 + // 10 11 01 11 11 if (size_ <= BITS_PER_WORD) { - // Each tmp bit is true if that is 1, X or Z. - unsigned long tmp1 = abits_val_ | bbits_val_; - unsigned long tmp2 = that.abits_val_ | that.bbits_val_; - bbits_val_ = (bbits_val_& ~(that.abits_val_^that.bbits_val_)) - | (that.bbits_val_& ~abits_val_); - abits_val_ = tmp1 | tmp2; + unsigned long tmp = abits_val_ | bbits_val_ | + that.abits_val_ | that.bbits_val_; + bbits_val_ = (~abits_val_ | bbits_val_) & that.bbits_val_ | + (~that.abits_val_ | that.bbits_val_) & bbits_val_; + abits_val_ = tmp; } else { unsigned words = (size_ + BITS_PER_WORD - 1) / BITS_PER_WORD; for (unsigned idx = 0; idx < words ; idx += 1) { - unsigned long tmp1 = abits_ptr_[idx] | bbits_ptr_[idx]; - unsigned long tmp2 = that.abits_ptr_[idx] | that.bbits_ptr_[idx]; - bbits_ptr_[idx] = (bbits_ptr_[idx]& ~(that.abits_ptr_[idx]^that.bbits_ptr_[idx])) - | (that.bbits_ptr_[idx]& ~abits_ptr_[idx]); - abits_ptr_[idx] = tmp1 | tmp2; + unsigned long tmp = abits_ptr_[idx] | bbits_ptr_[idx] | + that.abits_ptr_[idx] | that.bbits_ptr_[idx]; + bbits_ptr_[idx] = (~abits_ptr_[idx] | bbits_ptr_[idx]) & + that.bbits_ptr_[idx] | + (~that.abits_ptr_[idx] | + that.bbits_ptr_[idx]) & bbits_ptr_[idx]; + abits_ptr_[idx] = tmp; } } From 1942327ae2b0d921c5de41819dcb8785db4a0f64 Mon Sep 17 00:00:00 2001 From: Cary R Date: Thu, 4 Jun 2009 16:12:08 -0700 Subject: [PATCH 10/12] Allocate the fd table dynamically in 32 entry chunks. The fd table used to be statically allocated with only 32 entries. Three of these were preallocated for stdin, stdout and stderr leaving only 29 for the user. This patch makes the allocation of this table dynamic with a hard limit at 1024 total fds. The table is increased in 32 bit chunks. --- vvp/main.cc | 4 +- vvp/vpi_mcd.cc | 102 +++++++++++++++++++++++++++++-------------------- 2 files changed, 62 insertions(+), 44 deletions(-) diff --git a/vvp/main.cc b/vvp/main.cc index f255d59b3..539e277d3 100644 --- a/vvp/main.cc +++ b/vvp/main.cc @@ -194,7 +194,7 @@ void verify_version(char*ivl_ver, char*commit) unsigned module_cnt = 0; const char*module_tab[64]; -extern void vpi_mcd_init(FILE *log); +extern void vpip_mcd_init(FILE *log); extern void vvp_vpi_init(void); int main(int argc, char*argv[]) @@ -326,7 +326,7 @@ int main(int argc, char*argv[]) } } - vpi_mcd_init(logfile); + vpip_mcd_init(logfile); if (verbose_flag) { my_getrusage(cycles+0); diff --git a/vvp/vpi_mcd.cc b/vvp/vpi_mcd.cc index 57cc55557..9a0a71139 100644 --- a/vvp/vpi_mcd.cc +++ b/vvp/vpi_mcd.cc @@ -42,53 +42,65 @@ extern FILE* vpi_trace; */ #define IS_MCD(mcd) !((mcd)>>31&1) #define FD_IDX(fd) ((fd)&~(1U<<31)) -#define FD_MAX 32 +#define FD_INCR 32 -struct mcd_entry { +typedef struct mcd_entry { FILE *fp; char *filename; -}; -static struct mcd_entry mcd_table[31]; -static struct mcd_entry fd_table[FD_MAX]; +} mcd_entry_s; +static mcd_entry_s mcd_table[31]; +static mcd_entry_s *fd_table = NULL; +static unsigned fd_table_len = 0; static FILE* logfile; /* Initialize mcd portion of vpi. Must be called before * any vpi_mcd routines can be used. */ -void vpi_mcd_init(FILE *log) +void vpip_mcd_init(FILE *log) { - mcd_table[0].fp = stdout; - mcd_table[0].filename = strdup("stdout"); + fd_table_len = FD_INCR; + fd_table = (mcd_entry_s *) malloc(fd_table_len*sizeof(mcd_entry_s)); + for (unsigned idx = 0; idx < fd_table_len; idx += 1) { + fd_table[idx].fp = NULL; + fd_table[idx].filename = NULL; + } + + mcd_table[0].fp = stdout; + mcd_table[0].filename = strdup("stdout"); - fd_table[0].fp = stdin; - fd_table[0].filename = strdup("stdin"); - fd_table[1].fp = stdout; - fd_table[1].filename = strdup("stdout"); - fd_table[2].fp = stderr; - fd_table[2].filename = strdup("stderr"); + fd_table[0].fp = stdin; + fd_table[0].filename = strdup("stdin"); + fd_table[1].fp = stdout; + fd_table[1].filename = strdup("stdout"); + fd_table[2].fp = stderr; + fd_table[2].filename = strdup("stderr"); - logfile = log; + logfile = log; } #ifdef CHECK_WITH_VALGRIND void vpi_mcd_delete(void) { free(mcd_table[0].filename); - mcd_table[0].filename = 0; - mcd_table[0].fp = 0; + mcd_table[0].filename = NULL; + mcd_table[0].fp = NULL; free(fd_table[0].filename); - fd_table[0].filename = 0; - fd_table[0].fp = 0; + fd_table[0].filename = NULL; + fd_table[0].fp = NULL; free(fd_table[1].filename); - fd_table[1].filename = 0; - fd_table[1].fp = 0; + fd_table[1].filename = NULL; + fd_table[1].fp = NULL; free(fd_table[2].filename); - fd_table[2].filename = 0; - fd_table[2].fp = 0; + fd_table[2].filename = NULL; + fd_table[2].fp = NULL; + + free(fd_table); + fd_table = NULL; + fd_table_len = 0; } #endif @@ -112,7 +124,7 @@ extern "C" PLI_UINT32 vpi_mcd_close(PLI_UINT32 mcd) } } else { unsigned idx = FD_IDX(mcd); - if (idx > 2 && idx < FD_MAX && fd_table[idx].fp) { + if (idx > 2 && idx < fd_table_len && fd_table[idx].fp) { rc = fclose(fd_table[idx].fp); free(fd_table[idx].filename); fd_table[idx].fp = NULL; @@ -131,7 +143,7 @@ extern "C" char *vpi_mcd_name(PLI_UINT32 mcd) } } else { unsigned idx = FD_IDX(mcd); - if (idx < FD_MAX) + if (idx < fd_table_len) return fd_table[idx].filename; } return NULL; @@ -222,7 +234,7 @@ extern "C" PLI_INT32 vpi_mcd_flush(PLI_UINT32 mcd) } } else { unsigned idx = FD_IDX(mcd); - if (idx < FD_MAX) rc = fflush(fd_table[idx].fp); + if (idx < fd_table_len) rc = fflush(fd_table[idx].fp); } return rc; } @@ -240,29 +252,35 @@ extern "C" PLI_INT32 vpi_mcd_flush(PLI_UINT32 mcd) */ extern "C" PLI_INT32 vpi_fopen(const char*name, const char*mode) { - unsigned i; - for(i = 0; i < FD_MAX; i++) { - if(fd_table[i].filename == NULL) - goto got_entry; - } - return 0; /* too many open fd's */ + unsigned i; + for (i = 0; i < fd_table_len; i += 1) { + if (fd_table[i].filename == NULL) goto got_entry; + } + /* We need to allocate more table entries, but to keep things */ + /* sane we'll hard limit this to 1024 file descriptors total. */ + if (fd_table_len >= 1024) return 0; + fd_table_len += FD_INCR; + fd_table = (mcd_entry_s *) realloc(fd_table, + fd_table_len*sizeof(mcd_entry_s)); + for (unsigned idx = i; idx < fd_table_len; idx += 1) { + fd_table[idx].fp = NULL; + fd_table[idx].filename = NULL; + } got_entry: - fd_table[i].fp = fopen(name, mode); - if(fd_table[i].fp == NULL) - return 0; - fd_table[i].filename = strdup(name); - return ((1U<<31)|i); + fd_table[i].fp = fopen(name, mode); + if (fd_table[i].fp == NULL) return 0; + fd_table[i].filename = strdup(name); + return ((1U<<31)|i); } extern "C" FILE *vpi_get_file(PLI_INT32 fd) { // Only deal with FD's - if (IS_MCD(fd)) return NULL; + if (IS_MCD(fd)) return NULL; - // Only know about FD_MAX indices - if (FD_IDX(fd) >= FD_MAX) return NULL; + // Only know about fd_table_len indices + if (FD_IDX(fd) >= fd_table_len) return NULL; - return fd_table[FD_IDX(fd)].fp; + return fd_table[FD_IDX(fd)].fp; } - From aeac491cfce70df64ae43ad22506b5ace1e263b1 Mon Sep 17 00:00:00 2001 From: Cary R Date: Fri, 5 Jun 2009 13:36:20 -0700 Subject: [PATCH 11/12] Some delay expressions need to probe their width (ternary) The ternary operator requires that the expression width be defined. This requires that the delay expression has test_width() run on it. --- PDelays.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/PDelays.cc b/PDelays.cc index 06729fe3d..efbc36861 100644 --- a/PDelays.cc +++ b/PDelays.cc @@ -65,8 +65,11 @@ void PDelays::set_delays(const svector*del, bool df) delete_flag_ = df; } -static NetExpr*calculate_val(Design*des, NetScope*scope, const PExpr*expr) +static NetExpr*calculate_val(Design*des, NetScope*scope, PExpr*expr) { + ivl_variable_type_t tmp_type = IVL_VT_NO_TYPE; + bool tmp_flag = false; + expr->test_width(des, scope, 0, 0, tmp_type, tmp_flag); NetExpr*dex = expr->elaborate_expr(des, scope, -1, false); eval_expr(dex); From 5153bfc1f7c3ad81a153cdfcc1fc6b280f1dff50 Mon Sep 17 00:00:00 2001 From: Cary R Date: Fri, 5 Jun 2009 16:12:17 -0700 Subject: [PATCH 12/12] Ignore specify pulsestyle_* and *showcancelled directives. This patch adds code to silently ignore the specify directives: pulsestyle_onevent pulsestyle_ondetect showcancelled noshowcancelled. --- parse.y | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/parse.y b/parse.y index 9ecf12849..d25591943 100644 --- a/parse.y +++ b/parse.y @@ -3256,6 +3256,18 @@ specify_item | K_Swidth '(' spec_reference_event ',' delay_value ')' ';' { delete $5; } + | K_pulsestyle_onevent specify_path_identifiers ';' + { delete $2; + } + | K_pulsestyle_ondetect specify_path_identifiers ';' + { delete $2; + } + | K_showcancelled specify_path_identifiers ';' + { delete $2; + } + | K_noshowcancelled specify_path_identifiers ';' + { delete $2; + } ; specify_item_list