commit
2a210dfee1
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 << ")";
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue