diff --git a/elab_expr.cc b/elab_expr.cc index 453f91b02..b15d1aecf 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -5685,7 +5685,6 @@ unsigned PETernary::test_width(Design*des, NetScope*scope, width_mode_t&mode) } else if (tru_type == IVL_VT_LOGIC || fal_type == IVL_VT_LOGIC) { expr_type_ = IVL_VT_LOGIC; } else { - ivl_assert(*this, tru_type == fal_type); expr_type_ = tru_type; } if (expr_type_ == IVL_VT_REAL) { diff --git a/iverilog-vpi.man.in b/iverilog-vpi.man.in index 2f5f090b0..bd8f7a930 100644 --- a/iverilog-vpi.man.in +++ b/iverilog-vpi.man.in @@ -1,4 +1,4 @@ -.TH iverilog-vpi 1 "May 10th, 2015" "" "Version %M.%n%E" +.TH iverilog-vpi 1 "Jan 29th, 2017" "" "Version %M.%n%E" .SH NAME iverilog-vpi - Compile front end for VPI modules @@ -26,6 +26,11 @@ becomes \fIfoo.vpi\fP. Include the named library in the link of the VPI module. This allows VPI modules to further reference external libraries. +.TP 8 +.B -L\fIdirectory\fP +Add \fIdirectory\fP to the list of directories that will be searched +for library files. + .TP 8 .B -I\fIdirectory\fP Add \fIdirectory\fP to the list of directories that will be searched @@ -115,7 +120,7 @@ iverilog(1), vvp(1), .SH COPYRIGHT .nf -Copyright \(co 2002\-2015 Stephen Williams +Copyright \(co 2002\-2017 Stephen Williams This document can be freely redistributed according to the terms of the GNU General Public License version 2.0 diff --git a/iverilog-vpi.sh b/iverilog-vpi.sh index d1554d420..3b918d7f0 100644 --- a/iverilog-vpi.sh +++ b/iverilog-vpi.sh @@ -35,6 +35,7 @@ CCSRC= CXSRC= OBJ= LIB= +LIBDIR= OUT= INCOPT= DEFS= @@ -81,6 +82,9 @@ do -l*) LIB="$LIB $parm" ;; + -L*) LIBDIR="$LIBDIR $parm" + ;; + -I*) INCOPT="$INCOPT $parm" ;; @@ -148,4 +152,4 @@ then fi echo "Making $OUT from $OBJ..." -exec $LD -o $OUT $LDFLAGS $OBJ $LIB $LDLIBS +exec $LD -o $OUT $LDFLAGS $LIBDIR $OBJ $LIB $LDLIBS diff --git a/pform.cc b/pform.cc index 1cf58e4fa..329b8a797 100644 --- a/pform.cc +++ b/pform.cc @@ -40,6 +40,7 @@ # include # include # include +# include # include "ivl_assert.h" # include "ivl_alloc.h" @@ -86,6 +87,42 @@ std::string vlltype::get_fileline() const } +static bool is_hex_digit_str(const char *str) +{ + while (*str) { + if (!isxdigit(*str)) return false; + str++; + } + return true; +} + +static bool is_dec_digit_str(const char *str) +{ + while (*str) { + if (!isdigit(*str)) return false; + str++; + } + return true; +} + +static bool is_oct_digit_str(const char *str) +{ + while (*str) { + if (*str < '0' || *str > '7') return false; + str++; + } + return true; +} + +static bool is_bin_digit_str(const char *str) +{ + while (*str) { + if (*str != '0' && *str != '1') return false; + str++; + } + return true; +} + /* * Parse configuration file with format =, where key * is the hierarchical name of a valid parameter name, and value @@ -152,90 +189,137 @@ void parm_to_defparam_list(const string¶m) ptr = strchr(nkey, '.'); } name.push_back(name_component_t(lex_strings.make(nkey))); + free(key); // Resolve value to PExpr class. Should support all kind of constant // format including based number, dec number, real number and string. - if (*value == '"') { // string type - char *buf = strdup (value); - char *buf_ptr = buf+1; - // Parse until another '"' or '\0' - while (*buf_ptr != '"' && *buf_ptr != '\0') { - buf_ptr++; - // Check for escape, especially '\"', which does not mean the - // end of string. - if (*buf_ptr == '\\' && *(buf_ptr+1) != '\0') - buf_ptr += 2; - } - if (*buf_ptr == '\0') // String end without '"' - cerr << ": error: missing close quote of string for defparam: " << name << endl; - else if (*(buf_ptr+1) != 0) { // '"' appears within string with no escape - cerr << buf_ptr << endl; - cerr << ": error: \'\"\' appears within string value for defparam: " << name - << ". Ignore characters after \'\"\'" << endl; - } - *buf_ptr = '\0'; - buf_ptr = buf+1; - // Remember to use 'new' to allocate string for PEString - // because 'delete' is used by its destructor. - char *nchar = strcpy(new char [strlen(buf_ptr)+1], buf_ptr); - PExpr* ndec = new PEString(nchar); + // Is it a string? + if (*value == '"') { + char *buf = strdup (value); + char *buf_ptr = buf+1; + // Parse until another '"' or '\0' + while (*buf_ptr != '"' && *buf_ptr != '\0') { + buf_ptr++; + // Check for escape, especially '\"', which does not mean the + // end of string. + if (*buf_ptr == '\\' && *(buf_ptr+1) != '\0') + buf_ptr += 2; + } + if (*buf_ptr == '\0') // String end without '"' + cerr << ": error: missing close quote of string for defparam: " << name << endl; + else if (*(buf_ptr+1) != 0) { // '"' appears within string with no escape + cerr << buf_ptr << endl; + cerr << ": error: \'\"\' appears within string value for defparam: " << name + << ". Ignore characters after \'\"\'" << endl; + } + + *buf_ptr = '\0'; + buf_ptr = buf+1; + // Remember to use 'new' to allocate string for PEString + // because 'delete' is used by its destructor. + char *nchar = strcpy(new char [strlen(buf_ptr)+1], buf_ptr); + PExpr* ndec = new PEString(nchar); Module::user_defparms.push_back( make_pair(name, ndec) ); - free(buf); + free(buf); + free(value); + return; } - else { // number type - char *num = strchr(value, '\''); - if (num != 0) { - verinum *val; - // BASED_NUMBER, something like - scope.parameter='b11 - // make sure to check 'h' first because 'b'&'d' may be included - // in hex format - if (strchr(num, 'h') || strchr(num, 'H')) - val = make_unsized_hex(num); - else if (strchr(num, 'd') || strchr(num, 'D')) - if (strchr(num, 'x') || strchr(num, 'X') || strchr(num, 'z') || strchr(num, 'Z')) - val = make_undef_highz_dec(num); - else - val = make_unsized_dec(num); - else if (strchr(num, 'b') || strchr(num, 'B')) { - val = make_unsized_binary(num); - } - else if (strchr(num, 'o') || strchr(num, 'O')) - val = make_unsized_octal(num); - else { - cerr << ": error: value specify error for defparam: " << name << endl; - free(key); - free(value); - return; - } - // BASED_NUMBER with size, something like - scope.parameter=2'b11 - if (num != value) { - *num = 0; - verinum *siz = make_unsized_dec(value); - val = pform_verinum_with_size(siz, val, "", 0); - } - - PExpr* ndec = new PENumber(val); - Module::user_defparms.push_back( make_pair(name, ndec) ); - - } - else { - // REALTIME, something like - scope.parameter=1.22 or scope.parameter=1e2 - if (strchr(value, '.') || strchr(value, 'e') || strchr(value, 'E')) { - verireal *val = new verireal(value); - PExpr* nreal = new PEFNumber(val); - Module::user_defparms.push_back( make_pair(name, nreal) ); - } - else { - // DEC_NUMBER, something like - scope.parameter=3 - verinum *val = make_unsized_dec(value); - PExpr* ndec = new PENumber(val); - Module::user_defparms.push_back( make_pair(name, ndec) ); - } - } + // Is it a based number? + char *num = strchr(value, '\''); + if (num != 0) { + verinum *val; + const char *base = num + 1; + if (*base == 's' || *base == 'S') + base++; + switch (*base) { + case 'h': + case 'H': + if (is_hex_digit_str(base+1)) { + val = make_unsized_hex(num); + } else { + cerr << ": error: invalid digit in hex value specified for defparam: " << name << endl; + free(value); + return; + } + break; + case 'd': + case 'D': + if (is_dec_digit_str(base+1)) { + val = make_unsized_dec(num); + } else { + cerr << ": error: invalid digit in decimal value specified for defparam: " << name << endl; + free(value); + return; + } + break; + case 'o': + case 'O': + if (is_oct_digit_str(base+1)) { + val = make_unsized_octal(num); + } else { + cerr << ": error: invalid digit in octal value specified for defparam: " << name << endl; + free(value); + return; + } + break; + case 'b': + case 'B': + if (is_bin_digit_str(base+1)) { + val = make_unsized_binary(num); + } else { + cerr << ": error: invalid digit in binary value specified for defparam: " << name << endl; + free(value); + return; + } + break; + default: + cerr << ": error: invalid numeric base specified for defparam: " << name << endl; + free(value); + return; + } + if (num != value) { // based number with size + *num = 0; + if (is_dec_digit_str(value)) { + verinum *siz = make_unsized_dec(value); + val = pform_verinum_with_size(siz, val, "", 0); + } else { + cerr << ": error: invalid size for value specified for defparam: " << name << endl; + free(value); + return; + } + } + PExpr* ndec = new PENumber(val); + Module::user_defparms.push_back( make_pair(name, ndec) ); + free(value); + return; } - free(key); + + // Is it a decimal number? + num = (value[0] == '-') ? value + 1 : value; + if (is_dec_digit_str(num)) { + verinum *val = make_unsized_dec(num); + if (value[0] == '-') *val = -(*val); + PExpr* ndec = new PENumber(val); + Module::user_defparms.push_back( make_pair(name, ndec) ); + free(value); + return; + } + + // Is it a real number? + char *end = 0; + double rval = strtod(value, &end); + if (end != value && *end == 0) { + verireal *val = new verireal(rval); + PExpr* nreal = new PEFNumber(val); + Module::user_defparms.push_back( make_pair(name, nreal) ); + free(value); + return; + } + + // None of the above. + cerr << ": error: invalid value specified for defparam: " << name << endl; free(value); }