vhdlpp: Subprogram split to SubprogramHeader and SubprogramBody.
This commit is contained in:
parent
3c437874e2
commit
47c5ce0ab6
|
|
@ -101,7 +101,7 @@ int Architecture::emit(ostream&out, Entity*entity)
|
|||
errors += emit_signals(out, entity, this);
|
||||
errors += emit_variables(out, entity, this);
|
||||
|
||||
for (map<perm_string,Subprogram*>::const_iterator cur = cur_subprograms_.begin()
|
||||
for (map<perm_string,SubprogramHeader*>::const_iterator cur = cur_subprograms_.begin()
|
||||
; cur != cur_subprograms_.end() ; ++ cur) {
|
||||
// Do not emit unbounded functions, we will just need fixed instances later
|
||||
if(!cur->second->unbounded())
|
||||
|
|
|
|||
|
|
@ -150,17 +150,21 @@ void Scope::dump_scope(ostream&out) const
|
|||
}
|
||||
// Dump subprograms
|
||||
out << " -- Imported Subprograms" << endl;
|
||||
for (map<perm_string,Subprogram*>::const_iterator cur = use_subprograms_.begin()
|
||||
for (map<perm_string,SubprogramHeader*>::const_iterator cur = use_subprograms_.begin()
|
||||
; cur != use_subprograms_.end() ; ++cur) {
|
||||
out << " subprogram " << cur->first << " is" << endl;
|
||||
cur->second->dump(out);
|
||||
if(cur->second->body())
|
||||
cur->second->body()->dump(out);
|
||||
out << " end subprogram " << cur->first << endl;
|
||||
}
|
||||
out << " -- Subprograms from this scope" << endl;
|
||||
for (map<perm_string,Subprogram*>::const_iterator cur = cur_subprograms_.begin()
|
||||
for (map<perm_string,SubprogramHeader*>::const_iterator cur = cur_subprograms_.begin()
|
||||
; cur != cur_subprograms_.end() ; ++cur) {
|
||||
out << " subprogram " << cur->first << " is" << endl;
|
||||
cur->second->dump(out);
|
||||
if(cur->second->body())
|
||||
cur->second->body()->dump(out);
|
||||
out << " end subprogram " << cur->first << endl;
|
||||
}
|
||||
// Dump component declarations
|
||||
|
|
@ -467,7 +471,20 @@ ostream& ExpReal::dump_inline(ostream&out) const
|
|||
return out;
|
||||
}
|
||||
|
||||
void Subprogram::dump(ostream&fd) const
|
||||
void SubprogramBody::dump(ostream&fd) const
|
||||
{
|
||||
if (statements_== 0 || statements_->empty()) {
|
||||
fd << " <no definition>" << endl;
|
||||
} else {
|
||||
for (list<SequentialStmt*>::const_iterator cur = statements_->begin()
|
||||
; cur != statements_->end() ; ++cur) {
|
||||
SequentialStmt*curp = *cur;
|
||||
curp->dump(fd, 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SubprogramHeader::dump(ostream&fd) const
|
||||
{
|
||||
fd << " " << name_;
|
||||
|
||||
|
|
@ -493,14 +510,4 @@ void Subprogram::dump(ostream&fd) const
|
|||
fd << " return ";
|
||||
return_type_->show(fd);
|
||||
fd << endl;
|
||||
|
||||
if (statements_== 0 || statements_->empty()) {
|
||||
fd << " <no definition>" << endl;
|
||||
} else {
|
||||
for (list<SequentialStmt*>::const_iterator cur = statements_->begin()
|
||||
; cur != statements_->end() ; ++cur) {
|
||||
SequentialStmt*curp = *cur;
|
||||
curp->dump(fd, 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
class prange_t;
|
||||
class Entity;
|
||||
class ScopeBase;
|
||||
class Subprogram;
|
||||
class SubprogramHeader;
|
||||
class VType;
|
||||
class VTypeArray;
|
||||
class VTypePrimitive;
|
||||
|
|
@ -564,7 +564,7 @@ class ExpFunc : public Expression {
|
|||
private:
|
||||
perm_string name_;
|
||||
std::vector<Expression*> argv_;
|
||||
Subprogram*def_;
|
||||
SubprogramHeader*def_;
|
||||
};
|
||||
|
||||
class ExpInteger : public Expression {
|
||||
|
|
|
|||
|
|
@ -777,7 +777,7 @@ const VType*ExpFunc::probe_type(Entity*ent, ScopeBase*scope) const
|
|||
return new VTypeArray(&primitive_STDLOGIC, msb, 0);
|
||||
}
|
||||
|
||||
Subprogram*prog = scope->find_subprogram(name_);
|
||||
SubprogramHeader*prog = scope->find_subprogram(name_);
|
||||
|
||||
if(!prog)
|
||||
prog = library_find_subprogram(name_);
|
||||
|
|
@ -793,7 +793,7 @@ int ExpFunc::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*)
|
|||
int errors = 0;
|
||||
|
||||
ivl_assert(*this, scope);
|
||||
Subprogram*prog = scope->find_subprogram(name_);
|
||||
SubprogramHeader*prog = scope->find_subprogram(name_);
|
||||
|
||||
if(!prog)
|
||||
prog = library_find_subprogram(name_);
|
||||
|
|
@ -878,7 +878,7 @@ const VType* ExpFunc::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*) c
|
|||
}
|
||||
|
||||
// Other cases
|
||||
Subprogram*prog = def_;
|
||||
SubprogramHeader*prog = def_;
|
||||
|
||||
if(!prog) {
|
||||
ivl_assert(*this, scope);
|
||||
|
|
|
|||
|
|
@ -72,9 +72,9 @@ void library_add_directory(const char*directory)
|
|||
library_search_path.push_front(directory);
|
||||
}
|
||||
|
||||
Subprogram*library_find_subprogram(perm_string name)
|
||||
SubprogramHeader*library_find_subprogram(perm_string name)
|
||||
{
|
||||
Subprogram*subp = NULL;
|
||||
SubprogramHeader*subp = NULL;
|
||||
map<perm_string,struct library_contents>::const_iterator lib_it;
|
||||
|
||||
for(lib_it = libraries.begin(); lib_it != libraries.end(); ++lib_it) {
|
||||
|
|
|
|||
|
|
@ -19,12 +19,12 @@
|
|||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
class Subprogram;
|
||||
class SubprogramHeader;
|
||||
|
||||
extern void library_set_work_path(const char*work_path);
|
||||
extern void library_add_directory(const char*directory);
|
||||
|
||||
extern Subprogram*library_find_subprogram(perm_string name);
|
||||
extern SubprogramHeader*library_find_subprogram(perm_string name);
|
||||
|
||||
extern void emit_std_types(ostream&out);
|
||||
extern int emit_packages(void);
|
||||
|
|
|
|||
|
|
@ -111,9 +111,10 @@ void Package::write_to_stream(ostream&fd) const
|
|||
fd << ";" << endl;
|
||||
}
|
||||
|
||||
for (map<perm_string,Subprogram*>::const_iterator cur = cur_subprograms_.begin()
|
||||
for (map<perm_string,SubprogramHeader*>::const_iterator cur = cur_subprograms_.begin()
|
||||
; cur != cur_subprograms_.end() ; ++cur) {
|
||||
cur->second->write_to_stream(fd);
|
||||
fd << ";" << endl;
|
||||
}
|
||||
|
||||
for (map<perm_string,ComponentBase*>::const_iterator cur = old_components_.begin()
|
||||
|
|
@ -130,9 +131,14 @@ void Package::write_to_stream(ostream&fd) const
|
|||
fd << "end package " << name_ << ";" << endl;
|
||||
|
||||
fd << "package body " << name_ << " is" << endl;
|
||||
for (map<perm_string,Subprogram*>::const_iterator cur = cur_subprograms_.begin()
|
||||
for (map<perm_string,SubprogramHeader*>::const_iterator cur = cur_subprograms_.begin()
|
||||
; cur != cur_subprograms_.end() ; ++cur) {
|
||||
cur->second->write_to_stream_body(fd);
|
||||
SubprogramHeader*subp = cur->second;
|
||||
if(subp->body()) {
|
||||
subp->write_to_stream(fd);
|
||||
fd << " is" << endl;
|
||||
subp->body()->write_to_stream(fd);
|
||||
}
|
||||
}
|
||||
fd << "end " << name_ << ";" << endl;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ class Package : public Scope, public LineInfo {
|
|||
|
||||
perm_string name() const { return name_; }
|
||||
|
||||
Subprogram* recall_subprogram(perm_string name) const;
|
||||
SubprogramHeader* recall_subprogram(perm_string name) const;
|
||||
|
||||
// This method writes a package header to a library file.
|
||||
void write_to_stream(std::ostream&fd) const;
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ int Package::emit_package(ostream&fd) const
|
|||
//}
|
||||
|
||||
fd << "package \\" << name() << " ;" << endl;
|
||||
for (map<perm_string,Subprogram*>::const_iterator cur = cur_subprograms_.begin()
|
||||
for (map<perm_string,SubprogramHeader*>::const_iterator cur = cur_subprograms_.begin()
|
||||
; cur != cur_subprograms_.end() ; ++ cur) {
|
||||
// Do not emit unbounded functions, we will just need fixed instances later
|
||||
if(!cur->second->unbounded())
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ extern int yylex(union YYSTYPE*yylvalp,YYLTYPE*yyllocp,yyscan_t yyscanner);
|
|||
*/
|
||||
static ActiveScope*active_scope = new ActiveScope;
|
||||
static stack<ActiveScope*> scope_stack;
|
||||
static Subprogram*active_sub = NULL;
|
||||
static SubprogramHeader*active_sub = NULL;
|
||||
|
||||
// perm_strings for attributes
|
||||
const static perm_string left_attr = perm_string::literal("left");
|
||||
|
|
@ -262,7 +262,7 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
|
|||
|
||||
ReportStmt::severity_t severity;
|
||||
|
||||
Subprogram*subprogram;
|
||||
SubprogramHeader*subprogram;
|
||||
};
|
||||
|
||||
/* The keywords are all tokens. */
|
||||
|
|
@ -374,6 +374,7 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
|
|||
%type <exp_options_list> else_when_waveforms selected_waveform_list
|
||||
|
||||
%type <subprogram> function_specification subprogram_specification subprogram_body_start
|
||||
|
||||
%type <severity> severity severity_opt
|
||||
|
||||
%%
|
||||
|
|
@ -1246,8 +1247,8 @@ function_specification /* IEEE 1076-2008 P4.2.1 */
|
|||
perm_string name = lex_strings.make($2);
|
||||
const VType*type_mark = active_scope->find_type(type_name);
|
||||
touchup_interface_for_functions($4);
|
||||
Subprogram*tmp = new Subprogram(name, $4, type_mark);
|
||||
FILE_NAME(tmp,@1);
|
||||
SubprogramHeader*tmp = new SubprogramHeader(name, $4, type_mark);
|
||||
FILE_NAME(tmp, @1);
|
||||
delete[]$2;
|
||||
delete[]$7;
|
||||
$$ = tmp;
|
||||
|
|
@ -2420,16 +2421,20 @@ subprogram_body /* IEEE 1076-2008 P4.3 */
|
|||
: subprogram_body_start subprogram_declarative_part
|
||||
K_begin subprogram_statement_part K_end
|
||||
subprogram_kind_opt identifier_opt ';'
|
||||
{ Subprogram*prog = $1;
|
||||
Subprogram*tmp = active_scope->recall_subprogram(prog->name());
|
||||
{ SubprogramHeader*prog = $1;
|
||||
SubprogramHeader*tmp = active_scope->recall_subprogram(prog->name());
|
||||
if (tmp && prog->compare_specification(tmp)) {
|
||||
delete prog;
|
||||
prog = tmp;
|
||||
} else if (tmp) {
|
||||
errormsg(@1, "Subprogram specification for %s doesn't match specification in package header.\n", prog->name().str());
|
||||
}
|
||||
prog->transfer_from(*active_scope, ScopeBase::VARIABLES);
|
||||
prog->set_program_body($4);
|
||||
|
||||
SubprogramBody*body = new SubprogramBody();
|
||||
body->transfer_from(*active_scope, ScopeBase::VARIABLES);
|
||||
body->set_statements($4);
|
||||
|
||||
prog->set_body(body);
|
||||
active_scope->bind_name(prog->name(), prog);
|
||||
active_sub = NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,8 +65,8 @@ ScopeBase::ScopeBase(const ActiveScope&ref)
|
|||
// an active scope and is making the actual scope. At this point
|
||||
// we know that "this" is the parent scope for the subprograms,
|
||||
// so set it now.
|
||||
for (map<perm_string,Subprogram*>::iterator cur = cur_subprograms_.begin()
|
||||
; cur != cur_subprograms_.end() ; ++ cur) {
|
||||
for (map<perm_string,SubprogramHeader*>::iterator cur = cur_subprograms_.begin()
|
||||
; cur != cur_subprograms_.end(); ++cur) {
|
||||
cur->second->set_parent(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -158,13 +158,13 @@ Variable* ScopeBase::find_variable(perm_string by_name) const
|
|||
|
||||
const InterfacePort* ScopeBase::find_param(perm_string by_name) const
|
||||
{
|
||||
for(map<perm_string,Subprogram*>::const_iterator it = use_subprograms_.begin();
|
||||
for(map<perm_string,SubprogramHeader*>::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<perm_string,Subprogram*>::const_iterator it = cur_subprograms_.begin();
|
||||
for(map<perm_string,SubprogramHeader*>::const_iterator it = cur_subprograms_.begin();
|
||||
it != cur_subprograms_.end(); ++it) {
|
||||
if(const InterfacePort*port = it->second->find_param(by_name))
|
||||
return port;
|
||||
|
|
@ -173,9 +173,9 @@ const InterfacePort* ScopeBase::find_param(perm_string by_name) const
|
|||
return NULL;
|
||||
}
|
||||
|
||||
Subprogram* ScopeBase::find_subprogram(perm_string name) const
|
||||
SubprogramHeader* ScopeBase::find_subprogram(perm_string name) const
|
||||
{
|
||||
map<perm_string,Subprogram*>::const_iterator cur;
|
||||
map<perm_string,SubprogramHeader*>::const_iterator cur;
|
||||
|
||||
cur = cur_subprograms_.find(name);
|
||||
if (cur != cur_subprograms_.end())
|
||||
|
|
@ -218,7 +218,7 @@ void ScopeBase::do_use_from(const ScopeBase*that)
|
|||
old_components_[cur->first] = cur->second;
|
||||
}
|
||||
|
||||
for (map<perm_string,Subprogram*>::const_iterator cur = that->cur_subprograms_.begin()
|
||||
for (map<perm_string,SubprogramHeader*>::const_iterator cur = that->cur_subprograms_.begin()
|
||||
; cur != that->cur_subprograms_.end() ; ++ cur) {
|
||||
if (cur->second == 0)
|
||||
continue;
|
||||
|
|
@ -274,9 +274,9 @@ void ActiveScope::set_package_header(Package*pkg)
|
|||
package_header_ = pkg;
|
||||
}
|
||||
|
||||
Subprogram* ActiveScope::recall_subprogram(perm_string name) const
|
||||
SubprogramHeader* ActiveScope::recall_subprogram(perm_string name) const
|
||||
{
|
||||
if (Subprogram*tmp = find_subprogram(name))
|
||||
if (SubprogramHeader*tmp = find_subprogram(name))
|
||||
return tmp;
|
||||
|
||||
if (package_header_)
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class ActiveScope;
|
|||
class Architecture;
|
||||
class ComponentBase;
|
||||
class Package;
|
||||
class Subprogram;
|
||||
class SubprogramHeader;
|
||||
class VType;
|
||||
|
||||
template<typename T>
|
||||
|
|
@ -57,7 +57,7 @@ class ScopeBase {
|
|||
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;
|
||||
SubprogramHeader* find_subprogram(perm_string by_name) const;
|
||||
// Checks if a string is one of possible enum values. If so, the enum
|
||||
// type is returned, otherwise NULL.
|
||||
const VTypeEnum* is_enum_name(perm_string name) const;
|
||||
|
|
@ -67,8 +67,8 @@ class ScopeBase {
|
|||
enum transfer_type_t { SIGNALS = 1, VARIABLES = 2, COMPONENTS = 4, ALL = 0xffff };
|
||||
void transfer_from(ScopeBase&ref, transfer_type_t what = ALL);
|
||||
|
||||
inline void bind_subprogram(perm_string name, Subprogram*obj)
|
||||
{ map<perm_string, Subprogram*>::iterator it;
|
||||
inline void bind_subprogram(perm_string name, SubprogramHeader*obj)
|
||||
{ map<perm_string, SubprogramHeader*>::iterator it;
|
||||
if((it = use_subprograms_.find(name)) != use_subprograms_.end() )
|
||||
use_subprograms_.erase(it);
|
||||
cur_subprograms_[name] = obj;
|
||||
|
|
@ -116,8 +116,8 @@ class ScopeBase {
|
|||
std::map<perm_string, struct const_t*> use_constants_; //imported constants
|
||||
std::map<perm_string, struct const_t*> cur_constants_; //current constants
|
||||
|
||||
std::map<perm_string, Subprogram*> use_subprograms_; //imported
|
||||
std::map<perm_string, Subprogram*> cur_subprograms_; //current
|
||||
std::map<perm_string, SubprogramHeader*> use_subprograms_; //imported
|
||||
std::map<perm_string, SubprogramHeader*> cur_subprograms_; //current
|
||||
|
||||
std::list<const VTypeEnum*> use_enums_;
|
||||
|
||||
|
|
@ -170,7 +170,7 @@ class ActiveScope : public ScopeBase {
|
|||
// Locate the subprogram by name. The subprogram body uses
|
||||
// this to locate the sobprogram declaration. Note that the
|
||||
// subprogram may be in a package header.
|
||||
Subprogram* recall_subprogram(perm_string name) const;
|
||||
SubprogramHeader* recall_subprogram(perm_string name) const;
|
||||
|
||||
/* All bind_name function check if the given name was present
|
||||
* in previous scopes. If it is found, it is erased (but the pointer
|
||||
|
|
@ -219,8 +219,8 @@ class ActiveScope : public ScopeBase {
|
|||
cur_constants_[name] = new const_t(obj, val);
|
||||
}
|
||||
|
||||
inline void bind_name(perm_string name, Subprogram*obj)
|
||||
{ map<perm_string, Subprogram*>::iterator it;
|
||||
inline void bind_name(perm_string name, SubprogramHeader*obj)
|
||||
{ map<perm_string, SubprogramHeader*>::iterator it;
|
||||
if((it = use_subprograms_.find(name)) != use_subprograms_.end() )
|
||||
use_subprograms_.erase(it);
|
||||
cur_subprograms_[name] = obj;
|
||||
|
|
|
|||
|
|
@ -30,44 +30,61 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
Subprogram::Subprogram(perm_string nam, list<InterfacePort*>*ports,
|
||||
const VType*return_type)
|
||||
: name_(nam), parent_(0), ports_(ports), return_type_(return_type), statements_(0)
|
||||
SubprogramBody::SubprogramBody()
|
||||
: statements_(NULL), header_(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
Subprogram::~Subprogram()
|
||||
SubprogramBody::~SubprogramBody()
|
||||
{
|
||||
}
|
||||
|
||||
void Subprogram::set_parent(const ScopeBase*par)
|
||||
const InterfacePort*SubprogramBody::find_param(perm_string nam) const
|
||||
{
|
||||
ivl_assert(*this, parent_ == 0);
|
||||
parent_ = par;
|
||||
if(!header_)
|
||||
return NULL;
|
||||
|
||||
return header_->find_param(nam);
|
||||
}
|
||||
|
||||
void Subprogram::set_program_body(list<SequentialStmt*>*stmt)
|
||||
void SubprogramBody::set_statements(list<SequentialStmt*>*stmt)
|
||||
{
|
||||
ivl_assert(*this, statements_==0);
|
||||
statements_ = stmt;
|
||||
}
|
||||
|
||||
bool Subprogram::unbounded() const {
|
||||
if(return_type_->is_unbounded())
|
||||
return true;
|
||||
|
||||
if(ports_) {
|
||||
for(std::list<InterfacePort*>::const_iterator it = ports_->begin();
|
||||
it != ports_->end(); ++it) {
|
||||
if((*it)->type->is_unbounded())
|
||||
return true;
|
||||
}
|
||||
void SubprogramBody::write_to_stream(ostream&fd) const
|
||||
{
|
||||
for (map<perm_string,Variable*>::const_iterator cur = new_variables_.begin()
|
||||
; cur != new_variables_.end() ; ++cur) {
|
||||
cur->second->write_to_stream(fd);
|
||||
}
|
||||
|
||||
return false;
|
||||
fd << "begin" << endl;
|
||||
|
||||
if (statements_) {
|
||||
for (list<SequentialStmt*>::const_iterator cur = statements_->begin()
|
||||
; cur != statements_->end() ; ++cur) {
|
||||
(*cur)->write_to_stream(fd);
|
||||
}
|
||||
} else {
|
||||
fd << "--empty body" << endl;
|
||||
}
|
||||
fd << "end function;" << endl;
|
||||
}
|
||||
|
||||
bool Subprogram::compare_specification(Subprogram*that) const
|
||||
SubprogramHeader::SubprogramHeader(perm_string nam, list<InterfacePort*>*ports,
|
||||
const VType*return_type)
|
||||
: name_(nam), ports_(ports), return_type_(return_type), body_(NULL), parent_(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
SubprogramHeader::~SubprogramHeader()
|
||||
{
|
||||
delete body_;
|
||||
}
|
||||
|
||||
bool SubprogramHeader::compare_specification(SubprogramHeader*that) const
|
||||
{
|
||||
if (name_ != that->name_)
|
||||
return false;
|
||||
|
|
@ -98,7 +115,7 @@ bool Subprogram::compare_specification(Subprogram*that) const
|
|||
return true;
|
||||
}
|
||||
|
||||
const InterfacePort*Subprogram::find_param(perm_string nam) const
|
||||
const InterfacePort*SubprogramHeader::find_param(perm_string nam) const
|
||||
{
|
||||
if(!ports_)
|
||||
return NULL;
|
||||
|
|
@ -112,7 +129,7 @@ const InterfacePort*Subprogram::find_param(perm_string nam) const
|
|||
return NULL;
|
||||
}
|
||||
|
||||
const VType*Subprogram::peek_param_type(int idx) const
|
||||
const VType*SubprogramHeader::peek_param_type(int idx) const
|
||||
{
|
||||
if(!ports_ || idx < 0 || (size_t)idx >= ports_->size())
|
||||
return NULL;
|
||||
|
|
@ -123,7 +140,37 @@ const VType*Subprogram::peek_param_type(int idx) const
|
|||
return (*p)->type;
|
||||
}
|
||||
|
||||
Subprogram*Subprogram::make_instance(std::vector<Expression*> arguments, ScopeBase*scope) {
|
||||
void SubprogramHeader::set_parent(const ScopeBase*par)
|
||||
{
|
||||
ivl_assert(*this, !parent_);
|
||||
parent_ = par;
|
||||
}
|
||||
|
||||
bool SubprogramHeader::unbounded() const {
|
||||
if(return_type_->is_unbounded())
|
||||
return true;
|
||||
|
||||
if(ports_) {
|
||||
for(std::list<InterfacePort*>::const_iterator it = ports_->begin();
|
||||
it != ports_->end(); ++it) {
|
||||
if((*it)->type->is_unbounded())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void SubprogramHeader::set_body(SubprogramBody*bdy)
|
||||
{
|
||||
ivl_assert(*this, !body_);
|
||||
body_ = bdy;
|
||||
ivl_assert(*this, !bdy->header_);
|
||||
bdy->header_ = this;
|
||||
}
|
||||
|
||||
SubprogramHeader*SubprogramHeader::make_instance(std::vector<Expression*> arguments,
|
||||
ScopeBase*scope) {
|
||||
assert(arguments.size() == ports_->size());
|
||||
|
||||
std::list<InterfacePort*>*ports = new std::list<InterfacePort*>;
|
||||
|
|
@ -142,25 +189,31 @@ Subprogram*Subprogram::make_instance(std::vector<Expression*> arguments, ScopeBa
|
|||
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_);
|
||||
SubprogramHeader*instance = new SubprogramHeader(new_name, ports, return_type_);
|
||||
|
||||
if(body_) {
|
||||
SubprogramBody*body_inst = new SubprogramBody();
|
||||
|
||||
// Copy variables
|
||||
for(std::map<perm_string,Variable*>::iterator it = new_variables_.begin();
|
||||
it != new_variables_.end(); ++it) {
|
||||
for(std::map<perm_string,Variable*>::iterator it = body_->new_variables_.begin();
|
||||
it != body_->new_variables_.end(); ++it) {
|
||||
Variable*v = new Variable(it->first, it->second->peek_type()->clone());
|
||||
instance->new_variables_[it->first] = v;
|
||||
body_inst->new_variables_[it->first] = v;
|
||||
}
|
||||
|
||||
body_inst->set_statements(body_->statements_);
|
||||
instance->set_parent(scope);
|
||||
instance->set_program_body(statements_);
|
||||
instance->set_body(body_inst);
|
||||
instance->fix_return_type();
|
||||
}
|
||||
|
||||
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) {}
|
||||
check_return_type(const SubprogramBody*subp) : subp_(subp), ret_type_(NULL) {}
|
||||
|
||||
void operator() (SequentialStmt*s)
|
||||
{
|
||||
|
|
@ -195,54 +248,35 @@ struct check_return_type : public SeqStmtVisitor {
|
|||
const VType*get_type() const { return ret_type_; }
|
||||
|
||||
private:
|
||||
const Subprogram*subp_;
|
||||
const SubprogramBody*subp_;
|
||||
const VType*ret_type_;
|
||||
};
|
||||
|
||||
void Subprogram::fix_return_type()
|
||||
void SubprogramHeader::fix_return_type()
|
||||
{
|
||||
if(!statements_)
|
||||
if(!body_ || !body_->statements_)
|
||||
return;
|
||||
|
||||
check_return_type r(this);
|
||||
check_return_type r(body_);
|
||||
|
||||
for (std::list<SequentialStmt*>::iterator s = statements_->begin()
|
||||
; s != statements_->end(); ++s) {
|
||||
for (std::list<SequentialStmt*>::iterator s = body_->statements_->begin()
|
||||
; s != body_->statements_->end(); ++s) {
|
||||
(*s)->visit(r);
|
||||
}
|
||||
|
||||
VType*return_type = const_cast<VType*>(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 not, then it depends on information about e.g. function params
|
||||
if(return_type->is_variable_length(NULL)) {
|
||||
if(VTypeArray*arr = dynamic_cast<VTypeArray*>(return_type))
|
||||
arr->evaluate_ranges(this);
|
||||
arr->evaluate_ranges(body_);
|
||||
}
|
||||
return_type_ = return_type;
|
||||
}
|
||||
}
|
||||
|
||||
void Subprogram::write_to_stream(ostream&fd) const
|
||||
{
|
||||
fd << " function " << name_ << "(";
|
||||
if (ports_ && ! ports_->empty()) {
|
||||
list<InterfacePort*>::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 << ";" << endl;
|
||||
}
|
||||
|
||||
void Subprogram::write_to_stream_body(ostream&fd) const
|
||||
void SubprogramHeader::write_to_stream(ostream&fd) const
|
||||
{
|
||||
fd << "function " << name_ << "(";
|
||||
if (ports_ && ! ports_->empty()) {
|
||||
|
|
@ -258,22 +292,4 @@ void Subprogram::write_to_stream_body(ostream&fd) const
|
|||
}
|
||||
fd << ") return ";
|
||||
return_type_->write_to_stream(fd);
|
||||
fd << " is" << endl;
|
||||
|
||||
for (map<perm_string,Variable*>::const_iterator cur = new_variables_.begin()
|
||||
; cur != new_variables_.end() ; ++cur) {
|
||||
cur->second->write_to_stream(fd);
|
||||
}
|
||||
|
||||
fd << "begin" << endl;
|
||||
|
||||
if (statements_) {
|
||||
for (list<SequentialStmt*>::const_iterator cur = statements_->begin()
|
||||
; cur != statements_->end() ; ++cur) {
|
||||
(*cur)->write_to_stream(fd);
|
||||
}
|
||||
} else {
|
||||
fd << "--empty body" << endl;
|
||||
}
|
||||
fd << "end function;" << endl;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,51 +27,75 @@
|
|||
# include "scope.h"
|
||||
# include <iostream>
|
||||
# include <list>
|
||||
# include <cassert>
|
||||
|
||||
class InterfacePort;
|
||||
class SequentialStmt;
|
||||
class VType;
|
||||
class SubprogramHeader;
|
||||
|
||||
class Subprogram : public LineInfo, public ScopeBase {
|
||||
class SubprogramBody : public LineInfo, public ScopeBase {
|
||||
|
||||
public:
|
||||
Subprogram(perm_string name, std::list<InterfacePort*>*ports,
|
||||
SubprogramBody();
|
||||
~SubprogramBody();
|
||||
|
||||
const InterfacePort*find_param(perm_string nam) const;
|
||||
|
||||
void set_statements(std::list<SequentialStmt*>*statements);
|
||||
inline bool empty_statements() const { return !statements_ || statements_->empty(); }
|
||||
|
||||
int emit(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
|
||||
// Emit body as it would show up in a package.
|
||||
int emit_package(std::ostream&fd) const;
|
||||
|
||||
void write_to_stream(std::ostream&fd) const;
|
||||
void dump(std::ostream&fd) const;
|
||||
|
||||
private:
|
||||
std::list<SequentialStmt*>*statements_;
|
||||
SubprogramHeader*header_;
|
||||
|
||||
friend class SubprogramHeader;
|
||||
};
|
||||
|
||||
class SubprogramHeader : public LineInfo {
|
||||
public:
|
||||
SubprogramHeader(perm_string name, std::list<InterfacePort*>*ports,
|
||||
const VType*return_type);
|
||||
~Subprogram();
|
||||
|
||||
void set_parent(const ScopeBase*par);
|
||||
inline const ScopeBase*get_parent() const { return parent_; }
|
||||
|
||||
inline const perm_string&name() const { return name_; }
|
||||
|
||||
void set_program_body(std::list<SequentialStmt*>*statements);
|
||||
inline bool empty_program_body() const { return !statements_ || statements_->empty(); }
|
||||
~SubprogramHeader();
|
||||
|
||||
// Return true if the specification (name, types, ports)
|
||||
// matches this subprogram and that subprogram.
|
||||
bool compare_specification(Subprogram*that) const;
|
||||
bool compare_specification(SubprogramHeader*that) const;
|
||||
|
||||
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, ScopeBase*scope);
|
||||
void set_parent(const ScopeBase*par);
|
||||
inline const ScopeBase*get_parent() const { return parent_; }
|
||||
|
||||
// Emit a definition as it would show up in a package.
|
||||
int emit_package(std::ostream&fd) const;
|
||||
// Checks if either return type or parameters are unbounded vectors.
|
||||
bool unbounded() const;
|
||||
|
||||
void write_to_stream(std::ostream&fd) const;
|
||||
void write_to_stream_body(std::ostream&fd) const;
|
||||
void dump(std::ostream&fd) const;
|
||||
inline SubprogramBody*body() { return body_; }
|
||||
void set_body(SubprogramBody*bdy);
|
||||
|
||||
inline perm_string name() { return name_; }
|
||||
|
||||
// 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<Expression*> arguments, ScopeBase*scope);
|
||||
SubprogramHeader*make_instance(std::vector<Expression*> arguments, ScopeBase*scope);
|
||||
|
||||
// Checks if either return type or parameters are unbounded vectors.
|
||||
bool unbounded() const;
|
||||
// Emit header as it would show up in a package.
|
||||
int emit_package(std::ostream&fd) const;
|
||||
|
||||
void write_to_stream(std::ostream&fd) const;
|
||||
void dump(std::ostream&fd) const;
|
||||
|
||||
private:
|
||||
// Tries to set the return type to a fixed type. VHDL functions that
|
||||
|
|
@ -79,11 +103,13 @@ class Subprogram : public LineInfo, public ScopeBase {
|
|||
// demands.
|
||||
void fix_return_type();
|
||||
|
||||
// Procedure/function name
|
||||
perm_string name_;
|
||||
const ScopeBase*parent_;
|
||||
|
||||
std::list<InterfacePort*>*ports_;
|
||||
const VType*return_type_;
|
||||
std::list<SequentialStmt*>*statements_;
|
||||
SubprogramBody*body_;
|
||||
const ScopeBase*parent_;
|
||||
};
|
||||
|
||||
#endif /* IVL_subprogram_H */
|
||||
|
|
|
|||
|
|
@ -25,7 +25,30 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
int Subprogram::emit_package(ostream&fd) const
|
||||
int SubprogramBody::emit_package(ostream&fd) const
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
for (map<perm_string,Variable*>::const_iterator cur = new_variables_.begin()
|
||||
; cur != new_variables_.end() ; ++cur) {
|
||||
// Workaround to enable reg_flag for variables
|
||||
cur->second->count_ref_sequ();
|
||||
errors += cur->second->emit(fd, NULL, NULL);
|
||||
}
|
||||
|
||||
if (statements_) {
|
||||
for (list<SequentialStmt*>::const_iterator cur = statements_->begin()
|
||||
; cur != statements_->end() ; ++cur) {
|
||||
errors += (*cur)->emit(fd, NULL, const_cast<SubprogramBody*>(this));
|
||||
}
|
||||
} else {
|
||||
fd << " begin /* empty body */ end" << endl;
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int SubprogramHeader::emit_package(ostream&fd) const
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
|
|
@ -63,21 +86,8 @@ int Subprogram::emit_package(ostream&fd) const
|
|||
|
||||
fd << ");" << endl;
|
||||
|
||||
for (map<perm_string,Variable*>::const_iterator cur = new_variables_.begin()
|
||||
; cur != new_variables_.end() ; ++cur) {
|
||||
// Workaround to enable reg_flag for variables
|
||||
cur->second->count_ref_sequ();
|
||||
errors += cur->second->emit(fd, NULL, NULL);
|
||||
}
|
||||
|
||||
if (statements_) {
|
||||
for (list<SequentialStmt*>::const_iterator cur = statements_->begin()
|
||||
; cur != statements_->end() ; ++cur) {
|
||||
errors += (*cur)->emit(fd, NULL, const_cast<Subprogram*>(this));
|
||||
}
|
||||
} else {
|
||||
fd << " begin /* empty body */ end" << endl;
|
||||
}
|
||||
if (body_)
|
||||
body_->emit_package(fd);
|
||||
|
||||
if (return_type_)
|
||||
fd << "endfunction" << endl;
|
||||
|
|
@ -86,3 +96,23 @@ int Subprogram::emit_package(ostream&fd) const
|
|||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int SubprogramHeader::emit_name(const std::vector<Expression*>&,
|
||||
std::ostream&out, Entity*, ScopeBase*) const
|
||||
{
|
||||
out << "\\" << name_;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SubprogramHeader::emit_args(const std::vector<Expression*>&argv,
|
||||
std::ostream&out, Entity*ent, ScopeBase*scope) const
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
for (size_t idx = 0; idx < argv.size() ; idx += 1) {
|
||||
if (idx > 0) out << ", ";
|
||||
errors += argv[idx]->emit(out, ent, scope);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue