vhdlpp: Procedure calls.
This commit is contained in:
parent
d39f692cfd
commit
cc9b182eb6
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
Loading…
Reference in New Issue