Merge pull request #56 from orsonmmz/expfunc

Expfunc
This commit is contained in:
Stephen Williams 2015-03-27 17:44:13 -07:00
commit 2a210dfee1
12 changed files with 200 additions and 44 deletions

View File

@ -1078,7 +1078,7 @@ unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope,
if (name=="$ivlh_to_unsigned") {
ivl_assert(*this, parms_.size() == 2);
// The Icarus Verilog specific $ivl_unsigned() system
// The Icarus Verilog specific $ivlh_to_unsigned() system
// task takes a second argument which is the output
// size. This can be an arbitrary constant function.
PExpr*pexpr = parms_[1];
@ -1100,6 +1100,8 @@ unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope,
bool rc = eval_as_long(value, nexpr);
ivl_assert(*this, rc && value>=0);
parms_[0]->test_width(des, scope, mode);
expr_width_ = value;
signed_flag_= false;
return expr_width_;

View File

@ -1138,18 +1138,29 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root)
if (sub->vector_width() == expr_width())
return sub;
// The vector_width is not exactly right, so the source is
// probably asking for padding. Create nodes to do sign
// extension or 0 extension, depending on the has_sign() mode
// of the expression.
netvector_t*net_vec = new netvector_t(expr_type(), expr_width()-1, 0);
net_vec->set_signed(has_sign());
NetNet*net = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, net_vec);
net->set_line(*this);
net->local_flag(true);
if (has_sign()) {
// It may still happen that the expression is wider than the selection,
// and there was no part select created earlier (size casting).
if(expr_width() < sub->vector_width()) {
NetPartSelect*sel = new NetPartSelect(sub, 0, expr_width(),
NetPartSelect::VP, has_sign());
sel->set_line(*this);
des->add_node(sel);
connect(net->pin(0), sel->pin(0));
// The vector_width is not exactly right, so the source is
// probably asking for padding. Create nodes to do sign
// extension or 0 extension, depending on the has_sign() mode
// of the expression.
} else if (has_sign()) {
NetSignExtend*pad = new NetSignExtend(scope,
scope->local_symbol(),
expr_width());
@ -1166,7 +1177,6 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root)
cat->set_line(*this);
des->add_node(cat);
assert(expr_width() > sub->vector_width());
unsigned pad_width = expr_width() - sub->vector_width();
verinum pad((uint64_t)0, pad_width);
NetConst*con = new NetConst(scope, scope->local_symbol(),

View File

@ -1,6 +1,7 @@
/*
* Copyright (c) 2011 Stephen Williams (steve@icarus.com)
* Copyright (c) 2014 CERN / Maciej Suminski (maciej.suminski@cern.ch)
* Copyright (c) 2014 CERN
* @author Maciej Suminski (maciej.suminski@cern.ch)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU

View File

@ -1,7 +1,7 @@
/*
* Copyright (c) 2011-2013 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012-2015 / Stephen Williams (steve@icarus.com),
* Maciej Suminski (maciej.suminski@cern.ch)
* @author Maciej Suminski (maciej.suminski@cern.ch)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU

View File

@ -3,7 +3,7 @@
/*
* Copyright (c) 2011-2014 Stephen Williams (steve@icarus.com)
* Copyright CERN 2015 / Stephen Williams (steve@icarus.com),
* Maciej Suminski (maciej.suminski@cern.ch)
* @author Maciej Suminski (maciej.suminski@cern.ch)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -516,12 +516,14 @@ class ExpFunc : public Expression {
Expression*clone() const;
const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const;
inline perm_string func_name() const { return name_; }
inline size_t func_args() const { return argv_.size(); }
inline const Expression*func_arg(size_t idx) const { return argv_[idx]; }
const VType*func_ret_type() const;
public: // Base methods
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;
int emit(ostream&out, Entity*ent, ScopeBase*scope);

View File

@ -80,11 +80,7 @@ const VType*ExpName::elaborate_adjust_type_with_range_(Entity*, ScopeBase*scope,
flag = lsb_->evaluate(scope, use_lsb);
ivl_assert(*this, flag);
Expression*exp_msb = new ExpInteger(use_msb);
Expression*exp_lsb = new ExpInteger(use_lsb);
vector<VTypeArray::range_t> use_dims (1);
use_dims[0] = VTypeArray::range_t(exp_msb, exp_lsb);
type = new VTypeArray(array->element_type(), use_dims);
type = new VTypeArray(array->element_type(), use_msb, use_lsb);
}
}
@ -600,9 +596,7 @@ const VType*ExpBitstring::fit_type(Entity*, ScopeBase*, const VTypeArray*atype)
int ExpBitstring::elaborate_expr(Entity*, ScopeBase*, const VType*)
{
int errors = 0;
std::vector<VTypeArray::range_t> range;
range.push_back(VTypeArray::range_t(new ExpInteger(value_.size() - 1), new ExpInteger(0)));
const VTypeArray*type = new VTypeArray(&primitive_STDLOGIC, range);
const VTypeArray*type = new VTypeArray(&primitive_STDLOGIC, value_.size() - 1, 0);
set_type(type);
return errors;
}
@ -750,6 +744,56 @@ int ExpConditional::else_t::elaborate_expr(Entity*ent, ScopeBase*scope, const VT
return errors;
}
const VType*ExpFunc::probe_type(Entity*ent, ScopeBase*scope) const
{
if(name_ == "integer")
return &primitive_INTEGER;
if(name_ == "unsigned" || name_ == "resize") {
if(argv_.empty())
return NULL;
const VType*type = argv_[0]->probe_type(ent, scope);
if(!type)
return NULL;
int msb = type->get_width(scope) - 1;
ivl_assert(*this, msb >= 0);
// Determine the sign
bool sign = false;
if(name_ == "resize") {
if(const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type))
sign = arr->signed_vector();
}
return new VTypeArray(&primitive_BIT, msb, 0, sign);
}
if(name_ == "std_logic_vector" || name_ == "conv_std_logic_vector") {
if(argv_.empty())
return NULL;
const VType*type = argv_[0]->probe_type(ent, scope);
if(!type)
return NULL;
int msb = type->get_width(scope) - 1;
return new VTypeArray(&primitive_STDLOGIC, msb, 0);
}
Subprogram*prog = scope->find_subprogram(name_);
if(!prog)
prog = library_find_subprogram(name_);
if(!prog)
return NULL;
return prog->peek_return_type();
}
int ExpFunc::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*)
{
int errors = 0;
@ -782,6 +826,73 @@ int ExpFunc::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*)
return errors;
}
const VType* ExpFunc::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*) const
{
// Built-in functions
if(name_ == "to_integer" || name_ == "unsigned" || name_ == "integer") {
ivl_assert(*this, argv_.size() == 1);
const VType*type = argv_[0]->probe_type(ent, scope);
ivl_assert(*this, type);
// Determine the sign
bool sign = false;
if(name_ == "integer") {
sign = true;
} else if(name_ == "to_integer") {
if(const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type))
sign = arr->signed_vector();
}
return new VTypeArray(&primitive_BIT, type->get_width(scope), 0, sign);
}
if(name_ == "to_unsigned" || name_ == "std_logic_vector" ||
name_ == "conv_std_logic_vector" || name_ == "resize")
{
ivl_assert(*this, argv_.size() == 2);
// Determine the sign
bool sign = false;
const VType*element = &primitive_STDLOGIC;
if(name_ == "resize") {
const VType*type = argv_[0]->probe_type(ent, scope);
ivl_assert(*this, type);
if(const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type))
{
sign = arr->signed_vector();
element = arr->element_type();
}
} else if(name_ == "to_unsigned") {
element = &primitive_BIT;
}
int64_t width = 0;
bool evaluated = argv_[1]->evaluate(scope, width);
ivl_assert(*this, evaluated);
return new VTypeArray(element, width, 0, sign);
}
// Other cases
Subprogram*prog = def_;
if(!prog) {
ivl_assert(*this, scope);
prog = scope->find_subprogram(name_);
}
if(!prog)
prog = library_find_subprogram(name_);
ivl_assert(*this, prog);
return def_->peek_return_type();
}
const VType* ExpInteger::probe_type(Entity*, ScopeBase*) const
{
return &primitive_INTEGER;
@ -871,6 +982,13 @@ const VType* ExpName::probe_prefixed_type_(Entity*ent, ScopeBase*scope) const
return element_type;
}
if (const VTypeArray*pref_array = dynamic_cast<const VTypeArray*> (prefix_type)) {
const VType*element_type = pref_array->element_type();
ivl_assert(*this, element_type);
return element_type;
}
cerr << get_fileline() << ": sorry: I don't know how to probe "
<< "prefix type " << typeid(*prefix_type).name()
<< " of " << name_ << "." << endl;
@ -991,13 +1109,8 @@ const VType*ExpString::fit_type(Entity*, ScopeBase*, const VTypeArray*atype) con
// Generate an array range for this string
ivl_assert(*this, range.size() == 1);
ExpInteger*use_msb = new ExpInteger(value_.size());
ExpInteger*use_lsb = new ExpInteger(0);
FILE_NAME(use_msb, this);
FILE_NAME(use_lsb, this);
range[0] = VTypeArray::range_t(use_msb, use_lsb);
VTypeArray*type = new VTypeArray(atype->element_type(), range);
VTypeArray*type = new VTypeArray(atype->element_type(), value_.size(), 0);
return type;
}

View File

@ -1,7 +1,7 @@
/*
* Copyright (c) 2011-2013 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012-2015 / Stephen Williams (steve@icarus.com)
* Maciej Suminski (maciej.suminski@cern.ch)
* @author Maciej Suminski (maciej.suminski@cern.ch)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -560,13 +560,7 @@ int ExpFunc::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
// SystemVerilog takes care of sign & width, depending on the lvalue type
if ((name_ == "to_integer" && argv_.size() == 1) ||
(name_ == "resize" && argv_.size() == 2)) {
errors += argv_[0]->emit(out, ent, scope);
}
else if (name_ == "unsigned" && argv_.size() == 1) {
if (name_ == "unsigned" && argv_.size() == 1) {
// Handle the special case that this is a cast to
// unsigned. This function is brought in as part of the
// std numeric library, but we interpret it as the same
@ -580,6 +574,25 @@ int ExpFunc::emit(ostream&out, Entity*ent, ScopeBase*scope)
errors += argv_[0]->emit(out, ent, scope);
out << ")";
} else if (name_ == "to_integer" && argv_.size() == 1) {
bool signed_flag = false;
// to_integer converts unsigned to natural
// signed to integer
// try to determine the converted type
const VType*type = argv_[0]->probe_type(ent, scope);
const VTypeArray*array = dynamic_cast<const VTypeArray*>(type);
if(array)
signed_flag = array->signed_vector();
else
cerr << get_fileline() << ": sorry: Could not determine the "
<< "expression sign. Output may be erroneous." << endl;
out << (signed_flag ? "$signed(" : "$unsigned(");
errors += argv_[0]->emit(out, ent, scope);
out << ")";
} else if (name_ == "std_logic_vector" && argv_.size() == 1) {
// Special case: The std_logic_vector function casts its
// argument to std_logic_vector. Internally, we don't
@ -596,7 +609,8 @@ int ExpFunc::emit(ostream&out, Entity*ent, ScopeBase*scope)
errors += argv_[1]->emit(out, ent, scope);
out << ")";
} else if (name_ == "conv_std_logic_vector" && argv_.size() == 2) {
} else if ((name_ == "conv_std_logic_vector" || name_ == "resize") &&
argv_.size() == 2) {
int64_t use_size;
bool rc = argv_[1]->evaluate(ent, scope, use_size);
ivl_assert(*this, rc);
@ -604,12 +618,12 @@ int ExpFunc::emit(ostream&out, Entity*ent, ScopeBase*scope)
errors += argv_[0]->emit(out, ent, scope);
out << ")";
} else if (name_ == "rising_edge" && argv_.size()==1) {
} else if (name_ == "rising_edge" && argv_.size() == 1) {
out << "$ivlh_rising_edge(";
errors += argv_[0]->emit(out, ent, scope);
out << ")";
} else if (name_ == "falling_edge" && argv_.size()==1) {
} else if (name_ == "falling_edge" && argv_.size() == 1) {
out << "$ivlh_falling_edge(";
errors += argv_[0]->emit(out, ent, scope);
out << ")";

View File

@ -8,7 +8,7 @@
/*
* Copyright (c) 2011-2013 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012-2014 / Stephen Williams (steve@icarus.com),
* Maciej Suminski (maciej.suminski@cern.ch)
* @author Maciej Suminski (maciej.suminski@cern.ch)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU

View File

@ -1,6 +1,7 @@
/*
* Copyright (c) 2011 Stephen Williams (steve@icarus.com)
* Copyright CERN 2014 / Maciej Suminski (maciej.suminski@cern.ch)
* Copyright CERN 2014
* @author Maciej Suminski (maciej.suminski@cern.ch)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU

View File

@ -93,6 +93,11 @@ int VTypePrimitive::get_width(ScopeBase*) const
case CHARACTER:
return 8;
default:
std::cerr << "sorry: primitive type " << type_ <<
" has no get_width() implementation." << std::endl;
break;
}
return -1;
@ -128,6 +133,12 @@ VTypeArray::VTypeArray(const VType*element, std::list<prange_t*>*r, bool sv)
}
}
VTypeArray::VTypeArray(const VType*element, int msb, int lsb, bool sv)
: etype_(element), ranges_(1), signed_flag_(sv), parent_(NULL)
{
bool down_to = msb > lsb;
ranges_[0] = range_t(new ExpInteger(msb), new ExpInteger(lsb), down_to);
}
VTypeArray::~VTypeArray()
{

View File

@ -3,7 +3,7 @@
/*
* Copyright (c) 2011-2014 Stephen Williams (steve@icarus.com)
* Copyright CERN 2014 / Stephen Williams (steve@icarus.com),
* Maciej Suminski (maciej.suminski@cern.ch)
* @author Maciej Suminski (maciej.suminski@cern.ch)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -199,8 +199,8 @@ class VTypeArray : public VType {
public:
class range_t {
public:
range_t(Expression*m = NULL, Expression*l = NULL, bool dir = true) :
msb_(m), lsb_(l), direction_(dir) { }
range_t(Expression*m = NULL, Expression*l = NULL, bool down_to = true) :
msb_(m), lsb_(l), direction_(down_to) { }
range_t*clone() const;
@ -217,8 +217,9 @@ 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, 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, int msb, int lsb, bool signed_vector = false);
~VTypeArray();
VType*clone() const;

View File

@ -1,6 +1,7 @@
/*
* Copyright (c) 2011-2012 Stephen Williams (steve@icarus.com)
* Copyright (c) 2014 CERN / Maciej Suminski (maciej.suminski@cern.ch)
* Copyright (c) 2014 CERN
* @author Maciej Suminski (maciej.suminski@cern.ch)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU