commit
935ee6137d
|
|
@ -2009,6 +2009,12 @@ static bool check_dimension(const NetExpr*dim_expr, long &dim)
|
|||
static bool get_array_info(const NetExpr*arg, long dim,
|
||||
long &left, long &right, bool&defer)
|
||||
{
|
||||
if (const NetEConstParam*param = dynamic_cast<const NetEConstParam*>(arg)) {
|
||||
assert(dim == 1);
|
||||
left = param->expr_width() - 1;
|
||||
right = 0;
|
||||
return false;
|
||||
}
|
||||
/* The argument must be a signal that has enough dimensions. */
|
||||
const NetESignal*esig = dynamic_cast<const NetESignal*>(arg);
|
||||
if (esig == 0) return true;
|
||||
|
|
|
|||
3
parse.y
3
parse.y
|
|
@ -4169,6 +4169,9 @@ port_declaration
|
|||
use_type = NetNet::IMPLICIT_REG;
|
||||
} else if (dynamic_cast<struct_type_t*> ($4)) {
|
||||
use_type = NetNet::IMPLICIT_REG;
|
||||
} else if (enum_type_t*etype = dynamic_cast<enum_type_t*> ($4)) {
|
||||
if(etype->base_type == IVL_VT_LOGIC)
|
||||
use_type = NetNet::IMPLICIT_REG;
|
||||
}
|
||||
}
|
||||
ptmp = pform_module_port_reference(name, @2.text, @2.first_line);
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ LIBS = @LIBS@ @EXTRALIBS@
|
|||
|
||||
M = StringHeap.o LineInfo.o
|
||||
|
||||
O = main.o architec.o compiler.o entity.o \
|
||||
O = main.o architec.o compiler.o entity.o std_funcs.o std_types.o \
|
||||
expression.o package.o scope.o sequential.o subprogram.o vsignal.o vtype.o \
|
||||
vtype_match.o \
|
||||
architec_elaborate.o entity_elaborate.o expression_elaborate.o \
|
||||
|
|
|
|||
|
|
@ -195,50 +195,6 @@ int ProcessStatement::rewrite_as_always_edge_(Entity*, Architecture*)
|
|||
return -1;
|
||||
|
||||
const Expression*ce_raw = stmt->peek_condition();
|
||||
// Now we have matched this pattern:
|
||||
// process(<expr>) begin if <ce_raw>...
|
||||
// The <ce_raw> is the condition.
|
||||
|
||||
if (const ExpFunc*ce_func = dynamic_cast<const ExpFunc*>(ce_raw)) {
|
||||
if (ce_func->func_args() != 1)
|
||||
return -1;
|
||||
if (ce_func->func_name()!="rising_edge" && ce_func->func_name()!="falling_edge")
|
||||
return -1;
|
||||
|
||||
if (! se->symbolic_compare(ce_func->func_arg(0)))
|
||||
return -1;
|
||||
|
||||
// We've matched this pattern:
|
||||
// process(<se>) if (rising_edge(<se>)) then ...
|
||||
// and we can convert it to:
|
||||
// always @(posedge <se>) ...
|
||||
|
||||
ExpEdge::fun_t use_edge;
|
||||
if (ce_func->func_name()=="rising_edge")
|
||||
use_edge = ExpEdge::POSEDGE;
|
||||
else if (ce_func->func_name()=="falling_edge")
|
||||
use_edge = ExpEdge::NEGEDGE;
|
||||
else
|
||||
use_edge = ExpEdge::ANYEDGE;
|
||||
|
||||
// Replace the sensitivity expression with an edge
|
||||
// expression. The ExpEdge expression signals that this
|
||||
// is an always-@(edge) statement.
|
||||
ExpEdge*edge = new ExpEdge(use_edge, se);
|
||||
assert(sensitivity_list_.size() == 1);
|
||||
sensitivity_list_.pop_front();
|
||||
sensitivity_list_.push_front(edge);
|
||||
|
||||
// Replace the statement with the body of the always
|
||||
// statement, which is the true clause of the top "if"
|
||||
// statement. There should be no "else" clause.
|
||||
assert(statements_list_.size() == 1);
|
||||
statements_list_.pop_front();
|
||||
stmt->extract_true(statements_list_);
|
||||
|
||||
delete stmt;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Here we expect the condition to be
|
||||
// <name>'event AND <name>='1'.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -279,22 +283,14 @@ void ExpCharacter::dump(ostream&out, int indent) const
|
|||
void ExpConditional::dump(ostream&out, int indent) const
|
||||
{
|
||||
out << setw(indent) << "" << "Conditional expression at "<< get_fileline() << endl;
|
||||
out << setw(indent) << "" << " when:" << endl;
|
||||
cond_->dump(out, indent+4);
|
||||
|
||||
out << setw(indent) << "" << " do:" << endl;
|
||||
for (list<Expression*>::const_iterator cur = true_clause_.begin()
|
||||
; cur != true_clause_.end() ; ++cur) {
|
||||
(*cur)->dump(out, indent+4);
|
||||
}
|
||||
|
||||
for (list<else_t*>::const_iterator cur = else_clause_.begin()
|
||||
; cur != else_clause_.end() ; ++cur) {
|
||||
for (list<case_t*>::const_iterator cur = options_.begin()
|
||||
; cur != options_.end() ; ++cur) {
|
||||
(*cur)->dump(out, indent);
|
||||
}
|
||||
}
|
||||
|
||||
void ExpConditional::else_t::dump(ostream&out, int indent) const
|
||||
void ExpConditional::case_t::dump(ostream&out, int indent) const
|
||||
{
|
||||
out << setw(indent) << "" << "when:" << endl;
|
||||
if (cond_) cond_->dump(out, indent+4);
|
||||
|
|
@ -475,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_;
|
||||
|
||||
|
|
@ -501,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,16 @@ class Expression;
|
|||
|
||||
class InterfacePort : public LineInfo {
|
||||
public:
|
||||
InterfacePort() { mode = PORT_NONE; type=0; expr=0; }
|
||||
InterfacePort(port_mode_t mod = PORT_NONE,
|
||||
perm_string nam = empty_perm_string,
|
||||
const VType*typ = NULL,
|
||||
Expression*exp = NULL)
|
||||
: mode(mod), name(nam), type(typ), expr(exp)
|
||||
{}
|
||||
|
||||
InterfacePort(const VType*typ)
|
||||
: mode(PORT_NONE), type(typ), expr(NULL)
|
||||
{}
|
||||
|
||||
// Port direction from the source code.
|
||||
port_mode_t mode;
|
||||
|
|
|
|||
|
|
@ -129,12 +129,21 @@ ExpAggregate::ExpAggregate(std::list<element_t*>*el)
|
|||
elements_[idx++] = el->front();
|
||||
el->pop_front();
|
||||
}
|
||||
delete el;
|
||||
}
|
||||
|
||||
ExpAggregate::~ExpAggregate()
|
||||
{
|
||||
for (size_t idx = 0 ; idx < elements_.size() ; idx += 1)
|
||||
delete elements_[idx];
|
||||
for(std::vector<element_t*>::iterator it = elements_.begin();
|
||||
it != elements_.end(); ++it) {
|
||||
delete *it;
|
||||
}
|
||||
|
||||
for(std::vector<choice_element>::iterator it = aggregate_.begin();
|
||||
it != aggregate_.end(); ++it) {
|
||||
delete it->choice;
|
||||
delete it->expr;
|
||||
}
|
||||
}
|
||||
|
||||
Expression* ExpAggregate::clone() const
|
||||
|
|
@ -301,84 +310,53 @@ void ExpConcat::visit(ExprVisitor& func)
|
|||
}
|
||||
|
||||
ExpConditional::ExpConditional(Expression*co, list<Expression*>*tru,
|
||||
list<ExpConditional::else_t*>*fal)
|
||||
: cond_(co)
|
||||
list<ExpConditional::case_t*>*options)
|
||||
{
|
||||
if (tru) true_clause_.splice(true_clause_.end(), *tru);
|
||||
if (fal) else_clause_.splice(else_clause_.end(), *fal);
|
||||
if(co && tru) options_.push_back(new case_t(co, tru));
|
||||
if(options) options_.splice(options_.end(), *options);
|
||||
}
|
||||
|
||||
ExpConditional::~ExpConditional()
|
||||
{
|
||||
delete cond_;
|
||||
while (! true_clause_.empty()) {
|
||||
Expression*tmp = true_clause_.front();
|
||||
true_clause_.pop_front();
|
||||
delete tmp;
|
||||
}
|
||||
while (! else_clause_.empty()) {
|
||||
else_t*tmp = else_clause_.front();
|
||||
else_clause_.pop_front();
|
||||
while (!options_.empty()) {
|
||||
case_t*tmp = options_.front();
|
||||
options_.pop_front();
|
||||
delete tmp;
|
||||
}
|
||||
}
|
||||
|
||||
Expression*ExpConditional::clone() const
|
||||
{
|
||||
std::list<Expression*>*new_true_clause = NULL;
|
||||
if(!true_clause_.empty()) {
|
||||
new_true_clause = new std::list<Expression*>();
|
||||
std::list<case_t*>*new_options = NULL;
|
||||
if(!options_.empty()) {
|
||||
new_options = new std::list<case_t*>();
|
||||
|
||||
for(std::list<Expression*>::const_iterator it = true_clause_.begin();
|
||||
it != true_clause_.end(); ++it) {
|
||||
new_true_clause->push_back((*it)->clone());
|
||||
for(std::list<case_t*>::const_iterator it = options_.begin();
|
||||
it != options_.end(); ++it) {
|
||||
new_options->push_back(new case_t(**it));
|
||||
}
|
||||
}
|
||||
|
||||
std::list<else_t*>*new_else_clause = NULL;
|
||||
if(!else_clause_.empty()) {
|
||||
new_else_clause = new std::list<else_t*>();
|
||||
|
||||
for(std::list<else_t*>::const_iterator it = else_clause_.begin();
|
||||
it != else_clause_.end(); ++it) {
|
||||
new_else_clause->push_back(new else_t(**it));
|
||||
}
|
||||
}
|
||||
|
||||
return new ExpConditional(cond_->clone(), new_true_clause, new_else_clause);
|
||||
return new ExpConditional(NULL, NULL, new_options);
|
||||
}
|
||||
|
||||
void ExpConditional::visit(ExprVisitor& func)
|
||||
{
|
||||
if(!true_clause_.empty()) {
|
||||
for(std::list<Expression*>::iterator it = true_clause_.begin();
|
||||
it != true_clause_.end(); ++it) {
|
||||
(*it)->visit(func);
|
||||
}
|
||||
}
|
||||
|
||||
if(!else_clause_.empty()) {
|
||||
for(std::list<else_t*>::iterator it = else_clause_.begin();
|
||||
it != else_clause_.end(); ++it) {
|
||||
std::list<Expression*>& else_clause = (*it)->extract_true_clause();
|
||||
|
||||
for(std::list<Expression*>::iterator jt = else_clause.begin();
|
||||
jt != else_clause.end(); ++jt) {
|
||||
(*jt)->visit(func);
|
||||
}
|
||||
}
|
||||
for(std::list<case_t*>::iterator it = options_.begin();
|
||||
it != options_.end(); ++it) {
|
||||
(*it)->visit(func);
|
||||
}
|
||||
|
||||
func(this);
|
||||
}
|
||||
|
||||
ExpConditional::else_t::else_t(Expression*cond, std::list<Expression*>*tru)
|
||||
ExpConditional::case_t::case_t(Expression*cond, std::list<Expression*>*tru)
|
||||
: cond_(cond)
|
||||
{
|
||||
if (tru) true_clause_.splice(true_clause_.end(), *tru);
|
||||
}
|
||||
|
||||
ExpConditional::else_t::else_t(const else_t&other)
|
||||
ExpConditional::case_t::case_t(const case_t&other)
|
||||
: LineInfo(other)
|
||||
{
|
||||
cond_ = other.cond_->clone();
|
||||
|
|
@ -388,7 +366,7 @@ ExpConditional::else_t::else_t(const else_t&other)
|
|||
}
|
||||
}
|
||||
|
||||
ExpConditional::else_t::~else_t()
|
||||
ExpConditional::case_t::~case_t()
|
||||
{
|
||||
delete cond_;
|
||||
while (! true_clause_.empty()) {
|
||||
|
|
@ -398,6 +376,49 @@ ExpConditional::else_t::~else_t()
|
|||
}
|
||||
}
|
||||
|
||||
ExpSelected::ExpSelected(Expression*selector, std::list<case_t*>*options)
|
||||
: ExpConditional(NULL, NULL, options), selector_(selector)
|
||||
{
|
||||
// Currently condition field contains only value,
|
||||
// so substitute it with a comparison to create a valid condition
|
||||
for(std::list<case_t*>::iterator it = options_.begin();
|
||||
it != options_.end(); ++it) {
|
||||
Expression*cond = (*it)->condition();
|
||||
|
||||
if(cond)
|
||||
(*it)->set_condition(new ExpRelation(ExpRelation::EQ, selector_->clone(), cond));
|
||||
}
|
||||
}
|
||||
|
||||
ExpSelected::~ExpSelected()
|
||||
{
|
||||
}
|
||||
|
||||
Expression*ExpSelected::clone() const
|
||||
{
|
||||
std::list<case_t*>*new_options = NULL;
|
||||
if(!options_.empty()) {
|
||||
new_options = new std::list<case_t*>();
|
||||
|
||||
for(std::list<case_t*>::const_iterator it = options_.begin();
|
||||
it != options_.end(); ++it) {
|
||||
new_options->push_back(new case_t(**it));
|
||||
}
|
||||
}
|
||||
|
||||
return new ExpSelected(selector_->clone(), new_options);
|
||||
}
|
||||
|
||||
void ExpConditional::case_t::visit(ExprVisitor& func)
|
||||
{
|
||||
if(cond_)
|
||||
func(cond_);
|
||||
|
||||
for(std::list<Expression*>::iterator it = true_clause_.begin();
|
||||
it != true_clause_.end(); ++it) {
|
||||
func(*it);
|
||||
}
|
||||
}
|
||||
|
||||
ExpEdge::ExpEdge(ExpEdge::fun_t typ, Expression*op)
|
||||
: ExpUnary(op), fun_(typ)
|
||||
|
|
@ -527,6 +548,7 @@ ExpName::ExpName(ExpName*prefix, perm_string nn, Expression*msb, Expression*lsb)
|
|||
ExpName::~ExpName()
|
||||
{
|
||||
delete index_;
|
||||
delete lsb_;
|
||||
}
|
||||
|
||||
bool ExpName::symbolic_compare(const Expression*that) const
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
class prange_t;
|
||||
class Entity;
|
||||
class ScopeBase;
|
||||
class Subprogram;
|
||||
class SubprogramHeader;
|
||||
class VType;
|
||||
class VTypeArray;
|
||||
class VTypePrimitive;
|
||||
|
|
@ -460,17 +460,21 @@ class ExpConcat : public Expression {
|
|||
class ExpConditional : public Expression {
|
||||
|
||||
public:
|
||||
class else_t : public LineInfo {
|
||||
class case_t : public LineInfo {
|
||||
public:
|
||||
else_t(Expression*cond, std::list<Expression*>*tru);
|
||||
else_t(const else_t&other);
|
||||
~else_t();
|
||||
case_t(Expression*cond, std::list<Expression*>*tru);
|
||||
case_t(const case_t&other);
|
||||
~case_t();
|
||||
|
||||
inline Expression*condition() { return cond_; }
|
||||
inline void set_condition(Expression*cond) { cond_ = cond; }
|
||||
|
||||
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*lt);
|
||||
int emit_when_else(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
int emit_else(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
int emit_option(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
int emit_default(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
std::list<Expression*>& extract_true_clause() { return true_clause_; }
|
||||
void visit(ExprVisitor& func);
|
||||
|
||||
private:
|
||||
Expression*cond_;
|
||||
|
|
@ -479,10 +483,10 @@ class ExpConditional : public Expression {
|
|||
|
||||
public:
|
||||
ExpConditional(Expression*cond, std::list<Expression*>*tru,
|
||||
std::list<else_t*>*fal);
|
||||
~ExpConditional();
|
||||
std::list<case_t*>*options);
|
||||
virtual ~ExpConditional();
|
||||
|
||||
Expression*clone() const;
|
||||
virtual Expression*clone() const;
|
||||
|
||||
const VType*probe_type(Entity*ent, ScopeBase*scope) const;
|
||||
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
|
||||
|
|
@ -491,10 +495,22 @@ class ExpConditional : public Expression {
|
|||
void dump(ostream&out, int indent = 0) const;
|
||||
void visit(ExprVisitor& func);
|
||||
|
||||
protected:
|
||||
std::list<case_t*> options_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Expression to handle selected assignments (with .. select target <= value when ..)
|
||||
*/
|
||||
class ExpSelected : public ExpConditional {
|
||||
public:
|
||||
ExpSelected(Expression*selector, std::list<case_t*>*options);
|
||||
~ExpSelected();
|
||||
|
||||
Expression*clone() const;
|
||||
|
||||
private:
|
||||
Expression*cond_;
|
||||
std::list<Expression*> true_clause_;
|
||||
std::list<else_t*> else_clause_;
|
||||
Expression*selector_;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -548,7 +564,7 @@ class ExpFunc : public Expression {
|
|||
private:
|
||||
perm_string name_;
|
||||
std::vector<Expression*> argv_;
|
||||
Subprogram*def_;
|
||||
SubprogramHeader*def_;
|
||||
};
|
||||
|
||||
class ExpInteger : public Expression {
|
||||
|
|
@ -662,6 +678,11 @@ class ExpName : public Expression {
|
|||
public:
|
||||
index_t(Expression*idx, Expression*size, Expression*offset = NULL) :
|
||||
idx_(idx), size_(size), offset_(offset) {}
|
||||
~index_t() {
|
||||
delete idx_;
|
||||
delete size_;
|
||||
delete offset_;
|
||||
}
|
||||
|
||||
int emit(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
# include "vsignal.h"
|
||||
# include "subprogram.h"
|
||||
# include "library.h"
|
||||
# include "std_types.h"
|
||||
# include <iostream>
|
||||
# include <typeinfo>
|
||||
# include "parse_types.h"
|
||||
|
|
@ -714,22 +715,16 @@ int ExpConditional::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltyp
|
|||
|
||||
/* Note that the type for the condition expression need not
|
||||
have anything to do with the type of this expression. */
|
||||
errors += cond_->elaborate_expr(ent, scope, 0);
|
||||
|
||||
for (list<Expression*>::const_iterator cur = true_clause_.begin()
|
||||
; cur != true_clause_.end() ; ++cur) {
|
||||
errors += (*cur)->elaborate_expr(ent, scope, ltype);
|
||||
}
|
||||
|
||||
for (list<else_t*>::const_iterator cur = else_clause_.begin()
|
||||
; cur != else_clause_.end() ; ++cur) {
|
||||
for (list<case_t*>::const_iterator cur = options_.begin()
|
||||
; cur != options_.end() ; ++cur) {
|
||||
errors += (*cur)->elaborate_expr(ent, scope, ltype);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpConditional::else_t::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
|
||||
int ExpConditional::case_t::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
|
|
@ -744,53 +739,22 @@ int ExpConditional::else_t::elaborate_expr(Entity*ent, ScopeBase*scope, const VT
|
|||
return errors;
|
||||
}
|
||||
|
||||
const VType*ExpFunc::probe_type(Entity*ent, ScopeBase*scope) const
|
||||
const VType*ExpFunc::probe_type(Entity*, ScopeBase*scope) const
|
||||
{
|
||||
if(name_ == "integer")
|
||||
return &primitive_INTEGER;
|
||||
SubprogramHeader*prog = def_;
|
||||
|
||||
if(name_ == "unsigned" || name_ == "resize") {
|
||||
if(argv_.empty())
|
||||
return NULL;
|
||||
|
||||
const VType*type = argv_[0]->probe_type(ent, scope);
|
||||
if(!type)
|
||||
return NULL;
|
||||
|
||||
int msb = type->get_width(scope) - 1;
|
||||
ivl_assert(*this, msb >= 0);
|
||||
|
||||
// Determine the sign
|
||||
bool sign = false;
|
||||
if(name_ == "resize") {
|
||||
if(const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type))
|
||||
sign = arr->signed_vector();
|
||||
}
|
||||
|
||||
return new VTypeArray(&primitive_BIT, msb, 0, sign);
|
||||
if(!prog) {
|
||||
prog = scope->find_subprogram(name_);
|
||||
}
|
||||
|
||||
if(name_ == "std_logic_vector" || name_ == "conv_std_logic_vector") {
|
||||
if(argv_.empty())
|
||||
return NULL;
|
||||
if(!prog)
|
||||
prog = library_find_subprogram(name_);
|
||||
|
||||
const VType*type = argv_[0]->probe_type(ent, scope);
|
||||
if(!type)
|
||||
return NULL;
|
||||
|
||||
int msb = type->get_width(scope) - 1;
|
||||
|
||||
return new VTypeArray(&primitive_STDLOGIC, msb, 0);
|
||||
if(!prog) {
|
||||
cerr << get_fileline() << ": sorry: VHDL function " << name_ << " not yet implemented" << endl;
|
||||
ivl_assert(*this, false);
|
||||
}
|
||||
|
||||
Subprogram*prog = scope->find_subprogram(name_);
|
||||
|
||||
if(!prog)
|
||||
prog = library_find_subprogram(name_);
|
||||
|
||||
if(!prog)
|
||||
return NULL;
|
||||
|
||||
return prog->peek_return_type();
|
||||
}
|
||||
|
||||
|
|
@ -799,7 +763,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_);
|
||||
|
|
@ -818,86 +782,25 @@ int ExpFunc::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*)
|
|||
errors += argv_[idx]->elaborate_expr(ent, scope, tmp);
|
||||
}
|
||||
|
||||
if(def_ && def_->unbounded()) {
|
||||
// SystemVerilog functions work only with defined size data types, therefore
|
||||
// if header does not specify argument or return type size, create a function
|
||||
// instance that work with this particular size.
|
||||
if(def_ && !def_->is_std() && def_->unbounded()) {
|
||||
def_ = prog->make_instance(argv_, scope);
|
||||
name_ = def_->name();
|
||||
}
|
||||
|
||||
if(!def_) {
|
||||
cerr << get_fileline() << ": error: could not find function " << name_ << endl;
|
||||
++errors;
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
const VType* ExpFunc::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*) const
|
||||
{
|
||||
// Built-in functions
|
||||
if(name_ == "to_integer" || name_ == "unsigned" || name_ == "integer") {
|
||||
ivl_assert(*this, argv_.size() == 1);
|
||||
|
||||
const VType*type = argv_[0]->probe_type(ent, scope);
|
||||
ivl_assert(*this, type);
|
||||
|
||||
// Determine the sign
|
||||
bool sign = false;
|
||||
|
||||
if(name_ == "integer") {
|
||||
sign = true;
|
||||
} else if(name_ == "to_integer") {
|
||||
if(const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type))
|
||||
sign = arr->signed_vector();
|
||||
}
|
||||
|
||||
return new VTypeArray(&primitive_BIT, type->get_width(scope), 0, sign);
|
||||
}
|
||||
|
||||
if(name_ == "to_unsigned" || name_ == "std_logic_vector" ||
|
||||
name_ == "conv_std_logic_vector" || name_ == "resize")
|
||||
{
|
||||
ivl_assert(*this, argv_.size() == 2);
|
||||
|
||||
// Determine the sign
|
||||
bool sign = false;
|
||||
const VType*element = &primitive_STDLOGIC;
|
||||
|
||||
if(name_ == "resize") {
|
||||
const VType*type = argv_[0]->probe_type(ent, scope);
|
||||
ivl_assert(*this, type);
|
||||
|
||||
if(const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type))
|
||||
{
|
||||
sign = arr->signed_vector();
|
||||
element = arr->element_type();
|
||||
}
|
||||
} else if(name_ == "to_unsigned") {
|
||||
element = &primitive_BIT;
|
||||
}
|
||||
|
||||
int64_t width = 0;
|
||||
bool evaluated = argv_[1]->evaluate(scope, width);
|
||||
ivl_assert(*this, evaluated);
|
||||
|
||||
return new VTypeArray(element, width, 0, sign);
|
||||
}
|
||||
|
||||
if(name_ == "and_reduce" || name_ == "or_reduce") {
|
||||
ivl_assert(*this, argv_.size() == 1);
|
||||
const VType*element = &primitive_STDLOGIC;
|
||||
return new VTypeArray(element, 0, 0, false);
|
||||
}
|
||||
|
||||
// Other cases
|
||||
Subprogram*prog = def_;
|
||||
|
||||
if(!prog) {
|
||||
ivl_assert(*this, scope);
|
||||
prog = scope->find_subprogram(name_);
|
||||
}
|
||||
|
||||
if(!prog)
|
||||
prog = library_find_subprogram(name_);
|
||||
|
||||
cerr << get_fileline() << ": sorry: VHDL function " << name_ << " not yet implemented" << endl;
|
||||
ivl_assert(*this, prog);
|
||||
|
||||
return def_->peek_return_type();
|
||||
return probe_type(ent, scope);
|
||||
}
|
||||
|
||||
const VType* ExpInteger::probe_type(Entity*, ScopeBase*) const
|
||||
|
|
@ -1037,6 +940,10 @@ const VType* ExpName::probe_type(Entity*ent, ScopeBase*scope) const
|
|||
return type;
|
||||
}
|
||||
|
||||
if (const InterfacePort*port = scope->find_param(name_)) {
|
||||
return port->type;
|
||||
}
|
||||
|
||||
if ((type = scope->is_enum_name(name_))) {
|
||||
return type;
|
||||
}
|
||||
|
|
@ -1052,13 +959,22 @@ const VType* ExpName::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*)co
|
|||
return probe_type(ent, scope);
|
||||
}
|
||||
|
||||
int ExpName::elaborate_expr(Entity*, ScopeBase*, const VType*ltype)
|
||||
int ExpName::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
|
||||
{
|
||||
if (ltype) {
|
||||
ivl_assert(*this, ltype != 0);
|
||||
set_type(ltype);
|
||||
}
|
||||
|
||||
if(prefix_.get())
|
||||
prefix_.get()->elaborate_expr(ent, scope, NULL);
|
||||
|
||||
if(index_)
|
||||
index_->elaborate_expr(ent, scope, &primitive_INTEGER);
|
||||
|
||||
if(lsb_)
|
||||
lsb_->elaborate_expr(ent, scope, &primitive_INTEGER);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1069,7 +985,7 @@ const VType* ExpNameALL::probe_type(Entity*, ScopeBase*) const
|
|||
|
||||
const VType* ExpRelation::probe_type(Entity*, ScopeBase*) const
|
||||
{
|
||||
return &primitive_BOOLEAN;
|
||||
return &type_BOOLEAN;
|
||||
}
|
||||
|
||||
int ExpRelation::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
|
||||
|
|
|
|||
|
|
@ -23,7 +23,8 @@
|
|||
# include "vtype.h"
|
||||
# include "architec.h"
|
||||
# include "package.h"
|
||||
# include "subprogram.h"
|
||||
# include "std_funcs.h"
|
||||
# include "std_types.h"
|
||||
# include "parse_types.h"
|
||||
# include <typeinfo>
|
||||
# include <iostream>
|
||||
|
|
@ -481,45 +482,33 @@ int ExpConditional::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
|||
{
|
||||
int errors = 0;
|
||||
out << "(";
|
||||
errors += cond_->emit(out, ent, scope);
|
||||
out << ")? (";
|
||||
|
||||
if (true_clause_.size() > 1) {
|
||||
cerr << get_fileline() << ": sorry: Multiple expression waveforms not supported here." << endl;
|
||||
errors += 1;
|
||||
}
|
||||
|
||||
Expression*tmp = true_clause_.front();
|
||||
errors += tmp->emit(out, ent, scope);
|
||||
|
||||
out << ") : (";
|
||||
|
||||
// Draw out any when-else expressions. These are all the else_
|
||||
// clauses besides the last.
|
||||
if (else_clause_.size() > 1) {
|
||||
list<else_t*>::iterator last = else_clause_.end();
|
||||
-- last;
|
||||
if (options_.size() > 1) {
|
||||
list<case_t*>::iterator last = options_.end();
|
||||
--last;
|
||||
|
||||
for (list<else_t*>::iterator cur = else_clause_.begin()
|
||||
for (list<case_t*>::iterator cur = options_.begin()
|
||||
; cur != last ; ++cur) {
|
||||
errors += (*cur) ->emit_when_else(out, ent, scope);
|
||||
errors += (*cur)->emit_option(out, ent, scope);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
errors += else_clause_.back()->emit_else(out, ent, scope);
|
||||
errors += options_.back()->emit_default(out, ent, scope);
|
||||
out << ")";
|
||||
|
||||
// The emit_when_else() functions do not close the last
|
||||
// The emit_option() functions do not close the last
|
||||
// parentheses so that the following expression can be
|
||||
// nested. But that means come the end, we have some
|
||||
// expressions to close.
|
||||
for (size_t idx = 1 ; idx < else_clause_.size() ; idx += 1)
|
||||
for (size_t idx = 1 ; idx < options_.size() ; idx += 1)
|
||||
out << ")";
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpConditional::else_t::emit_when_else(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
int ExpConditional::case_t::emit_option(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
assert(cond_ != 0);
|
||||
|
|
@ -541,7 +530,7 @@ int ExpConditional::else_t::emit_when_else(ostream&out, Entity*ent, ScopeBase*sc
|
|||
return errors;
|
||||
}
|
||||
|
||||
int ExpConditional::else_t::emit_else(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
int ExpConditional::case_t::emit_default(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
// Trailing else must have no condition.
|
||||
|
|
@ -579,103 +568,21 @@ int ExpFunc::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
|||
{
|
||||
int errors = 0;
|
||||
|
||||
if (name_ == "unsigned" && argv_.size() == 1) {
|
||||
// Handle the special case that this is a cast to
|
||||
// unsigned. This function is brought in as part of the
|
||||
// std numeric library, but we interpret it as the same
|
||||
// as the $unsigned function.
|
||||
out << "$unsigned(";
|
||||
errors += argv_[0]->emit(out, ent, scope);
|
||||
out << ")";
|
||||
ivl_assert(*this, def_);
|
||||
|
||||
} else if (name_ == "integer" && argv_.size() == 1) {
|
||||
out << "$signed(";
|
||||
errors += argv_[0]->emit(out, ent, scope);
|
||||
out << ")";
|
||||
// If this function has an elaborated definition, and if
|
||||
// that definition is in a package, then include the
|
||||
// package name as a scope qualifier. This assures that
|
||||
// the SV elaborator finds the correct VHDL elaborated
|
||||
// definition.
|
||||
const Package*pkg = dynamic_cast<const Package*> (def_->get_parent());
|
||||
if (pkg != 0)
|
||||
out << "\\" << pkg->name() << " ::";
|
||||
|
||||
} else if (name_ == "to_integer" && argv_.size() == 1) {
|
||||
bool signed_flag = false;
|
||||
|
||||
// to_integer converts unsigned to natural
|
||||
// signed to integer
|
||||
// try to determine the converted type
|
||||
const VType*type = argv_[0]->probe_type(ent, scope);
|
||||
const VTypeArray*array = dynamic_cast<const VTypeArray*>(type);
|
||||
|
||||
if(array)
|
||||
signed_flag = array->signed_vector();
|
||||
else
|
||||
cerr << get_fileline() << ": sorry: Could not determine the "
|
||||
<< "expression sign. Output may be erroneous." << endl;
|
||||
|
||||
out << (signed_flag ? "$signed(" : "$unsigned(");
|
||||
errors += argv_[0]->emit(out, ent, scope);
|
||||
out << ")";
|
||||
|
||||
} else if (name_ == "std_logic_vector" && argv_.size() == 1) {
|
||||
// Special case: The std_logic_vector function casts its
|
||||
// argument to std_logic_vector. Internally, we don't
|
||||
// have to do anything for that to work.
|
||||
out << "(";
|
||||
errors += argv_[0]->emit(out, ent, scope);
|
||||
out << ")";
|
||||
|
||||
} else if (name_ == "to_unsigned" && argv_.size() == 2) {
|
||||
|
||||
out << "$ivlh_to_unsigned(";
|
||||
errors += argv_[0]->emit(out, ent, scope);
|
||||
out << ", ";
|
||||
errors += argv_[1]->emit(out, ent, scope);
|
||||
out << ")";
|
||||
|
||||
} else if ((name_ == "conv_std_logic_vector" || name_ == "resize") &&
|
||||
argv_.size() == 2) {
|
||||
int64_t use_size;
|
||||
bool rc = argv_[1]->evaluate(ent, scope, use_size);
|
||||
ivl_assert(*this, rc);
|
||||
out << use_size << "'(";
|
||||
errors += argv_[0]->emit(out, ent, scope);
|
||||
out << ")";
|
||||
|
||||
} else if (name_ == "rising_edge" && argv_.size() == 1) {
|
||||
out << "$ivlh_rising_edge(";
|
||||
errors += argv_[0]->emit(out, ent, scope);
|
||||
out << ")";
|
||||
|
||||
} else if (name_ == "falling_edge" && argv_.size() == 1) {
|
||||
out << "$ivlh_falling_edge(";
|
||||
errors += argv_[0]->emit(out, ent, scope);
|
||||
out << ")";
|
||||
|
||||
} else if (name_ == "and_reduce" && argv_.size() == 1) {
|
||||
out << "&(";
|
||||
errors += argv_[0]->emit(out, ent, scope);
|
||||
out << ")";
|
||||
|
||||
} else if (name_ == "or_reduce" && argv_.size() == 1) {
|
||||
out << "|(";
|
||||
errors += argv_[0]->emit(out, ent, scope);
|
||||
out << ")";
|
||||
|
||||
} else {
|
||||
// If this function has an elaborated definition, and if
|
||||
// that definition is in a package, then include the
|
||||
// package name as a scope qualifier. This assures that
|
||||
// the SV elaborator finds the correct VHDL elaborated
|
||||
// definition.
|
||||
if (def_) {
|
||||
const Package*pkg = dynamic_cast<const Package*> (def_->get_parent());
|
||||
if (pkg != 0)
|
||||
out << "\\" << pkg->name() << " ::";
|
||||
}
|
||||
|
||||
out << "\\" << name_ << " (";
|
||||
for (size_t idx = 0; idx < argv_.size() ; idx += 1) {
|
||||
if (idx > 0) out << ", ";
|
||||
errors += argv_[idx]->emit(out, ent, scope);
|
||||
}
|
||||
out << ")";
|
||||
}
|
||||
errors += def_->emit_name(argv_, out, ent, scope);
|
||||
out << " (";
|
||||
def_->emit_args(argv_, out, ent, scope);
|
||||
out << ")";
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
|
@ -767,6 +674,11 @@ int ExpName::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
|||
|
||||
if(try_workarounds_(out, ent, scope, indices, field_size)) {
|
||||
emit_workaround_(out, ent, scope, indices, field_size);
|
||||
for(list<index_t*>::iterator it = indices.begin();
|
||||
it != indices.end(); ++it)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -847,7 +759,7 @@ bool ExpName::check_const_array_workaround_(const VTypeArray*arr,
|
|||
data_size = element->get_width(scope);
|
||||
if(data_size < 0)
|
||||
return false;
|
||||
indices.push_back(new index_t(index_, new ExpInteger(data_size)));
|
||||
indices.push_back(new index_t(index_->clone(), new ExpInteger(data_size)));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1044,7 +956,14 @@ int ExpUAbs::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
|||
int ExpUNot::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
out << "~(";
|
||||
|
||||
const VType*op_type = peek_operand()->probe_type(ent, scope);
|
||||
|
||||
if(op_type && op_type->type_match(&type_BOOLEAN))
|
||||
out << "!(";
|
||||
else
|
||||
out << "~(";
|
||||
|
||||
errors += emit_operand1(out, ent, scope);
|
||||
out << ")";
|
||||
return errors;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
# include "parse_misc.h"
|
||||
# include "compiler.h"
|
||||
# include "package.h"
|
||||
# include "std_types.h"
|
||||
# include <fstream>
|
||||
# include <list>
|
||||
# include <map>
|
||||
|
|
@ -72,9 +73,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) {
|
||||
|
|
@ -305,9 +306,7 @@ static void import_ieee_use_std_logic_1164(ActiveScope*res, perm_string name)
|
|||
bool all_flag = name=="all";
|
||||
|
||||
if (all_flag || name == "std_logic_vector") {
|
||||
vector<VTypeArray::range_t> dims (1);
|
||||
res->use_name(perm_string::literal("std_logic_vector"),
|
||||
new VTypeArray(&primitive_STDLOGIC, dims, false));
|
||||
res->use_name(perm_string::literal("std_logic_vector"), &primitive_STDLOGIC_VECTOR);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -320,14 +319,10 @@ static void import_ieee_use_numeric_bit(ActiveScope*res, perm_string name)
|
|||
bool all_flag = name=="all";
|
||||
|
||||
if (all_flag || name == "signed") {
|
||||
vector<VTypeArray::range_t> dims (1);
|
||||
res->use_name(perm_string::literal("signed"),
|
||||
new VTypeArray(&primitive_STDLOGIC, dims, true));
|
||||
res->use_name(perm_string::literal("signed"), &primitive_SIGNED);
|
||||
}
|
||||
if (all_flag || name == "unsigned") {
|
||||
vector<VTypeArray::range_t> dims (1);
|
||||
res->use_name(perm_string::literal("unsigned"),
|
||||
new VTypeArray(&primitive_BIT, dims, false));
|
||||
res->use_name(perm_string::literal("unsigned"), &primitive_UNSIGNED);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -336,14 +331,10 @@ static void import_ieee_use_numeric_std(ActiveScope*res, perm_string name)
|
|||
bool all_flag = name=="all";
|
||||
|
||||
if (all_flag || name == "signed") {
|
||||
vector<VTypeArray::range_t> dims (1);
|
||||
res->use_name(perm_string::literal("signed"),
|
||||
new VTypeArray(&primitive_STDLOGIC, dims, true));
|
||||
res->use_name(perm_string::literal("signed"), &primitive_SIGNED);
|
||||
}
|
||||
if (all_flag || name == "unsigned") {
|
||||
vector<VTypeArray::range_t> dims (1);
|
||||
res->use_name(perm_string::literal("unsigned"),
|
||||
new VTypeArray(&primitive_STDLOGIC, dims, false));
|
||||
res->use_name(perm_string::literal("unsigned"), &primitive_UNSIGNED);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -384,59 +375,6 @@ static void import_std_use(const YYLTYPE&loc, ActiveScope*/*res*/, perm_string p
|
|||
}
|
||||
}
|
||||
|
||||
const VTypePrimitive primitive_BOOLEAN(VTypePrimitive::BOOLEAN, true);
|
||||
const VTypePrimitive primitive_BIT(VTypePrimitive::BIT, true);
|
||||
const VTypePrimitive primitive_INTEGER(VTypePrimitive::INTEGER);
|
||||
const VTypePrimitive primitive_NATURAL(VTypePrimitive::NATURAL);
|
||||
const VTypePrimitive primitive_REAL(VTypePrimitive::REAL);
|
||||
const VTypePrimitive primitive_STDLOGIC(VTypePrimitive::STDLOGIC, true);
|
||||
const VTypePrimitive primitive_CHARACTER(VTypePrimitive::CHARACTER);
|
||||
const VTypePrimitive primitive_TIME(VTypePrimitive::TIME);
|
||||
|
||||
static const VTypeArray primitive_BIT_VECTOR(&primitive_BIT, vector<VTypeArray::range_t> (1));
|
||||
static const VTypeArray primitive_BOOL_VECTOR(&primitive_BOOLEAN, vector<VTypeArray::range_t> (1));
|
||||
static const VTypeArray primitive_STRING(&primitive_CHARACTER, vector<VTypeArray::range_t> (1));
|
||||
|
||||
void generate_global_types(ActiveScope*res)
|
||||
{
|
||||
res->use_name(perm_string::literal("boolean"), &primitive_BOOLEAN);
|
||||
res->use_name(perm_string::literal("bit"), &primitive_BIT);
|
||||
res->use_name(perm_string::literal("integer"), &primitive_INTEGER);
|
||||
res->use_name(perm_string::literal("real"), &primitive_REAL);
|
||||
res->use_name(perm_string::literal("std_logic"), &primitive_STDLOGIC);
|
||||
res->use_name(perm_string::literal("character"), &primitive_CHARACTER);
|
||||
res->use_name(perm_string::literal("bit_vector"),&primitive_BIT_VECTOR);
|
||||
res->use_name(perm_string::literal("string"), &primitive_STRING);
|
||||
res->use_name(perm_string::literal("natural"), &primitive_NATURAL);
|
||||
res->use_name(perm_string::literal("time"), &primitive_TIME);
|
||||
}
|
||||
|
||||
void emit_std_types(ostream&out)
|
||||
{
|
||||
out << "`ifndef __VHDL_STD_TYPES" << endl;
|
||||
out << "`define __VHDL_STD_TYPES" << endl;
|
||||
out << "typedef enum bit { \\false , \\true } boolean ;" << endl;
|
||||
out << "`endif" << endl;
|
||||
}
|
||||
|
||||
bool is_global_type(perm_string name)
|
||||
{
|
||||
if (name == "boolean") return true;
|
||||
if (name == "bit") return true;
|
||||
if (name == "integer") return true;
|
||||
if (name == "real") return true;
|
||||
if (name == "std_logic") return true;
|
||||
if (name == "std_logic_vector") return true;
|
||||
if (name == "character") return true;
|
||||
if (name == "bit_vector") return true;
|
||||
if (name == "string") return true;
|
||||
if (name == "natural") return true;
|
||||
if (name == "signed") return true;
|
||||
if (name == "unsigned") return true;
|
||||
if (name == "time") return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void library_set_work_path(const char*path)
|
||||
{
|
||||
assert(library_work_path == 0);
|
||||
|
|
|
|||
|
|
@ -19,15 +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 void emit_std_types(ostream&out);
|
||||
extern int emit_packages(void);
|
||||
extern SubprogramHeader*library_find_subprogram(perm_string name);
|
||||
|
||||
#endif /* IVL_library_H */
|
||||
|
||||
|
|
|
|||
|
|
@ -76,6 +76,8 @@ const char NOTICE[] =
|
|||
|
||||
# include "compiler.h"
|
||||
# include "library.h"
|
||||
# include "std_funcs.h"
|
||||
# include "std_types.h"
|
||||
# include "parse_api.h"
|
||||
# include "vtype.h"
|
||||
# include <fstream>
|
||||
|
|
@ -184,6 +186,8 @@ int main(int argc, char*argv[])
|
|||
library_set_work_path(work_path);
|
||||
|
||||
preload_global_types();
|
||||
preload_std_funcs();
|
||||
|
||||
int errors = 0;
|
||||
|
||||
for (int idx = optind ; idx < argc ; idx += 1) {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
# include "entity.h"
|
||||
# include "subprogram.h"
|
||||
# include "parse_misc.h"
|
||||
# include "std_types.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
Package::Package(perm_string n, const ActiveScope&ref)
|
||||
|
|
@ -57,6 +58,11 @@ void Package::write_to_stream(ostream&fd) const
|
|||
const VTypeDef*def = dynamic_cast<const VTypeDef*> (cur->second);
|
||||
if (def == 0)
|
||||
continue;
|
||||
|
||||
// Do not include global types in types dump
|
||||
if (is_global_type(cur->first))
|
||||
continue;
|
||||
|
||||
fd << "type " << cur->first << ";" << endl;
|
||||
}
|
||||
for (map<perm_string,const VType*>::const_iterator cur = cur_types_.begin()
|
||||
|
|
@ -64,6 +70,11 @@ void Package::write_to_stream(ostream&fd) const
|
|||
const VTypeDef*def = dynamic_cast<const VTypeDef*> (cur->second);
|
||||
if (def == 0)
|
||||
continue;
|
||||
|
||||
// Do not include global types in types dump
|
||||
if (is_global_type(cur->first))
|
||||
continue;
|
||||
|
||||
fd << "type " << cur->first << ";" << endl;
|
||||
}
|
||||
|
||||
|
|
@ -111,9 +122,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 +142,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())
|
||||
|
|
|
|||
203
vhdlpp/parse.y
203
vhdlpp/parse.y
|
|
@ -39,6 +39,8 @@
|
|||
# include "package.h"
|
||||
# include "vsignal.h"
|
||||
# include "vtype.h"
|
||||
# include "std_funcs.h"
|
||||
# include "std_types.h"
|
||||
# include <cstdarg>
|
||||
# include <cstring>
|
||||
# include <list>
|
||||
|
|
@ -83,7 +85,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");
|
||||
|
|
@ -146,6 +148,7 @@ void parser_cleanup(void)
|
|||
{
|
||||
delete_design_entities();
|
||||
delete_global_scope();
|
||||
delete_std_funcs();
|
||||
lex_strings.cleanup();
|
||||
}
|
||||
|
||||
|
|
@ -228,8 +231,8 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
|
|||
IfSequential::Elsif*elsif;
|
||||
std::list<IfSequential::Elsif*>*elsif_list;
|
||||
|
||||
ExpConditional::else_t*exp_else;
|
||||
std::list<ExpConditional::else_t*>*exp_else_list;
|
||||
ExpConditional::case_t*exp_options;
|
||||
std::list<ExpConditional::case_t*>*exp_options_list;
|
||||
|
||||
CaseSeqStmt::CaseStmtAlternative* case_alt;
|
||||
std::list<CaseSeqStmt::CaseStmtAlternative*>* case_alt_list;
|
||||
|
|
@ -262,7 +265,7 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
|
|||
|
||||
ReportStmt::severity_t severity;
|
||||
|
||||
Subprogram*subprogram;
|
||||
SubprogramHeader*subprogram;
|
||||
};
|
||||
|
||||
/* The keywords are all tokens. */
|
||||
|
|
@ -308,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
|
||||
|
|
@ -318,7 +322,7 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
|
|||
%type <arch_statement> concurrent_conditional_signal_assignment
|
||||
%type <arch_statement> concurrent_signal_assignment_statement concurrent_simple_signal_assignment
|
||||
%type <arch_statement> for_generate_statement generate_statement if_generate_statement
|
||||
%type <arch_statement> process_statement
|
||||
%type <arch_statement> process_statement selected_signal_assignment
|
||||
%type <arch_statement_list> architecture_statement_part generate_statement_body
|
||||
|
||||
%type <choice> choice
|
||||
|
|
@ -331,8 +335,8 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
|
|||
%type <expr> expression_logical_xnor expression_logical_xor
|
||||
%type <expr> name prefix selected_name
|
||||
%type <expr> shift_expression signal_declaration_assign_opt
|
||||
%type <expr> simple_expression simple_expression_2 term waveform_element
|
||||
%type <expr> interface_element_expression
|
||||
%type <expr> simple_expression simple_expression_2 term
|
||||
%type <expr> variable_declaration_assign_opt waveform_element interface_element_expression
|
||||
|
||||
%type <expr_list> waveform waveform_elements
|
||||
%type <expr_list> name_list expression_list
|
||||
|
|
@ -370,10 +374,12 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
|
|||
%type <elsif> if_statement_elsif
|
||||
%type <elsif_list> if_statement_elsif_list if_statement_elsif_list_opt
|
||||
|
||||
%type <exp_else> else_when_waveform
|
||||
%type <exp_else_list> else_when_waveforms
|
||||
%type <exp_options> else_when_waveform selected_waveform
|
||||
%type <exp_options_list> else_when_waveforms selected_waveform_list
|
||||
|
||||
%type <subprogram> function_specification procedure_specification
|
||||
%type <subprogram> subprogram_specification subprogram_body_start
|
||||
|
||||
%type <subprogram> function_specification subprogram_specification subprogram_body_start
|
||||
%type <severity> severity severity_opt
|
||||
|
||||
%%
|
||||
|
|
@ -800,12 +806,12 @@ concurrent_simple_signal_assignment
|
|||
|
||||
else_when_waveforms
|
||||
: else_when_waveforms else_when_waveform
|
||||
{ list<ExpConditional::else_t*>*tmp = $1;
|
||||
{ list<ExpConditional::case_t*>*tmp = $1;
|
||||
tmp ->push_back($2);
|
||||
$$ = tmp;
|
||||
}
|
||||
| else_when_waveform
|
||||
{ list<ExpConditional::else_t*>*tmp = new list<ExpConditional::else_t*>;
|
||||
{ list<ExpConditional::case_t*>*tmp = new list<ExpConditional::case_t*>;
|
||||
tmp->push_back($1);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
|
@ -813,12 +819,12 @@ else_when_waveforms
|
|||
|
||||
else_when_waveform
|
||||
: K_else waveform K_when expression
|
||||
{ ExpConditional::else_t*tmp = new ExpConditional::else_t($4, $2);
|
||||
{ ExpConditional::case_t*tmp = new ExpConditional::case_t($4, $2);
|
||||
FILE_NAME(tmp, @1);
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_else waveform
|
||||
{ ExpConditional::else_t*tmp = new ExpConditional::else_t(0, $2);
|
||||
{ ExpConditional::case_t*tmp = new ExpConditional::case_t(0, $2);
|
||||
FILE_NAME(tmp, @1);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
|
@ -827,11 +833,21 @@ else_when_waveform
|
|||
concurrent_signal_assignment_statement /* IEEE 1076-2008 P11.6 */
|
||||
: concurrent_simple_signal_assignment
|
||||
|
||||
| IDENTIFIER ':' concurrent_simple_signal_assignment { $$ = $3; }
|
||||
| IDENTIFIER ':' concurrent_simple_signal_assignment
|
||||
{ delete[] $1;
|
||||
$$ = $3;
|
||||
}
|
||||
|
||||
| concurrent_conditional_signal_assignment
|
||||
|
||||
| IDENTIFIER ':' concurrent_conditional_signal_assignment { $$ = $3; }
|
||||
| IDENTIFIER ':' concurrent_conditional_signal_assignment
|
||||
{ delete[] $1;
|
||||
$$ = $3;
|
||||
}
|
||||
|
||||
| selected_signal_assignment
|
||||
|
||||
| IDENTIFIER ':' selected_signal_assignment { $$ = $3; }
|
||||
|
||||
| name LEQ error ';'
|
||||
{ errormsg(@2, "Syntax error in signal assignment waveform.\n");
|
||||
|
|
@ -968,6 +984,7 @@ direction : K_to { $$ = false; } | K_downto { $$ = true; } ;
|
|||
element_association
|
||||
: choices ARROW expression
|
||||
{ ExpAggregate::element_t*tmp = new ExpAggregate::element_t($1, $3);
|
||||
delete $1;
|
||||
$$ = tmp;
|
||||
}
|
||||
| expression
|
||||
|
|
@ -991,7 +1008,9 @@ element_association_list
|
|||
|
||||
element_declaration
|
||||
: identifier_list ':' subtype_indication ';'
|
||||
{ $$ = record_elements($1, $3); }
|
||||
{ $$ = record_elements($1, $3);
|
||||
delete $1;
|
||||
}
|
||||
;
|
||||
|
||||
element_declaration_list
|
||||
|
|
@ -1237,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);
|
||||
Subprogram*tmp = new Subprogram(name, $4, type_mark);
|
||||
FILE_NAME(tmp,@1);
|
||||
touchup_interface_for_functions($3);
|
||||
SubprogramHeader*tmp = new SubprogramHeader(name, $3, type_mark);
|
||||
FILE_NAME(tmp, @1);
|
||||
delete[]$2;
|
||||
delete[]$7;
|
||||
delete[]$5;
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
|
@ -1267,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;
|
||||
|
|
@ -1306,7 +1325,7 @@ identifier_list
|
|||
}
|
||||
;
|
||||
|
||||
identifier_opt : IDENTIFIER { $$ = $1; } | { $$ = 0; } ;
|
||||
identifier_opt : IDENTIFIER { $$ = $1; } | { $$ = 0; } ;
|
||||
|
||||
identifier_colon_opt : IDENTIFIER ':' { $$ = $1; } | { $$ = 0; };
|
||||
|
||||
|
|
@ -1591,14 +1610,7 @@ mode_opt : mode {$$ = $1;} | {$$ = PORT_NONE;} ;
|
|||
|
||||
name /* IEEE 1076-2008 P8.1 */
|
||||
: IDENTIFIER /* simple_name (IEEE 1076-2008 P8.2) */
|
||||
{ Expression*tmp;
|
||||
if(!strcasecmp($1, "true"))
|
||||
tmp = new ExpBitstring("1");
|
||||
else if(!strcasecmp($1, "false"))
|
||||
tmp = new ExpBitstring("0");
|
||||
else
|
||||
tmp = new ExpName(lex_strings.make($1));
|
||||
|
||||
{ Expression*tmp = new ExpName(lex_strings.make($1));
|
||||
FILE_NAME(tmp, @1);
|
||||
delete[]$1;
|
||||
$$ = tmp;
|
||||
|
|
@ -1764,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;
|
||||
|
|
@ -1872,6 +1893,7 @@ primary
|
|||
VHDL syntax). */
|
||||
| IDENTIFIER '(' association_list ')'
|
||||
{ sorrymsg(@1, "Function calls not supported\n");
|
||||
delete[] $1;
|
||||
$$ = 0;
|
||||
}
|
||||
|
||||
|
|
@ -1890,19 +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;
|
||||
|
|
@ -1911,10 +1940,24 @@ procedure_call
|
|||
;
|
||||
|
||||
procedure_call_statement
|
||||
: IDENTIFIER ':' procedure_call { $$ = $3; }
|
||||
: IDENTIFIER ':' procedure_call
|
||||
{ delete[] $1;
|
||||
$$ = $3;
|
||||
}
|
||||
| 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
|
||||
;
|
||||
|
|
@ -2175,6 +2218,47 @@ selected_names_lib
|
|||
| selected_name_lib
|
||||
;
|
||||
|
||||
selected_signal_assignment
|
||||
: K_with expression K_select name LEQ selected_waveform_list ';'
|
||||
{ ExpSelected*tmp = new ExpSelected($2, $6);
|
||||
FILE_NAME(tmp, @3);
|
||||
delete $2;
|
||||
delete $6;
|
||||
|
||||
ExpName*name = dynamic_cast<ExpName*>($4);
|
||||
assert(name);
|
||||
SignalAssignment*tmpa = new SignalAssignment(name, tmp);
|
||||
FILE_NAME(tmpa, @1);
|
||||
|
||||
$$ = tmpa;
|
||||
}
|
||||
;
|
||||
|
||||
selected_waveform
|
||||
: waveform K_when expression
|
||||
{ ExpConditional::case_t*tmp = new ExpConditional::case_t($3, $1);
|
||||
FILE_NAME(tmp, @1);
|
||||
$$ = tmp;
|
||||
}
|
||||
| waveform K_when K_others
|
||||
{ ExpConditional::case_t*tmp = new ExpConditional::case_t(0, $1);
|
||||
FILE_NAME(tmp, @1);
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
||||
selected_waveform_list
|
||||
: selected_waveform_list ',' selected_waveform
|
||||
{ list<ExpConditional::case_t*>*tmp = $1;
|
||||
tmp->push_back($3);
|
||||
$$ = tmp;
|
||||
}
|
||||
| selected_waveform
|
||||
{ list<ExpConditional::case_t*>*tmp = new list<ExpConditional::case_t*>;
|
||||
tmp->push_back($1);
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
||||
sequence_of_statements
|
||||
: sequence_of_statements sequential_statement
|
||||
|
|
@ -2224,6 +2308,7 @@ severity
|
|||
errormsg(@1, "Invalid severity level (possible values: NOTE, WARNING, ERROR, FAILURE).\n");
|
||||
$$ = ReportStmt::UNSPECIFIED;
|
||||
}
|
||||
delete[] $2;
|
||||
}
|
||||
|
||||
severity_opt
|
||||
|
|
@ -2359,7 +2444,10 @@ signal_assignment
|
|||
|
||||
signal_assignment_statement
|
||||
: signal_assignment
|
||||
| IDENTIFIER ':' signal_assignment { $$ = $3; }
|
||||
| IDENTIFIER ':' signal_assignment
|
||||
{ delete[] $1;
|
||||
$$ = $3;
|
||||
}
|
||||
|
||||
subprogram_body_start
|
||||
: subprogram_specification K_is
|
||||
|
|
@ -2375,16 +2463,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;
|
||||
}
|
||||
|
|
@ -2429,6 +2521,7 @@ subprogram_kind_opt : subprogram_kind | ;
|
|||
|
||||
subprogram_specification
|
||||
: function_specification { $$ = $1; }
|
||||
| procedure_specification { $$ = $1; }
|
||||
;
|
||||
|
||||
/* This is an implementation of the rule:
|
||||
|
|
@ -2444,6 +2537,7 @@ subprogram_statement_part
|
|||
subtype_declaration
|
||||
: K_subtype IDENTIFIER K_is subtype_indication ';'
|
||||
{ perm_string name = lex_strings.make($2);
|
||||
delete[] $2;
|
||||
if ($4 == 0) {
|
||||
errormsg(@1, "Failed to declare type name %s.\n", name.str());
|
||||
} else {
|
||||
|
|
@ -2593,7 +2687,10 @@ use_clauses_opt
|
|||
|
||||
variable_assignment_statement /* IEEE 1076-2008 P10.6.1 */
|
||||
: variable_assignment
|
||||
| IDENTIFIER ':' variable_assignment { $$ = $3; }
|
||||
| IDENTIFIER ':' variable_assignment
|
||||
{ delete[] $1;
|
||||
$$ = $3;
|
||||
}
|
||||
|
||||
variable_assignment
|
||||
: name VASSIGN expression ';'
|
||||
|
|
@ -2616,11 +2713,12 @@ variable_assignment
|
|||
;
|
||||
|
||||
variable_declaration /* IEEE 1076-2008 P6.4.2.4 */
|
||||
: K_shared_opt K_variable identifier_list ':' subtype_indication ';'
|
||||
: K_shared_opt K_variable identifier_list ':' subtype_indication
|
||||
variable_declaration_assign_opt ';'
|
||||
{ /* 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);
|
||||
Variable*sig = new Variable(*cur, $5, $6);
|
||||
FILE_NAME(sig, @2);
|
||||
active_scope->bind_name(*cur, sig);
|
||||
}
|
||||
|
|
@ -2632,6 +2730,11 @@ variable_declaration /* IEEE 1076-2008 P6.4.2.4 */
|
|||
}
|
||||
;
|
||||
|
||||
variable_declaration_assign_opt
|
||||
: VASSIGN expression { $$ = $2; }
|
||||
| { $$ = 0; }
|
||||
;
|
||||
|
||||
wait_statement
|
||||
: K_wait K_for expression ';'
|
||||
{ WaitForStmt*tmp = new WaitForStmt($3);
|
||||
|
|
|
|||
|
|
@ -63,8 +63,4 @@ extern void library_import(const YYLTYPE&loc, const std::list<perm_string>*names
|
|||
|
||||
extern void library_use(const YYLTYPE&loc, ActiveScope*res, const char*libname, const char*pack, const char*ident);
|
||||
|
||||
extern void generate_global_types(ActiveScope*res);
|
||||
|
||||
extern bool is_global_type(perm_string type_name);
|
||||
|
||||
#endif /* IVL_parse_misc_H */
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@
|
|||
# include "package.h"
|
||||
# include "subprogram.h"
|
||||
# include "entity.h"
|
||||
# include "std_funcs.h"
|
||||
# include "std_types.h"
|
||||
# include <algorithm>
|
||||
# include <iostream>
|
||||
# include <iterator>
|
||||
|
|
@ -65,9 +67,9 @@ 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) {
|
||||
cur->second->set_parent(this);
|
||||
for (map<perm_string,SubprogramHeader*>::iterator cur = cur_subprograms_.begin()
|
||||
; cur != cur_subprograms_.end(); ++cur) {
|
||||
cur->second->set_parent(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -156,15 +158,20 @@ Variable* ScopeBase::find_variable(perm_string by_name) const
|
|||
}
|
||||
}
|
||||
|
||||
const InterfacePort* ScopeBase::find_param(perm_string by_name) const
|
||||
const InterfacePort* ScopeBase::find_param(perm_string) const
|
||||
{
|
||||
for(map<perm_string,Subprogram*>::const_iterator it = use_subprograms_.begin();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const InterfacePort* ScopeBase::find_param_all(perm_string by_name) const
|
||||
{
|
||||
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 +180,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())
|
||||
|
|
@ -185,7 +192,7 @@ Subprogram* ScopeBase::find_subprogram(perm_string name) const
|
|||
if (cur != use_subprograms_.end())
|
||||
return cur->second;
|
||||
|
||||
return 0;
|
||||
return find_std_subprogram(name);
|
||||
}
|
||||
|
||||
const VTypeEnum* ScopeBase::is_enum_name(perm_string name) const
|
||||
|
|
@ -196,7 +203,7 @@ const VTypeEnum* ScopeBase::is_enum_name(perm_string name) const
|
|||
return *it;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return find_std_enum_name(name);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -218,7 +225,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 +281,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,8 @@ 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;
|
||||
const InterfacePort* find_param_all(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 +68,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 +117,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 +171,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 +220,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;
|
||||
|
|
|
|||
|
|
@ -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*)
|
||||
{
|
||||
|
|
@ -149,16 +151,39 @@ int SignalSeqAssignment::elaborate(Entity*ent, ScopeBase*scope)
|
|||
// Elaborate the r-value expressions.
|
||||
for (list<Expression*>::iterator cur = waveform_.begin()
|
||||
; cur != waveform_.end() ; ++cur) {
|
||||
|
||||
errors += (*cur)->elaborate_expr(ent, scope, lval_type);
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,226 @@
|
|||
/*
|
||||
* Copyright CERN 2015
|
||||
* @author Maciej Suminski (maciej.suminski@cern.ch)
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "std_funcs.h"
|
||||
#include "std_types.h"
|
||||
#include "scope.h"
|
||||
|
||||
static std::map<perm_string,SubprogramHeader*> std_subprograms;
|
||||
|
||||
// Special case: to_integer function
|
||||
static class SubprogramToInteger : public SubprogramHeader {
|
||||
public:
|
||||
SubprogramToInteger()
|
||||
: SubprogramHeader(perm_string::literal("to_integer"), NULL, &primitive_REAL) {
|
||||
ports_ = new std::list<InterfacePort*>();
|
||||
ports_->push_back(new InterfacePort(&primitive_INTEGER));
|
||||
}
|
||||
|
||||
bool is_std() const { return true; }
|
||||
|
||||
int emit_name(const std::vector<Expression*>&argv,
|
||||
std::ostream&out, Entity*ent, ScopeBase*scope) const {
|
||||
bool signed_flag = false;
|
||||
|
||||
// to_integer converts unsigned to natural
|
||||
// signed to integer
|
||||
// try to determine the converted type
|
||||
const VType*type = argv[0]->probe_type(ent, scope);
|
||||
const VTypeArray*array = dynamic_cast<const VTypeArray*>(type);
|
||||
|
||||
if(array) {
|
||||
signed_flag = array->signed_vector();
|
||||
} else {
|
||||
cerr << get_fileline() << ": sorry: Could not determine the "
|
||||
<< "expression sign. Output may be erroneous." << endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
out << (signed_flag ? "$signed" : "$unsigned");
|
||||
return 0;
|
||||
}
|
||||
}*fn_to_integer;
|
||||
|
||||
// Special case: size casting (e.g. conv_std_logic_vector() / resize()).
|
||||
static class SubprogramSizeCast : public SubprogramHeader {
|
||||
public:
|
||||
SubprogramSizeCast(perm_string nam)
|
||||
: SubprogramHeader(nam, NULL, &primitive_STDLOGIC_VECTOR) {
|
||||
ports_ = new std::list<InterfacePort*>();
|
||||
ports_->push_back(new InterfacePort(&primitive_STDLOGIC_VECTOR));
|
||||
ports_->push_back(new InterfacePort(&primitive_INTEGER));
|
||||
}
|
||||
|
||||
bool is_std() const { return true; }
|
||||
|
||||
int emit_name(const std::vector<Expression*>&argv,
|
||||
std::ostream&out, Entity*ent, ScopeBase*scope) const {
|
||||
int64_t use_size;
|
||||
bool rc = argv[1]->evaluate(ent, scope, use_size);
|
||||
|
||||
if(!rc) {
|
||||
cerr << get_fileline() << ": sorry: Could not evaluate the "
|
||||
<< "expression size. Size casting impossible." << endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
out << use_size << "'";
|
||||
return 0;
|
||||
}
|
||||
|
||||
int emit_args(const std::vector<Expression*>&argv,
|
||||
std::ostream&out, Entity*ent, ScopeBase*scope) const {
|
||||
|
||||
return argv[0]->emit(out, ent, scope);
|
||||
}
|
||||
}*fn_conv_std_logic_vector, *fn_resize;
|
||||
|
||||
static SubprogramBuiltin*fn_std_logic_vector;
|
||||
static SubprogramBuiltin*fn_to_unsigned;
|
||||
static SubprogramBuiltin*fn_unsigned;
|
||||
static SubprogramBuiltin*fn_integer;
|
||||
|
||||
static SubprogramBuiltin*fn_rising_edge;
|
||||
static SubprogramBuiltin*fn_falling_edge;
|
||||
|
||||
static SubprogramBuiltin*fn_and_reduce;
|
||||
static SubprogramBuiltin*fn_or_reduce;
|
||||
|
||||
void preload_std_funcs(void)
|
||||
{
|
||||
/* numeric_std library
|
||||
* function unsigned
|
||||
*/
|
||||
std::list<InterfacePort*>*fn_unsigned_args = new std::list<InterfacePort*>();
|
||||
fn_unsigned_args->push_back(new InterfacePort(&primitive_INTEGER));
|
||||
fn_unsigned = new SubprogramBuiltin(perm_string::literal("unsigned"),
|
||||
perm_string::literal("$unsigned"),
|
||||
fn_unsigned_args, &primitive_UNSIGNED);
|
||||
std_subprograms[fn_unsigned->name()] = fn_unsigned;
|
||||
|
||||
/* function integer
|
||||
*/
|
||||
std::list<InterfacePort*>*fn_integer_args = new std::list<InterfacePort*>();
|
||||
fn_integer_args->push_back(new InterfacePort(&primitive_INTEGER));
|
||||
fn_integer = new SubprogramBuiltin(perm_string::literal("integer"),
|
||||
perm_string::literal("$signed"),
|
||||
fn_integer_args, &primitive_INTEGER);
|
||||
std_subprograms[fn_integer->name()] = fn_integer;
|
||||
|
||||
/* function std_logic_vector
|
||||
Special case: The std_logic_vector function casts its
|
||||
argument to std_logic_vector. Internally, we don't
|
||||
have to do anything for that to work.
|
||||
*/
|
||||
std::list<InterfacePort*>*fn_std_logic_vector_args = new std::list<InterfacePort*>();
|
||||
fn_std_logic_vector_args->push_back(new InterfacePort(&primitive_STDLOGIC_VECTOR));
|
||||
fn_std_logic_vector = new SubprogramBuiltin(perm_string::literal("std_logic_vector"),
|
||||
empty_perm_string,
|
||||
fn_std_logic_vector_args, &primitive_STDLOGIC_VECTOR);
|
||||
std_subprograms[fn_std_logic_vector->name()] = fn_std_logic_vector;
|
||||
|
||||
/* function resize
|
||||
*/
|
||||
fn_resize = new SubprogramSizeCast(perm_string::literal("resize"));
|
||||
std_subprograms[fn_resize->name()] = fn_resize;
|
||||
|
||||
/* function conv_std_logic_vector
|
||||
*/
|
||||
fn_conv_std_logic_vector = new SubprogramSizeCast(perm_string::literal("conv_std_logic_vector"));
|
||||
std_subprograms[fn_conv_std_logic_vector->name()] = fn_conv_std_logic_vector;
|
||||
|
||||
/* numeric_bit library
|
||||
* function to_integer (arg: unsigned) return natural;
|
||||
* function to_integer (arg: signed) return integer;
|
||||
*/
|
||||
fn_to_integer = new SubprogramToInteger();
|
||||
std_subprograms[fn_to_integer->name()] = fn_to_integer;
|
||||
|
||||
/* std_logic_1164 library
|
||||
* function rising_edge (signal s : std_ulogic) return boolean;
|
||||
*/
|
||||
std::list<InterfacePort*>*fn_rising_edge_args = new std::list<InterfacePort*>();
|
||||
fn_rising_edge_args->push_back(new InterfacePort(&primitive_STDLOGIC));
|
||||
fn_rising_edge = new SubprogramBuiltin(perm_string::literal("rising_edge"),
|
||||
perm_string::literal("$ivlh_rising_edge"),
|
||||
fn_rising_edge_args, &type_BOOLEAN);
|
||||
std_subprograms[fn_rising_edge->name()] = fn_rising_edge;
|
||||
|
||||
/* std_logic_1164 library
|
||||
* function falling_edge (signal s : std_ulogic) return boolean;
|
||||
*/
|
||||
std::list<InterfacePort*>*fn_falling_edge_args = new std::list<InterfacePort*>();
|
||||
fn_falling_edge_args->push_back(new InterfacePort(&primitive_STDLOGIC));
|
||||
fn_falling_edge = new SubprogramBuiltin(perm_string::literal("falling_edge"),
|
||||
perm_string::literal("$ivlh_falling_edge"),
|
||||
fn_falling_edge_args, &type_BOOLEAN);
|
||||
std_subprograms[fn_falling_edge->name()] = fn_falling_edge;
|
||||
|
||||
/* reduce_pack library
|
||||
* function or_reduce(arg : std_logic_vector) return std_logic;
|
||||
*/
|
||||
std::list<InterfacePort*>*fn_or_reduce_args = new std::list<InterfacePort*>();
|
||||
fn_or_reduce_args->push_back(new InterfacePort(&primitive_STDLOGIC_VECTOR));
|
||||
fn_or_reduce = new SubprogramBuiltin(perm_string::literal("or_reduce"),
|
||||
perm_string::literal("|"),
|
||||
fn_or_reduce_args, &primitive_STDLOGIC);
|
||||
std_subprograms[fn_or_reduce->name()] = fn_or_reduce;
|
||||
|
||||
/* reduce_pack library
|
||||
* function and_reduce(arg : std_logic_vector) return std_logic;
|
||||
*/
|
||||
std::list<InterfacePort*>*fn_and_reduce_args = new std::list<InterfacePort*>();
|
||||
fn_and_reduce_args->push_back(new InterfacePort(&primitive_STDLOGIC_VECTOR));
|
||||
fn_and_reduce = new SubprogramBuiltin(perm_string::literal("and_reduce"),
|
||||
perm_string::literal("&"),
|
||||
fn_and_reduce_args, &primitive_STDLOGIC);
|
||||
std_subprograms[fn_and_reduce->name()] = fn_and_reduce;
|
||||
|
||||
/* fixed_pkg library
|
||||
* function to_unsigned (
|
||||
* arg : ufixed; -- fixed point input
|
||||
* constant size : natural) -- length of output
|
||||
* return unsigned;
|
||||
*/
|
||||
std::list<InterfacePort*>*fn_to_unsigned_args = new std::list<InterfacePort*>();
|
||||
fn_to_unsigned_args->push_back(new InterfacePort(&primitive_REAL));
|
||||
fn_to_unsigned_args->push_back(new InterfacePort(&primitive_NATURAL));
|
||||
fn_to_unsigned = new SubprogramBuiltin(perm_string::literal("to_unsigned"),
|
||||
perm_string::literal("$ivlh_to_unsigned"),
|
||||
fn_to_unsigned_args, &primitive_UNSIGNED);
|
||||
std_subprograms[fn_to_unsigned->name()] = fn_to_unsigned;
|
||||
}
|
||||
|
||||
void delete_std_funcs()
|
||||
{
|
||||
for(std::map<perm_string,SubprogramHeader*>::iterator it = std_subprograms.begin();
|
||||
it != std_subprograms.end(); ++it) {
|
||||
delete it->second;
|
||||
}
|
||||
}
|
||||
|
||||
SubprogramHeader*find_std_subprogram(perm_string name)
|
||||
{
|
||||
map<perm_string,SubprogramHeader*>::const_iterator cur = std_subprograms.find(name);
|
||||
if (cur != std_subprograms.end())
|
||||
return cur->second;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
#ifndef IVL_std_funcs_H
|
||||
#define IVL_std_funcs_H
|
||||
/*
|
||||
* Copyright CERN 2015
|
||||
* @author Maciej Suminski (maciej.suminski@cern.ch)
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "subprogram.h"
|
||||
|
||||
// Generates subprogram headers for standard VHDL library functions.
|
||||
void preload_std_funcs();
|
||||
|
||||
// Destroys subprogram headers for standard VHDL library functions.
|
||||
void delete_std_funcs();
|
||||
|
||||
// Returns subprogram header for a requested function or NULL if it does not exist.
|
||||
SubprogramHeader*find_std_subprogram(perm_string name);
|
||||
|
||||
#endif /* IVL_std_funcs_H */
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* Copyright CERN 2015
|
||||
* @author Maciej Suminski (maciej.suminski@cern.ch)
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "std_types.h"
|
||||
#include "scope.h"
|
||||
|
||||
static std::map<perm_string, VTypeDef*> std_types;
|
||||
// this list contains enums used by typedefs in the std_types map
|
||||
static std::list<const VTypeEnum*> std_enums;
|
||||
|
||||
const VTypePrimitive primitive_BIT(VTypePrimitive::BIT, true);
|
||||
const VTypePrimitive primitive_INTEGER(VTypePrimitive::INTEGER);
|
||||
const VTypePrimitive primitive_NATURAL(VTypePrimitive::NATURAL);
|
||||
const VTypePrimitive primitive_REAL(VTypePrimitive::REAL);
|
||||
const VTypePrimitive primitive_STDLOGIC(VTypePrimitive::STDLOGIC, true);
|
||||
const VTypePrimitive primitive_CHARACTER(VTypePrimitive::CHARACTER);
|
||||
const VTypePrimitive primitive_TIME(VTypePrimitive::TIME);
|
||||
|
||||
VTypeDef type_BOOLEAN(perm_string::literal("boolean"));
|
||||
|
||||
const VTypeArray primitive_BIT_VECTOR(&primitive_BIT, vector<VTypeArray::range_t> (1));
|
||||
const VTypeArray primitive_BOOL_VECTOR(&type_BOOLEAN, vector<VTypeArray::range_t> (1));
|
||||
const VTypeArray primitive_STDLOGIC_VECTOR(&primitive_STDLOGIC, vector<VTypeArray::range_t> (1));
|
||||
const VTypeArray primitive_STRING(&primitive_CHARACTER, vector<VTypeArray::range_t> (1));
|
||||
const VTypeArray primitive_SIGNED(&primitive_STDLOGIC, vector<VTypeArray::range_t> (1), true);
|
||||
const VTypeArray primitive_UNSIGNED(&primitive_STDLOGIC, vector<VTypeArray::range_t> (1), false);
|
||||
|
||||
void generate_global_types(ActiveScope*res)
|
||||
{
|
||||
// boolean
|
||||
std::list<perm_string>*enum_BOOLEAN_vals = new std::list<perm_string>;
|
||||
enum_BOOLEAN_vals->push_back(perm_string::literal("false"));
|
||||
enum_BOOLEAN_vals->push_back(perm_string::literal("true"));
|
||||
VTypeEnum*enum_BOOLEAN = new VTypeEnum(enum_BOOLEAN_vals);
|
||||
type_BOOLEAN.set_definition(enum_BOOLEAN);
|
||||
std_types[type_BOOLEAN.peek_name()] = &type_BOOLEAN;
|
||||
std_enums.push_back(enum_BOOLEAN);
|
||||
|
||||
res->use_name(type_BOOLEAN.peek_name(), &type_BOOLEAN);
|
||||
res->use_name(perm_string::literal("bit"), &primitive_BIT);
|
||||
res->use_name(perm_string::literal("bit_vector"), &primitive_BIT_VECTOR);
|
||||
res->use_name(perm_string::literal("integer"), &primitive_INTEGER);
|
||||
res->use_name(perm_string::literal("real"), &primitive_REAL);
|
||||
res->use_name(perm_string::literal("std_logic"), &primitive_STDLOGIC);
|
||||
res->use_name(perm_string::literal("character"), &primitive_CHARACTER);
|
||||
res->use_name(perm_string::literal("string"), &primitive_STRING);
|
||||
res->use_name(perm_string::literal("natural"), &primitive_NATURAL);
|
||||
res->use_name(perm_string::literal("time"), &primitive_TIME);
|
||||
}
|
||||
|
||||
void delete_global_types()
|
||||
{
|
||||
typedef_context_t typedef_ctx;
|
||||
for(map<perm_string, VTypeDef*>::iterator cur = std_types.begin();
|
||||
cur != std_types.end() ; ++ cur) {
|
||||
delete cur->second->peek_definition();
|
||||
delete cur->second;
|
||||
}
|
||||
}
|
||||
|
||||
const VTypeEnum*find_std_enum_name(perm_string name)
|
||||
{
|
||||
for(list<const VTypeEnum*>::const_iterator it = std_enums.begin();
|
||||
it != std_enums.end(); ++it) {
|
||||
if((*it)->has_name(name))
|
||||
return *it;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void emit_std_types(ostream&fd)
|
||||
{
|
||||
fd << "`ifndef __VHDL_STD_TYPES" << endl;
|
||||
fd << "`define __VHDL_STD_TYPES" << endl;
|
||||
typedef_context_t typedef_ctx;
|
||||
for(map<perm_string, VTypeDef*>::iterator cur = std_types.begin();
|
||||
cur != std_types.end() ; ++ cur) {
|
||||
cur->second->emit_typedef(fd, typedef_ctx);
|
||||
}
|
||||
fd << "`endif" << endl;
|
||||
}
|
||||
|
||||
bool is_global_type(perm_string name)
|
||||
{
|
||||
if (name == "boolean") return true;
|
||||
if (name == "bit") return true;
|
||||
if (name == "bit_vector") return true;
|
||||
if (name == "integer") return true;
|
||||
if (name == "real") return true;
|
||||
if (name == "std_logic") return true;
|
||||
if (name == "std_logic_vector") return true;
|
||||
if (name == "character") return true;
|
||||
if (name == "string") return true;
|
||||
if (name == "natural") return true;
|
||||
if (name == "signed") return true;
|
||||
if (name == "unsigned") return true;
|
||||
if (name == "time") return true;
|
||||
|
||||
return std_types.count(name) > 0;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright CERN 2015
|
||||
* @author Maciej Suminski (maciej.suminski@cern.ch)
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "vtype.h"
|
||||
|
||||
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();
|
||||
const VTypeEnum*find_std_enum_name(perm_string name);
|
||||
|
||||
extern const VTypePrimitive primitive_BOOLEAN;
|
||||
extern const VTypePrimitive primitive_BIT;
|
||||
extern const VTypePrimitive primitive_INTEGER;
|
||||
extern const VTypePrimitive primitive_NATURAL;
|
||||
extern const VTypePrimitive primitive_REAL;
|
||||
extern const VTypePrimitive primitive_STDLOGIC;
|
||||
extern const VTypePrimitive primitive_CHARACTER;
|
||||
extern const VTypePrimitive primitive_TIME;
|
||||
|
||||
extern VTypeDef type_BOOLEAN;
|
||||
|
||||
extern const VTypeArray primitive_BIT_VECTOR;
|
||||
extern const VTypeArray primitive_BOOL_VECTOR;
|
||||
extern const VTypeArray primitive_STDLOGIC_VECTOR;
|
||||
extern const VTypeArray primitive_STRING;
|
||||
extern const VTypeArray primitive_SIGNED;
|
||||
extern const VTypeArray primitive_UNSIGNED;
|
||||
|
|
@ -30,44 +30,70 @@
|
|||
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
if(ports_) {
|
||||
for(std::list<InterfacePort*>::const_iterator it = ports_->begin();
|
||||
it != ports_->end(); ++it) {
|
||||
if((*it)->type->is_unbounded())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
fd << "begin" << endl;
|
||||
|
||||
return false;
|
||||
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_;
|
||||
|
||||
if(ports_) {
|
||||
for(list<InterfacePort*>::iterator it = ports_->begin();
|
||||
it != ports_->end(); ++it)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
delete ports_;
|
||||
}
|
||||
}
|
||||
|
||||
bool SubprogramHeader::compare_specification(SubprogramHeader*that) const
|
||||
{
|
||||
if (name_ != that->name_)
|
||||
return false;
|
||||
|
|
@ -98,7 +124,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 +138,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 +149,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_ && 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) const {
|
||||
assert(arguments.size() == ports_->size());
|
||||
|
||||
std::list<InterfacePort*>*ports = new std::list<InterfacePort*>;
|
||||
|
|
@ -142,25 +198,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_);
|
||||
|
||||
// Copy variables
|
||||
for(std::map<perm_string,Variable*>::iterator it = new_variables_.begin();
|
||||
it != new_variables_.end(); ++it) {
|
||||
Variable*v = new Variable(it->first, it->second->peek_type()->clone());
|
||||
instance->new_variables_[it->first] = v;
|
||||
if(body_) {
|
||||
SubprogramBody*body_inst = new SubprogramBody();
|
||||
|
||||
// Copy variables
|
||||
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());
|
||||
body_inst->new_variables_[it->first] = v;
|
||||
}
|
||||
|
||||
body_inst->set_statements(body_->statements_);
|
||||
instance->set_parent(scope);
|
||||
instance->set_body(body_inst);
|
||||
instance->fix_return_type();
|
||||
}
|
||||
|
||||
instance->set_parent(scope);
|
||||
instance->set_program_body(statements_);
|
||||
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,38 +257,44 @@ 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
|
||||
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 << " : ";
|
||||
|
|
@ -236,44 +304,21 @@ void Subprogram::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);
|
||||
fd << ";" << endl;
|
||||
}
|
||||
|
||||
void Subprogram::write_to_stream_body(ostream&fd) const
|
||||
SubprogramBuiltin::SubprogramBuiltin(perm_string vhdl_name, perm_string sv_name,
|
||||
std::list<InterfacePort*>*ports, const VType*return_type)
|
||||
: SubprogramHeader(vhdl_name, ports, return_type), sv_name_(sv_name)
|
||||
{
|
||||
}
|
||||
|
||||
SubprogramBuiltin::~SubprogramBuiltin()
|
||||
{
|
||||
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 << " 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,63 +27,122 @@
|
|||
# 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(); }
|
||||
virtual ~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;
|
||||
// Is the subprogram coming from the standard library?
|
||||
virtual bool is_std() const { return false; }
|
||||
|
||||
inline SubprogramBody*body() const { return body_; }
|
||||
void set_body(SubprogramBody*bdy);
|
||||
|
||||
inline perm_string name() const { return name_; }
|
||||
|
||||
// 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
|
||||
// (think of size casting or signed/unsigned functions).
|
||||
virtual int emit_name(const std::vector<Expression*>&,
|
||||
std::ostream&out, Entity*, ScopeBase*) const;
|
||||
|
||||
// Emit arguments for a specific call. It allows to reorder or skip
|
||||
// some of the arguments if function signature is different in
|
||||
// SystemVerilog compared to VHDL.
|
||||
virtual int emit_args(const std::vector<Expression*>&argv,
|
||||
std::ostream&out, Entity*, ScopeBase*) const;
|
||||
|
||||
// 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) const;
|
||||
|
||||
// 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;
|
||||
|
||||
private:
|
||||
void write_to_stream(std::ostream&fd) const;
|
||||
void dump(std::ostream&fd) const;
|
||||
|
||||
protected:
|
||||
// Tries to set the return type to a fixed type. VHDL functions that
|
||||
// return std_logic_vectors do not specify its length, as SystemVerilog
|
||||
// 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_;
|
||||
};
|
||||
|
||||
// Class to define functions headers defined in the standard VHDL libraries.
|
||||
class SubprogramBuiltin : public SubprogramHeader
|
||||
{
|
||||
public:
|
||||
SubprogramBuiltin(perm_string vhdl_name, perm_string sv_name,
|
||||
std::list<InterfacePort*>*ports, const VType*return_type);
|
||||
~SubprogramBuiltin();
|
||||
|
||||
bool is_std() const { return true; }
|
||||
|
||||
int emit_name(const std::vector<Expression*>&, std::ostream&out, Entity*, ScopeBase*) const;
|
||||
|
||||
private:
|
||||
// SystemVerilog counterpart function name
|
||||
perm_string sv_name_;
|
||||
};
|
||||
|
||||
#endif /* IVL_subprogram_H */
|
||||
|
|
|
|||
|
|
@ -25,19 +25,42 @@
|
|||
|
||||
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;
|
||||
|
||||
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())
|
||||
|
|
@ -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,31 @@ 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;
|
||||
}
|
||||
|
||||
int SubprogramBuiltin::emit_name(const std::vector<Expression*>&,
|
||||
std::ostream&out, Entity*, ScopeBase*) const
|
||||
{
|
||||
// do not escape the names for builtin functions
|
||||
out << sv_name_;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ int Signal::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
|||
return errors;
|
||||
}
|
||||
|
||||
int Variable::emit(ostream&out, Entity*, ScopeBase*)
|
||||
int Variable::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
|
|
@ -75,6 +75,12 @@ int Variable::emit(ostream&out, Entity*, ScopeBase*)
|
|||
if (peek_refcnt_sequ_() > 0 || !peek_type()->can_be_packed())
|
||||
decl.reg_flag = true;
|
||||
errors += decl.emit(out, peek_name());
|
||||
|
||||
Expression*init_expr = peek_init_expr();
|
||||
if (init_expr) {
|
||||
out << " = ";
|
||||
init_expr->emit(out, ent, scope);
|
||||
}
|
||||
out << ";" << endl;
|
||||
return errors;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ class Signal : public SigVarBase {
|
|||
class Variable : public SigVarBase {
|
||||
|
||||
public:
|
||||
Variable(perm_string name, const VType*type);
|
||||
Variable(perm_string name, const VType*type, Expression*init_expr = NULL);
|
||||
|
||||
int emit(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
void write_to_stream(std::ostream&fd);
|
||||
|
|
@ -93,8 +93,8 @@ inline Signal::Signal(perm_string name, const VType*type, Expression*init_expr)
|
|||
{
|
||||
}
|
||||
|
||||
inline Variable::Variable(perm_string name, const VType*type)
|
||||
: SigVarBase(name, type, 0)
|
||||
inline Variable::Variable(perm_string name, const VType*type, Expression*init_expr)
|
||||
: SigVarBase(name, type, init_expr)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,9 +55,6 @@ VTypePrimitive::~VTypePrimitive()
|
|||
void VTypePrimitive::show(ostream&out) const
|
||||
{
|
||||
switch (type_) {
|
||||
case BOOLEAN:
|
||||
out << "BOOLEAN";
|
||||
break;
|
||||
case BIT:
|
||||
out << "BIT";
|
||||
break;
|
||||
|
|
@ -85,7 +82,6 @@ void VTypePrimitive::show(ostream&out) const
|
|||
int VTypePrimitive::get_width(ScopeBase*) const
|
||||
{
|
||||
switch(type_) {
|
||||
case BOOLEAN:
|
||||
case BIT:
|
||||
case STDLOGIC:
|
||||
return 1;
|
||||
|
|
@ -266,12 +262,11 @@ bool VTypeArray::is_variable_length(ScopeBase*scope) const {
|
|||
void VTypeArray::evaluate_ranges(ScopeBase*scope) {
|
||||
for(std::vector<range_t>::iterator it = ranges_.begin(); it != ranges_.end(); ++it ) {
|
||||
int64_t lsb_val = -1, msb_val = -1;
|
||||
bool dir = it->is_downto();
|
||||
|
||||
if(it->msb()->evaluate(scope, msb_val) && it->lsb()->evaluate(scope, lsb_val)) {
|
||||
assert(lsb_val >= 0);
|
||||
assert(msb_val >= 0);
|
||||
*it = range_t(new ExpInteger(msb_val), new ExpInteger(lsb_val), dir);
|
||||
*it = range_t(new ExpInteger(msb_val), new ExpInteger(lsb_val), msb_val > lsb_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ class VTypeERROR : public VType {
|
|||
class VTypePrimitive : public VType {
|
||||
|
||||
public:
|
||||
enum type_t { BOOLEAN, BIT, INTEGER, NATURAL, REAL, STDLOGIC, CHARACTER, TIME };
|
||||
enum type_t { BIT, INTEGER, NATURAL, REAL, STDLOGIC, CHARACTER, TIME };
|
||||
|
||||
public:
|
||||
VTypePrimitive(type_t tt, bool packed = false);
|
||||
|
|
@ -180,15 +180,6 @@ class VTypePrimitive : public VType {
|
|||
bool packed_;
|
||||
};
|
||||
|
||||
extern const VTypePrimitive primitive_BOOLEAN;
|
||||
extern const VTypePrimitive primitive_BIT;
|
||||
extern const VTypePrimitive primitive_INTEGER;
|
||||
extern const VTypePrimitive primitive_NATURAL;
|
||||
extern const VTypePrimitive primitive_REAL;
|
||||
extern const VTypePrimitive primitive_STDLOGIC;
|
||||
extern const VTypePrimitive primitive_CHARACTER;
|
||||
extern const VTypePrimitive primitive_TIME;
|
||||
|
||||
/*
|
||||
* An array is a compound N-dimensional array of element type. The
|
||||
* construction of the array is from an element type and a vector of
|
||||
|
|
@ -265,6 +256,8 @@ class VTypeArray : public VType {
|
|||
private:
|
||||
int emit_with_dims_(std::ostream&out, bool packed, perm_string name) const;
|
||||
|
||||
// Handles a few special types of array (*_vector, string types).
|
||||
bool write_special_case(std::ostream&out) const;
|
||||
void write_range_to_stream_(std::ostream&fd) const;
|
||||
|
||||
const VType*etype_;
|
||||
|
|
@ -363,6 +356,8 @@ class VTypeDef : public VType {
|
|||
|
||||
VType*clone() const { return new VTypeDef(*this); }
|
||||
|
||||
bool type_match(const VType*that) const;
|
||||
|
||||
inline perm_string peek_name() const { return name_; }
|
||||
|
||||
// If the type is not given a definition in the constructor,
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ int VTypeArray::emit_with_dims_(std::ostream&out, bool packed, perm_string name)
|
|||
int VTypeEnum::emit_def(ostream&out, perm_string name) const
|
||||
{
|
||||
int errors = 0;
|
||||
out << "enum {";
|
||||
out << "enum integer {";
|
||||
assert(names_.size() >= 1);
|
||||
out << "\\" << names_[0] << " ";
|
||||
for (size_t idx = 1 ; idx < names_.size() ; idx += 1)
|
||||
|
|
@ -148,9 +148,6 @@ int VTypePrimitive::emit_primitive_type(ostream&out) const
|
|||
{
|
||||
int errors = 0;
|
||||
switch (type_) {
|
||||
case BOOLEAN:
|
||||
out << "boolean";
|
||||
break;
|
||||
case BIT:
|
||||
out << "bit";
|
||||
break;
|
||||
|
|
@ -167,7 +164,7 @@ int VTypePrimitive::emit_primitive_type(ostream&out) const
|
|||
out << "real";
|
||||
break;
|
||||
case CHARACTER:
|
||||
out << "char";
|
||||
out << "byte";
|
||||
break;
|
||||
case TIME:
|
||||
out << "time";
|
||||
|
|
@ -229,10 +226,9 @@ int VTypeDef::emit_def(ostream&out, perm_string name) const
|
|||
int VTypeDef::emit_decl(ostream&out, perm_string name, bool reg_flag) const
|
||||
{
|
||||
int errors = 0;
|
||||
if (reg_flag)
|
||||
out << "reg ";
|
||||
else
|
||||
out << "wire ";
|
||||
|
||||
if (!dynamic_cast<const VTypeEnum*>(type_))
|
||||
out << (reg_flag ? "reg " : "wire ");
|
||||
|
||||
if(dynamic_cast<const VTypeArray*>(type_)) {
|
||||
errors += type_->emit_def(out, name);
|
||||
|
|
|
|||
|
|
@ -22,5 +22,21 @@
|
|||
|
||||
bool VType::type_match(const VType*that) const
|
||||
{
|
||||
return this == that;
|
||||
if(this == that)
|
||||
return true;
|
||||
|
||||
if(const VTypeDef*tdef = dynamic_cast<const VTypeDef*>(that)) {
|
||||
if(type_match(tdef->peek_definition()))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VTypeDef::type_match(const VType*that) const
|
||||
{
|
||||
if(VType::type_match(that))
|
||||
return true;
|
||||
|
||||
return VType::type_match(type_);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
# define __STDC_LIMIT_MACROS
|
||||
# include "vtype.h"
|
||||
# include "std_types.h"
|
||||
# include "expression.h"
|
||||
# include <typeinfo>
|
||||
# include <stdint.h>
|
||||
|
|
@ -38,20 +38,8 @@ void VType::write_type_to_stream(ostream&fd) const
|
|||
|
||||
void VTypeArray::write_to_stream(ostream&fd) const
|
||||
{
|
||||
// Special cases: std_logic_vector & string
|
||||
if (etype_ == &primitive_STDLOGIC) {
|
||||
fd << "std_logic_vector";
|
||||
if (!ranges_.empty() && !ranges_[0].is_box()) {
|
||||
write_range_to_stream_(fd);
|
||||
}
|
||||
return;
|
||||
} else if (etype_ == &primitive_CHARACTER) {
|
||||
fd << "string";
|
||||
if (!ranges_.empty() && !ranges_[0].is_box()) {
|
||||
write_range_to_stream_(fd);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(write_special_case(fd))
|
||||
return;
|
||||
|
||||
bool typedefed = false;
|
||||
if(const VTypeDef*tdef = dynamic_cast<const VTypeDef*>(etype_)) {
|
||||
|
|
@ -96,26 +84,37 @@ void VTypeArray::write_range_to_stream_(std::ostream&fd) const
|
|||
fd << ") ";
|
||||
}
|
||||
|
||||
bool VTypeArray::write_special_case(std::ostream&fd) const
|
||||
{
|
||||
if(this == &primitive_SIGNED) {
|
||||
fd << "signed";
|
||||
} else if(this == &primitive_UNSIGNED) {
|
||||
fd << "unsigned";
|
||||
} else if(etype_ == &primitive_STDLOGIC) {
|
||||
fd << "std_logic_vector";
|
||||
} else if(etype_ == &primitive_BIT) {
|
||||
fd << "bit_vector";
|
||||
} else if(etype_ == &primitive_CHARACTER) {
|
||||
fd << "string";
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!ranges_.empty() && !ranges_[0].is_box()) {
|
||||
write_range_to_stream_(fd);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void VTypeArray::write_type_to_stream(ostream&fd) const
|
||||
{
|
||||
// Special case: std_logic_vector
|
||||
if (etype_ == &primitive_STDLOGIC) {
|
||||
fd << "std_logic_vector";
|
||||
if (! ranges_.empty() && ! ranges_[0].is_box()) {
|
||||
write_range_to_stream_(fd);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (etype_ == &primitive_CHARACTER) {
|
||||
fd << "string";
|
||||
if (! ranges_.empty() && ! ranges_[0].is_box()) {
|
||||
write_range_to_stream_(fd);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(write_special_case(fd))
|
||||
return;
|
||||
|
||||
fd << "array ";
|
||||
|
||||
// Unbounded array
|
||||
if (! ranges_.empty()) {
|
||||
assert(ranges_.size() < 2);
|
||||
if (ranges_[0].is_box()) {
|
||||
|
|
@ -165,9 +164,6 @@ void VTypePrimitive::write_to_stream(ostream&fd) const
|
|||
case CHARACTER:
|
||||
fd << "character";
|
||||
break;
|
||||
case BOOLEAN:
|
||||
fd << "boolean";
|
||||
break;
|
||||
case TIME:
|
||||
fd << "time";
|
||||
break;
|
||||
|
|
@ -183,7 +179,7 @@ void VTypeRange::write_to_stream(ostream&fd) const
|
|||
// Detect some special cases that can be written as ieee or
|
||||
// standard types.
|
||||
if (const VTypePrimitive*tmp = dynamic_cast<const VTypePrimitive*> (base_)) {
|
||||
if (start_==0 && end_==INT64_MAX && tmp->type()==VTypePrimitive::INTEGER) {
|
||||
if (tmp->type()==VTypePrimitive::NATURAL) {
|
||||
fd << "natural";
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -156,16 +156,16 @@ static PLI_INT32 ivlh_attribute_event_calltf(ICARUS_VPI_CONST PLI_BYTE8*data)
|
|||
|
||||
rval.value.scalar = vpi1;
|
||||
|
||||
// Detect if there was any change
|
||||
// Detect if change occured in this moment
|
||||
if (mon->last_event.high != tnow.high)
|
||||
rval.value.scalar = vpi0;
|
||||
if (mon->last_event.low != tnow.low)
|
||||
rval.value.scalar = vpi0;
|
||||
|
||||
// Determine the edge, if required
|
||||
if (type == RISING_EDGE && mon->last_value.value.scalar == vpi0)
|
||||
if (type == RISING_EDGE && mon->last_value.value.scalar != vpi1)
|
||||
rval.value.scalar = vpi0;
|
||||
else if (type == FALLING_EDGE && mon->last_value.value.scalar == vpi1)
|
||||
else if (type == FALLING_EDGE && mon->last_value.value.scalar != vpi0)
|
||||
rval.value.scalar = vpi0;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue