commit
2397aa1587
|
|
@ -21,6 +21,7 @@
|
|||
# include "entity.h"
|
||||
# include "expression.h"
|
||||
# include "sequential.h"
|
||||
# include "subprogram.h"
|
||||
# include "vsignal.h"
|
||||
# include <iostream>
|
||||
# include <typeinfo>
|
||||
|
|
|
|||
|
|
@ -34,8 +34,4 @@ extern StringHeapLex lex_strings;
|
|||
|
||||
extern StringHeapLex filename_strings;
|
||||
|
||||
extern void library_set_work_path(const char*work_path);
|
||||
extern void library_add_directory(const char*directory);
|
||||
extern int emit_packages(void);
|
||||
|
||||
#endif /* IVL_compiler_H */
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
# include "architec.h"
|
||||
# include "expression.h"
|
||||
# include "parse_types.h"
|
||||
# include "subprogram.h"
|
||||
# include "sequential.h"
|
||||
# include "vsignal.h"
|
||||
# include "vtype.h"
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@
|
|||
# include "architec.h"
|
||||
# include "entity.h"
|
||||
# include "vsignal.h"
|
||||
# include "subprogram.h"
|
||||
# include "library.h"
|
||||
# include <iostream>
|
||||
# include <typeinfo>
|
||||
# include "parse_types.h"
|
||||
|
|
@ -710,11 +712,16 @@ int ExpFunc::elaborate_expr(Entity*ent, Architecture*arc, const VType*)
|
|||
ivl_assert(*this, arc);
|
||||
Subprogram*prog = arc->find_subprogram(name_);
|
||||
|
||||
if(!prog)
|
||||
prog = library_find_subprogram(name_);
|
||||
|
||||
ivl_assert(*this, def_==0);
|
||||
def_ = prog;
|
||||
|
||||
for (size_t idx = 0 ; idx < argv_.size() ; idx += 1) {
|
||||
const VType*tmp = argv_[idx]->probe_type(ent, arc);
|
||||
if(!tmp && prog)
|
||||
tmp = prog->peek_param_type(idx);
|
||||
errors += argv_[idx]->elaborate_expr(ent, arc, tmp);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
# include "vtype.h"
|
||||
# include "architec.h"
|
||||
# include "package.h"
|
||||
# include "subprogram.h"
|
||||
# include "parse_types.h"
|
||||
# include <typeinfo>
|
||||
# include <iostream>
|
||||
|
|
|
|||
|
|
@ -69,7 +69,25 @@ void library_add_directory(const char*directory)
|
|||
return;
|
||||
}
|
||||
|
||||
library_search_path .push_front(directory);
|
||||
library_search_path.push_front(directory);
|
||||
}
|
||||
|
||||
Subprogram*library_find_subprogram(perm_string name)
|
||||
{
|
||||
Subprogram*subp = NULL;
|
||||
map<perm_string,struct library_contents>::const_iterator lib_it;
|
||||
|
||||
for(lib_it = libraries.begin(); lib_it != libraries.end(); ++lib_it) {
|
||||
const struct library_contents&lib = lib_it->second;
|
||||
map<perm_string,Package*>::const_iterator pack_it;
|
||||
|
||||
for(pack_it = lib.packages.begin(); pack_it != lib.packages.end(); ++pack_it) {
|
||||
if((subp = pack_it->second->find_subprogram(name)))
|
||||
return subp;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void store_package_in_work(const Package*pack);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
#ifndef IVL_library_H
|
||||
#define IVL_library_H
|
||||
/*
|
||||
* Copyright (c) 2011-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
class Subprogram;
|
||||
|
||||
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 int emit_packages(void);
|
||||
|
||||
#endif /* IVL_library_H */
|
||||
|
||||
|
|
@ -75,6 +75,7 @@ const char NOTICE[] =
|
|||
;
|
||||
|
||||
# include "compiler.h"
|
||||
# include "library.h"
|
||||
# include "parse_api.h"
|
||||
# include "vtype.h"
|
||||
# include <fstream>
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
# include "package.h"
|
||||
# include "entity.h"
|
||||
# include "subprogram.h"
|
||||
# include "parse_misc.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
|
||||
# include "package.h"
|
||||
# include "subprogram.h"
|
||||
# include <iostream>
|
||||
# include "ivl_assert.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -83,6 +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;
|
||||
|
||||
/*
|
||||
* When a scope boundary starts, call the push_scope function to push
|
||||
|
|
@ -106,6 +107,13 @@ static void pop_scope(void)
|
|||
scope_stack.pop();
|
||||
}
|
||||
|
||||
static bool is_subprogram_param(perm_string name)
|
||||
{
|
||||
if(!active_sub)
|
||||
return false;
|
||||
|
||||
return (active_sub->find_param(name) != NULL);
|
||||
}
|
||||
|
||||
void preload_global_types(void)
|
||||
{
|
||||
|
|
@ -1543,7 +1551,7 @@ name /* IEEE 1076-2008 P8.1 */
|
|||
| IDENTIFIER '(' expression_list ')'
|
||||
{ perm_string name = lex_strings.make($1);
|
||||
delete[]$1;
|
||||
if (active_scope->is_vector_name(name)) {
|
||||
if (active_scope->is_vector_name(name) || is_subprogram_param(name)) {
|
||||
ExpName*tmp = new ExpName(name, $3);
|
||||
$$ = tmp;
|
||||
} else {
|
||||
|
|
@ -1813,16 +1821,7 @@ procedure_call_statement
|
|||
;
|
||||
|
||||
process_declarative_item
|
||||
: K_variable identifier_list ':' subtype_indication ';'
|
||||
{ /* Save the signal declaration in the block_signals map. */
|
||||
for (std::list<perm_string>::iterator cur = $2->begin()
|
||||
; cur != $2->end() ; ++cur) {
|
||||
Variable*sig = new Variable(*cur, $4);
|
||||
FILE_NAME(sig, @1);
|
||||
active_scope->bind_name(*cur, sig);
|
||||
}
|
||||
delete $2;
|
||||
}
|
||||
: variable_declaration
|
||||
;
|
||||
|
||||
process_declarative_part
|
||||
|
|
@ -2175,6 +2174,7 @@ signal_assignment_statement
|
|||
|
||||
subprogram_body /* IEEE 1076-2008 P4.3 */
|
||||
: subprogram_specification K_is
|
||||
{ active_sub = $1; }
|
||||
subprogram_declarative_part
|
||||
K_begin subprogram_statement_part K_end
|
||||
subprogram_kind_opt identifier_opt ';'
|
||||
|
|
@ -2186,8 +2186,10 @@ subprogram_body /* IEEE 1076-2008 P4.3 */
|
|||
} else if (tmp) {
|
||||
errormsg(@1, "Subprogram specification for %s doesn't match specification in package header.\n", prog->name().str());
|
||||
}
|
||||
prog->set_program_body($5);
|
||||
prog->transfer_from(*active_scope);
|
||||
prog->set_program_body($6);
|
||||
active_scope->bind_name(prog->name(), prog);
|
||||
active_sub = NULL;
|
||||
}
|
||||
|
||||
| subprogram_specification K_is
|
||||
|
|
@ -2410,8 +2412,15 @@ variable_assignment_statement /* IEEE 1076-2008 P10.6.1 */
|
|||
|
||||
variable_declaration /* IEEE 1076-2008 P6.4.2.4 */
|
||||
: K_shared_opt K_variable identifier_list ':' subtype_indication ';'
|
||||
{ sorrymsg(@2, "variable_declaration not supported.\n"); }
|
||||
|
||||
{ /* Save the signal declaration in the block_signals map. */
|
||||
for (std::list<perm_string>::iterator cur = $3->begin()
|
||||
; cur != $3->end() ; ++cur) {
|
||||
Variable*sig = new Variable(*cur, $5);
|
||||
FILE_NAME(sig, @2);
|
||||
active_scope->bind_name(*cur, sig);
|
||||
}
|
||||
delete $3;
|
||||
}
|
||||
| K_shared_opt K_variable error ';'
|
||||
{ errormsg(@2, "Syntax error in variable declaration.\n");
|
||||
yyerrok;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
# include "scope.h"
|
||||
# include "package.h"
|
||||
# include "subprogram.h"
|
||||
# include <algorithm>
|
||||
# include <iostream>
|
||||
# include <iterator>
|
||||
|
|
@ -202,6 +203,27 @@ void ScopeBase::do_use_from(const ScopeBase*that)
|
|||
}
|
||||
}
|
||||
|
||||
void ScopeBase::transfer_from(ScopeBase&ref)
|
||||
{
|
||||
std::copy(ref.new_signals_.begin(), ref.new_signals_.end(),
|
||||
insert_iterator<map<perm_string, Signal*> >(
|
||||
new_signals_, new_signals_.end())
|
||||
);
|
||||
ref.new_signals_.clear();
|
||||
|
||||
std::copy(ref.new_variables_.begin(), ref.new_variables_.end(),
|
||||
insert_iterator<map<perm_string, Variable*> >(
|
||||
new_variables_, new_variables_.end())
|
||||
);
|
||||
ref.new_variables_.clear();
|
||||
|
||||
std::copy(ref.new_components_.begin(), ref.new_components_.end(),
|
||||
insert_iterator<map<perm_string, ComponentBase*> >(
|
||||
new_components_, new_components_.end())
|
||||
);
|
||||
ref.new_components_.clear();
|
||||
}
|
||||
|
||||
void ActiveScope::set_package_header(Package*pkg)
|
||||
{
|
||||
assert(package_header_ == 0);
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
# include "StringHeap.h"
|
||||
# include "entity.h"
|
||||
# include "expression.h"
|
||||
# include "subprogram.h"
|
||||
# include "vsignal.h"
|
||||
|
||||
class ActiveScope;
|
||||
|
|
@ -58,6 +57,9 @@ class ScopeBase {
|
|||
Signal* find_signal(perm_string by_name) const;
|
||||
Variable* find_variable(perm_string by_name) const;
|
||||
Subprogram* find_subprogram(perm_string by_name) const;
|
||||
// Moves all signals, variables and components from another scope to
|
||||
// this one. After the transfer new_* maps are emptied in the another scope.
|
||||
void transfer_from(ScopeBase&ref);
|
||||
|
||||
protected:
|
||||
void cleanup();
|
||||
|
|
@ -203,7 +205,7 @@ class ActiveScope : public ScopeBase {
|
|||
{ map<perm_string, Subprogram*>::iterator it;
|
||||
if((it = use_subprograms_.find(name)) != use_subprograms_.end() )
|
||||
use_subprograms_.erase(it);
|
||||
cur_subprograms_[name] = obj;;
|
||||
cur_subprograms_[name] = obj;
|
||||
}
|
||||
|
||||
void bind(Entity*ent)
|
||||
|
|
|
|||
|
|
@ -120,6 +120,8 @@ class ReturnStmt : public SequentialStmt {
|
|||
int emit(ostream&out, Entity*entity, Architecture*arc);
|
||||
void dump(ostream&out, int indent) const;
|
||||
|
||||
const Expression*peek_expr() const { return val_; };
|
||||
|
||||
private:
|
||||
Expression*val_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
# include "subprogram.h"
|
||||
# include "entity.h"
|
||||
# include "vtype.h"
|
||||
# include "sequential.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
using namespace std;
|
||||
|
|
@ -45,6 +46,7 @@ void Subprogram::set_program_body(list<SequentialStmt*>*stmt)
|
|||
{
|
||||
ivl_assert(*this, statements_==0);
|
||||
statements_ = stmt;
|
||||
fix_return_type();
|
||||
}
|
||||
|
||||
bool Subprogram::compare_specification(Subprogram*that) const
|
||||
|
|
@ -78,6 +80,57 @@ bool Subprogram::compare_specification(Subprogram*that) const
|
|||
return true;
|
||||
}
|
||||
|
||||
const InterfacePort*Subprogram::find_param(perm_string nam) const
|
||||
{
|
||||
if(!ports_)
|
||||
return NULL;
|
||||
|
||||
for (std::list<InterfacePort*>::const_iterator it = ports_->begin()
|
||||
; it != ports_->end(); ++it) {
|
||||
if((*it)->name == nam)
|
||||
return *it;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const VType*Subprogram::peek_param_type(int idx) const
|
||||
{
|
||||
if(!ports_ || idx >= ports_->size())
|
||||
return NULL;
|
||||
|
||||
std::list<InterfacePort*>::const_iterator p = ports_->begin();
|
||||
std::advance(p, idx);
|
||||
|
||||
return (*p)->type;
|
||||
}
|
||||
|
||||
void Subprogram::fix_return_type(void)
|
||||
{
|
||||
if(!statements_)
|
||||
return;
|
||||
|
||||
const ReturnStmt*ret = NULL;
|
||||
const VType*t = NULL;
|
||||
|
||||
for (std::list<SequentialStmt*>::const_iterator s = statements_->begin()
|
||||
; s != statements_->end(); ++s) {
|
||||
if((ret = dynamic_cast<const ReturnStmt*>(*s))) {
|
||||
const Expression*expr = ret->peek_expr();
|
||||
|
||||
if(const ExpName*n = dynamic_cast<const ExpName*>(expr)) {
|
||||
if(Variable*v = find_variable(n->peek_name()))
|
||||
t = v->peek_type();
|
||||
} else {
|
||||
t = expr->peek_type();
|
||||
}
|
||||
|
||||
if(t)
|
||||
return_type_ = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Subprogram::write_to_stream(ostream&fd) const
|
||||
{
|
||||
fd << " function " << name_ << "(";
|
||||
|
|
|
|||
|
|
@ -22,15 +22,15 @@
|
|||
|
||||
# include "StringHeap.h"
|
||||
# include "LineInfo.h"
|
||||
# include "scope.h"
|
||||
# include <iostream>
|
||||
# include <list>
|
||||
|
||||
class InterfacePort;
|
||||
class ScopeBase;
|
||||
class SequentialStmt;
|
||||
class VType;
|
||||
|
||||
class Subprogram : public LineInfo {
|
||||
class Subprogram : public LineInfo, public ScopeBase {
|
||||
|
||||
public:
|
||||
Subprogram(perm_string name, std::list<InterfacePort*>*ports,
|
||||
|
|
@ -48,6 +48,11 @@ class Subprogram : public LineInfo {
|
|||
// matches this subprogram and that subprogram.
|
||||
bool compare_specification(Subprogram*that) const;
|
||||
|
||||
const InterfacePort*find_param(perm_string nam) const;
|
||||
const VType*peek_param_type(int idx) const;
|
||||
|
||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
|
||||
// Emit a definition as it would show up in a package.
|
||||
int emit_package(std::ostream&fd) const;
|
||||
|
||||
|
|
@ -55,6 +60,10 @@ class Subprogram : public LineInfo {
|
|||
void dump(std::ostream&fd) const;
|
||||
|
||||
private:
|
||||
// Determines appropriate return type. Un case of std_logic_vector
|
||||
// VHDL requires skipping its size in contrary to Verilog
|
||||
void fix_return_type(void);
|
||||
|
||||
perm_string name_;
|
||||
const ScopeBase*parent_;
|
||||
std::list<InterfacePort*>*ports_;
|
||||
|
|
|
|||
|
|
@ -60,6 +60,13 @@ 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) {
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ class VType {
|
|||
virtual bool can_be_packed() const { return false; }
|
||||
|
||||
private:
|
||||
friend class decl_t;
|
||||
friend struct decl_t;
|
||||
// This virtual method is called to emit the declaration. This
|
||||
// is used by the decl_t object to emit variable/wire/port declarations.
|
||||
virtual int emit_decl(std::ostream&out, perm_string name, bool reg_flag) const;
|
||||
|
|
|
|||
Loading…
Reference in New Issue