From bcca3cf395b64a3c6bf11faabad9f1442f231762 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 13 Jan 2015 10:07:16 +0100 Subject: [PATCH 01/41] ivl: Unpacked array typedefs are correctly recognized when used in function parameters. --- pform.cc | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/pform.cc b/pform.cc index b8318c792..c0ad24fd9 100644 --- a/pform.cc +++ b/pform.cc @@ -2661,7 +2661,6 @@ vector*pform_make_task_ports(const struct vlltype&loc, } delete range; - delete names; return res; } @@ -2690,7 +2689,6 @@ static vector*do_make_task_ports(const struct vlltype&loc, res->push_back(pform_tf_port_t(curw)); } - delete names; return res; } @@ -2699,35 +2697,54 @@ vector*pform_make_task_ports(const struct vlltype&loc, data_type_t*vtype, list*names) { + vector*ret = NULL; + std::list*unpacked_dims = NULL; + + if (uarray_type_t*uarray = dynamic_cast (vtype)) { + unpacked_dims = uarray->dims.get(); + vtype = uarray->base_type; + } + if (atom2_type_t*atype = dynamic_cast (vtype)) { list*range_tmp = make_range_from_width(atype->type_code); - return pform_make_task_ports(loc, pt, IVL_VT_BOOL, + ret = pform_make_task_ports(loc, pt, IVL_VT_BOOL, atype->signed_flag, range_tmp, names); } if (vector_type_t*vec_type = dynamic_cast (vtype)) { - return pform_make_task_ports(loc, pt, vec_type->base_type, + ret = pform_make_task_ports(loc, pt, vec_type->base_type, vec_type->signed_flag, copy_range(vec_type->pdims.get()), names, vec_type->integer_flag); } if (/*real_type_t*real_type = */ dynamic_cast (vtype)) { - return pform_make_task_ports(loc, pt, IVL_VT_REAL, + ret = pform_make_task_ports(loc, pt, IVL_VT_REAL, true, 0, names); } if (dynamic_cast (vtype)) { - return pform_make_task_ports(loc, pt, IVL_VT_STRING, + ret = pform_make_task_ports(loc, pt, IVL_VT_STRING, false, 0, names); } if (class_type_t*class_type = dynamic_cast (vtype)) { - return do_make_task_ports(loc, pt, IVL_VT_CLASS, class_type, names); + ret = do_make_task_ports(loc, pt, IVL_VT_CLASS, class_type, names); } - return do_make_task_ports(loc, pt, IVL_VT_NO_TYPE, vtype, names); + ret = do_make_task_ports(loc, pt, IVL_VT_NO_TYPE, vtype, names); + + if (unpacked_dims) { + for (list::iterator cur = names->begin() + ; cur != names->end() ; ++ cur ) { + PWire*wire = pform_get_wire_in_scope(*cur); + wire->set_unpacked_idx(*unpacked_dims); + } + } + + delete names; + return ret; } /* From 0592ba042e299288b7ad4372c8f8c830a9d067aa Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 13 Jan 2015 18:00:41 +0100 Subject: [PATCH 02/41] vhdlpp: For-loop emission rewritten to handle 'range in subprograms. --- vhdlpp/expression_evaluate.cc | 8 +- vhdlpp/sequential.h | 6 +- vhdlpp/sequential_emit.cc | 146 +++++++++++++++++++++------------- 3 files changed, 100 insertions(+), 60 deletions(-) diff --git a/vhdlpp/expression_evaluate.cc b/vhdlpp/expression_evaluate.cc index 2f506eb28..27baba7e7 100644 --- a/vhdlpp/expression_evaluate.cc +++ b/vhdlpp/expression_evaluate.cc @@ -112,10 +112,14 @@ bool ExpAttribute::evaluate(ScopeBase*, int64_t&val) const bool ExpAttribute::evaluate(Entity*ent, Architecture*arc, int64_t&val) const { + if (!ent || !arc) { // it's impossible to evaluate, probably it is inside a subprogram + return false; + } + if (name_ == "left" || name_ == "right") { const VType*base_type = base_->peek_type(); if (base_type == 0) - base_type = base_->probe_type(ent,arc); + base_type = base_->probe_type(ent, arc); ivl_assert(*this, base_type); @@ -130,7 +134,7 @@ bool ExpAttribute::evaluate(Entity*ent, Architecture*arc, int64_t&val) const ivl_assert(*this, arr->dimensions() == 1); if(name_ == "left") arr->dimension(0).msb()->evaluate(ent, arc, val); - else + else // "right" arr->dimension(0).lsb()->evaluate(ent, arc, val); return true; diff --git a/vhdlpp/sequential.h b/vhdlpp/sequential.h index 9271e4ed3..51973d159 100644 --- a/vhdlpp/sequential.h +++ b/vhdlpp/sequential.h @@ -225,10 +225,14 @@ class ForLoopStatement : public LoopStatement { ~ForLoopStatement(); int elaborate(Entity*ent, Architecture*arc); - int emit(ostream&out, Entity*entity, Architecture*arc); + int emit(ostream&out, Entity*ent, Architecture*arc); void dump(ostream&out, int indent) const; private: + // Emits for-loop which direction is determined at run-time. + // It is used for 'range & 'reverse_range attributes. + int emit_runtime_(ostream&out, Entity*ent, Architecture*arc); + perm_string it_; prange_t* range_; }; diff --git a/vhdlpp/sequential_emit.cc b/vhdlpp/sequential_emit.cc index 86a9a529c..3203eb704 100644 --- a/vhdlpp/sequential_emit.cc +++ b/vhdlpp/sequential_emit.cc @@ -200,76 +200,108 @@ int CaseSeqStmt::CaseStmtAlternative::emit(ostream&out, Entity*ent, Architecture int ForLoopStatement::emit(ostream&out, Entity*ent, Architecture*arc) { - int errors = 0; - ivl_assert(*this, range_); + int errors = 0; + ivl_assert(*this, range_); - int64_t start_val; - bool start_rc = range_->msb()->evaluate(ent, arc, start_val); + int64_t start_val; + bool start_rc = range_->msb()->evaluate(ent, arc, start_val); - int64_t finish_val; - bool finish_rc = range_->lsb()->evaluate(ent, arc, finish_val); + int64_t finish_val; + bool finish_rc = range_->lsb()->evaluate(ent, arc, finish_val); - ivl_assert(*this, start_rc); - ivl_assert(*this, finish_rc); + perm_string scope_name = loop_name(); + if (scope_name.nil()) { + char buf[80]; + snprintf(buf, sizeof buf, "__%p", this); + scope_name = lex_strings.make(buf); + } - bool dir = range_->is_downto(); + out << "begin : " << scope_name << endl; + out << "longint \\" << it_ << " ;" << endl; - if (!dir) { - int64_t tmp = start_val; - start_val = finish_val; - finish_val = tmp; - } + if(!start_rc || !finish_rc) { + // Could not evaluate one of the loop boundaries, it has to be + // determined during the run-time + errors += emit_runtime_(out, ent, arc); + } else { + bool dir = range_->is_downto(); - if (dir && (start_val < finish_val)) { - if(range_->is_auto_dir()) { - dir = false; - } else { - out << "begin /* Degenerate loop at " << get_fileline() - << ": " << start_val - << " downto " << finish_val << " */ end" << endl; - return errors; - } - } + if (!dir) { + int64_t tmp = start_val; + start_val = finish_val; + finish_val = tmp; + } - else if (!dir && start_val > finish_val) { - if(range_->is_auto_dir()) { - dir = true; - } else { - out << "begin /* Degenerate loop at " << get_fileline() - << ": " << start_val - << " to " << finish_val << " */ end" << endl; - return errors; - } - } + if (dir && (start_val < finish_val)) { + if(range_->is_auto_dir()) { + dir = false; + } else { + out << "begin /* Degenerate loop at " << get_fileline() + << ": " << start_val + << " downto " << finish_val << " */ end" << endl; + return errors; + } + } - perm_string scope_name = loop_name(); - if (scope_name.nil()) { - char buf[80]; - snprintf(buf, sizeof buf, "__%p", this); - scope_name = lex_strings.make(buf); - } + else if (!dir && start_val > finish_val) { + if(range_->is_auto_dir()) { + dir = true; + } else { + out << "begin /* Degenerate loop at " << get_fileline() + << ": " << start_val + << " to " << finish_val << " */ end" << endl; + return errors; + } + } - out << "begin : " << scope_name << endl; - out << "longint \\" << it_ << " ;" << endl; - out << "for (\\" << it_ << " = " << start_val << " ; "; - if (dir) - out << "\\" << it_ << " >= " << finish_val; - else - out << "\\" << it_ << " <= " << finish_val; - out << "; \\" << it_ << " = \\" << it_; - if (dir) - out << " - 1"; - else - out << " + 1"; + out << "for (\\" << it_ << " = " << start_val << " ; "; - out << ") begin" << endl; + if (dir) + out << "\\" << it_ << " >= " << finish_val; + else + out << "\\" << it_ << " <= " << finish_val; - errors += emit_substatements(out, ent, arc); + out << "; \\" << it_ << " = \\" << it_; - out << "end" << endl; - out << "end /* " << scope_name << " */" << endl; + if (dir) + out << " - 1)"; + else + out << " + 1)"; + } - return errors; + out << " begin" << endl; + + errors += emit_substatements(out, ent, arc); + + out << "end" << endl; + out << "end /* " << scope_name << " */" << endl; + + return errors; +} + +int ForLoopStatement::emit_runtime_(ostream&out, Entity*ent, Architecture*arc) +{ + int errors = 0; + + out << "for (\\" << it_ << " = "; + errors += range_->expr_left()->emit(out, ent, arc); + + // Twisted way of determining the loop direction at runtime + out << " ;\n("; + errors += range_->expr_left()->emit(out, ent, arc); + out << " < "; + errors += range_->expr_right()->emit(out, ent, arc); + out << " ? \\" << it_ << " <= "; + errors += range_->expr_right()->emit(out, ent, arc); + out << " : \\" << it_ << " >= "; + errors += range_->expr_right()->emit(out, ent, arc); + out << ");\n\\" << it_ << " = \\" << it_ << " + ("; + errors += range_->expr_left()->emit(out, ent, arc); + out << " < "; + errors += range_->expr_right()->emit(out, ent, arc); + out << " ? 1 : -1))"; + + return errors; } int WhileLoopStatement::emit(ostream&out, Entity*, Architecture*) From a02ebc3114de279e9ce2723286429b94c210d652 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 19 Jan 2015 10:24:49 +0100 Subject: [PATCH 03/41] $ivl_darray_method$[from/to]_vec works with constants. --- vpi/sys_darray.c | 1 + 1 file changed, 1 insertion(+) diff --git a/vpi/sys_darray.c b/vpi/sys_darray.c index e6d76d3bd..507bb974a 100644 --- a/vpi/sys_darray.c +++ b/vpi/sys_darray.c @@ -143,6 +143,7 @@ static PLI_INT32 to_from_vec_compiletf(ICARUS_VPI_CONST PLI_BYTE8*name) case vpiReg: case vpiBitVar: case vpiIntegerVar: + case vpiConstant: break; default: vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), From e6b22a2beac208af8658f551de5d5b8e707d7fdb Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 19 Jan 2015 16:12:04 +0100 Subject: [PATCH 04/41] vhdlpp: Visitor for SequentialStmt. --- vhdlpp/sequential.cc | 38 ++++++++++++++++++++++++++++++++++++++ vhdlpp/sequential.h | 6 ++++++ 2 files changed, 44 insertions(+) diff --git a/vhdlpp/sequential.cc b/vhdlpp/sequential.cc index 9d5d8d6e3..f5d4509eb 100644 --- a/vhdlpp/sequential.cc +++ b/vhdlpp/sequential.cc @@ -20,6 +20,14 @@ # include "sequential.h" # include "expression.h" +template +inline static void visit_stmt_list(std::list& stmts, void((*func))(SequentialStmt*)) +{ + for(typename std::list::iterator it = stmts.begin(); it != stmts.end(); ++it) { + (*it)->visit(func); + } +} + SequentialStmt::SequentialStmt() { } @@ -75,6 +83,14 @@ void IfSequential::extract_false(std::list&that) } } +void IfSequential::visit(void((*func))(SequentialStmt*)) +{ + visit_stmt_list(if_, func); + visit_stmt_list(elsif_, func); + visit_stmt_list(else_, func); + ((*func))(this); +} + IfSequential::Elsif::Elsif(Expression*cond, std::list*tr) : cond_(cond) { @@ -91,6 +107,11 @@ IfSequential::Elsif::~Elsif() } } +void IfSequential::Elsif::visit(void((*func))(SequentialStmt*)) +{ + visit_stmt_list(if_, func); +} + SignalSeqAssignment::SignalSeqAssignment(Expression*sig, std::list*wav) { lval_ = sig; @@ -118,6 +139,12 @@ CaseSeqStmt::~CaseSeqStmt() } } +void CaseSeqStmt::visit(void((*func))(SequentialStmt*)) +{ + visit_stmt_list(alt_, func); + ((*func))(this); +} + CaseSeqStmt::CaseStmtAlternative::CaseStmtAlternative(Expression* exp, list* stmts) : exp_(exp) { @@ -134,6 +161,11 @@ CaseSeqStmt::CaseStmtAlternative::~CaseStmtAlternative() } } +void CaseSeqStmt::CaseStmtAlternative::visit(void((*func))(SequentialStmt*)) +{ + visit_stmt_list(stmts_, func); +} + ProcedureCall::ProcedureCall(perm_string name) : name_(name), param_list_(0) { @@ -178,6 +210,12 @@ LoopStatement::~LoopStatement() } } +void LoopStatement::visit(void((*func))(SequentialStmt*)) +{ + visit_stmt_list(stmts_, func); + (*func)(this); +} + ForLoopStatement::ForLoopStatement(perm_string scope_name, perm_string it, prange_t* range, list* stmts) : LoopStatement(scope_name, stmts), it_(it), range_(range) { diff --git a/vhdlpp/sequential.h b/vhdlpp/sequential.h index 51973d159..881c9b002 100644 --- a/vhdlpp/sequential.h +++ b/vhdlpp/sequential.h @@ -38,6 +38,7 @@ class SequentialStmt : public LineInfo { virtual int elaborate(Entity*ent, Architecture*arc); virtual int emit(ostream&out, Entity*entity, Architecture*arc); virtual void dump(ostream&out, int indent) const; + virtual void visit(void(*func)(SequentialStmt*)) { (*func)(this); } }; /* @@ -52,6 +53,7 @@ class LoopStatement : public SequentialStmt { inline perm_string loop_name() const { return name_; } void dump(ostream&out, int indent) const; + void visit(void(*func)(SequentialStmt*)); protected: int elaborate_substatements(Entity*ent, Architecture*arc); @@ -75,6 +77,7 @@ class IfSequential : public SequentialStmt { int statement_emit(ostream&out, Entity*entity, Architecture*arc); void dump(ostream&out, int indent) const; + void visit(void(*func)(SequentialStmt*)); private: Expression*cond_; @@ -94,6 +97,7 @@ class IfSequential : public SequentialStmt { int elaborate(Entity*ent, Architecture*arc); int emit(ostream&out, Entity*entity, Architecture*arc); void dump(ostream&out, int indent) const; + void visit(void(*func)(SequentialStmt*)); const Expression*peek_condition() const { return cond_; } @@ -151,6 +155,7 @@ class CaseSeqStmt : public SequentialStmt { int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); int elaborate(Entity*ent, Architecture*arc); int emit(ostream&out, Entity*entity, Architecture*arc); + void visit(void(*func)(SequentialStmt*)); private: Expression* exp_; @@ -168,6 +173,7 @@ class CaseSeqStmt : public SequentialStmt { void dump(ostream&out, int indent) const; int elaborate(Entity*ent, Architecture*arc); int emit(ostream&out, Entity*entity, Architecture*arc); + void visit(void(*func)(SequentialStmt*)); private: Expression* cond_; From b05a19dffc816f58fbcc25ecc5400ce14db6097d Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 19 Jan 2015 17:33:15 +0100 Subject: [PATCH 05/41] vhdlpp: VTypeArray emits dimensions in a bit smarter way. --- vhdlpp/vtype.h | 3 ++- vhdlpp/vtype_emit.cc | 43 ++++++++++++++++++++++++++----------------- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index 580cf92b9..0412acd66 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -215,11 +215,12 @@ class VTypeArray : public VType { int emit_def(std::ostream&out, perm_string name) const; int emit_typedef(std::ostream&out, typedef_context_t&ctx) const; - int emit_dimensions(std::ostream&out) const; bool can_be_packed() const { return etype_->can_be_packed(); } private: + int emit_with_dims_(std::ostream&out, bool packed, perm_string name) const; + void write_range_to_stream_(std::ostream&fd) const; const VType*etype_; diff --git a/vhdlpp/vtype_emit.cc b/vhdlpp/vtype_emit.cc index aa24dd362..8def8dd32 100644 --- a/vhdlpp/vtype_emit.cc +++ b/vhdlpp/vtype_emit.cc @@ -59,9 +59,7 @@ int VTypeERROR::emit_def(ostream&out, perm_string) const int VTypeArray::emit_def(ostream&out, perm_string name) const { int errors = 0; - const VType*raw_base = basic_type(); - const VTypePrimitive*base = dynamic_cast (raw_base); if (base) { @@ -74,13 +72,7 @@ int VTypeArray::emit_def(ostream&out, perm_string name) const raw_base->emit_def(out, empty_perm_string); } - if(raw_base->can_be_packed()) { - errors += emit_dimensions(out); - emit_name(out, name); - } else { - emit_name(out, name); - errors += emit_dimensions(out); - } + errors += emit_with_dims_(out, raw_base->can_be_packed(), name); return errors; } @@ -90,7 +82,7 @@ int VTypeArray::emit_typedef(std::ostream&out, typedef_context_t&ctx) const return etype_->emit_typedef(out, ctx); } -int VTypeArray::emit_dimensions(std::ostream&out) const +int VTypeArray::emit_with_dims_(std::ostream&out, bool packed, perm_string name) const { int errors = 0; @@ -102,18 +94,35 @@ int VTypeArray::emit_dimensions(std::ostream&out) const } dims.push_back(cur); + bool name_emitted = false; + while (! dims.empty()) { cur = dims.front(); dims.pop_front(); - out << "["; - if (cur->dimension(0).msb() && cur->dimension(0).lsb()) { - // bounded array, unbounded arrays have msb() & lsb() nullified - errors += cur->dimension(0).msb()->emit(out, 0, 0); - out << ":"; - errors += cur->dimension(0).lsb()->emit(out, 0, 0); + if(!packed) { + emit_name(out, name); + name_emitted = true; } - out << "]"; + + for(unsigned i = 0; i < cur->dimensions(); ++i) { + if(cur->dimension(i).is_box() && !name_emitted) { + emit_name(out, name); + name_emitted = true; + } + + out << "["; + if (!cur->dimension(i).is_box()) { // if not unbounded { + errors += cur->dimension(i).msb()->emit(out, 0, 0); + out << ":"; + errors += cur->dimension(i).lsb()->emit(out, 0, 0); + } + out << "]"; + } + } + + if(!name_emitted) { + emit_name(out, name); } return errors; From ff5b696569bab1ef5c03cc8ed8c10da4fffb26e1 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 20 Jan 2015 11:06:02 +0100 Subject: [PATCH 06/41] vhdlpp: Improved SequentialStmt visitor. --- vhdlpp/sequential.cc | 18 +++++++++--------- vhdlpp/sequential.h | 21 +++++++++++++++------ 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/vhdlpp/sequential.cc b/vhdlpp/sequential.cc index f5d4509eb..85b874a83 100644 --- a/vhdlpp/sequential.cc +++ b/vhdlpp/sequential.cc @@ -21,7 +21,7 @@ # include "expression.h" template -inline static void visit_stmt_list(std::list& stmts, void((*func))(SequentialStmt*)) +inline static void visit_stmt_list(std::list& stmts, SeqStmtVisitor& func) { for(typename std::list::iterator it = stmts.begin(); it != stmts.end(); ++it) { (*it)->visit(func); @@ -83,12 +83,12 @@ void IfSequential::extract_false(std::list&that) } } -void IfSequential::visit(void((*func))(SequentialStmt*)) +void IfSequential::visit(SeqStmtVisitor& func) { visit_stmt_list(if_, func); visit_stmt_list(elsif_, func); visit_stmt_list(else_, func); - ((*func))(this); + func(this); } IfSequential::Elsif::Elsif(Expression*cond, std::list*tr) @@ -107,7 +107,7 @@ IfSequential::Elsif::~Elsif() } } -void IfSequential::Elsif::visit(void((*func))(SequentialStmt*)) +void IfSequential::Elsif::visit(SeqStmtVisitor& func) { visit_stmt_list(if_, func); } @@ -139,10 +139,10 @@ CaseSeqStmt::~CaseSeqStmt() } } -void CaseSeqStmt::visit(void((*func))(SequentialStmt*)) +void CaseSeqStmt::visit(SeqStmtVisitor& func) { visit_stmt_list(alt_, func); - ((*func))(this); + func(this); } CaseSeqStmt::CaseStmtAlternative::CaseStmtAlternative(Expression* exp, list* stmts) @@ -161,7 +161,7 @@ CaseSeqStmt::CaseStmtAlternative::~CaseStmtAlternative() } } -void CaseSeqStmt::CaseStmtAlternative::visit(void((*func))(SequentialStmt*)) +void CaseSeqStmt::CaseStmtAlternative::visit(SeqStmtVisitor& func) { visit_stmt_list(stmts_, func); } @@ -210,10 +210,10 @@ LoopStatement::~LoopStatement() } } -void LoopStatement::visit(void((*func))(SequentialStmt*)) +void LoopStatement::visit(SeqStmtVisitor& func) { visit_stmt_list(stmts_, func); - (*func)(this); + func(this); } ForLoopStatement::ForLoopStatement(perm_string scope_name, perm_string it, prange_t* range, list* stmts) diff --git a/vhdlpp/sequential.h b/vhdlpp/sequential.h index 881c9b002..387041b70 100644 --- a/vhdlpp/sequential.h +++ b/vhdlpp/sequential.h @@ -23,10 +23,17 @@ # include "LineInfo.h" # include "parse_types.h" # include +# include class Architecture; class Entity; class Expression; +class SequentialStmt; + +struct SeqStmtVisitor { + virtual ~SeqStmtVisitor() {}; + virtual void operator() (SequentialStmt*s) = 0; +}; class SequentialStmt : public LineInfo { @@ -38,7 +45,9 @@ class SequentialStmt : public LineInfo { virtual int elaborate(Entity*ent, Architecture*arc); virtual int emit(ostream&out, Entity*entity, Architecture*arc); virtual void dump(ostream&out, int indent) const; - virtual void visit(void(*func)(SequentialStmt*)) { (*func)(this); } + + // Recursively visits a tree of sequential statements. + virtual void visit(SeqStmtVisitor& func) { func(this); } }; /* @@ -53,7 +62,7 @@ class LoopStatement : public SequentialStmt { inline perm_string loop_name() const { return name_; } void dump(ostream&out, int indent) const; - void visit(void(*func)(SequentialStmt*)); + void visit(SeqStmtVisitor& func); protected: int elaborate_substatements(Entity*ent, Architecture*arc); @@ -77,7 +86,7 @@ class IfSequential : public SequentialStmt { int statement_emit(ostream&out, Entity*entity, Architecture*arc); void dump(ostream&out, int indent) const; - void visit(void(*func)(SequentialStmt*)); + void visit(SeqStmtVisitor& func); private: Expression*cond_; @@ -97,7 +106,7 @@ class IfSequential : public SequentialStmt { int elaborate(Entity*ent, Architecture*arc); int emit(ostream&out, Entity*entity, Architecture*arc); void dump(ostream&out, int indent) const; - void visit(void(*func)(SequentialStmt*)); + void visit(SeqStmtVisitor& func); const Expression*peek_condition() const { return cond_; } @@ -155,7 +164,7 @@ class CaseSeqStmt : public SequentialStmt { int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); int elaborate(Entity*ent, Architecture*arc); int emit(ostream&out, Entity*entity, Architecture*arc); - void visit(void(*func)(SequentialStmt*)); + void visit(SeqStmtVisitor& func); private: Expression* exp_; @@ -173,7 +182,7 @@ class CaseSeqStmt : public SequentialStmt { void dump(ostream&out, int indent) const; int elaborate(Entity*ent, Architecture*arc); int emit(ostream&out, Entity*entity, Architecture*arc); - void visit(void(*func)(SequentialStmt*)); + void visit(SeqStmtVisitor& func); private: Expression* cond_; From a52242745a13e4b3e25aff381518476058a680b0 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 20 Jan 2015 13:48:15 +0100 Subject: [PATCH 07/41] ivl: Casting dynamic arrays to vectors. --- elab_expr.cc | 2 +- tgt-vvp/stmt_assign.c | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index 367093a30..5ef4eede6 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -2536,7 +2536,7 @@ unsigned PECastType::test_width(Design*des, NetScope*scope, width_mode_t&wid) expr_width_ = t->packed_width(); } - signed_flag_= t->get_signed(); + signed_flag_ = t->get_signed(); min_width_ = expr_width_; return expr_width_; } diff --git a/tgt-vvp/stmt_assign.c b/tgt-vvp/stmt_assign.c index 779104510..9e59481a4 100644 --- a/tgt-vvp/stmt_assign.c +++ b/tgt-vvp/stmt_assign.c @@ -444,7 +444,7 @@ static int show_stmt_assign_vector(ivl_statement_t net) fprintf(vvp_out, " %%cvt/vr %u;\n", wid); } else if (ivl_expr_value(rval) == IVL_VT_STRING) { - /* Special case: vector to string casting */ + /* Special case: string to vector casting */ ivl_lval_t lval = ivl_stmt_lval(net, 0); fprintf(vvp_out, " %%vpi_call %u %u \"$ivl_string_method$to_vec\", v%p_0, v%p_0 {0 0 0};\n", ivl_file_table_index(ivl_stmt_file(net)), ivl_stmt_lineno(net), @@ -452,6 +452,15 @@ static int show_stmt_assign_vector(ivl_statement_t net) if (slices) free(slices); return 0; + } else if (ivl_expr_value(rval) == IVL_VT_DARRAY) { + /* Special case: dynamic array to vector casting */ + ivl_lval_t lval = ivl_stmt_lval(net, 0); + fprintf(vvp_out, " %%vpi_call %u %u \"$ivl_darray_method$to_vec\", v%p_0, v%p_0 {0 0 0};\n", + ivl_file_table_index(ivl_stmt_file(net)), ivl_stmt_lineno(net), + ivl_expr_signal(rval), ivl_lval_sig(lval)); + if (slices) free(slices); + return 0; + } else { unsigned wid = ivl_stmt_lwidth(net); draw_eval_vec4(rval); From 8b3667f76e5a0877a5a92ea3a164829cb2401e0f Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 21 Jan 2015 10:03:20 +0100 Subject: [PATCH 08/41] ivl: Casting vectors to dynamic arrays. --- PExpr.h | 3 +++ elab_expr.cc | 33 +++++++++++++++++++++++++++++++++ tgt-vvp/eval_object.c | 9 ++++++--- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/PExpr.h b/PExpr.h index e8e07f7e4..b68a8eb24 100644 --- a/PExpr.h +++ b/PExpr.h @@ -999,6 +999,9 @@ class PECastType : public PExpr { void dump(ostream &out) const; + virtual NetExpr*elaborate_expr(Design*des, NetScope*scope, + ivl_type_t type, unsigned flags) const; + virtual NetExpr*elaborate_expr(Design*des, NetScope*scope, unsigned expr_wid, unsigned flags) const; diff --git a/elab_expr.cc b/elab_expr.cc index 5ef4eede6..d36ae1eb5 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -2541,6 +2541,39 @@ unsigned PECastType::test_width(Design*des, NetScope*scope, width_mode_t&wid) return expr_width_; } +NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope, + ivl_type_t type, unsigned) const +{ + const netdarray_t*darray = NULL; + const netvector_t*vector = NULL; + + // Casting array of vectors to dynamic array type + if((darray = dynamic_cast(type)) && + (vector = dynamic_cast(darray->element_type()))) { + PExpr::width_mode_t mode = PExpr::SIZED; + unsigned use_wid = base_->test_width(des, scope, mode); + NetExpr*base = base_->elaborate_expr(des, scope, use_wid, NO_FLAGS); + + assert(vector->packed_width() > 0); + assert(base->expr_width() > 0); + + // Find rounded up length that can fit the whole casted array of vectors + int len = base->expr_width() + vector->packed_width() - 1; + if(base->expr_width() > vector->packed_width()) { + len /= vector->packed_width(); + } else { + len /= base->expr_width(); + } + + // Number of words in the created dynamic array + NetEConst*len_expr = new NetEConst(verinum(len)); + return new NetENew(type, len_expr, base); + } + + // Fallback + return elaborate_expr(des, scope, (unsigned) 0, 0); +} + NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope, unsigned, unsigned) const { diff --git a/tgt-vvp/eval_object.c b/tgt-vvp/eval_object.c index 2ce9868c9..3c03c188d 100644 --- a/tgt-vvp/eval_object.c +++ b/tgt-vvp/eval_object.c @@ -129,12 +129,15 @@ static int eval_darray_new(ivl_expr_t ex) unsigned wid; switch (ivl_type_base(element_type)) { case IVL_VT_BOOL: + case IVL_VT_LOGIC: wid = width_of_packed_type(element_type); - draw_eval_vec4(init_expr); - resize_vec4_wid(init_expr, wid); for (idx = 0 ; idx < cnt ; idx += 1) { - fprintf(vvp_out, " %%ix/load 3, %ld, 0;\n", idx); + draw_eval_vec4(init_expr); + fprintf(vvp_out, " %%parti/%c %d, %ld, 6;\n", + ivl_expr_signed(init_expr) ? 's' : 'u', wid, idx * wid); + fprintf(vvp_out, " %%ix/load 3, %ld, 0;\n", cnt - idx - 1); fprintf(vvp_out, " %%set/dar/obj/vec4 3;\n"); + fprintf(vvp_out, " %%pop/vec4 1;\n"); } break; case IVL_VT_REAL: From 756c9ceccfff70e5a2c5066c18f8d222dd25252f Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 21 Jan 2015 16:31:14 +0100 Subject: [PATCH 09/41] ivl: Functions returning a dynamic array may be casted to vector. --- tgt-vvp/stmt_assign.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/tgt-vvp/stmt_assign.c b/tgt-vvp/stmt_assign.c index 9e59481a4..e2456ae25 100644 --- a/tgt-vvp/stmt_assign.c +++ b/tgt-vvp/stmt_assign.c @@ -455,9 +455,22 @@ static int show_stmt_assign_vector(ivl_statement_t net) } else if (ivl_expr_value(rval) == IVL_VT_DARRAY) { /* Special case: dynamic array to vector casting */ ivl_lval_t lval = ivl_stmt_lval(net, 0); + void*rval_addr = NULL; + + /* Even more special case: function call returning dynamic array */ + if(ivl_expr_type(rval) == IVL_EX_UFUNC) { + rval_addr = ivl_scope_port(ivl_expr_def(rval), 0); + draw_ufunc_object(rval); + /* We do not need to store the result, it is going to be + converted to vector quite soon. */ + fprintf(vvp_out, " %%pop/obj 1, 0; drop the result\n"); + } else { + rval_addr = ivl_expr_signal(rval); + } + fprintf(vvp_out, " %%vpi_call %u %u \"$ivl_darray_method$to_vec\", v%p_0, v%p_0 {0 0 0};\n", ivl_file_table_index(ivl_stmt_file(net)), ivl_stmt_lineno(net), - ivl_expr_signal(rval), ivl_lval_sig(lval)); + rval_addr, ivl_lval_sig(lval)); if (slices) free(slices); return 0; From 51b9191021190ccd205f4669b2881527b0faf5ef Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 22 Jan 2015 11:17:33 +0100 Subject: [PATCH 10/41] vhdlpp: Added VType::is_unbounded() method. --- vhdlpp/vtype.cc | 11 +++++++++++ vhdlpp/vtype.h | 7 +++++++ 2 files changed, 18 insertions(+) diff --git a/vhdlpp/vtype.cc b/vhdlpp/vtype.cc index a7f9233aa..652c9047e 100644 --- a/vhdlpp/vtype.cc +++ b/vhdlpp/vtype.cc @@ -148,6 +148,17 @@ void VTypeArray::show(ostream&out) const out << ""; } +bool VTypeArray::is_unbounded() const { + for(std::vector::const_iterator it = ranges_.begin(); + it != ranges_.end(); ++it) + { + if(it->is_box()) + return true; + } + + return etype_->is_unbounded(); +} + VTypeRange::VTypeRange(const VType*base, int64_t max_val, int64_t min_val) : base_(base) { diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index 0412acd66..9f761536a 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -85,6 +85,9 @@ class VType { // Determines if a type can be used in Verilog packed array. virtual bool can_be_packed() const { return false; } + // Returns true if the type has an undefined dimension. + virtual bool is_unbounded() const { return false; } + private: friend struct decl_t; // This virtual method is called to emit the declaration. This @@ -218,6 +221,8 @@ class VTypeArray : public VType { bool can_be_packed() const { return etype_->can_be_packed(); } + bool is_unbounded() const; + private: int emit_with_dims_(std::ostream&out, bool packed, perm_string name) const; @@ -320,6 +325,8 @@ class VTypeDef : public VType { int emit_def(std::ostream&out, perm_string name) const; bool can_be_packed() const { return type_->can_be_packed(); } + + bool is_unbounded() const { return type_->is_unbounded(); } private: int emit_decl(std::ostream&out, perm_string name, bool reg_flag) const; From 9b3bd039bb6aa8efe801df70e874a17a76378e1d Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 22 Jan 2015 11:26:53 +0100 Subject: [PATCH 11/41] vhdlpp: Added ExpCast class. --- vhdlpp/expression.cc | 10 ++++++++++ vhdlpp/expression.h | 21 +++++++++++++++++++++ vhdlpp/expression_debug.cc | 8 ++++++++ vhdlpp/expression_emit.cc | 10 ++++++++++ vhdlpp/expression_stream.cc | 6 ++++++ 5 files changed, 55 insertions(+) diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index feeddd88e..f0e7ee25b 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -423,3 +423,13 @@ ExpUNot::ExpUNot(Expression*op1) ExpUNot::~ExpUNot() { } + +ExpCast::ExpCast(Expression*base, const VType*type) : + base_(base), type_(type) +{ +} + +ExpCast::~ExpCast() +{ +} + diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index b791f9a21..28ab2b16f 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -674,4 +674,25 @@ class ExpUNot : public ExpUnary { void dump(ostream&out, int indent = 0) const; }; +/* + * Class that wraps other expressions to cast them to other types. + */ +class ExpCast : public Expression { + + public: + ExpCast(Expression*base, const VType*type); + ~ExpCast(); + + inline int elaborate_expr(Entity*ent, Architecture*arc, const VType*) { + return base_->elaborate_expr(ent, arc, type_); + } + void write_to_stream(std::ostream&fd); + int emit(ostream&out, Entity*ent, Architecture*arc); + void dump(ostream&out, int indent = 0) const; + + private: + Expression*base_; + const VType*type_; +}; + #endif /* IVL_expression_H */ diff --git a/vhdlpp/expression_debug.cc b/vhdlpp/expression_debug.cc index befd6ea84..da5e25385 100644 --- a/vhdlpp/expression_debug.cc +++ b/vhdlpp/expression_debug.cc @@ -68,3 +68,11 @@ void ExpConcat::dump(ostream&out, int indent) const operand1_->dump(out, indent); operand2_->dump(out, indent); } + +void ExpCast::dump(ostream&out, int indent) const +{ + out << "Casting "; + base_->dump(out, indent+4); + out << " to "; + type_->emit_def(out, empty_perm_string); +} diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index 2c1e510e5..122962868 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -860,3 +860,13 @@ int ExpUNot::emit(ostream&out, Entity*ent, Architecture*arc) out << ")"; return errors; } + +int ExpCast::emit(ostream&out, Entity*ent, Architecture*arc) +{ + int errors = 0; + errors += type_->emit_def(out, empty_perm_string); + out << "'("; + errors += base_->emit(out, ent, arc); + out << ")"; + return errors; +} diff --git a/vhdlpp/expression_stream.cc b/vhdlpp/expression_stream.cc index 103e210ae..80864265e 100644 --- a/vhdlpp/expression_stream.cc +++ b/vhdlpp/expression_stream.cc @@ -230,3 +230,9 @@ void ExpUNot::write_to_stream(ostream&fd) write_to_stream_operand1(fd); } +void ExpCast::write_to_stream(ostream&fd) +{ + // Type casting is introduced only for a few specific cases in + // SystemVerilog, so no need to use it here + base_->write_to_stream(fd); +} From b8b2f5302756d3df350d3d597565fb8019f76cb6 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 22 Jan 2015 11:32:28 +0100 Subject: [PATCH 12/41] vhdlpp: Added VType::get_generic_typename() method. --- vhdlpp/vtype.cc | 8 ++++++++ vhdlpp/vtype.h | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/vhdlpp/vtype.cc b/vhdlpp/vtype.cc index 652c9047e..ea3341ce7 100644 --- a/vhdlpp/vtype.cc +++ b/vhdlpp/vtype.cc @@ -19,6 +19,7 @@ # include "vtype.h" # include "parse_types.h" +# include "compiler.h" # include # include # include @@ -35,6 +36,13 @@ void VType::show(ostream&out) const write_to_stream(out); } +perm_string VType::get_generic_typename() const +{ + char buf[16] = {0,}; + snprintf(buf, 16, "type_%p", this); + return lex_strings.make(buf); +} + VTypePrimitive::VTypePrimitive(VTypePrimitive::type_t tt, bool packed) : type_(tt), packed_(packed) { diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index 9f761536a..5310e868a 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -88,6 +88,10 @@ class VType { // Returns true if the type has an undefined dimension. virtual bool is_unbounded() const { return false; } + // Returns a perm_string that can be used in automatically created + // typedefs (i.e. not ones defined by the user). + perm_string get_generic_typename() const; + private: friend struct decl_t; // This virtual method is called to emit the declaration. This From 839f9cd7aec62a5c2bbd79a868b8aa6e81d7e26f Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 22 Jan 2015 11:41:54 +0100 Subject: [PATCH 13/41] vhdlpp: Added ReturnStmt::cast_to() method. --- vhdlpp/sequential.cc | 7 +++++++ vhdlpp/sequential.h | 1 + 2 files changed, 8 insertions(+) diff --git a/vhdlpp/sequential.cc b/vhdlpp/sequential.cc index 85b874a83..dc6043d70 100644 --- a/vhdlpp/sequential.cc +++ b/vhdlpp/sequential.cc @@ -19,6 +19,7 @@ # include "sequential.h" # include "expression.h" +# include template inline static void visit_stmt_list(std::list& stmts, SeqStmtVisitor& func) @@ -195,6 +196,12 @@ ReturnStmt::~ReturnStmt() delete val_; } +void ReturnStmt::cast_to(const VType*type) +{ + assert(val_); + val_ = new ExpCast(val_, type); +} + LoopStatement::LoopStatement(perm_string name, list* stmts) : name_(name) { diff --git a/vhdlpp/sequential.h b/vhdlpp/sequential.h index 387041b70..6edd2321e 100644 --- a/vhdlpp/sequential.h +++ b/vhdlpp/sequential.h @@ -134,6 +134,7 @@ class ReturnStmt : public SequentialStmt { void dump(ostream&out, int indent) const; const Expression*peek_expr() const { return val_; }; + void cast_to(const VType*type); private: Expression*val_; From 777e7e0a3d5241e83ff18fdb7753ccd6d5c68caa Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 22 Jan 2015 17:04:23 +0100 Subject: [PATCH 14/41] vhdlpp: Added ExpFunc::func_ret_type() method. --- vhdlpp/expression.cc | 6 ++++++ vhdlpp/expression.h | 1 + 2 files changed, 7 insertions(+) diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index f0e7ee25b..063063772 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -20,6 +20,7 @@ */ # include "expression.h" +# include "subprogram.h" # include "parse_types.h" # include "scope.h" # include @@ -283,6 +284,11 @@ ExpFunc::~ExpFunc() delete argv_[idx]; } +const VType* ExpFunc::func_ret_type() const +{ + return def_->peek_return_type(); +} + ExpInteger::ExpInteger(int64_t val) : value_(val) { diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 28ab2b16f..b5b5f5c0a 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -477,6 +477,7 @@ class ExpFunc : public Expression { inline perm_string func_name() const { return name_; } inline size_t func_args() const { return argv_.size(); } inline const Expression*func_arg(size_t idx) const { return argv_[idx]; } + const VType*func_ret_type() const; public: // Base methods int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); From 962330f20a3b46b85bbedbbd69459e95cdb14379 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 22 Jan 2015 17:17:02 +0100 Subject: [PATCH 15/41] vhdlpp: Functions support unbounded vectors as return type and parameters. --- vhdlpp/architec_elaborate.cc | 9 ++++- vhdlpp/expression.cc | 2 +- vhdlpp/expression_elaborate.cc | 13 ++++++- vhdlpp/sequential_elaborate.cc | 8 +++- vhdlpp/subprogram.cc | 69 +++++++++++++++++++++++++++++++++- vhdlpp/subprogram.h | 15 +++++++- 6 files changed, 108 insertions(+), 8 deletions(-) diff --git a/vhdlpp/architec_elaborate.cc b/vhdlpp/architec_elaborate.cc index c255df43a..749e2a0d6 100644 --- a/vhdlpp/architec_elaborate.cc +++ b/vhdlpp/architec_elaborate.cc @@ -368,9 +368,16 @@ int SignalAssignment::elaborate(Entity*ent, Architecture*arc) return errors; } - for (list::const_iterator cur = rval_.begin() + for (list::iterator cur = rval_.begin() ; cur != rval_.end() ; ++cur) { (*cur)->elaborate_expr(ent, arc, lval_type); + + // Handle functions that return unbounded arrays + if(ExpFunc*call = dynamic_cast(*cur)) { + const VType*ret_type = call->func_ret_type(); + if(ret_type && ret_type->is_unbounded()) + *cur = new ExpCast(*cur, get_global_typedef(lval_type)); + } } return errors; diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index 063063772..019c2fb89 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -286,7 +286,7 @@ ExpFunc::~ExpFunc() const VType* ExpFunc::func_ret_type() const { - return def_->peek_return_type(); + return def_ ? def_->peek_return_type() : NULL; } ExpInteger::ExpInteger(int64_t val) diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index b07ff6994..11f43de6d 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -751,11 +751,20 @@ int ExpFunc::elaborate_expr(Entity*ent, Architecture*arc, const VType*) ivl_assert(*this, def_==0); def_ = prog; + // Elaborate arguments for (size_t idx = 0 ; idx < argv_.size() ; idx += 1) { const VType*tmp = argv_[idx]->probe_type(ent, arc); - if(!tmp && prog) - tmp = prog->peek_param_type(idx); + const VType*param_type = prog ? prog->peek_param_type(idx) : NULL; + + if(!tmp && param_type) + tmp = param_type; + errors += argv_[idx]->elaborate_expr(ent, arc, tmp); + + // Type casting for unbounded arrays + if(param_type && param_type->is_unbounded() /*&& !param_type->type_match(tmp)*/) { + argv_[idx] = new ExpCast(argv_[idx], get_global_typedef(param_type)); + } } return errors; diff --git a/vhdlpp/sequential_elaborate.cc b/vhdlpp/sequential_elaborate.cc index 184f85d56..dcfabe978 100644 --- a/vhdlpp/sequential_elaborate.cc +++ b/vhdlpp/sequential_elaborate.cc @@ -80,7 +80,6 @@ int CaseSeqStmt::CaseStmtAlternative::elaborate(Entity*ent, Architecture*arc) return errors; } - int ForLoopStatement::elaborate(Entity*ent, Architecture*arc) { int errors = 0; @@ -176,6 +175,13 @@ int VariableSeqAssignment::elaborate(Entity*ent, Architecture*arc) // Elaborate the r-value expression. errors += rval_->elaborate_expr(ent, arc, lval_type); + // Handle functions that return unbounded arrays + if(ExpFunc*call = dynamic_cast(rval_)) { + const VType*ret_type = call->func_ret_type(); + if(ret_type && ret_type->is_unbounded()) + rval_ = new ExpCast(rval_, get_global_typedef(lval_type)); + } + return errors; } diff --git a/vhdlpp/subprogram.cc b/vhdlpp/subprogram.cc index 5814bfdbf..19aa56e62 100644 --- a/vhdlpp/subprogram.cc +++ b/vhdlpp/subprogram.cc @@ -1,6 +1,8 @@ /* * Copyright (c) 2013-2014 Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) + * Copyright CERN 2015 + * @author Maciej Suminski (maciej.suminski@cern.ch) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -23,6 +25,7 @@ # include "vtype.h" # include "sequential.h" # include "ivl_assert.h" +# include "compiler.h" using namespace std; @@ -46,7 +49,71 @@ void Subprogram::set_program_body(list*stmt) { ivl_assert(*this, statements_==0); statements_ = stmt; - fix_return_type(); + fix_port_types(); +} + +// Functor used to add type casting to each return statement. +struct cast_return_type : public SeqStmtVisitor { + cast_return_type(const VType*ret_type) : ret_(ret_type) {} + + void operator() (SequentialStmt*s) + { + ReturnStmt*ret; + if((ret = dynamic_cast(s))) { + ret->cast_to(ret_); + } + } + +private: + const VType*ret_; +}; + +void Subprogram::fix_port_types() +{ + // Check function parameters for unbounded vectors and possibly fix it. + if(ports_) { + for(std::list::iterator it = ports_->begin(); + it != ports_->end(); ++it) { + check_unb_vector((*it)->type); + } + } + + // Check if the returned type is an unbounded vector. + if(check_unb_vector(return_type_)) { + if(!statements_) + return; + + // Go through the statement list and add type casting to return + // statements to comply with the modified return type. + for (std::list::iterator s = statements_->begin() + ; s != statements_->end(); ++s) { + cast_return_type r(return_type_) ; + (*s)->visit(r); + } + } + + //fix_return_type(); +} + +bool Subprogram::check_unb_vector(const VType*&type) +{ + if(const VTypeArray*arr = dynamic_cast(type)) { + if(arr->dimensions() == 1 && arr->dimension(0).is_box() ) { + // For the time being, dynamic arrays work exclusively with vectors. + // To emulate simple 'logic'/'bit' type, we need to create a vector + // of width == 1, to be used as the array element type. + // Effectively 'logic name []' becomes 'logic [0:0] name []'. + Expression*zero = new ExpInteger(0); + std::vector sub_range; + sub_range.push_back(VTypeArray::range_t(zero, zero)); + VTypeArray*new_arr = new VTypeArray(arr, sub_range); + type = get_global_typedef(new_arr); + + return true; + } + } + + return false; } bool Subprogram::compare_specification(Subprogram*that) const diff --git a/vhdlpp/subprogram.h b/vhdlpp/subprogram.h index 5b38f1223..b37fe6cd4 100644 --- a/vhdlpp/subprogram.h +++ b/vhdlpp/subprogram.h @@ -3,6 +3,8 @@ /* * Copyright (c) 2013-2014 Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) + * Copyright CERN 2015 + * @author Maciej Suminski (maciej.suminski@cern.ch) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -50,6 +52,7 @@ class Subprogram : public LineInfo, public ScopeBase { const InterfacePort*find_param(perm_string nam) const; const VType*peek_param_type(int idx) const; + const VType*peek_return_type() const { return return_type_; } int emit(ostream&out, Entity*ent, Architecture*arc); @@ -60,10 +63,18 @@ class Subprogram : public LineInfo, public ScopeBase { void dump(std::ostream&fd) const; private: - // Determines appropriate return type. Un case of std_logic_vector - // VHDL requires skipping its size in contrary to Verilog + // Determines appropriate return type, basing on the *first* return + // statement found in the function body. In case of std_logic_vector + // VHDL requires skipping its size, contrary to Verilog. void fix_return_type(void); + // Iterates through the list of function ports to fix all quirks related + // to translation between VHDL and SystemVerilog. + void fix_port_types(); + + // Creates a typedef for an unbounded vector and updates the given type. + bool check_unb_vector(const VType*&type); + perm_string name_; const ScopeBase*parent_; std::list*ports_; From c287281bbe7c11e4890d77bb1b636c914716930a Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 22 Jan 2015 18:29:43 +0100 Subject: [PATCH 16/41] vhdlpp: Tries to determine if function return type is fixed size. Added Subprogram::fixed_return_type() method. --- vhdlpp/subprogram.cc | 69 ++++++++++++++++++++++++++++++++++---------- vhdlpp/subprogram.h | 14 +++++---- 2 files changed, 62 insertions(+), 21 deletions(-) diff --git a/vhdlpp/subprogram.cc b/vhdlpp/subprogram.cc index 19aa56e62..b663a8cc7 100644 --- a/vhdlpp/subprogram.cc +++ b/vhdlpp/subprogram.cc @@ -78,6 +78,10 @@ void Subprogram::fix_port_types() } } + // Try to settle at a fixed width return type. + if(fixed_return_type()) + return; + // Check if the returned type is an unbounded vector. if(check_unb_vector(return_type_)) { if(!statements_) @@ -87,12 +91,10 @@ void Subprogram::fix_port_types() // statements to comply with the modified return type. for (std::list::iterator s = statements_->begin() ; s != statements_->end(); ++s) { - cast_return_type r(return_type_) ; + cast_return_type r(return_type_); (*s)->visit(r); } } - - //fix_return_type(); } bool Subprogram::check_unb_vector(const VType*&type) @@ -172,30 +174,65 @@ const VType*Subprogram::peek_param_type(int idx) const return (*p)->type; } -void Subprogram::fix_return_type(void) -{ - if(!statements_) - return; +struct check_return_type : public SeqStmtVisitor { + check_return_type(const Subprogram*subp) : subp_(subp), ret_type_(NULL) {} - const ReturnStmt*ret = NULL; - const VType*t = NULL; - - for (std::list::const_iterator s = statements_->begin() - ; s != statements_->end(); ++s) { - if((ret = dynamic_cast(*s))) { + void operator() (SequentialStmt*s) + { + ReturnStmt*ret; + if((ret = dynamic_cast(s))) { const Expression*expr = ret->peek_expr(); + const VType*t = NULL; if(const ExpName*n = dynamic_cast(expr)) { - if(Variable*v = find_variable(n->peek_name())) + if(Variable*v = subp_->find_variable(n->peek_name())) t = v->peek_type(); } else { t = expr->peek_type(); } - if(t) - return_type_ = t; + if(!t) { // cannot determine the type at least in one case + ret_type_ = NULL; + return; + } + + if(!ret_type_) { // this is first processed return statement + ret_type_ = t; + } else if(!t->type_match(ret_type_)) { + // the function can return different types, + // we cannot have fixed width + ret_type_ = NULL; + return; + } } } + + const VType*get_type() const { return ret_type_; } + +private: + const Subprogram*subp_; + const VType*ret_type_; +}; + +bool Subprogram::fixed_return_type(void) +{ + if(!statements_) + return false; + + check_return_type r(this); + + for (std::list::iterator s = statements_->begin() + ; s != statements_->end(); ++s) { + (*s)->visit(r); + } + + const VType*return_type = r.get_type(); + if(return_type && !return_type->is_unbounded()) { + return_type_ = return_type; + return true; + } else { + return false; + } } void Subprogram::write_to_stream(ostream&fd) const diff --git a/vhdlpp/subprogram.h b/vhdlpp/subprogram.h index b37fe6cd4..21cdaa053 100644 --- a/vhdlpp/subprogram.h +++ b/vhdlpp/subprogram.h @@ -63,13 +63,17 @@ class Subprogram : public LineInfo, public ScopeBase { void dump(std::ostream&fd) const; private: - // Determines appropriate return type, basing on the *first* return - // statement found in the function body. In case of std_logic_vector - // VHDL requires skipping its size, contrary to Verilog. - void fix_return_type(void); + // Tries to set the return type to a fixed type. VHDL functions that + // return std_logic_vectors do not specify its length, as SystemVerilog + // demands. + // The function goes through the function body looking for return + // statments and probes the returned type. If it is the same for every + // statemnt then we can assume that the function returns vector of a + // fixed size. + bool fixed_return_type(); // Iterates through the list of function ports to fix all quirks related - // to translation between VHDL and SystemVerilog. + // to translation between VHDL and SystemVerilog. void fix_port_types(); // Creates a typedef for an unbounded vector and updates the given type. From d4dd635bf6584a620c866b8362352c2c5f1e7f0b Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 23 Jan 2015 12:13:28 +0100 Subject: [PATCH 17/41] vhdlpp: Added ExpNew class. --- vhdlpp/expression.cc | 9 +++++++++ vhdlpp/expression.h | 19 +++++++++++++++++++ vhdlpp/expression_debug.cc | 6 ++++++ vhdlpp/expression_emit.cc | 9 +++++++++ 4 files changed, 43 insertions(+) diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index 019c2fb89..8127d90e4 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -439,3 +439,12 @@ ExpCast::~ExpCast() { } +ExpNew::ExpNew(Expression*size) : + size_(size) +{ +} + +ExpNew::~ExpNew() +{ + delete size_; +} diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index b5b5f5c0a..e3651ef4f 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -696,4 +696,23 @@ class ExpCast : public Expression { const VType*type_; }; +/* + * Class that handles 'new' statement. VHDL is not capable of dynamic memory + * allocation, but it is useful for emitting some cases. + */ +class ExpNew : public Expression { + + public: + ExpNew(Expression*size); + ~ExpNew(); + + // There is no 'new' in VHDL - do not emit anything + void write_to_stream(std::ostream&) {}; + int emit(ostream&out, Entity*ent, Architecture*arc); + void dump(ostream&out, int indent = 0) const; + + private: + Expression*size_; +}; + #endif /* IVL_expression_H */ diff --git a/vhdlpp/expression_debug.cc b/vhdlpp/expression_debug.cc index da5e25385..deeb3099e 100644 --- a/vhdlpp/expression_debug.cc +++ b/vhdlpp/expression_debug.cc @@ -76,3 +76,9 @@ void ExpCast::dump(ostream&out, int indent) const out << " to "; type_->emit_def(out, empty_perm_string); } + +void ExpNew::dump(ostream&out, int indent) const +{ + out << "New dynamic array size: "; + size_->dump(out, indent); +} diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index 122962868..32733913c 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -870,3 +870,12 @@ int ExpCast::emit(ostream&out, Entity*ent, Architecture*arc) out << ")"; return errors; } + +int ExpNew::emit(ostream&out, Entity*ent, Architecture*arc) +{ + int errors = 0; + out << "new["; + errors += size_->emit(out, ent, arc); + out << "]"; + return errors; +} From 56e410f386ee6b63cbc82a592a30a41fee71e615 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 23 Jan 2015 12:13:56 +0100 Subject: [PATCH 18/41] vhdlpp: SigVarBase::peek_name_() method made public. --- vhdlpp/vsignal.cc | 4 ++-- vhdlpp/vsignal.h | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/vhdlpp/vsignal.cc b/vhdlpp/vsignal.cc index e8bc87a35..14c6f9420 100644 --- a/vhdlpp/vsignal.cc +++ b/vhdlpp/vsignal.cc @@ -54,7 +54,7 @@ int Signal::emit(ostream&out, Entity*ent, Architecture*arc) type_elaborate_(decl); if (peek_refcnt_sequ_() > 0 || !peek_type()->can_be_packed()) decl.reg_flag = true; - errors += decl.emit(out, peek_name_()); + errors += decl.emit(out, peek_name()); Expression*init_expr = peek_init_expr(); if (init_expr) { @@ -73,7 +73,7 @@ int Variable::emit(ostream&out, Entity*, Architecture*) type_elaborate_(decl); if (peek_refcnt_sequ_() > 0 || !peek_type()->can_be_packed()) decl.reg_flag = true; - errors += decl.emit(out, peek_name_()); + errors += decl.emit(out, peek_name()); out << ";" << endl; return errors; } diff --git a/vhdlpp/vsignal.h b/vhdlpp/vsignal.h index 9d97e3b0f..ab560470d 100644 --- a/vhdlpp/vsignal.h +++ b/vhdlpp/vsignal.h @@ -44,8 +44,9 @@ class SigVarBase : public LineInfo { // Elaborates initializer expressions if needed. void elaborate_init_expr(Entity*ent, Architecture*arc); + perm_string peek_name() const { return name_; } + protected: - perm_string peek_name_() const { return name_; } unsigned peek_refcnt_sequ_() const { return refcnt_sequ_; } void type_elaborate_(VType::decl_t&decl); From 2ecfed0baa5c831e55959d9d334fc3a48ee2e048 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 23 Jan 2015 13:30:31 +0100 Subject: [PATCH 19/41] vhdlpp: Moved part of check_unb_vector() to fix_logic_darray(). --- vhdlpp/subprogram.cc | 19 +++++++++---------- vhdlpp/subprogram.h | 6 ++++++ 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/vhdlpp/subprogram.cc b/vhdlpp/subprogram.cc index b663a8cc7..32737c9c1 100644 --- a/vhdlpp/subprogram.cc +++ b/vhdlpp/subprogram.cc @@ -97,20 +97,19 @@ void Subprogram::fix_port_types() } } +VTypeArray*Subprogram::fix_logic_darray(const VTypeArray*type) +{ + Expression*zero = new ExpInteger(0); + std::vector sub_range; + sub_range.push_back(VTypeArray::range_t(zero, zero)); + return new VTypeArray(type, sub_range); +} + bool Subprogram::check_unb_vector(const VType*&type) { if(const VTypeArray*arr = dynamic_cast(type)) { if(arr->dimensions() == 1 && arr->dimension(0).is_box() ) { - // For the time being, dynamic arrays work exclusively with vectors. - // To emulate simple 'logic'/'bit' type, we need to create a vector - // of width == 1, to be used as the array element type. - // Effectively 'logic name []' becomes 'logic [0:0] name []'. - Expression*zero = new ExpInteger(0); - std::vector sub_range; - sub_range.push_back(VTypeArray::range_t(zero, zero)); - VTypeArray*new_arr = new VTypeArray(arr, sub_range); - type = get_global_typedef(new_arr); - + type = get_global_typedef(fix_logic_darray(arr)); return true; } } diff --git a/vhdlpp/subprogram.h b/vhdlpp/subprogram.h index 21cdaa053..fa38d504f 100644 --- a/vhdlpp/subprogram.h +++ b/vhdlpp/subprogram.h @@ -76,6 +76,12 @@ class Subprogram : public LineInfo, public ScopeBase { // to translation between VHDL and SystemVerilog. void fix_port_types(); + // For the time being, dynamic arrays work exclusively with vectors. + // To emulate dynamic array of 'logic'/'bit' type, we need to create a vector + // of width == 1, to be used as the array element type. + // Effectively 'logic name []' becomes 'logic [0:0] name []'. + VTypeArray*fix_logic_darray(const VTypeArray*type); + // Creates a typedef for an unbounded vector and updates the given type. bool check_unb_vector(const VType*&type); From 870a8262256c1c2cc91616e748177a9b5fee92ea Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 23 Jan 2015 14:14:34 +0100 Subject: [PATCH 20/41] vhdlpp: Corrected VTypeDef::emit_def() to allow typedefed names in function headers. --- vhdlpp/package_emit.cc | 3 ++- vhdlpp/vtype_emit.cc | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/vhdlpp/package_emit.cc b/vhdlpp/package_emit.cc index 94a40c8c8..f8e631c2f 100644 --- a/vhdlpp/package_emit.cc +++ b/vhdlpp/package_emit.cc @@ -49,7 +49,8 @@ int Package::emit_package(ostream&fd) const for (map::const_iterator cur = cur_types_.begin() ; cur != cur_types_.end() ; ++ cur) { fd << "typedef "; - errors += cur->second->emit_def(fd, cur->first); + errors += cur->second->emit_def(fd, + dynamic_cast(cur->second) ? empty_perm_string : cur->first); fd << " ;" << endl; } diff --git a/vhdlpp/vtype_emit.cc b/vhdlpp/vtype_emit.cc index 8def8dd32..7675568f9 100644 --- a/vhdlpp/vtype_emit.cc +++ b/vhdlpp/vtype_emit.cc @@ -209,10 +209,11 @@ int VTypeRecord::emit_def(ostream&out, perm_string name) const * type. (We are defining a variable here, not the type itself.) The * emit_typedef() method was presumably called to define type already. */ -int VTypeDef::emit_def(ostream&out, perm_string) const +int VTypeDef::emit_def(ostream&out, perm_string name) const { int errors = 0; emit_name(out, name_); + emit_name(out, name); return errors; } From 9ba7694484f6b432ac3275c9c22b21d015e52727 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 23 Jan 2015 16:47:28 +0100 Subject: [PATCH 21/41] vhdlpp: Minor assert. --- vhdlpp/expression_elaborate.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index 11f43de6d..a8f09879e 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -513,7 +513,9 @@ int ExpAggregate::elaborate_expr_record_(Entity*ent, Architecture*arc, const VTy ivl_assert(*this, field); perm_string field_name = field->peek_name(); + idx = -1; const VTypeRecord::element_t*el = ltype->element_by_name(field_name, &idx); + ivl_assert(*this, idx >= 0); aggregate_[idx] = tmp; errors += aggregate_[idx].expr->elaborate_expr(ent, arc, el->peek_type()); From 774609fbbb0401ed4a51d30c205d88b402908088 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 23 Jan 2015 17:07:19 +0100 Subject: [PATCH 22/41] vhdlpp: VTypeArray stores parent type, in case it is a subtype. --- vhdlpp/parse_misc.cc | 1 + vhdlpp/vtype.cc | 4 ++-- vhdlpp/vtype.h | 6 +++++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/vhdlpp/parse_misc.cc b/vhdlpp/parse_misc.cc index 734443d3e..f49a631c3 100644 --- a/vhdlpp/parse_misc.cc +++ b/vhdlpp/parse_misc.cc @@ -105,6 +105,7 @@ static const VType* calculate_subtype_array(const YYLTYPE&loc, const char*base_n VTypeArray*subtype = new VTypeArray(element, range, base_array->signed_vector()); + subtype->set_parent_type(base_array); return subtype; } diff --git a/vhdlpp/vtype.cc b/vhdlpp/vtype.cc index ea3341ce7..6e8ac00dd 100644 --- a/vhdlpp/vtype.cc +++ b/vhdlpp/vtype.cc @@ -77,7 +77,7 @@ void VTypePrimitive::show(ostream&out) const } VTypeArray::VTypeArray(const VType*element, const vector&r, bool sv) -: etype_(element), ranges_(r), signed_flag_(sv) +: etype_(element), ranges_(r), signed_flag_(sv), parent_(NULL) { } @@ -89,7 +89,7 @@ VTypeArray::VTypeArray(const VType*element, const vector&r, * this is a memory leak. Something to fix. */ VTypeArray::VTypeArray(const VType*element, std::list*r, bool sv) -: etype_(element), ranges_(r->size()), signed_flag_(sv) +: etype_(element), ranges_(r->size()), signed_flag_(sv), parent_(NULL) { for (size_t idx = 0 ; idx < ranges_.size() ; idx += 1) { prange_t*curp = r->front(); diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index 5310e868a..a98c81a5d 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -212,7 +212,7 @@ class VTypeArray : public VType { inline bool signed_vector() const { return signed_flag_; } // returns the type of element held in the array - inline const VType* element_type() const { return etype_; } + inline const VType* element_type() const { return parent_ ? parent_->element_type() : etype_; } // returns the basic type of element held in the array // (unfolds typedefs and multidimensional arrays) @@ -227,6 +227,9 @@ class VTypeArray : public VType { bool is_unbounded() const; + // To handle subtypes + inline void set_parent_type(const VTypeArray*parent) { parent_ = parent; } + private: int emit_with_dims_(std::ostream&out, bool packed, perm_string name) const; @@ -235,6 +238,7 @@ class VTypeArray : public VType { std::vector ranges_; bool signed_flag_; + const VTypeArray*parent_; }; class VTypeRange : public VType { From 5d26f0e28dc882ff7dda7bfbe57c501399069044 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 23 Jan 2015 17:24:00 +0100 Subject: [PATCH 23/41] vhdlpp: Added VTypeArray::is_variable_length() method. --- vhdlpp/vtype.cc | 16 ++++++++++++++++ vhdlpp/vtype.h | 6 ++++++ 2 files changed, 22 insertions(+) diff --git a/vhdlpp/vtype.cc b/vhdlpp/vtype.cc index 6e8ac00dd..795992649 100644 --- a/vhdlpp/vtype.cc +++ b/vhdlpp/vtype.cc @@ -167,6 +167,22 @@ bool VTypeArray::is_unbounded() const { return etype_->is_unbounded(); } +bool VTypeArray::is_variable_length() const { + int64_t dummy; + + for(std::vector::const_iterator it = ranges_.begin(); + it != ranges_.end(); ++it) + { + if(!it->lsb()->evaluate(NULL, dummy)) + return true; + + if(!it->msb()->evaluate(NULL, dummy)) + return true; + } + + return etype_->is_variable_length(); +} + VTypeRange::VTypeRange(const VType*base, int64_t max_val, int64_t min_val) : base_(base) { diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index a98c81a5d..e5b0fd378 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -88,6 +88,10 @@ class VType { // Returns true if the type has an undefined dimension. virtual bool is_unbounded() const { return false; } + // Checks if the variable length is dependent on other expressions, that + // cannot be evaluated (e.g. 'length, 'left, 'right). + virtual bool is_variable_length() const { return false; } + // Returns a perm_string that can be used in automatically created // typedefs (i.e. not ones defined by the user). perm_string get_generic_typename() const; @@ -227,6 +231,8 @@ class VTypeArray : public VType { bool is_unbounded() const; + bool is_variable_length() const; + // To handle subtypes inline void set_parent_type(const VTypeArray*parent) { parent_ = parent; } From 6d75af86e62b23644a096b49b3afc8e5a48af973 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 23 Jan 2015 17:24:27 +0100 Subject: [PATCH 24/41] vhdlpp: Added Subprogram::fix_variables() method. --- vhdlpp/subprogram.cc | 43 +++++++++++++++++++++++++++++++++++++++++++ vhdlpp/subprogram.h | 6 ++++++ 2 files changed, 49 insertions(+) diff --git a/vhdlpp/subprogram.cc b/vhdlpp/subprogram.cc index 32737c9c1..a3990bc69 100644 --- a/vhdlpp/subprogram.cc +++ b/vhdlpp/subprogram.cc @@ -26,6 +26,7 @@ # include "sequential.h" # include "ivl_assert.h" # include "compiler.h" +# include using namespace std; @@ -49,6 +50,7 @@ void Subprogram::set_program_body(list*stmt) { ivl_assert(*this, statements_==0); statements_ = stmt; + fix_variables(); fix_port_types(); } @@ -97,6 +99,47 @@ void Subprogram::fix_port_types() } } +void Subprogram::fix_variables() { + for(std::map::iterator it = new_variables_.begin(); it != new_variables_.end(); ++it) { + Variable*var = it->second; + const VType*type = var->peek_type(); + + // SystemVerilog does not handle variables that have length dependendent + // on other variables. We have to convert it to a dynamic array and + // construct it. + if(type->is_variable_length()) { + const VTypeArray*arr = dynamic_cast(type); + + // Currently we handle only one dimensional variables + assert(arr->dimensions() == 1); + + Expression*lsb = arr->dimension(0).lsb(); + Expression*msb = arr->dimension(0).msb(); + + // We cannot have dynamic arrays with custom range, + // it has to be [size-1:0] + int64_t lsb_val; + assert(lsb->evaluate(NULL, lsb_val) && lsb_val == 0); + //ExpArithmetic*size = new ExpArithmetic(ExpArithmetic::MINUS, msb, lsb); + // Because lsb_val == 0, we may simplify the size expression: + Expression*size = msb; + + // Prepare the construction statement + assert(statements_); + VariableSeqAssignment*init = new VariableSeqAssignment(new ExpName(var->peek_name()), + new ExpNew(size)); + statements_->push_front(init); + + // Now substitute the variable type + std::vector new_range; + new_range.push_back(VTypeArray::range_t()); + VTypeArray*new_array = new VTypeArray(arr->element_type(), new_range); + it->second = new Variable(var->peek_name(), fix_logic_darray(new_array)); + delete var; + } + } +} + VTypeArray*Subprogram::fix_logic_darray(const VTypeArray*type) { Expression*zero = new ExpInteger(0); diff --git a/vhdlpp/subprogram.h b/vhdlpp/subprogram.h index fa38d504f..8570da82e 100644 --- a/vhdlpp/subprogram.h +++ b/vhdlpp/subprogram.h @@ -76,6 +76,12 @@ class Subprogram : public LineInfo, public ScopeBase { // to translation between VHDL and SystemVerilog. void fix_port_types(); + // SystemVerilog does not allow to have signals/variables which size is + // evaluated at runtime. This function finds such variables and modifies + // their type to dynamic array and adds appropriate 'new' statement in + // the program body. + void fix_variables(); + // For the time being, dynamic arrays work exclusively with vectors. // To emulate dynamic array of 'logic'/'bit' type, we need to create a vector // of width == 1, to be used as the array element type. From 621cf373395042b88b0580caa64ad5481227cc49 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 26 Jan 2015 11:14:31 +0100 Subject: [PATCH 25/41] vhdlpp: Added ScopeBase::find_param() method. --- vhdlpp/scope.cc | 18 ++++++++++++++++++ vhdlpp/scope.h | 1 + 2 files changed, 19 insertions(+) diff --git a/vhdlpp/scope.cc b/vhdlpp/scope.cc index 5182aee1a..eac3ece1e 100644 --- a/vhdlpp/scope.cc +++ b/vhdlpp/scope.cc @@ -21,6 +21,7 @@ # include "scope.h" # include "package.h" # include "subprogram.h" +# include "entity.h" # include # include # include @@ -148,6 +149,23 @@ Variable* ScopeBase::find_variable(perm_string by_name) const } } +const InterfacePort* ScopeBase::find_param(perm_string by_name) const +{ + for(map::const_iterator it = use_subprograms_.begin(); + it != use_subprograms_.end(); ++it) { + if(const InterfacePort*port = it->second->find_param(by_name)) + return port; + } + + for(map::const_iterator it = cur_subprograms_.begin(); + it != cur_subprograms_.end(); ++it) { + if(const InterfacePort*port = it->second->find_param(by_name)) + return port; + } + + return NULL; +} + Subprogram* ScopeBase::find_subprogram(perm_string name) const { map::const_iterator cur; diff --git a/vhdlpp/scope.h b/vhdlpp/scope.h index 2b0fdc5b3..8fd94b73e 100644 --- a/vhdlpp/scope.h +++ b/vhdlpp/scope.h @@ -56,6 +56,7 @@ class ScopeBase { bool find_constant(perm_string by_name, const VType*&typ, Expression*&exp); Signal* find_signal(perm_string by_name) const; Variable* find_variable(perm_string by_name) const; + virtual const InterfacePort* find_param(perm_string by_name) const; Subprogram* find_subprogram(perm_string by_name) const; // Moves all signals, variables and components from another scope to // this one. After the transfer new_* maps are emptied in the another scope. From 90293d8e0a9f675cf9b80455bd7e082e1e13a4da Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 26 Jan 2015 11:15:57 +0100 Subject: [PATCH 26/41] vhdlpp: VTypeArray::is_variable_length() uses ScopeBase to determine if variable has constant length. --- vhdlpp/subprogram.cc | 2 +- vhdlpp/vtype.cc | 11 +++++++---- vhdlpp/vtype.h | 5 +++-- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/vhdlpp/subprogram.cc b/vhdlpp/subprogram.cc index a3990bc69..bfa1be9a7 100644 --- a/vhdlpp/subprogram.cc +++ b/vhdlpp/subprogram.cc @@ -107,7 +107,7 @@ void Subprogram::fix_variables() { // SystemVerilog does not handle variables that have length dependendent // on other variables. We have to convert it to a dynamic array and // construct it. - if(type->is_variable_length()) { + if(type->is_variable_length(this)) { const VTypeArray*arr = dynamic_cast(type); // Currently we handle only one dimensional variables diff --git a/vhdlpp/vtype.cc b/vhdlpp/vtype.cc index 795992649..cd4ea42e1 100644 --- a/vhdlpp/vtype.cc +++ b/vhdlpp/vtype.cc @@ -167,20 +167,23 @@ bool VTypeArray::is_unbounded() const { return etype_->is_unbounded(); } -bool VTypeArray::is_variable_length() const { +bool VTypeArray::is_variable_length(ScopeBase*scope) const { int64_t dummy; + if(is_unbounded()) + return true; + for(std::vector::const_iterator it = ranges_.begin(); it != ranges_.end(); ++it) { - if(!it->lsb()->evaluate(NULL, dummy)) + if(!it->lsb()->evaluate(scope, dummy)) return true; - if(!it->msb()->evaluate(NULL, dummy)) + if(!it->msb()->evaluate(scope, dummy)) return true; } - return etype_->is_variable_length(); + return etype_->is_variable_length(scope); } VTypeRange::VTypeRange(const VType*base, int64_t max_val, int64_t min_val) diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index e5b0fd378..eb6c10553 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -34,6 +34,7 @@ class Entity; class Expression; class prange_t; class VTypeDef; +class ScopeBase; typedef enum typedef_topo_e { NONE=0, PENDING, MARKED } typedef_topo_t; typedef std::map typedef_context_t; @@ -90,7 +91,7 @@ class VType { // Checks if the variable length is dependent on other expressions, that // cannot be evaluated (e.g. 'length, 'left, 'right). - virtual bool is_variable_length() const { return false; } + virtual bool is_variable_length(ScopeBase*) const { return false; } // Returns a perm_string that can be used in automatically created // typedefs (i.e. not ones defined by the user). @@ -231,7 +232,7 @@ class VTypeArray : public VType { bool is_unbounded() const; - bool is_variable_length() const; + bool is_variable_length(ScopeBase*scope) const; // To handle subtypes inline void set_parent_type(const VTypeArray*parent) { parent_ = parent; } From 25c379824822aaeca3951250929e8df2476f0150 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 26 Jan 2015 15:00:51 +0100 Subject: [PATCH 27/41] vhdlpp: Elaborate and emit functions work with ScopeBase instead of Architecture. --- vhdlpp/expression.h | 167 +++++++++++----------- vhdlpp/expression_elaborate.cc | 252 +++++++++++++++++---------------- vhdlpp/expression_emit.cc | 185 ++++++++++++------------ vhdlpp/expression_evaluate.cc | 22 +-- vhdlpp/sequential.h | 58 ++++---- vhdlpp/sequential_elaborate.cc | 62 ++++---- vhdlpp/sequential_emit.cc | 88 ++++++------ vhdlpp/subprogram.h | 2 +- vhdlpp/subprogram_emit.cc | 2 +- vhdlpp/vsignal.cc | 10 +- vhdlpp/vsignal.h | 7 +- vhdlpp/vtype.h | 5 +- vhdlpp/vtype_elaborate.cc | 10 +- 13 files changed, 439 insertions(+), 431 deletions(-) diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index e3651ef4f..6f2d2b4fe 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -31,7 +31,6 @@ class prange_t; class Entity; -class Architecture; class ScopeBase; class Subprogram; class VType; @@ -56,13 +55,13 @@ class Expression : public LineInfo { // assignment. This generates an error for most cases, but // expressions that are valid l-values return 0 and set any // flags needed to indicate their status as writable variables. - virtual int elaborate_lval(Entity*ent, Architecture*arc, + virtual int elaborate_lval(Entity*ent, ScopeBase*scope, bool is_sequ); // This virtual method probes the expression to get the most // constrained type for the expression. For a given instance, // this may be called before the elaborate_expr method. - virtual const VType*probe_type(Entity*ent, Architecture*arc) const; + virtual const VType*probe_type(Entity*ent, ScopeBase*scope) const; // The fit_type virtual method is used by the ExpConcat class // to probe the type of operands. The atype argument is the @@ -70,13 +69,13 @@ class Expression : public LineInfo { // returns its type as interpreted in this context. Really, // this is mostly about helping aggregate expressions within // concatenations to figure out their type. - virtual const VType*fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const; + virtual const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const; // This virtual method elaborates an expression. The ltype is // the type of the lvalue expression, if known, and can be // used to calculate the type for the expression being // elaborated. - virtual int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); + virtual int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); // Return the type that this expression would be if it were an // l-value. This should only be called after elaborate_lval is @@ -91,7 +90,7 @@ class Expression : public LineInfo { // The emit virtual method is called by architecture emit to // output the generated code for the expression. The derived // class fills in the details of what exactly happened. - virtual int emit(ostream&out, Entity*ent, Architecture*arc) =0; + virtual int emit(ostream&out, Entity*ent, ScopeBase*scope) =0; // The emit_package virtual message is similar, but is called // in a package context and to emit SV packages. @@ -102,7 +101,7 @@ class Expression : public LineInfo { // argument if the evaluation works, or return false if it // cannot be done. virtual bool evaluate(ScopeBase*scope, int64_t&val) const; - virtual bool evaluate(Entity*ent, Architecture*arc, int64_t&val) const; + virtual bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const; // The symbolic compare returns true if the two expressions @@ -150,13 +149,13 @@ class ExpUnary : public Expression { ExpUnary(Expression*op1); virtual ~ExpUnary() =0; - const VType*fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const; + const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const; protected: inline void write_to_stream_operand1(std::ostream&fd) { operand1_->write_to_stream(fd); } - int emit_operand1(ostream&out, Entity*ent, Architecture*arc); + int emit_operand1(ostream&out, Entity*ent, ScopeBase*scope); void dump_operand1(ostream&out, int indent = 0) const; private: @@ -176,13 +175,13 @@ class ExpBinary : public Expression { const Expression* peek_operand1(void) const { return operand1_; } const Expression* peek_operand2(void) const { return operand2_; } - const VType*probe_type(Entity*ent, Architecture*arc) const; + const VType*probe_type(Entity*ent, ScopeBase*scope) const; protected: - int elaborate_exprs(Entity*, Architecture*, const VType*); - int emit_operand1(ostream&out, Entity*ent, Architecture*arc); - int emit_operand2(ostream&out, Entity*ent, Architecture*arc); + int elaborate_exprs(Entity*, ScopeBase*, const VType*); + int emit_operand1(ostream&out, Entity*ent, ScopeBase*scope); + int emit_operand2(ostream&out, Entity*ent, ScopeBase*scope); bool eval_operand1(ScopeBase*scope, int64_t&val) const; bool eval_operand2(ScopeBase*scope, int64_t&val) const; @@ -274,18 +273,18 @@ class ExpAggregate : public Expression { ~ExpAggregate(); - const VType*probe_type(Entity*ent, Architecture*arc) const; - const VType*fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const; - int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); + const VType*probe_type(Entity*ent, ScopeBase*scope) const; + const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const; + int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); void write_to_stream(std::ostream&fd); - int emit(ostream&out, Entity*ent, Architecture*arc); + int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; private: - int elaborate_expr_array_(Entity*ent, Architecture*arc, const VTypeArray*ltype); - int elaborate_expr_record_(Entity*ent, Architecture*arc, const VTypeRecord*ltype); - int emit_array_(ostream&out, Entity*ent, Architecture*arc, const VTypeArray*ltype); - int emit_record_(ostream&out, Entity*ent, Architecture*arc, const VTypeRecord*ltype); + int elaborate_expr_array_(Entity*ent, ScopeBase*scope, const VTypeArray*ltype); + int elaborate_expr_record_(Entity*ent, ScopeBase*scope, const VTypeRecord*ltype); + int emit_array_(ostream&out, Entity*ent, ScopeBase*scope, const VTypeArray*ltype); + int emit_record_(ostream&out, Entity*ent, ScopeBase*scope, const VTypeRecord*ltype); private: // This is the elements as directly parsed. @@ -305,9 +304,9 @@ class ExpArithmetic : public ExpBinary { ExpArithmetic(ExpArithmetic::fun_t op, Expression*op1, Expression*op2); ~ExpArithmetic(); - int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); + int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); void write_to_stream(std::ostream&fd); - int emit(ostream&out, Entity*ent, Architecture*arc); + int emit(ostream&out, Entity*ent, ScopeBase*scope); virtual bool evaluate(ScopeBase*scope, int64_t&val) const; void dump(ostream&out, int indent = 0) const; @@ -327,13 +326,13 @@ class ExpAttribute : public Expression { inline perm_string peek_attribute() const { return name_; } inline const ExpName* peek_base() const { return base_; } - const VType*probe_type(Entity*ent, Architecture*arc) const; - int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); + const VType*probe_type(Entity*ent, ScopeBase*scope) const; + int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); void write_to_stream(std::ostream&fd); - int emit(ostream&out, Entity*ent, Architecture*arc); + int emit(ostream&out, Entity*ent, ScopeBase*scope); // Some attributes can be evaluated at compile time bool evaluate(ScopeBase*scope, int64_t&val) const; - bool evaluate(Entity*ent, Architecture*arc, int64_t&val) const; + bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const; void dump(ostream&out, int indent = 0) const; private: @@ -347,10 +346,10 @@ class ExpBitstring : public Expression { explicit ExpBitstring(const char*); ~ExpBitstring(); - const VType*fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const; - int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); + const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const; + int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); void write_to_stream(std::ostream&fd); - int emit(ostream&out, Entity*ent, Architecture*arc); + int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; private: @@ -364,17 +363,17 @@ class ExpCharacter : public Expression { ExpCharacter(char val); ~ExpCharacter(); - const VType*fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const; - int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); + const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const; + int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); void write_to_stream(std::ostream&fd); - int emit(ostream&out, Entity*ent, Architecture*arc); + int emit(ostream&out, Entity*ent, ScopeBase*scope); bool is_primary(void) const; void dump(ostream&out, int indent = 0) const; char value() const { return value_; } private: - int emit_primitive_bit_(ostream&out, Entity*ent, Architecture*arc, + int emit_primitive_bit_(ostream&out, Entity*ent, ScopeBase*scope, const VTypePrimitive*etype); private: @@ -387,17 +386,17 @@ class ExpConcat : public Expression { ExpConcat(Expression*op1, Expression*op2); ~ExpConcat(); - const VType*probe_type(Entity*ent, Architecture*arc) const; - const VType*fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const; - int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); + const VType*probe_type(Entity*ent, ScopeBase*scope) const; + const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const; + int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); void write_to_stream(std::ostream&fd); - int emit(ostream&out, Entity*ent, Architecture*arc); + int emit(ostream&out, Entity*ent, ScopeBase*scope); virtual bool evaluate(ScopeBase*scope, int64_t&val) const; bool is_primary(void) const; void dump(ostream&out, int indent = 0) const; private: - int elaborate_expr_array_(Entity*ent, Architecture*arc, const VTypeArray*ltype); + int elaborate_expr_array_(Entity*ent, ScopeBase*scope, const VTypeArray*ltype); private: Expression*operand1_; @@ -417,9 +416,9 @@ class ExpConditional : public Expression { else_t(Expression*cond, std::list*tru); ~else_t(); - int elaborate_expr(Entity*ent, Architecture*arc, const VType*lt); - int emit_when_else(ostream&out, Entity*ent, Architecture*arc); - int emit_else(ostream&out, Entity*ent, Architecture*arc); + int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*lt); + int emit_when_else(ostream&out, Entity*ent, ScopeBase*scope); + int emit_else(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; private: @@ -432,10 +431,10 @@ class ExpConditional : public Expression { std::list*fal); ~ExpConditional(); - const VType*probe_type(Entity*ent, Architecture*arc) const; - int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); + const VType*probe_type(Entity*ent, ScopeBase*scope) const; + int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); void write_to_stream(std::ostream&fd); - int emit(ostream&out, Entity*ent, Architecture*arc); + int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; private: @@ -460,7 +459,7 @@ class ExpEdge : public ExpUnary { inline fun_t edge_fun() const { return fun_; } void write_to_stream(std::ostream&fd); - int emit(ostream&out, Entity*ent, Architecture*arc); + int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; private: @@ -480,9 +479,9 @@ class ExpFunc : public Expression { const VType*func_ret_type() const; public: // Base methods - int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); + int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); void write_to_stream(std::ostream&fd); - int emit(ostream&out, Entity*ent, Architecture*arc); + int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; private: @@ -497,10 +496,10 @@ class ExpInteger : public Expression { ExpInteger(int64_t val); ~ExpInteger(); - const VType*probe_type(Entity*ent, Architecture*arc) const; - int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); + const VType*probe_type(Entity*ent, ScopeBase*scope) const; + int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); void write_to_stream(std::ostream&fd); - int emit(ostream&out, Entity*ent, Architecture*arc); + int emit(ostream&out, Entity*ent, ScopeBase*scope); int emit_package(std::ostream&out); bool is_primary(void) const; bool evaluate(ScopeBase*scope, int64_t&val) const; @@ -517,10 +516,10 @@ class ExpReal : public Expression { ExpReal(double val); ~ExpReal(); - const VType*probe_type(Entity*ent, Architecture*arc) const; - int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); + const VType*probe_type(Entity*ent, ScopeBase*scope) const; + int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); void write_to_stream(std::ostream&fd); - int emit(ostream&out, Entity*ent, Architecture*arc); + int emit(ostream&out, Entity*ent, ScopeBase*scope); int emit_package(std::ostream&out); bool is_primary(void) const; void dump(ostream&out, int indent = 0) const; @@ -541,9 +540,9 @@ class ExpLogical : public ExpBinary { inline fun_t logic_fun() const { return fun_; } - int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); + int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); void write_to_stream(std::ostream&fd); - int emit(ostream&out, Entity*ent, Architecture*arc); + int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; private: @@ -566,16 +565,16 @@ class ExpName : public Expression { ~ExpName(); public: // Base methods - int elaborate_lval(Entity*ent, Architecture*arc, bool); - int elaborate_rval(Entity*ent, Architecture*arc, const InterfacePort*); - const VType* probe_type(Entity*ent, Architecture*arc) const; - const VType* fit_type(Entity*ent, Architecture*arc, const VTypeArray*host) const; - int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); + int elaborate_lval(Entity*ent, ScopeBase*scope, bool); + int elaborate_rval(Entity*ent, ScopeBase*scope, const InterfacePort*); + const VType* probe_type(Entity*ent, ScopeBase*scope) const; + const VType* fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*host) const; + int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); void write_to_stream(std::ostream&fd); - int emit(ostream&out, Entity*ent, Architecture*arc); + int emit(ostream&out, Entity*ent, ScopeBase*scope); bool is_primary(void) const; bool evaluate(ScopeBase*scope, int64_t&val) const; - bool evaluate(Entity*ent, Architecture*arc, int64_t&val) const; + bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const; bool symbolic_compare(const Expression*that) const; void dump(ostream&out, int indent = 0) const; const char* name() const; @@ -584,13 +583,13 @@ class ExpName : public Expression { void set_range(Expression*msb, Expression*lsb); private: - const VType* elaborate_adjust_type_with_range_(Entity*ent, Architecture*arc, const VType*type); + const VType* elaborate_adjust_type_with_range_(Entity*ent, ScopeBase*scope, 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; + int elaborate_lval_(Entity*ent, ScopeBase*scope, bool, ExpName*suffix); + const VType* probe_prefix_type_(Entity*ent, ScopeBase*scope) const; + const VType* probe_prefixed_type_(Entity*ent, ScopeBase*scope) const; - int emit_as_prefix_(ostream&out, Entity*ent, Architecture*arc); + int emit_as_prefix_(ostream&out, Entity*ent, ScopeBase*scope); private: std::auto_ptr prefix_; @@ -605,8 +604,8 @@ class ExpNameALL : public ExpName { ExpNameALL() : ExpName(perm_string()) { } public: - int elaborate_lval(Entity*ent, Architecture*arc, bool); - const VType* probe_type(Entity*ent, Architecture*arc) const; + int elaborate_lval(Entity*ent, ScopeBase*scope, bool); + const VType* probe_type(Entity*ent, ScopeBase*scope) const; void dump(ostream&out, int indent =0) const; }; @@ -621,10 +620,10 @@ class ExpRelation : public ExpBinary { ExpRelation(ExpRelation::fun_t ty, Expression*op1, Expression*op2); ~ExpRelation(); - const VType* probe_type(Entity*ent, Architecture*arc) const; - int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); + const VType* probe_type(Entity*ent, ScopeBase*scope) const; + int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); void write_to_stream(std::ostream&fd); - int emit(ostream&out, Entity*ent, Architecture*arc); + int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; private: @@ -637,16 +636,16 @@ class ExpString : public Expression { explicit ExpString(const char*); ~ExpString(); - const VType*fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const; - int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); + const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const; + int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); void write_to_stream(std::ostream&fd); - int emit(ostream&out, Entity*ent, Architecture*arc); + int emit(ostream&out, Entity*ent, ScopeBase*scope); bool is_primary(void) const; void dump(ostream&out, int indent = 0) const; const std::vector& get_value() const { return value_; } private: - int emit_as_array_(ostream&out, Entity*ent, Architecture*arc, const VTypeArray*arr); + int emit_as_array_(ostream&out, Entity*ent, ScopeBase*scope, const VTypeArray*arr); private: std::vector value_; @@ -659,7 +658,7 @@ class ExpUAbs : public ExpUnary { ~ExpUAbs(); void write_to_stream(std::ostream&fd); - int emit(ostream&out, Entity*ent, Architecture*arc); + int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; }; @@ -669,9 +668,9 @@ class ExpUNot : public ExpUnary { ExpUNot(Expression*op1); ~ExpUNot(); - int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); + int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); void write_to_stream(std::ostream&fd); - int emit(ostream&out, Entity*ent, Architecture*arc); + int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; }; @@ -684,11 +683,11 @@ class ExpCast : public Expression { ExpCast(Expression*base, const VType*type); ~ExpCast(); - inline int elaborate_expr(Entity*ent, Architecture*arc, const VType*) { - return base_->elaborate_expr(ent, arc, type_); + inline int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*) { + return base_->elaborate_expr(ent, scope, type_); } void write_to_stream(std::ostream&fd); - int emit(ostream&out, Entity*ent, Architecture*arc); + int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; private: @@ -708,7 +707,7 @@ class ExpNew : public Expression { // There is no 'new' in VHDL - do not emit anything void write_to_stream(std::ostream&) {}; - int emit(ostream&out, Entity*ent, Architecture*arc); + int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; private: diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index a8f09879e..70fedaca4 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -33,20 +33,20 @@ using namespace std; -int Expression::elaborate_lval(Entity*, Architecture*, bool) +int Expression::elaborate_lval(Entity*, ScopeBase*, bool) { cerr << get_fileline() << ": error: Expression is not a valid l-value." << endl; return 1; } -const VType* Expression::probe_type(Entity*, Architecture*) const +const VType* Expression::probe_type(Entity*, ScopeBase*) const { return 0; } -const VType* Expression::fit_type(Entity*ent, Architecture*arc, const VTypeArray*) const +const VType* Expression::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*) const { - const VType*res = probe_type(ent,arc); + const VType*res = probe_type(ent,scope); if (res == 0) { cerr << get_fileline() << ": internal error: " << "fit_type for " << typeid(*this).name() @@ -56,7 +56,7 @@ const VType* Expression::fit_type(Entity*ent, Architecture*arc, const VTypeArray return res; } -const VType*ExpName::elaborate_adjust_type_with_range_(Entity*, Architecture*arc, const VType*type) +const VType*ExpName::elaborate_adjust_type_with_range_(Entity*, ScopeBase*scope, const VType*type) { // Unfold typedefs while (const VTypeDef*tdef = dynamic_cast(type)) { @@ -75,9 +75,9 @@ const VType*ExpName::elaborate_adjust_type_with_range_(Entity*, Architecture*arc int64_t use_msb, use_lsb; bool flag; - flag = index_->evaluate(arc, use_msb); + flag = index_->evaluate(scope, use_msb); ivl_assert(*this, flag); - flag = lsb_->evaluate(arc, use_lsb); + flag = lsb_->evaluate(scope, use_lsb); ivl_assert(*this, flag); Expression*exp_msb = new ExpInteger(use_msb); @@ -91,7 +91,7 @@ const VType*ExpName::elaborate_adjust_type_with_range_(Entity*, Architecture*arc return type; } -int ExpName::elaborate_lval_(Entity*ent, Architecture*arc, bool is_sequ, ExpName*suffix) +int ExpName::elaborate_lval_(Entity*ent, ScopeBase*scope, bool is_sequ, ExpName*suffix) { int errors = 0; @@ -134,13 +134,13 @@ int ExpName::elaborate_lval_(Entity*ent, Architecture*arc, bool is_sequ, ExpName << ent->get_name() << "." << endl; return errors + 1; - } else if (Signal*sig = arc->find_signal(name_)) { + } else if (Signal*sig = scope->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_)) { + } else if (Variable*var = scope->find_variable(name_)) { // Tell the target signal that this may be a sequential l-value. if (is_sequ) var->count_ref_sequ(); @@ -201,7 +201,7 @@ int ExpName::elaborate_lval_(Entity*ent, Architecture*arc, bool is_sequ, ExpName return errors; } - suffix_type = suffix->elaborate_adjust_type_with_range_(ent, arc, suffix_type); + suffix_type = suffix->elaborate_adjust_type_with_range_(ent, scope, suffix_type); ivl_assert(*this, suffix_type); suffix->set_type(suffix_type); @@ -209,12 +209,12 @@ int ExpName::elaborate_lval_(Entity*ent, Architecture*arc, bool is_sequ, ExpName return errors; } -int ExpName::elaborate_lval(Entity*ent, Architecture*arc, bool is_sequ) +int ExpName::elaborate_lval(Entity*ent, ScopeBase*scope, bool is_sequ) { int errors = 0; if (prefix_.get()) { - return prefix_->elaborate_lval_(ent, arc, is_sequ, this); + return prefix_->elaborate_lval_(ent, scope, is_sequ, this); } const VType*found_type = 0; @@ -238,13 +238,13 @@ int ExpName::elaborate_lval(Entity*ent, Architecture*arc, bool is_sequ) << ent->get_name() << "." << endl; return 1; - } else if (Signal*sig = arc->find_signal(name_)) { + } else if (Signal*sig = scope->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_)) { + } else if (Variable*var = scope->find_variable(name_)) { // Tell the target signal that this may be a sequential l-value. if (is_sequ) var->count_ref_sequ(); @@ -257,13 +257,13 @@ int ExpName::elaborate_lval(Entity*ent, Architecture*arc, bool is_sequ) return errors + 1; } - found_type = elaborate_adjust_type_with_range_(ent, arc, found_type); + found_type = elaborate_adjust_type_with_range_(ent, scope, found_type); set_type(found_type); return errors; } -int ExpName::elaborate_rval(Entity*ent, Architecture*arc, const InterfacePort*lval) +int ExpName::elaborate_rval(Entity*ent, ScopeBase*scope, const InterfacePort*lval) { int errors = 0; @@ -295,7 +295,7 @@ int ExpName::elaborate_rval(Entity*ent, Architecture*arc, const InterfacePort*lv default: break; } - } else if (arc->find_signal(name_)) { + } else if (scope->find_signal(name_)) { /* OK */ } else if (ent->find_generic(name_)) { @@ -310,21 +310,21 @@ int ExpName::elaborate_rval(Entity*ent, Architecture*arc, const InterfacePort*lv return errors; } -int ExpNameALL::elaborate_lval(Entity*ent, Architecture*arc, bool is_sequ) +int ExpNameALL::elaborate_lval(Entity*ent, ScopeBase*scope, bool is_sequ) { - return Expression::elaborate_lval(ent, arc, is_sequ); + return Expression::elaborate_lval(ent, scope, is_sequ); } -int Expression::elaborate_expr(Entity*, Architecture*, const VType*) +int Expression::elaborate_expr(Entity*, ScopeBase*, const VType*) { cerr << get_fileline() << ": internal error: I don't know how to elaborate expression type=" << typeid(*this).name() << endl; return 1; } -const VType* ExpBinary::probe_type(Entity*ent, Architecture*arc) const +const VType* ExpBinary::probe_type(Entity*ent, ScopeBase*scope) const { - const VType*t1 = operand1_->probe_type(ent, arc); - const VType*t2 = operand2_->probe_type(ent, arc); + const VType*t1 = operand1_->probe_type(ent, scope); + const VType*t2 = operand2_->probe_type(ent, scope); if (t1 == 0) return t2; @@ -351,12 +351,12 @@ const VType*ExpBinary::resolve_operand_types_(const VType*, const VType*) const return 0; } -int ExpBinary::elaborate_exprs(Entity*ent, Architecture*arc, const VType*ltype) +int ExpBinary::elaborate_exprs(Entity*ent, ScopeBase*scope, const VType*ltype) { int errors = 0; - errors += operand1_->elaborate_expr(ent, arc, ltype); - errors += operand2_->elaborate_expr(ent, arc, ltype); + errors += operand1_->elaborate_expr(ent, scope, ltype); + errors += operand2_->elaborate_expr(ent, scope, ltype); return errors; } @@ -365,17 +365,17 @@ int ExpBinary::elaborate_exprs(Entity*ent, Architecture*arc, const VType*ltype) * return the fit_type for the operand. The assumption is that the * operator doesn't change the type. */ -const VType*ExpUnary::fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const +const VType*ExpUnary::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const { - return operand1_->fit_type(ent, arc, atype); + return operand1_->fit_type(ent, scope, atype); } -const VType*ExpAggregate::probe_type(Entity*ent, Architecture*arc) const +const VType*ExpAggregate::probe_type(Entity*ent, ScopeBase*scope) const { - return Expression::probe_type(ent, arc); + return Expression::probe_type(ent, scope); } -const VType*ExpAggregate::fit_type(Entity*, Architecture*, const VTypeArray*host) const +const VType*ExpAggregate::fit_type(Entity*, ScopeBase*, const VTypeArray*host) const { ivl_assert(*this, elements_.size() == 1); size_t choice_count = elements_[0]->count_choices(); @@ -401,7 +401,7 @@ const VType*ExpAggregate::fit_type(Entity*, Architecture*, const VTypeArray*host return res; } -int ExpAggregate::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype) +int ExpAggregate::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype) { if (ltype == 0) { cerr << get_fileline() << ": error: Elaboration of aggregate types needs well known type context?" << endl; @@ -415,10 +415,10 @@ int ExpAggregate::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype } if (const VTypeArray*larray = dynamic_cast(ltype)) { - return elaborate_expr_array_(ent, arc, larray); + return elaborate_expr_array_(ent, scope, larray); } else if(const VTypeRecord*lrecord = dynamic_cast(ltype)) { - return elaborate_expr_record_(ent, arc, lrecord); + return elaborate_expr_record_(ent, scope, lrecord); } cerr << get_fileline() << ": internal error: I don't know how to elaborate aggregate expressions. type=" << typeid(*ltype).name() << endl; @@ -430,7 +430,7 @@ int ExpAggregate::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype * expressions (the elements_ member) using the element type as the * ltype for the subexpression. */ -int ExpAggregate::elaborate_expr_array_(Entity*ent, Architecture*arc, const VTypeArray*ltype) +int ExpAggregate::elaborate_expr_array_(Entity*ent, ScopeBase*scope, const VTypeArray*ltype) { const VType*element_type = ltype->element_type(); int errors = 0; @@ -476,7 +476,7 @@ int ExpAggregate::elaborate_expr_array_(Entity*ent, Architecture*arc, const VTyp if (aggregate_[idx].alias_flag) continue; - errors += aggregate_[idx].expr->elaborate_expr(ent, arc, element_type); + errors += aggregate_[idx].expr->elaborate_expr(ent, scope, element_type); } // done with the obsolete elements_ vector. @@ -485,7 +485,7 @@ int ExpAggregate::elaborate_expr_array_(Entity*ent, Architecture*arc, const VTyp return errors; } -int ExpAggregate::elaborate_expr_record_(Entity*ent, Architecture*arc, const VTypeRecord*ltype) +int ExpAggregate::elaborate_expr_record_(Entity*ent, ScopeBase*scope, const VTypeRecord*ltype) { int errors = 0; @@ -518,7 +518,7 @@ int ExpAggregate::elaborate_expr_record_(Entity*ent, Architecture*arc, const VTy ivl_assert(*this, idx >= 0); aggregate_[idx] = tmp; - errors += aggregate_[idx].expr->elaborate_expr(ent, arc, el->peek_type()); + errors += aggregate_[idx].expr->elaborate_expr(ent, scope, el->peek_type()); } // done with the obsolete elements_ vector. @@ -537,16 +537,16 @@ void ExpAggregate::element_t::map_choices(ExpAggregate::choice_element*dst) } } -int ExpArithmetic::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype) +int ExpArithmetic::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype) { int errors = 0; if (ltype == 0) { - ltype = probe_type(ent, arc); + ltype = probe_type(ent, scope); } ivl_assert(*this, ltype != 0); - errors += elaborate_exprs(ent, arc, ltype); + errors += elaborate_exprs(ent, scope, ltype); return errors; } @@ -565,9 +565,9 @@ const VType* ExpArithmetic::resolve_operand_types_(const VType*t1, const VType*t return 0; } -const VType* ExpAttribute::probe_type(Entity*ent, Architecture*arc) const +const VType* ExpAttribute::probe_type(Entity*ent, ScopeBase*scope) const { - base_->probe_type(ent, arc); + base_->probe_type(ent, scope); if (name_ == "length" || name_ == "left" || name_ == "right") { return &primitive_INTEGER; @@ -576,42 +576,42 @@ const VType* ExpAttribute::probe_type(Entity*ent, Architecture*arc) const return 0; } -int ExpAttribute::elaborate_expr(Entity*ent, Architecture*arc, const VType*) +int ExpAttribute::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*) { int errors = 0; - const VType*sub_type = base_->probe_type(ent, arc); - errors += base_->elaborate_expr(ent, arc, sub_type); + const VType*sub_type = base_->probe_type(ent, scope); + errors += base_->elaborate_expr(ent, scope, sub_type); return errors; } -const VType*ExpBitstring::fit_type(Entity*, Architecture*, const VTypeArray*atype) const +const VType*ExpBitstring::fit_type(Entity*, ScopeBase*, const VTypeArray*atype) const { // Really should check that this string can work with the // array element type? return atype->element_type(); } -int ExpBitstring::elaborate_expr(Entity*, Architecture*, const VType*) +int ExpBitstring::elaborate_expr(Entity*, ScopeBase*, const VType*) { int errors = 0; return errors; } -const VType*ExpCharacter::fit_type(Entity*, Architecture*, const VTypeArray*atype) const +const VType*ExpCharacter::fit_type(Entity*, ScopeBase*, const VTypeArray*atype) const { // Really should check that this character can work with the // array element type? return atype->element_type(); } -int ExpCharacter::elaborate_expr(Entity*, Architecture*, const VType*ltype) +int ExpCharacter::elaborate_expr(Entity*, ScopeBase*, const VType*ltype) { ivl_assert(*this, ltype != 0); set_type(ltype); return 0; } -const VType*ExpConcat::fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const +const VType*ExpConcat::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const { Expression*operands[2] = {operand1_, operand2_}; const VType*types[2] = {NULL, NULL}; @@ -619,7 +619,7 @@ const VType*ExpConcat::fit_type(Entity*ent, Architecture*arc, const VTypeArray*a // determine the type and size of concatenated expressions for(int i = 0; i < 2; ++i) { - types[i] = operands[i]->fit_type(ent, arc, atype); + types[i] = operands[i]->fit_type(ent, scope, atype); if(const VTypeArray*arr = dynamic_cast(types[i])) { types[i] = arr->element_type(); @@ -647,62 +647,62 @@ const VType*ExpConcat::fit_type(Entity*ent, Architecture*arc, const VTypeArray*a /* * I don't know how to probe the type of a concatenation, quite yet. */ -const VType*ExpConcat::probe_type(Entity*, Architecture*) const +const VType*ExpConcat::probe_type(Entity*, ScopeBase*) const { ivl_assert(*this, 0); return 0; } -int ExpConcat::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype) +int ExpConcat::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype) { int errors = 0; if (ltype == 0) { - ltype = probe_type(ent, arc); + ltype = probe_type(ent, scope); } ivl_assert(*this, ltype != 0); if (const VTypeArray*atype = dynamic_cast(ltype)) { - errors += elaborate_expr_array_(ent, arc, atype); + errors += elaborate_expr_array_(ent, scope, atype); } else { - errors += operand1_->elaborate_expr(ent, arc, ltype); - errors += operand2_->elaborate_expr(ent, arc, ltype); + errors += operand1_->elaborate_expr(ent, scope, ltype); + errors += operand2_->elaborate_expr(ent, scope, ltype); } return errors; } -int ExpConcat::elaborate_expr_array_(Entity*ent, Architecture*arc, const VTypeArray*atype) +int ExpConcat::elaborate_expr_array_(Entity*ent, ScopeBase*scope, const VTypeArray*atype) { int errors = 0; // For now, only support single-dimension arrays here. ivl_assert(*this, atype->dimensions() == 1); - const VType*type1 = operand1_->fit_type(ent, arc, atype); + const VType*type1 = operand1_->fit_type(ent, scope, atype); ivl_assert(*this, type1); - const VType*type2 = operand2_->fit_type(ent, arc, atype); + const VType*type2 = operand2_->fit_type(ent, scope, atype); ivl_assert(*this, type2); - errors += operand1_->elaborate_expr(ent, arc, type1); - errors += operand2_->elaborate_expr(ent, arc, type2); + errors += operand1_->elaborate_expr(ent, scope, type1); + errors += operand2_->elaborate_expr(ent, scope, type2); return errors; } -const VType* ExpConditional::probe_type(Entity*, Architecture*) const +const VType* ExpConditional::probe_type(Entity*, ScopeBase*) const { return 0; } -int ExpConditional::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype) +int ExpConditional::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype) { int errors = 0; if (ltype == 0) - ltype = probe_type(ent, arc); + ltype = probe_type(ent, scope); ivl_assert(*this, ltype); @@ -710,42 +710,42 @@ int ExpConditional::elaborate_expr(Entity*ent, Architecture*arc, const VType*lty /* Note that the type for the condition expression need not have anything to do with the type of this expression. */ - errors += cond_->elaborate_expr(ent, arc, 0); + errors += cond_->elaborate_expr(ent, scope, 0); for (list::const_iterator cur = true_clause_.begin() ; cur != true_clause_.end() ; ++cur) { - errors += (*cur)->elaborate_expr(ent, arc, ltype); + errors += (*cur)->elaborate_expr(ent, scope, ltype); } for (list::const_iterator cur = else_clause_.begin() ; cur != else_clause_.end() ; ++cur) { - errors += (*cur)->elaborate_expr(ent, arc, ltype); + errors += (*cur)->elaborate_expr(ent, scope, ltype); } return errors; } -int ExpConditional::else_t::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype) +int ExpConditional::else_t::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype) { int errors = 0; if (cond_) - errors += cond_->elaborate_expr(ent, arc, 0); + errors += cond_->elaborate_expr(ent, scope, 0); for (list::const_iterator cur = true_clause_.begin() ; cur != true_clause_.end() ; ++cur) { - errors += (*cur)->elaborate_expr(ent, arc, ltype); + errors += (*cur)->elaborate_expr(ent, scope, ltype); } return errors; } -int ExpFunc::elaborate_expr(Entity*ent, Architecture*arc, const VType*) +int ExpFunc::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*) { int errors = 0; - ivl_assert(*this, arc); - Subprogram*prog = arc->find_subprogram(name_); + ivl_assert(*this, scope); + Subprogram*prog = scope->find_subprogram(name_); if(!prog) prog = library_find_subprogram(name_); @@ -755,13 +755,13 @@ int ExpFunc::elaborate_expr(Entity*ent, Architecture*arc, const VType*) // Elaborate arguments for (size_t idx = 0 ; idx < argv_.size() ; idx += 1) { - const VType*tmp = argv_[idx]->probe_type(ent, arc); + const VType*tmp = argv_[idx]->probe_type(ent, scope); const VType*param_type = prog ? prog->peek_param_type(idx) : NULL; if(!tmp && param_type) tmp = param_type; - errors += argv_[idx]->elaborate_expr(ent, arc, tmp); + errors += argv_[idx]->elaborate_expr(ent, scope, tmp); // Type casting for unbounded arrays if(param_type && param_type->is_unbounded() /*&& !param_type->type_match(tmp)*/) { @@ -772,17 +772,17 @@ int ExpFunc::elaborate_expr(Entity*ent, Architecture*arc, const VType*) return errors; } -const VType* ExpInteger::probe_type(Entity*, Architecture*) const +const VType* ExpInteger::probe_type(Entity*, ScopeBase*) const { return &primitive_INTEGER; } -int ExpInteger::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype) +int ExpInteger::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype) { int errors = 0; if (ltype == 0) { - ltype = probe_type(ent, arc); + ltype = probe_type(ent, scope); } ivl_assert(*this, ltype != 0); @@ -790,17 +790,17 @@ int ExpInteger::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype) return errors; } -const VType* ExpReal::probe_type(Entity*, Architecture*) const +const VType* ExpReal::probe_type(Entity*, ScopeBase*) const { return &primitive_REAL; } -int ExpReal::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype) +int ExpReal::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype) { int errors = 0; if (ltype == 0) { - ltype = probe_type(ent, arc); + ltype = probe_type(ent, scope); } ivl_assert(*this, ltype != 0); @@ -808,27 +808,27 @@ int ExpReal::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype) return errors; } -int ExpLogical::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype) +int ExpLogical::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype) { int errors = 0; if (ltype == 0) { - ltype = probe_type(ent, arc); + ltype = probe_type(ent, scope); } ivl_assert(*this, ltype != 0); - errors += elaborate_exprs(ent, arc, ltype); + errors += elaborate_exprs(ent, scope, ltype); return errors; } -const VType* ExpName::probe_prefix_type_(Entity*ent, Architecture*arc) const +const VType* ExpName::probe_prefix_type_(Entity*ent, ScopeBase*scope) const { if (prefix_.get()) { cerr << get_fileline() << ": sorry: I do not know how to support nested prefix parts." << endl; return 0; } - const VType*type = probe_type(ent, arc); + const VType*type = probe_type(ent, scope); return type; } @@ -837,10 +837,10 @@ const VType* ExpName::probe_prefix_type_(Entity*ent, Architecture*arc) const * that have prefix parts. In this case we try to get the type of the * prefix and interpret the name in that context. */ -const VType* ExpName::probe_prefixed_type_(Entity*ent, Architecture*arc) const +const VType* ExpName::probe_prefixed_type_(Entity*ent, ScopeBase*scope) const { // First, get the type of the prefix. - const VType*prefix_type = prefix_->probe_prefix_type_(ent, arc); + const VType*prefix_type = prefix_->probe_prefix_type_(ent, scope); if (prefix_type == 0) { return 0; } @@ -868,34 +868,40 @@ const VType* ExpName::probe_prefixed_type_(Entity*ent, Architecture*arc) const return 0; } -const VType* ExpName::probe_type(Entity*ent, Architecture*arc) const +const VType* ExpName::probe_type(Entity*ent, ScopeBase*scope) const { if (prefix_.get()) - return probe_prefixed_type_(ent, arc); + return probe_prefixed_type_(ent, scope); - if (const InterfacePort*cur = ent->find_port(name_)) { - ivl_assert(*this, cur->type); - return cur->type; + if(ent) { + if (const InterfacePort*cur = ent->find_port(name_)) { + ivl_assert(*this, cur->type); + return cur->type; + } + + if (const InterfacePort*cur = ent->find_generic(name_)) { + ivl_assert(*this, cur->type); + return cur->type; + } } - if (const InterfacePort*cur = ent->find_generic(name_)) { - ivl_assert(*this, cur->type); - return cur->type; - } + if(scope) { + if (Signal*sig = scope->find_signal(name_)) + return sig->peek_type(); - if (Signal*sig = arc->find_signal(name_)) - return sig->peek_type(); + if (Variable*var = scope->find_variable(name_)) + return var->peek_type(); - if (Variable*var = arc->find_variable(name_)) - return var->peek_type(); + const VType*ctype = 0; + Expression*cval = 0; + if (scope->find_constant(name_, ctype, cval)) + return ctype; - const VType*ctype = 0; - Expression*cval = 0; - if (arc->find_constant(name_, ctype, cval)) - return ctype; - - if (const VType*gtype = arc->probe_genvar_type(name_)) { - return gtype; + const VType*gtype = 0; + Architecture*arc = dynamic_cast(scope); + if (arc && (gtype = arc->probe_genvar_type(name_))) { + return gtype; + } } cerr << get_fileline() << ": error: Signal/variable " << name_ @@ -903,12 +909,12 @@ const VType* ExpName::probe_type(Entity*ent, Architecture*arc) const return 0; } -const VType* ExpName::fit_type(Entity*ent, Architecture*arc, const VTypeArray*)const +const VType* ExpName::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*)const { - return probe_type(ent, arc); + return probe_type(ent, scope); } -int ExpName::elaborate_expr(Entity*, Architecture*, const VType*ltype) +int ExpName::elaborate_expr(Entity*, ScopeBase*, const VType*ltype) { if (ltype) { ivl_assert(*this, ltype != 0); @@ -918,22 +924,22 @@ int ExpName::elaborate_expr(Entity*, Architecture*, const VType*ltype) return 0; } -const VType* ExpNameALL::probe_type(Entity*, Architecture*) const +const VType* ExpNameALL::probe_type(Entity*, ScopeBase*) const { return 0; } -const VType* ExpRelation::probe_type(Entity*, Architecture*) const +const VType* ExpRelation::probe_type(Entity*, ScopeBase*) const { return &primitive_BOOLEAN; } -int ExpRelation::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype) +int ExpRelation::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype) { int errors = 0; if (ltype == 0) { - ltype = probe_type(ent, arc); + ltype = probe_type(ent, scope); } ivl_assert(*this, ltype != 0); @@ -941,8 +947,8 @@ int ExpRelation::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype) // The type of the operands must match, but need not match the // type for the ExpRelation itself. So get the operand type // separately. - const VType*otype = ExpBinary::probe_type(ent, arc); - errors += elaborate_exprs(ent, arc, otype); + const VType*otype = ExpBinary::probe_type(ent, scope); + errors += elaborate_exprs(ent, scope, otype); return errors; } @@ -952,7 +958,7 @@ int ExpRelation::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype) * string is an array with the same element type of the concatenation, * but with elements for each character of the string. */ -const VType*ExpString::fit_type(Entity*, Architecture*, const VTypeArray*atype) const +const VType*ExpString::fit_type(Entity*, ScopeBase*, const VTypeArray*atype) const { vector range (atype->dimensions()); @@ -968,14 +974,14 @@ const VType*ExpString::fit_type(Entity*, Architecture*, const VTypeArray*atype) return type; } -int ExpString::elaborate_expr(Entity*, Architecture*, const VType*ltype) +int ExpString::elaborate_expr(Entity*, ScopeBase*, const VType*ltype) { ivl_assert(*this, ltype != 0); set_type(ltype); return 0; } -int ExpUNot::elaborate_expr(Entity*, Architecture*, const VType*ltype) +int ExpUNot::elaborate_expr(Entity*, ScopeBase*, const VType*ltype) { ivl_assert(*this, ltype != 0); set_type(ltype); diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index 32733913c..04b4d21a3 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -33,7 +33,7 @@ using namespace std; -int Expression::emit(ostream&out, Entity*, Architecture*) +int Expression::emit(ostream&out, Entity*, ScopeBase*) { out << " /* " << get_fileline() << ": internal error: " << "I don't know how to emit this expression! " @@ -54,34 +54,34 @@ bool Expression::is_primary(void) const return false; } -int ExpBinary::emit_operand1(ostream&out, Entity*ent, Architecture*arc) +int ExpBinary::emit_operand1(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; bool oper_primary = operand1_->is_primary(); if (! oper_primary) out << "("; - errors += operand1_->emit(out, ent, arc); + errors += operand1_->emit(out, ent, scope); if (! oper_primary) out << ")"; return errors; } -int ExpBinary::emit_operand2(ostream&out, Entity*ent, Architecture*arc) +int ExpBinary::emit_operand2(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; bool oper_primary = operand2_->is_primary(); if (! oper_primary) out << "("; - errors += operand2_->emit(out, ent, arc); + errors += operand2_->emit(out, ent, scope); if (! oper_primary) out << ")"; return errors; } -int ExpUnary::emit_operand1(ostream&out, Entity*ent, Architecture*arc) +int ExpUnary::emit_operand1(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; - errors += operand1_->emit(out, ent, arc); + errors += operand1_->emit(out, ent, scope); return errors; } -int ExpAggregate::emit(ostream&out, Entity*ent, Architecture*arc) +int ExpAggregate::emit(ostream&out, Entity*ent, ScopeBase*scope) { if (peek_type() == 0) { out << "/* " << get_fileline() << ": internal error: " @@ -95,9 +95,9 @@ int ExpAggregate::emit(ostream&out, Entity*ent, Architecture*arc) } if (const VTypeArray*atype = dynamic_cast (use_type)) - return emit_array_(out, ent, arc, atype); + return emit_array_(out, ent, scope, atype); else if (const VTypeRecord*arecord = dynamic_cast (use_type)) - return emit_record_(out, ent, arc, arecord); + return emit_record_(out, ent, scope, arecord); out << "/* " << get_fileline() << ": internal error: " << "I don't know how to elab/emit aggregate in " << typeid(use_type).name() @@ -105,7 +105,7 @@ int ExpAggregate::emit(ostream&out, Entity*ent, Architecture*arc) return 1; } -int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const VTypeArray*atype) +int ExpAggregate::emit_array_(ostream&out, Entity*ent, ScopeBase*scope, const VTypeArray*atype) { int errors = 0; @@ -119,14 +119,14 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V int64_t use_msb; int64_t use_lsb; bool rc_msb, rc_lsb; - rc_msb = rang.msb()->evaluate(ent, arc, use_msb); - rc_lsb = rang.lsb()->evaluate(ent, arc, use_lsb); + rc_msb = rang.msb()->evaluate(ent, scope, use_msb); + rc_lsb = rang.lsb()->evaluate(ent, scope, use_lsb); if (rc_msb && rc_lsb) { int asize = (use_msb >= use_lsb) ? (use_msb - use_lsb) + 1 : (use_lsb - use_msb) + 1; out << "{" << asize << "{"; - errors += aggregate_[0].expr->emit(out, ent, arc); + errors += aggregate_[0].expr->emit(out, ent, scope); out << "}}"; } else { out << "{("; @@ -134,7 +134,7 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V out << use_msb; } else { out << "("; - errors += rang.msb()->emit(out, ent, arc); + errors += rang.msb()->emit(out, ent, scope); out << ")"; } if (rc_lsb && use_lsb==0) { @@ -142,11 +142,11 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V out << "-" << use_lsb; } else { out << "-("; - errors += rang.lsb()->emit(out, ent, arc); + errors += rang.lsb()->emit(out, ent, scope); out << ")"; } out << "+1){"; - errors += aggregate_[0].expr->emit(out, ent, arc); + errors += aggregate_[0].expr->emit(out, ent, scope); out << "}}"; } return errors; @@ -158,9 +158,9 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V // Fully calculate the range numbers. int64_t use_msb, use_lsb; bool rc; - rc = rang.msb()->evaluate(ent, arc, use_msb); + rc = rang.msb()->evaluate(ent, scope, use_msb); ivl_assert(*this, rc); - rc = rang.lsb()->evaluate(ent, arc, use_lsb); + rc = rang.lsb()->evaluate(ent, scope, use_lsb); ivl_assert(*this, rc); if(use_msb < use_lsb) swap(use_msb, use_lsb); @@ -198,14 +198,14 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V if (prange_t*range = aggregate_[idx].choice->range_expressions()) { int64_t begin_val, end_val; - if (! range->msb()->evaluate(ent, arc, begin_val)) { + if (! range->msb()->evaluate(ent, scope, begin_val)) { cerr << range->msb()->get_fileline() << ": error: " << "Unable to evaluate aggregate choice expression." << endl; errors += 1; continue; } - if (! range->lsb()->evaluate(ent, arc, end_val)) { + if (! range->lsb()->evaluate(ent, scope, end_val)) { cerr << range->msb()->get_fileline() << ": error: " << "Unable to evaluate aggregate choice expression." << endl; errors += 1; @@ -235,7 +235,7 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V // elements so disable further positional // processing. positional_section = false; - if (! tmp->evaluate(ent, arc, tmp_val)) { + if (! tmp->evaluate(ent, scope, tmp_val)) { cerr << tmp->get_fileline() << ": error: " << "Unable to evaluate aggregate choice expression." << endl; errors += 1; @@ -266,7 +266,7 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V << "Missing element " << idx << "." << endl; errors += 1; } else { - errors += cur->expr->emit(out, ent, arc); + errors += cur->expr->emit(out, ent, scope); } } out << "}"; @@ -274,7 +274,7 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V return errors; } -int ExpAggregate::emit_record_(ostream&out, Entity*ent, Architecture*arc, const VTypeRecord*) +int ExpAggregate::emit_record_(ostream&out, Entity*ent, ScopeBase*scope, const VTypeRecord*) { int errors = 0; @@ -292,9 +292,9 @@ int ExpAggregate::emit_record_(ostream&out, Entity*ent, Architecture*arc, const if(idx != 0) out << ","; - //errors += name->emit(out, ent, arc); + //errors += name->emit(out, ent, scope); //out << ": "; - errors += val->emit(out, ent, arc); + errors += val->emit(out, ent, scope); } out << "}"; @@ -302,13 +302,13 @@ int ExpAggregate::emit_record_(ostream&out, Entity*ent, Architecture*arc, const return errors; } -int ExpAttribute::emit(ostream&out, Entity*ent, Architecture*arc) +int ExpAttribute::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; if (name_ == "event") { out << "$ivlh_attribute_event("; - errors += base_->emit(out, ent, arc); + errors += base_->emit(out, ent, scope); out << ")"; return errors; } @@ -319,27 +319,27 @@ int ExpAttribute::emit(ostream&out, Entity*ent, Architecture*arc) expression doesn't even need to be evaluated.) */ if (name_=="length") { out << "$bits("; - errors += base_->emit(out, ent, arc); + errors += base_->emit(out, ent, scope); out << ")"; return errors; } else if (name_=="left" || name_=="right") { out << "$" << name_ << "("; - errors += base_->emit(out, ent, arc); + errors += base_->emit(out, ent, scope); out << ")"; return errors; } out << "$ivl_attribute("; - errors += base_->emit(out, ent, arc); + errors += base_->emit(out, ent, scope); out << ", \"" << name_ << "\")"; return errors; } -int ExpArithmetic::emit(ostream&out, Entity*ent, Architecture*arc) +int ExpArithmetic::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; - errors += emit_operand1(out, ent, arc); + errors += emit_operand1(out, ent, scope); switch (fun_) { case PLUS: @@ -369,12 +369,12 @@ int ExpArithmetic::emit(ostream&out, Entity*ent, Architecture*arc) break; } - errors += emit_operand2(out, ent, arc); + errors += emit_operand2(out, ent, scope); return errors; } -int ExpBitstring::emit(ostream&out, Entity*, Architecture*) +int ExpBitstring::emit(ostream&out, Entity*, ScopeBase*) { int errors = 0; @@ -385,7 +385,7 @@ int ExpBitstring::emit(ostream&out, Entity*, Architecture*) return errors; } -int ExpCharacter::emit_primitive_bit_(ostream&out, Entity*, Architecture*, +int ExpCharacter::emit_primitive_bit_(ostream&out, Entity*, ScopeBase*, const VTypePrimitive*etype) { switch (etype->type()) { @@ -407,17 +407,17 @@ int ExpCharacter::emit_primitive_bit_(ostream&out, Entity*, Architecture*, return 1; } -int ExpCharacter::emit(ostream&out, Entity*ent, Architecture*arc) +int ExpCharacter::emit(ostream&out, Entity*ent, ScopeBase*scope) { const VType*etype = peek_type(); if (const VTypePrimitive*use_type = dynamic_cast(etype)) { - return emit_primitive_bit_(out, ent, arc, use_type); + return emit_primitive_bit_(out, ent, scope, use_type); } if (const VTypeArray*array = dynamic_cast(etype)) { if (const VTypePrimitive*use_type = dynamic_cast(array->element_type())) { - return emit_primitive_bit_(out, ent, arc, use_type); + return emit_primitive_bit_(out, ent, scope, use_type); } } @@ -439,22 +439,22 @@ bool ExpConcat::is_primary(void) const return true; } -int ExpConcat::emit(ostream&out, Entity*ent, Architecture*arc) +int ExpConcat::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; out << "{"; - errors += operand1_->emit(out, ent, arc); + errors += operand1_->emit(out, ent, scope); out << ", "; - errors += operand2_->emit(out, ent, arc); + errors += operand2_->emit(out, ent, scope); out << "}"; return errors; } -int ExpConditional::emit(ostream&out, Entity*ent, Architecture*arc) +int ExpConditional::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; out << "("; - errors += cond_->emit(out, ent, arc); + errors += cond_->emit(out, ent, scope); out << ")? ("; if (true_clause_.size() > 1) { @@ -463,7 +463,7 @@ int ExpConditional::emit(ostream&out, Entity*ent, Architecture*arc) } Expression*tmp = true_clause_.front(); - errors += tmp->emit(out, ent, arc); + errors += tmp->emit(out, ent, scope); out << ") : ("; @@ -475,11 +475,11 @@ int ExpConditional::emit(ostream&out, Entity*ent, Architecture*arc) for (list::iterator cur = else_clause_.begin() ; cur != last ; ++cur) { - errors += (*cur) ->emit_when_else(out, ent, arc); + errors += (*cur) ->emit_when_else(out, ent, scope); } } - errors += else_clause_.back()->emit_else(out, ent, arc); + errors += else_clause_.back()->emit_else(out, ent, scope); out << ")"; // The emit_when_else() functions do not close the last @@ -492,13 +492,13 @@ int ExpConditional::emit(ostream&out, Entity*ent, Architecture*arc) return errors; } -int ExpConditional::else_t::emit_when_else(ostream&out, Entity*ent, Architecture*arc) +int ExpConditional::else_t::emit_when_else(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; assert(cond_ != 0); out << "("; - errors += cond_->emit(out, ent, arc); + errors += cond_->emit(out, ent, scope); out << ")? ("; if (true_clause_.size() > 1) { @@ -507,14 +507,14 @@ int ExpConditional::else_t::emit_when_else(ostream&out, Entity*ent, Architecture } Expression*tmp = true_clause_.front(); - errors += tmp->emit(out, ent, arc); + errors += tmp->emit(out, ent, scope); out << ") : ("; return errors; } -int ExpConditional::else_t::emit_else(ostream&out, Entity*ent, Architecture*arc) +int ExpConditional::else_t::emit_else(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; // Trailing else must have no condition. @@ -526,12 +526,12 @@ int ExpConditional::else_t::emit_else(ostream&out, Entity*ent, Architecture*arc) } Expression*tmp = true_clause_.front(); - errors += tmp->emit(out, ent, arc); + errors += tmp->emit(out, ent, scope); return errors; } -int ExpEdge::emit(ostream&out, Entity*ent, Architecture*arc) +int ExpEdge::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; switch (fun_) { @@ -544,11 +544,11 @@ int ExpEdge::emit(ostream&out, Entity*ent, Architecture*arc) case ANYEDGE: break; } - errors += emit_operand1(out, ent, arc); + errors += emit_operand1(out, ent, scope); return errors; } -int ExpFunc::emit(ostream&out, Entity*ent, Architecture*arc) +int ExpFunc::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; @@ -558,46 +558,46 @@ int ExpFunc::emit(ostream&out, Entity*ent, Architecture*arc) // std numeric library, but we interpret it as the same // as the $unsigned function. out << "$unsigned("; - errors += argv_[0]->emit(out, ent, arc); + errors += argv_[0]->emit(out, ent, scope); out << ")"; } else if (name_ == "integer" && argv_.size() == 1) { // Simply skip the function name, SystemVerilog takes care of // rounding real numbers - errors += argv_[0]->emit(out, ent, arc); + errors += argv_[0]->emit(out, ent, scope); } else if (name_ == "std_logic_vector" && argv_.size() == 1) { // Special case: The std_logic_vector function casts its // argument to std_logic_vector. Internally, we don't // have to do anything for that to work. out << "("; - errors += argv_[0]->emit(out, ent, arc); + errors += argv_[0]->emit(out, ent, scope); out << ")"; } else if (name_ == "to_unsigned" && argv_.size() == 2) { out << "$ivlh_to_unsigned("; - errors += argv_[0]->emit(out, ent, arc); + errors += argv_[0]->emit(out, ent, scope); out << ", "; - errors += argv_[1]->emit(out, ent, arc); + errors += argv_[1]->emit(out, ent, scope); out << ")"; } else if (name_ == "conv_std_logic_vector" && argv_.size() == 2) { int64_t use_size; - bool rc = argv_[1]->evaluate(ent, arc, use_size); + bool rc = argv_[1]->evaluate(ent, scope, use_size); ivl_assert(*this, rc); out << use_size << "'("; - errors += argv_[0]->emit(out, ent, arc); + errors += argv_[0]->emit(out, ent, scope); out << ")"; } else if (name_ == "rising_edge" && argv_.size()==1) { out << "$ivlh_rising_edge("; - errors += argv_[0]->emit(out, ent, arc); + errors += argv_[0]->emit(out, ent, scope); out << ")"; } else if (name_ == "falling_edge" && argv_.size()==1) { out << "$ivlh_falling_edge("; - errors += argv_[0]->emit(out, ent, arc); + errors += argv_[0]->emit(out, ent, scope); out << ")"; } else { @@ -615,7 +615,7 @@ int ExpFunc::emit(ostream&out, Entity*ent, Architecture*arc) out << "\\" << name_ << " ("; for (size_t idx = 0; idx < argv_.size() ; idx += 1) { if (idx > 0) out << ", "; - errors += argv_[idx]->emit(out, ent, arc); + errors += argv_[idx]->emit(out, ent, scope); } out << ")"; } @@ -623,7 +623,7 @@ int ExpFunc::emit(ostream&out, Entity*ent, Architecture*arc) return errors; } -int ExpInteger::emit(ostream&out, Entity*, Architecture*) +int ExpInteger::emit(ostream&out, Entity*, ScopeBase*) { out << value_; return 0; @@ -640,7 +640,7 @@ bool ExpInteger::is_primary(void) const return true; } -int ExpReal::emit(ostream&out, Entity*, Architecture*) +int ExpReal::emit(ostream&out, Entity*, ScopeBase*) { out << value_; return 0; @@ -657,11 +657,11 @@ bool ExpReal::is_primary(void) const return true; } -int ExpLogical::emit(ostream&out, Entity*ent, Architecture*arc) +int ExpLogical::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; - errors += emit_operand1(out, ent, arc); + errors += emit_operand1(out, ent, scope); switch (fun_) { case AND: @@ -684,22 +684,22 @@ int ExpLogical::emit(ostream&out, Entity*ent, Architecture*arc) break; } - errors += emit_operand2(out, ent, arc); + errors += emit_operand2(out, ent, scope); return errors; } -int ExpName::emit_as_prefix_(ostream&out, Entity*ent, Architecture*arc) +int ExpName::emit_as_prefix_(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; if (prefix_.get()) { - errors += prefix_->emit_as_prefix_(out, ent, arc); + errors += prefix_->emit_as_prefix_(out, ent, scope); } out << "\\" << name_ << " "; if (index_) { out << "["; - errors += index_->emit(out, ent, arc); + errors += index_->emit(out, ent, scope); out << "]"; ivl_assert(*this, lsb_ == 0); } @@ -707,27 +707,28 @@ int ExpName::emit_as_prefix_(ostream&out, Entity*ent, Architecture*arc) return errors; } -int ExpName::emit(ostream&out, Entity*ent, Architecture*arc) +int ExpName::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; if (prefix_.get()) { - errors += prefix_->emit_as_prefix_(out, ent, arc); + errors += prefix_->emit_as_prefix_(out, ent, scope); } const GenerateStatement*gs = 0; + Architecture*arc = dynamic_cast(scope); if (arc && (gs = arc->probe_genvar_emit(name_))) - out << "\\" << gs->get_name() << ":" << name_ << " "; + out << "\\" << gs->get_name() << ":" << name_ << " "; else out << "\\" << name_ << " "; if (index_) { out << "["; - errors += index_->emit(out, ent, arc); + errors += index_->emit(out, ent, scope); if (lsb_) { out << ":"; - errors += lsb_->emit(out, ent, arc); + errors += lsb_->emit(out, ent, scope); } out << "]"; } @@ -740,10 +741,10 @@ bool ExpName::is_primary(void) const return true; } -int ExpRelation::emit(ostream&out, Entity*ent, Architecture*arc) +int ExpRelation::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; - errors += emit_operand1(out, ent, arc); + errors += emit_operand1(out, ent, scope); switch (fun_) { case EQ: @@ -766,7 +767,7 @@ int ExpRelation::emit(ostream&out, Entity*ent, Architecture*arc) break; } - errors += emit_operand2(out, ent, arc); + errors += emit_operand2(out, ent, scope); return errors; } @@ -775,13 +776,13 @@ bool ExpString::is_primary(void) const return true; } -int ExpString::emit(ostream& out, Entity*ent, Architecture*arc) +int ExpString::emit(ostream& out, Entity*ent, ScopeBase*scope) { const VType*type = peek_type(); assert(type != 0); if (const VTypeArray*arr = dynamic_cast(type)) { - return emit_as_array_(out, ent, arc, arr); + return emit_as_array_(out, ent, scope, arr); } out << "\""; @@ -792,7 +793,7 @@ int ExpString::emit(ostream& out, Entity*ent, Architecture*arc) return 0; } -int ExpString::emit_as_array_(ostream& out, Entity*, Architecture*, const VTypeArray*arr) +int ExpString::emit_as_array_(ostream& out, Entity*, ScopeBase*, const VTypeArray*arr) { int errors = 0; assert(arr->dimensions() == 1); @@ -843,39 +844,39 @@ int ExpString::emit_as_array_(ostream& out, Entity*, Architecture*, const VTypeA return errors; } -int ExpUAbs::emit(ostream&out, Entity*ent, Architecture*arc) +int ExpUAbs::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; out << "abs("; - errors += emit_operand1(out, ent, arc); + errors += emit_operand1(out, ent, scope); out << ")"; return errors; } -int ExpUNot::emit(ostream&out, Entity*ent, Architecture*arc) +int ExpUNot::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; out << "~("; - errors += emit_operand1(out, ent, arc); + errors += emit_operand1(out, ent, scope); out << ")"; return errors; } -int ExpCast::emit(ostream&out, Entity*ent, Architecture*arc) +int ExpCast::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; errors += type_->emit_def(out, empty_perm_string); out << "'("; - errors += base_->emit(out, ent, arc); + errors += base_->emit(out, ent, scope); out << ")"; return errors; } -int ExpNew::emit(ostream&out, Entity*ent, Architecture*arc) +int ExpNew::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; out << "new["; - errors += size_->emit(out, ent, arc); + errors += size_->emit(out, ent, scope); out << "]"; return errors; } diff --git a/vhdlpp/expression_evaluate.cc b/vhdlpp/expression_evaluate.cc index 27baba7e7..90cc39ebc 100644 --- a/vhdlpp/expression_evaluate.cc +++ b/vhdlpp/expression_evaluate.cc @@ -26,9 +26,9 @@ bool Expression::evaluate(ScopeBase*, int64_t&) const return false; } -bool Expression::evaluate(Entity*, Architecture*arc, int64_t&val) const +bool Expression::evaluate(Entity*, ScopeBase*scope, int64_t&val) const { - return evaluate(arc, val); + return evaluate(scope, val); } @@ -110,16 +110,16 @@ bool ExpAttribute::evaluate(ScopeBase*, int64_t&val) const return false; } -bool ExpAttribute::evaluate(Entity*ent, Architecture*arc, int64_t&val) const +bool ExpAttribute::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const { - if (!ent || !arc) { // it's impossible to evaluate, probably it is inside a subprogram + if (!ent || !scope) { // it's impossible to evaluate, probably it is inside a subprogram return false; } if (name_ == "left" || name_ == "right") { const VType*base_type = base_->peek_type(); if (base_type == 0) - base_type = base_->probe_type(ent, arc); + base_type = base_->probe_type(ent, scope); ivl_assert(*this, base_type); @@ -133,14 +133,14 @@ bool ExpAttribute::evaluate(Entity*ent, Architecture*arc, int64_t&val) const ivl_assert(*this, arr->dimensions() == 1); if(name_ == "left") - arr->dimension(0).msb()->evaluate(ent, arc, val); + arr->dimension(0).msb()->evaluate(ent, scope, val); else // "right" - arr->dimension(0).lsb()->evaluate(ent, arc, val); + arr->dimension(0).lsb()->evaluate(ent, scope, val); return true; } - return evaluate(arc, val); + return evaluate(scope, val); } /* @@ -169,7 +169,7 @@ bool ExpName::evaluate(ScopeBase*scope, int64_t&val) const return exp->evaluate(scope, val); } -bool ExpName::evaluate(Entity*ent, Architecture*arc, int64_t&val) const +bool ExpName::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const { if (prefix_.get()) { cerr << get_fileline() << ": sorry: I don't know how to evaluate ExpName prefix parts." << endl; @@ -182,8 +182,8 @@ bool ExpName::evaluate(Entity*ent, Architecture*arc, int64_t&val) const // Evaluate the default expression and use that. if (gen->expr) - return gen->expr->evaluate(ent, arc, val); + return gen->expr->evaluate(ent, scope, val); } - return evaluate(arc, val); + return evaluate(scope, val); } diff --git a/vhdlpp/sequential.h b/vhdlpp/sequential.h index 6edd2321e..d3229d9ff 100644 --- a/vhdlpp/sequential.h +++ b/vhdlpp/sequential.h @@ -25,7 +25,7 @@ # include # include -class Architecture; +class ScopeBase; class Entity; class Expression; class SequentialStmt; @@ -42,8 +42,8 @@ class SequentialStmt : public LineInfo { virtual ~SequentialStmt() =0; public: - virtual int elaborate(Entity*ent, Architecture*arc); - virtual int emit(ostream&out, Entity*entity, Architecture*arc); + virtual int elaborate(Entity*ent, ScopeBase*scope); + virtual int emit(ostream&out, Entity*entity, ScopeBase*scope); virtual void dump(ostream&out, int indent) const; // Recursively visits a tree of sequential statements. @@ -65,8 +65,8 @@ class LoopStatement : public SequentialStmt { void visit(SeqStmtVisitor& func); protected: - int elaborate_substatements(Entity*ent, Architecture*arc); - int emit_substatements(std::ostream&out, Entity*ent, Architecture*arc); + int elaborate_substatements(Entity*ent, ScopeBase*scope); + int emit_substatements(std::ostream&out, Entity*ent, ScopeBase*scope); private: perm_string name_; @@ -81,9 +81,9 @@ class IfSequential : public SequentialStmt { Elsif(Expression*cond, std::list*tr); ~Elsif(); - int elaborate(Entity*entity, Architecture*arc); - int condition_emit(ostream&out, Entity*entity, Architecture*arc); - int statement_emit(ostream&out, Entity*entity, Architecture*arc); + int elaborate(Entity*entity, ScopeBase*scope); + int condition_emit(ostream&out, Entity*entity, ScopeBase*scope); + int statement_emit(ostream&out, Entity*entity, ScopeBase*scope); void dump(ostream&out, int indent) const; void visit(SeqStmtVisitor& func); @@ -103,8 +103,8 @@ class IfSequential : public SequentialStmt { ~IfSequential(); public: - int elaborate(Entity*ent, Architecture*arc); - int emit(ostream&out, Entity*entity, Architecture*arc); + int elaborate(Entity*ent, ScopeBase*scope); + int emit(ostream&out, Entity*entity, ScopeBase*scope); void dump(ostream&out, int indent) const; void visit(SeqStmtVisitor& func); @@ -130,7 +130,7 @@ class ReturnStmt : public SequentialStmt { ~ReturnStmt(); public: - int emit(ostream&out, Entity*entity, Architecture*arc); + int emit(ostream&out, Entity*entity, ScopeBase*scope); void dump(ostream&out, int indent) const; const Expression*peek_expr() const { return val_; }; @@ -146,8 +146,8 @@ class SignalSeqAssignment : public SequentialStmt { ~SignalSeqAssignment(); public: - int elaborate(Entity*ent, Architecture*arc); - int emit(ostream&out, Entity*entity, Architecture*arc); + int elaborate(Entity*ent, ScopeBase*scope); + int emit(ostream&out, Entity*entity, ScopeBase*scope); void dump(ostream&out, int indent) const; private: @@ -162,9 +162,9 @@ class CaseSeqStmt : public SequentialStmt { CaseStmtAlternative(Expression* exp, std::list* stmts); ~CaseStmtAlternative(); void dump(std::ostream& out, int indent) const; - int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); - int elaborate(Entity*ent, Architecture*arc); - int emit(ostream&out, Entity*entity, Architecture*arc); + int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); + int elaborate(Entity*ent, ScopeBase*scope); + int emit(ostream&out, Entity*entity, ScopeBase*scope); void visit(SeqStmtVisitor& func); private: @@ -181,8 +181,8 @@ class CaseSeqStmt : public SequentialStmt { public: void dump(ostream&out, int indent) const; - int elaborate(Entity*ent, Architecture*arc); - int emit(ostream&out, Entity*entity, Architecture*arc); + int elaborate(Entity*ent, ScopeBase*scope); + int emit(ostream&out, Entity*entity, ScopeBase*scope); void visit(SeqStmtVisitor& func); private: @@ -196,8 +196,8 @@ class ProcedureCall : public SequentialStmt { ProcedureCall(perm_string name, std::list* param_list); ~ProcedureCall(); - int elaborate(Entity*ent, Architecture*arc); - int emit(ostream&out, Entity*entity, Architecture*arc); + int elaborate(Entity*ent, ScopeBase*scope); + int emit(ostream&out, Entity*entity, ScopeBase*scope); void dump(ostream&out, int indent) const; private: @@ -211,8 +211,8 @@ class VariableSeqAssignment : public SequentialStmt { ~VariableSeqAssignment(); public: - int elaborate(Entity*ent, Architecture*arc); - int emit(ostream&out, Entity*entity, Architecture*arc); + int elaborate(Entity*ent, ScopeBase*scope); + int emit(ostream&out, Entity*entity, ScopeBase*scope); void dump(ostream&out, int indent) const; private: @@ -226,8 +226,8 @@ class WhileLoopStatement : public LoopStatement { ExpLogical*, list*); ~WhileLoopStatement(); - int elaborate(Entity*ent, Architecture*arc); - int emit(ostream&out, Entity*entity, Architecture*arc); + int elaborate(Entity*ent, ScopeBase*scope); + int emit(ostream&out, Entity*entity, ScopeBase*scope); void dump(ostream&out, int indent) const; private: @@ -240,14 +240,14 @@ class ForLoopStatement : public LoopStatement { perm_string index, prange_t*, list*); ~ForLoopStatement(); - int elaborate(Entity*ent, Architecture*arc); - int emit(ostream&out, Entity*ent, Architecture*arc); + int elaborate(Entity*ent, ScopeBase*scope); + int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent) const; private: // Emits for-loop which direction is determined at run-time. // It is used for 'range & 'reverse_range attributes. - int emit_runtime_(ostream&out, Entity*ent, Architecture*arc); + int emit_runtime_(ostream&out, Entity*ent, ScopeBase*scope); perm_string it_; prange_t* range_; @@ -258,8 +258,8 @@ class BasicLoopStatement : public LoopStatement { BasicLoopStatement(perm_string lname, list*); ~BasicLoopStatement(); - int elaborate(Entity*ent, Architecture*arc); - int emit(ostream&out, Entity*entity, Architecture*arc); + int elaborate(Entity*ent, ScopeBase*scope); + int emit(ostream&out, Entity*entity, ScopeBase*scope); void dump(ostream&out, int indent) const; }; diff --git a/vhdlpp/sequential_elaborate.cc b/vhdlpp/sequential_elaborate.cc index dcfabe978..88d215de7 100644 --- a/vhdlpp/sequential_elaborate.cc +++ b/vhdlpp/sequential_elaborate.cc @@ -20,35 +20,35 @@ # include "sequential.h" # include "expression.h" -int SequentialStmt::elaborate(Entity*, Architecture*) +int SequentialStmt::elaborate(Entity*, ScopeBase*) { return 0; } -int LoopStatement::elaborate_substatements(Entity*ent, Architecture*arc) +int LoopStatement::elaborate_substatements(Entity*ent, ScopeBase*scope) { int errors = 0; for (list::iterator cur = stmts_.begin() ; cur != stmts_.end() ; ++cur) { - errors += (*cur)->elaborate(ent, arc); + errors += (*cur)->elaborate(ent, scope); } return errors; } -int CaseSeqStmt::elaborate(Entity*ent, Architecture*arc) +int CaseSeqStmt::elaborate(Entity*ent, ScopeBase*scope) { int errors = 0; - const VType*ctype = cond_->probe_type(ent, arc); - errors += cond_->elaborate_expr(ent, arc, ctype); + const VType*ctype = cond_->probe_type(ent, scope); + errors += cond_->elaborate_expr(ent, scope, ctype); for (list::iterator cur = alt_.begin() ; cur != alt_.end() ; ++cur) { CaseStmtAlternative*curp = *cur; - errors += curp->elaborate_expr(ent, arc, ctype); - errors += curp->elaborate(ent, arc); + errors += curp->elaborate_expr(ent, scope, ctype); + errors += curp->elaborate(ent, scope); } return errors; @@ -59,78 +59,78 @@ int CaseSeqStmt::elaborate(Entity*ent, Architecture*arc) * ltype is the probed type for the main case condition. The * expression needs to elaborate itself in that context. */ -int CaseSeqStmt::CaseStmtAlternative::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype) +int CaseSeqStmt::CaseStmtAlternative::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype) { int errors = 0; if (exp_) - errors += exp_->elaborate_expr(ent, arc, ltype); + errors += exp_->elaborate_expr(ent, scope, ltype); return errors; } -int CaseSeqStmt::CaseStmtAlternative::elaborate(Entity*ent, Architecture*arc) +int CaseSeqStmt::CaseStmtAlternative::elaborate(Entity*ent, ScopeBase*scope) { int errors = 0; for (list::iterator cur = stmts_.begin() ; cur != stmts_.end() ; ++cur) { SequentialStmt*curp = *cur; - errors += curp->elaborate(ent, arc); + errors += curp->elaborate(ent, scope); } return errors; } -int ForLoopStatement::elaborate(Entity*ent, Architecture*arc) +int ForLoopStatement::elaborate(Entity*ent, ScopeBase*scope) { int errors = 0; - errors += elaborate_substatements(ent, arc); + errors += elaborate_substatements(ent, scope); return errors; } -int IfSequential::elaborate(Entity*ent, Architecture*arc) +int IfSequential::elaborate(Entity*ent, ScopeBase*scope) { int errors = 0; - errors += cond_->elaborate_expr(ent, arc, 0); + errors += cond_->elaborate_expr(ent, scope, 0); for (list::iterator cur = if_.begin() ; cur != if_.end() ; ++cur) { - errors += (*cur)->elaborate(ent, arc); + errors += (*cur)->elaborate(ent, scope); } for (list::iterator cur = elsif_.begin() ; cur != elsif_.end() ; ++cur) { - errors += (*cur)->elaborate(ent, arc); + errors += (*cur)->elaborate(ent, scope); } for (list::iterator cur = else_.begin() ; cur != else_.end() ; ++cur) { - errors += (*cur)->elaborate(ent, arc); + errors += (*cur)->elaborate(ent, scope); } return errors; } -int IfSequential::Elsif::elaborate(Entity*ent, Architecture*arc) +int IfSequential::Elsif::elaborate(Entity*ent, ScopeBase*scope) { int errors = 0; - errors += cond_->elaborate_expr(ent, arc, 0); + errors += cond_->elaborate_expr(ent, scope, 0); for (list::iterator cur = if_.begin() ; cur != if_.end() ; ++cur) { - errors += (*cur)->elaborate(ent, arc); + errors += (*cur)->elaborate(ent, scope); } return errors; } -int SignalSeqAssignment::elaborate(Entity*ent, Architecture*arc) +int SignalSeqAssignment::elaborate(Entity*ent, ScopeBase*scope) { int errors = 0; // Elaborate the l-value expression. - errors += lval_->elaborate_lval(ent, arc, true); + errors += lval_->elaborate_lval(ent, scope, true); // The elaborate_lval should have resolved the type of the // l-value expression. We'll use that type to elaborate the @@ -145,23 +145,23 @@ int SignalSeqAssignment::elaborate(Entity*ent, Architecture*arc) for (list::iterator cur = waveform_.begin() ; cur != waveform_.end() ; ++cur) { - errors += (*cur)->elaborate_expr(ent, arc, lval_type); + errors += (*cur)->elaborate_expr(ent, scope, lval_type); } return errors; } -int ProcedureCall::elaborate(Entity*, Architecture*) +int ProcedureCall::elaborate(Entity*, ScopeBase*) { return 0; } -int VariableSeqAssignment::elaborate(Entity*ent, Architecture*arc) +int VariableSeqAssignment::elaborate(Entity*ent, ScopeBase*scope) { int errors = 0; // Elaborate the l-value expression. - errors += lval_->elaborate_lval(ent, arc, true); + errors += lval_->elaborate_lval(ent, scope, true); // The elaborate_lval should have resolved the type of the // l-value expression. We'll use that type to elaborate the @@ -173,7 +173,7 @@ int VariableSeqAssignment::elaborate(Entity*ent, Architecture*arc) } // Elaborate the r-value expression. - errors += rval_->elaborate_expr(ent, arc, lval_type); + errors += rval_->elaborate_expr(ent, scope, lval_type); // Handle functions that return unbounded arrays if(ExpFunc*call = dynamic_cast(rval_)) { @@ -185,13 +185,13 @@ int VariableSeqAssignment::elaborate(Entity*ent, Architecture*arc) return errors; } -int WhileLoopStatement::elaborate(Entity*, Architecture*) +int WhileLoopStatement::elaborate(Entity*, ScopeBase*) { //TODO:check whether there is any wait statement in the statements (there should be) return 0; } -int BasicLoopStatement::elaborate(Entity*, Architecture*) +int BasicLoopStatement::elaborate(Entity*, ScopeBase*) { return 0; } diff --git a/vhdlpp/sequential_emit.cc b/vhdlpp/sequential_emit.cc index 3203eb704..44846a69d 100644 --- a/vhdlpp/sequential_emit.cc +++ b/vhdlpp/sequential_emit.cc @@ -27,7 +27,7 @@ # include # include -int SequentialStmt::emit(ostream&out, Entity*, Architecture*) +int SequentialStmt::emit(ostream&out, Entity*, ScopeBase*) { out << " // " << get_fileline() << ": internal error: " << "I don't know how to emit this sequential statement! " @@ -35,23 +35,23 @@ int SequentialStmt::emit(ostream&out, Entity*, Architecture*) return 1; } -int IfSequential::emit(ostream&out, Entity*ent, Architecture*arc) +int IfSequential::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; out << "if ("; - errors += cond_->emit(out, ent, arc); + errors += cond_->emit(out, ent, scope); out << ") begin" << endl; for (list::iterator cur = if_.begin() ; cur != if_.end() ; ++cur) - errors += (*cur)->emit(out, ent, arc); + errors += (*cur)->emit(out, ent, scope); for (list::iterator cur = elsif_.begin() ; cur != elsif_.end() ; ++cur) { out << "end else if ("; - errors += (*cur)->condition_emit(out, ent, arc); + errors += (*cur)->condition_emit(out, ent, scope); out << ") begin" << endl; - errors += (*cur)->statement_emit(out, ent, arc); + errors += (*cur)->statement_emit(out, ent, scope); } if (! else_.empty()) { @@ -59,7 +59,7 @@ int IfSequential::emit(ostream&out, Entity*ent, Architecture*arc) for (list::iterator cur = else_.begin() ; cur != else_.end() ; ++cur) - errors += (*cur)->emit(out, ent, arc); + errors += (*cur)->emit(out, ent, scope); } @@ -67,36 +67,36 @@ int IfSequential::emit(ostream&out, Entity*ent, Architecture*arc) return errors; } -int IfSequential::Elsif::condition_emit(ostream&out, Entity*ent, Architecture*arc) +int IfSequential::Elsif::condition_emit(ostream&out, Entity*ent, ScopeBase*scope) { - return cond_->emit(out, ent, arc); + return cond_->emit(out, ent, scope); } -int IfSequential::Elsif::statement_emit(ostream&out, Entity*ent, Architecture*arc) +int IfSequential::Elsif::statement_emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; for (list::iterator cur = if_.begin() ; cur != if_.end() ; ++cur) - errors += (*cur)->emit(out, ent, arc); + errors += (*cur)->emit(out, ent, scope); return errors; } -int ReturnStmt::emit(ostream&out, Entity*ent, Architecture*arc) +int ReturnStmt::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; out << "return "; - errors += val_->emit(out, ent, arc); + errors += val_->emit(out, ent, scope); out << ";" << endl; return errors; } -int SignalSeqAssignment::emit(ostream&out, Entity*ent, Architecture*arc) +int SignalSeqAssignment::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; - errors += lval_->emit(out, ent, arc); + errors += lval_->emit(out, ent, scope); if (waveform_.size() != 1) { out << "/* Confusing waveform? */;" << endl; @@ -105,27 +105,27 @@ int SignalSeqAssignment::emit(ostream&out, Entity*ent, Architecture*arc) } else { Expression*tmp = waveform_.front(); out << " <= "; - errors += tmp->emit(out, ent, arc); + errors += tmp->emit(out, ent, scope); out << ";" << endl; } return errors; } -int VariableSeqAssignment::emit(ostream&out, Entity*ent, Architecture*arc) +int VariableSeqAssignment::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; - errors += lval_->emit(out, ent, arc); + errors += lval_->emit(out, ent, scope); out << " = "; - errors += rval_->emit(out, ent, arc); + errors += rval_->emit(out, ent, scope); out << ";" << endl; return errors; } -int ProcedureCall::emit(ostream&out, Entity*, Architecture*) +int ProcedureCall::emit(ostream&out, Entity*, ScopeBase*) { out << " // " << get_fileline() << ": internal error: " << "I don't know how to emit this sequential statement! " @@ -133,29 +133,29 @@ int ProcedureCall::emit(ostream&out, Entity*, Architecture*) return 1; } -int LoopStatement::emit_substatements(ostream&out, Entity*ent, Architecture*arc) +int LoopStatement::emit_substatements(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; for (list::iterator cur = stmts_.begin() ; cur != stmts_.end() ; ++cur) { SequentialStmt*tmp = *cur; - errors += tmp->emit(out, ent, arc); + errors += tmp->emit(out, ent, scope); } return errors; } -int CaseSeqStmt::emit(ostream&out, Entity*ent, Architecture*arc) +int CaseSeqStmt::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; out << "case ("; - errors += cond_->emit(out, ent, arc); + errors += cond_->emit(out, ent, scope); out << ")" << endl; for (list::iterator cur = alt_.begin() ; cur != alt_.end() ; ++cur) { CaseStmtAlternative*curp = *cur; - errors += curp ->emit(out, ent, arc); + errors += curp ->emit(out, ent, scope); } out << "endcase" << endl; @@ -163,12 +163,12 @@ int CaseSeqStmt::emit(ostream&out, Entity*ent, Architecture*arc) return errors; } -int CaseSeqStmt::CaseStmtAlternative::emit(ostream&out, Entity*ent, Architecture*arc) +int CaseSeqStmt::CaseStmtAlternative::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; if (exp_) { - errors += exp_->emit(out, ent, arc); + errors += exp_->emit(out, ent, scope); out << ":" << endl; } else { out << "default:" << endl; @@ -182,14 +182,14 @@ int CaseSeqStmt::CaseStmtAlternative::emit(ostream&out, Entity*ent, Architecture break; case 1: curp = stmts_.front(); - errors += curp->emit(out, ent, arc); + errors += curp->emit(out, ent, scope); break; default: out << "begin" << endl; for (list::iterator cur = stmts_.begin() ; cur != stmts_.end() ; ++cur) { curp = *cur; - errors += curp->emit(out, ent, arc); + errors += curp->emit(out, ent, scope); } out << "end" << endl; break; @@ -198,16 +198,16 @@ int CaseSeqStmt::CaseStmtAlternative::emit(ostream&out, Entity*ent, Architecture return errors; } -int ForLoopStatement::emit(ostream&out, Entity*ent, Architecture*arc) +int ForLoopStatement::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; ivl_assert(*this, range_); int64_t start_val; - bool start_rc = range_->msb()->evaluate(ent, arc, start_val); + bool start_rc = range_->msb()->evaluate(ent, scope, start_val); int64_t finish_val; - bool finish_rc = range_->lsb()->evaluate(ent, arc, finish_val); + bool finish_rc = range_->lsb()->evaluate(ent, scope, finish_val); perm_string scope_name = loop_name(); if (scope_name.nil()) { @@ -222,7 +222,7 @@ int ForLoopStatement::emit(ostream&out, Entity*ent, Architecture*arc) if(!start_rc || !finish_rc) { // Could not evaluate one of the loop boundaries, it has to be // determined during the run-time - errors += emit_runtime_(out, ent, arc); + errors += emit_runtime_(out, ent, scope); } else { bool dir = range_->is_downto(); @@ -271,7 +271,7 @@ int ForLoopStatement::emit(ostream&out, Entity*ent, Architecture*arc) out << " begin" << endl; - errors += emit_substatements(out, ent, arc); + errors += emit_substatements(out, ent, scope); out << "end" << endl; out << "end /* " << scope_name << " */" << endl; @@ -279,32 +279,32 @@ int ForLoopStatement::emit(ostream&out, Entity*ent, Architecture*arc) return errors; } -int ForLoopStatement::emit_runtime_(ostream&out, Entity*ent, Architecture*arc) +int ForLoopStatement::emit_runtime_(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; out << "for (\\" << it_ << " = "; - errors += range_->expr_left()->emit(out, ent, arc); + errors += range_->expr_left()->emit(out, ent, scope); // Twisted way of determining the loop direction at runtime out << " ;\n("; - errors += range_->expr_left()->emit(out, ent, arc); + errors += range_->expr_left()->emit(out, ent, scope); out << " < "; - errors += range_->expr_right()->emit(out, ent, arc); + errors += range_->expr_right()->emit(out, ent, scope); out << " ? \\" << it_ << " <= "; - errors += range_->expr_right()->emit(out, ent, arc); + errors += range_->expr_right()->emit(out, ent, scope); out << " : \\" << it_ << " >= "; - errors += range_->expr_right()->emit(out, ent, arc); + errors += range_->expr_right()->emit(out, ent, scope); out << ");\n\\" << it_ << " = \\" << it_ << " + ("; - errors += range_->expr_left()->emit(out, ent, arc); + errors += range_->expr_left()->emit(out, ent, scope); out << " < "; - errors += range_->expr_right()->emit(out, ent, arc); + errors += range_->expr_right()->emit(out, ent, scope); out << " ? 1 : -1))"; return errors; } -int WhileLoopStatement::emit(ostream&out, Entity*, Architecture*) +int WhileLoopStatement::emit(ostream&out, Entity*, ScopeBase*) { out << " // " << get_fileline() << ": internal error: " << "I don't know how to emit this sequential statement! " @@ -312,7 +312,7 @@ int WhileLoopStatement::emit(ostream&out, Entity*, Architecture*) return 1; } -int BasicLoopStatement::emit(ostream&out, Entity*, Architecture*) +int BasicLoopStatement::emit(ostream&out, Entity*, ScopeBase*) { out << " // " << get_fileline() << ": internal error: " << "I don't know how to emit this sequential statement! " diff --git a/vhdlpp/subprogram.h b/vhdlpp/subprogram.h index 8570da82e..2eab8f59c 100644 --- a/vhdlpp/subprogram.h +++ b/vhdlpp/subprogram.h @@ -54,7 +54,7 @@ class Subprogram : public LineInfo, public ScopeBase { const VType*peek_param_type(int idx) const; const VType*peek_return_type() const { return return_type_; } - int emit(ostream&out, Entity*ent, Architecture*arc); + int emit(ostream&out, Entity*ent, ScopeBase*scope); // Emit a definition as it would show up in a package. int emit_package(std::ostream&fd) const; diff --git a/vhdlpp/subprogram_emit.cc b/vhdlpp/subprogram_emit.cc index 6f1b37508..5cb43e3a6 100644 --- a/vhdlpp/subprogram_emit.cc +++ b/vhdlpp/subprogram_emit.cc @@ -70,7 +70,7 @@ int Subprogram::emit_package(ostream&fd) const if (statements_) { for (list::const_iterator cur = statements_->begin() ; cur != statements_->end() ; ++cur) { - errors += (*cur)->emit(fd, NULL, NULL); + errors += (*cur)->emit(fd, NULL, const_cast(this)); } } else { fd << " begin /* empty body */ end" << endl; diff --git a/vhdlpp/vsignal.cc b/vhdlpp/vsignal.cc index 14c6f9420..3f5baa706 100644 --- a/vhdlpp/vsignal.cc +++ b/vhdlpp/vsignal.cc @@ -34,10 +34,10 @@ SigVarBase::~SigVarBase() { } -void SigVarBase::elaborate_init_expr(Entity*ent, Architecture*arc) +void SigVarBase::elaborate_init_expr(Entity*ent, ScopeBase*scope) { if(init_expr_) { - init_expr_->elaborate_expr(ent, arc, peek_type()); + init_expr_->elaborate_expr(ent, scope, peek_type()); } } @@ -46,7 +46,7 @@ void SigVarBase::type_elaborate_(VType::decl_t&decl) decl.type = type_; } -int Signal::emit(ostream&out, Entity*ent, Architecture*arc) +int Signal::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; @@ -59,13 +59,13 @@ int Signal::emit(ostream&out, Entity*ent, Architecture*arc) Expression*init_expr = peek_init_expr(); if (init_expr) { out << " = "; - init_expr->emit(out, ent, arc); + init_expr->emit(out, ent, scope); } out << ";" << endl; return errors; } -int Variable::emit(ostream&out, Entity*, Architecture*) +int Variable::emit(ostream&out, Entity*, ScopeBase*) { int errors = 0; diff --git a/vhdlpp/vsignal.h b/vhdlpp/vsignal.h index ab560470d..9d1464560 100644 --- a/vhdlpp/vsignal.h +++ b/vhdlpp/vsignal.h @@ -24,6 +24,7 @@ # include "vtype.h" class Architecture; +class ScopeBase; class Entity; class Expression; @@ -42,7 +43,7 @@ class SigVarBase : public LineInfo { void dump(ostream&out, int indent = 0) const; // Elaborates initializer expressions if needed. - void elaborate_init_expr(Entity*ent, Architecture*arc); + void elaborate_init_expr(Entity*ent, ScopeBase*scope); perm_string peek_name() const { return name_; } @@ -70,7 +71,7 @@ class Signal : public SigVarBase { public: Signal(perm_string name, const VType*type, Expression*init_expr); - int emit(ostream&out, Entity*ent, Architecture*arc); + int emit(ostream&out, Entity*ent, ScopeBase*scope); }; class Variable : public SigVarBase { @@ -78,7 +79,7 @@ class Variable : public SigVarBase { public: Variable(perm_string name, const VType*type); - int emit(ostream&out, Entity*ent, Architecture*arc); + int emit(ostream&out, Entity*ent, ScopeBase*scope); }; inline void SigVarBase::count_ref_sequ() diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index eb6c10553..b417cbafb 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -30,6 +30,7 @@ # include "StringHeap.h" class Architecture; +class ScopeBase; class Entity; class Expression; class prange_t; @@ -52,7 +53,7 @@ class VType { // This is rarely used, but some types may have expressions // that need to be elaborated. - virtual int elaborate(Entity*end, Architecture*arc) const; + virtual int elaborate(Entity*end, ScopeBase*scope) const; // This virtual method returns true if that is equivalent to // this type. This method is used for example to compare @@ -205,7 +206,7 @@ class VTypeArray : public VType { VTypeArray(const VType*etype, std::list*r, bool signed_vector =false); ~VTypeArray(); - int elaborate(Entity*ent, Architecture*arc) const; + int elaborate(Entity*ent, ScopeBase*scope) const; void write_to_stream(std::ostream&fd) const; void write_type_to_stream(std::ostream&fd) const; void show(std::ostream&) const; diff --git a/vhdlpp/vtype_elaborate.cc b/vhdlpp/vtype_elaborate.cc index f3611d9f4..b3b4cfd9d 100644 --- a/vhdlpp/vtype_elaborate.cc +++ b/vhdlpp/vtype_elaborate.cc @@ -21,24 +21,24 @@ # include "vtype.h" # include "expression.h" -int VType::elaborate(Entity*, Architecture*) const +int VType::elaborate(Entity*, ScopeBase*) const { return 0; } -int VTypeArray::elaborate(Entity*ent, Architecture*arc) const +int VTypeArray::elaborate(Entity*ent, ScopeBase*scope) const { int errors = 0; - etype_->elaborate(ent, arc); + etype_->elaborate(ent, scope); for (vector::const_iterator cur = ranges_.begin() ; cur != ranges_.end() ; ++ cur) { Expression*tmp = cur->msb(); - if (tmp) errors += tmp->elaborate_expr(ent, arc, 0); + if (tmp) errors += tmp->elaborate_expr(ent, scope, 0); tmp = cur->lsb(); - if (tmp) errors += tmp->elaborate_expr(ent, arc, 0); + if (tmp) errors += tmp->elaborate_expr(ent, scope, 0); } return errors; From abbcea64d0bca09b8e3f9c6d25e7c20e7b26ba55 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 26 Jan 2015 17:09:00 +0100 Subject: [PATCH 28/41] vhdlpp: Array attributes can be evaluated in packages/functions. --- vhdlpp/expression_evaluate.cc | 55 ++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/vhdlpp/expression_evaluate.cc b/vhdlpp/expression_evaluate.cc index 90cc39ebc..d53c707f3 100644 --- a/vhdlpp/expression_evaluate.cc +++ b/vhdlpp/expression_evaluate.cc @@ -1,5 +1,7 @@ /* * Copyright (c) 2011-2013 Stephen Williams (steve@icarus.com) + * Copyright CERN 2015 + * @author Maciej Suminski (maciej.suminski@cern.ch) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -76,18 +78,31 @@ bool ExpArithmetic::evaluate(ScopeBase*scope, int64_t&val) const return true; } -bool ExpAttribute::evaluate(ScopeBase*, int64_t&val) const +bool ExpAttribute::evaluate(ScopeBase*scope, int64_t&val) const { - /* Special Case: The length attribute can be calculated all + /* Special Case: The array attributes can sometimes be calculated all the down to a literal integer at compile time, and all it needs is the type of the base expression. (The base expression doesn't even need to be evaluated.) */ - if (name_ == "length") { + if (name_ == "length" || name_ == "right" || name_ == "left") { const VType*base_type = base_->peek_type(); - //if (base_type == 0) - // base_type = base_->probe_type(ent,arc); - ivl_assert(*this, base_type); + if(!base_type) { + const ExpName*name = NULL; + + if(scope && (name = dynamic_cast(base_))) { + const perm_string& n = name->peek_name(); + if(const Variable*var = scope->find_variable(n)) + base_type = var->peek_type(); + else if(const Signal*sig = scope->find_signal(n)) + base_type = sig->peek_type(); + else if(const InterfacePort*port = scope->find_param(n)) + base_type = port->type; + } + } + + if(!base_type) + return false; // I tried really hard, sorry const VTypeArray*arr = dynamic_cast(base_type); if (arr == 0) { @@ -97,13 +112,27 @@ bool ExpAttribute::evaluate(ScopeBase*, int64_t&val) const return false; } - int64_t size = 1; - for (size_t idx = 0 ; idx < arr->dimensions() ; idx += 1) { - const VTypeArray::range_t&dim = arr->dimension(idx); - ivl_assert(*this, ! dim.is_box()); - size *= 1 + labs(dim.msb() - dim.lsb()); - } - val = size; + if(name_ == "length") { + int64_t size = 1; + for (size_t idx = 0 ; idx < arr->dimensions() ; idx += 1) { + const VTypeArray::range_t&dim = arr->dimension(idx); + int64_t msb_val, lsb_val; + + if(dim.is_box()) + return false; + + dim.msb()->evaluate(scope, msb_val); + dim.lsb()->evaluate(scope, lsb_val); + + size *= 1 + labs(msb_val - lsb_val); + } + val = size; + } else if(name_ == "left") { + arr->dimension(0).msb()->evaluate(scope, val); + } else if(name_ == "right") { + arr->dimension(0).lsb()->evaluate(scope, val); + } else ivl_assert(*this, false); + return true; } From 48265ecd9b23be3cc7997b83a9a44730786eb162 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 26 Jan 2015 17:51:42 +0100 Subject: [PATCH 29/41] vhdlpp: Subprograms return types have their ranges evaluated if possible. Added VTypeArray::evaluate_ranges() method. --- vhdlpp/subprogram.cc | 8 +++++++- vhdlpp/vtype.cc | 13 +++++++++++++ vhdlpp/vtype.h | 4 ++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/vhdlpp/subprogram.cc b/vhdlpp/subprogram.cc index bfa1be9a7..a6bd8f63f 100644 --- a/vhdlpp/subprogram.cc +++ b/vhdlpp/subprogram.cc @@ -268,8 +268,14 @@ bool Subprogram::fixed_return_type(void) (*s)->visit(r); } - const VType*return_type = r.get_type(); + VType*return_type = const_cast(r.get_type()); if(return_type && !return_type->is_unbounded()) { + // Let's check if the variable length can be evaluated without any scope. + // If not, then it is depends on information about e.g. function params + if(return_type->is_variable_length(NULL)) { + if(VTypeArray*arr = dynamic_cast(return_type)) + arr->evaluate_ranges(this); + } return_type_ = return_type; return true; } else { diff --git a/vhdlpp/vtype.cc b/vhdlpp/vtype.cc index cd4ea42e1..3f2368b5f 100644 --- a/vhdlpp/vtype.cc +++ b/vhdlpp/vtype.cc @@ -186,6 +186,19 @@ bool VTypeArray::is_variable_length(ScopeBase*scope) const { return etype_->is_variable_length(scope); } +void VTypeArray::evaluate_ranges(ScopeBase*scope) { + for(std::vector::iterator it = ranges_.begin(); it != ranges_.end(); ++it ) { + int64_t lsb_val = -1, msb_val = -1; + bool dir = it->is_downto(); + + if(it->msb()->evaluate(scope, msb_val) && it->lsb()->evaluate(scope, lsb_val)) { + assert(lsb_val >= 0); + assert(msb_val >= 0); + *it = range_t(new ExpInteger(msb_val), new ExpInteger(lsb_val), dir); + } + } +} + VTypeRange::VTypeRange(const VType*base, int64_t max_val, int64_t min_val) : base_(base) { diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index b417cbafb..0e602d5ec 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -238,6 +238,10 @@ class VTypeArray : public VType { // To handle subtypes inline void set_parent_type(const VTypeArray*parent) { parent_ = parent; } + // Wherever it is possible, replaces range lsb & msb expressions with + // constant integers. + void evaluate_ranges(ScopeBase*scope); + private: int emit_with_dims_(std::ostream&out, bool packed, perm_string name) const; From 51ce9f1a60b7ca5419e38f6c445c7d22ddcf14dd Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 27 Jan 2015 11:00:32 +0100 Subject: [PATCH 30/41] vhdlpp: Minor correction for casting to integer. --- vhdlpp/expression.h | 2 +- vhdlpp/expression_emit.cc | 9 ++------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 6f2d2b4fe..443332e85 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -501,7 +501,7 @@ class ExpInteger : public Expression { void write_to_stream(std::ostream&fd); int emit(ostream&out, Entity*ent, ScopeBase*scope); int emit_package(std::ostream&out); - bool is_primary(void) const; + bool is_primary(void) const { return true; } bool evaluate(ScopeBase*scope, int64_t&val) const; void dump(ostream&out, int indent = 0) const; virtual ostream& dump_inline(ostream&out) const; diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index 04b4d21a3..bf5d47e92 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -562,9 +562,9 @@ int ExpFunc::emit(ostream&out, Entity*ent, ScopeBase*scope) out << ")"; } else if (name_ == "integer" && argv_.size() == 1) { - // Simply skip the function name, SystemVerilog takes care of - // rounding real numbers + out << "$signed("; errors += argv_[0]->emit(out, ent, scope); + out << ")"; } else if (name_ == "std_logic_vector" && argv_.size() == 1) { // Special case: The std_logic_vector function casts its @@ -635,11 +635,6 @@ int ExpInteger::emit_package(ostream&out) return 0; } -bool ExpInteger::is_primary(void) const -{ - return true; -} - int ExpReal::emit(ostream&out, Entity*, ScopeBase*) { out << value_; From 60077f4f060dea11929f91f8d88105039a4749b2 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 27 Jan 2015 16:30:56 +0100 Subject: [PATCH 31/41] vhdlpp: ExpBitstring elaborate_expr(). --- vhdlpp/expression_elaborate.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index 70fedaca4..b27deeff3 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -594,6 +594,10 @@ const VType*ExpBitstring::fit_type(Entity*, ScopeBase*, const VTypeArray*atype) int ExpBitstring::elaborate_expr(Entity*, ScopeBase*, const VType*) { int errors = 0; + std::vector range; + range.push_back(VTypeArray::range_t(new ExpInteger(value_.size() - 1), new ExpInteger(0))); + const VTypeArray*type = new VTypeArray(&primitive_STDLOGIC, range); + set_type(type); return errors; } From 8a854affa6f61c51db1afbc885a3d828d83ab81c Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 2 Feb 2015 11:00:59 +0100 Subject: [PATCH 32/41] vhdlpp: Clone routines for Expression & VType classes. --- vhdlpp/expression.cc | 93 ++++++++++++++++++++++++++++++++++++++++++++ vhdlpp/expression.h | 85 +++++++++++++++++++++++++++++++++++++--- vhdlpp/parse_types.h | 4 +- vhdlpp/vtype.cc | 18 ++++++++- vhdlpp/vtype.h | 20 +++++++++- 5 files changed, 211 insertions(+), 9 deletions(-) diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index 8127d90e4..e8c71ee12 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -64,6 +64,11 @@ ExpAttribute::~ExpAttribute() delete base_; } +Expression*ExpAttribute::clone() const +{ + return new ExpAttribute(static_cast(base_->clone()), name_); +} + ExpBinary::ExpBinary(Expression*op1, Expression*op2) : operand1_(op1), operand2_(op2) { @@ -113,6 +118,23 @@ ExpAggregate::~ExpAggregate() delete elements_[idx]; } +Expression* ExpAggregate::clone() const +{ + std::list*new_elements = NULL; + + if(!elements_.empty()) { + new_elements = new std::list(); + for(std::vector::const_iterator it = elements_.begin(); + it != elements_.end(); ++it) { + new_elements->push_back(new element_t(**it)); + } + } + + assert(aggregate_.empty()); // cloning should not happen after elab + + return new ExpAggregate(new_elements); +} + ExpAggregate::choice_t::choice_t(Expression*exp) : expr_(exp) { @@ -127,6 +149,15 @@ ExpAggregate::choice_t::choice_t(prange_t*rang) { } +ExpAggregate::choice_t::choice_t(const choice_t&other) +{ + if(Expression*e = other.expr_.get()) + expr_.reset(e->clone()); + + if(other.range_.get()) + range_.reset(new prange_t(*other.range_.get())); +} + ExpAggregate::choice_t::~choice_t() { } @@ -160,6 +191,18 @@ ExpAggregate::element_t::element_t(list*fields, Expression*val) } } +ExpAggregate::element_t::element_t(const ExpAggregate::element_t&other) +{ + fields_.reserve(other.fields_.size()); + + for(std::vector::const_iterator it = other.fields_.begin(); + it != other.fields_.end(); ++it) { + fields_.push_back(*it); + } + + val_ = other.val_->clone(); +} + ExpAggregate::element_t::~element_t() { for (size_t idx = 0 ; idx < fields_.size() ; idx += 1) @@ -236,12 +279,46 @@ ExpConditional::~ExpConditional() } } +Expression*ExpConditional::clone() const +{ + std::list*new_true_clause = NULL; + if(!true_clause_.empty()) { + new_true_clause = new std::list(); + + for(std::list::const_iterator it = true_clause_.begin(); + it != true_clause_.end(); ++it) { + new_true_clause->push_back((*it)->clone()); + } + } + + std::list*new_else_clause = NULL; + if(!else_clause_.empty()) { + new_else_clause = new std::list(); + + for(std::list::const_iterator it = else_clause_.begin(); + it != else_clause_.end(); ++it) { + new_else_clause->push_back(new else_t(**it)); + } + } + + return new ExpConditional(cond_->clone(), new_true_clause, new_else_clause); +} + ExpConditional::else_t::else_t(Expression*cond, std::list*tru) : cond_(cond) { if (tru) true_clause_.splice(true_clause_.end(), *tru); } +ExpConditional::else_t::else_t(const else_t&other) +{ + cond_ = other.cond_->clone(); + for(std::list::const_iterator it = other.true_clause_.begin(); + it != other.true_clause_.end(); ++it) { + true_clause_.push_back((*it)->clone()); + } +} + ExpConditional::else_t::~else_t() { delete cond_; @@ -284,6 +361,22 @@ ExpFunc::~ExpFunc() delete argv_[idx]; } +Expression*ExpFunc::clone() const { + std::list*new_args = NULL; + + if(!argv_.empty()) { + new_args = new std::list(); + for(std::vector::const_iterator it = argv_.begin(); + it != argv_.end(); ++it) + new_args->push_back((*it)->clone()); + } + + ExpFunc*f = new ExpFunc(name_, new_args); + f->def_ = def_; + + return f; +} + const VType* ExpFunc::func_ret_type() const { return def_ ? def_->peek_return_type() : NULL; diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 443332e85..15983a25d 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -36,7 +36,6 @@ class Subprogram; class VType; class VTypeArray; class VTypePrimitive; - class ExpName; /* @@ -50,6 +49,9 @@ class Expression : public LineInfo { Expression(); virtual ~Expression() =0; + // Returns a deep copy of the expression. + virtual Expression*clone() const =0; + // This virtual method handles the special case of elaborating // an expression that is the l-value of a sequential variable // assignment. This generates an error for most cases, but @@ -133,6 +135,13 @@ class Expression : public LineInfo { Expression& operator = (const Expression&); }; +/* + * Checks before cloning if the other expression actually exists (!=NULL). + */ +static inline Expression*safe_clone(const Expression*other) { + return (other ? other->clone() : NULL); +} + static inline void FILE_NAME(Expression*tgt, const LineInfo*src) { tgt->set_line(*src); @@ -149,6 +158,8 @@ class ExpUnary : public Expression { ExpUnary(Expression*op1); virtual ~ExpUnary() =0; + inline const Expression*peek_operand() const { return operand1_; } + const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const; protected: @@ -172,8 +183,8 @@ class ExpBinary : public Expression { ExpBinary(Expression*op1, Expression*op2); virtual ~ExpBinary() =0; - const Expression* peek_operand1(void) const { return operand1_; } - const Expression* peek_operand2(void) const { return operand2_; } + inline const Expression* peek_operand1(void) const { return operand1_; } + inline const Expression* peek_operand2(void) const { return operand2_; } const VType*probe_type(Entity*ent, ScopeBase*scope) const; @@ -218,6 +229,9 @@ class ExpAggregate : public Expression { explicit choice_t(perm_string name); // discreate_range choice explicit choice_t(prange_t*ran); + + choice_t(const choice_t&other); + ~choice_t(); // true if this represents an "others" choice @@ -234,11 +248,17 @@ class ExpAggregate : public Expression { std::auto_ptrexpr_; std::auto_ptr range_; private: // not implemented - choice_t(const choice_t&); choice_t& operator= (const choice_t&); }; struct choice_element { + choice_element() : choice(), expr() {} + + choice_element(const choice_element&other) { + choice = other.choice ? new choice_t(*other.choice) : NULL; + expr = safe_clone(other.expr); + } + choice_t*choice; Expression*expr; bool alias_flag; @@ -250,6 +270,7 @@ class ExpAggregate : public Expression { class element_t { public: explicit element_t(std::list*fields, Expression*val); + element_t(const element_t&other); ~element_t(); size_t count_choices() const { return fields_.size(); } @@ -264,7 +285,6 @@ class ExpAggregate : public Expression { std::vectorfields_; Expression*val_; private: // not implemented - element_t(const element_t&); element_t& operator = (const element_t&); }; @@ -272,6 +292,7 @@ class ExpAggregate : public Expression { ExpAggregate(std::list*el); ~ExpAggregate(); + Expression*clone() const; const VType*probe_type(Entity*ent, ScopeBase*scope) const; const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const; @@ -304,6 +325,10 @@ class ExpArithmetic : public ExpBinary { ExpArithmetic(ExpArithmetic::fun_t op, Expression*op1, Expression*op2); ~ExpArithmetic(); + Expression*clone() const { + return new ExpArithmetic(fun_, peek_operand1()->clone(), peek_operand2()->clone()); + } + int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); void write_to_stream(std::ostream&fd); int emit(ostream&out, Entity*ent, ScopeBase*scope); @@ -323,6 +348,8 @@ class ExpAttribute : public Expression { ExpAttribute(ExpName*base, perm_string name); ~ExpAttribute(); + Expression*clone() const; + inline perm_string peek_attribute() const { return name_; } inline const ExpName* peek_base() const { return base_; } @@ -344,8 +371,11 @@ class ExpBitstring : public Expression { public: explicit ExpBitstring(const char*); + ExpBitstring(const ExpBitstring&other) : Expression() { value_ = other.value_; } ~ExpBitstring(); + Expression*clone() const { return new ExpBitstring(*this); } + const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const; int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); void write_to_stream(std::ostream&fd); @@ -361,8 +391,11 @@ class ExpCharacter : public Expression { public: ExpCharacter(char val); + ExpCharacter(const ExpCharacter&other) : Expression() { value_ = other.value_; } ~ExpCharacter(); + Expression*clone() const { return new ExpCharacter(*this); } + const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const; int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); void write_to_stream(std::ostream&fd); @@ -386,6 +419,10 @@ class ExpConcat : public Expression { ExpConcat(Expression*op1, Expression*op2); ~ExpConcat(); + Expression*clone() const { + return new ExpConcat(operand1_->clone(), operand2_->clone()); + } + const VType*probe_type(Entity*ent, ScopeBase*scope) const; const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const; int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); @@ -414,6 +451,7 @@ class ExpConditional : public Expression { class else_t : public LineInfo { public: else_t(Expression*cond, std::list*tru); + else_t(const else_t&other); ~else_t(); int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*lt); @@ -431,6 +469,8 @@ class ExpConditional : public Expression { std::list*fal); ~ExpConditional(); + Expression*clone() const; + const VType*probe_type(Entity*ent, ScopeBase*scope) const; int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); void write_to_stream(std::ostream&fd); @@ -456,6 +496,8 @@ class ExpEdge : public ExpUnary { explicit ExpEdge(ExpEdge::fun_t ty, Expression*op); ~ExpEdge(); + Expression*clone() const { return new ExpEdge(fun_, peek_operand()->clone()); } + inline fun_t edge_fun() const { return fun_; } void write_to_stream(std::ostream&fd); @@ -473,6 +515,8 @@ class ExpFunc : public Expression { ExpFunc(perm_string nn, std::list*args); ~ExpFunc(); + Expression*clone() const; + inline perm_string func_name() const { return name_; } inline size_t func_args() const { return argv_.size(); } inline const Expression*func_arg(size_t idx) const { return argv_[idx]; } @@ -494,8 +538,11 @@ class ExpInteger : public Expression { public: ExpInteger(int64_t val); + ExpInteger(const ExpInteger&other) : Expression(), value_(other.value_) {} ~ExpInteger(); + Expression*clone() const { return new ExpInteger(*this); } + const VType*probe_type(Entity*ent, ScopeBase*scope) const; int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); void write_to_stream(std::ostream&fd); @@ -514,8 +561,11 @@ class ExpReal : public Expression { public: ExpReal(double val); + ExpReal(const ExpReal&other) : Expression(), value_(other.value_) {} ~ExpReal(); + Expression*clone() const { return new ExpReal(*this); } + const VType*probe_type(Entity*ent, ScopeBase*scope) const; int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); void write_to_stream(std::ostream&fd); @@ -538,6 +588,10 @@ class ExpLogical : public ExpBinary { ExpLogical(ExpLogical::fun_t ty, Expression*op1, Expression*op2); ~ExpLogical(); + Expression*clone() const { + return new ExpLogical(fun_, peek_operand1()->clone(), peek_operand2()->clone()); + } + inline fun_t logic_fun() const { return fun_; } int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); @@ -565,6 +619,10 @@ class ExpName : public Expression { ~ExpName(); public: // Base methods + Expression*clone() const { + return new ExpName(static_cast(safe_clone(prefix_.get())), + name_, safe_clone(index_), safe_clone(lsb_)); + } int elaborate_lval(Entity*ent, ScopeBase*scope, bool); int elaborate_rval(Entity*ent, ScopeBase*scope, const InterfacePort*); const VType* probe_type(Entity*ent, ScopeBase*scope) const; @@ -578,7 +636,7 @@ class ExpName : public Expression { bool symbolic_compare(const Expression*that) const; void dump(ostream&out, int indent = 0) const; const char* name() const; - inline perm_string peek_name() const { return name_; } + inline const perm_string& peek_name() const { return name_; } void set_range(Expression*msb, Expression*lsb); @@ -620,6 +678,10 @@ class ExpRelation : public ExpBinary { ExpRelation(ExpRelation::fun_t ty, Expression*op1, Expression*op2); ~ExpRelation(); + Expression*clone() const { + return new ExpRelation(fun_, peek_operand1()->clone(), peek_operand2()->clone()); + } + const VType* probe_type(Entity*ent, ScopeBase*scope) const; int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); void write_to_stream(std::ostream&fd); @@ -634,8 +696,11 @@ class ExpString : public Expression { public: explicit ExpString(const char*); + ExpString(const ExpString&other) : Expression(), value_(other.value_) {} ~ExpString(); + Expression*clone() const { return new ExpString(*this); } + const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const; int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); void write_to_stream(std::ostream&fd); @@ -657,6 +722,8 @@ class ExpUAbs : public ExpUnary { ExpUAbs(Expression*op1); ~ExpUAbs(); + Expression*clone() const { return new ExpUAbs(peek_operand()->clone()); } + void write_to_stream(std::ostream&fd); int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; @@ -668,6 +735,8 @@ class ExpUNot : public ExpUnary { ExpUNot(Expression*op1); ~ExpUNot(); + Expression*clone() const { return new ExpUNot(peek_operand()->clone()); } + int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); void write_to_stream(std::ostream&fd); int emit(ostream&out, Entity*ent, ScopeBase*scope); @@ -683,6 +752,8 @@ class ExpCast : public Expression { ExpCast(Expression*base, const VType*type); ~ExpCast(); + Expression*clone() const { return new ExpCast(base_->clone(), type_->clone()); } + inline int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*) { return base_->elaborate_expr(ent, scope, type_); } @@ -705,6 +776,8 @@ class ExpNew : public Expression { ExpNew(Expression*size); ~ExpNew(); + Expression*clone() const { return new ExpNew(size_->clone()); } + // There is no 'new' in VHDL - do not emit anything void write_to_stream(std::ostream&) {}; int emit(ostream&out, Entity*ent, ScopeBase*scope); diff --git a/vhdlpp/parse_types.h b/vhdlpp/parse_types.h index 625312762..3639a9c1f 100644 --- a/vhdlpp/parse_types.h +++ b/vhdlpp/parse_types.h @@ -72,6 +72,9 @@ class prange_t { public: prange_t(Expression* left, Expression* right, bool dir) : left_(left), right_(right), direction_(dir), auto_dir_(false) {} + prange_t(const prange_t&other) : + left_(other.left_->clone()), right_(other.right_->clone()), + direction_(other.direction_), auto_dir_(other.auto_dir_) {} ~prange_t() { delete left_; delete right_; } void dump(ostream&out, int indent) const; @@ -91,7 +94,6 @@ class prange_t { bool auto_dir_; private: //not implemented - prange_t(const prange_t&); prange_t operator=(const prange_t&); }; diff --git a/vhdlpp/vtype.cc b/vhdlpp/vtype.cc index 3f2368b5f..4a05d82aa 100644 --- a/vhdlpp/vtype.cc +++ b/vhdlpp/vtype.cc @@ -26,7 +26,6 @@ using namespace std; - VType::~VType() { } @@ -76,6 +75,11 @@ void VTypePrimitive::show(ostream&out) const } } +VTypeArray::range_t*VTypeArray::range_t::clone() const +{ + return new VTypeArray::range_t(safe_clone(msb_), safe_clone(lsb_), direction_); +} + VTypeArray::VTypeArray(const VType*element, const vector&r, bool sv) : etype_(element), ranges_(r), signed_flag_(sv), parent_(NULL) { @@ -106,6 +110,18 @@ VTypeArray::~VTypeArray() { } +VType*VTypeArray::clone() const { + std::vector new_ranges; + new_ranges.reserve(ranges_.size()); + for(std::vector::const_iterator it = ranges_.begin(); + it != ranges_.end(); ++it) { + new_ranges.push_back(*(it->clone())); + } + VTypeArray*a = new VTypeArray(etype_->clone(), new_ranges, signed_flag_); + a->set_parent_type(parent_); + return a; +} + const VType* VTypeArray::basic_type(bool typedef_allowed) const { const VType*t = etype_; diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index 0e602d5ec..595ca381c 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -51,6 +51,8 @@ class VType { VType() { } virtual ~VType() =0; + virtual VType*clone() const =0; + // This is rarely used, but some types may have expressions // that need to be elaborated. virtual int elaborate(Entity*end, ScopeBase*scope) const; @@ -136,6 +138,8 @@ extern void preload_global_types(void); * This type is a placeholder for ERROR types. */ class VTypeERROR : public VType { + VType*clone() const { return NULL; } + public: int emit_def(std::ostream&out, perm_string name) const; }; @@ -153,6 +157,8 @@ class VTypePrimitive : public VType { VTypePrimitive(type_t tt, bool packed = false); ~VTypePrimitive(); + VType*clone() const { return new VTypePrimitive(*this); } + void write_to_stream(std::ostream&fd) const; void show(std::ostream&) const; @@ -189,6 +195,8 @@ class VTypeArray : public VType { range_t(Expression*m = NULL, Expression*l = NULL, bool dir = true) : msb_(m), lsb_(l), direction_(dir) { } + range_t*clone() const; + inline bool is_box() const { return msb_==0 && lsb_==0; } inline bool is_downto() const { return direction_; } @@ -206,6 +214,8 @@ class VTypeArray : public VType { VTypeArray(const VType*etype, std::list*r, bool signed_vector =false); ~VTypeArray(); + VType*clone() const; + int elaborate(Entity*ent, ScopeBase*scope) const; void write_to_stream(std::ostream&fd) const; void write_type_to_stream(std::ostream&fd) const; @@ -246,8 +256,8 @@ class VTypeArray : public VType { int emit_with_dims_(std::ostream&out, bool packed, perm_string name) const; void write_range_to_stream_(std::ostream&fd) const; - const VType*etype_; + const VType*etype_; std::vector ranges_; bool signed_flag_; const VTypeArray*parent_; @@ -259,6 +269,8 @@ class VTypeRange : public VType { VTypeRange(const VType*base, int64_t max_val, int64_t min_val); ~VTypeRange(); + VType*clone() const { return new VTypeRange(base_->clone(), max_, min_); } + // Get the type that is limited by the range. inline const VType* base_type() const { return base_; } @@ -277,6 +289,8 @@ class VTypeEnum : public VType { VTypeEnum(const std::list*names); ~VTypeEnum(); + VType*clone() const { return new VTypeEnum(*this); } + void write_to_stream(std::ostream&fd) const; void show(std::ostream&) const; int emit_def(std::ostream&out, perm_string name) const; @@ -310,6 +324,8 @@ class VTypeRecord : public VType { explicit VTypeRecord(std::list*elements); ~VTypeRecord(); + VType*clone() const { return new VTypeRecord(*this); } + void write_to_stream(std::ostream&fd) const; void show(std::ostream&) const; int emit_def(std::ostream&out, perm_string name) const; @@ -328,6 +344,8 @@ class VTypeDef : public VType { explicit VTypeDef(perm_string name, const VType*is); ~VTypeDef(); + VType*clone() const { return new VTypeDef(*this); } + inline perm_string peek_name() const { return name_; } // If the type is not given a definition in the constructor, From 1a367c84b61e9f5d0f7e5ac85250163bd9777444 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 2 Feb 2015 11:50:50 +0100 Subject: [PATCH 33/41] vhdlpp: Subprograms can have instances that take a different set of parameter types. --- vhdlpp/expression_elaborate.cc | 9 ++++- vhdlpp/scope.h | 7 ++++ vhdlpp/subprogram.cc | 69 +++++++++++++++++++--------------- vhdlpp/subprogram.h | 7 ++++ 4 files changed, 60 insertions(+), 32 deletions(-) diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index b27deeff3..256970085 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -757,6 +757,8 @@ int ExpFunc::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*) ivl_assert(*this, def_==0); def_ = prog; + bool new_instance = false; + // Elaborate arguments for (size_t idx = 0 ; idx < argv_.size() ; idx += 1) { const VType*tmp = argv_[idx]->probe_type(ent, scope); @@ -769,10 +771,15 @@ int ExpFunc::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*) // Type casting for unbounded arrays if(param_type && param_type->is_unbounded() /*&& !param_type->type_match(tmp)*/) { - argv_[idx] = new ExpCast(argv_[idx], get_global_typedef(param_type)); + new_instance = true; // we need a new instance } } + if(new_instance) { + def_ = prog->make_instance(argv_, scope); + name_ = def_->name(); + } + return errors; } diff --git a/vhdlpp/scope.h b/vhdlpp/scope.h index 8fd94b73e..6bb7ed4e5 100644 --- a/vhdlpp/scope.h +++ b/vhdlpp/scope.h @@ -62,6 +62,13 @@ class ScopeBase { // this one. After the transfer new_* maps are emptied in the another scope. void transfer_from(ScopeBase&ref); + inline void bind_subprogram(perm_string name, Subprogram*obj) + { map::iterator it; + if((it = use_subprograms_.find(name)) != use_subprograms_.end() ) + use_subprograms_.erase(it); + cur_subprograms_[name] = obj; + } + protected: void cleanup(); diff --git a/vhdlpp/subprogram.cc b/vhdlpp/subprogram.cc index a6bd8f63f..56d07a599 100644 --- a/vhdlpp/subprogram.cc +++ b/vhdlpp/subprogram.cc @@ -50,7 +50,6 @@ void Subprogram::set_program_body(list*stmt) { ivl_assert(*this, statements_==0); statements_ = stmt; - fix_variables(); fix_port_types(); } @@ -73,12 +72,6 @@ private: void Subprogram::fix_port_types() { // Check function parameters for unbounded vectors and possibly fix it. - if(ports_) { - for(std::list::iterator it = ports_->begin(); - it != ports_->end(); ++it) { - check_unb_vector((*it)->type); - } - } // Try to settle at a fixed width return type. if(fixed_return_type()) @@ -104,37 +97,16 @@ void Subprogram::fix_variables() { Variable*var = it->second; const VType*type = var->peek_type(); - // SystemVerilog does not handle variables that have length dependendent - // on other variables. We have to convert it to a dynamic array and - // construct it. if(type->is_variable_length(this)) { const VTypeArray*arr = dynamic_cast(type); // Currently we handle only one dimensional variables assert(arr->dimensions() == 1); - Expression*lsb = arr->dimension(0).lsb(); - Expression*msb = arr->dimension(0).msb(); - - // We cannot have dynamic arrays with custom range, - // it has to be [size-1:0] - int64_t lsb_val; - assert(lsb->evaluate(NULL, lsb_val) && lsb_val == 0); - //ExpArithmetic*size = new ExpArithmetic(ExpArithmetic::MINUS, msb, lsb); - // Because lsb_val == 0, we may simplify the size expression: - Expression*size = msb; - - // Prepare the construction statement - assert(statements_); - VariableSeqAssignment*init = new VariableSeqAssignment(new ExpName(var->peek_name()), - new ExpNew(size)); - statements_->push_front(init); - // Now substitute the variable type - std::vector new_range; - new_range.push_back(VTypeArray::range_t()); - VTypeArray*new_array = new VTypeArray(arr->element_type(), new_range); - it->second = new Variable(var->peek_name(), fix_logic_darray(new_array)); + VTypeArray*new_array = static_cast(arr->clone()); + new_array->evaluate_ranges(this); + it->second = new Variable(var->peek_name(), new_array); delete var; } } @@ -216,6 +188,41 @@ const VType*Subprogram::peek_param_type(int idx) const return (*p)->type; } +Subprogram*Subprogram::make_instance(std::vector arguments, ScopeBase*scope) { + assert(arguments.size() == ports_->size()); + + std::list*ports = new std::list; + int i = 0; + + // Change the argument types to match the ones that were used during + // the function call + for(std::list::iterator it = ports_->begin(); + it != ports_->end(); ++it) { + InterfacePort*p = new InterfacePort(**it); + p->type = arguments[i++]->peek_type()->clone(); + assert(p->type); + ports->push_back(p); + } + + char buf[80]; + snprintf(buf, sizeof(buf), "__%s_%p", name_.str(), ports); + perm_string new_name = lex_strings.make(buf); + Subprogram*instance = new Subprogram(new_name, ports, return_type_); + + // Copy variables + for(std::map::iterator it = new_variables_.begin(); + it != new_variables_.end(); ++it) { + Variable*v = new Variable(it->first, it->second->peek_type()->clone()); + instance->new_variables_[it->first] = v; + } + + instance->set_parent(scope); + instance->set_program_body(statements_); + scope->bind_subprogram(new_name, instance); + + return instance; +} + struct check_return_type : public SeqStmtVisitor { check_return_type(const Subprogram*subp) : subp_(subp), ret_type_(NULL) {} diff --git a/vhdlpp/subprogram.h b/vhdlpp/subprogram.h index 2eab8f59c..bba9c757f 100644 --- a/vhdlpp/subprogram.h +++ b/vhdlpp/subprogram.h @@ -45,6 +45,7 @@ class Subprogram : public LineInfo, public ScopeBase { inline const perm_string&name() const { return name_; } void set_program_body(std::list*statements); + inline bool empty_program_body() const { return !statements_ || statements_->empty(); } // Return true if the specification (name, types, ports) // matches this subprogram and that subprogram. @@ -62,6 +63,12 @@ class Subprogram : public LineInfo, public ScopeBase { void write_to_stream(std::ostream&fd) const; void dump(std::ostream&fd) const; + // Creates a new instance of the function that takes arguments of + // a different type. It is used to allow VHDL functions that work with + // unbounded std_logic_vectors, so there can be a separate instance + // for limited length logic vector. + Subprogram*make_instance(std::vector arguments, ScopeBase*scope); + private: // Tries to set the return type to a fixed type. VHDL functions that // return std_logic_vectors do not specify its length, as SystemVerilog From dae3410dcd933062563d4046db5b4be80cff644b Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 3 Feb 2015 14:28:18 +0100 Subject: [PATCH 34/41] vhdlpp: Variable::write_to_stream(). --- vhdlpp/vsignal.cc | 7 +++++++ vhdlpp/vsignal.h | 1 + 2 files changed, 8 insertions(+) diff --git a/vhdlpp/vsignal.cc b/vhdlpp/vsignal.cc index 3f5baa706..94bd8959b 100644 --- a/vhdlpp/vsignal.cc +++ b/vhdlpp/vsignal.cc @@ -77,3 +77,10 @@ int Variable::emit(ostream&out, Entity*, ScopeBase*) out << ";" << endl; return errors; } + +void Variable::write_to_stream(std::ostream&fd) +{ + fd << "variable " << peek_name() << " : "; + peek_type()->write_to_stream(fd); + fd << ";" << endl; +} diff --git a/vhdlpp/vsignal.h b/vhdlpp/vsignal.h index 9d1464560..d2bfdbcd0 100644 --- a/vhdlpp/vsignal.h +++ b/vhdlpp/vsignal.h @@ -80,6 +80,7 @@ class Variable : public SigVarBase { Variable(perm_string name, const VType*type); int emit(ostream&out, Entity*ent, ScopeBase*scope); + void write_to_stream(std::ostream&fd); }; inline void SigVarBase::count_ref_sequ() From 9de69f2f243da744d969046cd6c16ce62f59aa53 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 3 Feb 2015 14:30:48 +0100 Subject: [PATCH 35/41] vhdlpp: SequentialStmts write_to_stream() methods. --- vhdlpp/sequential.h | 14 +++- vhdlpp/sequential_emit.cc | 153 +++++++++++++++++++++++++++++++++----- 2 files changed, 147 insertions(+), 20 deletions(-) diff --git a/vhdlpp/sequential.h b/vhdlpp/sequential.h index d3229d9ff..06fff7b8d 100644 --- a/vhdlpp/sequential.h +++ b/vhdlpp/sequential.h @@ -45,6 +45,7 @@ class SequentialStmt : public LineInfo { virtual int elaborate(Entity*ent, ScopeBase*scope); virtual int emit(ostream&out, Entity*entity, ScopeBase*scope); virtual void dump(ostream&out, int indent) const; + virtual void write_to_stream(std::ostream&fd); // Recursively visits a tree of sequential statements. virtual void visit(SeqStmtVisitor& func) { func(this); } @@ -67,6 +68,7 @@ class LoopStatement : public SequentialStmt { protected: int elaborate_substatements(Entity*ent, ScopeBase*scope); int emit_substatements(std::ostream&out, Entity*ent, ScopeBase*scope); + void write_to_stream_substatements(ostream&fd); private: perm_string name_; @@ -85,6 +87,9 @@ class IfSequential : public SequentialStmt { int condition_emit(ostream&out, Entity*entity, ScopeBase*scope); int statement_emit(ostream&out, Entity*entity, ScopeBase*scope); + void condition_write_to_stream(ostream&fd); + void statement_write_to_stream(ostream&fd); + void dump(ostream&out, int indent) const; void visit(SeqStmtVisitor& func); @@ -105,6 +110,7 @@ class IfSequential : public SequentialStmt { public: int elaborate(Entity*ent, ScopeBase*scope); int emit(ostream&out, Entity*entity, ScopeBase*scope); + void write_to_stream(std::ostream&fd); void dump(ostream&out, int indent) const; void visit(SeqStmtVisitor& func); @@ -131,6 +137,7 @@ class ReturnStmt : public SequentialStmt { public: int emit(ostream&out, Entity*entity, ScopeBase*scope); + void write_to_stream(std::ostream&fd); void dump(ostream&out, int indent) const; const Expression*peek_expr() const { return val_; }; @@ -148,6 +155,7 @@ class SignalSeqAssignment : public SequentialStmt { public: int elaborate(Entity*ent, ScopeBase*scope); int emit(ostream&out, Entity*entity, ScopeBase*scope); + void write_to_stream(std::ostream&fd); void dump(ostream&out, int indent) const; private: @@ -165,6 +173,7 @@ class CaseSeqStmt : public SequentialStmt { int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); int elaborate(Entity*ent, ScopeBase*scope); int emit(ostream&out, Entity*entity, ScopeBase*scope); + void write_to_stream(std::ostream&fd); void visit(SeqStmtVisitor& func); private: @@ -183,6 +192,7 @@ class CaseSeqStmt : public SequentialStmt { void dump(ostream&out, int indent) const; int elaborate(Entity*ent, ScopeBase*scope); int emit(ostream&out, Entity*entity, ScopeBase*scope); + void write_to_stream(std::ostream&fd); void visit(SeqStmtVisitor& func); private: @@ -213,6 +223,7 @@ class VariableSeqAssignment : public SequentialStmt { public: int elaborate(Entity*ent, ScopeBase*scope); int emit(ostream&out, Entity*entity, ScopeBase*scope); + void write_to_stream(std::ostream&fd); void dump(ostream&out, int indent) const; private: @@ -227,7 +238,6 @@ class WhileLoopStatement : public LoopStatement { ~WhileLoopStatement(); int elaborate(Entity*ent, ScopeBase*scope); - int emit(ostream&out, Entity*entity, ScopeBase*scope); void dump(ostream&out, int indent) const; private: @@ -242,6 +252,7 @@ class ForLoopStatement : public LoopStatement { int elaborate(Entity*ent, ScopeBase*scope); int emit(ostream&out, Entity*ent, ScopeBase*scope); + void write_to_stream(std::ostream&fd); void dump(ostream&out, int indent) const; private: @@ -259,7 +270,6 @@ class BasicLoopStatement : public LoopStatement { ~BasicLoopStatement(); int elaborate(Entity*ent, ScopeBase*scope); - int emit(ostream&out, Entity*entity, ScopeBase*scope); void dump(ostream&out, int indent) const; }; diff --git a/vhdlpp/sequential_emit.cc b/vhdlpp/sequential_emit.cc index 44846a69d..36e784a4e 100644 --- a/vhdlpp/sequential_emit.cc +++ b/vhdlpp/sequential_emit.cc @@ -1,6 +1,8 @@ /* * Copyright (c) 2011-2013 Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) + * Copyright CERN 2015 + * @author Maciej Suminski (maciej.suminski@cern.ch) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -35,6 +37,13 @@ int SequentialStmt::emit(ostream&out, Entity*, ScopeBase*) return 1; } +void SequentialStmt::write_to_stream(std::ostream&fd) +{ + fd << " // " << get_fileline() << ": internal error: " + << "I don't know how to write_to_stream this sequential statement! " + << "type=" << typeid(*this).name() << endl; +} + int IfSequential::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; @@ -67,6 +76,35 @@ int IfSequential::emit(ostream&out, Entity*ent, ScopeBase*scope) return errors; } +void IfSequential::write_to_stream(std::ostream&fd) +{ + fd << "if "; + cond_->write_to_stream(fd); + fd << " then " << endl; + + for (list::iterator cur = if_.begin() + ; cur != if_.end() ; ++cur) + (*cur)->write_to_stream(fd); + + for (list::iterator cur = elsif_.begin() + ; cur != elsif_.end() ; ++cur) { + fd << "elsif "; + (*cur)->condition_write_to_stream(fd); + fd << " " << endl; + (*cur)->statement_write_to_stream(fd); + } + + if (! else_.empty()) { + fd << " else " << endl; + + for (list::iterator cur = else_.begin() + ; cur != else_.end() ; ++cur) + (*cur)->write_to_stream(fd); + } + + fd << "end if;" << endl; +} + int IfSequential::Elsif::condition_emit(ostream&out, Entity*ent, ScopeBase*scope) { return cond_->emit(out, ent, scope); @@ -83,6 +121,18 @@ int IfSequential::Elsif::statement_emit(ostream&out, Entity*ent, ScopeBase*scope return errors; } +void IfSequential::Elsif::condition_write_to_stream(ostream&fd) +{ + cond_->write_to_stream(fd); +} + +void IfSequential::Elsif::statement_write_to_stream(ostream&fd) +{ + for (list::iterator cur = if_.begin() + ; cur != if_.end() ; ++cur) + (*cur)->write_to_stream(fd); +} + int ReturnStmt::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; @@ -92,6 +142,13 @@ int ReturnStmt::emit(ostream&out, Entity*ent, ScopeBase*scope) return errors; } +void ReturnStmt::write_to_stream(ostream&fd) +{ + fd << "return "; + val_->write_to_stream(fd); + fd << ";" << endl; +} + int SignalSeqAssignment::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; @@ -112,6 +169,21 @@ int SignalSeqAssignment::emit(ostream&out, Entity*ent, ScopeBase*scope) return errors; } +void SignalSeqAssignment::write_to_stream(ostream&fd) +{ + lval_->write_to_stream(fd); + + if (waveform_.size() != 1) { + fd << "-- Confusing waveform?" << endl; + + } else { + Expression*tmp = waveform_.front(); + fd << " <= "; + tmp->write_to_stream(fd); + fd << ";" << endl; + } +} + int VariableSeqAssignment::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; @@ -125,6 +197,14 @@ int VariableSeqAssignment::emit(ostream&out, Entity*ent, ScopeBase*scope) return errors; } +void VariableSeqAssignment::write_to_stream(ostream&fd) +{ + lval_->write_to_stream(fd); + fd << " := "; + rval_->write_to_stream(fd); + fd << ";" << endl; +} + int ProcedureCall::emit(ostream&out, Entity*, ScopeBase*) { out << " // " << get_fileline() << ": internal error: " @@ -144,6 +224,15 @@ int LoopStatement::emit_substatements(ostream&out, Entity*ent, ScopeBase*scope) return errors; } +void LoopStatement::write_to_stream_substatements(ostream&fd) +{ + for (list::iterator cur = stmts_.begin() + ; cur != stmts_.end() ; ++cur) { + SequentialStmt*tmp = *cur; + tmp->write_to_stream(fd); + } +} + int CaseSeqStmt::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; @@ -163,6 +252,21 @@ int CaseSeqStmt::emit(ostream&out, Entity*ent, ScopeBase*scope) return errors; } +void CaseSeqStmt::write_to_stream(ostream&fd) +{ + fd << "case "; + cond_->write_to_stream(fd); + fd << " is" << endl; + + for (list::iterator cur = alt_.begin() + ; cur != alt_.end() ; ++cur) { + CaseStmtAlternative*curp = *cur; + curp ->write_to_stream(fd); + } + + fd << "end case;" << endl; +} + int CaseSeqStmt::CaseStmtAlternative::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; @@ -198,6 +302,22 @@ int CaseSeqStmt::CaseStmtAlternative::emit(ostream&out, Entity*ent, ScopeBase*sc return errors; } +void CaseSeqStmt::CaseStmtAlternative::write_to_stream(ostream&fd) +{ + fd << "when "; + if (exp_) { + exp_->write_to_stream(fd); + } else { + fd << "others" << endl; + } + fd << "=>" << endl; + + for (list::iterator cur = stmts_.begin() + ; cur != stmts_.end() ; ++cur) { + (*cur)->write_to_stream(fd); + } +} + int ForLoopStatement::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; @@ -238,7 +358,8 @@ int ForLoopStatement::emit(ostream&out, Entity*ent, ScopeBase*scope) } else { out << "begin /* Degenerate loop at " << get_fileline() << ": " << start_val - << " downto " << finish_val << " */ end" << endl; + << " downto " << finish_val << " */ end" << endl + << "end" << endl; return errors; } } @@ -249,7 +370,8 @@ int ForLoopStatement::emit(ostream&out, Entity*ent, ScopeBase*scope) } else { out << "begin /* Degenerate loop at " << get_fileline() << ": " << start_val - << " to " << finish_val << " */ end" << endl; + << " to " << finish_val << " */ end" << endl + << "end" << endl; return errors; } } @@ -279,6 +401,17 @@ int ForLoopStatement::emit(ostream&out, Entity*ent, ScopeBase*scope) return errors; } +void ForLoopStatement::write_to_stream(ostream&fd) +{ + fd << "for " << it_ << " in "; + range_->expr_left()->write_to_stream(fd); + fd << " to "; + range_->expr_right()->write_to_stream(fd); + fd << " loop" << endl; + write_to_stream_substatements(fd); + fd << "end loop;" << endl; +} + int ForLoopStatement::emit_runtime_(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; @@ -303,19 +436,3 @@ int ForLoopStatement::emit_runtime_(ostream&out, Entity*ent, ScopeBase*scope) return errors; } - -int WhileLoopStatement::emit(ostream&out, Entity*, ScopeBase*) -{ - out << " // " << get_fileline() << ": internal error: " - << "I don't know how to emit this sequential statement! " - << "type=" << typeid(*this).name() << endl; - return 1; -} - -int BasicLoopStatement::emit(ostream&out, Entity*, ScopeBase*) -{ - out << " // " << get_fileline() << ": internal error: " - << "I don't know how to emit this sequential statement! " - << "type=" << typeid(*this).name() << endl; - return 1; -} From 11bb7ac348a7cf6ea3f2f60031a56a185e2a7325 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 3 Feb 2015 14:38:04 +0100 Subject: [PATCH 36/41] vhdlpp: Expression::write_to_stream becomes const. --- vhdlpp/expression.h | 46 ++++++++++++++++++------------------- vhdlpp/expression_stream.cc | 38 +++++++++++++++--------------- 2 files changed, 42 insertions(+), 42 deletions(-) diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 15983a25d..058533f86 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -87,7 +87,7 @@ class Expression : public LineInfo { // This virtual method writes a VHDL-accurate representation // of this expression to the designated stream. This is used // for writing parsed types to library files. - virtual void write_to_stream(std::ostream&fd) =0; + virtual void write_to_stream(std::ostream&fd) const =0; // The emit virtual method is called by architecture emit to // output the generated code for the expression. The derived @@ -163,7 +163,7 @@ class ExpUnary : public Expression { const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const; protected: - inline void write_to_stream_operand1(std::ostream&fd) + inline void write_to_stream_operand1(std::ostream&fd) const { operand1_->write_to_stream(fd); } int emit_operand1(ostream&out, Entity*ent, ScopeBase*scope); @@ -197,9 +197,9 @@ class ExpBinary : public Expression { bool eval_operand1(ScopeBase*scope, int64_t&val) const; bool eval_operand2(ScopeBase*scope, int64_t&val) const; - inline void write_to_stream_operand1(std::ostream&out) + inline void write_to_stream_operand1(std::ostream&out) const { operand1_->write_to_stream(out); } - inline void write_to_stream_operand2(std::ostream&out) + inline void write_to_stream_operand2(std::ostream&out) const { operand2_->write_to_stream(out); } void dump_operands(ostream&out, int indent = 0) const; @@ -297,7 +297,7 @@ class ExpAggregate : public Expression { const VType*probe_type(Entity*ent, ScopeBase*scope) const; const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const; int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); - void write_to_stream(std::ostream&fd); + void write_to_stream(std::ostream&fd) const; int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; @@ -330,7 +330,7 @@ class ExpArithmetic : public ExpBinary { } int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); - void write_to_stream(std::ostream&fd); + void write_to_stream(std::ostream&fd) const; int emit(ostream&out, Entity*ent, ScopeBase*scope); virtual bool evaluate(ScopeBase*scope, int64_t&val) const; void dump(ostream&out, int indent = 0) const; @@ -355,7 +355,7 @@ class ExpAttribute : public Expression { const VType*probe_type(Entity*ent, ScopeBase*scope) const; int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); - void write_to_stream(std::ostream&fd); + void write_to_stream(std::ostream&fd) const; int emit(ostream&out, Entity*ent, ScopeBase*scope); // Some attributes can be evaluated at compile time bool evaluate(ScopeBase*scope, int64_t&val) const; @@ -378,7 +378,7 @@ class ExpBitstring : public Expression { const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const; int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); - void write_to_stream(std::ostream&fd); + void write_to_stream(std::ostream&fd) const; int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; @@ -398,7 +398,7 @@ class ExpCharacter : public Expression { const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const; int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); - void write_to_stream(std::ostream&fd); + void write_to_stream(std::ostream&fd) const; int emit(ostream&out, Entity*ent, ScopeBase*scope); bool is_primary(void) const; void dump(ostream&out, int indent = 0) const; @@ -426,7 +426,7 @@ class ExpConcat : public Expression { const VType*probe_type(Entity*ent, ScopeBase*scope) const; const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const; int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); - void write_to_stream(std::ostream&fd); + void write_to_stream(std::ostream&fd) const; int emit(ostream&out, Entity*ent, ScopeBase*scope); virtual bool evaluate(ScopeBase*scope, int64_t&val) const; bool is_primary(void) const; @@ -473,7 +473,7 @@ class ExpConditional : public Expression { const VType*probe_type(Entity*ent, ScopeBase*scope) const; int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); - void write_to_stream(std::ostream&fd); + void write_to_stream(std::ostream&fd) const; int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; @@ -500,7 +500,7 @@ class ExpEdge : public ExpUnary { inline fun_t edge_fun() const { return fun_; } - void write_to_stream(std::ostream&fd); + void write_to_stream(std::ostream&fd) const; int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; @@ -524,7 +524,7 @@ class ExpFunc : public Expression { public: // Base methods int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); - void write_to_stream(std::ostream&fd); + void write_to_stream(std::ostream&fd) const; int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; @@ -545,7 +545,7 @@ class ExpInteger : public Expression { const VType*probe_type(Entity*ent, ScopeBase*scope) const; int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); - void write_to_stream(std::ostream&fd); + void write_to_stream(std::ostream&fd) const; int emit(ostream&out, Entity*ent, ScopeBase*scope); int emit_package(std::ostream&out); bool is_primary(void) const { return true; } @@ -568,7 +568,7 @@ class ExpReal : public Expression { const VType*probe_type(Entity*ent, ScopeBase*scope) const; int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); - void write_to_stream(std::ostream&fd); + void write_to_stream(std::ostream&fd) const; int emit(ostream&out, Entity*ent, ScopeBase*scope); int emit_package(std::ostream&out); bool is_primary(void) const; @@ -595,7 +595,7 @@ class ExpLogical : public ExpBinary { inline fun_t logic_fun() const { return fun_; } int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); - void write_to_stream(std::ostream&fd); + void write_to_stream(std::ostream&fd) const; int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; @@ -628,7 +628,7 @@ class ExpName : public Expression { const VType* probe_type(Entity*ent, ScopeBase*scope) const; const VType* fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*host) const; int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); - void write_to_stream(std::ostream&fd); + void write_to_stream(std::ostream&fd) const; int emit(ostream&out, Entity*ent, ScopeBase*scope); bool is_primary(void) const; bool evaluate(ScopeBase*scope, int64_t&val) const; @@ -684,7 +684,7 @@ class ExpRelation : public ExpBinary { const VType* probe_type(Entity*ent, ScopeBase*scope) const; int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); - void write_to_stream(std::ostream&fd); + void write_to_stream(std::ostream&fd) const; int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; @@ -703,7 +703,7 @@ class ExpString : public Expression { const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const; int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); - void write_to_stream(std::ostream&fd); + void write_to_stream(std::ostream&fd) const; int emit(ostream&out, Entity*ent, ScopeBase*scope); bool is_primary(void) const; void dump(ostream&out, int indent = 0) const; @@ -724,7 +724,7 @@ class ExpUAbs : public ExpUnary { Expression*clone() const { return new ExpUAbs(peek_operand()->clone()); } - void write_to_stream(std::ostream&fd); + void write_to_stream(std::ostream&fd) const; int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; }; @@ -738,7 +738,7 @@ class ExpUNot : public ExpUnary { Expression*clone() const { return new ExpUNot(peek_operand()->clone()); } int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); - void write_to_stream(std::ostream&fd); + void write_to_stream(std::ostream&fd) const; int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; }; @@ -757,7 +757,7 @@ class ExpCast : public Expression { inline int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*) { return base_->elaborate_expr(ent, scope, type_); } - void write_to_stream(std::ostream&fd); + void write_to_stream(std::ostream&fd) const; int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; @@ -779,7 +779,7 @@ class ExpNew : public Expression { Expression*clone() const { return new ExpNew(size_->clone()); } // There is no 'new' in VHDL - do not emit anything - void write_to_stream(std::ostream&) {}; + void write_to_stream(std::ostream&) const {}; int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; diff --git a/vhdlpp/expression_stream.cc b/vhdlpp/expression_stream.cc index 80864265e..992415df0 100644 --- a/vhdlpp/expression_stream.cc +++ b/vhdlpp/expression_stream.cc @@ -24,7 +24,7 @@ using namespace std; -void ExpAggregate::write_to_stream(ostream&fd) +void ExpAggregate::write_to_stream(ostream&fd) const { fd << "("; for (vector::const_iterator cur = elements_.begin() @@ -73,7 +73,7 @@ void ExpAggregate::choice_t::write_to_stream(ostream&fd) fd << "/* ERROR */"; } -void ExpArithmetic::write_to_stream(ostream&out) +void ExpArithmetic::write_to_stream(ostream&out) const { out << "("; write_to_stream_operand1(out); @@ -111,13 +111,13 @@ void ExpArithmetic::write_to_stream(ostream&out) out << ")"; } -void ExpAttribute::write_to_stream(ostream&fd) +void ExpAttribute::write_to_stream(ostream&fd) const { base_->write_to_stream(fd); fd << "'" << name_; } -void ExpBitstring::write_to_stream(ostream&fd) +void ExpBitstring::write_to_stream(ostream&fd) const { fd << "\""; for(vector::const_iterator it = value_.begin(); @@ -127,7 +127,7 @@ void ExpBitstring::write_to_stream(ostream&fd) fd << "\""; } -void ExpCharacter::write_to_stream(ostream&fd) +void ExpCharacter::write_to_stream(ostream&fd) const { char buf[4]; buf[0] = '\''; @@ -137,7 +137,7 @@ void ExpCharacter::write_to_stream(ostream&fd) fd << buf; } -void ExpConcat::write_to_stream(ostream&fd) +void ExpConcat::write_to_stream(ostream&fd) const { fd << "("; operand1_->write_to_stream(fd); @@ -146,21 +146,21 @@ void ExpConcat::write_to_stream(ostream&fd) fd << ")"; } -void ExpConditional::write_to_stream(ostream&) +void ExpConditional::write_to_stream(ostream&) const { ivl_assert(*this, !"Not supported"); } -void ExpEdge::write_to_stream(ostream&) +void ExpEdge::write_to_stream(ostream&) const { ivl_assert(*this, !"Not supported"); } -void ExpFunc::write_to_stream(ostream&fd) +void ExpFunc::write_to_stream(ostream&fd) const { const char*comma = ""; fd << name_ << "("; - for (vector::iterator cur = argv_.begin() + for (vector::const_iterator cur = argv_.begin() ; cur != argv_.end() ; ++cur) { fd << comma; (*cur)->write_to_stream(fd); @@ -169,22 +169,22 @@ void ExpFunc::write_to_stream(ostream&fd) fd << ")"; } -void ExpInteger::write_to_stream(ostream&fd) +void ExpInteger::write_to_stream(ostream&fd) const { fd << value_; } -void ExpReal::write_to_stream(ostream&fd) +void ExpReal::write_to_stream(ostream&fd) const { fd << value_; } -void ExpLogical::write_to_stream(ostream&) +void ExpLogical::write_to_stream(ostream&) const { ivl_assert(*this, !"Not supported"); } -void ExpName::write_to_stream(ostream&fd) +void ExpName::write_to_stream(ostream&fd) const { if (prefix_.get()) { prefix_->write_to_stream(fd); @@ -203,12 +203,12 @@ void ExpName::write_to_stream(ostream&fd) } } -void ExpRelation::write_to_stream(ostream&) +void ExpRelation::write_to_stream(ostream&) const { ivl_assert(*this, !"Not supported"); } -void ExpString::write_to_stream(ostream&fd) +void ExpString::write_to_stream(ostream&fd) const { fd << "\""; for(vector::const_iterator it = value_.begin(); @@ -218,19 +218,19 @@ void ExpString::write_to_stream(ostream&fd) fd << "\""; } -void ExpUAbs::write_to_stream(ostream&fd) +void ExpUAbs::write_to_stream(ostream&fd) const { fd << "abs "; write_to_stream_operand1(fd); } -void ExpUNot::write_to_stream(ostream&fd) +void ExpUNot::write_to_stream(ostream&fd) const { fd << "not "; write_to_stream_operand1(fd); } -void ExpCast::write_to_stream(ostream&fd) +void ExpCast::write_to_stream(ostream&fd) const { // Type casting is introduced only for a few specific cases in // SystemVerilog, so no need to use it here From 8777cd8e7c6f58b94548fb053e3e4cac91bac7b8 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 3 Feb 2015 14:41:32 +0100 Subject: [PATCH 37/41] vhdlpp: Fixed ExpBitstring & ExpRelation write_to_stream() method. --- vhdlpp/expression_stream.cc | 38 ++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/vhdlpp/expression_stream.cc b/vhdlpp/expression_stream.cc index 992415df0..5c682a5cd 100644 --- a/vhdlpp/expression_stream.cc +++ b/vhdlpp/expression_stream.cc @@ -119,9 +119,9 @@ void ExpAttribute::write_to_stream(ostream&fd) const void ExpBitstring::write_to_stream(ostream&fd) const { - fd << "\""; - for(vector::const_iterator it = value_.begin(); - it != value_.end(); ++it) { + fd << "B\""; + for(vector::const_reverse_iterator it = value_.rbegin(); + it != value_.rend(); ++it) { fd << *it; } fd << "\""; @@ -203,9 +203,37 @@ void ExpName::write_to_stream(ostream&fd) const } } -void ExpRelation::write_to_stream(ostream&) const +void ExpRelation::write_to_stream(ostream&fd) const { - ivl_assert(*this, !"Not supported"); + peek_operand1()->write_to_stream(fd); + + switch(fun_) { + case EQ: + fd << " = "; + break; + + case LT: + fd << " < "; + break; + + case GT: + fd << " > "; + break; + + case NEQ: + fd << " != "; + break; + + case LE: + fd << " <= "; + break; + + case GE: + fd << " >= "; + break; + } + + peek_operand2()->write_to_stream(fd); } void ExpString::write_to_stream(ostream&fd) const From a1c2a8e60584649fe02f83e62ae2e1aa2a1dfb90 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 3 Feb 2015 15:07:19 +0100 Subject: [PATCH 38/41] vhdlpp: Generic syntax errors display messages. --- vhdlpp/parse.y | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index ecde6b0b2..bd3add632 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -2504,9 +2504,9 @@ K_postponed_opt : K_postponed | ; K_shared_opt : K_shared | ; %% -static void yyerror(YYLTYPE*, yyscan_t, const char*, bool, const char* /*msg*/) +static void yyerror(YYLTYPE*loc, yyscan_t, const char*, bool, const char*msg) { - //fprintf(stderr, "%s\n", msg); + fprintf(stderr, "%s:%u: %s\n", loc->text, loc->first_line, msg); parse_errors += 1; } From 5b7b980ead0fccf9eaca94a8552bbb679fd1c517 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 3 Feb 2015 16:52:19 +0100 Subject: [PATCH 39/41] vhdlpp: Support for multiple choices in case statements. --- vhdlpp/parse.y | 46 ++++++++++++++++++++++++---------- vhdlpp/sequential.cc | 3 ++- vhdlpp/sequential.h | 4 +-- vhdlpp/sequential_debug.cc | 4 ++- vhdlpp/sequential_elaborate.cc | 8 ++++-- vhdlpp/sequential_emit.cc | 23 ++++++++++++++--- 6 files changed, 65 insertions(+), 23 deletions(-) diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index bd3add632..a509d8fa6 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -573,20 +573,40 @@ case_statement_alternative_list * statement alternative and pass that up instead. */ case_statement_alternative - : K_when choice ARROW sequence_of_statements + : K_when choices ARROW sequence_of_statements { CaseSeqStmt::CaseStmtAlternative* tmp; - if ($2->others()) { - tmp = new CaseSeqStmt::CaseStmtAlternative(0, $4); - } else if (Expression*ex = $2->simple_expression()) { - tmp = new CaseSeqStmt::CaseStmtAlternative(ex, $4); - } else { - errormsg(@2, "I don't know what to make of the case choice\n"); - tmp = 0; - } - if (tmp) FILE_NAME(tmp, @1); - delete $2; - delete $4; - $$ = tmp; + std::list*choices = $2; + std::list*exp_list = new std::list; + bool others = false; + + for(std::list::iterator it = choices->begin(); + it != choices->end(); ++it) { + if((*it)->others() || others) + // If there is one "others", then it also covers all other alternatives + // Continue the loop to delete every choice_t, but do not + // bother to add the expressions to the exp_list (we are going to + // delete them very soon) + others = true; + else + exp_list->push_back((*it)->simple_expression()); + + delete (*it); + } + + if(others) { + tmp = new CaseSeqStmt::CaseStmtAlternative(0, $4); + for(std::list::iterator it = exp_list->begin(); + it != exp_list->end(); ++it) { + delete (*it); + } + } else { + tmp = new CaseSeqStmt::CaseStmtAlternative(exp_list, $4); + } + if (tmp) FILE_NAME(tmp, @1); + + delete choices; + delete $4; + $$ = tmp; } ; diff --git a/vhdlpp/sequential.cc b/vhdlpp/sequential.cc index dc6043d70..f6fe41d0d 100644 --- a/vhdlpp/sequential.cc +++ b/vhdlpp/sequential.cc @@ -146,7 +146,8 @@ void CaseSeqStmt::visit(SeqStmtVisitor& func) func(this); } -CaseSeqStmt::CaseStmtAlternative::CaseStmtAlternative(Expression* exp, list* stmts) +CaseSeqStmt::CaseStmtAlternative::CaseStmtAlternative(std::list*exp, + list*stmts) : exp_(exp) { if (stmts) stmts_.splice(stmts_.end(), *stmts); diff --git a/vhdlpp/sequential.h b/vhdlpp/sequential.h index 06fff7b8d..c9f039fea 100644 --- a/vhdlpp/sequential.h +++ b/vhdlpp/sequential.h @@ -167,7 +167,7 @@ class CaseSeqStmt : public SequentialStmt { public: class CaseStmtAlternative : public LineInfo { public: - CaseStmtAlternative(Expression* exp, std::list* stmts); + CaseStmtAlternative(std::list*exp, std::list*stmts); ~CaseStmtAlternative(); void dump(std::ostream& out, int indent) const; int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); @@ -177,7 +177,7 @@ class CaseSeqStmt : public SequentialStmt { void visit(SeqStmtVisitor& func); private: - Expression* exp_; + std::list*exp_; std::list stmts_; private: // not implemented CaseStmtAlternative(const CaseStmtAlternative&); diff --git a/vhdlpp/sequential_debug.cc b/vhdlpp/sequential_debug.cc index b28d0f8cc..31f3655d2 100644 --- a/vhdlpp/sequential_debug.cc +++ b/vhdlpp/sequential_debug.cc @@ -105,7 +105,9 @@ void CaseSeqStmt::CaseStmtAlternative::dump(ostream& out, int indent) const out << setw(indent) << "" << "when "; if (exp_) - exp_->dump(out, 0); + for (list::iterator it = exp_->begin(); it != exp_->end(); ++it) { + (*it)->dump(out, 0); + } else out << "others" << endl; diff --git a/vhdlpp/sequential_elaborate.cc b/vhdlpp/sequential_elaborate.cc index 88d215de7..2244e0f16 100644 --- a/vhdlpp/sequential_elaborate.cc +++ b/vhdlpp/sequential_elaborate.cc @@ -62,8 +62,12 @@ int CaseSeqStmt::elaborate(Entity*ent, ScopeBase*scope) int CaseSeqStmt::CaseStmtAlternative::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype) { int errors = 0; - if (exp_) - errors += exp_->elaborate_expr(ent, scope, ltype); + if (exp_) { + for (list::iterator it = exp_->begin(); it != exp_->end(); + ++it) { + errors += (*it)->elaborate_expr(ent, scope, ltype); + } + } return errors; } diff --git a/vhdlpp/sequential_emit.cc b/vhdlpp/sequential_emit.cc index 36e784a4e..895d1d839 100644 --- a/vhdlpp/sequential_emit.cc +++ b/vhdlpp/sequential_emit.cc @@ -271,12 +271,19 @@ int CaseSeqStmt::CaseStmtAlternative::emit(ostream&out, Entity*ent, ScopeBase*sc { int errors = 0; + bool first = true; if (exp_) { - errors += exp_->emit(out, ent, scope); - out << ":" << endl; + for (list::iterator it = exp_->begin(); it != exp_->end(); ++it) { + if(first) + first = false; + else + out << ","; + errors += (*it)->emit(out, ent, scope); + } } else { - out << "default:" << endl; + out << "default"; } + out << ":" << endl; SequentialStmt*curp; @@ -306,7 +313,15 @@ void CaseSeqStmt::CaseStmtAlternative::write_to_stream(ostream&fd) { fd << "when "; if (exp_) { - exp_->write_to_stream(fd); + bool first = true; + for (list::iterator it = exp_->begin(); it != exp_->end(); ++it) { + if(first) + first = false; + else + fd << "|"; + + (*it)->write_to_stream(fd); + } } else { fd << "others" << endl; } From 5349ca9a5558dd2f1708699971f53989c18e3656 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 4 Feb 2015 11:46:20 +0100 Subject: [PATCH 40/41] vhdlpp: Added Subprogram::write_to_stream_body() method. --- vhdlpp/subprogram.cc | 36 ++++++++++++++++++++++++++++++++++++ vhdlpp/subprogram.h | 1 + 2 files changed, 37 insertions(+) diff --git a/vhdlpp/subprogram.cc b/vhdlpp/subprogram.cc index 56d07a599..c5b6d9ee0 100644 --- a/vhdlpp/subprogram.cc +++ b/vhdlpp/subprogram.cc @@ -308,3 +308,39 @@ void Subprogram::write_to_stream(ostream&fd) const return_type_->write_to_stream(fd); fd << ";" << endl; } + +void Subprogram::write_to_stream_body(ostream&fd) const +{ + fd << "function " << name_ << "("; + if (ports_ && ! ports_->empty()) { + list::const_iterator cur = ports_->begin(); + InterfacePort*curp = *cur; + fd << curp->name << " : "; + curp->type->write_to_stream(fd); + for (++cur ; cur != ports_->end() ; ++cur) { + curp = *cur; + fd << "; " << curp->name << " : "; + curp->type->write_to_stream(fd); + } + } + fd << ") return "; + return_type_->write_to_stream(fd); + fd << " is" << endl; + + for (map::const_iterator cur = new_variables_.begin() + ; cur != new_variables_.end() ; ++cur) { + cur->second->write_to_stream(fd); + } + + fd << "begin" << endl; + + if (statements_) { + for (list::const_iterator cur = statements_->begin() + ; cur != statements_->end() ; ++cur) { + (*cur)->write_to_stream(fd); + } + } else { + fd << "--empty body" << endl; + } + fd << "end function;" << endl; +} diff --git a/vhdlpp/subprogram.h b/vhdlpp/subprogram.h index bba9c757f..5af77244d 100644 --- a/vhdlpp/subprogram.h +++ b/vhdlpp/subprogram.h @@ -61,6 +61,7 @@ class Subprogram : public LineInfo, public ScopeBase { int emit_package(std::ostream&fd) const; void write_to_stream(std::ostream&fd) const; + void write_to_stream_body(std::ostream&fd) const; void dump(std::ostream&fd) const; // Creates a new instance of the function that takes arguments of From 19ff6a434bbac5fb3d887eaa212f3cfb00d5a141 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 4 Feb 2015 14:29:41 +0100 Subject: [PATCH 41/41] vhdlpp: Alternative way of dealing with unbounded vectors in fuctions (instances). --- vhdlpp/architec_elaborate.cc | 5 -- vhdlpp/architec_emit.cc | 4 +- vhdlpp/expression_elaborate.cc | 9 +--- vhdlpp/library.cc | 14 ++++-- vhdlpp/package.cc | 7 +++ vhdlpp/package_emit.cc | 4 +- vhdlpp/sequential_elaborate.cc | 7 --- vhdlpp/subprogram.cc | 89 +++++----------------------------- vhdlpp/subprogram.h | 28 ++--------- 9 files changed, 38 insertions(+), 129 deletions(-) diff --git a/vhdlpp/architec_elaborate.cc b/vhdlpp/architec_elaborate.cc index 749e2a0d6..62a368813 100644 --- a/vhdlpp/architec_elaborate.cc +++ b/vhdlpp/architec_elaborate.cc @@ -373,11 +373,6 @@ int SignalAssignment::elaborate(Entity*ent, Architecture*arc) (*cur)->elaborate_expr(ent, arc, lval_type); // Handle functions that return unbounded arrays - if(ExpFunc*call = dynamic_cast(*cur)) { - const VType*ret_type = call->func_ret_type(); - if(ret_type && ret_type->is_unbounded()) - *cur = new ExpCast(*cur, get_global_typedef(lval_type)); - } } return errors; diff --git a/vhdlpp/architec_emit.cc b/vhdlpp/architec_emit.cc index ef17e370a..c344564e0 100644 --- a/vhdlpp/architec_emit.cc +++ b/vhdlpp/architec_emit.cc @@ -103,7 +103,9 @@ int Architecture::emit(ostream&out, Entity*entity) for (map::const_iterator cur = cur_subprograms_.begin() ; cur != cur_subprograms_.end() ; ++ cur) { - errors += cur->second->emit_package(out); + // Do not emit unbounded functions, we will just need fixed instances later + if(!cur->second->unbounded()) + errors += cur->second->emit_package(out); } for (list::iterator cur = statements_.begin() diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index 256970085..d16f63db4 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -757,8 +757,6 @@ int ExpFunc::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*) ivl_assert(*this, def_==0); def_ = prog; - bool new_instance = false; - // Elaborate arguments for (size_t idx = 0 ; idx < argv_.size() ; idx += 1) { const VType*tmp = argv_[idx]->probe_type(ent, scope); @@ -768,14 +766,9 @@ int ExpFunc::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*) tmp = param_type; errors += argv_[idx]->elaborate_expr(ent, scope, tmp); - - // Type casting for unbounded arrays - if(param_type && param_type->is_unbounded() /*&& !param_type->type_match(tmp)*/) { - new_instance = true; // we need a new instance - } } - if(new_instance) { + if(def_ && def_->unbounded()) { def_ = prog->make_instance(argv_, scope); name_ = def_->name(); } diff --git a/vhdlpp/library.cc b/vhdlpp/library.cc index 3ed27b0e2..1eb5fc54f 100644 --- a/vhdlpp/library.cc +++ b/vhdlpp/library.cc @@ -430,13 +430,10 @@ void library_set_work_path(const char*path) library_work_path = path; } +list work_packages; static void store_package_in_work(const Package*pack) { - string path = make_work_package_path(pack->name()); - - ofstream file (path.c_str(), ios_base::out); - - pack->write_to_stream(file); + work_packages.push_back(pack); } static int emit_packages(perm_string, const map&packages) @@ -447,6 +444,13 @@ static int emit_packages(perm_string, const map&packages) errors += cur->second->emit_package(cout); } + for (list::const_iterator cur = work_packages.begin() + ; cur != work_packages.end(); ++cur) { + string path = make_work_package_path((*cur)->name()); + ofstream file (path.c_str(), ios_base::out); + (*cur)->write_to_stream(file); + } + return errors; } diff --git a/vhdlpp/package.cc b/vhdlpp/package.cc index 9c0025f47..240eb37a1 100644 --- a/vhdlpp/package.cc +++ b/vhdlpp/package.cc @@ -130,4 +130,11 @@ void Package::write_to_stream(ostream&fd) const } fd << "end package " << name_ << ";" << endl; + + fd << "package body " << name_ << " is" << endl; + for (map::const_iterator cur = cur_subprograms_.begin() + ; cur != cur_subprograms_.end() ; ++cur) { + cur->second->write_to_stream_body(fd); + } + fd << "end " << name_ << ";" << endl; } diff --git a/vhdlpp/package_emit.cc b/vhdlpp/package_emit.cc index f8e631c2f..42ce821a9 100644 --- a/vhdlpp/package_emit.cc +++ b/vhdlpp/package_emit.cc @@ -69,7 +69,9 @@ int Package::emit_package(ostream&fd) const for (map::const_iterator cur = cur_subprograms_.begin() ; cur != cur_subprograms_.end() ; ++ cur) { - errors += cur->second->emit_package(fd); + // Do not emit unbounded functions, we will just need fixed instances later + if(!cur->second->unbounded()) + errors += cur->second->emit_package(fd); } fd << "endpackage" << endl; diff --git a/vhdlpp/sequential_elaborate.cc b/vhdlpp/sequential_elaborate.cc index 2244e0f16..29b4e4914 100644 --- a/vhdlpp/sequential_elaborate.cc +++ b/vhdlpp/sequential_elaborate.cc @@ -179,13 +179,6 @@ int VariableSeqAssignment::elaborate(Entity*ent, ScopeBase*scope) // Elaborate the r-value expression. errors += rval_->elaborate_expr(ent, scope, lval_type); - // Handle functions that return unbounded arrays - if(ExpFunc*call = dynamic_cast(rval_)) { - const VType*ret_type = call->func_ret_type(); - if(ret_type && ret_type->is_unbounded()) - rval_ = new ExpCast(rval_, get_global_typedef(lval_type)); - } - return errors; } diff --git a/vhdlpp/subprogram.cc b/vhdlpp/subprogram.cc index c5b6d9ee0..8d2f4f814 100644 --- a/vhdlpp/subprogram.cc +++ b/vhdlpp/subprogram.cc @@ -50,82 +50,17 @@ void Subprogram::set_program_body(list*stmt) { ivl_assert(*this, statements_==0); statements_ = stmt; - fix_port_types(); } -// Functor used to add type casting to each return statement. -struct cast_return_type : public SeqStmtVisitor { - cast_return_type(const VType*ret_type) : ret_(ret_type) {} +bool Subprogram::unbounded() const { + if(return_type_->is_unbounded()) + return true; - void operator() (SequentialStmt*s) - { - ReturnStmt*ret; - if((ret = dynamic_cast(s))) { - ret->cast_to(ret_); - } - } - -private: - const VType*ret_; -}; - -void Subprogram::fix_port_types() -{ - // Check function parameters for unbounded vectors and possibly fix it. - - // Try to settle at a fixed width return type. - if(fixed_return_type()) - return; - - // Check if the returned type is an unbounded vector. - if(check_unb_vector(return_type_)) { - if(!statements_) - return; - - // Go through the statement list and add type casting to return - // statements to comply with the modified return type. - for (std::list::iterator s = statements_->begin() - ; s != statements_->end(); ++s) { - cast_return_type r(return_type_); - (*s)->visit(r); - } - } -} - -void Subprogram::fix_variables() { - for(std::map::iterator it = new_variables_.begin(); it != new_variables_.end(); ++it) { - Variable*var = it->second; - const VType*type = var->peek_type(); - - if(type->is_variable_length(this)) { - const VTypeArray*arr = dynamic_cast(type); - - // Currently we handle only one dimensional variables - assert(arr->dimensions() == 1); - - // Now substitute the variable type - VTypeArray*new_array = static_cast(arr->clone()); - new_array->evaluate_ranges(this); - it->second = new Variable(var->peek_name(), new_array); - delete var; - } - } -} - -VTypeArray*Subprogram::fix_logic_darray(const VTypeArray*type) -{ - Expression*zero = new ExpInteger(0); - std::vector sub_range; - sub_range.push_back(VTypeArray::range_t(zero, zero)); - return new VTypeArray(type, sub_range); -} - -bool Subprogram::check_unb_vector(const VType*&type) -{ - if(const VTypeArray*arr = dynamic_cast(type)) { - if(arr->dimensions() == 1 && arr->dimension(0).is_box() ) { - type = get_global_typedef(fix_logic_darray(arr)); - return true; + if(ports_) { + for(std::list::const_iterator it = ports_->begin(); + it != ports_->end(); ++it) { + if((*it)->type->is_unbounded()) + return true; } } @@ -218,6 +153,7 @@ Subprogram*Subprogram::make_instance(std::vector arguments, ScopeBa instance->set_parent(scope); instance->set_program_body(statements_); + instance->fix_return_type(); scope->bind_subprogram(new_name, instance); return instance; @@ -263,10 +199,10 @@ private: const VType*ret_type_; }; -bool Subprogram::fixed_return_type(void) +void Subprogram::fix_return_type() { if(!statements_) - return false; + return; check_return_type r(this); @@ -284,9 +220,6 @@ bool Subprogram::fixed_return_type(void) arr->evaluate_ranges(this); } return_type_ = return_type; - return true; - } else { - return false; } } diff --git a/vhdlpp/subprogram.h b/vhdlpp/subprogram.h index 5af77244d..22c49879e 100644 --- a/vhdlpp/subprogram.h +++ b/vhdlpp/subprogram.h @@ -70,34 +70,14 @@ class Subprogram : public LineInfo, public ScopeBase { // for limited length logic vector. Subprogram*make_instance(std::vector arguments, ScopeBase*scope); + // Checks if either return type or parameters are unbounded vectors. + bool unbounded() const; + private: // Tries to set the return type to a fixed type. VHDL functions that // return std_logic_vectors do not specify its length, as SystemVerilog // demands. - // The function goes through the function body looking for return - // statments and probes the returned type. If it is the same for every - // statemnt then we can assume that the function returns vector of a - // fixed size. - bool fixed_return_type(); - - // Iterates through the list of function ports to fix all quirks related - // to translation between VHDL and SystemVerilog. - void fix_port_types(); - - // SystemVerilog does not allow to have signals/variables which size is - // evaluated at runtime. This function finds such variables and modifies - // their type to dynamic array and adds appropriate 'new' statement in - // the program body. - void fix_variables(); - - // For the time being, dynamic arrays work exclusively with vectors. - // To emulate dynamic array of 'logic'/'bit' type, we need to create a vector - // of width == 1, to be used as the array element type. - // Effectively 'logic name []' becomes 'logic [0:0] name []'. - VTypeArray*fix_logic_darray(const VTypeArray*type); - - // Creates a typedef for an unbounded vector and updates the given type. - bool check_unb_vector(const VType*&type); + void fix_return_type(); perm_string name_; const ScopeBase*parent_;