diff --git a/driver/main.c b/driver/main.c index 73c0d666e..0409166d3 100644 --- a/driver/main.c +++ b/driver/main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2010 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2011 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -705,10 +705,11 @@ int process_generation(const char*name) fprintf(stderr, "Unknown/Unsupported Language generation " "%s\n\n", name); fprintf(stderr, "Supported generations are:\n"); - fprintf(stderr, " 1995 -- IEEE1364-1995\n" - " 2001 -- IEEE1364-2001\n" - " 2005 -- IEEE1364-2005\n" - " 2009 -- IEEE1800-2009\n" + fprintf(stderr, " 1995 -- IEEE1364-1995\n" + " 2001 -- IEEE1364-2001\n" + " 2005 -- IEEE1364-2005\n" + " 2005-sv -- IEEE1800-2005\n" + " 2009 -- IEEE1800-2009\n" "Other generation flags:\n" " specify | no-specify\n" " verilog-ams | no-verilog-ams\n" @@ -792,21 +793,28 @@ int main(int argc, char **argv) so we chop the file name and the last directory by turning the last two \ characters to null. Then we append the lib\ivl$(suffix) to finish. */ - { char *s; - char basepath[4096], tmppath[4096]; - GetModuleFileName(NULL, tmppath, sizeof tmppath); - /* Convert to a short name to remove any embedded spaces. */ - GetShortPathName(tmppath, basepath, sizeof basepath); - strncpy(ivl_root, basepath, MAXSIZE); - ivl_root[MAXSIZE-1] = 0; - s = strrchr(ivl_root, sep); - if (s) *s = 0; - s = strrchr(ivl_root, sep); - if (s) *s = 0; - strcat(ivl_root, "\\lib\\ivl" IVL_SUFFIX); - - base = ivl_root; + char *s; + char tmppath[MAXSIZE]; + GetModuleFileName(NULL, tmppath, sizeof tmppath); + /* Convert to a short name to remove any embedded spaces. */ + GetShortPathName(tmppath, ivl_root, sizeof ivl_root); + s = strrchr(ivl_root, sep); + if (s) *s = 0; + else { + fprintf(stderr, "%s: Missing first %c in exe path!\n", + argv[0], sep); + exit(1); } + s = strrchr(ivl_root, sep); + if (s) *s = 0; + else { + fprintf(stderr, "%s: Missing second %c in exe path!\n", + argv[0], sep); + exit(1); + } + strcat(ivl_root, "\\lib\\ivl" IVL_SUFFIX); + + base = ivl_root; #else /* In a UNIX environment, the IVL_ROOT from the Makefile is diff --git a/elab_expr.cc b/elab_expr.cc index 1eef016e0..d4795ee03 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -1853,8 +1853,8 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode) expr_type_ = use_enum->base_type(); expr_width_ = use_enum->base_width(); - min_width_ = expr_width_; - signed_flag_ = false; + min_width_ = expr_width_; + signed_flag_ = par_enum->has_sign(); return expr_width_; } @@ -3654,18 +3654,29 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope, << "vector slice." << endl; des->errors += 1; return 0; - } else if (t == IVL_VT_REAL) { + } else if (t == IVL_VT_LOGIC || t == IVL_VT_BOOL || + t == IVL_VT_REAL) { + + if (dynamic_cast (ip) || + dynamic_cast (ip)) { + /* + * invalid operand: operand is a constant + * or real number + */ + cerr << get_fileline() << ": error: " + << "inappropriate use of " + << human_readable_op(op_, true) + << " operator." << endl; + des->errors += 1; + return 0; + } + /* - * TODO: Need to modify draw_unary_real() to support - * operations on real variables + * **** Valid use of operator *** + * For REAL variables draw_unary_real() is ivoked during + * evaluation and for LOGIC/BOOLEAN draw_unary_expr() + * is called for evaluation. */ - cerr << get_fileline() << ": sorry: " - << human_readable_op(op_, true) - << " operation is not yet supported on " - << "reals." << endl; - des->errors += 1; - return 0; - } else if (t == IVL_VT_LOGIC || t == IVL_VT_BOOL) { tmp = new NetEUnary(op_, ip, expr_wid, signed_flag_); tmp->set_line(*this); } else { diff --git a/elab_scope.cc b/elab_scope.cc index 2347f7ac2..72a367ad0 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -147,6 +147,7 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope, netenum_t*use_enum = new netenum_t(enum_type->base_type, enum_type->signed_flag, msb, lsb, enum_type->names->size()); + use_enum->set_line(enum_type->li); scope->add_enumeration_set(use_enum); verinum cur_value (0); @@ -177,7 +178,8 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope, NetExpr*val = elab_and_eval(des, scope, cur->parm, -1); NetEConst*val_const = dynamic_cast (val); if (val_const == 0) { - cerr << "<>:0: error: Enumeration expression is not " + cerr << use_enum->get_fileline() + << ": error: Enumeration expression is not " "constant." << endl; des->errors += 1; continue; @@ -186,14 +188,16 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope, if (enum_type->base_type==IVL_VT_BOOL && ! cur_value.is_defined()) { - cerr << "<>:0: error: Enumeration name " << cur->name + cerr << use_enum->get_fileline() + << ": error: Enumeration name " << cur->name << " cannot have an undefined value." << endl; des->errors += 1; continue; } } else if (! cur_value.is_defined()) { - cerr << "<>:0: error: Enumeration name " << cur->name + cerr << use_enum->get_fileline() + << ": error: Enumeration name " << cur->name << " cannot have an undefined inferred value." << endl; des->errors += 1; continue; @@ -202,7 +206,8 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope, // The enumeration value must fit into the enumeration bits. if ((cur_value > max_value) || (cur_value.has_sign() && (cur_value < min_value))) { - cerr << "<>:0: error: Enumeration name " << cur->name + cerr << use_enum->get_fileline() + << ": error: Enumeration name " << cur->name << " cannot have a value equal to " << cur_value << "." << endl; des->errors += 1; @@ -226,7 +231,8 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope, rc_flag = use_enum->insert_name(name_idx, cur->name, tmp_val); rc_flag &= scope->add_enumeration_name(use_enum, cur->name); if (! rc_flag) { - cerr << "<>:0: error: Duplicate enumeration name " + cerr << use_enum->get_fileline() + << ": error: Duplicate enumeration name " << cur->name << endl; des->errors += 1; } diff --git a/ivl.def b/ivl.def index b942383d1..ebc1844fe 100644 --- a/ivl.def +++ b/ivl.def @@ -30,9 +30,12 @@ ivl_discipline_flow ivl_discipline_name ivl_discipline_potential +ivl_enum_bits +ivl_enum_file +ivl_enum_lineno ivl_enum_name ivl_enum_names -ivl_enum_bits +ivl_enum_signed ivl_enum_type ivl_enum_width diff --git a/ivl_target.h b/ivl_target.h index f63852a2f..d46454cd4 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -652,6 +652,9 @@ extern const char* ivl_nature_name(ivl_nature_t net); * of the enumeration should match the length of this string. Every * name also has bits that make up the value. * + * ivl_enum_signed + * Is the base type for the enum signed? + * * ivl_enum_type * Get the data-type for the base type that the enum uses. This * will be either IVL_VT_BOOL or IVL_VT_LOGIC @@ -664,9 +667,13 @@ extern const char* ivl_nature_name(ivl_nature_t net); extern unsigned ivl_enum_names(ivl_enumtype_t net); extern const char*ivl_enum_name(ivl_enumtype_t net, unsigned idx); extern const char*ivl_enum_bits(ivl_enumtype_t net, unsigned idx); +extern int ivl_enum_signed(ivl_enumtype_t net); extern ivl_variable_type_t ivl_enum_type(ivl_enumtype_t net); extern unsigned ivl_enum_width(ivl_enumtype_t net); +extern const char*ivl_enum_file(ivl_enumtype_t net); +extern unsigned ivl_enum_lineno(ivl_enumtype_t net); + /* EVENTS * * Events are a unification of named events and implicit events diff --git a/netenum.h b/netenum.h index d89a45595..b88f75918 100644 --- a/netenum.h +++ b/netenum.h @@ -1,7 +1,7 @@ #ifndef __netenum_H #define __netenum_H /* - * Copyright (c) 2010 Stephen Williams (steve@icarus.com) + * Copyright (c) 2010-2011 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -22,12 +22,13 @@ # include "ivl_target.h" # include "verinum.h" # include "StringHeap.h" +# include "LineInfo.h" # include # include class NetScope; -class netenum_t { +class netenum_t : public LineInfo { public: explicit netenum_t(ivl_variable_type_t base_type, bool signed_flag, @@ -36,6 +37,7 @@ class netenum_t { ivl_variable_type_t base_type() const; unsigned base_width() const; + bool has_sign() const; // The size() is the number of enumeration literals. size_t size() const; @@ -79,4 +81,6 @@ inline unsigned netenum_t::base_width() const inline size_t netenum_t::size() const { return names_.size(); } +inline bool netenum_t::has_sign() const { return signed_flag_; } + #endif diff --git a/parse.y b/parse.y index d633c726c..0f96c5b02 100644 --- a/parse.y +++ b/parse.y @@ -773,28 +773,28 @@ enum_data_type enum_type->range.reset( make_range_from_width(integer_width) ); $$ = enum_type; } - | K_enum K_logic range unsigned_signed_opt '{' enum_name_list '}' + | K_enum K_logic unsigned_signed_opt range '{' enum_name_list '}' { enum_type_t*enum_type = new enum_type_t; enum_type->names .reset($6); enum_type->base_type = IVL_VT_LOGIC; - enum_type->signed_flag = $4; - enum_type->range.reset( $3 ); + enum_type->signed_flag = $3; + enum_type->range.reset( $4 ); $$ = enum_type; } - | K_enum K_reg range unsigned_signed_opt '{' enum_name_list '}' + | K_enum K_reg unsigned_signed_opt range '{' enum_name_list '}' { enum_type_t*enum_type = new enum_type_t; enum_type->names .reset($6); enum_type->base_type = IVL_VT_LOGIC; - enum_type->signed_flag = $4; - enum_type->range.reset( $3 ); + enum_type->signed_flag = $3; + enum_type->range.reset( $4 ); $$ = enum_type; } - | K_enum K_bit range unsigned_signed_opt '{' enum_name_list '}' + | K_enum K_bit unsigned_signed_opt range '{' enum_name_list '}' { enum_type_t*enum_type = new enum_type_t; enum_type->names .reset($6); enum_type->base_type = IVL_VT_BOOL; - enum_type->signed_flag = $4; - enum_type->range.reset( $3 ); + enum_type->signed_flag = $3; + enum_type->range.reset( $4 ); $$ = enum_type; } ; diff --git a/pform.cc b/pform.cc index 05ddc3314..82bb894ce 100644 --- a/pform.cc +++ b/pform.cc @@ -2508,6 +2508,9 @@ void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type, listrange.get() != 0); assert(enum_type->range->size() == 2); + // Add the file and line information to the enumeration type. + FILE_NAME(&(enum_type->li), li); + // Attach the enumeration to the current scope. pform_put_enum_type_in_scope(enum_type); diff --git a/pform_types.h b/pform_types.h index 61a41d4f2..609641e1f 100644 --- a/pform_types.h +++ b/pform_types.h @@ -1,7 +1,7 @@ #ifndef __pform_types_H #define __pform_types_H /* - * Copyright (c) 2007-2008 Stephen Williams (steve@icarus.com) + * Copyright (c) 2007-2011 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -21,6 +21,7 @@ // This for the perm_string type. # include "StringHeap.h" +# include "LineInfo.h" # include "verinum.h" # include "named.h" # include "ivl_target.h" @@ -67,6 +68,7 @@ struct enum_type_t { bool signed_flag; std::auto_ptr< list > range; std::auto_ptr< list > names; + LineInfo li; }; diff --git a/t-dll-api.cc b/t-dll-api.cc index 4a7a67a94..d6d1f08a0 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -262,6 +262,24 @@ extern "C" unsigned ivl_enum_width(ivl_enumtype_t net) return net->base_width(); } +extern "C" int ivl_enum_signed(ivl_enumtype_t net) +{ + assert(net); + return net->has_sign(); +} + +extern "C" const char*ivl_enum_file(ivl_enumtype_t net) +{ + assert(net); + return net->get_file().str(); +} + +extern "C" unsigned ivl_enum_lineno(ivl_enumtype_t net) +{ + assert(net); + return net->get_lineno(); +} + extern "C" const char* ivl_event_name(ivl_event_t net) { static char*name_buffer = 0; @@ -291,7 +309,6 @@ extern "C" const char* ivl_event_basename(ivl_event_t net) return net->name; } - extern "C" const char*ivl_event_file(ivl_event_t net) { assert(net); diff --git a/tgt-vhdl/stmt.cc b/tgt-vhdl/stmt.cc index 1053ed00f..7581113df 100644 --- a/tgt-vhdl/stmt.cc +++ b/tgt-vhdl/stmt.cc @@ -767,6 +767,11 @@ static bool draw_synthesisable_wait(vhdl_process *proc, stmt_container *containe set test_nexuses; get_nexuses_from_expr(ivl_stmt_cond_expr(sub_stmt), test_nexuses); + // If the test is not a simple function of one variable then this + // template will not work + if (test_nexuses.size() != 1) + return false; + // Now subtracting this set from the set of edge triggered events // should leave just one nexus, which is hopefully the clock. // If not, then we fall back on the default draw_wait diff --git a/tgt-vvp/draw_enum.c b/tgt-vvp/draw_enum.c index 6567e1c86..61ad79604 100644 --- a/tgt-vvp/draw_enum.c +++ b/tgt-vvp/draw_enum.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Stephen Williams (steve@icarus.com) + * Copyright (c) 2010-2011 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -23,13 +23,36 @@ # include # include +// HERE: This still needs work! Fall back to 'b format for +// very large constants. This should also be int64_t sized values. +// The run time still needs to be modified to work with signed values +// and we also need to pass the file and line information. static void draw_enum2_value(ivl_enumtype_t enumtype, unsigned idx) { - long val = 0; - long mask = 1; + long val, mask; const char*bits = ivl_enum_bits(enumtype, idx); const char*bit; - for (bit = bits, mask = 1 ; bit[0] != 0 ; bit += 1, mask <<= 1) { + unsigned len = strlen(bits); + /* Sign extend if needed. */ + if (ivl_enum_signed(enumtype)) { + assert(len <= sizeof(long)*8); + if ((bits[len-1] == '1') && (len < sizeof(long)*8)) { + val = -1L & ~((1L << len) - 1L); +// HERE: Remove once vvp has been updated. + if (ivl_enum_signed(enumtype)) { + fprintf(stderr, "%s:%u: tgt-vvp sorry: signed " + "enumerations with negative values are not " + "currently supported by vvp.\n", + ivl_enum_file(enumtype), + ivl_enum_lineno(enumtype)); + vvp_errors += 1; + } + } else val = 0; + } else { + assert(len < sizeof(long)*8); + val = 0; + } + for (bit = bits, mask = 1 ; *bit != 0 ; bit += 1, mask <<= 1) { if (*bit == '1') val |= mask; } @@ -42,7 +65,8 @@ static void draw_enum4_value(ivl_enumtype_t enumtype, unsigned idx) const char*bits = ivl_enum_bits(enumtype, idx); const char*bit; - fprintf(vvp_out, "%u'b", ivl_enum_width(enumtype)); + fprintf(vvp_out, "%u'%sb", ivl_enum_width(enumtype), + ivl_enum_signed(enumtype) ? "s" : ""); for (bit = bits+strlen(bits) ; bit > bits ; bit -= 1) fputc(bit[-1], vvp_out); diff --git a/tgt-vvp/eval_real.c b/tgt-vvp/eval_real.c index f5f9dfe59..ce8c10d22 100644 --- a/tgt-vvp/eval_real.c +++ b/tgt-vvp/eval_real.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010 Stephen Williams (steve@icarus.com) + * Copyright (c) 2003-2011 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -25,6 +25,7 @@ # include # include # include +# include static unsigned long word_alloc_mask = 0x0f; @@ -442,6 +443,84 @@ static int draw_ternary_real(ivl_expr_t expr) return res; } +static int increment(ivl_expr_t e, int s, bool pre) +{ + ivl_signal_t sig; + int r; + int one; + + sig = ivl_expr_signal(e); + r = s; + + /* create a temporary word to hold value 1.0 */ + one = allocate_word(); + fprintf(vvp_out, " %%loadi/wr %d, 1, 0x1000; load 1.0\n", one); + + if (!pre) { + /* + * post-increment must return the non-incremented value. + * Therefore, copy the current value in a new word and return + * it. + */ + r = allocate_word(); + fprintf(vvp_out, " %%mov/wr %d, %d;\n", r, s); + } + + fprintf(vvp_out, " %%add/wr %d, %d;\n", s, one); + fprintf(vvp_out, " %%set/wr v%p_0, %d;\n", sig, s); + + return r; +} + +static inline int pre_increment(ivl_expr_t e, int s) +{ + return increment(e, s, true); +} + +static inline int post_increment(ivl_expr_t e, int s) +{ + return increment(e, s, false); +} + +static int decrement(ivl_expr_t e, int s, bool pre) +{ + ivl_signal_t sig; + int r; + int one; + + sig = ivl_expr_signal(e); + r = s; + + /* create a temporary word to hold value 1.0 */ + one = allocate_word(); + fprintf(vvp_out, " %%loadi/wr %d, 1, 0x1000; load 1.0\n", one); + + if (!pre) { + /* + * post-decrement must return the non-incremented value. + * Therefore, copy the current value in a new word and return + * it. + */ + r = allocate_word(); + fprintf(vvp_out, " %%mov/wr %d, %d;\n", r, s); + } + + fprintf(vvp_out, " %%sub/wr %d, %d;\n", s, one); + fprintf(vvp_out, " %%set/wr v%p_0, %d;\n", sig, s); + + return r; +} + +static inline int pre_decrement(ivl_expr_t e, int s) +{ + return decrement(e, s, true); +} + +static inline int post_decrement(ivl_expr_t e, int s) +{ + return decrement(e, s, false); +} + static int draw_unary_real(ivl_expr_t expr) { ivl_expr_t sube; @@ -494,6 +573,20 @@ static int draw_unary_real(ivl_expr_t expr) assert(0); } + switch (ivl_expr_opcode(expr)) { + case 'I': + return pre_increment(sube, sub); + + case 'i': + return post_increment(sube, sub); + + case 'D': + return pre_decrement(sube, sub); + + case 'd': + return post_decrement(sube, sub); + } + fprintf(stderr, "vvp.tgt error: unhandled real unary operator: %c.\n", ivl_expr_opcode(expr)); assert(0); diff --git a/vhdlpp/README.txt b/vhdlpp/README.txt index 2007dd436..e904d94c0 100644 --- a/vhdlpp/README.txt +++ b/vhdlpp/README.txt @@ -47,6 +47,6 @@ in your VHDL code, access packages like this: use bar.test3.all; The *.pkg files are just VHDL code containing only the package with -the same name. When Icarus Verilog encounters the "use ..*;" +the same name. When Icarus Verilog encounters the "use ..*;" statement, it looks for the .pkg file in the library and parses that file to get the package header declared therin. diff --git a/vpi/Makefile.in b/vpi/Makefile.in index ee0542bc1..f692a37c7 100644 --- a/vpi/Makefile.in +++ b/vpi/Makefile.in @@ -87,7 +87,7 @@ clean: rm -f sdf_lexor.c sdf_parse.c sdf_parse.output sdf_parse.h rm -f table_mod_parse.c table_mod_parse.h table_mod_parse.output rm -f table_mod_lexor.c - rm -f va_math.vpi v2005_math.vpi v2009.vpi + rm -f va_math.vpi v2005_math.vpi v2009.vpi vhdl_sys.vpi distclean: clean rm -f Makefile config.log diff --git a/vpi/sys_clog2.c b/vpi/sys_clog2.c index ee29c6105..e19aeecc4 100644 --- a/vpi/sys_clog2.c +++ b/vpi/sys_clog2.c @@ -20,6 +20,7 @@ #include #include #include "vpi_user.h" +#include "sv_vpi_user.h" /* * This routine returns 1 if the argument supports has a numeric value, @@ -42,6 +43,11 @@ static unsigned is_numeric_obj(vpiHandle obj) /* These can have a valid numeric value. */ case vpiIntegerVar: + case vpiBitVar: + case vpiByteVar: + case vpiShortIntVar: + case vpiIntVar: + case vpiLongIntVar: case vpiMemoryWord: case vpiNet: case vpiPartSelect: diff --git a/vpi/sys_display.c b/vpi/sys_display.c index 5b8e5af6b..cf315c97c 100644 --- a/vpi/sys_display.c +++ b/vpi/sys_display.c @@ -916,6 +916,11 @@ static char *get_display(unsigned int *rtnsz, const struct strobe_cb_info *info) case vpiNet: case vpiReg: + case vpiBitVar: + case vpiByteVar: + case vpiShortIntVar: + case vpiIntVar: + case vpiLongIntVar: case vpiIntegerVar: case vpiMemoryWord: case vpiPartSelect: @@ -1438,6 +1443,11 @@ static PLI_INT32 sys_monitor_calltf(ICARUS_VPI_CONST PLI_BYTE8*name) case vpiNet: case vpiReg: case vpiIntegerVar: + case vpiBitVar: + case vpiByteVar: + case vpiShortIntVar: + case vpiIntVar: + case vpiLongIntVar: case vpiRealVar: case vpiPartSelect: /* Monitoring reg and net values involves setting @@ -1798,6 +1808,11 @@ static PLI_INT32 sys_printtimescale_compiletf(ICARUS_VPI_CONST PLI_BYTE8*name) switch (vpi_get(vpiType, arg)) { case vpiFunction: case vpiIntegerVar: + case vpiBitVar: + case vpiByteVar: + case vpiShortIntVar: + case vpiIntVar: + case vpiLongIntVar: case vpiMemory: case vpiMemoryWord: case vpiModule: diff --git a/vpi/sys_fst.c b/vpi/sys_fst.c index 4e0e5a8f0..228e4ea04 100644 --- a/vpi/sys_fst.c +++ b/vpi/sys_fst.c @@ -503,11 +503,16 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) item_type = vpi_get(vpiType, item); switch (item_type) { case vpiNamedEvent: type = FST_VT_VCD_EVENT; break; + case vpiIntVar: case vpiIntegerVar: type = FST_VT_VCD_INTEGER; break; case vpiParameter: type = FST_VT_VCD_PARAMETER; break; /* Icarus converts realtime to real. */ case vpiRealVar: type = FST_VT_VCD_REAL; break; case vpiMemoryWord: + case vpiBitVar: + case vpiByteVar: + case vpiShortIntVar: + case vpiLongIntVar: case vpiReg: type = FST_VT_VCD_REG; break; /* Icarus converts a time to a plain register. */ case vpiTimeVar: type = FST_VT_VCD_TIME; break; @@ -572,6 +577,11 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) case vpiNamedEvent: case vpiIntegerVar: + case vpiBitVar: + case vpiByteVar: + case vpiShortIntVar: + case vpiIntVar: + case vpiLongIntVar: case vpiRealVar: case vpiMemoryWord: case vpiReg: @@ -791,6 +801,11 @@ static PLI_INT32 sys_dumpvars_calltf(ICARUS_VPI_CONST PLI_BYTE8*name) * been included. */ switch (item_type) { case vpiIntegerVar: + case vpiBitVar: + case vpiByteVar: + case vpiShortIntVar: + case vpiIntVar: + case vpiLongIntVar: case vpiMemoryWord: case vpiNamedEvent: case vpiNet: diff --git a/vpi/sys_lxt.c b/vpi/sys_lxt.c index 1576229f8..7879cba81 100644 --- a/vpi/sys_lxt.c +++ b/vpi/sys_lxt.c @@ -557,6 +557,11 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) item = vpi_handle_by_index(array, idx); } case vpiIntegerVar: + case vpiBitVar: + case vpiByteVar: + case vpiShortIntVar: + case vpiIntVar: + case vpiLongIntVar: case vpiTimeVar: case vpiReg: type = "reg"; } diff --git a/vpi/sys_lxt2.c b/vpi/sys_lxt2.c index 3032f6345..0a558138c 100644 --- a/vpi/sys_lxt2.c +++ b/vpi/sys_lxt2.c @@ -620,6 +620,11 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) item = vpi_handle_by_index(array, idx); } case vpiIntegerVar: + case vpiBitVar: + case vpiByteVar: + case vpiShortIntVar: + case vpiIntVar: + case vpiLongIntVar: case vpiTimeVar: case vpiReg: type = "reg"; } diff --git a/vpi/sys_plusargs.c b/vpi/sys_plusargs.c index f4aeae324..f1d5e23f3 100644 --- a/vpi/sys_plusargs.c +++ b/vpi/sys_plusargs.c @@ -109,6 +109,11 @@ static PLI_INT32 sys_value_plusargs_compiletf(ICARUS_VPI_CONST PLI_BYTE8*name) case vpiReg: case vpiIntegerVar: + case vpiBitVar: + case vpiByteVar: + case vpiShortIntVar: + case vpiIntVar: + case vpiLongIntVar: case vpiRealVar: case vpiTimeVar: break; diff --git a/vpi/sys_priv.c b/vpi/sys_priv.c index a71971cd8..f14d5f285 100644 --- a/vpi/sys_priv.c +++ b/vpi/sys_priv.c @@ -169,6 +169,11 @@ unsigned is_numeric_obj(vpiHandle obj) /* These can have a valid numeric value. */ case vpiIntegerVar: + case vpiBitVar: + case vpiByteVar: + case vpiShortIntVar: + case vpiIntVar: + case vpiLongIntVar: case vpiMemoryWord: case vpiNet: case vpiPartSelect: @@ -204,6 +209,11 @@ unsigned is_string_obj(vpiHandle obj) /* These can have a valid string value. */ case vpiIntegerVar: + case vpiBitVar: + case vpiByteVar: + case vpiShortIntVar: + case vpiIntVar: + case vpiLongIntVar: case vpiMemoryWord: case vpiNet: case vpiPartSelect: diff --git a/vpi/sys_queue.c b/vpi/sys_queue.c index f7312c0fc..c45fb63ec 100644 --- a/vpi/sys_queue.c +++ b/vpi/sys_queue.c @@ -493,6 +493,10 @@ static unsigned is_32_or_smaller_obj(vpiHandle obj) /* These can have valid 32 bit or smaller numeric values. */ case vpiIntegerVar: + case vpiBitVar: + case vpiByteVar: + case vpiShortIntVar: + case vpiIntVar: case vpiMemoryWord: case vpiNet: case vpiPartSelect: @@ -518,6 +522,7 @@ static void check_var_arg_32(vpiHandle arg, vpiHandle callh, switch (vpi_get(vpiType, arg)) { case vpiMemoryWord: case vpiPartSelect: + case vpiBitVar: case vpiReg: // Check that we have exactly 32 bits. if (vpi_get(vpiSize, arg) != 32) { vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), @@ -527,6 +532,7 @@ static void check_var_arg_32(vpiHandle arg, vpiHandle callh, vpi_control(vpiFinish, 1); } case vpiIntegerVar: + case vpiIntVar: break; default: vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), @@ -548,6 +554,7 @@ static void check_var_arg_large(vpiHandle arg, vpiHandle callh, switch (vpi_get(vpiType, arg)) { case vpiMemoryWord: case vpiPartSelect: + case vpiBitVar: case vpiReg: // Check that we have at least 32 bits. if (vpi_get(vpiSize, arg) < 32) { vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), @@ -557,6 +564,8 @@ static void check_var_arg_large(vpiHandle arg, vpiHandle callh, vpi_control(vpiFinish, 1); } case vpiIntegerVar: + case vpiIntVar: + case vpiLongIntVar: case vpiTimeVar: break; default: diff --git a/vpi/sys_random.c b/vpi/sys_random.c index 67d10ad9a..2193b3140 100644 --- a/vpi/sys_random.c +++ b/vpi/sys_random.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2010 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2011 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -374,9 +374,22 @@ static unsigned is_seed_obj(vpiHandle obj, vpiHandle callh, const char *name) switch (vpi_get(vpiType, obj)) { case vpiTimeVar: case vpiIntegerVar: - case vpiReg: + case vpiIntVar: + case vpiLongIntVar: rtn = 1; break; + case vpiBitVar: + case vpiReg: + if (vpi_get(vpiSize, obj) < 32) { + vpi_printf("Error: %s:%d: ", + vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("%s's seed variable is less than 32 bits " + " (%d).\n", name, + (int)vpi_get(vpiSize, obj)); + vpi_control(vpiFinish, 1); + } else rtn = 1; + break; default: vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); diff --git a/vpi/sys_scanf.c b/vpi/sys_scanf.c index 896a2af0a..440661eba 100644 --- a/vpi/sys_scanf.c +++ b/vpi/sys_scanf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2010 Stephen Williams (steve@icarus.com) + * Copyright (c) 2006-2011 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -552,6 +552,11 @@ static int is_assignable_obj(vpiHandle obj) case vpiPartSelect: if (! is_assignable_obj(vpi_handle(vpiParent, obj))) break; case vpiIntegerVar: + case vpiBitVar: + case vpiByteVar: + case vpiShortIntVar: + case vpiIntVar: + case vpiLongIntVar: case vpiRealVar: case vpiReg: case vpiTimeVar: diff --git a/vpi/sys_vcd.c b/vpi/sys_vcd.c index e027608af..22ba24621 100644 --- a/vpi/sys_vcd.c +++ b/vpi/sys_vcd.c @@ -532,11 +532,16 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) item_type = vpi_get(vpiType, item); switch (item_type) { case vpiNamedEvent: type = "event"; break; + case vpiIntVar: case vpiIntegerVar: type = "integer"; break; case vpiParameter: type = "parameter"; break; /* Icarus converts realtime to real. */ case vpiRealVar: type = "real"; break; case vpiMemoryWord: + case vpiBitVar: + case vpiByteVar: + case vpiShortIntVar: + case vpiLongIntVar: case vpiReg: type = "reg"; break; /* Icarus converts a time to a plain register. */ case vpiTimeVar: type = "time"; break; @@ -601,12 +606,18 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) case vpiNamedEvent: case vpiIntegerVar: + case vpiBitVar: + case vpiByteVar: + case vpiShortIntVar: + case vpiIntVar: + case vpiLongIntVar: case vpiRealVar: case vpiMemoryWord: case vpiReg: case vpiTimeVar: case vpiNet: + /* If we are skipping all signal or this is in an automatic * scope then just return. */ if (skip || vpi_get(vpiAutomatic, item)) return; @@ -787,6 +798,11 @@ static PLI_INT32 sys_dumpvars_calltf(ICARUS_VPI_CONST PLI_BYTE8*name) * been included. */ switch (item_type) { case vpiIntegerVar: + case vpiBitVar: + case vpiByteVar: + case vpiShortIntVar: + case vpiIntVar: + case vpiLongIntVar: case vpiMemoryWord: case vpiNamedEvent: case vpiNet: diff --git a/vpi/vcd_priv.c b/vpi/vcd_priv.c index dcbb59fbe..e95a87309 100644 --- a/vpi/vcd_priv.c +++ b/vpi/vcd_priv.c @@ -189,6 +189,11 @@ PLI_INT32 sys_dumpvars_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name) case vpiNet: case vpiReg: case vpiIntegerVar: + case vpiBitVar: + case vpiByteVar: + case vpiShortIntVar: + case vpiIntVar: + case vpiLongIntVar: case vpiTimeVar: case vpiRealVar: case vpiNamedEvent: diff --git a/vvp/main.cc b/vvp/main.cc index 68e0ef42c..cb2f63d5b 100644 --- a/vvp/main.cc +++ b/vvp/main.cc @@ -263,18 +263,25 @@ int main(int argc, char*argv[]) so we chop the file name and the last directory by turning the last two \ characters to null. Then we append the lib\ivl$(suffix) to finish. */ - { char *s; - char basepath[4096], tmp[4096]; - GetModuleFileName(NULL, tmp, sizeof tmp); - /* Convert to a short name to remove any embedded spaces. */ - GetShortPathName(tmp, basepath, sizeof basepath); - s = strrchr(basepath, '\\'); - if (s) *s = 0; - s = strrchr(basepath, '\\'); - if (s) *s = 0; - strcat(s, "\\lib\\ivl" IVL_SUFFIX); - vpip_module_path[0] = strdup(basepath); + char *s; + char basepath[4096], tmp[4096]; + GetModuleFileName(NULL, tmp, sizeof tmp); + /* Convert to a short name to remove any embedded spaces. */ + GetShortPathName(tmp, basepath, sizeof basepath); + s = strrchr(basepath, '\\'); + if (s) *s = 0; + else { + fprintf(stderr, "%s: Missing first \\ in exe path!\n", argv[0]); + exit(1); } + s = strrchr(basepath, '\\'); + if (s) *s = 0; + else { + fprintf(stderr, "%s: Missing second \\ in exe path!\n", argv[0]); + exit(1); + } + strcat(s, "\\lib\\ivl" IVL_SUFFIX); + vpip_module_path[0] = strdup(basepath); #endif /* For non-interactive runs we do not want to run the interactive diff --git a/vvp/parse.y b/vvp/parse.y index 23bab0337..5b7a310f1 100644 --- a/vvp/parse.y +++ b/vvp/parse.y @@ -682,10 +682,10 @@ statement | T_LABEL K_VAR_I local_flag T_STRING ',' T_NUMBER T_NUMBER ';' { compile_variable($1, $4, $6, $7, vpiIntegerVar, true, $3); } - | T_LABEL K_VAR_2S local_flag T_STRING ',' T_NUMBER T_NUMBER ';' + | T_LABEL K_VAR_2S local_flag T_STRING ',' signed_t_number signed_t_number ';' { compile_variable($1, $4, $6, $7, vpiIntVar, true, $3); } - | T_LABEL K_VAR_2U local_flag T_STRING ',' T_NUMBER T_NUMBER ';' + | T_LABEL K_VAR_2U local_flag T_STRING ',' signed_t_number signed_t_number ';' { compile_variable($1, $4, $6, $7, vpiIntVar, false, $3); } | T_LABEL K_VAR_R T_STRING ',' signed_t_number signed_t_number ';' diff --git a/vvp/vpi_callback.cc b/vvp/vpi_callback.cc index 201b3aa12..1ff3b9352 100644 --- a/vvp/vpi_callback.cc +++ b/vvp/vpi_callback.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2010 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2011 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -148,6 +148,11 @@ static struct __vpiCallback* make_value_change(p_cb_data data) case vpiReg: case vpiNet: case vpiIntegerVar: + case vpiBitVar: + case vpiByteVar: + case vpiShortIntVar: + case vpiIntVar: + case vpiLongIntVar: /* Attach the callback to the vvp_fun_signal node by putting it in the vpi_callbacks list. */ struct __vpiSignal*sig; diff --git a/vvp/vpi_priv.cc b/vvp/vpi_priv.cc index 5696344e1..a009be2fa 100644 --- a/vvp/vpi_priv.cc +++ b/vvp/vpi_priv.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2010 Stephen Williams (steve@icarus.com) + * Copyright (c) 2008-2011 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -256,6 +256,8 @@ static const char* vpi_type_values(PLI_INT32 code) { static char buf[32]; switch (code) { + case vpiBitVar: + return "vpiBitVar"; case vpiByteVar: return "vpiByteVar"; case vpiConstant: diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index 71c859fbc..68272c41c 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -263,7 +263,7 @@ extern unsigned vpip_size(__vpiSignal *sig); extern struct __vpiScope* vpip_scope(__vpiSignal*sig); extern vpiHandle vpip_make_int2(const char*name, int msb, int lsb, - vvp_net_t*vec); + bool signed_flag, vvp_net_t*vec); extern vpiHandle vpip_make_int4(const char*name, int msb, int lsb, vvp_net_t*vec); extern vpiHandle vpip_make_var4(const char*name, int msb, int lsb, diff --git a/vvp/vpi_scope.cc b/vvp/vpi_scope.cc index 45afce324..084cd064f 100644 --- a/vvp/vpi_scope.cc +++ b/vvp/vpi_scope.cc @@ -270,8 +270,13 @@ static int compare_types(int code, int type) return 1; if ( code == vpiVariables && - (type == vpiIntegerVar || - type == vpiTimeVar || + (type == vpiIntegerVar || + type == vpiBitVar || + type == vpiByteVar || + type == vpiShortIntVar || + type == vpiIntVar || + type == vpiLongIntVar || + type == vpiTimeVar || type == vpiRealVar)) return 1; diff --git a/vvp/vpi_signal.cc b/vvp/vpi_signal.cc index f51ccee52..08df4e1ce 100644 --- a/vvp/vpi_signal.cc +++ b/vvp/vpi_signal.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2010 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2011 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -996,31 +996,39 @@ vpiHandle vpip_make_int4(const char*name, int msb, int lsb, vvp_net_t*vec) } /* - * Construct a vpi + * Construct the two-state SystemVerilog variables. */ -vpiHandle vpip_make_int2(const char*name, int msb, int lsb, vvp_net_t*vec) +vpiHandle vpip_make_int2(const char*name, int msb, int lsb, bool signed_flag, + vvp_net_t*vec) { - vpiHandle obj = vpip_make_net4(name, msb,lsb, true, vec); + vpiHandle obj = vpip_make_net4(name, msb, lsb, signed_flag, vec); - assert(lsb == 0); - switch (msb) { - case 7: - obj->vpi_type = &vpip_byte_rt; - break; - case 15: - obj->vpi_type = &vpip_shortint_rt; - break; - case 31: - obj->vpi_type = &vpip_int_rt; - break; - case 63: - obj->vpi_type = &vpip_longint_rt; - break; - default: - // Every other type of bit vector is a vpiBitVar with - // array dimensions. + // All unsigned 2-state variables are a vpiBitVar. All 2-state + // variables with a non-zero lsb are also a vpiBitVar. + if ((! signed_flag) || (lsb != 0) ) { obj->vpi_type = &vpip_bitvar_rt; - break; + } else { + // These could also be bit declarations with matching + // information, but for now they get the apparent type. + switch (msb) { + case 7: + obj->vpi_type = &vpip_byte_rt; + break; + case 15: + obj->vpi_type = &vpip_shortint_rt; + break; + case 31: + obj->vpi_type = &vpip_int_rt; + break; + case 63: + obj->vpi_type = &vpip_longint_rt; + break; + default: + // Every other type of bit vector is a vpiBitVar with + // array dimensions. + obj->vpi_type = &vpip_bitvar_rt; + break; + } } return obj; diff --git a/vvp/vthread.cc b/vvp/vthread.cc index a6042f652..78980de0e 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -2034,7 +2034,7 @@ static unsigned long divide2words(unsigned long a, unsigned long b, remain += 1; if (remain >= b) { remain -= b; - result += 1; + tmp_result += 1; } // Now 0x1_0...0 = b*tmp_result + remain @@ -2050,7 +2050,9 @@ static unsigned long divide2words(unsigned long a, unsigned long b, // The new iteration starts with high*remain + a. remain = multiply_with_carry(high, remain, high); - a = add_with_carry(a, remain, high); + a += remain; + if(a < remain) + high += 1; // Now result*b + {high,a} == the input {high,a}. It is // possible that the new high >= 1. If so, it will diff --git a/vvp/words.cc b/vvp/words.cc index 9485cc257..a1168223f 100644 --- a/vvp/words.cc +++ b/vvp/words.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010 Stephen Williams (steve@icarus.com) + * Copyright (c) 2003-2011 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -117,7 +117,7 @@ void compile_variable(char*label, char*name, obj = vpip_make_int4(name, msb, lsb, net); break; case vpiIntVar: // This handles all the atom2 int types - obj = vpip_make_int2(name, msb, lsb, net); + obj = vpip_make_int2(name, msb, lsb, signed_flag, net); break; default: fprintf(stderr, "internal error: %s: vpi_type_code=%d\n", name, vpi_type_code);