Fix some enum bugs.
This patch fixes a few more bugs in the enumeration code. It add support for saving the file and line information to make diagnostic messages better. It updates some of the compiler warning messages to use the file and line information. It passes if the enumeration type is signed all the way to the code generators. It fixes the parser to correctly have the range after the signed designation for the vector types. It adds a warning that vvp does not currently support a negative two state enumeration value.
This commit is contained in:
parent
f3522e98f1
commit
b2ebc29c5a
|
|
@ -1834,7 +1834,7 @@ 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;
|
||||
signed_flag_ = par_enum->has_sign();
|
||||
|
||||
return expr_width_;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<NetEConst*> (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;
|
||||
}
|
||||
|
|
|
|||
5
ivl.def
5
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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 <vector>
|
||||
# include <map>
|
||||
|
||||
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
|
||||
|
|
|
|||
18
parse.y
18
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;
|
||||
}
|
||||
;
|
||||
|
|
|
|||
3
pform.cc
3
pform.cc
|
|
@ -2508,6 +2508,9 @@ void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type, list<perm_st
|
|||
assert(enum_type->range.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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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<PExpr*> > range;
|
||||
std::auto_ptr< list<named_pexpr_t> > names;
|
||||
LineInfo li;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
19
t-dll-api.cc
19
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);
|
||||
|
|
|
|||
|
|
@ -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 <string.h>
|
||||
# include <assert.h>
|
||||
|
||||
// HERE: This still needs work! Fall back to <width>'<signed>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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue