Merge branch 'master' into return-stack

# Conflicts:
#	sv_vpi_user.h
This commit is contained in:
Stephen Williams 2016-02-01 14:47:44 -08:00
commit f494b478cc
52 changed files with 1030 additions and 537 deletions

View File

@ -384,6 +384,11 @@ The function returns an integer.
The function returns a vector with the given width, and is signed or The function returns a vector with the given width, and is signed or
unsigned according to the flag. unsigned according to the flag.
.TP 8
.B vpiSysFuncString
The function returns a string. This is an Icarus-specific extension, not
available in the VPI standard.
.SH "COMMAND FILES" .SH "COMMAND FILES"
The command file allows the user to place source file names and The command file allows the user to place source file names and
certain command line switches into a text file instead of on a long certain command line switches into a text file instead of on a long

View File

@ -2838,7 +2838,7 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
concat->set(idx, parms[off+idx]); concat->set(idx, parms[off+idx]);
} }
if (wid_sum == 0) { if (wid_sum == 0 && expr_type_ != IVL_VT_STRING) {
cerr << get_fileline() << ": error: Concatenation/replication " cerr << get_fileline() << ": error: Concatenation/replication "
<< "may not have zero width in this context." << endl; << "may not have zero width in this context." << endl;
des->errors += 1; des->errors += 1;

View File

@ -75,6 +75,10 @@ EXTERN_C_START
/********* task/function properties **********/ /********* task/function properties **********/
#define vpiOtherFunc 6 #define vpiOtherFunc 6
/* Icarus-specific function type to use string as the return type */
#define vpiStringFunc 10
#define vpiSysFuncString vpiSysFuncString
EXTERN_C_END EXTERN_C_END
#endif /* SV_VPI_USER_H */ #endif /* SV_VPI_USER_H */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2002-2015 Stephen Williams (steve@icarus.com) * Copyright (c) 2002-2016 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -103,6 +103,14 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
NetNet*rsig = rval_->synthesize(des, scope, rval_); NetNet*rsig = rval_->synthesize(des, scope, rval_);
assert(rsig); assert(rsig);
if (lval_->word() && ! dynamic_cast<NetEConst*>(lval_->word())) {
cerr << get_fileline() << ": sorry: assignment to variable "
"location in memory is not currently supported in "
"synthesis." << endl;
des->errors += 1;
return false;
}
NetNet*lsig = lval_->sig(); NetNet*lsig = lval_->sig();
if (!lsig) { if (!lsig) {
cerr << get_fileline() << ": error: " cerr << get_fileline() << ": error: "
@ -218,6 +226,8 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
rsig = tmp; rsig = tmp;
} }
rsig = crop_to_width(des, rsig, lsig->vector_width());
if (nex_out.pin_count() > 1) { if (nex_out.pin_count() > 1) {
NexusSet tmp_set; NexusSet tmp_set;
nex_output(tmp_set); nex_output(tmp_set);
@ -1411,6 +1421,16 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope,
are used to collect the outputs from the substatement are used to collect the outputs from the substatement
for the inputs of the FF bank. */ for the inputs of the FF bank. */
NetBus tmp_out (scope, tmp_set.size()); NetBus tmp_out (scope, tmp_set.size());
for (unsigned idx = 0 ; idx < tmp_out.pin_count() ; idx += 1) {
unsigned ptr = nex_map.find_nexus(tmp_set[idx]);
ivl_assert(*this, ptr < nex_out.pin_count());
if (nex_out.pin(ptr).is_linked()) {
cerr << get_fileline() << ": sorry: multiple statements "
"assigning to the same flip-flop are not yet "
"supported in synthesis." << endl;
return false;
}
}
/* Create a temporary ff_ce (FF clock-enable) that /* Create a temporary ff_ce (FF clock-enable) that
accounts for the subset of outputs that this accounts for the subset of outputs that this

View File

@ -204,6 +204,17 @@ int load_sys_func_table(const char*path)
continue; continue;
} }
if (strcmp(stype,"vpiSysFuncString") == 0) {
cell = new struct sfunc_return_type_cell;
cell->name = lex_strings.add(name);
cell->type = IVL_VT_STRING;
cell->wid = 0; // string is a dynamic length type
cell->signed_flag = false;
cell->next = sfunc_stack;
sfunc_stack = cell;
continue;
}
fprintf(stderr, "%s:%s: Unknown type: %s\n", fprintf(stderr, "%s:%s: Unknown type: %s\n",
path, name, stype); path, name, stype);
} }

View File

@ -519,3 +519,14 @@ void draw_vpi_rfunc_call(ivl_expr_t fnet)
draw_vpi_taskfunc_args(call_string, 0, fnet); draw_vpi_taskfunc_args(call_string, 0, fnet);
} }
void draw_vpi_sfunc_call(ivl_expr_t fnet)
{
char call_string[1024];
sprintf(call_string, " %%vpi_func/s %u %u \"%s\"",
ivl_file_table_index(ivl_expr_file(fnet)),
ivl_expr_lineno(fnet), ivl_expr_name(fnet));
draw_vpi_taskfunc_args(call_string, 0, fnet);
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014 Stephen Williams (steve@icarus.com) * Copyright (c) 2014-2016 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -76,8 +76,8 @@ static int draw_condition_binary_compare(ivl_expr_t expr)
%cmp instruction. */ %cmp instruction. */
if (ivl_expr_width(le)==use_wid && test_immediate_vec4_ok(le)) { if (ivl_expr_width(le)==use_wid && test_immediate_vec4_ok(le)) {
ivl_expr_t tmp = le; ivl_expr_t tmp = le;
re = le; le = re;
le = tmp; re = tmp;
} }
draw_eval_vec4(le); draw_eval_vec4(le);

View File

@ -163,6 +163,12 @@ static void string_ex_pop(ivl_expr_t expr)
fprintf(vvp_out, " %%qpop/%s/str v%p_0;\n", fb, ivl_expr_signal(arg)); fprintf(vvp_out, " %%qpop/%s/str v%p_0;\n", fb, ivl_expr_signal(arg));
} }
static void draw_sfunc_string(ivl_expr_t expr)
{
assert(ivl_expr_value(expr) == IVL_VT_STRING);
draw_vpi_sfunc_call(expr);
}
void draw_eval_string(ivl_expr_t expr) void draw_eval_string(ivl_expr_t expr)
{ {
@ -195,7 +201,7 @@ void draw_eval_string(ivl_expr_t expr)
else if (strcmp(ivl_expr_name(expr), "$ivl_darray_method$pop_front")==0) else if (strcmp(ivl_expr_name(expr), "$ivl_darray_method$pop_front")==0)
string_ex_pop(expr); string_ex_pop(expr);
else else
fallback_eval(expr); draw_sfunc_string(expr);
break; break;
case IVL_EX_UFUNC: case IVL_EX_UFUNC:

View File

@ -133,6 +133,7 @@ extern void draw_vpi_task_call(ivl_statement_t net);
extern void draw_vpi_func_call(ivl_expr_t expr); extern void draw_vpi_func_call(ivl_expr_t expr);
extern void draw_vpi_rfunc_call(ivl_expr_t expr); extern void draw_vpi_rfunc_call(ivl_expr_t expr);
extern void draw_vpi_sfunc_call(ivl_expr_t expr);
extern void draw_class_in_scope(ivl_type_t classtype); extern void draw_class_in_scope(ivl_type_t classtype);

View File

@ -137,7 +137,7 @@ GenerateStatement::~GenerateStatement()
} }
ForGenerate::ForGenerate(perm_string gname, perm_string genvar, ForGenerate::ForGenerate(perm_string gname, perm_string genvar,
prange_t*rang, std::list<Architecture::Statement*>&s) ExpRange*rang, std::list<Architecture::Statement*>&s)
: GenerateStatement(gname, s), genvar_(genvar), : GenerateStatement(gname, s), genvar_(genvar),
lsb_(rang->lsb()), msb_(rang->msb()) lsb_(rang->lsb()), msb_(rang->msb())
{ {

View File

@ -33,7 +33,7 @@ class GenerateStatement;
class SequentialStmt; class SequentialStmt;
class Signal; class Signal;
class named_expr_t; class named_expr_t;
class prange_t; class ExpRange;
/* /*
* The Architecture class carries the contents (name, statements, * The Architecture class carries the contents (name, statements,
@ -142,7 +142,7 @@ class ForGenerate : public GenerateStatement {
public: public:
ForGenerate(perm_string gname, perm_string genvar, ForGenerate(perm_string gname, perm_string genvar,
prange_t*rang, std::list<Architecture::Statement*>&s); ExpRange*rang, std::list<Architecture::Statement*>&s);
~ForGenerate(); ~ForGenerate();
int elaborate(Entity*ent, Architecture*arc); int elaborate(Entity*ent, Architecture*arc);

View File

@ -21,6 +21,7 @@
# include "entity.h" # include "entity.h"
# include "expression.h" # include "expression.h"
# include "sequential.h" # include "sequential.h"
# include "subprogram.h"
# include <typeinfo> # include <typeinfo>
# include <cassert> # include <cassert>
@ -59,6 +60,11 @@ int Architecture::elaborate(Entity*entity)
cur->second->elaborate_init_expr(entity, this); cur->second->elaborate_init_expr(entity, this);
} }
// Elaborate subprograms
for (map<perm_string,SubprogramHeader*>::const_iterator cur = cur_subprograms_.begin()
; cur != cur_subprograms_.end() ; ++cur) {
errors += cur->second->elaborate();
}
// Create 'initial' and 'final' blocks for implicit // Create 'initial' and 'final' blocks for implicit
// initalization and clean-up actions // initalization and clean-up actions
if(!initializers_.empty()) if(!initializers_.empty())
@ -222,7 +228,7 @@ int ProcessStatement::rewrite_as_always_edge_(Entity*, Architecture*)
} }
// If operand1 is not an 'event attribute, I give up. // If operand1 is not an 'event attribute, I give up.
const ExpAttribute*op1 = dynamic_cast<const ExpAttribute*>(op1_raw); const ExpObjAttribute*op1 = dynamic_cast<const ExpObjAttribute*>(op1_raw);
if (op1 == 0) if (op1 == 0)
return -1; return -1;
if (op1->peek_attribute() != "event") if (op1->peek_attribute() != "event")

View File

@ -101,7 +101,7 @@ void ComponentBase::dump_ports(ostream&out, int indent) const
} }
} }
void Scope::dump_scope(ostream&out) const void ScopeBase::dump_scope(ostream&out) const
{ {
// Dump types // Dump types
out << " -- imported types" << endl; out << " -- imported types" << endl;
@ -251,9 +251,16 @@ void ExpAggregate::choice_t::dump(ostream&out, int indent) const
out << setw(indent) << "" << "?choice_t?" << endl; out << setw(indent) << "" << "?choice_t?" << endl;
} }
void ExpAttribute::dump(ostream&out, int indent) const void ExpTypeAttribute::dump(ostream&out, int indent) const
{ {
out << setw(indent) << "" << "Attribute " << name_ out << setw(indent) << "" << "Attribute (type-related) " << name_
<< " at " << get_fileline() << endl;
base_->show(out);
}
void ExpObjAttribute::dump(ostream&out, int indent) const
{
out << setw(indent) << "" << "Attribute (object-related) " << name_
<< " at " << get_fileline() << endl; << " at " << get_fileline() << endl;
base_->dump(out, indent+4); base_->dump(out, indent+4);
} }
@ -442,13 +449,6 @@ void named_expr_t::dump(ostream&out, int indent) const
expr_->dump(out, indent); expr_->dump(out, indent);
} }
void prange_t::dump(ostream&out, int indent) const
{
left_->dump(out, indent);
out << setw(indent) << "" << (direction_ ? "downto" : "to");
right_->dump(out, indent);
}
ostream& Expression::dump_inline(ostream&out) const ostream& Expression::dump_inline(ostream&out) const
{ {
out << typeid(*this).name(); out << typeid(*this).name();

View File

@ -54,29 +54,88 @@ bool Expression::symbolic_compare(const Expression*) const
return false; return false;
} }
ExpAttribute::ExpAttribute(ExpName*bas, perm_string nam) ExpAttribute::ExpAttribute(perm_string nam, list<Expression*>*args)
: base_(bas), name_(nam) : name_(nam), args_(args)
{ {
} }
ExpAttribute::~ExpAttribute() ExpAttribute::~ExpAttribute()
{ {
/* Different attributes can point to the same base so we cannot delete this here. if(args_) {
* Look at the vhdl_range test with valgrind to see this issue. */ for(list<Expression*>::iterator it = args_->begin();
// delete base_; it != args_->end(); ++it) {
delete *it;
}
}
delete args_;
} }
Expression*ExpAttribute::clone() const list<Expression*>*ExpAttribute::clone_args() const {
{ list<Expression*>*new_args = NULL;
return new ExpAttribute(static_cast<ExpName*>(base_->clone()), name_);
if(args_) {
for(list<Expression*>::iterator it = args_->begin();
it != args_->end(); ++it) {
new_args->push_back((*it)->clone());
}
}
return new_args;
} }
void ExpAttribute::visit(ExprVisitor& func) void ExpAttribute::visit_args(ExprVisitor& func)
{ {
if(args_) {
for(list<Expression*>::iterator it = args_->begin();
it != args_->end(); ++it) {
func(*it);
}
}
}
ExpObjAttribute::ExpObjAttribute(ExpName*base, perm_string name, list<Expression*>*args)
: ExpAttribute(name, args), base_(base)
{
}
ExpObjAttribute::~ExpObjAttribute()
{
delete base_;
}
Expression*ExpObjAttribute::clone() const
{
return new ExpObjAttribute(static_cast<ExpName*>(base_->clone()),
name_, clone_args());
}
void ExpObjAttribute::visit(ExprVisitor& func)
{
visit_args(func);
base_->visit(func); base_->visit(func);
func(this); func(this);
} }
ExpTypeAttribute::ExpTypeAttribute(const VType*base, perm_string name, list<Expression*>*args)
: ExpAttribute(name, args), base_(base)
{
}
Expression*ExpTypeAttribute::clone() const
{
return new ExpTypeAttribute(base_, name_, clone_args());
}
void ExpTypeAttribute::visit(ExprVisitor& func)
{
visit_args(func);
func(this);
}
const perm_string ExpAttribute::LEFT = perm_string::literal("left");
const perm_string ExpAttribute::RIGHT = perm_string::literal("right");
ExpBinary::ExpBinary(Expression*op1, Expression*op2) ExpBinary::ExpBinary(Expression*op1, Expression*op2)
: operand1_(op1), operand2_(op2) : operand1_(op1), operand2_(op2)
{ {
@ -88,14 +147,14 @@ ExpBinary::~ExpBinary()
delete operand2_; delete operand2_;
} }
bool ExpBinary::eval_operand1(ScopeBase*scope, int64_t&val) const bool ExpBinary::eval_operand1(Entity*ent, ScopeBase*scope, int64_t&val) const
{ {
return operand1_->evaluate(scope, val); return operand1_->evaluate(ent, scope, val);
} }
bool ExpBinary::eval_operand2(ScopeBase*scope, int64_t&val) const bool ExpBinary::eval_operand2(Entity*ent, ScopeBase*scope, int64_t&val) const
{ {
return operand2_->evaluate(scope, val); return operand2_->evaluate(ent, scope, val);
} }
void ExpBinary::visit(ExprVisitor& func) void ExpBinary::visit(ExprVisitor& func)
@ -192,7 +251,7 @@ ExpAggregate::choice_t::choice_t()
{ {
} }
ExpAggregate::choice_t::choice_t(prange_t*rang) ExpAggregate::choice_t::choice_t(ExpRange*rang)
: range_(rang) : range_(rang)
{ {
} }
@ -203,7 +262,7 @@ ExpAggregate::choice_t::choice_t(const choice_t&other)
expr_.reset(e->clone()); expr_.reset(e->clone());
if(other.range_.get()) if(other.range_.get())
range_.reset(new prange_t(*other.range_.get())); range_.reset(static_cast<ExpRange*>(other.range_.get()->clone()));
} }
ExpAggregate::choice_t::~choice_t() ExpAggregate::choice_t::~choice_t()
@ -221,7 +280,7 @@ Expression*ExpAggregate::choice_t::simple_expression(bool detach_flag)
return res; return res;
} }
prange_t*ExpAggregate::choice_t::range_expressions(void) ExpRange*ExpAggregate::choice_t::range_expressions(void)
{ {
return range_.get(); return range_.get();
} }
@ -493,7 +552,7 @@ ExpInteger::~ExpInteger()
{ {
} }
bool ExpInteger::evaluate(ScopeBase*, int64_t&val) const bool ExpInteger::evaluate(Entity*, ScopeBase*, int64_t&val) const
{ {
val = value_; val = value_;
return true; return true;
@ -535,6 +594,7 @@ ExpName::ExpName(perm_string nn, list<Expression*>*indices)
ExpName::ExpName(perm_string nn, Expression*msb, Expression*lsb) ExpName::ExpName(perm_string nn, Expression*msb, Expression*lsb)
: name_(nn), index_(msb), lsb_(lsb) : name_(nn), index_(msb), lsb_(lsb)
{ {
ivl_assert(*this, !msb || msb != lsb);
} }
ExpName::ExpName(ExpName*prefix, perm_string nn) ExpName::ExpName(ExpName*prefix, perm_string nn)
@ -545,6 +605,7 @@ ExpName::ExpName(ExpName*prefix, perm_string nn)
ExpName::ExpName(ExpName*prefix, perm_string nn, Expression*msb, Expression*lsb) ExpName::ExpName(ExpName*prefix, perm_string nn, Expression*msb, Expression*lsb)
: prefix_(prefix), name_(nn), index_(msb), lsb_(lsb) : prefix_(prefix), name_(nn), index_(msb), lsb_(lsb)
{ {
ivl_assert(*this, !msb || msb != lsb);
} }
ExpName::~ExpName() ExpName::~ExpName()
@ -712,3 +773,75 @@ double ExpTime::to_fs() const
return val; return val;
} }
ExpRange::ExpRange(Expression*left, Expression*right, range_dir_t direction)
: left_(left), right_(right), direction_(direction), range_expr_(false),
range_base_(NULL)
{
}
ExpRange::ExpRange(ExpName*base, bool reverse_range)
: left_(NULL), right_(NULL), direction_(AUTO), range_expr_(true),
range_base_(base), range_reverse_(reverse_range)
{
}
ExpRange::~ExpRange()
{
delete left_;
delete right_;
delete range_base_;
}
Expression*ExpRange::clone() const
{
if(range_expr_)
return new ExpRange(static_cast<ExpName*>(range_base_->clone()), range_reverse_);
else
return new ExpRange(left_->clone(), right_->clone(), direction_);
}
Expression* ExpRange::msb()
{
ivl_assert(*this, direction() != AUTO);
switch(direction()) {
case DOWNTO: return left_;
case TO: return right_;
default: return NULL;
}
return NULL;
}
Expression* ExpRange::lsb()
{
ivl_assert(*this, direction() != AUTO);
switch(direction()) {
case DOWNTO: return right_;
case TO: return left_;
default: return NULL;
}
return NULL;
}
Expression*ExpRange::left()
{
if(range_expr_ && !left_)
// TODO check if it is an object or type
left_ = new ExpObjAttribute(static_cast<ExpName*>(range_base_->clone()),
ExpAttribute::LEFT, NULL);
return left_;
}
Expression*ExpRange::right()
{
if(range_expr_ && !right_)
// TODO check if it is an object or type
right_ = new ExpObjAttribute(static_cast<ExpName*>(range_base_->clone()),
ExpAttribute::RIGHT, NULL);
return right_;
}

View File

@ -29,8 +29,7 @@
# include <memory> # include <memory>
# include <vector> # include <vector>
class prange_t; class ExpRange;
class Entity;
class ScopeBase; class ScopeBase;
class SubprogramHeader; class SubprogramHeader;
class VType; class VType;
@ -107,8 +106,8 @@ class Expression : public LineInfo {
// to constant literal values. Return true and set the val // to constant literal values. Return true and set the val
// argument if the evaluation works, or return false if it // argument if the evaluation works, or return false if it
// cannot be done. // cannot be done.
virtual bool evaluate(ScopeBase*scope, int64_t&val) const; virtual bool evaluate(Entity*, ScopeBase*, int64_t&) const { return false; }
virtual bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const; bool evaluate(ScopeBase*scope, int64_t&val) const { return evaluate(NULL, scope, val); }
// The symbolic compare returns true if the two expressions // The symbolic compare returns true if the two expressions
// are equal without actually calculating the value. // are equal without actually calculating the value.
@ -125,7 +124,7 @@ class Expression : public LineInfo {
virtual void dump(ostream&out, int indent = 0) const =0; virtual void dump(ostream&out, int indent = 0) const =0;
virtual ostream& dump_inline(ostream&out) const; virtual ostream& dump_inline(ostream&out) const;
// Recursively visits a tree of expressions (useful of complex expressions). // Recursively visits a tree of expressions (useful for complex expressions).
virtual void visit(ExprVisitor& func) { func(this); } virtual void visit(ExprVisitor& func) { func(this); }
protected: protected:
@ -205,8 +204,8 @@ class ExpBinary : public Expression {
int emit_operand1(ostream&out, Entity*ent, ScopeBase*scope); int emit_operand1(ostream&out, Entity*ent, ScopeBase*scope);
int emit_operand2(ostream&out, Entity*ent, ScopeBase*scope); int emit_operand2(ostream&out, Entity*ent, ScopeBase*scope);
bool eval_operand1(ScopeBase*scope, int64_t&val) const; bool eval_operand1(Entity*ent, ScopeBase*scope, int64_t&val) const;
bool eval_operand2(ScopeBase*scope, int64_t&val) const; bool eval_operand2(Entity*ent, ScopeBase*scope, int64_t&val) const;
inline void write_to_stream_operand1(std::ostream&out) const inline void write_to_stream_operand1(std::ostream&out) const
{ operand1_->write_to_stream(out); } { operand1_->write_to_stream(out); }
@ -239,7 +238,7 @@ class ExpAggregate : public Expression {
// Create a named choice // Create a named choice
explicit choice_t(perm_string name); explicit choice_t(perm_string name);
// discreate_range choice // discreate_range choice
explicit choice_t(prange_t*ran); explicit choice_t(ExpRange*ran);
choice_t(const choice_t&other); choice_t(const choice_t&other);
@ -249,15 +248,15 @@ class ExpAggregate : public Expression {
bool others() const; bool others() const;
// Return expression if this represents a simple_expression. // Return expression if this represents a simple_expression.
Expression*simple_expression(bool detach_flag =true); Expression*simple_expression(bool detach_flag =true);
// Return prange_t if this represents a range_expression // Return ExpRange if this represents a range_expression
prange_t*range_expressions(void); ExpRange*range_expressions(void);
void write_to_stream(std::ostream&fd); void write_to_stream(std::ostream&fd);
void dump(ostream&out, int indent) const; void dump(ostream&out, int indent) const;
private: private:
std::auto_ptr<Expression>expr_; std::auto_ptr<Expression>expr_;
std::auto_ptr<prange_t> range_; std::auto_ptr<ExpRange> range_;
private: // not implemented private: // not implemented
choice_t& operator= (const choice_t&); choice_t& operator= (const choice_t&);
}; };
@ -343,7 +342,7 @@ class ExpArithmetic : public ExpBinary {
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd) const; void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope); int emit(ostream&out, Entity*ent, ScopeBase*scope);
virtual bool evaluate(ScopeBase*scope, int64_t&val) const; virtual bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const;
void dump(ostream&out, int indent = 0) const; void dump(ostream&out, int indent = 0) const;
private: private:
@ -356,18 +355,60 @@ class ExpArithmetic : public ExpBinary {
class ExpAttribute : public Expression { class ExpAttribute : public Expression {
public: public:
ExpAttribute(ExpName*base, perm_string name); ExpAttribute(perm_string name,std::list<Expression*>*args);
~ExpAttribute(); virtual ~ExpAttribute();
inline perm_string peek_attribute() const { return name_; }
// Constants for the standard attributes
static const perm_string LEFT;
static const perm_string RIGHT;
protected:
std::list<Expression*>*clone_args() const;
void visit_args(ExprVisitor& func);
bool evaluate_type_attr(const VType*type, Entity*ent, ScopeBase*scope, int64_t&val) const;
bool test_array_type(const VType*type) const;
perm_string name_;
std::list<Expression*>*args_;
};
class ExpObjAttribute : public ExpAttribute {
public:
ExpObjAttribute(ExpName*base, perm_string name, std::list<Expression*>*args);
~ExpObjAttribute();
Expression*clone() const; Expression*clone() const;
inline perm_string peek_attribute() const { return name_; }
inline const ExpName* peek_base() const { return base_; } inline const ExpName* peek_base() const { return base_; }
int emit(ostream&out, Entity*ent, ScopeBase*scope);
const VType*probe_type(Entity*ent, ScopeBase*scope) const; const VType*probe_type(Entity*ent, ScopeBase*scope) const;
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd) const; void write_to_stream(std::ostream&fd) const;
// Some attributes can be evaluated at compile time
bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const;
void dump(ostream&out, int indent = 0) const;
void visit(ExprVisitor& func);
private:
ExpName*base_;
};
class ExpTypeAttribute : public ExpAttribute {
public:
ExpTypeAttribute(const VType*base, perm_string name, std::list<Expression*>*args);
// no destructor - VType objects (base_) are shared between many expressions
Expression*clone() const;
inline const VType* peek_base() const { return base_; }
int emit(ostream&out, Entity*ent, ScopeBase*scope); int emit(ostream&out, Entity*ent, ScopeBase*scope);
const VType*probe_type(Entity*ent, ScopeBase*scope) const;
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd) const;
// Some attributes can be evaluated at compile time // Some attributes can be evaluated at compile time
bool evaluate(ScopeBase*scope, int64_t&val) const; bool evaluate(ScopeBase*scope, int64_t&val) const;
bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const; bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const;
@ -375,8 +416,7 @@ class ExpAttribute : public Expression {
void visit(ExprVisitor& func); void visit(ExprVisitor& func);
private: private:
ExpName*base_; const VType*base_;
perm_string name_;
}; };
class ExpBitstring : public Expression { class ExpBitstring : public Expression {
@ -440,7 +480,6 @@ class ExpConcat : public Expression {
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd) const; void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope); int emit(ostream&out, Entity*ent, ScopeBase*scope);
virtual bool evaluate(ScopeBase*scope, int64_t&val) const;
bool is_primary(void) const; bool is_primary(void) const;
void dump(ostream&out, int indent = 0) const; void dump(ostream&out, int indent = 0) const;
void visit(ExprVisitor& func); void visit(ExprVisitor& func);
@ -583,7 +622,7 @@ class ExpInteger : public Expression {
int emit(ostream&out, Entity*ent, ScopeBase*scope); int emit(ostream&out, Entity*ent, ScopeBase*scope);
int emit_package(std::ostream&out); int emit_package(std::ostream&out);
bool is_primary(void) const { return true; } bool is_primary(void) const { return true; }
bool evaluate(ScopeBase*scope, int64_t&val) const; bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const;
void dump(ostream&out, int indent = 0) const; void dump(ostream&out, int indent = 0) const;
virtual ostream& dump_inline(ostream&out) const; virtual ostream& dump_inline(ostream&out) const;
@ -665,7 +704,6 @@ class ExpName : public Expression {
void write_to_stream(std::ostream&fd) const; void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope); int emit(ostream&out, Entity*ent, ScopeBase*scope);
bool is_primary(void) const; bool is_primary(void) const;
bool evaluate(ScopeBase*scope, int64_t&val) const;
bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const; bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const;
bool symbolic_compare(const Expression*that) const; bool symbolic_compare(const Expression*that) const;
void dump(ostream&out, int indent = 0) const; void dump(ostream&out, int indent = 0) const;
@ -773,7 +811,7 @@ class ExpShift : public ExpBinary {
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd) const; void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope); int emit(ostream&out, Entity*ent, ScopeBase*scope);
virtual bool evaluate(ScopeBase*scope, int64_t&val) const; bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const;
void dump(ostream&out, int indent = 0) const; void dump(ostream&out, int indent = 0) const;
private: private:
@ -891,7 +929,6 @@ class ExpTime : public Expression {
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&) const; void write_to_stream(std::ostream&) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope); int emit(ostream&out, Entity*ent, ScopeBase*scope);
//bool evaluate(ScopeBase*scope, int64_t&val) const;
//bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const; //bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const;
void dump(ostream&out, int indent = 0) const; void dump(ostream&out, int indent = 0) const;
@ -902,6 +939,46 @@ class ExpTime : public Expression {
timeunit_t unit_; timeunit_t unit_;
}; };
class ExpRange : public Expression {
public:
typedef enum { DOWNTO, TO, AUTO } range_dir_t;
// Regular range
ExpRange(Expression*left, Expression*right, range_dir_t direction);
// 'range/'reverse range attribute
ExpRange(ExpName*base, bool reverse_range);
~ExpRange();
Expression*clone() const;
// Returns the upper boundary
Expression*msb();
// Returns the lower boundary
Expression*lsb();
Expression*left();
Expression*right();
range_dir_t direction() const { return direction_; }
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope);
void dump(ostream&out, int indent = 0) const;
private:
// Regular range related fields
Expression*left_, *right_;
range_dir_t direction_;
// 'range/'reverse_range attribute related fields
// Flag to indicate it is a 'range/'reverse_range expression
bool range_expr_;
// Object name to which the attribute is applied
ExpName*range_base_;
// Flag to distinguish between 'range & 'reverse_range
bool range_reverse_;
};
// Elaborates an expression used as an argument in a procedure/function call. // Elaborates an expression used as an argument in a procedure/function call.
int elaborate_argument(Expression*expr, const SubprogramHeader*subp, int elaborate_argument(Expression*expr, const SubprogramHeader*subp,
int idx, Entity*ent, ScopeBase*scope); int idx, Entity*ent, ScopeBase*scope);

View File

@ -117,3 +117,9 @@ void ExpTime::dump(ostream&out, int indent) const
out << setw(indent) << "" << "Time "; out << setw(indent) << "" << "Time ";
write_to_stream(out); write_to_stream(out);
} }
void ExpRange::dump(ostream&out, int indent) const
{
out << setw(indent) << "" << "Range ";
write_to_stream(out);
}

View File

@ -57,7 +57,8 @@ const VType* Expression::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*
return res; return res;
} }
const VType*ExpName::elaborate_adjust_type_with_range_(Entity*, ScopeBase*scope, const VType*type) const VType*ExpName::elaborate_adjust_type_with_range_(Entity*ent, ScopeBase*scope,
const VType*type)
{ {
// Unfold typedefs // Unfold typedefs
while (const VTypeDef*tdef = dynamic_cast<const VTypeDef*>(type)) { while (const VTypeDef*tdef = dynamic_cast<const VTypeDef*>(type)) {
@ -76,9 +77,9 @@ const VType*ExpName::elaborate_adjust_type_with_range_(Entity*, ScopeBase*scope,
int64_t use_msb, use_lsb; int64_t use_msb, use_lsb;
bool flag; bool flag;
flag = index_->evaluate(scope, use_msb); flag = index_->evaluate(ent, scope, use_msb);
ivl_assert(*this, flag); ivl_assert(*this, flag);
flag = lsb_->evaluate(scope, use_lsb); flag = lsb_->evaluate(ent, scope, use_lsb);
ivl_assert(*this, flag); ivl_assert(*this, flag);
type = new VTypeArray(array->element_type(), use_msb, use_lsb); type = new VTypeArray(array->element_type(), use_msb, use_lsb);
@ -216,36 +217,44 @@ int ExpName::elaborate_lval(Entity*ent, ScopeBase*scope, bool is_sequ)
const VType*found_type = 0; const VType*found_type = 0;
if (const InterfacePort*cur = ent->find_port(name_)) { if (ent) {
if (cur->mode != PORT_OUT && cur->mode != PORT_INOUT) { if (const InterfacePort*cur = ent->find_port(name_)) {
cerr << get_fileline() << ": error: Assignment to " if (cur->mode != PORT_OUT && cur->mode != PORT_INOUT) {
"input port " << name_ << "." << endl; cerr << get_fileline() << ": error: Assignment to "
return errors += 1; "input port " << name_ << "." << endl;
} return errors += 1;
}
if (is_sequ) if (is_sequ)
ent->set_declaration_l_value(name_, is_sequ); ent->set_declaration_l_value(name_, is_sequ);
found_type = cur->type; found_type = cur->type;
} else if (ent->find_generic(name_)) { } else if (ent->find_generic(name_)) {
cerr << get_fileline() << ": error: Assignment to generic " cerr << get_fileline() << ": error: Assignment to generic "
<< name_ << " from entity " << name_ << " from entity "
<< ent->get_name() << "." << endl; << ent->get_name() << "." << endl;
return 1; return 1;
}
}
} else if (Signal*sig = scope->find_signal(name_)) { if (!found_type && scope) {
// Tell the target signal that this may be a sequential l-value. if (Signal*sig = scope->find_signal(name_)) {
if (is_sequ) sig->count_ref_sequ(); // Tell the target signal that this may be a sequential l-value.
if (is_sequ) sig->count_ref_sequ();
found_type = sig->peek_type(); found_type = sig->peek_type();
} else if (Variable*var = scope->find_variable(name_)) { } else if (Variable*var = scope->find_variable(name_)) {
// Tell the target signal that this may be a sequential l-value. // Tell the target signal that this may be a sequential l-value.
if (is_sequ) var->count_ref_sequ(); if (is_sequ) var->count_ref_sequ();
found_type = var->peek_type(); found_type = var->peek_type();
} else if (const InterfacePort*port = scope->find_param(name_)) {
found_type = port->type;
}
} }
if (found_type == 0) { if (found_type == 0) {
@ -318,7 +327,8 @@ int ExpName::elaborate_rval(Entity*ent, ScopeBase*scope, const InterfacePort*lva
int Expression::elaborate_expr(Entity*, ScopeBase*, const VType*) int Expression::elaborate_expr(Entity*, ScopeBase*, const VType*)
{ {
cerr << get_fileline() << ": internal error: I don't know how to elaborate expression type=" << typeid(*this).name() << endl; cerr << get_fileline() << ": internal error: I don't know how to "
<< "elaborate expression type=" << typeid(*this).name() << endl;
return 1; return 1;
} }
@ -393,7 +403,7 @@ const VType*ExpAggregate::fit_type(Entity*, ScopeBase*, const VTypeArray*host) c
elements_[0]->map_choices(&ce[0]); elements_[0]->map_choices(&ce[0]);
ivl_assert(*this, ce.size() == 1); ivl_assert(*this, ce.size() == 1);
prange_t*prange = ce[0].choice->range_expressions(); ExpRange*prange = ce[0].choice->range_expressions();
ivl_assert(*this, prange); ivl_assert(*this, prange);
Expression*use_msb = prange->msb(); Expression*use_msb = prange->msb();
@ -573,23 +583,32 @@ const VType* ExpArithmetic::resolve_operand_types_(const VType*t1, const VType*t
return 0; return 0;
} }
const VType* ExpAttribute::probe_type(Entity*ent, ScopeBase*scope) const int ExpObjAttribute::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*)
{ {
base_->probe_type(ent, scope); const VType*sub_type = base_->probe_type(ent, scope);
return base_->elaborate_expr(ent, scope, sub_type);
}
if (name_ == "length" || name_ == "left" || name_ == "right") { const VType* ExpObjAttribute::probe_type(Entity*, ScopeBase*) const
{
if (name_ == "length" || name_ == "left" || name_ == "right")
return &primitive_NATURAL; return &primitive_NATURAL;
}
return NULL;
}
int ExpTypeAttribute::elaborate_expr(Entity*, ScopeBase*, const VType*)
{
// This is just to mute warnings, there is nothing to elaborate here
return 0; return 0;
} }
int ExpAttribute::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*) const VType* ExpTypeAttribute::probe_type(Entity*, ScopeBase*) const
{ {
int errors = 0; if(name_ == "image")
const VType*sub_type = base_->probe_type(ent, scope); return &primitive_STRING;
errors += base_->elaborate_expr(ent, scope, sub_type);
return errors; return NULL;
} }
const VType*ExpBitstring::fit_type(Entity*, ScopeBase*, const VTypeArray*atype) const const VType*ExpBitstring::fit_type(Entity*, ScopeBase*, const VTypeArray*atype) const
@ -648,8 +667,8 @@ const VType*ExpConcat::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*at
new ExpArithmetic(ExpArithmetic::PLUS, sizes[0], sizes[1]), new ExpArithmetic(ExpArithmetic::PLUS, sizes[0], sizes[1]),
new ExpInteger(1)); new ExpInteger(1));
std::list<prange_t*> ranges; std::list<ExpRange*> ranges;
ranges.push_front(new prange_t(size, new ExpInteger(0), true)); ranges.push_front(new ExpRange(size, new ExpInteger(0), ExpRange::DOWNTO));
const VType*array = new VTypeArray(types[1], &ranges); const VType*array = new VTypeArray(types[1], &ranges);
return array; return array;
@ -912,31 +931,31 @@ const VType* ExpName::probe_type(Entity*ent, ScopeBase*scope) const
if(ent) { if(ent) {
if (const InterfacePort*cur = ent->find_port(name_)) { if (const InterfacePort*cur = ent->find_port(name_)) {
ivl_assert(*this, cur->type); ivl_assert(*this, cur->type);
return cur->type; return cur->type;
} }
if (const InterfacePort*cur = ent->find_generic(name_)) { if (const InterfacePort*cur = ent->find_generic(name_)) {
ivl_assert(*this, cur->type); ivl_assert(*this, cur->type);
return cur->type; return cur->type;
} }
} }
if(scope) { if(scope) {
if (Signal*sig = scope->find_signal(name_)) if (Signal*sig = scope->find_signal(name_))
return sig->peek_type(); return sig->peek_type();
if (Variable*var = scope->find_variable(name_)) if (Variable*var = scope->find_variable(name_))
return var->peek_type(); return var->peek_type();
const VType*type = 0; const VType*type = 0;
Expression*cval = 0; Expression*cval = 0;
if (scope->find_constant(name_, type, cval)) if (scope->find_constant(name_, type, cval))
return type; return type;
Architecture*arc = dynamic_cast<Architecture*>(scope); Architecture*arc = dynamic_cast<Architecture*>(scope);
if (arc && (type = arc->probe_genvar_type(name_))) { if (arc && (type = arc->probe_genvar_type(name_))) {
return type; return type;
} }
if (const InterfacePort*port = scope->find_param(name_)) { if (const InterfacePort*port = scope->find_param(name_)) {
@ -1048,6 +1067,19 @@ int ExpTime::elaborate_expr(Entity*, ScopeBase*, const VType*)
return 0; return 0;
} }
int ExpRange::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*)
{
int errors = 0;
if(left_)
errors += left_->elaborate_expr(ent, scope, &primitive_INTEGER);
if(right_)
errors += right_->elaborate_expr(ent, scope, &primitive_INTEGER);
return errors;
}
int elaborate_argument(Expression*expr, const SubprogramHeader*subp, int elaborate_argument(Expression*expr, const SubprogramHeader*subp,
int idx, Entity*ent, ScopeBase*scope) int idx, Entity*ent, ScopeBase*scope)
{ {

View File

@ -224,7 +224,7 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, ScopeBase*scope, const VT
// If this is a range choice, then calculate the bounds // If this is a range choice, then calculate the bounds
// of the range and scan through the values, mapping the // of the range and scan through the values, mapping the
// value to the aggregate_[idx] element. // value to the aggregate_[idx] element.
if (prange_t*range = aggregate_[idx].choice->range_expressions()) { if (ExpRange*range = aggregate_[idx].choice->range_expressions()) {
int64_t begin_val, end_val; int64_t begin_val, end_val;
if (! range->msb()->evaluate(ent, scope, begin_val)) { if (! range->msb()->evaluate(ent, scope, begin_val)) {
@ -331,13 +331,13 @@ int ExpAggregate::emit_record_(ostream&out, Entity*ent, ScopeBase*scope, const V
return errors; return errors;
} }
int ExpAttribute::emit(ostream&out, Entity*ent, ScopeBase*scope) int ExpObjAttribute::emit(ostream&out, Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
// Try to evaluate first // Try to evaluate first
int64_t val; int64_t val;
if(evaluate(scope, val)) { if(evaluate(ent, scope, val)) {
out << val; out << val;
return 0; return 0;
} }
@ -365,12 +365,50 @@ int ExpAttribute::emit(ostream&out, Entity*ent, ScopeBase*scope)
return errors; return errors;
} }
// Fallback
out << "$ivl_attribute("; out << "$ivl_attribute(";
errors += base_->emit(out, ent, scope); errors += base_->emit(out, ent, scope);
out << ", \"" << name_ << "\")"; out << ", \"" << name_ << "\")";
return errors; return errors;
} }
int ExpTypeAttribute::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
// Special case: The image attribute
if (name_=="image") {
if(!args_ || args_->size() != 1) {
out << "/* Invalid 'image attribute */" << endl;
cerr << get_fileline() << ": error: 'image attribute takes "
<< "exactly one argument." << endl;
++errors;
} else {
out << "$sformatf(\"";
if(base_->type_match(&primitive_INTEGER))
out << "%0d";
else if(base_->type_match(&primitive_REAL))
out << "%f";
else if(base_->type_match(&primitive_CHARACTER))
out << "'%c'";
else if(base_->type_match(&primitive_TIME))
out << "%+0t";
out << "\",";
args_->front()->emit(out, ent, scope);
out << ")";
}
return errors;
}
// Fallback
out << "$ivl_attribute(";
errors += base_->emit_def(out, empty_perm_string);
out << ", \"" << name_ << "\")";
return errors;
}
int ExpArithmetic::emit(ostream&out, Entity*ent, ScopeBase*scope) int ExpArithmetic::emit(ostream&out, Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
@ -453,17 +491,16 @@ int ExpCharacter::emit_primitive_bit_(ostream&out, Entity*, ScopeBase*,
int ExpCharacter::emit(ostream&out, Entity*ent, ScopeBase*scope) int ExpCharacter::emit(ostream&out, Entity*ent, ScopeBase*scope)
{ {
const VType*etype = peek_type(); const VType*etype = peek_type();
const VTypeArray*array;
if (etype != &primitive_CHARACTER && (array = dynamic_cast<const VTypeArray*>(etype))) {
etype = array->element_type();
}
if (const VTypePrimitive*use_type = dynamic_cast<const VTypePrimitive*>(etype)) { if (const VTypePrimitive*use_type = dynamic_cast<const VTypePrimitive*>(etype)) {
return emit_primitive_bit_(out, ent, scope, use_type); return emit_primitive_bit_(out, ent, scope, use_type);
} }
if (const VTypeArray*array = dynamic_cast<const VTypeArray*>(etype)) {
if (const VTypePrimitive*use_type = dynamic_cast<const VTypePrimitive*>(array->element_type())) {
return emit_primitive_bit_(out, ent, scope, use_type);
}
}
out << "\"" << value_ << "\""; out << "\"" << value_ << "\"";
return 0; return 0;
} }
@ -583,7 +620,10 @@ int ExpFunc::emit(ostream&out, Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
ivl_assert(*this, def_); if(!def_) {
cerr << get_fileline() << ": error: unknown function: " << name_ << endl;
return 1;
}
// If this function has an elaborated definition, and if // If this function has an elaborated definition, and if
// that definition is in a package, then include the // that definition is in a package, then include the
@ -909,10 +949,11 @@ bool ExpString::is_primary(void) const
int ExpString::emit(ostream& out, Entity*ent, ScopeBase*scope) int ExpString::emit(ostream& out, Entity*ent, ScopeBase*scope)
{ {
const VTypeArray*arr;
const VType*type = peek_type(); const VType*type = peek_type();
assert(type != 0); assert(type != 0);
if (const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type)) { if (type != &primitive_STRING && (arr = dynamic_cast<const VTypeArray*>(type))) {
return emit_as_array_(out, ent, scope, arr); return emit_as_array_(out, ent, scope, arr);
} }
@ -1028,3 +1069,25 @@ int ExpTime::emit(ostream&out, Entity*, ScopeBase*)
return 0; return 0;
} }
int ExpRange::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
if(range_expr_) {
out << "$left(";
errors += range_base_->emit(out, ent, scope);
out << "):$right(";
errors += range_base_->emit(out, ent, scope);
out << ")";
} else if(direction_ == AUTO) {
ivl_assert(*this, false);
out << "/* auto dir */";
} else {
errors += left_->emit(out, ent, scope);
out << ":";
errors += right_->emit(out, ent, scope);
}
return 0;
}

View File

@ -25,26 +25,16 @@
# include <limits> # include <limits>
# include <cmath> # include <cmath>
bool Expression::evaluate(ScopeBase*, int64_t&) const bool ExpArithmetic::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const
{
return false;
}
bool Expression::evaluate(Entity*, ScopeBase*scope, int64_t&val) const
{
return evaluate(scope, val);
}
bool ExpArithmetic::evaluate(ScopeBase*scope, int64_t&val) const
{ {
int64_t val1, val2; int64_t val1, val2;
bool rc; bool rc;
rc = eval_operand1(scope, val1); rc = eval_operand1(ent, scope, val1);
if (rc == false) if (rc == false)
return false; return false;
rc = eval_operand2(scope, val2); rc = eval_operand2(ent, scope, val2);
if (rc == false) if (rc == false)
return false; return false;
@ -83,151 +73,110 @@ bool ExpArithmetic::evaluate(ScopeBase*scope, int64_t&val) const
return true; return true;
} }
bool ExpAttribute::evaluate(ScopeBase*scope, int64_t&val) const bool ExpAttribute::test_array_type(const VType*type) const
{ {
/* Special Case: The array attributes can sometimes be calculated all const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type);
the down to a literal integer at compile time, and all it
needs is the type of the base expression. (The base
expression doesn't even need to be evaluated.) */
if (name_ == "length" || name_ == "right" || name_ == "left") {
const VType*base_type = base_->peek_type();
if(!base_type) { if (arr == 0) {
const ExpName*name = NULL; cerr << endl << get_fileline() << ": error: "
<< "Cannot apply the '" << name_ << " attribute to non-array objects"
<< endl;
ivl_assert(*this, false);
return false;
}
if(scope && (name = dynamic_cast<const ExpName*>(base_))) { if (arr->dimensions() > 1) {
const perm_string& n = name->peek_name(); cerr << endl << get_fileline() << ": error: "
if(const Variable*var = scope->find_variable(n)) << "Cannot apply the '" << name_
base_type = var->peek_type(); << " attribute to multidimensional arrays" << endl;
else if(const Signal*sig = scope->find_signal(n)) return false;
base_type = sig->peek_type(); }
else if(const InterfacePort*port = scope->find_param(n))
base_type = port->type;
}
}
if(!base_type) if (arr->dimension(0).is_box())
return false; // I tried really hard, sorry return false;
const VTypeArray*arr = dynamic_cast<const VTypeArray*>(base_type); return true;
if (arr == 0) { }
cerr << endl << get_fileline() << ": error: "
<< "Cannot apply the '" << name_ << " attribute to non-array objects"
<< endl;
ivl_assert(*this, false);
return false;
}
if(name_ == "length") { bool ExpAttribute::evaluate_type_attr(const VType*type, Entity*ent, ScopeBase*scope, int64_t&val) const
int64_t size = arr->get_width(scope); {
if (name_ == "length" && test_array_type(type)) {
int64_t size = type->get_width(scope);
if(size > 0) if(size > 0) {
val = size; val = size;
else return true;
return false; }
} else if(name_ == "left") { } else if (name_ == "left" && test_array_type(type)) {
arr->dimension(0).msb()->evaluate(scope, val); const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type);
} else if(name_ == "right") { return arr->dimension(0).msb()->evaluate(ent, scope, val);
arr->dimension(0).lsb()->evaluate(scope, val); } else if (name_ == "right" && test_array_type(type)) {
} else ivl_assert(*this, false); const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type);
return arr->dimension(0).lsb()->evaluate(ent, scope, val);
return true;
} }
return false; return false;
} }
bool ExpAttribute::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const bool ExpObjAttribute::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const
{ {
if (!ent || !scope) { // it's impossible to evaluate, probably it is inside a subprogram const VType*base_type = base_->peek_type();
return false;
}
if (name_ == "left" || name_ == "right") { if (base_type == NULL)
const VType*base_type = base_->peek_type(); base_type = base_->probe_type(ent, scope);
if (base_type == 0)
base_type = base_->probe_type(ent, scope);
ivl_assert(*this, base_type); if (base_type)
return evaluate_type_attr(base_type, ent, scope, val);
const VTypeArray*arr = dynamic_cast<const VTypeArray*>(base_type);
if (arr == 0) {
cerr << endl << get_fileline() << ": error: "
<< "Cannot apply the '" << name_
<< " attribute to non-array objects" << endl;
ivl_assert(*this, false);
return false;
}
ivl_assert(*this, arr->dimensions() == 1);
if(name_ == "left")
arr->dimension(0).msb()->evaluate(ent, scope, val);
else // "right"
arr->dimension(0).lsb()->evaluate(ent, scope, val);
return true;
}
return evaluate(scope, val);
}
/*
* I don't yet know how to evaluate concatenations. It is not likely
* to come up anyhow.
*/
bool ExpConcat::evaluate(ScopeBase*, int64_t&) const
{
return false; return false;
} }
bool ExpName::evaluate(ScopeBase*scope, int64_t&val) const bool ExpTypeAttribute::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const
{ {
const VType*type; return evaluate_type_attr(base_, ent, scope, val);
Expression*exp;
if (prefix_.get()) {
cerr << get_fileline() << ": sorry: I don't know how to evaluate ExpName prefix parts." << endl;
return false;
}
if (!scope)
return false;
if (!scope->find_constant(name_, type, exp))
return false;
return exp->evaluate(scope, val);
} }
bool ExpName::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const bool ExpName::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const
{ {
if (prefix_.get()) { if (prefix_.get()) {
cerr << get_fileline() << ": sorry: I don't know how to evaluate ExpName prefix parts." << endl; cerr << get_fileline() << ": sorry: I don't know how to evaluate "
return false; << "ExpName prefix parts." << endl;
return false;
} }
const InterfacePort*gen = ent->find_generic(name_); if (ent) {
if (gen) { const InterfacePort*gen = ent->find_generic(name_);
cerr << get_fileline() << ": sorry: I don't necessarily handle generic overrides." << endl; if (gen) {
cerr << get_fileline() << ": sorry: I don't necessarily "
<< "handle generic overrides." << endl;
// Evaluate the default expression and use that. // Evaluate the default expression and use that.
if (gen->expr) if (gen->expr)
return gen->expr->evaluate(ent, scope, val); return gen->expr->evaluate(ent, scope, val);
}
} }
return evaluate(scope, val); if (scope) {
const VType*type;
Expression*exp;
if (scope->find_constant(name_, type, exp))
return exp->evaluate(ent, scope, val);
}
return false;
} }
bool ExpShift::evaluate(ScopeBase*scope, int64_t&val) const bool ExpShift::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const
{ {
int64_t val1, val2; int64_t val1, val2;
bool rc; bool rc;
rc = eval_operand1(scope, val1); rc = eval_operand1(ent, scope, val1);
if (rc == false) if (rc == false)
return false; return false;
rc = eval_operand2(scope, val2); rc = eval_operand2(ent, scope, val2);
if (rc == false) if (rc == false)
return false; return false;
@ -252,7 +201,7 @@ bool ExpShift::evaluate(ScopeBase*scope, int64_t&val) const
return true; return true;
} }
/*bool ExpTime::evaluate(ScopeBase*, int64_t&val) const /*bool ExpTime::evaluate(Entity*, ScopeBase*, int64_t&val) const
{ {
double v = to_fs(); double v = to_fs();
@ -265,8 +214,4 @@ bool ExpShift::evaluate(ScopeBase*scope, int64_t&val) const
val = v; val = v;
return true; return true;
} }
bool ExpTime::evaluate(Entity*, ScopeBase*, int64_t&val) const
{
return evaluate(NULL, val);
}*/ }*/

View File

@ -61,13 +61,9 @@ void ExpAggregate::choice_t::write_to_stream(ostream&fd)
return; return;
} }
if (prange_t*rp = range_expressions()) { if (ExpRange*rp = range_expressions()) {
rp->msb()->write_to_stream(fd); rp->write_to_stream(fd);
if (rp->is_downto()) return;
fd << " downto ";
else
fd << " to ";
rp->msb()->write_to_stream(fd);
} }
fd << "/* ERROR */"; fd << "/* ERROR */";
@ -111,7 +107,13 @@ void ExpArithmetic::write_to_stream(ostream&out) const
out << ")"; out << ")";
} }
void ExpAttribute::write_to_stream(ostream&fd) const void ExpObjAttribute::write_to_stream(ostream&fd) const
{
base_->write_to_stream(fd);
fd << "'" << name_;
}
void ExpTypeAttribute::write_to_stream(ostream&fd) const
{ {
base_->write_to_stream(fd); base_->write_to_stream(fd);
fd << "'" << name_; fd << "'" << name_;
@ -316,3 +318,19 @@ void ExpTime::write_to_stream(ostream&fd) const
case S: fd << " s"; break; case S: fd << " s"; break;
} }
} }
void ExpRange::write_to_stream(ostream&fd) const
{
if(range_expr_) {
range_base_->write_to_stream(fd);
fd << (range_reverse_ ? "'reverse_range" : "'range");
} else {
left_->write_to_stream(fd);
switch(direction_) {
case DOWNTO: fd << " downto "; break;
case TO: fd << " to "; break;
default: ivl_assert(*this, false); break;
}
right_->write_to_stream(fd);
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -87,10 +87,6 @@ static ActiveScope*active_scope = new ActiveScope;
static stack<ActiveScope*> scope_stack; static stack<ActiveScope*> scope_stack;
static SubprogramHeader*active_sub = NULL; static SubprogramHeader*active_sub = NULL;
// perm_strings for attributes
const static perm_string left_attr = perm_string::literal("left");
const static perm_string right_attr = perm_string::literal("right");
/* /*
* When a scope boundary starts, call the push_scope function to push * When a scope boundary starts, call the push_scope function to push
* a scope context. Preload this scope context with the contents of * a scope context. Preload this scope context with the contents of
@ -245,8 +241,9 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
const VType* vtype; const VType* vtype;
prange_t* range; ExpRange*range;
std::list<prange_t*>*range_list; std::list<ExpRange*>*range_list;
ExpRange::range_dir_t range_dir;
ExpArithmetic::fun_t arithmetic_op; ExpArithmetic::fun_t arithmetic_op;
std::list<struct adding_term>*adding_terms; std::list<struct adding_term>*adding_terms;
@ -305,8 +302,6 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
/* The rules may have types. */ /* The rules may have types. */
%type <flag> direction
%type <arithmetic_op> adding_operator %type <arithmetic_op> adding_operator
%type <adding_terms> simple_expression_terms %type <adding_terms> simple_expression_terms
@ -341,7 +336,7 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
%type <expr> variable_declaration_assign_opt waveform_element interface_element_expression %type <expr> variable_declaration_assign_opt waveform_element interface_element_expression
%type <expr_list> waveform waveform_elements %type <expr_list> waveform waveform_elements
%type <expr_list> name_list expression_list %type <expr_list> name_list expression_list argument_list argument_list_opt
%type <expr_list> process_sensitivity_list process_sensitivity_list_opt %type <expr_list> process_sensitivity_list process_sensitivity_list_opt
%type <expr_list> selected_names use_clause %type <expr_list> selected_names use_clause
@ -372,6 +367,7 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
%type <range> range %type <range> range
%type <range_list> range_list index_constraint %type <range_list> range_list index_constraint
%type <range_dir> direction
%type <case_alt> case_statement_alternative %type <case_alt> case_statement_alternative
%type <case_alt_list> case_statement_alternative_list %type <case_alt_list> case_statement_alternative_list
@ -448,11 +444,18 @@ architecture_statement_part
} }
; ;
argument_list : '(' expression_list ')' { $$ = $2; };
argument_list_opt
: argument_list { $$ = $1; }
| { $$ = 0; }
;
assertion_statement assertion_statement
: K_assert expression report_statement : K_assert expression report_statement
{ ReportStmt*report = dynamic_cast<ReportStmt*>($3); { ReportStmt*report = dynamic_cast<ReportStmt*>($3);
assert(report); assert(report);
AssertStmt*tmp = new AssertStmt($2, report->message().c_str(), report->severity()); AssertStmt*tmp = new AssertStmt($2, report->message(), report->severity());
delete report; delete report;
FILE_NAME(tmp,@2); FILE_NAME(tmp,@2);
$$ = tmp; $$ = tmp;
@ -752,8 +755,9 @@ composite_type_definition
/* unbounded_array_definition IEEE 1076-2008 P5.3.2.1 */ /* unbounded_array_definition IEEE 1076-2008 P5.3.2.1 */
| K_array '(' index_subtype_definition_list ')' K_of subtype_indication | K_array '(' index_subtype_definition_list ')' K_of subtype_indication
{ std::list<prange_t*> r; { std::list<ExpRange*> r;
r.push_back(new prange_t(NULL, NULL, true)); // NULL boundaries indicate unbounded array type // NULL boundaries indicate unbounded array type
r.push_back(new ExpRange(NULL, NULL, ExpRange::DOWNTO));
VTypeArray*tmp = new VTypeArray($6, &r); VTypeArray*tmp = new VTypeArray($6, &r);
$$ = tmp; $$ = tmp;
} }
@ -983,8 +987,10 @@ design_units
| design_unit | design_unit
; ;
/* Indicate the direction as a flag, with "downto" being TRUE. */ direction
direction : K_to { $$ = false; } | K_downto { $$ = true; } ; : K_to { $$ = ExpRange::TO; }
| K_downto { $$ = ExpRange::DOWNTO; }
;
element_association element_association
: choices ARROW expression : choices ARROW expression
@ -1258,8 +1264,8 @@ file_declaration
// add file_open() call in 'initial' block // add file_open() call in 'initial' block
params.push_back(new ExpName(*cur)); params.push_back(new ExpName(*cur));
params.push_back($5->filename()); params.push_back($5->filename()->clone());
params.push_back($5->kind()); params.push_back($5->kind()->clone());
ProcedureCall*fopen_call = new ProcedureCall(perm_string::literal("file_open"), &params); ProcedureCall*fopen_call = new ProcedureCall(perm_string::literal("file_open"), &params);
active_scope->add_initializer(fopen_call); active_scope->add_initializer(fopen_call);
@ -1268,6 +1274,8 @@ file_declaration
params.push_back(new ExpName(*cur)); params.push_back(new ExpName(*cur));
ProcedureCall*fclose_call = new ProcedureCall(perm_string::literal("file_close"), &params); ProcedureCall*fclose_call = new ProcedureCall(perm_string::literal("file_close"), &params);
active_scope->add_finalizer(fclose_call); active_scope->add_finalizer(fclose_call);
delete $5;
} }
} }
@ -1498,7 +1506,7 @@ index_constraint
| '(' error ')' | '(' error ')'
{ errormsg(@2, "Errors in the index constraint.\n"); { errormsg(@2, "Errors in the index constraint.\n");
yyerrok; yyerrok;
$$ = new list<prange_t*>; $$ = new list<ExpRange*>;
} }
; ;
@ -1679,14 +1687,14 @@ name /* IEEE 1076-2008 P8.1 */
function calls. The only way we can tell the difference is from function calls. The only way we can tell the difference is from
left context, namely whether the name is a type name or function left context, namely whether the name is a type name or function
name. If none of the above, treat it as a array element select. */ name. If none of the above, treat it as a array element select. */
| IDENTIFIER '(' expression_list ')' | IDENTIFIER argument_list
{ perm_string name = lex_strings.make($1); { perm_string name = lex_strings.make($1);
delete[]$1; delete[]$1;
if (active_scope->is_vector_name(name) || is_subprogram_param(name)) { if (active_scope->is_vector_name(name) || is_subprogram_param(name)) {
ExpName*tmp = new ExpName(name, $3); ExpName*tmp = new ExpName(name, $2);
$$ = tmp; $$ = tmp;
} else { } else {
ExpFunc*tmp = new ExpFunc(name, $3); ExpFunc*tmp = new ExpFunc(name, $2);
$$ = tmp; $$ = tmp;
} }
FILE_NAME($$, @1); FILE_NAME($$, @1);
@ -1876,10 +1884,18 @@ prefix /* IEEE 1076-2008 P8.1 */
primary primary
: name : name
{ $$ = $1; } { $$ = $1; }
| name '\'' IDENTIFIER | name '\'' IDENTIFIER argument_list_opt
{ perm_string name = lex_strings.make($3); { ExpAttribute*tmp = NULL;
ExpName*base = dynamic_cast<ExpName*> ($1); perm_string attr = lex_strings.make($3);
ExpAttribute*tmp = new ExpAttribute(base, name); ExpName*base = dynamic_cast<ExpName*>($1);
const VType*type = parse_type_by_name(base->peek_name());
if(type) {
tmp = new ExpTypeAttribute(type, attr, $4);
} else {
tmp = new ExpObjAttribute(base, attr, $4);
}
FILE_NAME(tmp, @3); FILE_NAME(tmp, @3);
delete[]$3; delete[]$3;
$$ = tmp; $$ = tmp;
@ -1980,11 +1996,11 @@ procedure_call
delete[] $1; delete[] $1;
$$ = tmp; $$ = tmp;
} }
| IDENTIFIER '(' expression_list ')' ';' | IDENTIFIER argument_list ';'
{ {
ProcedureCall* tmp = new ProcedureCall(lex_strings.make($1), $3); ProcedureCall* tmp = new ProcedureCall(lex_strings.make($1), $2);
delete[] $1; delete[] $1;
delete $3; // parameters are copied in this variant delete $2; // parameters are copied in this variant
$$ = tmp; $$ = tmp;
} }
| IDENTIFIER '(' error ')' ';' | IDENTIFIER '(' error ')' ';'
@ -2096,18 +2112,15 @@ process_sensitivity_list
range range
: simple_expression direction simple_expression : simple_expression direction simple_expression
{ prange_t* tmp = new prange_t($1, $3, $2); { ExpRange* tmp = new ExpRange($1, $3, $2);
$$ = tmp; $$ = tmp;
} }
| name '\'' K_range | name '\'' K_range
{ {
prange_t*tmp = NULL; ExpRange*tmp = NULL;
ExpName*name = NULL; ExpName*name = NULL;
if((name = dynamic_cast<ExpName*>($1))) { if((name = dynamic_cast<ExpName*>($1))) {
ExpAttribute*left = new ExpAttribute(name, left_attr); tmp = new ExpRange(name, false);
ExpAttribute*right = new ExpAttribute(name, right_attr);
tmp = new prange_t(left, right, true);
tmp->set_auto_dir();
} else { } else {
errormsg(@1, "'range attribute can be used with named expressions only"); errormsg(@1, "'range attribute can be used with named expressions only");
} }
@ -2115,13 +2128,10 @@ range
} }
| name '\'' K_reverse_range | name '\'' K_reverse_range
{ {
prange_t*tmp = NULL; ExpRange*tmp = NULL;
ExpName*name = NULL; ExpName*name = NULL;
if((name = dynamic_cast<ExpName*>($1))) { if((name = dynamic_cast<ExpName*>($1))) {
ExpAttribute*left = new ExpAttribute(name, left_attr); tmp = new ExpRange(name, true);
ExpAttribute*right = new ExpAttribute(name, right_attr);
tmp = new prange_t(left, right, false);
tmp->set_auto_dir();
} else { } else {
errormsg(@1, "'reverse_range attribute can be used with named expressions only"); errormsg(@1, "'reverse_range attribute can be used with named expressions only");
} }
@ -2131,12 +2141,12 @@ range
range_list range_list
: range : range
{ list<prange_t*>*tmp = new list<prange_t*>; { list<ExpRange*>*tmp = new list<ExpRange*>;
tmp->push_back($1); tmp->push_back($1);
$$ = tmp; $$ = tmp;
} }
| range_list ',' range | range_list ',' range
{ list<prange_t*>*tmp = $1; { list<ExpRange*>*tmp = $1;
tmp->push_back($3); tmp->push_back($3);
$$ = tmp; $$ = tmp;
} }
@ -2185,10 +2195,9 @@ relation
; ;
report_statement report_statement
: K_report STRING_LITERAL severity_opt ';' : K_report expression severity_opt ';'
{ ReportStmt*tmp = new ReportStmt($2, $3); { ReportStmt*tmp = new ReportStmt($2, $3);
FILE_NAME(tmp,@2); FILE_NAME(tmp,@2);
delete[]$2;
$$ = tmp; $$ = tmp;
} }

View File

@ -113,14 +113,14 @@ static const VType* calculate_subtype_array(const YYLTYPE&loc, const char*base_n
} }
const VType* calculate_subtype_array(const YYLTYPE&loc, const char*base_name, const VType* calculate_subtype_array(const YYLTYPE&loc, const char*base_name,
ScopeBase*scope, list<prange_t*>*ranges) ScopeBase*scope, list<ExpRange*>*ranges)
{ {
if (ranges->size() == 1) { if (ranges->size() == 1) {
prange_t*tmpr = ranges->front(); ExpRange*tmpr = ranges->front();
Expression*lef = tmpr->expr_left(); Expression*lef = tmpr->left();
Expression*rig = tmpr->expr_right(); Expression*rig = tmpr->right();
return calculate_subtype_array(loc, base_name, scope, return calculate_subtype_array(loc, base_name, scope,
lef, tmpr->is_downto(), rig); lef, tmpr->direction(), rig);
} }
sorrymsg(loc, "Don't know how to handle multiple ranges here.\n"); sorrymsg(loc, "Don't know how to handle multiple ranges here.\n");
@ -130,7 +130,7 @@ const VType* calculate_subtype_array(const YYLTYPE&loc, const char*base_name,
const VType* calculate_subtype_range(const YYLTYPE&loc, const char*base_name, const VType* calculate_subtype_range(const YYLTYPE&loc, const char*base_name,
ScopeBase*scope, ScopeBase*scope,
Expression*range_left, Expression*range_left,
bool downto, int direction,
Expression*range_right) Expression*range_right)
{ {
const VType*base_type = parse_type_by_name(lex_strings.make(base_name)); const VType*base_type = parse_type_by_name(lex_strings.make(base_name));
@ -148,7 +148,7 @@ const VType* calculate_subtype_range(const YYLTYPE&loc, const char*base_name,
if(range_left->evaluate(scope, left_val) && range_right->evaluate(scope, right_val)) { if(range_left->evaluate(scope, left_val) && range_right->evaluate(scope, right_val)) {
subtype = new VTypeRangeConst(base_type, left_val, right_val); subtype = new VTypeRangeConst(base_type, left_val, right_val);
} else { } else {
subtype = new VTypeRangeExpr(base_type, range_left, range_right, downto); subtype = new VTypeRangeExpr(base_type, range_left, range_right, direction);
} }
return subtype; return subtype;

View File

@ -26,7 +26,7 @@ class ActiveScope;
class Architecture; class Architecture;
class Expression; class Expression;
class Package; class Package;
class prange_t; class ExpRange;
class ScopeBase; class ScopeBase;
class VType; class VType;
@ -35,11 +35,11 @@ extern void bind_architecture_to_entity(const char*ename, Architecture*arch);
extern const VType* calculate_subtype_array(const YYLTYPE&loc, const char*base_name, extern const VType* calculate_subtype_array(const YYLTYPE&loc, const char*base_name,
ScopeBase*scope, ScopeBase*scope,
std::list<prange_t*>*ranges); std::list<ExpRange*>*ranges);
extern const VType* calculate_subtype_range(const YYLTYPE&loc, const char*base_name, extern const VType* calculate_subtype_range(const YYLTYPE&loc, const char*base_name,
ScopeBase*scope, ScopeBase*scope,
Expression*range_left, Expression*range_left,
bool downto, int direction,
Expression*range_right); Expression*range_right);
/* /*

View File

@ -26,7 +26,8 @@
class named_expr_t { class named_expr_t {
public: public:
named_expr_t (perm_string n, Expression*e) : name_(n), expr_(e) { } named_expr_t(perm_string n, Expression*e) : name_(n), expr_(e) { }
~named_expr_t() { delete expr_; }
perm_string name() const { return name_; } perm_string name() const { return name_; }
Expression* expr() const { return expr_; } Expression* expr() const { return expr_; }
@ -68,35 +69,6 @@ class instant_list_t {
std::list<perm_string>* labels_; std::list<perm_string>* labels_;
}; };
class prange_t {
public:
prange_t(Expression* left, Expression* right, bool dir)
: left_(left), right_(right), direction_(dir), auto_dir_(false) {}
prange_t(const prange_t&other) :
left_(other.left_->clone()), right_(other.right_->clone()),
direction_(other.direction_), auto_dir_(other.auto_dir_) {}
~prange_t() { delete left_; delete right_; }
void dump(ostream&out, int indent) const;
inline Expression*msb() { return direction_? left_ : right_; }
inline Expression*lsb() { return direction_? right_: left_; }
inline bool is_downto() const { return direction_; }
inline void set_auto_dir(bool enabled = true) { auto_dir_ = enabled; };
inline bool is_auto_dir() const { return auto_dir_; }
inline Expression*expr_left() { return left_; }
inline Expression*expr_right() { return right_; }
private:
Expression *left_, *right_;
bool direction_;
bool auto_dir_;
private: //not implemented
prange_t operator=(const prange_t&);
};
struct adding_term { struct adding_term {
ExpArithmetic::fun_t op; ExpArithmetic::fun_t op;
Expression*term; Expression*term;

View File

@ -90,6 +90,7 @@ void ScopeBase::cleanup()
* objects from the other scopes untouched. * objects from the other scopes untouched.
*/ */
delete_all(new_signals_); delete_all(new_signals_);
delete_all(new_variables_);
delete_all(new_components_); delete_all(new_components_);
delete_all(cur_types_); delete_all(cur_types_);
delete_all(cur_constants_); delete_all(cur_constants_);

View File

@ -90,6 +90,8 @@ class ScopeBase {
finalizers_.push_back(s); finalizers_.push_back(s);
} }
void dump_scope(ostream&out) const;
protected: protected:
void cleanup(); void cleanup();
@ -154,9 +156,6 @@ class Scope : public ScopeBase {
ComponentBase* find_component(perm_string by_name); ComponentBase* find_component(perm_string by_name);
public:
void dump_scope(ostream&out) const;
protected: protected:
// Helper method for emitting signals in the scope. // Helper method for emitting signals in the scope.
int emit_signals(ostream&out, Entity*ent, Architecture*arc); int emit_signals(ostream&out, Entity*ent, Architecture*arc);

View File

@ -185,7 +185,7 @@ ProcedureCall::ProcedureCall(perm_string name, std::list<Expression*>* param_lis
for(std::list<Expression*>::const_iterator it = param_list->begin(); for(std::list<Expression*>::const_iterator it = param_list->begin();
it != param_list->end(); ++it) it != param_list->end(); ++it)
{ {
param_list_->push_back(new named_expr_t(empty_perm_string, (*it)->clone())); param_list_->push_back(new named_expr_t(empty_perm_string, *it));
} }
} }
@ -199,6 +199,8 @@ ProcedureCall::~ProcedureCall()
param_list_->pop_front(); param_list_->pop_front();
delete cur; delete cur;
} }
delete param_list_;
} }
ReturnStmt::ReturnStmt(Expression*val) ReturnStmt::ReturnStmt(Expression*val)
@ -238,7 +240,7 @@ void LoopStatement::visit(SeqStmtVisitor& func)
func(this); func(this);
} }
ForLoopStatement::ForLoopStatement(perm_string scope_name, perm_string it, prange_t* range, list<SequentialStmt*>* stmts) ForLoopStatement::ForLoopStatement(perm_string scope_name, perm_string it, ExpRange* range, list<SequentialStmt*>* stmts)
: LoopStatement(scope_name, stmts), it_(it), range_(range) : LoopStatement(scope_name, stmts), it_(it), range_(range)
{ {
} }
@ -278,26 +280,24 @@ BasicLoopStatement::~BasicLoopStatement()
{ {
} }
ReportStmt::ReportStmt(const char*msg, severity_t sev) ReportStmt::ReportStmt(Expression*msg, severity_t sev)
: msg_(msg), severity_(sev) : msg_(msg), severity_(sev)
{ {
if(sev == ReportStmt::UNSPECIFIED) if(sev == ReportStmt::UNSPECIFIED)
severity_ = ReportStmt::NOTE; severity_ = ReportStmt::NOTE;
} }
AssertStmt::AssertStmt(Expression*condition, const char*msg, ReportStmt::severity_t sev) AssertStmt::AssertStmt(Expression*condition, Expression*msg, ReportStmt::severity_t sev)
: ReportStmt("", sev), cond_(condition) : ReportStmt(msg, sev), cond_(condition)
{ {
if(msg == NULL) if(msg == NULL)
msg_ = default_msg_; msg_ = new ExpString(default_msg_);
else
msg_ = std::string(msg);
if(sev == ReportStmt::UNSPECIFIED) if(sev == ReportStmt::UNSPECIFIED)
severity_ = ReportStmt::ERROR; severity_ = ReportStmt::ERROR;
} }
const std::string AssertStmt::default_msg_ = std::string("Assertion violation."); const char*AssertStmt::default_msg_ = "Assertion violation.";
WaitForStmt::WaitForStmt(Expression*delay) WaitForStmt::WaitForStmt(Expression*delay)
: delay_(delay) : delay_(delay)

View File

@ -250,7 +250,7 @@ class WhileLoopStatement : public LoopStatement {
class ForLoopStatement : public LoopStatement { class ForLoopStatement : public LoopStatement {
public: public:
ForLoopStatement(perm_string loop_name, ForLoopStatement(perm_string loop_name,
perm_string index, prange_t*, list<SequentialStmt*>*); perm_string index, ExpRange*, list<SequentialStmt*>*);
~ForLoopStatement(); ~ForLoopStatement();
int elaborate(Entity*ent, ScopeBase*scope); int elaborate(Entity*ent, ScopeBase*scope);
@ -264,7 +264,7 @@ class ForLoopStatement : public LoopStatement {
int emit_runtime_(ostream&out, Entity*ent, ScopeBase*scope); int emit_runtime_(ostream&out, Entity*ent, ScopeBase*scope);
perm_string it_; perm_string it_;
prange_t* range_; ExpRange* range_;
}; };
class BasicLoopStatement : public LoopStatement { class BasicLoopStatement : public LoopStatement {
@ -280,24 +280,27 @@ class ReportStmt : public SequentialStmt {
public: public:
typedef enum { UNSPECIFIED, NOTE, WARNING, ERROR, FAILURE } severity_t; typedef enum { UNSPECIFIED, NOTE, WARNING, ERROR, FAILURE } severity_t;
ReportStmt(const char*message, severity_t severity = NOTE); ReportStmt(Expression*message, severity_t severity);
virtual ~ReportStmt() {} virtual ~ReportStmt() {}
void dump(ostream&out, int indent) const; void dump(ostream&out, int indent) const;
int elaborate(Entity*ent, ScopeBase*scope);
int emit(ostream&out, Entity*entity, ScopeBase*scope); int emit(ostream&out, Entity*entity, ScopeBase*scope);
void write_to_stream(std::ostream&fd); void write_to_stream(std::ostream&fd);
inline const std::string& message() const { return msg_; } inline Expression*message() const { return msg_; }
inline severity_t severity() const { return severity_; } inline severity_t severity() const { return severity_; }
protected: protected:
std::string msg_; void dump_sev_msg(ostream&out, int indent) const;
Expression*msg_;
severity_t severity_; severity_t severity_;
}; };
class AssertStmt : public ReportStmt { class AssertStmt : public ReportStmt {
public: public:
AssertStmt(Expression*condition, const char*message, AssertStmt(Expression*condition, Expression*message,
ReportStmt::severity_t severity = ReportStmt::ERROR); ReportStmt::severity_t severity = ReportStmt::ERROR);
void dump(ostream&out, int indent) const; void dump(ostream&out, int indent) const;
@ -309,7 +312,7 @@ class AssertStmt : public ReportStmt {
Expression*cond_; Expression*cond_;
// Message displayed when there is no report assigned. // Message displayed when there is no report assigned.
static const std::string default_msg_; static const char*default_msg_;
}; };
class WaitForStmt : public SequentialStmt { class WaitForStmt : public SequentialStmt {

View File

@ -169,16 +169,24 @@ void BasicLoopStatement::dump(ostream&out, int indent) const
void ReportStmt::dump(ostream&out, int indent) const void ReportStmt::dump(ostream&out, int indent) const
{ {
out << setw(indent) << "" << "ReportStmt at file=" << get_fileline() << endl; out << setw(indent) << "" << "ReportStmt at file=" << get_fileline() << endl;
out << setw(indent+3) << "" << "severity: " << severity_ << endl; dump_sev_msg(out, indent+3);
out << setw(indent+3) << "" << "message: " << msg_ << endl; }
void ReportStmt::dump_sev_msg(ostream&out, int indent) const
{
out << setw(indent) << "" << "severity: " << severity_ << endl;
if(msg_) {
out << setw(indent) << "" << "message: ";
msg_->dump(out, indent);
}
} }
void AssertStmt::dump(ostream&out, int indent) const void AssertStmt::dump(ostream&out, int indent) const
{ {
out << setw(indent) << "" << "AssertStmt at file=" << get_fileline() << endl; out << setw(indent) << "" << "AssertStmt at file=" << get_fileline() << endl;
out << setw(indent+3) << "" << "condition: "; out << setw(indent+3) << "" << "condition: ";
cond_->dump(out, indent+3); dump_sev_msg(out, indent+3);
ReportStmt::dump(out, indent+3);
} }
void WaitForStmt::dump(ostream&out, int indent) const void WaitForStmt::dump(ostream&out, int indent) const

View File

@ -217,9 +217,17 @@ int BasicLoopStatement::elaborate(Entity*, ScopeBase*)
return 0; return 0;
} }
int ReportStmt::elaborate(Entity*ent, ScopeBase*scope)
{
return msg_->elaborate_expr(ent, scope, &primitive_STRING);
}
int AssertStmt::elaborate(Entity*ent, ScopeBase*scope) int AssertStmt::elaborate(Entity*ent, ScopeBase*scope)
{ {
return cond_->elaborate_expr(ent, scope, cond_->probe_type(ent, scope)); int errors = 0;
errors += ReportStmt::elaborate(ent, scope);
errors += cond_->elaborate_expr(ent, scope, cond_->probe_type(ent, scope));
return errors;
} }
int WaitForStmt::elaborate(Entity*ent, ScopeBase*scope) int WaitForStmt::elaborate(Entity*ent, ScopeBase*scope)

View File

@ -383,10 +383,10 @@ int ForLoopStatement::emit(ostream&out, Entity*ent, ScopeBase*scope)
ivl_assert(*this, range_); ivl_assert(*this, range_);
int64_t start_val; int64_t start_val;
bool start_rc = range_->msb()->evaluate(ent, scope, start_val); bool start_rc = range_->left()->evaluate(ent, scope, start_val);
int64_t finish_val; int64_t finish_val;
bool finish_rc = range_->lsb()->evaluate(ent, scope, finish_val); bool finish_rc = range_->right()->evaluate(ent, scope, finish_val);
perm_string scope_name = loop_name(); perm_string scope_name = loop_name();
if (scope_name.nil()) { if (scope_name.nil()) {
@ -403,48 +403,31 @@ int ForLoopStatement::emit(ostream&out, Entity*ent, ScopeBase*scope)
// determined during the run-time // determined during the run-time
errors += emit_runtime_(out, ent, scope); errors += emit_runtime_(out, ent, scope);
} else { } else {
bool dir = range_->is_downto(); ExpRange::range_dir_t dir = range_->direction();
if (!dir) { if(dir == ExpRange::AUTO)
int64_t tmp = start_val; dir = start_val < finish_val ? ExpRange::TO : ExpRange::DOWNTO;
start_val = finish_val;
finish_val = tmp;
}
if (dir && (start_val < finish_val)) { if ((dir == ExpRange::DOWNTO && start_val < finish_val) ||
if(range_->is_auto_dir()) { (dir == ExpRange::TO && start_val > finish_val)) {
dir = false; out << "begin /* Degenerate loop at " << get_fileline()
} else { << ": " << start_val;
out << "begin /* Degenerate loop at " << get_fileline() out << (dir == ExpRange::DOWNTO ? " downto " : " to ");
<< ": " << start_val out << finish_val << " */ end" << endl
<< " downto " << finish_val << " */ end" << endl << "end" << endl;
<< "end" << endl; return errors;
return errors;
}
}
else if (!dir && start_val > finish_val) {
if(range_->is_auto_dir()) {
dir = true;
} else {
out << "begin /* Degenerate loop at " << get_fileline()
<< ": " << start_val
<< " to " << finish_val << " */ end" << endl
<< "end" << endl;
return errors;
}
} }
out << "for (\\" << it_ << " = " << start_val << " ; "; out << "for (\\" << it_ << " = " << start_val << " ; ";
if (dir) if (dir == ExpRange::DOWNTO)
out << "\\" << it_ << " >= " << finish_val; out << "\\" << it_ << " >= " << finish_val;
else else
out << "\\" << it_ << " <= " << finish_val; out << "\\" << it_ << " <= " << finish_val;
out << "; \\" << it_ << " = \\" << it_; out << "; \\" << it_ << " = \\" << it_;
if (dir) if (dir == ExpRange::DOWNTO)
out << " - 1)"; out << " - 1)";
else else
out << " + 1)"; out << " + 1)";
@ -463,9 +446,7 @@ int ForLoopStatement::emit(ostream&out, Entity*ent, ScopeBase*scope)
void ForLoopStatement::write_to_stream(ostream&fd) void ForLoopStatement::write_to_stream(ostream&fd)
{ {
fd << "for " << it_ << " in "; fd << "for " << it_ << " in ";
range_->expr_left()->write_to_stream(fd); range_->write_to_stream(fd);
fd << " to ";
range_->expr_right()->write_to_stream(fd);
fd << " loop" << endl; fd << " loop" << endl;
write_to_stream_substatements(fd); write_to_stream_substatements(fd);
fd << "end loop;" << endl; fd << "end loop;" << endl;
@ -476,41 +457,43 @@ int ForLoopStatement::emit_runtime_(ostream&out, Entity*ent, ScopeBase*scope)
int errors = 0; int errors = 0;
out << "for (\\" << it_ << " = "; out << "for (\\" << it_ << " = ";
errors += range_->expr_left()->emit(out, ent, scope); errors += range_->left()->emit(out, ent, scope);
// Twisted way of determining the loop direction at runtime // Twisted way of determining the loop direction at runtime
out << " ;\n("; out << " ;\n(";
errors += range_->expr_left()->emit(out, ent, scope); errors += range_->left()->emit(out, ent, scope);
out << " < "; out << " < ";
errors += range_->expr_right()->emit(out, ent, scope); errors += range_->right()->emit(out, ent, scope);
out << " ? \\" << it_ << " <= "; out << " ? \\" << it_ << " <= ";
errors += range_->expr_right()->emit(out, ent, scope); errors += range_->right()->emit(out, ent, scope);
out << " : \\" << it_ << " >= "; out << " : \\" << it_ << " >= ";
errors += range_->expr_right()->emit(out, ent, scope); errors += range_->right()->emit(out, ent, scope);
out << ");\n\\" << it_ << " = \\" << it_ << " + ("; out << ");\n\\" << it_ << " = \\" << it_ << " + (";
errors += range_->expr_left()->emit(out, ent, scope); errors += range_->left()->emit(out, ent, scope);
out << " < "; out << " < ";
errors += range_->expr_right()->emit(out, ent, scope); errors += range_->right()->emit(out, ent, scope);
out << " ? 1 : -1))"; out << " ? 1 : -1))";
return errors; return errors;
} }
int ReportStmt::emit(ostream&out, Entity*, ScopeBase*) int ReportStmt::emit(ostream&out, Entity*ent, ScopeBase*scope)
{ {
out << "$display(\""; out << "$display(\"** ";
switch(severity_) switch(severity_)
{ {
case NOTE: out << "** Note: "; break; case NOTE: out << "Note"; break;
case WARNING: out << "** Warning: "; break; case WARNING: out << "Warning"; break;
case ERROR: out << "** Error: "; break; case ERROR: out << "Error"; break;
case FAILURE: out << "** Failure: "; break; case FAILURE: out << "Failure"; break;
case UNSPECIFIED: ivl_assert(*this, false); break; case UNSPECIFIED: ivl_assert(*this, false); break;
} }
out << ExpString::escape_quot(msg_); out << ": \",";
out << " (" << get_fileline() << ")\");";
msg_->emit(out, ent, scope);
out << ",\" (" << get_fileline() << ")\");";
if(severity_ == FAILURE) if(severity_ == FAILURE)
out << "$finish();"; out << "$finish();";
@ -522,7 +505,8 @@ int ReportStmt::emit(ostream&out, Entity*, ScopeBase*)
void ReportStmt::write_to_stream(std::ostream&fd) void ReportStmt::write_to_stream(std::ostream&fd)
{ {
fd << "report \"" << ExpString::escape_quot(msg_) << "\"" << std::endl; fd << "report ";
msg_->write_to_stream(fd);
fd << "severity "; fd << "severity ";
switch(severity_) switch(severity_)
@ -563,7 +547,7 @@ int WaitForStmt::emit(ostream&out, Entity*ent, ScopeBase*scope)
out << "#("; out << "#(";
errors += delay_->emit(out, ent, scope); errors += delay_->emit(out, ent, scope);
out << ")"; out << ");" << std::endl;
return errors; return errors;
} }
@ -586,6 +570,7 @@ int WaitStmt::emit(ostream&out, Entity*ent, ScopeBase*scope)
case UNTIL: case UNTIL:
if(!sens_list_.empty()) { if(!sens_list_.empty()) {
out << "@("; out << "@(";
for(std::set<ExpName*>::iterator it = sens_list_.begin(); for(std::set<ExpName*>::iterator it = sens_list_.begin();
it != sens_list_.end(); ++it) { it != sens_list_.end(); ++it) {
if(it != sens_list_.begin()) if(it != sens_list_.begin())
@ -594,7 +579,7 @@ int WaitStmt::emit(ostream&out, Entity*ent, ScopeBase*scope)
(*it)->emit(out, ent, scope); (*it)->emit(out, ent, scope);
} }
out << ");"; out << "); ";
} }
out << "wait("; out << "wait(";

View File

@ -46,20 +46,20 @@ const VTypeArray primitive_UNSIGNED(&primitive_STDLOGIC, vector<VTypeArra
void generate_global_types(ActiveScope*res) void generate_global_types(ActiveScope*res)
{ {
// boolean // boolean
list<perm_string>*enum_BOOLEAN_vals = new list<perm_string>; list<perm_string> enum_BOOLEAN_vals;
enum_BOOLEAN_vals->push_back(perm_string::literal("false")); enum_BOOLEAN_vals.push_back(perm_string::literal("false"));
enum_BOOLEAN_vals->push_back(perm_string::literal("true")); enum_BOOLEAN_vals.push_back(perm_string::literal("true"));
VTypeEnum*enum_BOOLEAN = new VTypeEnum(enum_BOOLEAN_vals); VTypeEnum*enum_BOOLEAN = new VTypeEnum(&enum_BOOLEAN_vals);
type_BOOLEAN.set_definition(enum_BOOLEAN); type_BOOLEAN.set_definition(enum_BOOLEAN);
std_types[type_BOOLEAN.peek_name()] = &type_BOOLEAN; std_types[type_BOOLEAN.peek_name()] = &type_BOOLEAN;
std_enums.push_back(enum_BOOLEAN); std_enums.push_back(enum_BOOLEAN);
// file_open_kind // file_open_kind
list<perm_string>*enum_FILE_OPEN_KIND_vals = new list<perm_string>; list<perm_string> enum_FILE_OPEN_KIND_vals;
enum_FILE_OPEN_KIND_vals->push_back(perm_string::literal("read_mode")); enum_FILE_OPEN_KIND_vals.push_back(perm_string::literal("read_mode"));
enum_FILE_OPEN_KIND_vals->push_back(perm_string::literal("write_mode")); enum_FILE_OPEN_KIND_vals.push_back(perm_string::literal("write_mode"));
enum_FILE_OPEN_KIND_vals->push_back(perm_string::literal("append_mode")); enum_FILE_OPEN_KIND_vals.push_back(perm_string::literal("append_mode"));
VTypeEnum*enum_FILE_OPEN_KIND = new VTypeEnum(enum_FILE_OPEN_KIND_vals); VTypeEnum*enum_FILE_OPEN_KIND = new VTypeEnum(&enum_FILE_OPEN_KIND_vals);
type_FILE_OPEN_KIND.set_definition(enum_FILE_OPEN_KIND); type_FILE_OPEN_KIND.set_definition(enum_FILE_OPEN_KIND);
std_types[type_FILE_OPEN_KIND.peek_name()] = &type_FILE_OPEN_KIND; std_types[type_FILE_OPEN_KIND.peek_name()] = &type_FILE_OPEN_KIND;
std_enums.push_back(enum_FILE_OPEN_KIND); std_enums.push_back(enum_FILE_OPEN_KIND);
@ -80,10 +80,12 @@ void delete_global_types()
{ {
typedef_context_t typedef_ctx; typedef_context_t typedef_ctx;
for(map<perm_string, VTypeDef*>::iterator cur = std_types.begin(); for(map<perm_string, VTypeDef*>::iterator cur = std_types.begin();
cur != std_types.end() ; ++ cur) { cur != std_types.end(); ++cur) {
delete cur->second->peek_definition(); delete cur->second->peek_definition();
delete cur->second; delete cur->second;
} }
// std_enums are destroyed above
} }
const VTypeEnum*find_std_enum_name(perm_string name) const VTypeEnum*find_std_enum_name(perm_string name)

View File

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

View File

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

View File

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

View File

@ -72,8 +72,7 @@ int Variable::emit(ostream&out, Entity*ent, ScopeBase*scope)
VType::decl_t decl; VType::decl_t decl;
type_elaborate_(decl); type_elaborate_(decl);
if (peek_refcnt_sequ_() > 0 || !peek_type()->can_be_packed()) decl.reg_flag = true;
decl.reg_flag = true;
errors += decl.emit(out, peek_name()); errors += decl.emit(out, peek_name());
Expression*init_expr = peek_init_expr(); Expression*init_expr = peek_init_expr();

View File

@ -108,21 +108,18 @@ VTypeArray::VTypeArray(const VType*element, const vector<VTypeArray::range_t>&r,
/* /*
* Create a VTypeArray range set from a list of parsed ranges. * Create a VTypeArray range set from a list of parsed ranges.
* FIXME: We are copying pointers from the prange_t object into the * FIXME: We are copying pointers from the ExpRange object into the
* range_t. This means that we cannot delete the prange_t object * range_t. This means that we cannot delete the ExpRange object
* unless we invent a way to remove the pointers from that object. So * unless we invent a way to remove the pointers from that object. So
* this is a memory leak. Something to fix. * this is a memory leak. Something to fix.
*/ */
VTypeArray::VTypeArray(const VType*element, std::list<prange_t*>*r, bool sv) VTypeArray::VTypeArray(const VType*element, std::list<ExpRange*>*r, bool sv)
: etype_(element), ranges_(r->size()), signed_flag_(sv), parent_(NULL) : etype_(element), ranges_(r->size()), signed_flag_(sv), parent_(NULL)
{ {
for (size_t idx = 0 ; idx < ranges_.size() ; idx += 1) { for (size_t idx = 0 ; idx < ranges_.size() ; idx += 1) {
prange_t*curp = r->front(); ExpRange*curp = r->front();
r->pop_front(); r->pop_front();
Expression*msb = curp->msb(); ranges_[idx] = range_t(curp->msb(), curp->lsb(), curp->direction());
Expression*lsb = curp->lsb();
bool dir = curp->is_downto();
ranges_[idx] = range_t(msb, lsb, dir);
} }
} }

View File

@ -33,7 +33,7 @@ class Architecture;
class ScopeBase; class ScopeBase;
class Entity; class Entity;
class Expression; class Expression;
class prange_t; class ExpRange;
class VTypeDef; class VTypeDef;
class ScopeBase; class ScopeBase;
@ -210,7 +210,7 @@ class VTypeArray : public VType {
public: public:
VTypeArray(const VType*etype, const std::vector<range_t>&r, bool signed_vector = false); VTypeArray(const VType*etype, const std::vector<range_t>&r, bool signed_vector = false);
VTypeArray(const VType*etype, std::list<prange_t*>*r, bool signed_vector = false); VTypeArray(const VType*etype, std::list<ExpRange*>*r, bool signed_vector = false);
VTypeArray(const VType*etype, int msb, int lsb, bool signed_vector = false); VTypeArray(const VType*etype, int msb, int lsb, bool signed_vector = false);
~VTypeArray(); ~VTypeArray();

View File

@ -169,10 +169,11 @@ static int get_default_format(const char *name)
int default_format; int default_format;
switch(name[ strlen(name)-1 ]){ switch(name[ strlen(name)-1 ]){
/* writE/strobE or monitoR or displaY/fdisplaY or sformaT */ /* writE/strobE or monitoR or displaY/fdisplaY or sformaT/sformatF */
case 'e': case 'e':
case 'r': case 'r':
case 't': case 't':
case 'f':
case 'y': default_format = vpiDecStrVal; break; case 'y': default_format = vpiDecStrVal; break;
case 'h': default_format = vpiHexStrVal; break; case 'h': default_format = vpiHexStrVal; break;
case 'o': default_format = vpiOctStrVal; break; case 'o': default_format = vpiOctStrVal; break;
@ -620,10 +621,6 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus,
case 't': case 't':
case 'T': case 'T':
*idx += 1; *idx += 1;
if (plus != 0) {
vpi_printf("WARNING: %s:%d: invalid format %s%s.\n",
info->filename, info->lineno, info->name, fmtb);
}
if (*idx >= info->nitems) { if (*idx >= info->nitems) {
vpi_printf("WARNING: %s:%d: missing argument for %s%s.\n", vpi_printf("WARNING: %s:%d: missing argument for %s%s.\n",
info->filename, info->lineno, info->name, fmtb); info->filename, info->lineno, info->name, fmtb);
@ -647,6 +644,29 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus,
} else { } else {
char *tbuf; char *tbuf;
PLI_INT32 time_units = vpi_get(vpiTimeUnit, info->scope); PLI_INT32 time_units = vpi_get(vpiTimeUnit, info->scope);
if (plus != 0) {
/* Icarus-specific extension to print out time units.
* It is needed by vhdlpp to correctly implement time'image(). */
PLI_INT32 time_prec = vpi_get(vpiTimePrecision, info->scope);
if(time_units < -12)
timeformat_info.suff = strdup(" fs");
else if(time_units < -9)
timeformat_info.suff = strdup(" ps");
else if(time_units < -6)
timeformat_info.suff = strdup(" ns");
else if(time_units < -3)
timeformat_info.suff = strdup(" us");
else if(time_units < 0)
timeformat_info.suff = strdup(" ms");
else
timeformat_info.suff = strdup(" s");
/* Adjust shift for get_time(), so the number indeed matches the unit */
time_units += (3 + (time_units % 3)) % 3 + (time_prec - time_units);
}
unsigned swidth, free_flag = 0; unsigned swidth, free_flag = 0;
unsigned suff_len = strlen(timeformat_info.suff); unsigned suff_len = strlen(timeformat_info.suff);
char *cp; char *cp;
@ -1238,7 +1258,8 @@ static PLI_INT32 sys_display_compiletf(ICARUS_VPI_CONST PLI_BYTE8*name)
return sys_common_compiletf(name, 0, 0); return sys_common_compiletf(name, 0, 0);
} }
/* This implements the $display/$fdisplay and the $write/$fwrite based tasks. */ /* This implements the $sformatf, $display/$fdisplay
* and the $write/$fwrite based tasks. */
static PLI_INT32 sys_display_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) static PLI_INT32 sys_display_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name)
{ {
vpiHandle callh, argv, scope; vpiHandle callh, argv, scope;
@ -1246,6 +1267,7 @@ static PLI_INT32 sys_display_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name)
char* result; char* result;
unsigned int size; unsigned int size;
PLI_UINT32 fd_mcd; PLI_UINT32 fd_mcd;
s_vpi_value val;
callh = vpi_handle(vpiSysTfCall, 0); callh = vpi_handle(vpiSysTfCall, 0);
argv = vpi_iterate(vpiArgument, callh); argv = vpi_iterate(vpiArgument, callh);
@ -1254,7 +1276,6 @@ static PLI_INT32 sys_display_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name)
if(name[1] == 'f') { if(name[1] == 'f') {
errno = 0; errno = 0;
vpiHandle arg = vpi_scan(argv); vpiHandle arg = vpi_scan(argv);
s_vpi_value val;
val.format = vpiIntVal; val.format = vpiIntVal;
vpi_get_value(arg, &val); vpi_get_value(arg, &val);
fd_mcd = val.value.integer; fd_mcd = val.value.integer;
@ -1275,7 +1296,11 @@ static PLI_INT32 sys_display_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name)
vpi_free_object(argv); vpi_free_object(argv);
return 0; return 0;
} }
} else if(strncmp(name,"$sformatf",9) == 0) {
/* return as a string */
fd_mcd = 0;
} else { } else {
/* stdout */
fd_mcd = 1; fd_mcd = 1;
} }
@ -1293,13 +1318,21 @@ static PLI_INT32 sys_display_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name)
/* Because %u and %z may put embedded NULL characters into the /* Because %u and %z may put embedded NULL characters into the
* returned string strlen() may not match the real size! */ * returned string strlen() may not match the real size! */
result = get_display(&size, &info); result = get_display(&size, &info);
my_mcd_rawwrite(fd_mcd, result, size);
if ((strncmp(name,"$display",8) == 0) ||
(strncmp(name,"$fdisplay",9) == 0)) my_mcd_rawwrite(fd_mcd, "\n", 1);
if(fd_mcd > 0) {
my_mcd_rawwrite(fd_mcd, result, size);
if ((strncmp(name,"$display",8) == 0) ||
(strncmp(name,"$fdisplay",9) == 0)) my_mcd_rawwrite(fd_mcd, "\n", 1);
} else {
/* Return as a string ($sformatf) */
val.format = vpiStringVal;
val.value.str = result;
vpi_put_value(callh, &val, 0, vpiNoDelay);
}
free(result);
free(info.filename); free(info.filename);
free(info.items); free(info.items);
free(result);
return 0; return 0;
} }
@ -1665,7 +1698,7 @@ static PLI_INT32 sys_sformat_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name)
if (argv == 0) { if (argv == 0) {
vpi_printf("ERROR:%s:%d: ", vpi_get_str(vpiFile, callh), vpi_printf("ERROR:%s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh)); (int)vpi_get(vpiLineNo, callh));
vpi_printf("%s requires at least two argument.\n", name); vpi_printf("%s requires at least two arguments.\n", name);
vpi_control(vpiFinish, 1); vpi_control(vpiFinish, 1);
return 0; return 0;
} }
@ -1686,7 +1719,7 @@ static PLI_INT32 sys_sformat_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name)
if (arg == 0) { if (arg == 0) {
vpi_printf("ERROR:%s:%d: ", vpi_get_str(vpiFile, callh), vpi_printf("ERROR:%s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh)); (int)vpi_get(vpiLineNo, callh));
vpi_printf("%s requires at least two argument.\n", name); vpi_printf("%s requires at least two arguments.\n", name);
vpi_control(vpiFinish, 1); vpi_control(vpiFinish, 1);
return 0; return 0;
} }
@ -1754,6 +1787,46 @@ static PLI_INT32 sys_sformat_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name)
return 0; return 0;
} }
static PLI_INT32 sys_sformatf_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
vpiHandle arg;
PLI_INT32 type;
/* Check that there are arguments. */
if (argv == 0) {
vpi_printf("ERROR:%s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s requires at least one argument.\n", name);
vpi_control(vpiFinish, 1);
return 0;
}
/* The first argument must be a string, a register or a SV string. */
arg = vpi_scan(argv);
if (arg == 0) {
vpi_printf("ERROR:%s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s requires at least one argument.\n", name);
vpi_control(vpiFinish, 1);
return 0;
}
type = vpi_get(vpiType, arg);
if (((type != vpiConstant && type != vpiParameter) ||
vpi_get(vpiConstType, arg) != vpiStringConst) &&
type != vpiReg && type != vpiStringVar) {
vpi_printf("ERROR:%s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s's first argument must be a string or a register.\n", name);
vpi_control(vpiFinish, 1);
return 0;
}
if (sys_check_args(callh, argv, name, 0, 0)) vpi_control(vpiFinish, 1);
return 0;
}
static PLI_INT32 sys_end_of_compile(p_cb_data cb_data) static PLI_INT32 sys_end_of_compile(p_cb_data cb_data)
{ {
(void)cb_data; /* Parameter is not used. */ (void)cb_data; /* Parameter is not used. */
@ -2434,6 +2507,16 @@ void sys_display_register(void)
res = vpi_register_systf(&tf_data); res = vpi_register_systf(&tf_data);
vpip_make_systf_system_defined(res); vpip_make_systf_system_defined(res);
tf_data.type = vpiSysFunc;
tf_data.sysfunctype = vpiStringFunc;
tf_data.tfname = "$sformatf";
tf_data.calltf = sys_display_calltf;
tf_data.compiletf = sys_sformatf_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = "$sformatf";
res = vpi_register_systf(&tf_data);
vpip_make_systf_system_defined(res);
/*============================ timeformat */ /*============================ timeformat */
tf_data.type = vpiSysTask; tf_data.type = vpiSysTask;
tf_data.tfname = "$timeformat"; tf_data.tfname = "$timeformat";

View File

@ -24,3 +24,5 @@ $table_model vpiSysFuncReal
$ivl_string_method$len vpiSysFuncInt $ivl_string_method$len vpiSysFuncInt
$ivl_string_method$to_vec vpiSysFuncVoid $ivl_string_method$to_vec vpiSysFuncVoid
$sformatf vpiSysFuncString

View File

@ -840,6 +840,7 @@ instructions. The formats are:
%vpi_call/i <file-index> <lineno> <name>, <args>... ; %vpi_call/i <file-index> <lineno> <name>, <args>... ;
%vpi_func <file-index> <lineno> <name>, <args>... ; %vpi_func <file-index> <lineno> <name>, <args>... ;
%vpi_func/r <file-index> <lineno> <name>, <args>... ; %vpi_func/r <file-index> <lineno> <name>, <args>... ;
%vpi_func/s <file-index> <lineno> <name>, <args>... ;
The <file-index> is an index into the string table. The indexed string The <file-index> is an index into the string table. The indexed string
is the source code file name where this call appears. The <lineno> is is the source code file name where this call appears. The <lineno> is

View File

@ -235,6 +235,7 @@ static char* strdupnew(char const *str)
"%vpi_call/i" { return K_vpi_call_i; } "%vpi_call/i" { return K_vpi_call_i; }
"%vpi_func" { return K_vpi_func; } "%vpi_func" { return K_vpi_func; }
"%vpi_func/r" { return K_vpi_func_r; } "%vpi_func/r" { return K_vpi_func_r; }
"%vpi_func/s" { return K_vpi_func_s; }
"%file_line" { return K_file_line; } "%file_line" { return K_file_line; }
/* Handle the specialized variable access functions. */ /* Handle the specialized variable access functions. */

View File

@ -1241,6 +1241,7 @@ stack when the call returns.
* %vpi_func <file> <line> <name> [, ...] {<vec4> <real> <str>} * %vpi_func <file> <line> <name> [, ...] {<vec4> <real> <str>}
* %vpi_func/r <file> <line> <name> [, ...] {<vec4> <real> <str>} * %vpi_func/r <file> <line> <name> [, ...] {<vec4> <real> <str>}
* %vpi_func/s <file> <line> <name> [, ...] {<vec4> <real> <str>}
This instruction is similar to %vpi_call, except that it is for This instruction is similar to %vpi_call, except that it is for
calling system functions. The difference here is the return value from calling system functions. The difference here is the return value from

View File

@ -100,7 +100,7 @@ static struct __vpiModPath*modpath_dst = 0;
%token K_VAR_QUEUE %token K_VAR_QUEUE
%token K_VAR_S K_VAR_STR K_VAR_I K_VAR_R K_VAR_2S K_VAR_2U %token K_VAR_S K_VAR_STR K_VAR_I K_VAR_R K_VAR_2S K_VAR_2U
%token K_vpi_call K_vpi_call_w K_vpi_call_i %token K_vpi_call K_vpi_call_w K_vpi_call_i
%token K_vpi_func K_vpi_func_r %token K_vpi_func K_vpi_func_r K_vpi_func_s
%token K_ivl_version K_ivl_delay_selection %token K_ivl_version K_ivl_delay_selection
%token K_vpi_module K_vpi_time_precision K_file_names K_file_line %token K_vpi_module K_vpi_time_precision K_file_names K_file_line
%token K_PORT_INPUT K_PORT_OUTPUT K_PORT_INOUT K_PORT_MIXED K_PORT_NODIR %token K_PORT_INPUT K_PORT_OUTPUT K_PORT_INOUT K_PORT_MIXED K_PORT_NODIR
@ -658,6 +658,10 @@ statement
{ compile_vpi_func_call($1, $5, -vpiRealVal, 0, $3, $4, { compile_vpi_func_call($1, $5, -vpiRealVal, 0, $3, $4,
$6.argc, $6.argv, $8, $9, $10); } $6.argc, $6.argv, $8, $9, $10); }
| label_opt K_vpi_func_s T_NUMBER T_NUMBER T_STRING
argument_opt '{' T_NUMBER T_NUMBER T_NUMBER '}' ';'
{ compile_vpi_func_call($1, $5, -vpiStringVal, 0, $3, $4,
$6.argc, $6.argv, $8, $9, $10); }
/* Scope statements come in two forms. There are the scope /* Scope statements come in two forms. There are the scope
declaration and the scope recall. The declarations create the declaration and the scope recall. The declarations create the

View File

@ -143,54 +143,25 @@ static vpiHandle systask_iter(int, vpiHandle ref)
} }
struct systask_def : public __vpiSysTaskCall { struct systask_def : public __vpiSysTaskCall {
inline systask_def() { } virtual ~systask_def() {};
int get_type_code(void) const { return vpiSysTaskCall; } virtual int get_type_code(void) const { return vpiSysTaskCall; }
int vpi_get(int code) { return systask_get(code, this); } virtual int vpi_get(int code) { return systask_get(code, this); }
char*vpi_get_str(int code) { return systask_get_str(code, this); } virtual char*vpi_get_str(int code) { return systask_get_str(code, this); }
vpiHandle vpi_handle(int code) { return systask_handle(code, this); } virtual vpiHandle vpi_handle(int code) { return systask_handle(code, this); }
vpiHandle vpi_iterate(int code){ return systask_iter(code, this); } virtual vpiHandle vpi_iterate(int code){ return systask_iter(code, this); }
}; };
static vpiHandle sysfunc_put_rnet_value(vpiHandle ref, p_vpi_value vp, int) struct sysfunc_def : public systask_def {
{ virtual ~sysfunc_def() {};
struct __vpiSysTaskCall*rfp = dynamic_cast<__vpiSysTaskCall*>(ref); virtual int get_type_code(void) const { return vpiSysFuncCall; }
virtual int vpi_get(int code) { return sysfunc_get(code, this); }
};
rfp->put_value = true; struct sysfunc_real : public sysfunc_def {
double val;
switch (vp->format) {
case vpiRealVal:
val = vp->value.real;
break;
default:
val = 0.0;
fprintf(stderr, "Unsupported format %d.\n", (int)vp->format);
assert(0);
}
rfp->fnet->send_real(val, vthread_get_wt_context());
return 0;
}
static vpiHandle sysfunc_put_no_value(vpiHandle, p_vpi_value, int)
{
return 0;
}
struct sysfunc_real : public __vpiSysTaskCall {
inline sysfunc_real() { }
int get_type_code(void) const { return vpiSysFuncCall; }
int vpi_get(int code) { return sysfunc_get(code, this); }
char* vpi_get_str(int code) { return systask_get_str(code, this); }
vpiHandle vpi_put_value(p_vpi_value val, int flags); vpiHandle vpi_put_value(p_vpi_value val, int flags);
vpiHandle vpi_handle(int code) inline double return_value() const { return return_value_; }
{ return systask_handle(code, this); }
vpiHandle vpi_iterate(int code)
{ return systask_iter(code, this); }
private:
double return_value_; double return_value_;
}; };
@ -211,18 +182,53 @@ vpiHandle sysfunc_real::vpi_put_value(p_vpi_value vp, int)
return 0; return 0;
} }
class sysfunc_vec4 : public __vpiSysTaskCall { struct sysfunc_str : public sysfunc_def {
int vpi_get(int code);
vpiHandle vpi_put_value(p_vpi_value val, int flags);
inline const std::string& return_value() const { return return_value_; };
private:
std::string return_value_;
};
int sysfunc_str::vpi_get(int code)
{
switch (code) {
case vpiSize:
return return_value_.size();
case vpiLineNo:
return lineno;
case vpiUserDefn:
return defn->is_user_defn;
default:
return vpiUndefined;
}
}
vpiHandle sysfunc_str::vpi_put_value(p_vpi_value vp, int)
{
put_value = true;
switch (vp->format) {
case vpiStringVal:
return_value_ = std::string(vp->value.str);
break;
default:
fprintf(stderr, "Unsupported format %d.\n", (int)vp->format);
assert(0);
}
return 0;
}
class sysfunc_vec4 : public sysfunc_def {
public: public:
explicit inline sysfunc_vec4(unsigned wid): return_value_(wid, BIT4_X) { } explicit inline sysfunc_vec4(unsigned wid): return_value_(wid, BIT4_X) { }
int get_type_code(void) const { return vpiSysFuncCall; }
int vpi_get(int code); int vpi_get(int code);
char* vpi_get_str(int code) { return systask_get_str(code, this); }
vpiHandle vpi_put_value(p_vpi_value val, int flags); vpiHandle vpi_put_value(p_vpi_value val, int flags);
vpiHandle vpi_handle(int code)
{ return systask_handle(code, this); }
vpiHandle vpi_iterate(int code)
{ return systask_iter(code, this); }
inline const vvp_vector4_t& return_value() const { return return_value_; } inline const vvp_vector4_t& return_value() const { return return_value_; }
private: private:
@ -232,7 +238,6 @@ class sysfunc_vec4 : public __vpiSysTaskCall {
vpiHandle put_value_vector_(p_vpi_value vp); vpiHandle put_value_vector_(p_vpi_value vp);
vpiHandle put_value_time_(p_vpi_value vp); vpiHandle put_value_time_(p_vpi_value vp);
private:
vvp_vector4_t return_value_; vvp_vector4_t return_value_;
}; };
@ -388,48 +393,15 @@ vpiHandle sysfunc_vec4::vpi_put_value(p_vpi_value vp, int)
return 0; return 0;
} }
struct sysfunc_4net : public __vpiSysTaskCall { struct sysfunc_4net : public sysfunc_def {
explicit inline sysfunc_4net(unsigned wid) : vwid_(wid) { } explicit inline sysfunc_4net(unsigned wid) : vwid_(wid) { }
int get_type_code(void) const { return vpiSysFuncCall; }
int vpi_get(int code); int vpi_get(int code);
char* vpi_get_str(int code) { return systask_get_str(code, this); }
vpiHandle vpi_put_value(p_vpi_value val, int flags); vpiHandle vpi_put_value(p_vpi_value val, int flags);
vpiHandle vpi_handle(int code)
{ return systask_handle(code, this); }
vpiHandle vpi_iterate(int code)
{ return systask_iter(code, this); }
private: private:
unsigned vwid_; unsigned vwid_;
}; };
struct sysfunc_rnet : public __vpiSysTaskCall {
inline sysfunc_rnet() { }
int get_type_code(void) const { return vpiSysFuncCall; }
int vpi_get(int code) { return sysfunc_get(code, this); }
char* vpi_get_str(int code) { return systask_get_str(code, this); }
vpiHandle vpi_put_value(p_vpi_value val, int flags)
{ return sysfunc_put_rnet_value(this, val, flags); }
vpiHandle vpi_handle(int code)
{ return systask_handle(code, this); }
vpiHandle vpi_iterate(int code)
{ return systask_iter(code, this); }
};
struct sysfunc_no : public __vpiSysTaskCall {
inline sysfunc_no() { }
int get_type_code(void) const { return vpiSysFuncCall; }
int vpi_get(int code) { return sysfunc_get(code, this); }
char* vpi_get_str(int code) { return systask_get_str(code, this); }
vpiHandle vpi_put_value(p_vpi_value val, int flags)
{ return sysfunc_put_no_value(this, val, flags); }
vpiHandle vpi_handle(int code)
{ return systask_handle(code, this); }
vpiHandle vpi_iterate(int code)
{ return systask_iter(code, this); }
};
// support getting vpiSize for a system function call // support getting vpiSize for a system function call
int sysfunc_4net::vpi_get(int code) int sysfunc_4net::vpi_get(int code)
{ {
@ -547,6 +519,41 @@ vpiHandle sysfunc_4net::vpi_put_value(p_vpi_value vp, int)
return 0; return 0;
} }
struct sysfunc_rnet : public sysfunc_def {
vpiHandle vpi_put_value(p_vpi_value val, int flags);
};
vpiHandle sysfunc_rnet::vpi_put_value(p_vpi_value vp, int)
{
put_value = true;
double value;
switch (vp->format) {
case vpiRealVal:
value = vp->value.real;
break;
default:
value = 0.0;
fprintf(stderr, "Unsupported format %d.\n", (int)vp->format);
assert(0);
}
fnet->send_real(value, vthread_get_wt_context());
return 0;
}
struct sysfunc_no : public sysfunc_def {
vpiHandle vpi_put_value(p_vpi_value val, int flags);
};
vpiHandle sysfunc_no::vpi_put_value(p_vpi_value, int)
{
return 0;
}
/* **** Manipulate the internal data structures. **** */ /* **** Manipulate the internal data structures. **** */
@ -845,6 +852,9 @@ vpiHandle vpip_build_vpi_call(const char*name, int val_code, unsigned return_wid
} else if (val_code == -vpiVectorVal) { } else if (val_code == -vpiVectorVal) {
obj = new sysfunc_vec4(return_width); obj = new sysfunc_vec4(return_width);
} else if (val_code == -vpiStringVal) {
obj = new sysfunc_str;
} else if (val_code == 0 && fnet == 0) { } else if (val_code == 0 && fnet == 0) {
obj = new sysfunc_no; obj = new sysfunc_no;
@ -957,12 +967,15 @@ void vpip_execute_vpi_call(vthread_t thr, vpiHandle ref)
if (vpip_cur_task->string_stack > 0) if (vpip_cur_task->string_stack > 0)
vthread_pop_str(thr, vpip_cur_task->string_stack); vthread_pop_str(thr, vpip_cur_task->string_stack);
/* If the function has a real value, then push the value /* If the function returns a value, then push the value
to the thread stack. */ to the appropriate thread stack. */
if (sysfunc_real*func_real = dynamic_cast<sysfunc_real*>(ref)) { if (sysfunc_real*func_real = dynamic_cast<sysfunc_real*>(ref)) {
vthread_push_real(thr, func_real->return_value_); vthread_push_real(thr, func_real->return_value());
} }
if (sysfunc_vec4*func_vec4 = dynamic_cast<sysfunc_vec4*>(ref)) { else if (sysfunc_str*func_string = dynamic_cast<sysfunc_str*>(ref)) {
vthread_push_str(thr, func_string->return_value());
}
else if (sysfunc_vec4*func_vec4 = dynamic_cast<sysfunc_vec4*>(ref)) {
vthread_push_vec4(thr, func_vec4->return_value()); vthread_push_vec4(thr, func_vec4->return_value());
} }
} }

View File

@ -346,6 +346,11 @@ void vthread_push_real(struct vthread_s*thr, double val)
thr->push_real(val); thr->push_real(val);
} }
void vthread_push_str(struct vthread_s*thr, const string&val)
{
thr->push_str(val);
}
void vthread_pop_vec4(struct vthread_s*thr, unsigned depth) void vthread_pop_vec4(struct vthread_s*thr, unsigned depth)
{ {
thr->pop_vec4(depth); thr->pop_vec4(depth);

View File

@ -113,6 +113,7 @@ extern vvp_context_item_t vthread_get_rd_context_item(unsigned context_idx);
* Access value stacks from thread space. * Access value stacks from thread space.
*/ */
extern void vthread_push_vec4(struct vthread_s*thr, const vvp_vector4_t&val); extern void vthread_push_vec4(struct vthread_s*thr, const vvp_vector4_t&val);
extern void vthread_push_str(struct vthread_s*thr, const std::string&val);
extern void vthread_push_real(struct vthread_s*thr, double val); extern void vthread_push_real(struct vthread_s*thr, double val);
extern void vthread_pop_vec4(struct vthread_s*thr, unsigned count); extern void vthread_pop_vec4(struct vthread_s*thr, unsigned count);