vhdlpp: Elaborate subprograms in packages.

This commit is contained in:
Maciej Suminski 2015-12-10 10:42:46 +01:00
parent 517c9785e8
commit 3b310e8227
10 changed files with 101 additions and 26 deletions

View File

@ -21,6 +21,7 @@
# include "entity.h"
# include "expression.h"
# include "sequential.h"
# include "subprogram.h"
# include <typeinfo>
# include <cassert>
@ -59,6 +60,11 @@ int Architecture::elaborate(Entity*entity)
cur->second->elaborate_init_expr(entity, this);
}
// Elaborate subprograms
for (map<perm_string,SubprogramHeader*>::const_iterator cur = cur_subprograms_.begin()
; cur != cur_subprograms_.end() ; ++cur) {
errors += cur->second->elaborate();
}
// Create 'initial' and 'final' blocks for implicit
// initalization and clean-up actions
if(!initializers_.empty())

View File

@ -216,36 +216,44 @@ int ExpName::elaborate_lval(Entity*ent, ScopeBase*scope, bool is_sequ)
const VType*found_type = 0;
if (const InterfacePort*cur = ent->find_port(name_)) {
if (cur->mode != PORT_OUT && cur->mode != PORT_INOUT) {
cerr << get_fileline() << ": error: Assignment to "
"input port " << name_ << "." << endl;
return errors += 1;
}
if (ent) {
if (const InterfacePort*cur = ent->find_port(name_)) {
if (cur->mode != PORT_OUT && cur->mode != PORT_INOUT) {
cerr << get_fileline() << ": error: Assignment to "
"input port " << name_ << "." << endl;
return errors += 1;
}
if (is_sequ)
ent->set_declaration_l_value(name_, is_sequ);
if (is_sequ)
ent->set_declaration_l_value(name_, is_sequ);
found_type = cur->type;
found_type = cur->type;
} else if (ent->find_generic(name_)) {
} else if (ent->find_generic(name_)) {
cerr << get_fileline() << ": error: Assignment to generic "
<< name_ << " from entity "
<< ent->get_name() << "." << endl;
return 1;
cerr << get_fileline() << ": error: Assignment to generic "
<< name_ << " from entity "
<< ent->get_name() << "." << endl;
return 1;
}
}
} 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();
if (!found_type && scope) {
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();
found_type = sig->peek_type();
} 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();
} 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();
found_type = var->peek_type();
found_type = var->peek_type();
} else if (const InterfacePort*port = scope->find_param(name_)) {
found_type = port->type;
}
}
if (found_type == 0) {

View File

@ -417,3 +417,27 @@ int emit_packages(void)
return 0;
}
static int elaborate_library_packages(map<perm_string,Package*>packages)
{
int errors = 0;
for (map<perm_string,Package*>::iterator cur = packages.begin()
; cur != packages.end() ; ++cur) {
errors += cur->second->elaborate();
}
return errors;
}
int elaborate_libraries()
{
int errors = 0;
for (map<perm_string,struct library_contents>::iterator cur = libraries.begin()
; cur != libraries.end() ; ++cur) {
errors += elaborate_library_packages(cur->second.packages);
}
return errors;
}

View File

@ -24,6 +24,9 @@ class SubprogramHeader;
extern void library_set_work_path(const char*work_path);
extern void library_add_directory(const char*directory);
int elaborate_libraries(void);
int emit_packages(void);
extern SubprogramHeader*library_find_subprogram(perm_string name);
#endif /* IVL_library_H */

View File

@ -236,20 +236,27 @@ int main(int argc, char*argv[])
return 3;
}
errors = elaborate_libraries();
if (errors > 0) {
fprintf(stderr, "%d errors elaborating libraries.\n", errors);
parser_cleanup();
return 4;
}
emit_std_types(cout);
errors = emit_packages();
if (errors > 0) {
fprintf(stderr, "%d errors emitting packages.\n", errors);
parser_cleanup();
return 4;
return 5;
}
errors = emit_entities();
if (errors > 0) {
fprintf(stderr, "%d errors emitting design.\n", errors);
parser_cleanup();
return 4;
parser_cleanup();
return 6;
}
parser_cleanup();

View File

@ -41,6 +41,18 @@ void Package::set_library(perm_string lname)
from_library_ = lname;
}
int Package::elaborate()
{
int errors = 0;
for (map<perm_string,SubprogramHeader*>::const_iterator cur = cur_subprograms_.begin()
; cur != cur_subprograms_.end() ; ++cur) {
errors += cur->second->elaborate();
}
return errors;
}
/*
* The Package::write_to_stream is used to write the package to the
* work space (or library) so writes proper VHDL that the library

View File

@ -42,6 +42,7 @@ class Package : public Scope, public LineInfo {
void write_to_stream(std::ostream&fd) const;
int emit_package(std::ostream&fd) const;
int elaborate();
private:
perm_string from_library_;

View File

@ -23,7 +23,6 @@
class ActiveScope;
void emit_std_types(ostream&out);
int emit_packages(void);
void generate_global_types(ActiveScope*res);
bool is_global_type(perm_string type_name);
void delete_global_types();

View File

@ -53,6 +53,18 @@ void SubprogramBody::set_statements(list<SequentialStmt*>*stmt)
statements_ = stmt;
}
int SubprogramBody::elaborate()
{
int errors = 0;
for (list<SequentialStmt*>::const_iterator cur = statements_->begin()
; cur != statements_->end() ; ++cur) {
errors += (*cur)->elaborate(0, this);
}
return errors;
}
void SubprogramBody::write_to_stream(ostream&fd) const
{
for (map<perm_string,Variable*>::const_iterator cur = new_variables_.begin()

View File

@ -45,6 +45,7 @@ class SubprogramBody : public LineInfo, public ScopeBase {
void set_statements(std::list<SequentialStmt*>*statements);
inline bool empty_statements() const { return !statements_ || statements_->empty(); }
int elaborate();
int emit(ostream&out, Entity*ent, ScopeBase*scope);
// Emit body as it would show up in a package.
@ -89,6 +90,8 @@ class SubprogramHeader : public LineInfo {
inline perm_string name() const { return name_; }
int elaborate() { return (body_ ? body_->elaborate() : 0); }
// Function name used in the emission step. The main purpose of this
// method is to handle functions offered by standard VHDL libraries.
// Allows to return different function names depending on the arguments