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
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"
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

View File

@ -2838,7 +2838,7 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
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 "
<< "may not have zero width in this context." << endl;
des->errors += 1;

View File

@ -75,6 +75,10 @@ EXTERN_C_START
/********* task/function properties **********/
#define vpiOtherFunc 6
/* Icarus-specific function type to use string as the return type */
#define vpiStringFunc 10
#define vpiSysFuncString vpiSysFuncString
EXTERN_C_END
#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
* 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_);
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();
if (!lsig) {
cerr << get_fileline() << ": error: "
@ -218,6 +226,8 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
rsig = tmp;
}
rsig = crop_to_width(des, rsig, lsig->vector_width());
if (nex_out.pin_count() > 1) {
NexusSet 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
for the inputs of the FF bank. */
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
accounts for the subset of outputs that this

View File

@ -204,6 +204,17 @@ int load_sys_func_table(const char*path)
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",
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);
}
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
* 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. */
if (ivl_expr_width(le)==use_wid && test_immediate_vec4_ok(le)) {
ivl_expr_t tmp = le;
re = le;
le = tmp;
le = re;
re = tmp;
}
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));
}
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)
{
@ -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)
string_ex_pop(expr);
else
fallback_eval(expr);
draw_sfunc_string(expr);
break;
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_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);

View File

@ -137,7 +137,7 @@ GenerateStatement::~GenerateStatement()
}
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),
lsb_(rang->lsb()), msb_(rang->msb())
{

View File

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

View File

@ -21,6 +21,7 @@
# include "entity.h"
# include "expression.h"
# include "sequential.h"
# include "subprogram.h"
# include <typeinfo>
# include <cassert>
@ -59,6 +60,11 @@ int Architecture::elaborate(Entity*entity)
cur->second->elaborate_init_expr(entity, this);
}
// Elaborate subprograms
for (map<perm_string,SubprogramHeader*>::const_iterator cur = cur_subprograms_.begin()
; cur != cur_subprograms_.end() ; ++cur) {
errors += cur->second->elaborate();
}
// Create 'initial' and 'final' blocks for implicit
// initalization and clean-up actions
if(!initializers_.empty())
@ -222,7 +228,7 @@ int ProcessStatement::rewrite_as_always_edge_(Entity*, Architecture*)
}
// 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)
return -1;
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
out << " -- imported types" << endl;
@ -251,9 +251,16 @@ void ExpAggregate::choice_t::dump(ostream&out, int indent) const
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;
base_->dump(out, indent+4);
}
@ -442,13 +449,6 @@ void named_expr_t::dump(ostream&out, int indent) const
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
{
out << typeid(*this).name();

View File

@ -54,29 +54,88 @@ bool Expression::symbolic_compare(const Expression*) const
return false;
}
ExpAttribute::ExpAttribute(ExpName*bas, perm_string nam)
: base_(bas), name_(nam)
ExpAttribute::ExpAttribute(perm_string nam, list<Expression*>*args)
: name_(nam), args_(args)
{
}
ExpAttribute::~ExpAttribute()
{
/* Different attributes can point to the same base so we cannot delete this here.
* Look at the vhdl_range test with valgrind to see this issue. */
// delete base_;
if(args_) {
for(list<Expression*>::iterator it = args_->begin();
it != args_->end(); ++it) {
delete *it;
}
}
delete args_;
}
Expression*ExpAttribute::clone() const
{
return new ExpAttribute(static_cast<ExpName*>(base_->clone()), name_);
list<Expression*>*ExpAttribute::clone_args() const {
list<Expression*>*new_args = NULL;
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);
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)
: operand1_(op1), operand2_(op2)
{
@ -88,14 +147,14 @@ ExpBinary::~ExpBinary()
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)
@ -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)
{
}
@ -203,7 +262,7 @@ ExpAggregate::choice_t::choice_t(const choice_t&other)
expr_.reset(e->clone());
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()
@ -221,7 +280,7 @@ Expression*ExpAggregate::choice_t::simple_expression(bool detach_flag)
return res;
}
prange_t*ExpAggregate::choice_t::range_expressions(void)
ExpRange*ExpAggregate::choice_t::range_expressions(void)
{
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_;
return true;
@ -535,6 +594,7 @@ ExpName::ExpName(perm_string nn, list<Expression*>*indices)
ExpName::ExpName(perm_string nn, Expression*msb, Expression*lsb)
: name_(nn), index_(msb), lsb_(lsb)
{
ivl_assert(*this, !msb || msb != lsb);
}
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)
: prefix_(prefix), name_(nn), index_(msb), lsb_(lsb)
{
ivl_assert(*this, !msb || msb != lsb);
}
ExpName::~ExpName()
@ -712,3 +773,75 @@ double ExpTime::to_fs() const
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 <vector>
class prange_t;
class Entity;
class ExpRange;
class ScopeBase;
class SubprogramHeader;
class VType;
@ -107,8 +106,8 @@ class Expression : public LineInfo {
// to constant literal values. Return true and set the val
// argument if the evaluation works, or return false if it
// cannot be done.
virtual bool evaluate(ScopeBase*scope, int64_t&val) const;
virtual bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const;
virtual bool evaluate(Entity*, ScopeBase*, int64_t&) const { return false; }
bool evaluate(ScopeBase*scope, int64_t&val) const { return evaluate(NULL, scope, val); }
// The symbolic compare returns true if the two expressions
// 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 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); }
protected:
@ -205,8 +204,8 @@ class ExpBinary : public Expression {
int emit_operand1(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_operand2(ScopeBase*scope, int64_t&val) const;
bool eval_operand1(Entity*ent, 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
{ operand1_->write_to_stream(out); }
@ -239,7 +238,7 @@ class ExpAggregate : public Expression {
// Create a named choice
explicit choice_t(perm_string name);
// discreate_range choice
explicit choice_t(prange_t*ran);
explicit choice_t(ExpRange*ran);
choice_t(const choice_t&other);
@ -249,15 +248,15 @@ class ExpAggregate : public Expression {
bool others() const;
// Return expression if this represents a simple_expression.
Expression*simple_expression(bool detach_flag =true);
// Return prange_t if this represents a range_expression
prange_t*range_expressions(void);
// Return ExpRange if this represents a range_expression
ExpRange*range_expressions(void);
void write_to_stream(std::ostream&fd);
void dump(ostream&out, int indent) const;
private:
std::auto_ptr<Expression>expr_;
std::auto_ptr<prange_t> range_;
std::auto_ptr<ExpRange> range_;
private: // not implemented
choice_t& operator= (const choice_t&);
};
@ -343,7 +342,7 @@ class ExpArithmetic : public ExpBinary {
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd) const;
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;
private:
@ -356,18 +355,60 @@ class ExpArithmetic : public ExpBinary {
class ExpAttribute : public Expression {
public:
ExpAttribute(ExpName*base, perm_string name);
~ExpAttribute();
ExpAttribute(perm_string name,std::list<Expression*>*args);
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;
inline perm_string peek_attribute() const { return name_; }
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;
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
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);
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
bool evaluate(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);
private:
ExpName*base_;
perm_string name_;
const VType*base_;
};
class ExpBitstring : public Expression {
@ -440,7 +480,6 @@ class ExpConcat : public Expression {
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope);
virtual bool evaluate(ScopeBase*scope, int64_t&val) const;
bool is_primary(void) const;
void dump(ostream&out, int indent = 0) const;
void visit(ExprVisitor& func);
@ -583,7 +622,7 @@ class ExpInteger : public Expression {
int emit(ostream&out, Entity*ent, ScopeBase*scope);
int emit_package(std::ostream&out);
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;
virtual ostream& dump_inline(ostream&out) const;
@ -665,7 +704,6 @@ class ExpName : public Expression {
void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope);
bool is_primary(void) const;
bool evaluate(ScopeBase*scope, int64_t&val) const;
bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const;
bool symbolic_compare(const Expression*that) 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);
void write_to_stream(std::ostream&fd) const;
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;
private:
@ -891,7 +929,6 @@ class ExpTime : public Expression {
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);
//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;
@ -902,6 +939,46 @@ class ExpTime : public Expression {
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.
int elaborate_argument(Expression*expr, const SubprogramHeader*subp,
int idx, Entity*ent, ScopeBase*scope);

View File

@ -117,3 +117,9 @@ void ExpTime::dump(ostream&out, int indent) const
out << setw(indent) << "" << "Time ";
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;
}
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
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;
bool flag;
flag = index_->evaluate(scope, use_msb);
flag = index_->evaluate(ent, scope, use_msb);
ivl_assert(*this, flag);
flag = lsb_->evaluate(scope, use_lsb);
flag = lsb_->evaluate(ent, scope, use_lsb);
ivl_assert(*this, flag);
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;
if (const InterfacePort*cur = ent->find_port(name_)) {
if (cur->mode != PORT_OUT && cur->mode != PORT_INOUT) {
cerr << get_fileline() << ": error: Assignment to "
"input port " << name_ << "." << endl;
return errors += 1;
}
if (ent) {
if (const InterfacePort*cur = ent->find_port(name_)) {
if (cur->mode != PORT_OUT && cur->mode != PORT_INOUT) {
cerr << get_fileline() << ": error: Assignment to "
"input port " << name_ << "." << endl;
return errors += 1;
}
if (is_sequ)
ent->set_declaration_l_value(name_, is_sequ);
if (is_sequ)
ent->set_declaration_l_value(name_, is_sequ);
found_type = cur->type;
found_type = cur->type;
} else if (ent->find_generic(name_)) {
} else if (ent->find_generic(name_)) {
cerr << get_fileline() << ": error: Assignment to generic "
<< name_ << " from entity "
<< ent->get_name() << "." << endl;
return 1;
cerr << get_fileline() << ": error: Assignment to generic "
<< name_ << " from entity "
<< ent->get_name() << "." << endl;
return 1;
}
}
} else if (Signal*sig = scope->find_signal(name_)) {
// Tell the target signal that this may be a sequential l-value.
if (is_sequ) sig->count_ref_sequ();
if (!found_type && scope) {
if (Signal*sig = scope->find_signal(name_)) {
// Tell the target signal that this may be a sequential l-value.
if (is_sequ) sig->count_ref_sequ();
found_type = sig->peek_type();
found_type = sig->peek_type();
} else if (Variable*var = scope->find_variable(name_)) {
// Tell the target signal that this may be a sequential l-value.
if (is_sequ) var->count_ref_sequ();
} else if (Variable*var = scope->find_variable(name_)) {
// Tell the target signal that this may be a sequential l-value.
if (is_sequ) var->count_ref_sequ();
found_type = var->peek_type();
found_type = var->peek_type();
} else if (const InterfacePort*port = scope->find_param(name_)) {
found_type = port->type;
}
}
if (found_type == 0) {
@ -318,7 +327,8 @@ int ExpName::elaborate_rval(Entity*ent, ScopeBase*scope, const InterfacePort*lva
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;
}
@ -393,7 +403,7 @@ const VType*ExpAggregate::fit_type(Entity*, ScopeBase*, const VTypeArray*host) c
elements_[0]->map_choices(&ce[0]);
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);
Expression*use_msb = prange->msb();
@ -573,23 +583,32 @@ const VType* ExpArithmetic::resolve_operand_types_(const VType*t1, const VType*t
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 NULL;
}
int ExpTypeAttribute::elaborate_expr(Entity*, ScopeBase*, const VType*)
{
// This is just to mute warnings, there is nothing to elaborate here
return 0;
}
int ExpAttribute::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*)
const VType* ExpTypeAttribute::probe_type(Entity*, ScopeBase*) const
{
int errors = 0;
const VType*sub_type = base_->probe_type(ent, scope);
errors += base_->elaborate_expr(ent, scope, sub_type);
return errors;
if(name_ == "image")
return &primitive_STRING;
return NULL;
}
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 ExpInteger(1));
std::list<prange_t*> ranges;
ranges.push_front(new prange_t(size, new ExpInteger(0), true));
std::list<ExpRange*> ranges;
ranges.push_front(new ExpRange(size, new ExpInteger(0), ExpRange::DOWNTO));
const VType*array = new VTypeArray(types[1], &ranges);
return array;
@ -912,31 +931,31 @@ const VType* ExpName::probe_type(Entity*ent, ScopeBase*scope) const
if(ent) {
if (const InterfacePort*cur = ent->find_port(name_)) {
ivl_assert(*this, cur->type);
return cur->type;
ivl_assert(*this, cur->type);
return cur->type;
}
if (const InterfacePort*cur = ent->find_generic(name_)) {
ivl_assert(*this, cur->type);
return cur->type;
ivl_assert(*this, cur->type);
return cur->type;
}
}
if(scope) {
if (Signal*sig = scope->find_signal(name_))
return sig->peek_type();
return sig->peek_type();
if (Variable*var = scope->find_variable(name_))
return var->peek_type();
return var->peek_type();
const VType*type = 0;
Expression*cval = 0;
if (scope->find_constant(name_, type, cval))
return type;
return type;
Architecture*arc = dynamic_cast<Architecture*>(scope);
if (arc && (type = arc->probe_genvar_type(name_))) {
return type;
return type;
}
if (const InterfacePort*port = scope->find_param(name_)) {
@ -1048,6 +1067,19 @@ int ExpTime::elaborate_expr(Entity*, ScopeBase*, const VType*)
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 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
// of the range and scan through the values, mapping the
// 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;
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;
}
int ExpAttribute::emit(ostream&out, Entity*ent, ScopeBase*scope)
int ExpObjAttribute::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
// Try to evaluate first
int64_t val;
if(evaluate(scope, val)) {
if(evaluate(ent, scope, val)) {
out << val;
return 0;
}
@ -365,12 +365,50 @@ int ExpAttribute::emit(ostream&out, Entity*ent, ScopeBase*scope)
return errors;
}
// Fallback
out << "$ivl_attribute(";
errors += base_->emit(out, ent, scope);
out << ", \"" << name_ << "\")";
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 errors = 0;
@ -453,17 +491,16 @@ int ExpCharacter::emit_primitive_bit_(ostream&out, Entity*, ScopeBase*,
int ExpCharacter::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
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)) {
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_ << "\"";
return 0;
}
@ -583,7 +620,10 @@ int ExpFunc::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
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
// 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)
{
const VTypeArray*arr;
const VType*type = peek_type();
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);
}
@ -1028,3 +1069,25 @@ int ExpTime::emit(ostream&out, Entity*, ScopeBase*)
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 <cmath>
bool Expression::evaluate(ScopeBase*, int64_t&) 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
bool ExpArithmetic::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const
{
int64_t val1, val2;
bool rc;
rc = eval_operand1(scope, val1);
rc = eval_operand1(ent, scope, val1);
if (rc == false)
return false;
rc = eval_operand2(scope, val2);
rc = eval_operand2(ent, scope, val2);
if (rc == false)
return false;
@ -83,151 +73,110 @@ bool ExpArithmetic::evaluate(ScopeBase*scope, int64_t&val) const
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
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();
const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type);
if(!base_type) {
const ExpName*name = NULL;
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(scope && (name = dynamic_cast<const ExpName*>(base_))) {
const perm_string& n = name->peek_name();
if(const Variable*var = scope->find_variable(n))
base_type = var->peek_type();
else if(const Signal*sig = scope->find_signal(n))
base_type = sig->peek_type();
else if(const InterfacePort*port = scope->find_param(n))
base_type = port->type;
}
}
if (arr->dimensions() > 1) {
cerr << endl << get_fileline() << ": error: "
<< "Cannot apply the '" << name_
<< " attribute to multidimensional arrays" << endl;
return false;
}
if(!base_type)
return false; // I tried really hard, sorry
if (arr->dimension(0).is_box())
return false;
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;
}
return true;
}
if(name_ == "length") {
int64_t size = arr->get_width(scope);
bool ExpAttribute::evaluate_type_attr(const VType*type, Entity*ent, ScopeBase*scope, int64_t&val) const
{
if (name_ == "length" && test_array_type(type)) {
int64_t size = type->get_width(scope);
if(size > 0)
val = size;
else
return false;
} else if(name_ == "left") {
arr->dimension(0).msb()->evaluate(scope, val);
} else if(name_ == "right") {
arr->dimension(0).lsb()->evaluate(scope, val);
} else ivl_assert(*this, false);
return true;
if(size > 0) {
val = size;
return true;
}
} else if (name_ == "left" && test_array_type(type)) {
const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type);
return arr->dimension(0).msb()->evaluate(ent, scope, val);
} else if (name_ == "right" && test_array_type(type)) {
const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type);
return arr->dimension(0).lsb()->evaluate(ent, scope, val);
}
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
return false;
}
const VType*base_type = base_->peek_type();
if (name_ == "left" || name_ == "right") {
const VType*base_type = base_->peek_type();
if (base_type == 0)
base_type = base_->probe_type(ent, scope);
if (base_type == NULL)
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;
}
bool ExpName::evaluate(ScopeBase*scope, int64_t&val) const
bool ExpTypeAttribute::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const
{
const VType*type;
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);
return evaluate_type_attr(base_, ent, scope, val);
}
bool ExpName::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const
{
if (prefix_.get()) {
cerr << get_fileline() << ": sorry: I don't know how to evaluate ExpName prefix parts." << endl;
return false;
cerr << get_fileline() << ": sorry: I don't know how to evaluate "
<< "ExpName prefix parts." << endl;
return false;
}
const InterfacePort*gen = ent->find_generic(name_);
if (gen) {
cerr << get_fileline() << ": sorry: I don't necessarily handle generic overrides." << endl;
if (ent) {
const InterfacePort*gen = ent->find_generic(name_);
if (gen) {
cerr << get_fileline() << ": sorry: I don't necessarily "
<< "handle generic overrides." << endl;
// Evaluate the default expression and use that.
if (gen->expr)
return gen->expr->evaluate(ent, scope, val);
// Evaluate the default expression and use that.
if (gen->expr)
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;
bool rc;
rc = eval_operand1(scope, val1);
rc = eval_operand1(ent, scope, val1);
if (rc == false)
return false;
rc = eval_operand2(scope, val2);
rc = eval_operand2(ent, scope, val2);
if (rc == false)
return false;
@ -252,7 +201,7 @@ bool ExpShift::evaluate(ScopeBase*scope, int64_t&val) const
return true;
}
/*bool ExpTime::evaluate(ScopeBase*, int64_t&val) const
/*bool ExpTime::evaluate(Entity*, ScopeBase*, int64_t&val) const
{
double v = to_fs();
@ -265,8 +214,4 @@ bool ExpShift::evaluate(ScopeBase*scope, int64_t&val) const
val = v;
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;
}
if (prange_t*rp = range_expressions()) {
rp->msb()->write_to_stream(fd);
if (rp->is_downto())
fd << " downto ";
else
fd << " to ";
rp->msb()->write_to_stream(fd);
if (ExpRange*rp = range_expressions()) {
rp->write_to_stream(fd);
return;
}
fd << "/* ERROR */";
@ -111,7 +107,13 @@ void ExpArithmetic::write_to_stream(ostream&out) const
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);
fd << "'" << name_;
@ -316,3 +318,19 @@ void ExpTime::write_to_stream(ostream&fd) const
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;
}
static int elaborate_library_packages(map<perm_string,Package*>packages)
{
int errors = 0;
for (map<perm_string,Package*>::iterator cur = packages.begin()
; cur != packages.end() ; ++cur) {
errors += cur->second->elaborate();
}
return errors;
}
int elaborate_libraries()
{
int errors = 0;
for (map<perm_string,struct library_contents>::iterator cur = libraries.begin()
; cur != libraries.end() ; ++cur) {
errors += elaborate_library_packages(cur->second.packages);
}
return errors;
}

View File

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

View File

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

View File

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

View File

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

View File

@ -87,10 +87,6 @@ static ActiveScope*active_scope = new ActiveScope;
static stack<ActiveScope*> scope_stack;
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
* 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;
prange_t* range;
std::list<prange_t*>*range_list;
ExpRange*range;
std::list<ExpRange*>*range_list;
ExpRange::range_dir_t range_dir;
ExpArithmetic::fun_t arithmetic_op;
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. */
%type <flag> direction
%type <arithmetic_op> adding_operator
%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_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> selected_names use_clause
@ -372,6 +367,7 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
%type <range> range
%type <range_list> range_list index_constraint
%type <range_dir> direction
%type <case_alt> case_statement_alternative
%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
: K_assert expression report_statement
{ ReportStmt*report = dynamic_cast<ReportStmt*>($3);
assert(report);
AssertStmt*tmp = new AssertStmt($2, report->message().c_str(), report->severity());
AssertStmt*tmp = new AssertStmt($2, report->message(), report->severity());
delete report;
FILE_NAME(tmp,@2);
$$ = tmp;
@ -752,8 +755,9 @@ composite_type_definition
/* unbounded_array_definition IEEE 1076-2008 P5.3.2.1 */
| K_array '(' index_subtype_definition_list ')' K_of subtype_indication
{ std::list<prange_t*> r;
r.push_back(new prange_t(NULL, NULL, true)); // NULL boundaries indicate unbounded array type
{ std::list<ExpRange*> r;
// NULL boundaries indicate unbounded array type
r.push_back(new ExpRange(NULL, NULL, ExpRange::DOWNTO));
VTypeArray*tmp = new VTypeArray($6, &r);
$$ = tmp;
}
@ -983,8 +987,10 @@ design_units
| design_unit
;
/* Indicate the direction as a flag, with "downto" being TRUE. */
direction : K_to { $$ = false; } | K_downto { $$ = true; } ;
direction
: K_to { $$ = ExpRange::TO; }
| K_downto { $$ = ExpRange::DOWNTO; }
;
element_association
: choices ARROW expression
@ -1258,8 +1264,8 @@ file_declaration
// add file_open() call in 'initial' block
params.push_back(new ExpName(*cur));
params.push_back($5->filename());
params.push_back($5->kind());
params.push_back($5->filename()->clone());
params.push_back($5->kind()->clone());
ProcedureCall*fopen_call = new ProcedureCall(perm_string::literal("file_open"), &params);
active_scope->add_initializer(fopen_call);
@ -1268,6 +1274,8 @@ file_declaration
params.push_back(new ExpName(*cur));
ProcedureCall*fclose_call = new ProcedureCall(perm_string::literal("file_close"), &params);
active_scope->add_finalizer(fclose_call);
delete $5;
}
}
@ -1498,7 +1506,7 @@ index_constraint
| '(' error ')'
{ errormsg(@2, "Errors in the index constraint.\n");
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
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. */
| IDENTIFIER '(' expression_list ')'
| IDENTIFIER argument_list
{ perm_string name = lex_strings.make($1);
delete[]$1;
if (active_scope->is_vector_name(name) || is_subprogram_param(name)) {
ExpName*tmp = new ExpName(name, $3);
ExpName*tmp = new ExpName(name, $2);
$$ = tmp;
} else {
ExpFunc*tmp = new ExpFunc(name, $3);
ExpFunc*tmp = new ExpFunc(name, $2);
$$ = tmp;
}
FILE_NAME($$, @1);
@ -1876,10 +1884,18 @@ prefix /* IEEE 1076-2008 P8.1 */
primary
: name
{ $$ = $1; }
| name '\'' IDENTIFIER
{ perm_string name = lex_strings.make($3);
ExpName*base = dynamic_cast<ExpName*> ($1);
ExpAttribute*tmp = new ExpAttribute(base, name);
| name '\'' IDENTIFIER argument_list_opt
{ ExpAttribute*tmp = NULL;
perm_string attr = lex_strings.make($3);
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);
delete[]$3;
$$ = tmp;
@ -1980,11 +1996,11 @@ procedure_call
delete[] $1;
$$ = 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 $3; // parameters are copied in this variant
delete $2; // parameters are copied in this variant
$$ = tmp;
}
| IDENTIFIER '(' error ')' ';'
@ -2096,18 +2112,15 @@ process_sensitivity_list
range
: simple_expression direction simple_expression
{ prange_t* tmp = new prange_t($1, $3, $2);
{ ExpRange* tmp = new ExpRange($1, $3, $2);
$$ = tmp;
}
| name '\'' K_range
{
prange_t*tmp = NULL;
ExpRange*tmp = NULL;
ExpName*name = NULL;
if((name = dynamic_cast<ExpName*>($1))) {
ExpAttribute*left = new ExpAttribute(name, left_attr);
ExpAttribute*right = new ExpAttribute(name, right_attr);
tmp = new prange_t(left, right, true);
tmp->set_auto_dir();
tmp = new ExpRange(name, false);
} else {
errormsg(@1, "'range attribute can be used with named expressions only");
}
@ -2115,13 +2128,10 @@ range
}
| name '\'' K_reverse_range
{
prange_t*tmp = NULL;
ExpRange*tmp = NULL;
ExpName*name = NULL;
if((name = dynamic_cast<ExpName*>($1))) {
ExpAttribute*left = new ExpAttribute(name, left_attr);
ExpAttribute*right = new ExpAttribute(name, right_attr);
tmp = new prange_t(left, right, false);
tmp->set_auto_dir();
tmp = new ExpRange(name, true);
} else {
errormsg(@1, "'reverse_range attribute can be used with named expressions only");
}
@ -2131,12 +2141,12 @@ range
range_list
: range
{ list<prange_t*>*tmp = new list<prange_t*>;
{ list<ExpRange*>*tmp = new list<ExpRange*>;
tmp->push_back($1);
$$ = tmp;
}
| range_list ',' range
{ list<prange_t*>*tmp = $1;
{ list<ExpRange*>*tmp = $1;
tmp->push_back($3);
$$ = tmp;
}
@ -2185,10 +2195,9 @@ relation
;
report_statement
: K_report STRING_LITERAL severity_opt ';'
: K_report expression severity_opt ';'
{ ReportStmt*tmp = new ReportStmt($2, $3);
FILE_NAME(tmp,@2);
delete[]$2;
$$ = 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,
ScopeBase*scope, list<prange_t*>*ranges)
ScopeBase*scope, list<ExpRange*>*ranges)
{
if (ranges->size() == 1) {
prange_t*tmpr = ranges->front();
Expression*lef = tmpr->expr_left();
Expression*rig = tmpr->expr_right();
ExpRange*tmpr = ranges->front();
Expression*lef = tmpr->left();
Expression*rig = tmpr->right();
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");
@ -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,
ScopeBase*scope,
Expression*range_left,
bool downto,
int direction,
Expression*range_right)
{
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)) {
subtype = new VTypeRangeConst(base_type, left_val, right_val);
} else {
subtype = new VTypeRangeExpr(base_type, range_left, range_right, downto);
subtype = new VTypeRangeExpr(base_type, range_left, range_right, direction);
}
return subtype;

View File

@ -26,7 +26,7 @@ class ActiveScope;
class Architecture;
class Expression;
class Package;
class prange_t;
class ExpRange;
class ScopeBase;
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,
ScopeBase*scope,
std::list<prange_t*>*ranges);
std::list<ExpRange*>*ranges);
extern const VType* calculate_subtype_range(const YYLTYPE&loc, const char*base_name,
ScopeBase*scope,
Expression*range_left,
bool downto,
int direction,
Expression*range_right);
/*

View File

@ -26,7 +26,8 @@
class named_expr_t {
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_; }
Expression* expr() const { return expr_; }
@ -68,35 +69,6 @@ class instant_list_t {
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 {
ExpArithmetic::fun_t op;
Expression*term;

View File

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

View File

@ -90,6 +90,8 @@ class ScopeBase {
finalizers_.push_back(s);
}
void dump_scope(ostream&out) const;
protected:
void cleanup();
@ -154,9 +156,6 @@ class Scope : public ScopeBase {
ComponentBase* find_component(perm_string by_name);
public:
void dump_scope(ostream&out) const;
protected:
// Helper method for emitting signals in the scope.
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();
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();
delete cur;
}
delete param_list_;
}
ReturnStmt::ReturnStmt(Expression*val)
@ -238,7 +240,7 @@ void LoopStatement::visit(SeqStmtVisitor& func)
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)
{
}
@ -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)
{
if(sev == ReportStmt::UNSPECIFIED)
severity_ = ReportStmt::NOTE;
}
AssertStmt::AssertStmt(Expression*condition, const char*msg, ReportStmt::severity_t sev)
: ReportStmt("", sev), cond_(condition)
AssertStmt::AssertStmt(Expression*condition, Expression*msg, ReportStmt::severity_t sev)
: ReportStmt(msg, sev), cond_(condition)
{
if(msg == NULL)
msg_ = default_msg_;
else
msg_ = std::string(msg);
msg_ = new ExpString(default_msg_);
if(sev == ReportStmt::UNSPECIFIED)
severity_ = ReportStmt::ERROR;
}
const std::string AssertStmt::default_msg_ = std::string("Assertion violation.");
const char*AssertStmt::default_msg_ = "Assertion violation.";
WaitForStmt::WaitForStmt(Expression*delay)
: delay_(delay)

View File

@ -250,7 +250,7 @@ class WhileLoopStatement : public LoopStatement {
class ForLoopStatement : public LoopStatement {
public:
ForLoopStatement(perm_string loop_name,
perm_string index, prange_t*, list<SequentialStmt*>*);
perm_string index, ExpRange*, list<SequentialStmt*>*);
~ForLoopStatement();
int elaborate(Entity*ent, ScopeBase*scope);
@ -264,7 +264,7 @@ class ForLoopStatement : public LoopStatement {
int emit_runtime_(ostream&out, Entity*ent, ScopeBase*scope);
perm_string it_;
prange_t* range_;
ExpRange* range_;
};
class BasicLoopStatement : public LoopStatement {
@ -280,24 +280,27 @@ class ReportStmt : public SequentialStmt {
public:
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() {}
void dump(ostream&out, int indent) const;
int elaborate(Entity*ent, ScopeBase*scope);
int emit(ostream&out, Entity*entity, ScopeBase*scope);
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_; }
protected:
std::string msg_;
void dump_sev_msg(ostream&out, int indent) const;
Expression*msg_;
severity_t severity_;
};
class AssertStmt : public ReportStmt {
public:
AssertStmt(Expression*condition, const char*message,
AssertStmt(Expression*condition, Expression*message,
ReportStmt::severity_t severity = ReportStmt::ERROR);
void dump(ostream&out, int indent) const;
@ -309,7 +312,7 @@ class AssertStmt : public ReportStmt {
Expression*cond_;
// Message displayed when there is no report assigned.
static const std::string default_msg_;
static const char*default_msg_;
};
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
{
out << setw(indent) << "" << "ReportStmt at file=" << get_fileline() << endl;
out << setw(indent+3) << "" << "severity: " << severity_ << endl;
out << setw(indent+3) << "" << "message: " << msg_ << endl;
dump_sev_msg(out, indent+3);
}
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
{
out << setw(indent) << "" << "AssertStmt at file=" << get_fileline() << endl;
out << setw(indent+3) << "" << "condition: ";
cond_->dump(out, indent+3);
ReportStmt::dump(out, indent+3);
dump_sev_msg(out, indent+3);
}
void WaitForStmt::dump(ostream&out, int indent) const

View File

@ -217,9 +217,17 @@ int BasicLoopStatement::elaborate(Entity*, ScopeBase*)
return 0;
}
int ReportStmt::elaborate(Entity*ent, ScopeBase*scope)
{
return msg_->elaborate_expr(ent, scope, &primitive_STRING);
}
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)

View File

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

View File

@ -46,20 +46,20 @@ const VTypeArray primitive_UNSIGNED(&primitive_STDLOGIC, vector<VTypeArra
void generate_global_types(ActiveScope*res)
{
// boolean
list<perm_string>*enum_BOOLEAN_vals = new list<perm_string>;
enum_BOOLEAN_vals->push_back(perm_string::literal("false"));
enum_BOOLEAN_vals->push_back(perm_string::literal("true"));
VTypeEnum*enum_BOOLEAN = new VTypeEnum(enum_BOOLEAN_vals);
list<perm_string> enum_BOOLEAN_vals;
enum_BOOLEAN_vals.push_back(perm_string::literal("false"));
enum_BOOLEAN_vals.push_back(perm_string::literal("true"));
VTypeEnum*enum_BOOLEAN = new VTypeEnum(&enum_BOOLEAN_vals);
type_BOOLEAN.set_definition(enum_BOOLEAN);
std_types[type_BOOLEAN.peek_name()] = &type_BOOLEAN;
std_enums.push_back(enum_BOOLEAN);
// file_open_kind
list<perm_string>*enum_FILE_OPEN_KIND_vals = new list<perm_string>;
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("append_mode"));
VTypeEnum*enum_FILE_OPEN_KIND = new VTypeEnum(enum_FILE_OPEN_KIND_vals);
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("write_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);
type_FILE_OPEN_KIND.set_definition(enum_FILE_OPEN_KIND);
std_types[type_FILE_OPEN_KIND.peek_name()] = &type_FILE_OPEN_KIND;
std_enums.push_back(enum_FILE_OPEN_KIND);
@ -80,10 +80,12 @@ void delete_global_types()
{
typedef_context_t typedef_ctx;
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;
}
// std_enums are destroyed above
}
const VTypeEnum*find_std_enum_name(perm_string name)

View File

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

View File

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

View File

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

View File

@ -72,8 +72,7 @@ int Variable::emit(ostream&out, Entity*ent, ScopeBase*scope)
VType::decl_t 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());
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.
* FIXME: We are copying pointers from the prange_t object into the
* range_t. This means that we cannot delete the prange_t object
* FIXME: We are copying pointers from the ExpRange object into the
* range_t. This means that we cannot delete the ExpRange object
* unless we invent a way to remove the pointers from that object. So
* 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)
{
for (size_t idx = 0 ; idx < ranges_.size() ; idx += 1) {
prange_t*curp = r->front();
ExpRange*curp = r->front();
r->pop_front();
Expression*msb = curp->msb();
Expression*lsb = curp->lsb();
bool dir = curp->is_downto();
ranges_[idx] = range_t(msb, lsb, dir);
ranges_[idx] = range_t(curp->msb(), curp->lsb(), curp->direction());
}
}

View File

@ -33,7 +33,7 @@ class Architecture;
class ScopeBase;
class Entity;
class Expression;
class prange_t;
class ExpRange;
class VTypeDef;
class ScopeBase;
@ -210,7 +210,7 @@ class VTypeArray : public VType {
public:
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();

View File

@ -169,10 +169,11 @@ static int get_default_format(const char *name)
int default_format;
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 'r':
case 't':
case 'f':
case 'y': default_format = vpiDecStrVal; break;
case 'h': default_format = vpiHexStrVal; 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':
*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) {
vpi_printf("WARNING: %s:%d: missing argument for %s%s.\n",
info->filename, info->lineno, info->name, fmtb);
@ -647,6 +644,29 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus,
} else {
char *tbuf;
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 suff_len = strlen(timeformat_info.suff);
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);
}
/* 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)
{
vpiHandle callh, argv, scope;
@ -1246,6 +1267,7 @@ static PLI_INT32 sys_display_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name)
char* result;
unsigned int size;
PLI_UINT32 fd_mcd;
s_vpi_value val;
callh = vpi_handle(vpiSysTfCall, 0);
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') {
errno = 0;
vpiHandle arg = vpi_scan(argv);
s_vpi_value val;
val.format = vpiIntVal;
vpi_get_value(arg, &val);
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);
return 0;
}
} else if(strncmp(name,"$sformatf",9) == 0) {
/* return as a string */
fd_mcd = 0;
} else {
/* stdout */
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
* returned string strlen() may not match the real size! */
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.items);
free(result);
return 0;
}
@ -1665,7 +1698,7 @@ static PLI_INT32 sys_sformat_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name)
if (argv == 0) {
vpi_printf("ERROR:%s:%d: ", vpi_get_str(vpiFile, 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);
return 0;
}
@ -1686,7 +1719,7 @@ static PLI_INT32 sys_sformat_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name)
if (arg == 0) {
vpi_printf("ERROR:%s:%d: ", vpi_get_str(vpiFile, 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);
return 0;
}
@ -1754,6 +1787,46 @@ static PLI_INT32 sys_sformat_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name)
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)
{
(void)cb_data; /* Parameter is not used. */
@ -2434,6 +2507,16 @@ void sys_display_register(void)
res = vpi_register_systf(&tf_data);
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 */
tf_data.type = vpiSysTask;
tf_data.tfname = "$timeformat";

View File

@ -24,3 +24,5 @@ $table_model vpiSysFuncReal
$ivl_string_method$len vpiSysFuncInt
$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_func <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
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_func" { return K_vpi_func; }
"%vpi_func/r" { return K_vpi_func_r; }
"%vpi_func/s" { return K_vpi_func_s; }
"%file_line" { return K_file_line; }
/* 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/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
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_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_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_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
@ -658,6 +658,10 @@ statement
{ compile_vpi_func_call($1, $5, -vpiRealVal, 0, $3, $4,
$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
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 {
inline systask_def() { }
int get_type_code(void) const { return vpiSysTaskCall; }
int vpi_get(int code) { return systask_get(code, this); }
char*vpi_get_str(int code) { return systask_get_str(code, this); }
vpiHandle vpi_handle(int code) { return systask_handle(code, this); }
vpiHandle vpi_iterate(int code){ return systask_iter(code, this); }
virtual ~systask_def() {};
virtual int get_type_code(void) const { return vpiSysTaskCall; }
virtual int vpi_get(int code) { return systask_get(code, this); }
virtual char*vpi_get_str(int code) { return systask_get_str(code, this); }
virtual vpiHandle vpi_handle(int code) { return systask_handle(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 __vpiSysTaskCall*rfp = dynamic_cast<__vpiSysTaskCall*>(ref);
struct sysfunc_def : public systask_def {
virtual ~sysfunc_def() {};
virtual int get_type_code(void) const { return vpiSysFuncCall; }
virtual int vpi_get(int code) { return sysfunc_get(code, this); }
};
rfp->put_value = true;
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); }
struct sysfunc_real : public sysfunc_def {
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 double return_value() const { return return_value_; }
private:
double return_value_;
};
@ -211,18 +182,53 @@ vpiHandle sysfunc_real::vpi_put_value(p_vpi_value vp, int)
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:
explicit inline sysfunc_vec4(unsigned wid): return_value_(wid, BIT4_X) { }
int get_type_code(void) const { return vpiSysFuncCall; }
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_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_; }
private:
@ -232,7 +238,6 @@ class sysfunc_vec4 : public __vpiSysTaskCall {
vpiHandle put_value_vector_(p_vpi_value vp);
vpiHandle put_value_time_(p_vpi_value vp);
private:
vvp_vector4_t return_value_;
};
@ -388,48 +393,15 @@ vpiHandle sysfunc_vec4::vpi_put_value(p_vpi_value vp, int)
return 0;
}
struct sysfunc_4net : public __vpiSysTaskCall {
struct sysfunc_4net : public sysfunc_def {
explicit inline sysfunc_4net(unsigned wid) : vwid_(wid) { }
int get_type_code(void) const { return vpiSysFuncCall; }
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_handle(int code)
{ return systask_handle(code, this); }
vpiHandle vpi_iterate(int code)
{ return systask_iter(code, this); }
private:
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
int sysfunc_4net::vpi_get(int code)
{
@ -547,6 +519,41 @@ vpiHandle sysfunc_4net::vpi_put_value(p_vpi_value vp, int)
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. **** */
@ -845,6 +852,9 @@ vpiHandle vpip_build_vpi_call(const char*name, int val_code, unsigned return_wid
} else if (val_code == -vpiVectorVal) {
obj = new sysfunc_vec4(return_width);
} else if (val_code == -vpiStringVal) {
obj = new sysfunc_str;
} else if (val_code == 0 && fnet == 0) {
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)
vthread_pop_str(thr, vpip_cur_task->string_stack);
/* If the function has a real value, then push the value
to the thread stack. */
/* If the function returns a value, then push the value
to the appropriate thread stack. */
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());
}
}

View File

@ -346,6 +346,11 @@ void vthread_push_real(struct vthread_s*thr, double 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)
{
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.
*/
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_pop_vec4(struct vthread_s*thr, unsigned count);