From ae06863db123f0d214861de3ce6602e5f8f6eeed Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 8 Apr 2012 15:45:17 -0700 Subject: [PATCH] Elaborate prefix names which may be structure variables. --- vhdlpp/architec_elaborate.cc | 13 +++- vhdlpp/expression.h | 5 +- vhdlpp/expression_elaborate.cc | 131 ++++++++++++++++++++++++++------- 3 files changed, 118 insertions(+), 31 deletions(-) diff --git a/vhdlpp/architec_elaborate.cc b/vhdlpp/architec_elaborate.cc index d399c141d..23dc837f2 100644 --- a/vhdlpp/architec_elaborate.cc +++ b/vhdlpp/architec_elaborate.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Stephen Williams (steve@icarus.com) + * Copyright (c) 2011-2012 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 @@ -31,10 +31,12 @@ int Architecture::elaborate(Entity*entity) for (list::iterator cur = statements_.begin() ; cur != statements_.end() ; ++cur) { - errors += (*cur)->elaborate(entity, this); + int cur_errors = (*cur)->elaborate(entity, this); + errors += cur_errors; } - return errors; + cerr << errors << " errors in " << name_ << " architecture of " << entity->get_name() << "." << endl; + return errors; } int Architecture::Statement::elaborate(Entity*, Architecture*) @@ -276,7 +278,10 @@ int SignalAssignment::elaborate(Entity*ent, Architecture*arc) // r-value. const VType*lval_type = lval_->peek_type(); if (lval_type == 0) { - if (errors == 0) errors += 1; + if (errors == 0) { + errors += 1; + cerr << get_fileline() << ": error: Unable to calculate type for l-value expression." << endl; + } return errors; } diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 739f8079d..5004e2ce6 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -1,7 +1,7 @@ #ifndef __expression_H #define __expression_H /* - * Copyright (c) 2011 Stephen Williams (steve@icarus.com) + * Copyright (c) 2011-2012 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 @@ -485,6 +485,9 @@ class ExpName : public Expression { const char* name() const; private: + const VType* elaborate_adjust_type_with_range_(Entity*ent, Architecture*arc, const VType*type); + + int elaborate_lval_(Entity*ent, Architecture*arc, bool, ExpName*suffix); const VType* probe_prefix_type_(Entity*ent, Architecture*arc) const; const VType* probe_prefixed_type_(Entity*ent, Architecture*arc) const; diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index 1386a549d..8e3d4588d 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Stephen Williams (steve@icarus.com) + * Copyright (c) 2011-2012 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 @@ -39,7 +39,38 @@ const VType* Expression::probe_type(Entity*, Architecture*) const return 0; } -int ExpName::elaborate_lval(Entity*ent, Architecture*arc, bool is_sequ) +const VType*ExpName::elaborate_adjust_type_with_range_(Entity*, Architecture*arc, const VType*type) +{ + + if (const VTypeArray*array = dynamic_cast(type)) { + if (index_ && !lsb_) { + // If the name is an array or a vector, then an + // indexed name has the type of the element. + type = array->element_type(); + + } else if (index_ && lsb_) { + // 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; + + flag = index_->evaluate(arc, use_msb); + ivl_assert(*this, flag); + flag = lsb_->evaluate(arc, use_lsb); + ivl_assert(*this, flag); + + Expression*exp_msb = new ExpInteger(use_msb); + Expression*exp_lsb = new ExpInteger(use_lsb); + vector use_dims (1); + use_dims[0] = VTypeArray::range_t(exp_msb, exp_lsb); + type = new VTypeArray(array->element_type(), use_dims); + } + } + + return type; +} + +int ExpName::elaborate_lval_(Entity*ent, Architecture*arc, bool is_sequ, ExpName*suffix) { int errors = 0; @@ -52,6 +83,77 @@ int ExpName::elaborate_lval(Entity*ent, Architecture*arc, bool is_sequ) const VType*found_type = 0; + if (const InterfacePort*cur = ent->find_port(name_)) { + if (cur->mode != PORT_OUT) { + cerr << get_fileline() << ": error: Assignment to " + "input port " << name_ << "." << endl; + return errors + 1; + } + + if (is_sequ) + ent->set_declaration_l_value(name_, is_sequ); + + found_type = cur->type; + + } else if (ent->find_generic(name_)) { + + cerr << get_fileline() << ": error: Assignment to generic " + << name_ << " from entity " + << ent->get_name() << "." << endl; + return errors + 1; + + } else if (Signal*sig = arc->find_signal(name_)) { + // Tell the target signal that this may be a sequential l-value. + if (is_sequ) sig->count_ref_sequ(); + + found_type = sig->peek_type(); + + } else if (Variable*var = arc->find_variable(name_)) { + // Tell the target signal that this may be a sequential l-value. + if (is_sequ) var->count_ref_sequ(); + + found_type = var->peek_type(); + } + + ivl_assert(*this, found_type); + + const VType*suffix_type = 0; + + if (const VTypeRecord*record = dynamic_cast (found_type)) { + const VTypeRecord::element_t*element = record->element_by_name(suffix->name_); + ivl_assert(*this, element); + + const VType*element_type = element->peek_type(); + ivl_assert(*this, element_type); + + suffix_type = element_type; + } + + if (suffix_type == 0) { + cerr << get_fileline() << ": error: I don't know how to handle prefix " << name_ + << " with suffix " << suffix->name_ << endl; + errors += 1; + return errors; + } + + suffix_type = suffix->elaborate_adjust_type_with_range_(ent, arc, suffix_type); + + ivl_assert(*this, suffix_type); + suffix->set_type(suffix_type); + + return errors; +} + +int ExpName::elaborate_lval(Entity*ent, Architecture*arc, bool is_sequ) +{ + int errors = 0; + + if (prefix_.get()) { + return prefix_->elaborate_lval_(ent, arc, is_sequ, this); + } + + const VType*found_type = 0; + if (const InterfacePort*cur = ent->find_port(name_)) { if (cur->mode != PORT_OUT) { cerr << get_fileline() << ": error: Assignment to " @@ -90,30 +192,7 @@ int ExpName::elaborate_lval(Entity*ent, Architecture*arc, bool is_sequ) return errors + 1; } - if (const VTypeArray*array = dynamic_cast(found_type)) { - if (index_ && !lsb_) { - // If the name is an array or a vector, then an - // indexed name has the type of the element. - found_type = array->element_type(); - - } else if (index_ && lsb_) { - // 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; - - flag = index_->evaluate(arc, use_msb); - ivl_assert(*this, flag); - flag = lsb_->evaluate(arc, use_lsb); - ivl_assert(*this, flag); - - Expression*exp_msb = new ExpInteger(use_msb); - Expression*exp_lsb = new ExpInteger(use_lsb); - vector use_dims (1); - use_dims[0] = VTypeArray::range_t(exp_msb, exp_lsb); - found_type = new VTypeArray(array->element_type(), use_dims); - } - } + found_type = elaborate_adjust_type_with_range_(ent, arc, found_type); set_type(found_type); return errors;