vhdlpp: Procedure calls.

This commit is contained in:
Maciej Suminski 2015-06-12 10:06:56 +02:00
parent d39f692cfd
commit cc9b182eb6
7 changed files with 130 additions and 31 deletions

View File

@ -311,6 +311,7 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
%type <interface_list> interface_element interface_list
%type <interface_list> port_clause port_clause_opt
%type <interface_list> generic_clause generic_clause_opt
%type <interface_list> parameter_list parameter_list_opt
%type <port_mode> mode mode_opt
%type <entity_aspect> entity_aspect entity_aspect_opt binding_indication binding_indication_semicolon_opt
@ -376,7 +377,8 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
%type <exp_options> else_when_waveform selected_waveform
%type <exp_options_list> else_when_waveforms selected_waveform_list
%type <subprogram> function_specification subprogram_specification subprogram_body_start
%type <subprogram> function_specification procedure_specification
%type <subprogram> subprogram_specification subprogram_body_start
%type <severity> 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:

View File

@ -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<named_expr_t*>* param_list)
: name_(name), param_list_(param_list)
: name_(name), param_list_(param_list), def_(NULL)
{
}
ProcedureCall::ProcedureCall(perm_string name, std::list<Expression*>* param_list)
: name_(name), def_(NULL)
{
param_list_ = new std::list<named_expr_t*>;
for(std::list<Expression*>::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();

View File

@ -203,6 +203,7 @@ class ProcedureCall : public SequentialStmt {
public:
ProcedureCall(perm_string name);
ProcedureCall(perm_string name, std::list<named_expr_t*>* param_list);
ProcedureCall(perm_string name, std::list<Expression*>* param_list);
~ProcedureCall();
int elaborate(Entity*ent, ScopeBase*scope);
@ -212,6 +213,7 @@ class ProcedureCall : public SequentialStmt {
private:
perm_string name_;
std::list<named_expr_t*>* param_list_;
SubprogramHeader*def_;
};
class VariableSeqAssignment : public SequentialStmt {

View File

@ -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<named_expr_t*>::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)

View File

@ -23,7 +23,9 @@
# include "sequential.h"
# include "expression.h"
# include "architec.h"
# include "package.h"
# include "compiler.h"
# include "subprogram.h"
# include <iostream>
# include <cstdio>
# include <typeinfo>
@ -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::vector<Expression*>params(param_list_->size());
int i = 0;
for(std::list<named_expr_t*>::iterator it = param_list_->begin();
it != param_list_->end(); ++it)
params[i++] = (*it)->expr();
const Package*pkg = dynamic_cast<const Package*> (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)

View File

@ -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<InterfacePort*>::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,

View File

@ -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<InterfacePort*>::const_iterator cur = ports_->begin()
; cur != ports_->end() ; ++cur) {
if (cur != ports_->begin())