Merge branch 'master' of github.com:steveicarus/iverilog

This commit is contained in:
Stephen Williams 2017-02-17 10:40:14 -08:00
commit a427440054
4 changed files with 172 additions and 80 deletions

View File

@ -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) { } else if (tru_type == IVL_VT_LOGIC || fal_type == IVL_VT_LOGIC) {
expr_type_ = IVL_VT_LOGIC; expr_type_ = IVL_VT_LOGIC;
} else { } else {
ivl_assert(*this, tru_type == fal_type);
expr_type_ = tru_type; expr_type_ = tru_type;
} }
if (expr_type_ == IVL_VT_REAL) { if (expr_type_ == IVL_VT_REAL) {

View File

@ -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 .SH NAME
iverilog-vpi - Compile front end for VPI modules 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 Include the named library in the link of the VPI module. This allows
VPI modules to further reference external libraries. 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 .TP 8
.B -I\fIdirectory\fP .B -I\fIdirectory\fP
Add \fIdirectory\fP to the list of directories that will be searched Add \fIdirectory\fP to the list of directories that will be searched
@ -115,7 +120,7 @@ iverilog(1), vvp(1),
.SH COPYRIGHT .SH COPYRIGHT
.nf .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 This document can be freely redistributed according to the terms of the
GNU General Public License version 2.0 GNU General Public License version 2.0

View File

@ -35,6 +35,7 @@ CCSRC=
CXSRC= CXSRC=
OBJ= OBJ=
LIB= LIB=
LIBDIR=
OUT= OUT=
INCOPT= INCOPT=
DEFS= DEFS=
@ -81,6 +82,9 @@ do
-l*) LIB="$LIB $parm" -l*) LIB="$LIB $parm"
;; ;;
-L*) LIBDIR="$LIBDIR $parm"
;;
-I*) INCOPT="$INCOPT $parm" -I*) INCOPT="$INCOPT $parm"
;; ;;
@ -148,4 +152,4 @@ then
fi fi
echo "Making $OUT from $OBJ..." echo "Making $OUT from $OBJ..."
exec $LD -o $OUT $LDFLAGS $OBJ $LIB $LDLIBS exec $LD -o $OUT $LDFLAGS $LIBDIR $OBJ $LIB $LDLIBS

236
pform.cc
View File

@ -40,6 +40,7 @@
# include <sstream> # include <sstream>
# include <cstring> # include <cstring>
# include <cstdlib> # include <cstdlib>
# include <cctype>
# include "ivl_assert.h" # include "ivl_assert.h"
# include "ivl_alloc.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 <key>=<value>, where key * Parse configuration file with format <key>=<value>, where key
* is the hierarchical name of a valid parameter name, and value * is the hierarchical name of a valid parameter name, and value
@ -152,90 +189,137 @@ void parm_to_defparam_list(const string&param)
ptr = strchr(nkey, '.'); ptr = strchr(nkey, '.');
} }
name.push_back(name_component_t(lex_strings.make(nkey))); name.push_back(name_component_t(lex_strings.make(nkey)));
free(key);
// Resolve value to PExpr class. Should support all kind of constant // Resolve value to PExpr class. Should support all kind of constant
// format including based number, dec number, real number and string. // 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 << "<command line>: 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 << "<command line>: error: \'\"\' appears within string value for defparam: " << name
<< ". Ignore characters after \'\"\'" << endl;
}
*buf_ptr = '\0'; // Is it a string?
buf_ptr = buf+1; if (*value == '"') {
// Remember to use 'new' to allocate string for PEString char *buf = strdup (value);
// because 'delete' is used by its destructor. char *buf_ptr = buf+1;
char *nchar = strcpy(new char [strlen(buf_ptr)+1], buf_ptr); // Parse until another '"' or '\0'
PExpr* ndec = new PEString(nchar); 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 << "<command line>: 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 << "<command line>: 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) ); 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 << "<command line>: error: value specify error for defparam: " << name << endl;
free(key);
free(value);
return;
}
// BASED_NUMBER with size, something like - scope.parameter=2'b11 // Is it a based number?
if (num != value) { char *num = strchr(value, '\'');
*num = 0; if (num != 0) {
verinum *siz = make_unsized_dec(value); verinum *val;
val = pform_verinum_with_size(siz, val, "<command line>", 0); const char *base = num + 1;
} if (*base == 's' || *base == 'S')
base++;
PExpr* ndec = new PENumber(val); switch (*base) {
Module::user_defparms.push_back( make_pair(name, ndec) ); case 'h':
case 'H':
} if (is_hex_digit_str(base+1)) {
else { val = make_unsized_hex(num);
// REALTIME, something like - scope.parameter=1.22 or scope.parameter=1e2 } else {
if (strchr(value, '.') || strchr(value, 'e') || strchr(value, 'E')) { cerr << "<command line>: error: invalid digit in hex value specified for defparam: " << name << endl;
verireal *val = new verireal(value); free(value);
PExpr* nreal = new PEFNumber(val); return;
Module::user_defparms.push_back( make_pair(name, nreal) ); }
} break;
else { case 'd':
// DEC_NUMBER, something like - scope.parameter=3 case 'D':
verinum *val = make_unsized_dec(value); if (is_dec_digit_str(base+1)) {
PExpr* ndec = new PENumber(val); val = make_unsized_dec(num);
Module::user_defparms.push_back( make_pair(name, ndec) ); } else {
} cerr << "<command line>: 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 << "<command line>: 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 << "<command line>: error: invalid digit in binary value specified for defparam: " << name << endl;
free(value);
return;
}
break;
default:
cerr << "<command line>: 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, "<command line>", 0);
} else {
cerr << "<command line>: 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 << "<command line>: error: invalid value specified for defparam: " << name << endl;
free(value); free(value);
} }