From 503a1bf6d7d22e87769d851c7fe523e455a615c0 Mon Sep 17 00:00:00 2001 From: Cary R Date: Wed, 18 Dec 2013 18:52:00 -0800 Subject: [PATCH 01/16] Add support for the array querying function in a constant context This patchs adds support for the $dimensions() and $unpacked_dimensions() array functions. Since the argument is only used to get the type information these functions can always be evaluated at compile time. For the following functions if the dimension argument is constant or omitted and the first argument is not dynamic (a string or dynamic array) they will return the specified information. $left(), $right(), $high(), $low(), $increment() and $size() Dynamic information and a variable second argument will be implement in a future patch. --- eval_tree.cc | 227 ++++++++++++++++++++++++++++++++++++++++++++++++++- netlist.h | 90 +++++++++++++------- 2 files changed, 287 insertions(+), 30 deletions(-) diff --git a/eval_tree.cc b/eval_tree.cc index 8f18a760d..b0e675394 100644 --- a/eval_tree.cc +++ b/eval_tree.cc @@ -1923,6 +1923,173 @@ NetExpr* NetESFunc::evaluate_min_max_(ID id, const NetExpr*arg0_, return res; } +NetEConst* NetESFunc::evaluate_countbits_(const NetExpr* /*arg0*/, + const NetExpr* /*arg1*/) const +{ + return 0; +} + +NetEConst* NetESFunc::evaluate_countones_(const NetExpr* /*arg*/) const +{ + return 0; +} + +/* Get the total number of dimensions for the given expression. */ +NetEConst* NetESFunc::evaluate_dimensions_(const NetExpr*arg) const +{ + const NetESignal*esig = dynamic_cast(arg); + long res = 0; + if (esig != 0) { + const NetNet *sig = esig->sig(); + res = sig->packed_dimensions() + sig->unpacked_dimensions(); + /* Icarus does not think a string has a packed size so to + * make these routines work correct add one if this is a + * string data type. */ + if (sig->data_type() == IVL_VT_STRING) { + assert(sig->packed_dimensions() == 0); + res += 1; + } + } + /* Return the result as an integer sized constant. */ + return new NetEConst(verinum(verinum(res), integer_width)); +} + +NetEConst* NetESFunc::evaluate_isunknown_(const NetExpr* /*arg*/) const +{ + return 0; +} + +NetEConst* NetESFunc::evaluate_onehot_(const NetExpr* /*arg*/) const +{ + return 0; +} + +NetEConst* NetESFunc::evaluate_onehot0_(const NetExpr* /*arg*/) const +{ + return 0; +} + +/* Get the number of unpacked dimensions for the given expression. */ +NetEConst* NetESFunc::evaluate_unpacked_dimensions_(const NetExpr*arg) const +{ + const NetESignal*esig = dynamic_cast(arg); + long res = 0; + if (esig != 0) { + const NetNet *sig = esig->sig(); + res = sig->unpacked_dimensions(); + } + /* Return the result as an integer sized constant. */ + return new NetEConst(verinum(verinum(res), integer_width)); +} + +/* This code assumes that the dimension value will fit in a long. + * Return true if no constant dimension value is available. */ +static bool check_dimension(const NetExpr*dim_expr, long &dim) +{ + const NetEConst*dimi = dynamic_cast(dim_expr); + const NetECReal*dimr = dynamic_cast(dim_expr); + if (dimi == 0 && dimr == 0) return true; + + if (dimi) dim = dimi->value().as_long(); + if (dimr) dim = dimr->value().as_long(); + return false; +} + +/* Get the left and right values for the argument at the given dimension + * if it exists. Return true if no values are available. */ +static bool get_array_info(const NetExpr*arg, long dim, + long &left, long &right, bool&defer) +{ + /* The argument must be a signal that has enough dimensions. */ + const NetESignal*esig = dynamic_cast(arg); + if (esig == 0) return true; + const NetNet *sig = esig->sig(); + /* A string or dynamic array must be handled by the run time. */ + defer = false; + switch (sig->data_type()) { + case IVL_VT_DARRAY: + case IVL_VT_STRING: + defer = true; + return true; + break; + default: + break; + } + long pdims = sig->packed_dimensions(); + long updims = sig->unpacked_dimensions(); + if (dim > (pdims + updims)) return true; + /* Get the appropriate unpacked or packed dimension information. */ + if (dim > updims) { + const vector&dim_vals = sig->packed_dims(); + const netrange_t&range = dim_vals[dim-updims-1]; + left = range.get_msb(); + right = range.get_lsb(); + } else { + const vector&dim_vals = sig->unpacked_dims(); + const netrange_t&range = dim_vals[dim-1]; + left = range.get_msb(); + right = range.get_lsb(); + } + return false; +} + +/* Calculate the array property functions. */ +NetEConst* NetESFunc::evaluate_array_funcs_(ID id, + const NetExpr*arg0, + const NetExpr*arg1) const +{ + long dim = 0; + /* Check to see if the dimension argument is constant. */ + if (check_dimension(arg1, dim)) return 0; + /* If dimension is less than 1 return undefined. */ + if (dim < 1) { + return new NetEConst(verinum(verinum::Vx, integer_width)); + } + /* Get the left/right information for this dimension if it exists. */ + long left = 0; + long right = 0; + bool defer; + if (get_array_info(arg0, dim, left, right, defer)) { + /* If this is a string or dynamic array defer this function + * call since the left/right information is dynamic and is + * not available yet. */ + if (defer) return 0; + return new NetEConst(verinum(verinum::Vx, integer_width)); + } + /* Calculate the appropriate array function result. */ + long res; + switch (id) { + case HIGH: + res = (right > left) ? right : left; + break; + case INCR: + res = (right > left) ? -1 : 1; + break; + case LEFT: + res = left; + break; + case LOW: + res = (right > left) ? left : right; + break; + case RIGHT: + res = right; + break; + case SIZE: + res = (right > left) ? right - left : left - right; + res += 1; + break; + default: + res = 0; + assert(0); + } + /* Return the result as an integer sized constant. */ + return new NetEConst(verinum(verinum(res), integer_width)); +} + +/* Make a constant one value that can be used by the one argument + * array properties calls. */ +const NetEConst* NetESFunc::const_one_ = new NetEConst(verinum(1U, 32U)); + NetExpr* NetESFunc::evaluate_one_arg_(ID id, const NetExpr*arg) const { switch (id) { @@ -1930,21 +2097,51 @@ NetExpr* NetESFunc::evaluate_one_arg_(ID id, const NetExpr*arg) const return evaluate_abs_(arg); case CLOG2: return evaluate_clog2_(arg); + case CTONES: + return evaluate_countones_(arg); + case DIMS: + return evaluate_dimensions_(arg); + /* The array functions are handled together. */ + case HIGH: + case INCR: + case LEFT: + case LOW: + case RIGHT: + case SIZE: + return evaluate_array_funcs_(id, arg, const_one_); + case ISUNKN: + return evaluate_isunknown_(arg); case ITOR: return evaluate_itor_(arg); + case ONEHT: + return evaluate_onehot_(arg); + case ONEHT0: + return evaluate_onehot0_(arg); case RTOI: return evaluate_rtoi_(arg); + case UPDIMS: + return evaluate_unpacked_dimensions_(arg); default: return evaluate_math_one_arg_(id, arg); } } NetExpr* NetESFunc::evaluate_two_arg_(ID id, const NetExpr*arg0, - const NetExpr*arg1) const + const NetExpr*arg1) const { switch (id) { - case MIN: + case CTBITS: + return evaluate_countbits_(arg0, arg1); + /* The array functions are handled together. */ + case HIGH: + case INCR: + case LEFT: + case LOW: + case RIGHT: + case SIZE: + return evaluate_array_funcs_(id, arg0, arg1); case MAX: + case MIN: return evaluate_min_max_(id, arg0, arg1); default: return evaluate_math_two_arg_(id, arg0, arg1); @@ -1990,6 +2187,31 @@ NetESFunc::ID NetESFunc::built_in_id_() const built_in_func["$tanh" ] = TANH; } + /* These are available in 1800-2005 and later. */ + if (funcs_need_init && (generation_flag >= GN_VER2005_SV)) { + built_in_func["$dimensions" ] = DIMS; + built_in_func["$high" ] = HIGH; + built_in_func["$increment" ] = INCR; + built_in_func["$isunknown" ] = ISUNKN; + built_in_func["$left" ] = LEFT; + built_in_func["$low" ] = LOW; + built_in_func["$onehot" ] = ONEHT; + built_in_func["$onehot0" ] = ONEHT0; + built_in_func["$right" ] = RIGHT; + built_in_func["$size" ] = SIZE; + built_in_func["$unpacked_dimensions" ] = UPDIMS; + } + + /* These are available in 1800-2009 and later. */ + if (funcs_need_init && (generation_flag >= GN_VER2009)) { + built_in_func["$countones" ] = CTONES; + } + + /* These are available in 1800-2012 and later. */ + if (funcs_need_init && (generation_flag >= GN_VER2012)) { + built_in_func["$countbits" ] = CTBITS; + } + /* These are available in Verilog-A as Icarus extensions or if the * Icarus misc flag was given. */ if (funcs_need_init && (gn_verilog_ams_flag || gn_icarus_misc_flag)) { @@ -2045,6 +2267,7 @@ NetExpr* NetESFunc::eval_tree() << " arguments." << endl; return 0; } +// HERE: Need to add support for a multi argument $countbits(). cerr << get_fileline() << ": sorry: functions with " << parms_.size() << " arguments are not supported: " << name_ << "()." << endl; diff --git a/netlist.h b/netlist.h index 78cbb6a5c..1f2a3ddbe 100644 --- a/netlist.h +++ b/netlist.h @@ -4176,37 +4176,53 @@ class NetESFunc : public NetExpr { */ enum ID { NOT_BUILT_IN = 0x0, /* Available in all version of Verilog/SystemVerilog. */ - ITOR = 0x00020001, /* $itor takes one argument. */ - RTOI = 0x00020002, /* $rtoi takes one argument. */ + ITOR = 0x00020001, /* $itor takes one argument. */ + RTOI = 0x00020002, /* $rtoi takes one argument. */ /* Available in Verilog 2005 and later. */ - ACOS = 0x00020003, /* $acos takes one argument. */ - ACOSH = 0x00020004, /* $acosh takes one argument. */ - ASIN = 0x00020005, /* $asin takes one argument. */ - ASINH = 0x00020006, /* $asinh takes one argument. */ - ATAN = 0x00020007, /* $atan takes one argument. */ - ATANH = 0x00020008, /* $atanh takes one argument. */ - ATAN2 = 0x00040009, /* $atan2 takes two argument. */ - CEIL = 0x0002000a, /* $ceil takes one argument. */ - CLOG2 = 0x0002000b, /* $clog2 takes one argument. */ - COS = 0x0002000c, /* $cos takes one argument. */ - COSH = 0x0002000d, /* $cosh takes one argument. */ - EXP = 0x0002000e, /* $exp takes one argument. */ - FLOOR = 0x0002000f, /* $floor takes one argument. */ - HYPOT = 0x00040010, /* $hypot takes two argument. */ - LN = 0x00020011, /* $ln takes one argument. */ - LOG10 = 0x00020012, /* $log10 takes one argument. */ - POW = 0x00040013, /* $pow takes two argument. */ - SIN = 0x00020014, /* $sin takes one argument. */ - SINH = 0x00020015, /* $sinh takes one argument. */ - SQRT = 0x00020016, /* $sqrt takes one argument. */ - TAN = 0x00020017, /* $tan takes one argument. */ - TANH = 0x00020018, /* $tanh takes one argument. */ + ACOS = 0x00020003, /* $acos takes one argument. */ + ACOSH = 0x00020004, /* $acosh takes one argument. */ + ASIN = 0x00020005, /* $asin takes one argument. */ + ASINH = 0x00020006, /* $asinh takes one argument. */ + ATAN = 0x00020007, /* $atan takes one argument. */ + ATANH = 0x00020008, /* $atanh takes one argument. */ + ATAN2 = 0x00040009, /* $atan2 takes two argument. */ + CEIL = 0x0002000a, /* $ceil takes one argument. */ + CLOG2 = 0x0002000b, /* $clog2 takes one argument. */ + COS = 0x0002000c, /* $cos takes one argument. */ + COSH = 0x0002000d, /* $cosh takes one argument. */ + EXP = 0x0002000e, /* $exp takes one argument. */ + FLOOR = 0x0002000f, /* $floor takes one argument. */ + HYPOT = 0x00040010, /* $hypot takes two argument. */ + LN = 0x00020011, /* $ln takes one argument. */ + LOG10 = 0x00020012, /* $log10 takes one argument. */ + POW = 0x00040013, /* $pow takes two argument. */ + SIN = 0x00020014, /* $sin takes one argument. */ + SINH = 0x00020015, /* $sinh takes one argument. */ + SQRT = 0x00020016, /* $sqrt takes one argument. */ + TAN = 0x00020017, /* $tan takes one argument. */ + TANH = 0x00020018, /* $tanh takes one argument. */ + /* Added in SystemVerilog 2005 and later. */ + DIMS = 0x00020019, /* $dimensions takes one argument. */ + HIGH = 0x0006001a, /* $high takes one or two arguments. */ + INCR = 0x0006001b, /* $increment takes one or two arguments. */ + LEFT = 0x0006001c, /* $left takes one or two arguments. */ + LOW = 0x0006001d, /* $low takes one or two arguments. */ + RIGHT = 0x0006001e, /* $right takes one or two arguments. */ + SIZE = 0x0006001f, /* $size takes one or two arguments. */ + UPDIMS = 0x00020020, /* $unpacked_dimensions takes one argument. */ + ISUNKN = 0x00020021, /* $isunknown takes one argument. */ + ONEHT = 0x00020022, /* $onehot takes one argument. */ + ONEHT0 = 0x00020023, /* $onehot0 takes one argument. */ + /* Added in SystemVerilog 2009 and later. */ + CTONES = 0x00020024, /* $countones takes one argument. */ + /* Added in SystemVerilog 2012 and later. */ + CTBITS = 0xfffe0025, /* $countbits takes one or more arguments. */ /* Added as Icarus extensions to Verilog-A. */ - ABS = 0x00020019, /* $abs takes one argument. */ - MAX = 0x0004001a, /* $max takes two argument. */ - MIN = 0x0004001b, /* $min takes two argument. */ + ABS = 0x00020026, /* $abs takes one argument. */ + MAX = 0x00040027, /* $max takes two argument. */ + MIN = 0x00040028, /* $min takes two argument. */ /* A dummy value to properly close the enum. */ - DUMMY = 0xffffffff }; + DUMMY = 0xffffffff }; bool takes_nargs_(ID func, unsigned nargs) { if (nargs > 15) nargs = 15; @@ -4237,6 +4253,24 @@ class NetESFunc : public NetExpr { NetExpr* evaluate_min_max_(ID id, const NetExpr*arg0, const NetExpr*arg1) const; + /* Constant SystemVerilog functions. */ + NetEConst* evaluate_countones_(const NetExpr*arg) const; + NetEConst* evaluate_dimensions_(const NetExpr*arg) const; + NetEConst* evaluate_isunknown_(const NetExpr*arg) const; + NetEConst* evaluate_onehot_(const NetExpr*arg) const; + NetEConst* evaluate_onehot0_(const NetExpr*arg) const; + NetEConst* evaluate_unpacked_dimensions_(const NetExpr*arg) const; + + /* This value is used as a default when the array functions are + * called with a single argument. */ + static const NetEConst*const_one_; + + NetEConst* evaluate_array_funcs_(ID id, + const NetExpr*arg0, + const NetExpr*arg1) const; + NetEConst* evaluate_countbits_(const NetExpr*arg0, + const NetExpr*arg1) const; + public: bool is_built_in() const { return built_in_id_() != NOT_BUILT_IN; }; From 4def0110b53228f74948a4e36412552df4f2e404 Mon Sep 17 00:00:00 2001 From: Cary R Date: Thu, 19 Dec 2013 09:19:18 -0800 Subject: [PATCH 02/16] Fix compile warning. --- eval_tree.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/eval_tree.cc b/eval_tree.cc index b0e675394..36f3bad78 100644 --- a/eval_tree.cc +++ b/eval_tree.cc @@ -1996,7 +1996,8 @@ static bool check_dimension(const NetExpr*dim_expr, long &dim) } /* Get the left and right values for the argument at the given dimension - * if it exists. Return true if no values are available. */ + * if it exists. Return true if no values are available. Set defer to true + * if this should be handled in the run time. */ static bool get_array_info(const NetExpr*arg, long dim, long &left, long &right, bool&defer) { @@ -2005,7 +2006,6 @@ static bool get_array_info(const NetExpr*arg, long dim, if (esig == 0) return true; const NetNet *sig = esig->sig(); /* A string or dynamic array must be handled by the run time. */ - defer = false; switch (sig->data_type()) { case IVL_VT_DARRAY: case IVL_VT_STRING: @@ -2048,7 +2048,7 @@ NetEConst* NetESFunc::evaluate_array_funcs_(ID id, /* Get the left/right information for this dimension if it exists. */ long left = 0; long right = 0; - bool defer; + bool defer = false; if (get_array_info(arg0, dim, left, right, defer)) { /* If this is a string or dynamic array defer this function * call since the left/right information is dynamic and is From e4fc5806c4ecf152791c99bea14d67967d140c64 Mon Sep 17 00:00:00 2001 From: Cary R Date: Thu, 19 Dec 2013 20:37:55 -0800 Subject: [PATCH 03/16] vlog95: spelling fixes --- tgt-vlog95/scope.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tgt-vlog95/scope.c b/tgt-vlog95/scope.c index 72a58ccd3..59657e7b2 100644 --- a/tgt-vlog95/scope.c +++ b/tgt-vlog95/scope.c @@ -917,8 +917,8 @@ static unsigned has_func_disable(ivl_scope_t scope, ivl_statement_t stmt) rtn = scope == ivl_stmt_call(stmt); break; default: - fprintf(stderr, "%s:%u: vlog95 error: Unknown statment type (%d) " - "in functin disable check.\n", + fprintf(stderr, "%s:%u: vlog95 error: Unknown statement type (%d) " + "in function disable check.\n", ivl_stmt_file(stmt), ivl_stmt_lineno(stmt), (int)ivl_statement_type(stmt)); @@ -1187,7 +1187,7 @@ int emit_scope(ivl_scope_t scope, ivl_scope_t parent) name_return); free(name_return); } else emit_stmt(scope, body); - /* A non-block statment may need a named block for a return. */ + /* A non-block statement may need a named block for a return. */ } else if (has_func_disable(scope, body)) { char *name_return = get_func_return_name(scope); fprintf(vlog_out, "%*cbegin: %s\n", indent, ' ', From 7fa2a4ccf3494fd808dc4cf76d20ce81d6099260 Mon Sep 17 00:00:00 2001 From: Cary R Date: Thu, 19 Dec 2013 20:38:48 -0800 Subject: [PATCH 04/16] vlog95: add support for emitting nested class L-values --- tgt-vlog95/stmt.c | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/tgt-vlog95/stmt.c b/tgt-vlog95/stmt.c index 0cf39039d..530c9e471 100644 --- a/tgt-vlog95/stmt.c +++ b/tgt-vlog95/stmt.c @@ -214,16 +214,27 @@ static void emit_stmt_lval_darray(ivl_scope_t scope, ivl_lval_t lval, * Class or class properties are not supported in vlog95, but this assignment * can be translated correctly. */ -static void emit_stmt_lval_class(ivl_scope_t scope, ivl_lval_t lval, - ivl_signal_t sig) +static ivl_type_t emit_stmt_lval_class(ivl_scope_t scope, ivl_lval_t lval) { + ivl_lval_t nest = ivl_lval_nest(lval); + ivl_signal_t sig = ivl_lval_sig(lval); + ivl_type_t type; int idx = ivl_lval_property_idx(lval); - emit_scope_call_path(scope, ivl_signal_scope(sig)); - emit_id(ivl_signal_basename(sig)); - if (idx >= 0) { - ivl_type_t sig_type = ivl_signal_net_type(sig); - fprintf(vlog_out, ".%s", ivl_type_prop_name(sig_type, idx)); + + if (nest) { + type = emit_stmt_lval_class(scope, nest); + assert(type); + } else { + assert(sig); + emit_scope_call_path(scope, ivl_signal_scope(sig)); + emit_id(ivl_signal_basename(sig)); + type = ivl_signal_net_type(sig); } + + if (idx >= 0) { + fprintf(vlog_out, ".%s", ivl_type_prop_name(type, idx)); + return ivl_type_prop_type(type, idx); + } else return 0; } static void emit_stmt_lval_piece(ivl_scope_t scope, ivl_lval_t lval) @@ -234,14 +245,20 @@ static void emit_stmt_lval_piece(ivl_scope_t scope, ivl_lval_t lval) unsigned width = ivl_lval_width(lval); int msb, lsb; assert(width > 0); - assert(sig); + + /* A class supports a nested L-value so it may not have a signal + * at this level. */ + if (! sig) { + (void) emit_stmt_lval_class(scope, lval); + return; + } switch (ivl_signal_data_type(sig)) { case IVL_VT_DARRAY: emit_stmt_lval_darray(scope, lval, sig); return; case IVL_VT_CLASS: - emit_stmt_lval_class(scope, lval, sig); + (void) emit_stmt_lval_class(scope, lval); return; default: break; From 336b29955d7674130a49755040962a6c4098acd0 Mon Sep 17 00:00:00 2001 From: Cary R Date: Thu, 19 Dec 2013 20:40:35 -0800 Subject: [PATCH 05/16] vlog95: a zero width expression is special and is not a self determined context --- tgt-vlog95/expr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tgt-vlog95/expr.c b/tgt-vlog95/expr.c index 5d97e191f..e8f6810ad 100644 --- a/tgt-vlog95/expr.c +++ b/tgt-vlog95/expr.c @@ -267,8 +267,9 @@ static expr_sign_t expr_get_sign_type(ivl_expr_t expr, unsigned wid, break; } - /* Check for a self-determined context. */ - if ((rtn == NO_SIGN) && (wid != expr_wid) && + /* Check for a self-determined context. A zero width expression + * is special and is not considered a self determined context. */ + if ((rtn == NO_SIGN) && (wid != expr_wid) && expr_wid && ! (is_full_prec && ((expr_wid < wid) || (type == IVL_EX_SIGNAL)))) { if (ivl_expr_signed(expr)) rtn = NEED_SIGNED; else rtn = NEED_UNSIGNED; From ef06bf7589c47436089d88d141bcd54ac4259c80 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 30 Dec 2013 11:53:44 +0100 Subject: [PATCH 06/16] Added missing support for binary ^~ in eval_tree.cc --- eval_tree.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/eval_tree.cc b/eval_tree.cc index 36f3bad78..6897e9ab3 100644 --- a/eval_tree.cc +++ b/eval_tree.cc @@ -288,6 +288,13 @@ NetEConst* NetEBBits::eval_arguments_(const NetExpr*l, const NetExpr*r) const break; } + case 'X': { + for (unsigned idx = 0 ; idx < wid ; idx += 1) + res.set(idx, ~(lval.get(idx) ^ rval.get(idx))); + + break; + } + case '^': { for (unsigned idx = 0 ; idx < wid ; idx += 1) res.set(idx, lval.get(idx) ^ rval.get(idx)); From d1c9dd554bfd09813a27fec3ab3b3f9fe40f376a Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 5 Jan 2014 20:53:58 +0000 Subject: [PATCH 07/16] Fix for github issue #6. When creating a constant zero for implementing a unary minus operation using a binary subtraction operator, the constant needs to be to exactly the expression width. --- netmisc.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/netmisc.cc b/netmisc.cc index 351e32f24..4c2f58fa2 100644 --- a/netmisc.cc +++ b/netmisc.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2013 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2014 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 @@ -48,7 +48,7 @@ NetNet* sub_net_from(Design*des, NetScope*scope, long val, NetNet*sig) } else { verinum zero ((int64_t)val); - zero = pad_to_width(zero, sig->vector_width()); + zero = cast_to_width(zero, sig->vector_width()); zero.has_sign(sig->get_signed()); NetConst*zero_obj = new NetConst(scope, scope->local_symbol(), zero); zero_obj->set_line(*sig); From b0491b9c5458b83a7ca8bb98bf221cf71f19a8b4 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 15 Dec 2013 04:07:31 +0000 Subject: [PATCH 08/16] Handle typedefs in $root scope. --- parse.y | 7 ++++++- parse_api.h | 2 ++ pform.cc | 39 +++++++++++++++++++++++++++++++-------- pform_dump.cc | 5 ++++- pform_struct_type.cc | 4 ++++ 5 files changed, 47 insertions(+), 10 deletions(-) diff --git a/parse.y b/parse.y index 32e4d15bb..d5c352583 100644 --- a/parse.y +++ b/parse.y @@ -1081,7 +1081,7 @@ description /* IEEE1800-2005: A.1.2 */ | nature_declaration | package_declaration | discipline_declaration - | timeunits_declaration + | package_item | KK_attribute '(' IDENTIFIER ',' STRING ',' STRING ')' { perm_string tmp3 = lex_strings.make($3); pform_set_type_attrib(tmp3, $5, $7); @@ -2362,6 +2362,11 @@ struct_union_member /* IEEE 1800-2012 A.2.2.1 */ tmp->names .reset($3); $$ = tmp; } + | error ';' + { yyerror(@2, "Error in struct/union member."); + yyerrok; + $$ = 0; + } ; case_item diff --git a/parse_api.h b/parse_api.h index e3526f348..e334c0443 100644 --- a/parse_api.h +++ b/parse_api.h @@ -28,6 +28,7 @@ class Module; class PPackage; class PUdp; +class data_type_t; /* * These are maps of the modules and primitives parsed from the @@ -36,6 +37,7 @@ class PUdp; */ extern std::map pform_modules; extern std::map pform_primitives; +extern std::map pform_typedefs; extern std::map pform_packages; extern void pform_dump(std::ostream&out, const PPackage*pac); diff --git a/pform.cc b/pform.cc index 4d2a03737..e67417ec5 100644 --- a/pform.cc +++ b/pform.cc @@ -46,12 +46,15 @@ /* * The pform_modules is a map of the modules that have been defined in * the top level. This should not contain nested modules/programs. + * pform_primitives is similar, but for UDP primitives. */ map pform_modules; -/* - */ map pform_primitives; +/* + * typedefs in the $root scope go here. + */ +mappform_typedefs; std::string vlltype::get_fileline() const { @@ -505,7 +508,13 @@ PWire*pform_get_make_wire_in_scope(perm_string name, NetNet::Type net_type, NetN void pform_set_typedef(perm_string name, data_type_t*data_type) { - data_type_t*&ref = lexical_scope->typedefs[name]; + // If we are in a lexical scope (i.e. a package or module) + // then put the typedef into that scope. Otherwise, put it + // into the $root scope. + data_type_t*&ref = lexical_scope + ? lexical_scope->typedefs[name] + : pform_typedefs[name]; + ivl_assert(*data_type, ref == 0); ref = data_type; @@ -514,15 +523,25 @@ void pform_set_typedef(perm_string name, data_type_t*data_type) } } +static data_type_t* test_type_identifier_in_root(perm_string name) +{ + map::iterator cur = pform_typedefs.find(name); + if (cur != pform_typedefs.end()) + return cur->second; + else + return 0; +} + data_type_t* pform_test_type_identifier(const char*txt) { - // If there is no lexical_scope yet, then there is NO WAY the - // identifier can be a type_identifier. - if (lexical_scope == 0) - return 0; - perm_string name = lex_strings.make(txt); + // If there is no lexical_scope yet, then look only in the + // $root scope for typedefs. + if (lexical_scope == 0) { + return test_type_identifier_in_root(name); + } + LexicalScope*cur_scope = lexical_scope; do { map::iterator cur; @@ -552,6 +571,10 @@ data_type_t* pform_test_type_identifier(const char*txt) cur_scope = cur_scope->parent_scope(); } while (cur_scope); + // See if there is a typedef in the $root scope. + if (data_type_t*tmp = test_type_identifier_in_root(name)) + return tmp; + return 0; } diff --git a/pform_dump.cc b/pform_dump.cc index fb2882123..b5ab2b348 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -170,7 +170,10 @@ void uarray_type_t::pform_dump(ostream&out, unsigned indent) const void struct_type_t::pform_dump(ostream&out, unsigned indent) const { out << setw(indent) << "" << "Struct " << (packed_flag?"packed":"unpacked") - << " with " << members->size() << " members" << endl; + << " with " << (members.get()==0? 0 : members->size()) << " members" << endl; + if (members.get()==0) + return; + for (list::iterator cur = members->begin() ; cur != members->end() ; ++ cur) { struct_member_t*curp = *cur; diff --git a/pform_struct_type.cc b/pform_struct_type.cc index 60219524b..4a4d91251 100644 --- a/pform_struct_type.cc +++ b/pform_struct_type.cc @@ -26,8 +26,12 @@ ivl_variable_type_t struct_type_t::figure_packed_base_type(void) const if (! packed_flag) return IVL_VT_NO_TYPE; + if (members.get() == 0) + return IVL_VT_NO_TYPE; + ivl_variable_type_t base_type = IVL_VT_BOOL; + ivl_assert(*this, members.get()); for (list::iterator cur = members->begin() ; cur != members->end() ; ++ cur) { From a3b29dd70b6ef1f88b305203833e0dff299e8f9c Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 15 Dec 2013 23:55:26 +0200 Subject: [PATCH 09/16] Handle enumeration literals that are in $root. --- elab_scope.cc | 25 ++++++++++++-- elab_sig.cc | 5 ++- elaborate.cc | 3 ++ net_expr.cc | 2 +- net_scope.cc | 93 ++++++++++++++++++++++++++++++++------------------- netlist.h | 53 +++++++++++++++++++---------- parse_api.h | 6 ++++ pform.cc | 8 ++++- 8 files changed, 139 insertions(+), 56 deletions(-) diff --git a/elab_scope.cc b/elab_scope.cc index eb0028ee8..3c9c166c1 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -48,6 +48,7 @@ # include "netlist.h" # include "netclass.h" # include "netenum.h" +# include "parse_api.h" # include "util.h" # include # include @@ -156,6 +157,10 @@ static void collect_scope_specparams_(Design*des, NetScope*scope, } } +/* + * Elaborate the enumeration into the given scope. If scope==0, then + * the enumeration goes into $root instead of a scope. + */ static void elaborate_scope_enumeration(Design*des, NetScope*scope, enum_type_t*enum_type) { @@ -176,7 +181,10 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope, msb, lsb, enum_type->names->size()); use_enum->set_line(enum_type->li); - scope->add_enumeration_set(use_enum); + if (scope) + scope->add_enumeration_set(use_enum); + else + des->add_enumeration_set(use_enum); ivl_assert(*enum_type, enum_type->net_type == 0); enum_type->net_type = use_enum; @@ -270,7 +278,11 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope, tmp_val.has_sign(enum_type->signed_flag); rc_flag = use_enum->insert_name(name_idx, cur->name, tmp_val); - rc_flag &= scope->add_enumeration_name(use_enum, cur->name); + if (scope) + rc_flag &= scope->add_enumeration_name(use_enum, cur->name); + else + rc_flag &= des->add_enumeration_name(use_enum, cur->name); + if (! rc_flag) { cerr << use_enum->get_fileline() << ": error: Duplicate enumeration name " @@ -297,6 +309,15 @@ static void elaborate_scope_enumerations(Design*des, NetScope*scope, } } +void elaborate_rootscope_enumerations(Design*des) +{ + for (set::const_iterator cur = pform_enum_sets.begin() + ; cur != pform_enum_sets.end() ; ++ cur) { + enum_type_t*curp = *cur; + elaborate_scope_enumeration(des, 0, curp); + } +} + /* * If the pclass includes an implicit and explicit constructor, then * merge the implicit constructor into the explicit constructor as diff --git a/elab_sig.cc b/elab_sig.cc index 7f2c8780a..d60e2a1f5 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -965,7 +965,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const << "'." << endl; des->errors += 1; } - // A signal can not have the same name as a parameter. + // A signal can not have the same name as a parameter. Note + // that we treat enumeration literals similar to parameters, + // so if the name matches an enumeration literal, it will be + // caught here. const NetExpr *ex_msb, *ex_lsb; const NetExpr *parm = scope->get_parameter(des, name_, ex_msb, ex_lsb); if (parm) { diff --git a/elaborate.cc b/elaborate.cc index 4aa898d5c..1fa4d19be 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -5663,6 +5663,9 @@ Design* elaborate(listroots) // module and elaborate what I find. Design*des = new Design; + // Elaborate enum sets in $root scope. + elaborate_rootscope_enumerations(des); + // Elaborate the packages. Package elaboration is simpler // because there are fewer sub-scopes involved. i = 0; diff --git a/net_expr.cc b/net_expr.cc index 6ff935185..c0e92ed4d 100644 --- a/net_expr.cc +++ b/net_expr.cc @@ -260,7 +260,7 @@ void NetEConcat::set(unsigned idx, NetExpr*e) expr_width( expr_width() + repeat_ * e->expr_width() ); } -NetEConstEnum::NetEConstEnum(NetScope*s, perm_string n, const netenum_t*eset, const verinum&v) +NetEConstEnum::NetEConstEnum(Definitions*s, perm_string n, const netenum_t*eset, const verinum&v) : NetEConst(v), scope_(s), enum_set_(eset), name_(n) { assert(has_width()); diff --git a/net_scope.cc b/net_scope.cc index 64667c50e..410d1b16b 100644 --- a/net_scope.cc +++ b/net_scope.cc @@ -30,6 +30,59 @@ class PExpr; +Definitions::Definitions() +{ +} + +Definitions::~Definitions() +{ +} + +void Definitions::add_enumeration_set(netenum_t*enum_set) +{ + enum_sets_.push_back(enum_set); +} + +bool Definitions::add_enumeration_name(netenum_t*enum_set, perm_string name) +{ + netenum_t::iterator enum_val = enum_set->find_name(name); + assert(enum_val != enum_set->end_name()); + + NetEConstEnum*val = new NetEConstEnum(this, name, enum_set, enum_val->second); + + pair::iterator, bool> cur; + cur = enum_names_.insert(make_pair(name,val)); + + // Return TRUE if the name is added (i.e. is NOT a duplicate.) + return cur.second; +} + +/* + * This locates the enumeration TYPE for the given enumeration literal. + */ +const netenum_t*Definitions::enumeration_for_name(perm_string name) +{ + NetEConstEnum*tmp = enum_names_[name]; + assert(tmp != 0); + + return tmp->enumeration(); +} + +/* + * This locates the VALUE for the given enumeration literal. + */ +const NetExpr* Definitions::enumeration_expr(perm_string key) +{ + map::const_iterator eidx; + + eidx = enum_names_.find(key); + if (eidx != enum_names_.end()) { + return eidx->second; + } else { + return 0; + } +} + /* * The NetScope class keeps a scope tree organized. Each node of the * scope tree points to its parent, its right sibling and its leftmost @@ -265,14 +318,13 @@ const NetExpr* NetScope::get_parameter(Design*des, return idx->second.val; } - map::const_iterator eidx; + msb = 0; + lsb = 0; + const NetExpr*tmp = enumeration_expr(key); + if (tmp) return tmp; - eidx = enum_names_.find(key); - if (eidx != enum_names_.end()) { - msb = 0; - lsb = 0; - return eidx->second; - } + tmp = des->enumeration_expr(key); + if (tmp) return tmp; return 0; } @@ -551,33 +603,6 @@ NetNet* NetScope::find_signal(perm_string key) return 0; } -void NetScope::add_enumeration_set(netenum_t*enum_set) -{ - enum_sets_.push_back(enum_set); -} - -bool NetScope::add_enumeration_name(netenum_t*enum_set, perm_string name) -{ - netenum_t::iterator enum_val = enum_set->find_name(name); - assert(enum_val != enum_set->end_name()); - - NetEConstEnum*val = new NetEConstEnum(this, name, enum_set, enum_val->second); - - pair::iterator, bool> cur; - cur = enum_names_.insert(make_pair(name,val)); - - // Return TRUE if the name is added (i.e. is NOT a duplicate.) - return cur.second; -} - -const netenum_t*NetScope::enumeration_for_name(perm_string name) -{ - NetEConstEnum*tmp = enum_names_[name]; - assert(tmp != 0); - - return tmp->enumeration(); -} - void NetScope::add_class(netclass_t*net_class) { classes_[net_class->get_name()] = net_class; diff --git a/netlist.h b/netlist.h index 1f2a3ddbe..237019ce5 100644 --- a/netlist.h +++ b/netlist.h @@ -819,12 +819,44 @@ class NetBaseDef { NetProc*proc_; }; +/* + * Some definitions (and methods to manipulate them) are common to a + * couple of types. Keep them here. + */ +class Definitions { + + public: + Definitions(); + ~Definitions(); + + void add_enumeration_set(netenum_t*enum_set); + bool add_enumeration_name(netenum_t*enum_set, perm_string enum_name); + + // Look up the enumeration literal in this scope. if the name + // is present, then return the enumeration type that declares it. + const netenum_t* enumeration_for_name(perm_string name); + + // Look up an enumeration literal in this scope. If the + // literal is present, return the expression that defines its + // value. + const NetExpr* enumeration_expr(perm_string key); + + protected: + // Enumerations. The enum_sets_ is a list of all the + // enumerations present in this scope. The enum_names_ is a + // map of all the enumeration names back to the sets that + // contain them. + std::list enum_sets_; + std::map enum_names_; + +}; + /* * This object type is used to contain a logical scope within a * design. The scope doesn't represent any executable hardware, but is * just a handle that netlist processors can use to grab at the design. */ -class NetScope : public Attrib { +class NetScope : public Definitions, public Attrib { public: enum TYPE { MODULE, CLASS, TASK, FUNC, BEGIN_END, FORK_JOIN, GENBLOCK, PACKAGE }; @@ -897,11 +929,6 @@ class NetScope : public Attrib { void rem_signal(NetNet*); NetNet* find_signal(perm_string name); - void add_enumeration_set(netenum_t*enum_set); - bool add_enumeration_name(netenum_t*enum_set, perm_string enum_name); - - const netenum_t* enumeration_for_name(perm_string name); - void add_class(netclass_t*class_type); netclass_t* find_class(perm_string name); @@ -1153,13 +1180,6 @@ class NetScope : public Attrib { const PFunction*func_pform_; unsigned elab_stage_; - // Enumerations. The enum_sets_ is a list of all the - // enumerations present in this scope. The enum_names_ is a - // map of all the enumeration names back to the sets that - // contain them. - std::list enum_sets_; - std::map enum_names_; - std::map classes_; NetScope*up_; @@ -1973,12 +1993,11 @@ class NetEConst : public NetExpr { class NetEConstEnum : public NetEConst { public: - explicit NetEConstEnum(NetScope*scope, perm_string name, + explicit NetEConstEnum(Definitions*scope, perm_string name, const netenum_t*enum_set, const verinum&val); ~NetEConstEnum(); perm_string name() const; - const NetScope*scope() const; const netenum_t*enumeration() const; virtual void expr_scan(struct expr_scan_t*) const; @@ -1987,7 +2006,7 @@ class NetEConstEnum : public NetEConst { virtual NetEConstEnum* dup_expr() const; private: - NetScope*scope_; + Definitions*scope_; const netenum_t*enum_set_; perm_string name_; }; @@ -4499,7 +4518,7 @@ struct elaborator_work_item_t { * This class contains an entire design. It includes processes and a * netlist, and can be passed around from function to function. */ -class Design { +class Design : public Definitions { public: Design(); diff --git a/parse_api.h b/parse_api.h index e334c0443..8101e4295 100644 --- a/parse_api.h +++ b/parse_api.h @@ -24,11 +24,14 @@ # include # include # include +# include +class Design; class Module; class PPackage; class PUdp; class data_type_t; +class enum_type_t; /* * These are maps of the modules and primitives parsed from the @@ -38,10 +41,13 @@ class data_type_t; extern std::map pform_modules; extern std::map pform_primitives; extern std::map pform_typedefs; +extern std::set pform_enum_sets; extern std::map pform_packages; extern void pform_dump(std::ostream&out, const PPackage*pac); +extern void elaborate_rootscope_enumerations(Design*des); + /* * This code actually invokes the parser to make modules. The first * parameter is the name of the file that is to be parsed. The diff --git a/pform.cc b/pform.cc index e67417ec5..9a72eceab 100644 --- a/pform.cc +++ b/pform.cc @@ -55,6 +55,7 @@ map pform_primitives; * typedefs in the $root scope go here. */ mappform_typedefs; +setpform_enum_sets; std::string vlltype::get_fileline() const { @@ -487,7 +488,12 @@ static void pform_put_wire_in_scope(perm_string name, PWire*net) static void pform_put_enum_type_in_scope(enum_type_t*enum_set) { - lexical_scope->enum_sets.insert(enum_set); + if (lexical_scope) { + ivl_assert(*enum_set, lexical_scope); + lexical_scope->enum_sets.insert(enum_set); + } else { + pform_enum_sets.insert(enum_set); + } } PWire*pform_get_make_wire_in_scope(perm_string name, NetNet::Type net_type, NetNet::PortType port_type, ivl_variable_type_t vt_type) From 8a4d769b3d50953117b6a5a99070e5c3db6fbc61 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Mon, 16 Dec 2013 03:49:57 +0200 Subject: [PATCH 10/16] Type name expressions down to elaboration. --- PExpr.cc | 9 +++++++++ PExpr.h | 15 ++++++++++++++ elab_expr.cc | 54 ++++++++++++++++++++++++++++++++++++++++++--------- parse.y | 8 ++++++++ pform_dump.cc | 5 +++++ 5 files changed, 82 insertions(+), 9 deletions(-) diff --git a/PExpr.cc b/PExpr.cc index 538f4f37f..4c7f303f6 100644 --- a/PExpr.cc +++ b/PExpr.cc @@ -540,6 +540,15 @@ bool PETernary::has_aa_term(Design*des, NetScope*scope) const || fal_->has_aa_term(des, scope); } +PETypename::PETypename(data_type_t*dt) +: data_type_(dt) +{ +} + +PETypename::~PETypename() +{ +} + PEUnary::PEUnary(char op, PExpr*ex) : op_(op), expr_(ex) { diff --git a/PExpr.h b/PExpr.h index 714778994..910f8a1b8 100644 --- a/PExpr.h +++ b/PExpr.h @@ -660,6 +660,21 @@ class PEString : public PExpr { char*text_; }; +class PETypename : public PExpr { + public: + explicit PETypename(data_type_t*data_type); + ~PETypename(); + + virtual void dump(ostream&) const; + virtual unsigned test_width(Design*des, NetScope*scope, + width_mode_t&mode); + virtual NetExpr*elaborate_expr(Design*des, NetScope*scope, + ivl_type_t type, unsigned flags) const; + + private: + data_type_t*data_type_; +}; + class PEUnary : public PExpr { public: diff --git a/elab_expr.cc b/elab_expr.cc index dc0d8de69..67397c26e 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -188,7 +188,7 @@ NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, unsigned, unsigned) const * supported, can assign to packed arrays and structs, unpacked arrays * and dynamic arrays. */ -unsigned PEAssignPattern::test_width(Design*des, NetScope*scope, width_mode_t&mode) +unsigned PEAssignPattern::test_width(Design*, NetScope*, width_mode_t&) { expr_type_ = IVL_VT_DARRAY; expr_width_ = 1; @@ -1078,10 +1078,14 @@ unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope, if (expr == 0) return 0; - // The argument type/width is self-determined and doesn't - // affect the result type/width. - width_mode_t arg_mode = SIZED; - expr->test_width(des, scope, arg_mode); + if (! dynamic_cast(expr)) { + // The argument type/width is self-determined and doesn't + // affect the result type/width. Note that if the + // argument is a type name (a special case) then + // don't bother with this step. + width_mode_t arg_mode = SIZED; + expr->test_width(des, scope, arg_mode); + } expr_type_ = IVL_VT_BOOL; expr_width_ = integer_width; @@ -1393,11 +1397,18 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope, PExpr*expr = parms_[0]; - verinum val ( (uint64_t)expr->expr_width(), integer_width); - NetEConst*sub = new NetEConst(val); - sub->set_line(*this); + if (PETypename*type_expr = dynamic_cast(expr)) { + cerr << get_fileline() << ": sorry: " + << "I don't yet support typename argumets to $bits." << endl; + des->errors += 1; + return 0; + } else { + verinum val ( (uint64_t)expr->expr_width(), integer_width); + NetEConst*sub = new NetEConst(val); + sub->set_line(*this); - return cast_to_width_(sub, expr_wid); + return cast_to_width_(sub, expr_wid); + } } /* Interpret the internal $is_signed system function to return @@ -5158,6 +5169,31 @@ NetExpr* PETernary::elab_and_eval_alternative_(Design*des, NetScope*scope, return tmp; } +/* + * A typename expression is only legal in very narrow cases. This is + * just a placeholder. + */ +unsigned PETypename::test_width(Design*des, NetScope*, width_mode_t&) +{ + cerr << get_fileline() << ": error: " + << "Type names are not valid expressions here." << endl; + des->errors += 1; + + expr_type_ = IVL_VT_NO_TYPE; + expr_width_ = 1; + min_width_ = 1; + signed_flag_ = false; + return expr_width_; +} + +NetExpr*PETypename::elaborate_expr(Design*des, NetScope*, + ivl_type_t, unsigned) const +{ + cerr << get_fileline() << ": error: Type name not a valid expression here." << endl; + des->errors += 1; + return 0; +} + unsigned PEUnary::test_width(Design*des, NetScope*scope, width_mode_t&mode) { switch (op_) { diff --git a/parse.y b/parse.y index d5c352583..15e4a9814 100644 --- a/parse.y +++ b/parse.y @@ -3097,6 +3097,14 @@ expr_primary delete[]$1; } + /* There are a few special cases (notably $bits argument) where the + expression may be a type name. Let the elaborator sort this out. */ + | TYPE_IDENTIFIER + { PETypename*tmp = new PETypename($1); + FILE_NAME(tmp,@1); + $$ = tmp; + } + /* The hierarchy_identifier rule matches simple identifiers as well as indexed arrays and part selects */ diff --git a/pform_dump.cc b/pform_dump.cc index b5ab2b348..a8b08c04b 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -385,6 +385,11 @@ void PETernary::dump(ostream&out) const out << "(" << *expr_ << ")?(" << *tru_ << "):(" << *fal_ << ")"; } +void PETypename::dump(ostream&fd) const +{ + fd << ""; +} + void PEUnary::dump(ostream&out) const { switch (op_) { From 6ec31517a9ccdb0e312eeacd24ac38d309a10bf3 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Mon, 16 Dec 2013 04:36:13 +0200 Subject: [PATCH 11/16] Implement $bits(type) to get the size of a type In the process, I implemented a means to get at previously elaborated types from the pform type pointer. --- PExpr.h | 2 ++ PFunction.cc | 2 +- PTask.h | 4 ++-- elab_expr.cc | 29 ++++++++++++++++++++--------- elab_sig.cc | 7 ++++--- elab_type.cc | 18 +++++++++--------- pform_types.cc | 9 +++++++++ pform_types.h | 25 ++++++++++++++++--------- 8 files changed, 63 insertions(+), 33 deletions(-) diff --git a/PExpr.h b/PExpr.h index 910f8a1b8..fa44c70b5 100644 --- a/PExpr.h +++ b/PExpr.h @@ -671,6 +671,8 @@ class PETypename : public PExpr { virtual NetExpr*elaborate_expr(Design*des, NetScope*scope, ivl_type_t type, unsigned flags) const; + inline data_type_t* get_type() const { return data_type_; } + private: data_type_t*data_type_; }; diff --git a/PFunction.cc b/PFunction.cc index e15fab119..a5dc8f351 100644 --- a/PFunction.cc +++ b/PFunction.cc @@ -65,7 +65,7 @@ void PFunction::push_statement_front(Statement*stmt) blk->push_statement_front(stmt); } -void PFunction::set_return(const data_type_t*t) +void PFunction::set_return(data_type_t*t) { return_type_ = t; } diff --git a/PTask.h b/PTask.h index 87b0df958..9e417615f 100644 --- a/PTask.h +++ b/PTask.h @@ -114,7 +114,7 @@ class PFunction : public PTaskFunc { ~PFunction(); void set_statement(Statement *s); - void set_return(const data_type_t*t); + void set_return(data_type_t*t); inline Statement* get_statement() { return statement_; } @@ -141,7 +141,7 @@ class PFunction : public PTaskFunc { void dump(ostream&, unsigned) const; private: - const data_type_t* return_type_; + data_type_t* return_type_; Statement *statement_; bool is_auto_; }; diff --git a/elab_expr.cc b/elab_expr.cc index 67397c26e..71e584d67 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -1397,18 +1397,29 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope, PExpr*expr = parms_[0]; + uint64_t use_width = 0; if (PETypename*type_expr = dynamic_cast(expr)) { - cerr << get_fileline() << ": sorry: " - << "I don't yet support typename argumets to $bits." << endl; - des->errors += 1; - return 0; - } else { - verinum val ( (uint64_t)expr->expr_width(), integer_width); - NetEConst*sub = new NetEConst(val); - sub->set_line(*this); + ivl_type_t tmp_type = type_expr->get_type()->elaborate_type(des, scope); + ivl_assert(*this, tmp_type); + use_width = tmp_type->packed_width(); + if (debug_elaborate) { + cerr << get_fileline() << ": PECallFunction::elaborate_sfunc_: " + << " Packed width of type argument is " << use_width << endl; + } - return cast_to_width_(sub, expr_wid); + } else { + use_width = expr->expr_width(); + if (debug_elaborate) { + cerr << get_fileline() << ": PECallFunction::elaborate_sfunc_: " + << " Width of expression argument is " << use_width << endl; + } } + + verinum val (use_width, integer_width); + NetEConst*sub = new NetEConst(val); + sub->set_line(*this); + + return cast_to_width_(sub, expr_wid); } /* Interpret the internal $is_signed system function to return diff --git a/elab_sig.cc b/elab_sig.cc index d60e2a1f5..1b5c90f7a 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -563,7 +563,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const // Special case: this is a constructor, so the return // signal is also the first argument. For example, the // source code for the definition may be: - // function new(...); + // function new(...); // endfunction // In this case, the "@" port is the synthetic "this" // argument and we also use it as a return value at the @@ -876,7 +876,7 @@ static ivl_type_s*elaborate_type(Design*des, NetScope*scope, data_type_t*pform_type) { if (struct_type_t*struct_type = dynamic_cast(pform_type)) { - netstruct_t*use_type = struct_type->elaborate_type(des, scope); + ivl_type_s*use_type = struct_type->elaborate_type(des, scope); return use_type; } @@ -1210,7 +1210,8 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const } else if (struct_type_t*struct_type = dynamic_cast(set_data_type_)) { // If this is a struct type, then build the net with the // struct type. - netstruct_t*use_type = struct_type->elaborate_type(des, scope); + ivl_type_s*tmp_type = struct_type->elaborate_type(des, scope); + netstruct_t*use_type = dynamic_cast(tmp_type); if (debug_elaborate) { cerr << get_fileline() << ": debug: Create signal " << wtype; if (use_type->packed()) diff --git a/elab_type.cc b/elab_type.cc index 997069ea0..8f4b8068e 100644 --- a/elab_type.cc +++ b/elab_type.cc @@ -31,7 +31,7 @@ using namespace std; -ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*) const +ivl_type_s* data_type_t::elaborate_type_raw(Design*des, NetScope*) const { cerr << get_fileline() << ": internal error: " << "Elaborate method not implemented for " << typeid(*this).name() @@ -40,7 +40,7 @@ ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*) const return 0; } -ivl_type_s* atom2_type_t::elaborate_type(Design*des, NetScope*) const +ivl_type_s* atom2_type_t::elaborate_type_raw(Design*des, NetScope*) const { switch (type_code) { case 64: @@ -75,18 +75,18 @@ ivl_type_s* atom2_type_t::elaborate_type(Design*des, NetScope*) const } } -ivl_type_s* class_type_t::elaborate_type(Design*, NetScope*scope) const +ivl_type_s* class_type_t::elaborate_type_raw(Design*, NetScope*scope) const { return scope->find_class(name); } -ivl_type_s* enum_type_t::elaborate_type(Design*des, NetScope*scope) const +ivl_type_s* enum_type_t::elaborate_type_raw(Design*des, NetScope*scope) const { ivl_assert(*this, net_type); return net_type; } -ivl_type_s* vector_type_t::elaborate_type(Design*des, NetScope*scope) const +ivl_type_s* vector_type_t::elaborate_type_raw(Design*des, NetScope*scope) const { vector packed; @@ -122,7 +122,7 @@ ivl_type_s* vector_type_t::elaborate_type(Design*des, NetScope*scope) const return tmp; } -ivl_type_s* real_type_t::elaborate_type(Design*, NetScope*) const +ivl_type_s* real_type_t::elaborate_type_raw(Design*, NetScope*) const { switch (type_code) { case REAL: @@ -133,12 +133,12 @@ ivl_type_s* real_type_t::elaborate_type(Design*, NetScope*) const return 0; } -ivl_type_s* string_type_t::elaborate_type(Design*, NetScope*) const +ivl_type_s* string_type_t::elaborate_type_raw(Design*, NetScope*) const { return &netstring_t::type_string; } -netstruct_t* struct_type_t::elaborate_type(Design*des, NetScope*scope) const +netstruct_t* struct_type_t::elaborate_type_raw(Design*des, NetScope*scope) const { netstruct_t*res = new netstruct_t; @@ -173,7 +173,7 @@ netstruct_t* struct_type_t::elaborate_type(Design*des, NetScope*scope) const return res; } -ivl_type_s* uarray_type_t::elaborate_type(Design*des, NetScope*scope) const +ivl_type_s* uarray_type_t::elaborate_type_raw(Design*des, NetScope*scope) const { ivl_type_t btype = base_type->elaborate_type(des, scope); diff --git a/pform_types.cc b/pform_types.cc index 5a7868bef..c809ffbf6 100644 --- a/pform_types.cc +++ b/pform_types.cc @@ -24,6 +24,15 @@ data_type_t::~data_type_t() { } +ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*scope) +{ + if (cache_type_elaborate_) + return cache_type_elaborate_; + + cache_type_elaborate_ = elaborate_type_raw(des, scope); + return cache_type_elaborate_; +} + string_type_t::~string_type_t() { } diff --git a/pform_types.h b/pform_types.h index 207e47700..94ea7266c 100644 --- a/pform_types.h +++ b/pform_types.h @@ -88,14 +88,21 @@ struct pform_tf_port_t { */ class data_type_t : public LineInfo { public: + inline explicit data_type_t() : cache_type_elaborate_(0) { } virtual ~data_type_t() = 0; // This method is used to figure out the base type of a packed // compound object. Return IVL_VT_NO_TYPE if the type is not packed. virtual ivl_variable_type_t figure_packed_base_type(void)const; // This method is used by the pform dumper to diagnostic dump. virtual void pform_dump(std::ostream&out, unsigned indent) const; + + ivl_type_s* elaborate_type(Design*des, NetScope*scope); + + private: // Elaborate the type to an ivl_type_s type. - virtual ivl_type_s* elaborate_type(Design*des, NetScope*scope) const; + virtual ivl_type_s* elaborate_type_raw(Design*des, NetScope*scope) const; + + ivl_type_s*cache_type_elaborate_; }; struct void_type_t : public data_type_t { @@ -111,7 +118,7 @@ struct void_type_t : public data_type_t { struct enum_type_t : public data_type_t { inline enum_type_t(void) : net_type(0) { } // Return the elaborated version of the type. - virtual ivl_type_s*elaborate_type(Design*des, NetScope*scope) const; + virtual ivl_type_s*elaborate_type_raw(Design*des, NetScope*scope) const; ivl_variable_type_t base_type; bool signed_flag; @@ -134,7 +141,7 @@ struct struct_member_t : public LineInfo { struct struct_type_t : public data_type_t { virtual ivl_variable_type_t figure_packed_base_type(void)const; virtual void pform_dump(std::ostream&out, unsigned indent) const; - virtual netstruct_t* elaborate_type(Design*des, NetScope*scope) const; + virtual netstruct_t* elaborate_type_raw(Design*des, NetScope*scope) const; bool packed_flag; bool union_flag; @@ -147,7 +154,7 @@ struct atom2_type_t : public data_type_t { int type_code; bool signed_flag; - ivl_type_s* elaborate_type(Design*des, NetScope*scope) const; + ivl_type_s* elaborate_type_raw(Design*des, NetScope*scope) const; }; /* @@ -174,7 +181,7 @@ struct vector_type_t : public data_type_t { std::list*pd) : base_type(bt), signed_flag(sf), reg_flag(false), integer_flag(false), implicit_flag(false), pdims(pd) { } virtual ivl_variable_type_t figure_packed_base_type(void)const; - ivl_type_s* elaborate_type(Design*des, NetScope*scope) const; + ivl_type_s* elaborate_type_raw(Design*des, NetScope*scope) const; ivl_variable_type_t base_type; bool signed_flag; @@ -216,7 +223,7 @@ struct uarray_type_t : public array_base_t { public: virtual void pform_dump(std::ostream&out, unsigned indent) const; - virtual ivl_type_s* elaborate_type(Design*des, NetScope*scope) const; + virtual ivl_type_s* elaborate_type_raw(Design*des, NetScope*scope) const; }; struct real_type_t : public data_type_t { @@ -224,14 +231,14 @@ struct real_type_t : public data_type_t { inline explicit real_type_t(type_t tc) : type_code(tc) { } type_t type_code; - ivl_type_s* elaborate_type(Design*des, NetScope*scope) const; + ivl_type_s* elaborate_type_raw(Design*des, NetScope*scope) const; }; struct string_type_t : public data_type_t { inline explicit string_type_t() { } ~string_type_t(); - ivl_type_s* elaborate_type(Design*des, NetScope*scope) const; + ivl_type_s* elaborate_type_raw(Design*des, NetScope*scope) const; }; struct class_type_t : public data_type_t { @@ -271,7 +278,7 @@ struct class_type_t : public data_type_t { // without waiting for any constructor. std::vector initialize_static; - ivl_type_s* elaborate_type(Design*, NetScope*) const; + ivl_type_s* elaborate_type_raw(Design*, NetScope*) const; }; /* From fc42f40770068d531dbb7a1a5f5b1d783d9357a9 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Wed, 18 Dec 2013 08:16:59 +0200 Subject: [PATCH 12/16] Fix problem with enum types in re-used modules When a module is instantiated multiple times, the enum types contained within would cause trouble. This fixes that by elaborating in proper scope context. --- design_dump.cc | 4 ++-- elab_scope.cc | 7 ++----- elab_type.cc | 14 ++++++++++++-- emit.cc | 4 ++-- net_scope.cc | 17 +++++++++++++++-- netlist.h | 14 ++++++++++++-- pform_types.h | 6 ------ 7 files changed, 45 insertions(+), 21 deletions(-) diff --git a/design_dump.cc b/design_dump.cc index 2a9219f34..e42347bcb 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -1313,9 +1313,9 @@ void NetScope::dump(ostream&o) const o << " enum sets {" << endl; /* Dump the enumerations and enum names in this scope. */ - for (list::const_iterator cur = enum_sets_.begin() + for (map::const_iterator cur = enum_sets_.begin() ; cur != enum_sets_.end() ; ++ cur) { - o << " " << *cur << endl; + o << " " << cur->second << endl; } o << " }" << endl; diff --git a/elab_scope.cc b/elab_scope.cc index 3c9c166c1..ffc0a31af 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -182,12 +182,9 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope, use_enum->set_line(enum_type->li); if (scope) - scope->add_enumeration_set(use_enum); + scope->add_enumeration_set(enum_type, use_enum); else - des->add_enumeration_set(use_enum); - - ivl_assert(*enum_type, enum_type->net_type == 0); - enum_type->net_type = use_enum; + des->add_enumeration_set(enum_type, use_enum); verinum cur_value (0); verinum one_value (1); diff --git a/elab_type.cc b/elab_type.cc index 8f4b8068e..f1152e84a 100644 --- a/elab_type.cc +++ b/elab_type.cc @@ -80,10 +80,20 @@ ivl_type_s* class_type_t::elaborate_type_raw(Design*, NetScope*scope) const return scope->find_class(name); } +/* + * elaborate_type_raw for enumerations is actually mostly performed + * during scope elaboration so that the enumeration literals are + * available at the right time. At tha time, the netenum_t* object is + * stashed in the scope so that I can retrieve it here. + */ ivl_type_s* enum_type_t::elaborate_type_raw(Design*des, NetScope*scope) const { - ivl_assert(*this, net_type); - return net_type; + ivl_assert(*this, scope); + ivl_type_s*tmp = scope->enumeration_for_key(this); + if (tmp) return tmp; + + tmp = des->enumeration_for_key(this); + return tmp; } ivl_type_s* vector_type_t::elaborate_type_raw(Design*des, NetScope*scope) const diff --git a/emit.cc b/emit.cc index b49df2168..4da13d0d3 100644 --- a/emit.cc +++ b/emit.cc @@ -420,9 +420,9 @@ void NetScope::emit_scope(struct target_t*tgt) const tgt->class_type(this, cur->second); } - for (list::const_iterator cur = enum_sets_.begin() + for (map::const_iterator cur = enum_sets_.begin() ; cur != enum_sets_.end() ; ++cur) - tgt->enumeration(this, *cur); + tgt->enumeration(this, cur->second); for (map::const_iterator cur = children_.begin() ; cur != children_.end() ; ++ cur ) diff --git a/net_scope.cc b/net_scope.cc index 410d1b16b..e72a31133 100644 --- a/net_scope.cc +++ b/net_scope.cc @@ -38,9 +38,11 @@ Definitions::~Definitions() { } -void Definitions::add_enumeration_set(netenum_t*enum_set) +void Definitions::add_enumeration_set(const enum_type_t*key, netenum_t*enum_set) { - enum_sets_.push_back(enum_set); + netenum_t*&tmp = enum_sets_[key]; + assert(tmp == 0); + tmp = enum_set; } bool Definitions::add_enumeration_name(netenum_t*enum_set, perm_string name) @@ -57,6 +59,17 @@ bool Definitions::add_enumeration_name(netenum_t*enum_set, perm_string name) return cur.second; } +netenum_t* Definitions::enumeration_for_key(const enum_type_t*key) const +{ + map::const_iterator cur; + + cur = enum_sets_.find(key); + if (cur != enum_sets_.end()) + return cur->second; + else + return 0; +} + /* * This locates the enumeration TYPE for the given enumeration literal. */ diff --git a/netlist.h b/netlist.h index 237019ce5..02836b23f 100644 --- a/netlist.h +++ b/netlist.h @@ -76,6 +76,7 @@ class NetEvTrig; class NetEvWait; class PExpr; class PFunction; +class enum_type_t; class netclass_t; class netdarray_t; class netparray_t; @@ -829,13 +830,22 @@ class Definitions { Definitions(); ~Definitions(); - void add_enumeration_set(netenum_t*enum_set); + // Add the enumeration to the set of enumerations in this + // scope. Include a key that the elaboration can use to look + // up this enumeration based on the pform type. + void add_enumeration_set(const enum_type_t*key, netenum_t*enum_set); + bool add_enumeration_name(netenum_t*enum_set, perm_string enum_name); // Look up the enumeration literal in this scope. if the name // is present, then return the enumeration type that declares it. const netenum_t* enumeration_for_name(perm_string name); + // Look up the enumeration set that was added with the given + // key. This is used by enum_type_t::elaborate_type to locate + // a previously elaborated enumeration. + netenum_t* enumeration_for_key(const enum_type_t*key) const; + // Look up an enumeration literal in this scope. If the // literal is present, return the expression that defines its // value. @@ -846,7 +856,7 @@ class Definitions { // enumerations present in this scope. The enum_names_ is a // map of all the enumeration names back to the sets that // contain them. - std::list enum_sets_; + std::map enum_sets_; std::map enum_names_; }; diff --git a/pform_types.h b/pform_types.h index 94ea7266c..32758f5e4 100644 --- a/pform_types.h +++ b/pform_types.h @@ -116,7 +116,6 @@ struct void_type_t : public data_type_t { * until it is elaborated in a scope. */ struct enum_type_t : public data_type_t { - inline enum_type_t(void) : net_type(0) { } // Return the elaborated version of the type. virtual ivl_type_s*elaborate_type_raw(Design*des, NetScope*scope) const; @@ -125,11 +124,6 @@ struct enum_type_t : public data_type_t { std::auto_ptr< list > range; std::auto_ptr< list > names; LineInfo li; - // This is the elaborated type. The enumeration type is - // elaborated early so that names can be placed in the scope, - // but that means the result needs to be saved for the actual - // elaborate_type method to use. - netenum_t*net_type; }; struct struct_member_t : public LineInfo { From f906384423e60d814de90c4d3c6ec322bfc3f51d Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Thu, 19 Dec 2013 09:34:27 +0200 Subject: [PATCH 13/16] Elaborate r-vlaue packed struct members pads as needed. --- elab_expr.cc | 11 ++++++++--- elaborate.cc | 27 +++++++++------------------ 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index 71e584d67..2ee8f8510 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -3321,9 +3321,14 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope, << "got " << use_path.back().index.size() << "." << endl; } - return check_for_struct_members(this, des, use_scope, - net, use_path.back().index, - member_comp); + NetExpr*tmp = check_for_struct_members(this, des, use_scope, + net, use_path.back().index, + member_comp); + if (!tmp) return 0; + + tmp = pad_to_width(tmp, expr_wid, *this); + tmp->cast_signed(signed_flag_); + return tmp; } if (net->class_type() != 0) { diff --git a/elaborate.cc b/elaborate.cc index 1fa4d19be..e4cbca214 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -129,8 +129,8 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const << ", expr=" << *rval_expr << endl; } - assert(lval && rval); - assert(rval->pin_count() == 1); + ivl_assert(*this, lval && rval); + ivl_assert(*this, rval->pin_count() == 1); // Detect the case that the rvalue-expression is a simple // expression. In this case, we will need to create a driver @@ -139,23 +139,14 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const if (dynamic_cast(rval_expr)) need_driver_flag = true; -#if 0 - // MTW, 01-Mar-2013. The expression elaboration rework should have - // ensured that this can no longer occur. Leaving this here for the - // moment, but it should be safe to remove it. - - /* If the r-value insists on being smaller than the l-value - (perhaps it is explicitly sized) the pad it out to be the - right width so that something is connected to all the bits - of the l-value. */ - if (lval->vector_width() > rval->vector_width()) { - if (rval->get_signed()) - rval = pad_to_width_signed(des, rval, lval->vector_width(), - *this); - else - rval = pad_to_width(des, rval, lval->vector_width(), *this); + // expression elaboration should have caused the rval width to + // match the l-value by now. + if (rval->vector_width() < lval->vector_width()) { + cerr << get_fileline() << ": internal error: " + << "lval-rval width mismatch: " + << "rval->vector_width()==" << rval->vector_width() + << ", lval->vector_width()==" << lval->vector_width() << endl; } -#endif ivl_assert(*this, rval->vector_width() >= lval->vector_width()); /* If the r-value insists on being larger than the l-value, From 77a01f65d063e79060ef288bd6dcef38fdbba6a1 Mon Sep 17 00:00:00 2001 From: Larry Doolittle Date: Tue, 28 Jan 2014 15:40:24 -0800 Subject: [PATCH 14/16] Remove fixable unused-parameter warnings I see other warnings within vhdlpp/lexor.cc caused by a flex bug (see http://sourceforge.net/p/flex/bugs/115/), which I won't try to work around. --- elab_expr.cc | 2 +- nettypes.cc | 2 +- tgt-blif/blif.cc | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index 2ee8f8510..be49e5c18 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -4720,7 +4720,7 @@ unsigned PENewClass::test_width(Design*, NetScope*, width_mode_t&) */ NetExpr* PENewClass::elaborate_expr_constructor_(Design*des, NetScope*scope, const netclass_t*ctype, - NetExpr*obj, unsigned flags) const + NetExpr*obj, unsigned /*flags*/) const { // If there is an initializer function, then pass the object // through that function first. Note tha the initializer diff --git a/nettypes.cc b/nettypes.cc index d7d5c0883..1a36b177a 100644 --- a/nettypes.cc +++ b/nettypes.cc @@ -63,7 +63,7 @@ bool ivl_type_s::type_compatible(ivl_type_t that) const return test_compatibility(that); } -bool ivl_type_s::test_compatibility(const ivl_type_s*that) const +bool ivl_type_s::test_compatibility(const ivl_type_s* /*that*/) const { return false; } diff --git a/tgt-blif/blif.cc b/tgt-blif/blif.cc index 3d121ebd5..82bc83535 100644 --- a/tgt-blif/blif.cc +++ b/tgt-blif/blif.cc @@ -55,7 +55,7 @@ int blif_errors = 0; static void emit_blif(const char*blif_path, ivl_design_t des, ivl_scope_t model); -static int process_scan_fun(ivl_process_t net, void*raw) +static int process_scan_fun(ivl_process_t net, void* /*raw*/) { fprintf(stderr, "%s:%u: sorry: BLIF: Processes not supported yet.\n", ivl_process_file(net), ivl_process_lineno(net)); From be17bfc0e990e7dd4088be8cdd2a96a825d503b9 Mon Sep 17 00:00:00 2001 From: Larry Doolittle Date: Tue, 28 Jan 2014 15:50:27 -0800 Subject: [PATCH 15/16] Spelling fixes Mostly comments. One user-visible string ("Evalutated to ") changed in the debug_eval_tree case. --- elab_expr.cc | 6 +++--- elab_sig.cc | 2 +- elab_type.cc | 2 +- elaborate.cc | 2 +- lexor.lex | 2 +- net_func_eval.cc | 2 +- netlist.cc | 2 +- netmisc.cc | 2 +- pform.cc | 2 +- synth2.cc | 2 +- tgt-pcb/footprint.cc | 2 +- vhdlpp/expression_emit.cc | 2 +- vvp/class_type.h | 2 +- vvp/opcodes.txt | 2 +- 14 files changed, 16 insertions(+), 16 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index be49e5c18..f26b3354e 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -4723,8 +4723,8 @@ NetExpr* PENewClass::elaborate_expr_constructor_(Design*des, NetScope*scope, NetExpr*obj, unsigned /*flags*/) const { // If there is an initializer function, then pass the object - // through that function first. Note tha the initializer - // function has no arguments other then the object itself. + // through that function first. Note that the initializer + // function has no arguments other than the object itself. if (NetScope*new1_scope = ctype->method_from_name(perm_string::literal("new@"))) { NetFuncDef*def1 = new1_scope->func_def(); ivl_assert(*this, def1); @@ -4866,7 +4866,7 @@ NetExpr* PENewCopy::elaborate_expr(Design*des, NetScope*scope, ivl_type_t obj_ty /* * A "null" expression represents class objects/handles. This brings - * up a ton of special cases, but we handle it here bu setting the + * up a ton of special cases, but we handle it here by setting the * expr_type_ and expr_width_ to fixed values. */ unsigned PENull::test_width(Design*, NetScope*, width_mode_t&) diff --git a/elab_sig.cc b/elab_sig.cc index 1b5c90f7a..4b8b0ec36 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -1260,7 +1260,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const // The trick here is that the parray type has an // arbitrary sub-type, and not just a scalar bit... netparray_t*use_type = elaborate_parray_type(des, scope, parray_type); - // Should not be getting packed dimensions other then + // Should not be getting packed dimensions other than // through the parray type declaration. ivl_assert(*this, packed_dimensions.empty()); diff --git a/elab_type.cc b/elab_type.cc index f1152e84a..c4c97eaa7 100644 --- a/elab_type.cc +++ b/elab_type.cc @@ -83,7 +83,7 @@ ivl_type_s* class_type_t::elaborate_type_raw(Design*, NetScope*scope) const /* * elaborate_type_raw for enumerations is actually mostly performed * during scope elaboration so that the enumeration literals are - * available at the right time. At tha time, the netenum_t* object is + * available at the right time. At that time, the netenum_t* object is * stashed in the scope so that I can retrieve it here. */ ivl_type_s* enum_type_t::elaborate_type_raw(Design*des, NetScope*scope) const diff --git a/elaborate.cc b/elaborate.cc index e4cbca214..ffd497a03 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -3051,7 +3051,7 @@ NetProc* PChainConstructor::elaborate(Design*des, NetScope*scope) const NetNet*var_this = scope->find_signal(perm_string::literal("@")); // If super.new is an implicit constructor, then there are no - // arguments (other then "this" to worry about, so make a + // arguments (other than "this" to worry about, so make a // NetEUFunc and there we go. if (NetScope*new_scope = class_super->method_from_name(perm_string::literal("new@"))) { NetESignal*eres = new NetESignal(var_this); diff --git a/lexor.lex b/lexor.lex index f3fee4168..7c7a79649 100644 --- a/lexor.lex +++ b/lexor.lex @@ -341,7 +341,7 @@ TU [munpf] } } - /* If this identifer names a previously declared package, then + /* If this identifier names a previously declared package, then return this as a PACKAGE_IDENTIFIER instead. */ if (rc == IDENTIFIER && gn_system_verilog()) { if (PPackage*pkg = pform_test_package_identifier(yylval.text)) { diff --git a/net_func_eval.cc b/net_func_eval.cc index e6229602a..d130f3723 100644 --- a/net_func_eval.cc +++ b/net_func_eval.cc @@ -138,7 +138,7 @@ NetExpr* NetFuncDef::evaluate_function(const LineInfo&loc, const std::vector"; cerr << endl; diff --git a/netlist.cc b/netlist.cc index bc59461e7..0bd8ca28a 100644 --- a/netlist.cc +++ b/netlist.cc @@ -755,7 +755,7 @@ const netclass_t* NetNet::class_type(void) const /* * "depth" is the number of index expressions that the user is using - * to index this identifer. So consider if Net was declared like so: + * to index this identifier. So consider if Net was declared like so: * * reg [5:0][3:0] foo; * diff --git a/netmisc.cc b/netmisc.cc index 4c2f58fa2..e6b414e61 100644 --- a/netmisc.cc +++ b/netmisc.cc @@ -1309,7 +1309,7 @@ NetExpr*collapse_array_exprs(Design*des, NetScope*scope, /* * Given a list of indices, treat them as packed indices and convert * them to an expression that normalizes the list to a single index - * expression over a canonical equivilent 1-dimensional array. + * expression over a canonical equivalent 1-dimensional array. */ NetExpr*collapse_array_indices(Design*des, NetScope*scope, NetNet*net, const list&indices) diff --git a/pform.cc b/pform.cc index 9a72eceab..c9e716f08 100644 --- a/pform.cc +++ b/pform.cc @@ -555,7 +555,7 @@ data_type_t* pform_test_type_identifier(const char*txt) // First look to see if this identifier is imported from // a package. If it is, see if it is a type in that // package. If it is, then great. If imported as - // something other then a type, then give up now becase + // something other than a type, then give up now because // the name has at least shadowed any other possible // meaning for this name. map::iterator cur_pkg; diff --git a/synth2.cc b/synth2.cc index 2f5081087..0062b1632 100644 --- a/synth2.cc +++ b/synth2.cc @@ -232,7 +232,7 @@ bool NetCase::synth_async(Design*des, NetScope*scope, unsigned mux_size = max_guard_value + 1; - // If the sel_width can select more then just the explicit + // If the sel_width can select more than just the explicit // guard values, and there is a default statement, then adjust // the mux size to allow for the implicit selections. if (statement_default && ((1U< mux_size)) { diff --git a/tgt-pcb/footprint.cc b/tgt-pcb/footprint.cc index 5ba01ab42..a05c52709 100644 --- a/tgt-pcb/footprint.cc +++ b/tgt-pcb/footprint.cc @@ -45,7 +45,7 @@ int load_footprints(void) } /* - * The fpparse funciton calls back the callback_fp_element function + * The fpparse function calls back the callback_fp_element function * for each Element that it parses. The check_footprint function * stores in the cur_footprint variable the name of the footprint that * we are trying to find in the file. The callback uses that name to diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index 07916d159..f6cd315d0 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -566,7 +566,7 @@ int ExpFunc::emit(ostream&out, Entity*ent, Architecture*arc) out << ")"; } else { - // If this function has an elaborated defintion, and if + // If this function has an elaborated definition, and if // that definition is in a package, then include the // package name as a scope qualifier. This assures that // the SV elaborator finds the correct VHDL elaborated diff --git a/vvp/class_type.h b/vvp/class_type.h index 8304f812e..5c4b4831b 100644 --- a/vvp/class_type.h +++ b/vvp/class_type.h @@ -52,7 +52,7 @@ class class_type : public __vpiHandle { void set_property(size_t idx, const std::string&name, const std::string&type); // This method is called after all the properties are - // defined. This calculates information about the defintion. + // defined. This calculates information about the definition. void finish_setup(void); public: diff --git a/vvp/opcodes.txt b/vvp/opcodes.txt index d3e702356..b89f41291 100644 --- a/vvp/opcodes.txt +++ b/vvp/opcodes.txt @@ -873,7 +873,7 @@ includes an implicit pop, but sometimes it is necessary to pop explicitly. The is the number of top positions on the stack to keep, -beforing starting to pop. This allows for popping positions other then +beforing starting to pop. This allows for popping positions other than the top of the stack. * %pow , , From f76d56beb869abdada91fcfb3476650ac96efd90 Mon Sep 17 00:00:00 2001 From: Larry Doolittle Date: Thu, 30 Jan 2014 09:36:25 -0800 Subject: [PATCH 16/16] Remove lint detected by clang With this change, iverilog builds and runs with no extra warnings when using clang 3.0 --- netlist.h | 2 +- parse_api.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/netlist.h b/netlist.h index 02836b23f..f02970b86 100644 --- a/netlist.h +++ b/netlist.h @@ -76,7 +76,7 @@ class NetEvTrig; class NetEvWait; class PExpr; class PFunction; -class enum_type_t; +struct enum_type_t; class netclass_t; class netdarray_t; class netparray_t; diff --git a/parse_api.h b/parse_api.h index 8101e4295..a9de02dcf 100644 --- a/parse_api.h +++ b/parse_api.h @@ -31,7 +31,7 @@ class Module; class PPackage; class PUdp; class data_type_t; -class enum_type_t; +struct enum_type_t; /* * These are maps of the modules and primitives parsed from the