diff --git a/vhdlpp/architec_emit.cc b/vhdlpp/architec_emit.cc index 46695543e..0c72d3bd3 100644 --- a/vhdlpp/architec_emit.cc +++ b/vhdlpp/architec_emit.cc @@ -152,22 +152,9 @@ int CondSignalAssignment::emit(ostream&out, Entity*ent, Architecture*arc) int errors = 0; out << "// " << get_fileline() << endl; - out << "always @("; - + out << "always begin" << endl; bool first = true; - for(list::const_iterator it = sens_list_.begin(); - it != sens_list_.end(); ++it) { - if(first) - first = false; - else - out << ","; - errors += (*it)->emit(out, ent, arc); - } - - out << ") begin" << endl; - - first = true; for(list::iterator it = options_.begin(); it != options_.end(); ++it) { ExpConditional::case_t*cas = *it; @@ -192,6 +179,21 @@ int CondSignalAssignment::emit(ostream&out, Entity*ent, Architecture*arc) out << ";" << endl; } + // Sensitivity list + first = true; + out << "@("; + + for(list::const_iterator it = sens_list_.begin(); + it != sens_list_.end(); ++it) { + if(first) + first = false; + else + out << ","; + + errors += (*it)->emit(out, ent, arc); + } + + out << ");" << endl; out << "end" << endl; return errors; diff --git a/vhdlpp/debug.cc b/vhdlpp/debug.cc index af4fd7a32..717687d68 100644 --- a/vhdlpp/debug.cc +++ b/vhdlpp/debug.cc @@ -436,29 +436,6 @@ void ExpRelation::dump(ostream&out, int indent) const dump_operands(out, indent+4); } -void ExpString::dump(ostream&out, int indent) const -{ - out << setw(indent) << "" << "String \"" << value_; - out << "\"" << " at " << get_fileline() << endl; -} - -void ExpUAbs::dump(ostream&out, int indent) const -{ - out << setw(indent) << "" << "abs() at " << get_fileline() << endl; - dump_operand1(out, indent+4); -} - -void ExpUnary::dump_operand1(ostream&out, int indent) const -{ - operand1_->dump(out, indent); -} - -void ExpUNot::dump(ostream&out, int indent) const -{ - out << setw(indent) << "" << "not() at " << get_fileline() << endl; - dump_operand1(out, indent+4); -} - void named_expr_t::dump(ostream&out, int indent) const { out << setw(indent) << "" << name_ << "=>"; diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index 9efe60931..b9dff1b91 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -24,6 +24,7 @@ # include "subprogram.h" # include "parse_types.h" # include "scope.h" +# include "library.h" # include # include # include @@ -569,6 +570,32 @@ const VType* ExpFunc::func_ret_type() const return def_ ? def_->peek_return_type() : NULL; } +SubprogramHeader*ExpFunc::match_signature(Entity*ent, ScopeBase*scope) const +{ + SubprogramHeader*prog = NULL; + list arg_types; + + // Create a list of argument types to find a matching subprogram + for(vector::const_iterator it = argv_.begin(); + it != argv_.end(); ++it) { + arg_types.push_back((*it)->probe_type(ent, scope)); + } + + prog = scope->match_subprogram(name_, &arg_types); + + if(!prog) + prog = library_match_subprogram(name_, &arg_types); + + if(!prog) { + cerr << get_fileline() << ": sorry: could not find function "; + emit_subprogram_sig(cerr, name_, arg_types); + cerr << endl; + ivl_assert(*this, false); + } + + return prog; +} + ExpInteger::ExpInteger(int64_t val) : value_(val) { @@ -818,6 +845,15 @@ ExpUNot::~ExpUNot() { } +ExpUMinus::ExpUMinus(Expression*op1) +: ExpUnary(op1) +{ +} + +ExpUMinus::~ExpUMinus() +{ +} + ExpCast::ExpCast(Expression*base, const VType*type) : base_(base), type_(type) { diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 65e1934bd..d31955a89 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -620,12 +620,15 @@ class ExpFunc : public Expression { void write_to_stream(std::ostream&fd) const; int emit(ostream&out, Entity*ent, ScopeBase*scope) const; void dump(ostream&out, int indent = 0) const; - void visit(ExprVisitor& func); // NOTE: does not handle expressions in subprogram + void visit(ExprVisitor& func); // NOTE: does not handle expressions in subprogram body + + // Returns a subprogram header that matches the function call + SubprogramHeader*match_signature(Entity*ent, ScopeBase*scope) const; private: perm_string name_; std::vector argv_; - SubprogramHeader*def_; + mutable SubprogramHeader*def_; }; class ExpInteger : public Expression { @@ -948,6 +951,19 @@ class ExpUNot : public ExpUnary { void dump(ostream&out, int indent = 0) const; }; +class ExpUMinus : public ExpUnary { + + public: + explicit ExpUMinus(Expression*op1); + ~ExpUMinus(); + + Expression*clone() const { return new ExpUMinus(peek_operand()->clone()); } + + void write_to_stream(std::ostream&fd) const; + int emit(ostream&out, Entity*ent, ScopeBase*scope) const; + void dump(ostream&out, int indent = 0) const; +}; + /* * Class that wraps other expressions to cast them to other types. */ diff --git a/vhdlpp/expression_debug.cc b/vhdlpp/expression_debug.cc index feaaf9510..cf6a46902 100644 --- a/vhdlpp/expression_debug.cc +++ b/vhdlpp/expression_debug.cc @@ -119,6 +119,35 @@ void ExpShift::dump(ostream&out, int indent) const dump_operands(out, indent+4); } +void ExpString::dump(ostream&out, int indent) const +{ + out << setw(indent) << "" << "String \"" << value_; + out << "\"" << " at " << get_fileline() << endl; +} + +void ExpUAbs::dump(ostream&out, int indent) const +{ + out << setw(indent) << "" << "abs() at " << get_fileline() << endl; + dump_operand1(out, indent+4); +} + +void ExpUnary::dump_operand1(ostream&out, int indent) const +{ + operand1_->dump(out, indent); +} + +void ExpUNot::dump(ostream&out, int indent) const +{ + out << setw(indent) << "" << "not() at " << get_fileline() << endl; + dump_operand1(out, indent+4); +} + +void ExpUMinus::dump(ostream&out, int indent) const +{ + out << setw(indent) << "" << "unary_minus() at " << get_fileline() << endl; + dump_operand1(out, indent+4); +} + void ExpTime::dump(ostream&out, int indent) const { out << setw(indent) << "" << "Time "; diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index 7888f162a..97405ca0b 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -26,7 +26,6 @@ # include "entity.h" # include "vsignal.h" # include "subprogram.h" -# include "library.h" # include "std_types.h" # include # include @@ -74,14 +73,13 @@ const VType*ExpName::elaborate_adjust_type_with_range_(Entity*ent, ScopeBase*sco // If the name is an array, then a part select is // also an array, but with different bounds. int64_t use_msb, use_lsb; - bool flag; + bool flag = true; - flag = range->msb()->evaluate(ent, scope, use_msb); - ivl_assert(*this, flag); - flag = range->lsb()->evaluate(ent, scope, use_lsb); - ivl_assert(*this, flag); + flag &= range->msb()->evaluate(ent, scope, use_msb); + flag &= range->lsb()->evaluate(ent, scope, use_lsb); - type = new VTypeArray(array->element_type(), use_msb, use_lsb); + if(flag) + type = new VTypeArray(array->element_type(), use_msb, use_lsb); } else if(idx) { // If the name is an array or a vector, then an @@ -419,7 +417,7 @@ const VType*ExpAggregate::fit_type(Entity*, ScopeBase*, const VTypeArray*host) c Expression*use_msb = prange->msb(); Expression*use_lsb = prange->lsb(); - ivl_assert(*this, host->dimensions() == 1); + ivl_assert(*this, host->dimensions().size() == 1); vector range (1); range[0] = VTypeArray::range_t(use_msb, use_lsb); @@ -580,6 +578,7 @@ int ExpArithmetic::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype const VType* ExpArithmetic::resolve_operand_types_(const VType*t1, const VType*t2) const { + // Ranges while (const VTypeRange*tmp = dynamic_cast (t1)) t1 = tmp->base_type(); while (const VTypeRange*tmp = dynamic_cast (t2)) @@ -588,7 +587,58 @@ const VType* ExpArithmetic::resolve_operand_types_(const VType*t1, const VType*t if (t1->type_match(t2)) return t1; - return 0; + // Signed & unsigned (resized to the widest argument) + const VTypeArray*t1_arr = dynamic_cast(t1); + const VTypeArray*t2_arr = dynamic_cast(t2); + + if(t1_arr && t2_arr) { + const VTypeArray*t1_parent = t1_arr->get_parent_type(); + const VTypeArray*t2_parent = t2_arr->get_parent_type(); + + if(t1_parent == t2_parent + && (t1_parent == &primitive_SIGNED || t1_parent == &primitive_UNSIGNED)) { + int t1_size = t1_arr->get_width(NULL); + int t2_size = t2_arr->get_width(NULL); + + // Easy, the same sizes, so we do not need to resize + if(t1_size == t2_size && t1_size > 0) + return t1; // == t2 + + VTypeArray*resolved = new VTypeArray(t1_parent->element_type(), + std::max(t1_size, t2_size) - 1, 0, t1_parent->signed_vector()); + resolved->set_parent_type(t1_parent); + + return resolved; + } + + } else if(t1_arr) { + if(const VTypePrimitive*prim = dynamic_cast(t2)) { + const VTypeArray*t1_parent = t1_arr->get_parent_type(); + VTypePrimitive::type_t t2_type = prim->type(); + + if((t2_type == VTypePrimitive::NATURAL || t2_type == VTypePrimitive::INTEGER) + && t1_parent == &primitive_SIGNED) + return t1; + + if((t2_type == VTypePrimitive::NATURAL) && t1_parent == &primitive_UNSIGNED) + return t1; + } + + } else if(t2_arr) { + if(const VTypePrimitive*prim = dynamic_cast(t1)) { + const VTypeArray*t2_parent = t2_arr->get_parent_type(); + VTypePrimitive::type_t t1_type = prim->type(); + + if((t1_type == VTypePrimitive::NATURAL || t1_type == VTypePrimitive::INTEGER) + && t2_parent == &primitive_SIGNED) + return t2; + + if((t1_type == VTypePrimitive::NATURAL) && t2_parent == &primitive_UNSIGNED) + return t2; + } + } + + return 0; } int ExpAttribute::elaborate_args(Entity*ent, ScopeBase*scope, const VType*ltype) @@ -678,7 +728,7 @@ const VType*ExpConcat::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*at if(const VTypeArray*arr = dynamic_cast(types[i])) { types[i] = arr->element_type(); - ivl_assert(*this, arr->dimensions() == 1); + ivl_assert(*this, arr->dimensions().size() == 1); const VTypeArray::range_t&dim = arr->dimension(0); sizes[i] = new ExpArithmetic(ExpArithmetic::MINUS, dim.msb(), dim.lsb()); } else { @@ -733,7 +783,7 @@ int ExpConcat::elaborate_expr_array_(Entity*ent, ScopeBase*scope, const VTypeArr int errors = 0; // For now, only support single-dimension arrays here. - ivl_assert(*this, atype->dimensions() == 1); + ivl_assert(*this, atype->dimensions().size() == 1); const VType*type1 = operand1_->fit_type(ent, scope, atype); ivl_assert(*this, type1); @@ -791,55 +841,23 @@ int ExpConditional::case_t::elaborate_expr(Entity*ent, ScopeBase*scope, const VT const VType*ExpFunc::probe_type(Entity*ent, ScopeBase*scope) const { - SubprogramHeader*prog = def_; + if(!def_) + def_ = match_signature(ent, scope); - if(!prog) { - list arg_types; - - for(vector::const_iterator it = argv_.begin(); - it != argv_.end(); ++it) { - arg_types.push_back((*it)->probe_type(ent, scope)); - } - - prog = scope->match_subprogram(name_, &arg_types); - - if(!prog) - prog = library_match_subprogram(name_, &arg_types); - - if(!prog) { - cerr << get_fileline() << ": sorry: could not find function "; - emit_subprogram_sig(cerr, name_, arg_types); - cerr << endl; - ivl_assert(*this, false); - } - } - - return prog->peek_return_type(); + return def_ ? def_->exact_return_type(argv_, ent, scope) : NULL; } int ExpFunc::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*) { int errors = 0; - ivl_assert(*this, def_ == 0); // do not elaborate twice + if(def_) + return 0; - // Create a list of argument types to find a matching subprogram - list arg_types; - for(vector::iterator it = argv_.begin(); - it != argv_.end(); ++it) - arg_types.push_back((*it)->probe_type(ent, scope)); - - def_ = scope->match_subprogram(name_, &arg_types); + def_ = match_signature(ent, scope); if(!def_) - def_ = library_match_subprogram(name_, &arg_types); - - if(!def_) { - cerr << get_fileline() << ": error: could not find function "; - emit_subprogram_sig(cerr, name_, arg_types); - cerr << endl; - return 1; - } + return 1; // Elaborate arguments for (size_t idx = 0; idx < argv_.size(); ++idx) { @@ -859,7 +877,7 @@ int ExpFunc::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*) const VType* ExpFunc::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*) const { - return probe_type(ent, scope); + return probe_type(ent, scope); } const VType* ExpInteger::probe_type(Entity*, ScopeBase*) const diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index f490cf4dd..a3d6e77e0 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -140,7 +140,7 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, ScopeBase*scope, const VT // Special case: The aggregate is a single "others" item. if (aggregate_.size() == 1 && aggregate_[0].choice->others()) { - assert(atype->dimensions() == 1); + assert(atype->dimensions().size() == 1); const VTypeArray::range_t&rang = atype->dimension(0); assert(! rang.is_box()); @@ -978,7 +978,7 @@ int ExpString::emit(ostream& out, Entity*ent, ScopeBase*scope) const int ExpString::emit_as_array_(ostream& out, Entity*, ScopeBase*, const VTypeArray*arr) const { int errors = 0; - assert(arr->dimensions() == 1); + assert(arr->dimensions().size() == 1); const VTypePrimitive*etype = dynamic_cast (arr->basic_type()); assert(etype); @@ -1048,6 +1048,15 @@ int ExpUNot::emit(ostream&out, Entity*ent, ScopeBase*scope) const return errors; } +int ExpUMinus::emit(ostream&out, Entity*ent, ScopeBase*scope) const +{ + int errors = 0; + out << "-("; + errors += emit_operand1(out, ent, scope); + out << ")"; + return errors; +} + int ExpCast::emit(ostream&out, Entity*ent, ScopeBase*scope) const { int errors = 0; diff --git a/vhdlpp/expression_evaluate.cc b/vhdlpp/expression_evaluate.cc index 97a1e4470..56b2b7eec 100644 --- a/vhdlpp/expression_evaluate.cc +++ b/vhdlpp/expression_evaluate.cc @@ -85,7 +85,7 @@ bool ExpAttribute::test_array_type(const VType*type) const return false; } - if (arr->dimensions() > 1) { + if (arr->dimensions().size() > 1) { cerr << endl << get_fileline() << ": error: " << "Cannot apply the '" << name_ << " attribute to multidimensional arrays" << endl; @@ -144,19 +144,6 @@ bool ExpName::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const return false; } - if (ent) { - const InterfacePort*gen = ent->find_generic(name_); - if (gen) { - // Evaluate the default expression and use that. - if (gen->expr && gen->expr->evaluate(ent, scope, val)) - return true; - - cerr << get_fileline() << ": sorry: I could not evaluate " - << "generic override." << endl; - return false; - } - } - if (scope) { const VType*type; Expression*exp; diff --git a/vhdlpp/expression_stream.cc b/vhdlpp/expression_stream.cc index 43756922a..f9f6f40e5 100644 --- a/vhdlpp/expression_stream.cc +++ b/vhdlpp/expression_stream.cc @@ -327,6 +327,13 @@ void ExpUNot::write_to_stream(ostream&fd) const write_to_stream_operand1(fd); } +void ExpUMinus::write_to_stream(ostream&fd) const +{ + fd << "-("; + write_to_stream_operand1(fd); + fd << ")"; +} + void ExpCast::write_to_stream(ostream&fd) const { // Type casting is introduced only for a few specific cases in diff --git a/vhdlpp/library.cc b/vhdlpp/library.cc index fb015feab..5dd06d58b 100644 --- a/vhdlpp/library.cc +++ b/vhdlpp/library.cc @@ -25,6 +25,7 @@ # include "compiler.h" # include "package.h" # include "std_types.h" +# include "std_funcs.h" # include # include # include @@ -110,7 +111,7 @@ static string make_library_package_path(perm_string lib_name, perm_string name) } static void import_ieee(void); -static void import_ieee_use(ActiveScope*res, perm_string package, perm_string name); +static void import_ieee_use(const YYLTYPE&loc, ActiveScope*res, perm_string package, perm_string name); static void import_std_use(const YYLTYPE&loc, ActiveScope*res, perm_string package, perm_string name); static void dump_library_package(ostream&file, perm_string lname, perm_string pname, Package*pack) @@ -242,7 +243,7 @@ void library_use(const YYLTYPE&loc, ActiveScope*res, // Special case handling for the IEEE library. if (use_library == "ieee") { - import_ieee_use(res, use_package, use_name); + import_ieee_use(loc, res, use_package, use_name); return; } // Special case handling for the STD library. @@ -312,8 +313,30 @@ static void import_ieee_use_std_logic_1164(ActiveScope*res, perm_string name) } } -static void import_ieee_use_std_logic_arith(ActiveScope*, perm_string) +static void import_ieee_use_std_logic_misc(ActiveScope*, perm_string name) { + bool all_flag = name=="all"; + list*args; + + if (all_flag || name == "or_reduce") { + /* function or_reduce(arg : std_logic_vector) return std_logic; + */ + args = new list(); + args->push_back(new InterfacePort(&primitive_STDLOGIC_VECTOR)); + register_std_subprogram(new SubprogramBuiltin(perm_string::literal("or_reduce"), + perm_string::literal("|"), + args, &primitive_STDLOGIC)); + } + + if (all_flag || name == "and_reduce") { + /* function and_reduce(arg : std_logic_vector) return std_logic; + */ + args = new list(); + args->push_back(new InterfacePort(&primitive_STDLOGIC_VECTOR)); + register_std_subprogram(new SubprogramBuiltin(perm_string::literal("and_reduce"), + perm_string::literal("&"), + args, &primitive_STDLOGIC)); + } } static void import_ieee_use_numeric_bit(ActiveScope*res, perm_string name) @@ -340,7 +363,7 @@ static void import_ieee_use_numeric_std(ActiveScope*res, perm_string name) } } -static void import_ieee_use(ActiveScope*res, perm_string package, perm_string name) +static void import_ieee_use(const YYLTYPE&loc, ActiveScope*res, perm_string package, perm_string name) { if (package == "std_logic_1164") { import_ieee_use_std_logic_1164(res, name); @@ -348,10 +371,20 @@ static void import_ieee_use(ActiveScope*res, perm_string package, perm_string na } if (package == "std_logic_arith") { - import_ieee_use_std_logic_arith(res, name); + // arithmetic operators for std_logic_vector return; } + if (package == "std_logic_misc") { + import_ieee_use_std_logic_misc(res, name); + return; + } + + if (package == "std_logic_unsigned") { + // arithmetic operators for std_logic_vector + return; + } + if (package == "numeric_bit") { import_ieee_use_numeric_bit(res, name); return; @@ -361,9 +394,11 @@ static void import_ieee_use(ActiveScope*res, perm_string package, perm_string na import_ieee_use_numeric_std(res, name); return; } + + cerr << "Warning: Package ieee." << package.str() <<" is not yet supported" << endl; } -static void import_std_use(const YYLTYPE&loc, ActiveScope*res, perm_string package, perm_string name) +static void import_std_use(const YYLTYPE&loc, ActiveScope*res, perm_string package, perm_string /*name*/) { if (package == "standard") { // do nothing @@ -375,7 +410,7 @@ static void import_std_use(const YYLTYPE&loc, ActiveScope*res, perm_string packa res->use_name(type_FILE_OPEN_STATUS.peek_name(), &type_FILE_OPEN_STATUS); return; } else { - sorrymsg(loc, "package %s of library %s not yet supported", package.str(), name.str()); + cerr << "Warning: Package std." << package.str() <<" is not yet supported" << endl; return; } } diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 82ccde7e3..6b4c13e5d 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -2484,11 +2484,6 @@ shift_expression } ; -sign - : '+' - | '-' - ; - signal_declaration_assign_opt : VASSIGN expression { $$ = $2; } | { $$ = 0; } @@ -2514,10 +2509,10 @@ signal_declaration_assign_opt * list fixes up the associations. */ simple_expression - : sign simple_expression_2 - { sorrymsg(@1, "Unary expression +- not supported.\n"); - $$ = $2; - } + : '-' simple_expression_2 + { $$ = new ExpUMinus($2); } + | '+' simple_expression_2 + { $$ = $2; } | simple_expression_2 { $$ = $1; } ; diff --git a/vhdlpp/parse_misc.cc b/vhdlpp/parse_misc.cc index a26eac818..f1d86184d 100644 --- a/vhdlpp/parse_misc.cc +++ b/vhdlpp/parse_misc.cc @@ -77,7 +77,7 @@ static const VType* calculate_subtype_array(const YYLTYPE&loc, const char*base_n const VType*base_type = parse_type_by_name(lex_strings.make(base_name)); if (base_type == 0) { - errormsg(loc, "Unable to find base type %s of array.\n", base_name); + errormsg(loc, "Unable to find array base type '%s'.\n", base_name); return 0; } @@ -97,7 +97,7 @@ static const VType* calculate_subtype_array(const YYLTYPE&loc, const char*base_n vector range (base_array->dimensions()); // For now, I only know how to handle 1 dimension - assert(base_array->dimensions() == 1); + assert(base_array->dimensions().size() == 1); range[0] = VTypeArray::range_t(array_left, array_right, downto); @@ -141,7 +141,7 @@ const VType* calculate_subtype_range(const YYLTYPE&loc, const char*base_name, const VType*base_type = parse_type_by_name(lex_strings.make(base_name)); if (base_type == 0) { - errormsg(loc, "Unable to find base type %s of range.\n", base_name); + errormsg(loc, "Unable to find range base type '%s'.\n", base_name); return 0; } diff --git a/vhdlpp/std_funcs.cc b/vhdlpp/std_funcs.cc index fa417904e..e08e0c669 100644 --- a/vhdlpp/std_funcs.cc +++ b/vhdlpp/std_funcs.cc @@ -24,7 +24,7 @@ static std::map std_subprograms; -static inline void register_std_subprogram(SubprogramHeader*header) +void register_std_subprogram(SubprogramHeader*header) { std_subprograms[header->name()].push_back(header); } @@ -68,28 +68,51 @@ class SubprogramSizeCast : public SubprogramStdHeader { : SubprogramStdHeader(nam, NULL, target) { ports_ = new list(); ports_->push_back(new InterfacePort(base)); - ports_->push_back(new InterfacePort(&primitive_INTEGER)); + ports_->push_back(new InterfacePort(&primitive_NATURAL)); } - int emit_name(const std::vector&argv, - std::ostream&out, Entity*ent, ScopeBase*scope) const { - int64_t use_size; - bool rc = argv[1]->evaluate(ent, scope, use_size); - - if(!rc) { - cerr << get_fileline() << ": sorry: Could not evaluate the " - << "expression size. Size casting impossible." << endl; - return 1; - } - - out << use_size << "'"; + int emit_name(const std::vector&, + std::ostream&, Entity*, ScopeBase*) const { return 0; } int emit_args(const std::vector&argv, std::ostream&out, Entity*ent, ScopeBase*scope) const { + int64_t new_size, old_size; - return argv[0]->emit(out, ent, scope); + const VType*type = argv[0]->probe_type(ent, scope); + + if(!type) { + cerr << get_fileline() << ": sorry: Could not determine " + << "the argument type. Size casting impossible." << endl; + return 1; + } + + old_size = type->get_width(scope); + + if(old_size <= 0) { + cerr << get_fileline() << ": sorry: Could not determine " + << "the argument size. Size casting impossible." << endl; + return 1; + } + + if(!argv[1]->evaluate(ent, scope, new_size)) { + cerr << get_fileline() << ": sorry: Could not evaluate the requested" + << "expression size. Size casting impossible." << endl; + return 1; + } + + + out << new_size << "'(" << old_size << "'("; + + if(const VTypeArray*arr = dynamic_cast(type)) + out << (arr->signed_vector() ? "$signed" : "$unsigned"); + + out << "("; + bool res = argv[0]->emit(out, ent, scope); + out << ")))"; + + return res; } }; @@ -187,7 +210,13 @@ void preload_std_funcs(void) have to do anything for that to work. */ args = new list(); - args->push_back(new InterfacePort(&primitive_STDLOGIC_VECTOR)); + args->push_back(new InterfacePort(&primitive_SIGNED)); + register_std_subprogram(new SubprogramBuiltin(perm_string::literal("std_logic_vector"), + empty_perm_string, + args, &primitive_STDLOGIC_VECTOR)); + + args = new list(); + args->push_back(new InterfacePort(&primitive_UNSIGNED)); register_std_subprogram(new SubprogramBuiltin(perm_string::literal("std_logic_vector"), empty_perm_string, args, &primitive_STDLOGIC_VECTOR)); @@ -215,6 +244,13 @@ void preload_std_funcs(void) * function shift_right (arg: signed; count: natural) return signed; */ args = new list(); + args->push_back(new InterfacePort(&primitive_UNSIGNED)); + args->push_back(new InterfacePort(&primitive_NATURAL)); + register_std_subprogram(new SubprogramBuiltin(perm_string::literal("shift_right"), + perm_string::literal("$ivlh_shift_right"), + args, &primitive_UNSIGNED)); + + args = new list(); args->push_back(new InterfacePort(&primitive_SIGNED)); args->push_back(new InterfacePort(&primitive_NATURAL)); register_std_subprogram(new SubprogramBuiltin(perm_string::literal("shift_right"), @@ -224,12 +260,16 @@ void preload_std_funcs(void) /* function resize */ register_std_subprogram(new SubprogramSizeCast(perm_string::literal("resize"), - &primitive_STDLOGIC_VECTOR, &primitive_STDLOGIC_VECTOR)); + &primitive_UNSIGNED, &primitive_UNSIGNED)); + + register_std_subprogram(new SubprogramSizeCast(perm_string::literal("resize"), + &primitive_SIGNED, &primitive_SIGNED)); /* std_logic_arith library * function conv_std_logic_vector(arg: integer; size: integer) return std_logic_vector; */ - register_std_subprogram(new SubprogramSizeCast(perm_string::literal("conv_std_logic_vector"), + register_std_subprogram(new SubprogramSizeCast( + perm_string::literal("conv_std_logic_vector"), &primitive_INTEGER, &primitive_STDLOGIC_VECTOR)); /* numeric_bit library diff --git a/vhdlpp/std_funcs.h b/vhdlpp/std_funcs.h index f3a904d44..8569b2424 100644 --- a/vhdlpp/std_funcs.h +++ b/vhdlpp/std_funcs.h @@ -28,6 +28,9 @@ void preload_std_funcs(); // Destroys subprogram headers for standard VHDL library functions. void delete_std_funcs(); +// Adds a subprogram to the standard library subprogram set +void register_std_subprogram(SubprogramHeader*header); + // Returns subprogram header for a requested function or NULL if it does not exist. SubHeaderList find_std_subprogram(perm_string name); diff --git a/vhdlpp/subprogram.cc b/vhdlpp/subprogram.cc index bd7d832cc..d06917a31 100644 --- a/vhdlpp/subprogram.cc +++ b/vhdlpp/subprogram.cc @@ -172,6 +172,24 @@ const VType*SubprogramHeader::peek_param_type(int idx) const return NULL; } +const VType*SubprogramHeader::exact_return_type(const std::vector&argv, Entity*ent, ScopeBase*scope) +{ + const VTypeArray*orig_ret = dynamic_cast(return_type_); + + if(!orig_ret) + return return_type_; + + const VTypeArray*arg = dynamic_cast(argv[0]->fit_type(ent, scope, orig_ret)); + + if(!arg) + return return_type_; + + VTypeArray*ret = new VTypeArray(orig_ret->element_type(), arg->dimensions(), orig_ret->signed_vector()); + ret->set_parent_type(orig_ret); + + return ret; +} + bool SubprogramHeader::unbounded() const { if(return_type_ && return_type_->is_unbounded()) return true; diff --git a/vhdlpp/subprogram.h b/vhdlpp/subprogram.h index d06f82461..a03b8da92 100644 --- a/vhdlpp/subprogram.h +++ b/vhdlpp/subprogram.h @@ -80,6 +80,10 @@ class SubprogramHeader : public LineInfo { const VType*peek_param_type(int idx) const; const VType*peek_return_type() const { return return_type_; } + // Computes the exact return type (e.g. std_logic_vector(7 downto 0) + // instead of generic std_logic_vector) + virtual const VType*exact_return_type(const std::vector&, Entity*, ScopeBase*); + inline void set_package(const Package*pkg) { assert(!package_); package_ = pkg; } inline const Package*get_package() const { return package_; } diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index 7c5ec3aac..4f34c62ac 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -226,7 +226,7 @@ class VTypeArray : public VType { void show(std::ostream&) const; int get_width(ScopeBase*scope) const; - inline size_t dimensions() const { return ranges_.size(); }; + const std::vector&dimensions() const { return ranges_; }; const range_t&dimension(size_t idx) const { return ranges_[idx]; } @@ -253,6 +253,8 @@ class VTypeArray : public VType { // To handle subtypes inline void set_parent_type(const VTypeArray*parent) { parent_ = parent; } + const VTypeArray*get_parent_type() const { return parent_; } + // Wherever it is possible, replaces range lsb & msb expressions with // constant integers. void evaluate_ranges(ScopeBase*scope); diff --git a/vhdlpp/vtype_emit.cc b/vhdlpp/vtype_emit.cc index 8327af50c..81807fa4b 100644 --- a/vhdlpp/vtype_emit.cc +++ b/vhdlpp/vtype_emit.cc @@ -65,7 +65,7 @@ int VTypeArray::emit_def(ostream&out, perm_string name) const const VTypePrimitive*base = dynamic_cast (raw_base); if (base) { - assert(dimensions() == 1); + assert(dimensions().size() == 1); // If this is a string type without any boundaries specified, then // there is a direct counterpart in SV called.. 'string' @@ -127,7 +127,7 @@ int VTypeArray::emit_with_dims_(std::ostream&out, bool packed, perm_string name) name_emitted = true; } - for(unsigned i = 0; i < cur->dimensions(); ++i) { + for(unsigned i = 0; i < cur->dimensions().size(); ++i) { if(cur->dimension(i).is_box() && !name_emitted) { emit_name(out, name); name_emitted = true; diff --git a/vhdlpp/vtype_match.cc b/vhdlpp/vtype_match.cc index a4a49b1b5..c99a2fd78 100644 --- a/vhdlpp/vtype_match.cc +++ b/vhdlpp/vtype_match.cc @@ -70,7 +70,15 @@ bool VTypeArray::type_match(const VType*that) const // Check if both arrays are of the same size if(const VTypeArray*arr = dynamic_cast(that)) { - if(!element_type()->type_match(arr->element_type())) + const VTypeArray*this_parent = this; + while(const VTypeArray*tmp = this_parent->get_parent_type()) + this_parent = tmp; + + const VTypeArray*that_parent = arr; + while(const VTypeArray*tmp = that_parent->get_parent_type()) + that_parent = tmp; + + if(this_parent != that_parent) return false; int this_width = get_width(NULL);