diff --git a/elab_expr.cc b/elab_expr.cc index ec2bc5643..20e7b4f4c 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -1833,8 +1833,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_; } diff --git a/elab_scope.cc b/elab_scope.cc index da9030141..e1492c331 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 a75c4f893..90d1233ef 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-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);