From cc9b182eb6a749ef418e76f6adb71d4059683c8d Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 12 Jun 2015 10:06:56 +0200 Subject: [PATCH] vhdlpp: Procedure calls. --- vhdlpp/parse.y | 58 +++++++++++++++++++++++++--------- vhdlpp/sequential.cc | 18 +++++++++-- vhdlpp/sequential.h | 2 ++ vhdlpp/sequential_elaborate.cc | 30 ++++++++++++++++-- vhdlpp/sequential_emit.cc | 29 ++++++++++++++--- vhdlpp/subprogram.cc | 18 ++++++++--- vhdlpp/subprogram_emit.cc | 6 ++-- 7 files changed, 130 insertions(+), 31 deletions(-) diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 9b107833a..6a7fb2295 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -311,6 +311,7 @@ static void touchup_interface_for_functions(std::list*ports) %type interface_element interface_list %type port_clause port_clause_opt %type generic_clause generic_clause_opt +%type parameter_list parameter_list_opt %type mode mode_opt %type entity_aspect entity_aspect_opt binding_indication binding_indication_semicolon_opt @@ -376,7 +377,8 @@ static void touchup_interface_for_functions(std::list*ports) %type else_when_waveform selected_waveform %type else_when_waveforms selected_waveform_list -%type function_specification subprogram_specification subprogram_body_start +%type function_specification procedure_specification +%type subprogram_specification subprogram_body_start %type severity severity_opt @@ -1254,15 +1256,15 @@ for_generate_statement ; function_specification /* IEEE 1076-2008 P4.2.1 */ - : K_function IDENTIFIER '(' interface_list ')' K_return IDENTIFIER - { perm_string type_name = lex_strings.make($7); + : K_function IDENTIFIER parameter_list K_return IDENTIFIER + { perm_string type_name = lex_strings.make($5); perm_string name = lex_strings.make($2); const VType*type_mark = active_scope->find_type(type_name); - touchup_interface_for_functions($4); - SubprogramHeader*tmp = new SubprogramHeader(name, $4, type_mark); + touchup_interface_for_functions($3); + SubprogramHeader*tmp = new SubprogramHeader(name, $3, type_mark); FILE_NAME(tmp, @1); delete[]$2; - delete[]$7; + delete[]$5; $$ = tmp; } ; @@ -1284,8 +1286,8 @@ generic_clause_opt ; generic_clause - : K_generic '(' interface_list ')' ';' - { $$ = $3; } + : K_generic parameter_list ';' + { $$ = $2; } | K_generic '(' error ')' ';' { errormsg(@3, "Error in interface list for generic.\n"); yyerrok; @@ -1774,9 +1776,18 @@ package_body_start } ; +parameter_list + : '(' interface_list ')' { $$ = $2; } + ; + +parameter_list_opt + : parameter_list { $$ = $1; } + | { $$ = 0; } + ; + port_clause - : K_port '(' interface_list ')' ';' - { $$ = $3; } + : K_port parameter_list ';' + { $$ = $2; } | K_port '(' error ')' ';' { errormsg(@1, "Syntax error in port list.\n"); yyerrok; @@ -1901,21 +1912,26 @@ primary_unit ; procedure_call - : IDENTIFIER + : IDENTIFIER ';' { ProcedureCall* tmp = new ProcedureCall(lex_strings.make($1)); - sorrymsg(@1, "Procedure calls are not supported.\n"); delete[] $1; $$ = tmp; } - | IDENTIFIER '(' association_list ')' + | IDENTIFIER '(' association_list ')' ';' { ProcedureCall* tmp = new ProcedureCall(lex_strings.make($1), $3); - sorrymsg(@1, "Procedure calls are not supported.\n"); delete[] $1; $$ = tmp; } - | IDENTIFIER '(' error ')' + | IDENTIFIER '(' expression_list ')' ';' + { + ProcedureCall* tmp = new ProcedureCall(lex_strings.make($1), $3); + delete[] $1; + delete $3; // parameters are copied in this variant + $$ = tmp; + } + | IDENTIFIER '(' error ')' ';' { errormsg(@1, "Errors in procedure call.\n"); yyerrok; delete[]$1; @@ -1931,6 +1947,17 @@ procedure_call_statement | procedure_call { $$ = $1; } ; +procedure_specification /* IEEE 1076-2008 P4.2.1 */ + : K_procedure IDENTIFIER parameter_list_opt + { perm_string name = lex_strings.make($2); + touchup_interface_for_functions($3); + SubprogramHeader*tmp = new SubprogramHeader(name, $3, NULL); + FILE_NAME(tmp, @1); + delete[]$2; + $$ = tmp; + } + ; + process_declarative_item : variable_declaration ; @@ -2494,6 +2521,7 @@ subprogram_kind_opt : subprogram_kind | ; subprogram_specification : function_specification { $$ = $1; } + | procedure_specification { $$ = $1; } ; /* This is an implementation of the rule: diff --git a/vhdlpp/sequential.cc b/vhdlpp/sequential.cc index 0f793b713..a0f2878cb 100644 --- a/vhdlpp/sequential.cc +++ b/vhdlpp/sequential.cc @@ -169,17 +169,31 @@ void CaseSeqStmt::CaseStmtAlternative::visit(SeqStmtVisitor& func) } ProcedureCall::ProcedureCall(perm_string name) -: name_(name), param_list_(0) +: name_(name), param_list_(NULL), def_(NULL) { } ProcedureCall::ProcedureCall(perm_string name, std::list* param_list) -: name_(name), param_list_(param_list) +: name_(name), param_list_(param_list), def_(NULL) { } +ProcedureCall::ProcedureCall(perm_string name, std::list* param_list) +: name_(name), def_(NULL) +{ + param_list_ = new std::list; + for(std::list::const_iterator it = param_list->begin(); + it != param_list->end(); ++it) + { + param_list_->push_back(new named_expr_t(empty_perm_string, (*it)->clone())); + } +} + ProcedureCall::~ProcedureCall() { + if(!param_list_) + return; + while(param_list_->size() > 0) { named_expr_t* cur = param_list_->front(); param_list_->pop_front(); diff --git a/vhdlpp/sequential.h b/vhdlpp/sequential.h index eba398cef..12a57f6a1 100644 --- a/vhdlpp/sequential.h +++ b/vhdlpp/sequential.h @@ -203,6 +203,7 @@ class ProcedureCall : public SequentialStmt { public: ProcedureCall(perm_string name); ProcedureCall(perm_string name, std::list* param_list); + ProcedureCall(perm_string name, std::list* param_list); ~ProcedureCall(); int elaborate(Entity*ent, ScopeBase*scope); @@ -212,6 +213,7 @@ class ProcedureCall : public SequentialStmt { private: perm_string name_; std::list* param_list_; + SubprogramHeader*def_; }; class VariableSeqAssignment : public SequentialStmt { diff --git a/vhdlpp/sequential_elaborate.cc b/vhdlpp/sequential_elaborate.cc index 4a574c2e5..4f3af82b0 100644 --- a/vhdlpp/sequential_elaborate.cc +++ b/vhdlpp/sequential_elaborate.cc @@ -20,6 +20,8 @@ # include "sequential.h" # include "expression.h" # include "scope.h" +# include "library.h" +# include "subprogram.h" int SequentialStmt::elaborate(Entity*, ScopeBase*) { @@ -155,9 +157,33 @@ int SignalSeqAssignment::elaborate(Entity*ent, ScopeBase*scope) return errors; } -int ProcedureCall::elaborate(Entity*, ScopeBase*) +int ProcedureCall::elaborate(Entity*ent, ScopeBase*scope) { - return 0; + int errors = 0; + + def_ = scope->find_subprogram(name_); + + if(!def_) + def_ = library_find_subprogram(name_); + + assert(def_); + + // Elaborate arguments + size_t idx = 0; + if(param_list_) { + for(list::iterator cur = param_list_->begin() + ; cur != param_list_->end() ; ++cur) { + const VType*tmp = (*cur)->expr()->probe_type(ent, scope); + const VType*param_type = def_ ? def_->peek_param_type(idx) : NULL; + + if(!tmp && param_type) + tmp = param_type; + + errors += (*cur)->expr()->elaborate_expr(ent, scope, tmp); + } + } + + return errors; } int VariableSeqAssignment::elaborate(Entity*ent, ScopeBase*scope) diff --git a/vhdlpp/sequential_emit.cc b/vhdlpp/sequential_emit.cc index 619c0f5e5..7148e2b52 100644 --- a/vhdlpp/sequential_emit.cc +++ b/vhdlpp/sequential_emit.cc @@ -23,7 +23,9 @@ # include "sequential.h" # include "expression.h" # include "architec.h" +# include "package.h" # include "compiler.h" +# include "subprogram.h" # include # include # include @@ -205,12 +207,29 @@ void VariableSeqAssignment::write_to_stream(ostream&fd) fd << ";" << endl; } -int ProcedureCall::emit(ostream&out, Entity*, ScopeBase*) +int ProcedureCall::emit(ostream&out, Entity*ent, ScopeBase*scope) { - out << " // " << get_fileline() << ": internal error: " - << "I don't know how to emit this sequential statement! " - << "type=" << typeid(*this).name() << endl; - return 1; + int errors = 0; + + std::vectorparams(param_list_->size()); + int i = 0; + for(std::list::iterator it = param_list_->begin(); + it != param_list_->end(); ++it) + params[i++] = (*it)->expr(); + + const Package*pkg = dynamic_cast (def_->get_parent()); + if (pkg != 0) + out << "\\" << pkg->name() << " ::"; + + errors += def_->emit_name(params, out, ent, scope); + + out << " ("; + if(param_list_) { + errors += def_->emit_args(params, out, ent, scope); + } + + out << ");" << endl; + return errors; } int LoopStatement::emit_substatements(ostream&out, Entity*ent, ScopeBase*scope) diff --git a/vhdlpp/subprogram.cc b/vhdlpp/subprogram.cc index 57dd31514..730dc3938 100644 --- a/vhdlpp/subprogram.cc +++ b/vhdlpp/subprogram.cc @@ -156,7 +156,7 @@ void SubprogramHeader::set_parent(const ScopeBase*par) } bool SubprogramHeader::unbounded() const { - if(return_type_->is_unbounded()) + if(return_type_ && return_type_->is_unbounded()) return true; if(ports_) { @@ -287,8 +287,14 @@ void SubprogramHeader::fix_return_type() void SubprogramHeader::write_to_stream(ostream&fd) const { - fd << "function " << name_ << "("; + if(return_type_) + fd << "function "; + else + fd << "procedure "; + + fd << name_; if (ports_ && ! ports_->empty()) { + fd << "("; list::const_iterator cur = ports_->begin(); InterfacePort*curp = *cur; fd << curp->name << " : "; @@ -298,9 +304,13 @@ void SubprogramHeader::write_to_stream(ostream&fd) const fd << "; " << curp->name << " : "; curp->type->write_to_stream(fd); } + fd << ")"; + } + + if( return_type_) { + fd << " return "; + return_type_->write_to_stream(fd); } - fd << ") return "; - return_type_->write_to_stream(fd); } SubprogramBuiltin::SubprogramBuiltin(perm_string vhdl_name, perm_string sv_name, diff --git a/vhdlpp/subprogram_emit.cc b/vhdlpp/subprogram_emit.cc index ae2b23775..6c880e90f 100644 --- a/vhdlpp/subprogram_emit.cc +++ b/vhdlpp/subprogram_emit.cc @@ -55,12 +55,12 @@ int SubprogramHeader::emit_package(ostream&fd) const if (return_type_) { fd << "function "; return_type_->emit_def(fd, empty_perm_string); - fd << " " << name_; - fd << "("; } else { - fd << "task " << name_ << ";" << endl; + fd << "task"; } + fd << " \\" << name_ << " ("; + for (list::const_iterator cur = ports_->begin() ; cur != ports_->end() ; ++cur) { if (cur != ports_->begin())