Merge branch 'master' into vec4-stack
This commit is contained in:
commit
fdc9e8590d
9
PExpr.cc
9
PExpr.cc
|
|
@ -540,6 +540,15 @@ bool PETernary::has_aa_term(Design*des, NetScope*scope) const
|
|||
|| fal_->has_aa_term(des, scope);
|
||||
}
|
||||
|
||||
PETypename::PETypename(data_type_t*dt)
|
||||
: data_type_(dt)
|
||||
{
|
||||
}
|
||||
|
||||
PETypename::~PETypename()
|
||||
{
|
||||
}
|
||||
|
||||
PEUnary::PEUnary(char op, PExpr*ex)
|
||||
: op_(op), expr_(ex)
|
||||
{
|
||||
|
|
|
|||
17
PExpr.h
17
PExpr.h
|
|
@ -660,6 +660,23 @@ class PEString : public PExpr {
|
|||
char*text_;
|
||||
};
|
||||
|
||||
class PETypename : public PExpr {
|
||||
public:
|
||||
explicit PETypename(data_type_t*data_type);
|
||||
~PETypename();
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
width_mode_t&mode);
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
ivl_type_t type, unsigned flags) const;
|
||||
|
||||
inline data_type_t* get_type() const { return data_type_; }
|
||||
|
||||
private:
|
||||
data_type_t*data_type_;
|
||||
};
|
||||
|
||||
class PEUnary : public PExpr {
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ void PFunction::push_statement_front(Statement*stmt)
|
|||
blk->push_statement_front(stmt);
|
||||
}
|
||||
|
||||
void PFunction::set_return(const data_type_t*t)
|
||||
void PFunction::set_return(data_type_t*t)
|
||||
{
|
||||
return_type_ = t;
|
||||
}
|
||||
|
|
|
|||
4
PTask.h
4
PTask.h
|
|
@ -114,7 +114,7 @@ class PFunction : public PTaskFunc {
|
|||
~PFunction();
|
||||
|
||||
void set_statement(Statement *s);
|
||||
void set_return(const data_type_t*t);
|
||||
void set_return(data_type_t*t);
|
||||
|
||||
inline Statement* get_statement() { return statement_; }
|
||||
|
||||
|
|
@ -141,7 +141,7 @@ class PFunction : public PTaskFunc {
|
|||
void dump(ostream&, unsigned) const;
|
||||
|
||||
private:
|
||||
const data_type_t* return_type_;
|
||||
data_type_t* return_type_;
|
||||
Statement *statement_;
|
||||
bool is_auto_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1313,9 +1313,9 @@ void NetScope::dump(ostream&o) const
|
|||
o << " enum sets {" << endl;
|
||||
|
||||
/* Dump the enumerations and enum names in this scope. */
|
||||
for (list<netenum_t*>::const_iterator cur = enum_sets_.begin()
|
||||
for (map<const enum_type_t*,netenum_t*>::const_iterator cur = enum_sets_.begin()
|
||||
; cur != enum_sets_.end() ; ++ cur) {
|
||||
o << " " << *cur << endl;
|
||||
o << " " << cur->second << endl;
|
||||
}
|
||||
o << " }" << endl;
|
||||
|
||||
|
|
|
|||
78
elab_expr.cc
78
elab_expr.cc
|
|
@ -188,7 +188,7 @@ NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, unsigned, unsigned) const
|
|||
* supported, can assign to packed arrays and structs, unpacked arrays
|
||||
* and dynamic arrays.
|
||||
*/
|
||||
unsigned PEAssignPattern::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
||||
unsigned PEAssignPattern::test_width(Design*, NetScope*, width_mode_t&)
|
||||
{
|
||||
expr_type_ = IVL_VT_DARRAY;
|
||||
expr_width_ = 1;
|
||||
|
|
@ -1078,10 +1078,14 @@ unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope,
|
|||
if (expr == 0)
|
||||
return 0;
|
||||
|
||||
// The argument type/width is self-determined and doesn't
|
||||
// affect the result type/width.
|
||||
width_mode_t arg_mode = SIZED;
|
||||
expr->test_width(des, scope, arg_mode);
|
||||
if (! dynamic_cast<PETypename*>(expr)) {
|
||||
// The argument type/width is self-determined and doesn't
|
||||
// affect the result type/width. Note that if the
|
||||
// argument is a type name (a special case) then
|
||||
// don't bother with this step.
|
||||
width_mode_t arg_mode = SIZED;
|
||||
expr->test_width(des, scope, arg_mode);
|
||||
}
|
||||
|
||||
expr_type_ = IVL_VT_BOOL;
|
||||
expr_width_ = integer_width;
|
||||
|
|
@ -1393,7 +1397,25 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope,
|
|||
|
||||
PExpr*expr = parms_[0];
|
||||
|
||||
verinum val ( (uint64_t)expr->expr_width(), integer_width);
|
||||
uint64_t use_width = 0;
|
||||
if (PETypename*type_expr = dynamic_cast<PETypename*>(expr)) {
|
||||
ivl_type_t tmp_type = type_expr->get_type()->elaborate_type(des, scope);
|
||||
ivl_assert(*this, tmp_type);
|
||||
use_width = tmp_type->packed_width();
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PECallFunction::elaborate_sfunc_: "
|
||||
<< " Packed width of type argument is " << use_width << endl;
|
||||
}
|
||||
|
||||
} else {
|
||||
use_width = expr->expr_width();
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PECallFunction::elaborate_sfunc_: "
|
||||
<< " Width of expression argument is " << use_width << endl;
|
||||
}
|
||||
}
|
||||
|
||||
verinum val (use_width, integer_width);
|
||||
NetEConst*sub = new NetEConst(val);
|
||||
sub->set_line(*this);
|
||||
|
||||
|
|
@ -3299,9 +3321,14 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
<< "got " << use_path.back().index.size() << "." << endl;
|
||||
}
|
||||
|
||||
return check_for_struct_members(this, des, use_scope,
|
||||
net, use_path.back().index,
|
||||
member_comp);
|
||||
NetExpr*tmp = check_for_struct_members(this, des, use_scope,
|
||||
net, use_path.back().index,
|
||||
member_comp);
|
||||
if (!tmp) return 0;
|
||||
|
||||
tmp = pad_to_width(tmp, expr_wid, *this);
|
||||
tmp->cast_signed(signed_flag_);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
if (net->class_type() != 0) {
|
||||
|
|
@ -4693,11 +4720,11 @@ unsigned PENewClass::test_width(Design*, NetScope*, width_mode_t&)
|
|||
*/
|
||||
NetExpr* PENewClass::elaborate_expr_constructor_(Design*des, NetScope*scope,
|
||||
const netclass_t*ctype,
|
||||
NetExpr*obj, unsigned flags) const
|
||||
NetExpr*obj, unsigned /*flags*/) const
|
||||
{
|
||||
// If there is an initializer function, then pass the object
|
||||
// through that function first. Note tha the initializer
|
||||
// function has no arguments other then the object itself.
|
||||
// through that function first. Note that the initializer
|
||||
// function has no arguments other than the object itself.
|
||||
if (NetScope*new1_scope = ctype->method_from_name(perm_string::literal("new@"))) {
|
||||
NetFuncDef*def1 = new1_scope->func_def();
|
||||
ivl_assert(*this, def1);
|
||||
|
|
@ -4839,7 +4866,7 @@ NetExpr* PENewCopy::elaborate_expr(Design*des, NetScope*scope, ivl_type_t obj_ty
|
|||
|
||||
/*
|
||||
* A "null" expression represents class objects/handles. This brings
|
||||
* up a ton of special cases, but we handle it here bu setting the
|
||||
* up a ton of special cases, but we handle it here by setting the
|
||||
* expr_type_ and expr_width_ to fixed values.
|
||||
*/
|
||||
unsigned PENull::test_width(Design*, NetScope*, width_mode_t&)
|
||||
|
|
@ -5158,6 +5185,31 @@ NetExpr* PETernary::elab_and_eval_alternative_(Design*des, NetScope*scope,
|
|||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* A typename expression is only legal in very narrow cases. This is
|
||||
* just a placeholder.
|
||||
*/
|
||||
unsigned PETypename::test_width(Design*des, NetScope*, width_mode_t&)
|
||||
{
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Type names are not valid expressions here." << endl;
|
||||
des->errors += 1;
|
||||
|
||||
expr_type_ = IVL_VT_NO_TYPE;
|
||||
expr_width_ = 1;
|
||||
min_width_ = 1;
|
||||
signed_flag_ = false;
|
||||
return expr_width_;
|
||||
}
|
||||
|
||||
NetExpr*PETypename::elaborate_expr(Design*des, NetScope*,
|
||||
ivl_type_t, unsigned) const
|
||||
{
|
||||
cerr << get_fileline() << ": error: Type name not a valid expression here." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned PEUnary::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
||||
{
|
||||
switch (op_) {
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@
|
|||
# include "netlist.h"
|
||||
# include "netclass.h"
|
||||
# include "netenum.h"
|
||||
# include "parse_api.h"
|
||||
# include "util.h"
|
||||
# include <typeinfo>
|
||||
# include <cassert>
|
||||
|
|
@ -156,6 +157,10 @@ static void collect_scope_specparams_(Design*des, NetScope*scope,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Elaborate the enumeration into the given scope. If scope==0, then
|
||||
* the enumeration goes into $root instead of a scope.
|
||||
*/
|
||||
static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
||||
enum_type_t*enum_type)
|
||||
{
|
||||
|
|
@ -176,10 +181,10 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
|||
msb, lsb, enum_type->names->size());
|
||||
|
||||
use_enum->set_line(enum_type->li);
|
||||
scope->add_enumeration_set(use_enum);
|
||||
|
||||
ivl_assert(*enum_type, enum_type->net_type == 0);
|
||||
enum_type->net_type = use_enum;
|
||||
if (scope)
|
||||
scope->add_enumeration_set(enum_type, use_enum);
|
||||
else
|
||||
des->add_enumeration_set(enum_type, use_enum);
|
||||
|
||||
verinum cur_value (0);
|
||||
verinum one_value (1);
|
||||
|
|
@ -270,7 +275,11 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
|||
tmp_val.has_sign(enum_type->signed_flag);
|
||||
|
||||
rc_flag = use_enum->insert_name(name_idx, cur->name, tmp_val);
|
||||
rc_flag &= scope->add_enumeration_name(use_enum, cur->name);
|
||||
if (scope)
|
||||
rc_flag &= scope->add_enumeration_name(use_enum, cur->name);
|
||||
else
|
||||
rc_flag &= des->add_enumeration_name(use_enum, cur->name);
|
||||
|
||||
if (! rc_flag) {
|
||||
cerr << use_enum->get_fileline()
|
||||
<< ": error: Duplicate enumeration name "
|
||||
|
|
@ -297,6 +306,15 @@ static void elaborate_scope_enumerations(Design*des, NetScope*scope,
|
|||
}
|
||||
}
|
||||
|
||||
void elaborate_rootscope_enumerations(Design*des)
|
||||
{
|
||||
for (set<enum_type_t*>::const_iterator cur = pform_enum_sets.begin()
|
||||
; cur != pform_enum_sets.end() ; ++ cur) {
|
||||
enum_type_t*curp = *cur;
|
||||
elaborate_scope_enumeration(des, 0, curp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the pclass includes an implicit and explicit constructor, then
|
||||
* merge the implicit constructor into the explicit constructor as
|
||||
|
|
|
|||
14
elab_sig.cc
14
elab_sig.cc
|
|
@ -563,7 +563,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
|||
// Special case: this is a constructor, so the return
|
||||
// signal is also the first argument. For example, the
|
||||
// source code for the definition may be:
|
||||
// function new(...);
|
||||
// function new(...);
|
||||
// endfunction
|
||||
// In this case, the "@" port is the synthetic "this"
|
||||
// argument and we also use it as a return value at the
|
||||
|
|
@ -876,7 +876,7 @@ static ivl_type_s*elaborate_type(Design*des, NetScope*scope,
|
|||
data_type_t*pform_type)
|
||||
{
|
||||
if (struct_type_t*struct_type = dynamic_cast<struct_type_t*>(pform_type)) {
|
||||
netstruct_t*use_type = struct_type->elaborate_type(des, scope);
|
||||
ivl_type_s*use_type = struct_type->elaborate_type(des, scope);
|
||||
return use_type;
|
||||
}
|
||||
|
||||
|
|
@ -965,7 +965,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
<< "'." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
// A signal can not have the same name as a parameter.
|
||||
// A signal can not have the same name as a parameter. Note
|
||||
// that we treat enumeration literals similar to parameters,
|
||||
// so if the name matches an enumeration literal, it will be
|
||||
// caught here.
|
||||
const NetExpr *ex_msb, *ex_lsb;
|
||||
const NetExpr *parm = scope->get_parameter(des, name_, ex_msb, ex_lsb);
|
||||
if (parm) {
|
||||
|
|
@ -1207,7 +1210,8 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
} else if (struct_type_t*struct_type = dynamic_cast<struct_type_t*>(set_data_type_)) {
|
||||
// If this is a struct type, then build the net with the
|
||||
// struct type.
|
||||
netstruct_t*use_type = struct_type->elaborate_type(des, scope);
|
||||
ivl_type_s*tmp_type = struct_type->elaborate_type(des, scope);
|
||||
netstruct_t*use_type = dynamic_cast<netstruct_t*>(tmp_type);
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Create signal " << wtype;
|
||||
if (use_type->packed())
|
||||
|
|
@ -1256,7 +1260,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
// The trick here is that the parray type has an
|
||||
// arbitrary sub-type, and not just a scalar bit...
|
||||
netparray_t*use_type = elaborate_parray_type(des, scope, parray_type);
|
||||
// Should not be getting packed dimensions other then
|
||||
// Should not be getting packed dimensions other than
|
||||
// through the parray type declaration.
|
||||
ivl_assert(*this, packed_dimensions.empty());
|
||||
|
||||
|
|
|
|||
32
elab_type.cc
32
elab_type.cc
|
|
@ -31,7 +31,7 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*) const
|
||||
ivl_type_s* data_type_t::elaborate_type_raw(Design*des, NetScope*) const
|
||||
{
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Elaborate method not implemented for " << typeid(*this).name()
|
||||
|
|
@ -40,7 +40,7 @@ ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*) const
|
|||
return 0;
|
||||
}
|
||||
|
||||
ivl_type_s* atom2_type_t::elaborate_type(Design*des, NetScope*) const
|
||||
ivl_type_s* atom2_type_t::elaborate_type_raw(Design*des, NetScope*) const
|
||||
{
|
||||
switch (type_code) {
|
||||
case 64:
|
||||
|
|
@ -75,18 +75,28 @@ ivl_type_s* atom2_type_t::elaborate_type(Design*des, NetScope*) const
|
|||
}
|
||||
}
|
||||
|
||||
ivl_type_s* class_type_t::elaborate_type(Design*, NetScope*scope) const
|
||||
ivl_type_s* class_type_t::elaborate_type_raw(Design*, NetScope*scope) const
|
||||
{
|
||||
return scope->find_class(name);
|
||||
}
|
||||
|
||||
ivl_type_s* enum_type_t::elaborate_type(Design*des, NetScope*scope) const
|
||||
/*
|
||||
* elaborate_type_raw for enumerations is actually mostly performed
|
||||
* during scope elaboration so that the enumeration literals are
|
||||
* available at the right time. At that time, the netenum_t* object is
|
||||
* stashed in the scope so that I can retrieve it here.
|
||||
*/
|
||||
ivl_type_s* enum_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||
{
|
||||
ivl_assert(*this, net_type);
|
||||
return net_type;
|
||||
ivl_assert(*this, scope);
|
||||
ivl_type_s*tmp = scope->enumeration_for_key(this);
|
||||
if (tmp) return tmp;
|
||||
|
||||
tmp = des->enumeration_for_key(this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
ivl_type_s* vector_type_t::elaborate_type(Design*des, NetScope*scope) const
|
||||
ivl_type_s* vector_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||
{
|
||||
vector<netrange_t> packed;
|
||||
|
||||
|
|
@ -122,7 +132,7 @@ ivl_type_s* vector_type_t::elaborate_type(Design*des, NetScope*scope) const
|
|||
return tmp;
|
||||
}
|
||||
|
||||
ivl_type_s* real_type_t::elaborate_type(Design*, NetScope*) const
|
||||
ivl_type_s* real_type_t::elaborate_type_raw(Design*, NetScope*) const
|
||||
{
|
||||
switch (type_code) {
|
||||
case REAL:
|
||||
|
|
@ -133,12 +143,12 @@ ivl_type_s* real_type_t::elaborate_type(Design*, NetScope*) const
|
|||
return 0;
|
||||
}
|
||||
|
||||
ivl_type_s* string_type_t::elaborate_type(Design*, NetScope*) const
|
||||
ivl_type_s* string_type_t::elaborate_type_raw(Design*, NetScope*) const
|
||||
{
|
||||
return &netstring_t::type_string;
|
||||
}
|
||||
|
||||
netstruct_t* struct_type_t::elaborate_type(Design*des, NetScope*scope) const
|
||||
netstruct_t* struct_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||
{
|
||||
netstruct_t*res = new netstruct_t;
|
||||
|
||||
|
|
@ -173,7 +183,7 @@ netstruct_t* struct_type_t::elaborate_type(Design*des, NetScope*scope) const
|
|||
return res;
|
||||
}
|
||||
|
||||
ivl_type_s* uarray_type_t::elaborate_type(Design*des, NetScope*scope) const
|
||||
ivl_type_s* uarray_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||
{
|
||||
|
||||
ivl_type_t btype = base_type->elaborate_type(des, scope);
|
||||
|
|
|
|||
32
elaborate.cc
32
elaborate.cc
|
|
@ -129,8 +129,8 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
|||
<< ", expr=" << *rval_expr << endl;
|
||||
}
|
||||
|
||||
assert(lval && rval);
|
||||
assert(rval->pin_count() == 1);
|
||||
ivl_assert(*this, lval && rval);
|
||||
ivl_assert(*this, rval->pin_count() == 1);
|
||||
|
||||
// Detect the case that the rvalue-expression is a simple
|
||||
// expression. In this case, we will need to create a driver
|
||||
|
|
@ -139,23 +139,14 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
|||
if (dynamic_cast<NetESignal*>(rval_expr))
|
||||
need_driver_flag = true;
|
||||
|
||||
#if 0
|
||||
// MTW, 01-Mar-2013. The expression elaboration rework should have
|
||||
// ensured that this can no longer occur. Leaving this here for the
|
||||
// moment, but it should be safe to remove it.
|
||||
|
||||
/* If the r-value insists on being smaller than the l-value
|
||||
(perhaps it is explicitly sized) the pad it out to be the
|
||||
right width so that something is connected to all the bits
|
||||
of the l-value. */
|
||||
if (lval->vector_width() > rval->vector_width()) {
|
||||
if (rval->get_signed())
|
||||
rval = pad_to_width_signed(des, rval, lval->vector_width(),
|
||||
*this);
|
||||
else
|
||||
rval = pad_to_width(des, rval, lval->vector_width(), *this);
|
||||
// expression elaboration should have caused the rval width to
|
||||
// match the l-value by now.
|
||||
if (rval->vector_width() < lval->vector_width()) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "lval-rval width mismatch: "
|
||||
<< "rval->vector_width()==" << rval->vector_width()
|
||||
<< ", lval->vector_width()==" << lval->vector_width() << endl;
|
||||
}
|
||||
#endif
|
||||
ivl_assert(*this, rval->vector_width() >= lval->vector_width());
|
||||
|
||||
/* If the r-value insists on being larger than the l-value,
|
||||
|
|
@ -3060,7 +3051,7 @@ NetProc* PChainConstructor::elaborate(Design*des, NetScope*scope) const
|
|||
NetNet*var_this = scope->find_signal(perm_string::literal("@"));
|
||||
|
||||
// If super.new is an implicit constructor, then there are no
|
||||
// arguments (other then "this" to worry about, so make a
|
||||
// arguments (other than "this" to worry about, so make a
|
||||
// NetEUFunc and there we go.
|
||||
if (NetScope*new_scope = class_super->method_from_name(perm_string::literal("new@"))) {
|
||||
NetESignal*eres = new NetESignal(var_this);
|
||||
|
|
@ -5663,6 +5654,9 @@ Design* elaborate(list<perm_string>roots)
|
|||
// module and elaborate what I find.
|
||||
Design*des = new Design;
|
||||
|
||||
// Elaborate enum sets in $root scope.
|
||||
elaborate_rootscope_enumerations(des);
|
||||
|
||||
// Elaborate the packages. Package elaboration is simpler
|
||||
// because there are fewer sub-scopes involved.
|
||||
i = 0;
|
||||
|
|
|
|||
4
emit.cc
4
emit.cc
|
|
@ -420,9 +420,9 @@ void NetScope::emit_scope(struct target_t*tgt) const
|
|||
tgt->class_type(this, cur->second);
|
||||
}
|
||||
|
||||
for (list<netenum_t*>::const_iterator cur = enum_sets_.begin()
|
||||
for (map<const enum_type_t*,netenum_t*>::const_iterator cur = enum_sets_.begin()
|
||||
; cur != enum_sets_.end() ; ++cur)
|
||||
tgt->enumeration(this, *cur);
|
||||
tgt->enumeration(this, cur->second);
|
||||
|
||||
for (map<hname_t,NetScope*>::const_iterator cur = children_.begin()
|
||||
; cur != children_.end() ; ++ cur )
|
||||
|
|
|
|||
234
eval_tree.cc
234
eval_tree.cc
|
|
@ -288,6 +288,13 @@ NetEConst* NetEBBits::eval_arguments_(const NetExpr*l, const NetExpr*r) const
|
|||
break;
|
||||
}
|
||||
|
||||
case 'X': {
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1)
|
||||
res.set(idx, ~(lval.get(idx) ^ rval.get(idx)));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case '^': {
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1)
|
||||
res.set(idx, lval.get(idx) ^ rval.get(idx));
|
||||
|
|
@ -1923,6 +1930,173 @@ NetExpr* NetESFunc::evaluate_min_max_(ID id, const NetExpr*arg0_,
|
|||
return res;
|
||||
}
|
||||
|
||||
NetEConst* NetESFunc::evaluate_countbits_(const NetExpr* /*arg0*/,
|
||||
const NetExpr* /*arg1*/) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEConst* NetESFunc::evaluate_countones_(const NetExpr* /*arg*/) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the total number of dimensions for the given expression. */
|
||||
NetEConst* NetESFunc::evaluate_dimensions_(const NetExpr*arg) const
|
||||
{
|
||||
const NetESignal*esig = dynamic_cast<const NetESignal*>(arg);
|
||||
long res = 0;
|
||||
if (esig != 0) {
|
||||
const NetNet *sig = esig->sig();
|
||||
res = sig->packed_dimensions() + sig->unpacked_dimensions();
|
||||
/* Icarus does not think a string has a packed size so to
|
||||
* make these routines work correct add one if this is a
|
||||
* string data type. */
|
||||
if (sig->data_type() == IVL_VT_STRING) {
|
||||
assert(sig->packed_dimensions() == 0);
|
||||
res += 1;
|
||||
}
|
||||
}
|
||||
/* Return the result as an integer sized constant. */
|
||||
return new NetEConst(verinum(verinum(res), integer_width));
|
||||
}
|
||||
|
||||
NetEConst* NetESFunc::evaluate_isunknown_(const NetExpr* /*arg*/) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEConst* NetESFunc::evaluate_onehot_(const NetExpr* /*arg*/) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEConst* NetESFunc::evaluate_onehot0_(const NetExpr* /*arg*/) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the number of unpacked dimensions for the given expression. */
|
||||
NetEConst* NetESFunc::evaluate_unpacked_dimensions_(const NetExpr*arg) const
|
||||
{
|
||||
const NetESignal*esig = dynamic_cast<const NetESignal*>(arg);
|
||||
long res = 0;
|
||||
if (esig != 0) {
|
||||
const NetNet *sig = esig->sig();
|
||||
res = sig->unpacked_dimensions();
|
||||
}
|
||||
/* Return the result as an integer sized constant. */
|
||||
return new NetEConst(verinum(verinum(res), integer_width));
|
||||
}
|
||||
|
||||
/* This code assumes that the dimension value will fit in a long.
|
||||
* Return true if no constant dimension value is available. */
|
||||
static bool check_dimension(const NetExpr*dim_expr, long &dim)
|
||||
{
|
||||
const NetEConst*dimi = dynamic_cast<const NetEConst*>(dim_expr);
|
||||
const NetECReal*dimr = dynamic_cast<const NetECReal*>(dim_expr);
|
||||
if (dimi == 0 && dimr == 0) return true;
|
||||
|
||||
if (dimi) dim = dimi->value().as_long();
|
||||
if (dimr) dim = dimr->value().as_long();
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Get the left and right values for the argument at the given dimension
|
||||
* if it exists. Return true if no values are available. Set defer to true
|
||||
* if this should be handled in the run time. */
|
||||
static bool get_array_info(const NetExpr*arg, long dim,
|
||||
long &left, long &right, bool&defer)
|
||||
{
|
||||
/* The argument must be a signal that has enough dimensions. */
|
||||
const NetESignal*esig = dynamic_cast<const NetESignal*>(arg);
|
||||
if (esig == 0) return true;
|
||||
const NetNet *sig = esig->sig();
|
||||
/* A string or dynamic array must be handled by the run time. */
|
||||
switch (sig->data_type()) {
|
||||
case IVL_VT_DARRAY:
|
||||
case IVL_VT_STRING:
|
||||
defer = true;
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
long pdims = sig->packed_dimensions();
|
||||
long updims = sig->unpacked_dimensions();
|
||||
if (dim > (pdims + updims)) return true;
|
||||
/* Get the appropriate unpacked or packed dimension information. */
|
||||
if (dim > updims) {
|
||||
const vector<netrange_t>&dim_vals = sig->packed_dims();
|
||||
const netrange_t&range = dim_vals[dim-updims-1];
|
||||
left = range.get_msb();
|
||||
right = range.get_lsb();
|
||||
} else {
|
||||
const vector<netrange_t>&dim_vals = sig->unpacked_dims();
|
||||
const netrange_t&range = dim_vals[dim-1];
|
||||
left = range.get_msb();
|
||||
right = range.get_lsb();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Calculate the array property functions. */
|
||||
NetEConst* NetESFunc::evaluate_array_funcs_(ID id,
|
||||
const NetExpr*arg0,
|
||||
const NetExpr*arg1) const
|
||||
{
|
||||
long dim = 0;
|
||||
/* Check to see if the dimension argument is constant. */
|
||||
if (check_dimension(arg1, dim)) return 0;
|
||||
/* If dimension is less than 1 return undefined. */
|
||||
if (dim < 1) {
|
||||
return new NetEConst(verinum(verinum::Vx, integer_width));
|
||||
}
|
||||
/* Get the left/right information for this dimension if it exists. */
|
||||
long left = 0;
|
||||
long right = 0;
|
||||
bool defer = false;
|
||||
if (get_array_info(arg0, dim, left, right, defer)) {
|
||||
/* If this is a string or dynamic array defer this function
|
||||
* call since the left/right information is dynamic and is
|
||||
* not available yet. */
|
||||
if (defer) return 0;
|
||||
return new NetEConst(verinum(verinum::Vx, integer_width));
|
||||
}
|
||||
/* Calculate the appropriate array function result. */
|
||||
long res;
|
||||
switch (id) {
|
||||
case HIGH:
|
||||
res = (right > left) ? right : left;
|
||||
break;
|
||||
case INCR:
|
||||
res = (right > left) ? -1 : 1;
|
||||
break;
|
||||
case LEFT:
|
||||
res = left;
|
||||
break;
|
||||
case LOW:
|
||||
res = (right > left) ? left : right;
|
||||
break;
|
||||
case RIGHT:
|
||||
res = right;
|
||||
break;
|
||||
case SIZE:
|
||||
res = (right > left) ? right - left : left - right;
|
||||
res += 1;
|
||||
break;
|
||||
default:
|
||||
res = 0;
|
||||
assert(0);
|
||||
}
|
||||
/* Return the result as an integer sized constant. */
|
||||
return new NetEConst(verinum(verinum(res), integer_width));
|
||||
}
|
||||
|
||||
/* Make a constant one value that can be used by the one argument
|
||||
* array properties calls. */
|
||||
const NetEConst* NetESFunc::const_one_ = new NetEConst(verinum(1U, 32U));
|
||||
|
||||
NetExpr* NetESFunc::evaluate_one_arg_(ID id, const NetExpr*arg) const
|
||||
{
|
||||
switch (id) {
|
||||
|
|
@ -1930,21 +2104,51 @@ NetExpr* NetESFunc::evaluate_one_arg_(ID id, const NetExpr*arg) const
|
|||
return evaluate_abs_(arg);
|
||||
case CLOG2:
|
||||
return evaluate_clog2_(arg);
|
||||
case CTONES:
|
||||
return evaluate_countones_(arg);
|
||||
case DIMS:
|
||||
return evaluate_dimensions_(arg);
|
||||
/* The array functions are handled together. */
|
||||
case HIGH:
|
||||
case INCR:
|
||||
case LEFT:
|
||||
case LOW:
|
||||
case RIGHT:
|
||||
case SIZE:
|
||||
return evaluate_array_funcs_(id, arg, const_one_);
|
||||
case ISUNKN:
|
||||
return evaluate_isunknown_(arg);
|
||||
case ITOR:
|
||||
return evaluate_itor_(arg);
|
||||
case ONEHT:
|
||||
return evaluate_onehot_(arg);
|
||||
case ONEHT0:
|
||||
return evaluate_onehot0_(arg);
|
||||
case RTOI:
|
||||
return evaluate_rtoi_(arg);
|
||||
case UPDIMS:
|
||||
return evaluate_unpacked_dimensions_(arg);
|
||||
default:
|
||||
return evaluate_math_one_arg_(id, arg);
|
||||
}
|
||||
}
|
||||
|
||||
NetExpr* NetESFunc::evaluate_two_arg_(ID id, const NetExpr*arg0,
|
||||
const NetExpr*arg1) const
|
||||
const NetExpr*arg1) const
|
||||
{
|
||||
switch (id) {
|
||||
case MIN:
|
||||
case CTBITS:
|
||||
return evaluate_countbits_(arg0, arg1);
|
||||
/* The array functions are handled together. */
|
||||
case HIGH:
|
||||
case INCR:
|
||||
case LEFT:
|
||||
case LOW:
|
||||
case RIGHT:
|
||||
case SIZE:
|
||||
return evaluate_array_funcs_(id, arg0, arg1);
|
||||
case MAX:
|
||||
case MIN:
|
||||
return evaluate_min_max_(id, arg0, arg1);
|
||||
default:
|
||||
return evaluate_math_two_arg_(id, arg0, arg1);
|
||||
|
|
@ -1990,6 +2194,31 @@ NetESFunc::ID NetESFunc::built_in_id_() const
|
|||
built_in_func["$tanh" ] = TANH;
|
||||
}
|
||||
|
||||
/* These are available in 1800-2005 and later. */
|
||||
if (funcs_need_init && (generation_flag >= GN_VER2005_SV)) {
|
||||
built_in_func["$dimensions" ] = DIMS;
|
||||
built_in_func["$high" ] = HIGH;
|
||||
built_in_func["$increment" ] = INCR;
|
||||
built_in_func["$isunknown" ] = ISUNKN;
|
||||
built_in_func["$left" ] = LEFT;
|
||||
built_in_func["$low" ] = LOW;
|
||||
built_in_func["$onehot" ] = ONEHT;
|
||||
built_in_func["$onehot0" ] = ONEHT0;
|
||||
built_in_func["$right" ] = RIGHT;
|
||||
built_in_func["$size" ] = SIZE;
|
||||
built_in_func["$unpacked_dimensions" ] = UPDIMS;
|
||||
}
|
||||
|
||||
/* These are available in 1800-2009 and later. */
|
||||
if (funcs_need_init && (generation_flag >= GN_VER2009)) {
|
||||
built_in_func["$countones" ] = CTONES;
|
||||
}
|
||||
|
||||
/* These are available in 1800-2012 and later. */
|
||||
if (funcs_need_init && (generation_flag >= GN_VER2012)) {
|
||||
built_in_func["$countbits" ] = CTBITS;
|
||||
}
|
||||
|
||||
/* These are available in Verilog-A as Icarus extensions or if the
|
||||
* Icarus misc flag was given. */
|
||||
if (funcs_need_init && (gn_verilog_ams_flag || gn_icarus_misc_flag)) {
|
||||
|
|
@ -2045,6 +2274,7 @@ NetExpr* NetESFunc::eval_tree()
|
|||
<< " arguments." << endl;
|
||||
return 0;
|
||||
}
|
||||
// HERE: Need to add support for a multi argument $countbits().
|
||||
cerr << get_fileline() << ": sorry: functions with "
|
||||
<< parms_.size() << " arguments are not supported: "
|
||||
<< name_ << "()." << endl;
|
||||
|
|
|
|||
|
|
@ -341,7 +341,7 @@ TU [munpf]
|
|||
}
|
||||
}
|
||||
|
||||
/* If this identifer names a previously declared package, then
|
||||
/* If this identifier names a previously declared package, then
|
||||
return this as a PACKAGE_IDENTIFIER instead. */
|
||||
if (rc == IDENTIFIER && gn_system_verilog()) {
|
||||
if (PPackage*pkg = pform_test_package_identifier(yylval.text)) {
|
||||
|
|
|
|||
|
|
@ -260,7 +260,7 @@ void NetEConcat::set(unsigned idx, NetExpr*e)
|
|||
expr_width( expr_width() + repeat_ * e->expr_width() );
|
||||
}
|
||||
|
||||
NetEConstEnum::NetEConstEnum(NetScope*s, perm_string n, const netenum_t*eset, const verinum&v)
|
||||
NetEConstEnum::NetEConstEnum(Definitions*s, perm_string n, const netenum_t*eset, const verinum&v)
|
||||
: NetEConst(v), scope_(s), enum_set_(eset), name_(n)
|
||||
{
|
||||
assert(has_width());
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ NetExpr* NetFuncDef::evaluate_function(const LineInfo&loc, const std::vector<Net
|
|||
if (flag) {
|
||||
if (debug_eval_tree) {
|
||||
cerr << loc.get_fileline() << ": NetFuncDef::evaluate_function: "
|
||||
<< "Evalutated to ";
|
||||
<< "Evaluated to ";
|
||||
if (res) cerr << *res;
|
||||
else cerr << "<nil>";
|
||||
cerr << endl;
|
||||
|
|
|
|||
106
net_scope.cc
106
net_scope.cc
|
|
@ -30,6 +30,72 @@
|
|||
|
||||
class PExpr;
|
||||
|
||||
Definitions::Definitions()
|
||||
{
|
||||
}
|
||||
|
||||
Definitions::~Definitions()
|
||||
{
|
||||
}
|
||||
|
||||
void Definitions::add_enumeration_set(const enum_type_t*key, netenum_t*enum_set)
|
||||
{
|
||||
netenum_t*&tmp = enum_sets_[key];
|
||||
assert(tmp == 0);
|
||||
tmp = enum_set;
|
||||
}
|
||||
|
||||
bool Definitions::add_enumeration_name(netenum_t*enum_set, perm_string name)
|
||||
{
|
||||
netenum_t::iterator enum_val = enum_set->find_name(name);
|
||||
assert(enum_val != enum_set->end_name());
|
||||
|
||||
NetEConstEnum*val = new NetEConstEnum(this, name, enum_set, enum_val->second);
|
||||
|
||||
pair<map<perm_string,NetEConstEnum*>::iterator, bool> cur;
|
||||
cur = enum_names_.insert(make_pair(name,val));
|
||||
|
||||
// Return TRUE if the name is added (i.e. is NOT a duplicate.)
|
||||
return cur.second;
|
||||
}
|
||||
|
||||
netenum_t* Definitions::enumeration_for_key(const enum_type_t*key) const
|
||||
{
|
||||
map<const enum_type_t*,netenum_t*>::const_iterator cur;
|
||||
|
||||
cur = enum_sets_.find(key);
|
||||
if (cur != enum_sets_.end())
|
||||
return cur->second;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This locates the enumeration TYPE for the given enumeration literal.
|
||||
*/
|
||||
const netenum_t*Definitions::enumeration_for_name(perm_string name)
|
||||
{
|
||||
NetEConstEnum*tmp = enum_names_[name];
|
||||
assert(tmp != 0);
|
||||
|
||||
return tmp->enumeration();
|
||||
}
|
||||
|
||||
/*
|
||||
* This locates the VALUE for the given enumeration literal.
|
||||
*/
|
||||
const NetExpr* Definitions::enumeration_expr(perm_string key)
|
||||
{
|
||||
map<perm_string,NetEConstEnum*>::const_iterator eidx;
|
||||
|
||||
eidx = enum_names_.find(key);
|
||||
if (eidx != enum_names_.end()) {
|
||||
return eidx->second;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The NetScope class keeps a scope tree organized. Each node of the
|
||||
* scope tree points to its parent, its right sibling and its leftmost
|
||||
|
|
@ -265,14 +331,13 @@ const NetExpr* NetScope::get_parameter(Design*des,
|
|||
return idx->second.val;
|
||||
}
|
||||
|
||||
map<perm_string,NetEConstEnum*>::const_iterator eidx;
|
||||
msb = 0;
|
||||
lsb = 0;
|
||||
const NetExpr*tmp = enumeration_expr(key);
|
||||
if (tmp) return tmp;
|
||||
|
||||
eidx = enum_names_.find(key);
|
||||
if (eidx != enum_names_.end()) {
|
||||
msb = 0;
|
||||
lsb = 0;
|
||||
return eidx->second;
|
||||
}
|
||||
tmp = des->enumeration_expr(key);
|
||||
if (tmp) return tmp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -551,33 +616,6 @@ NetNet* NetScope::find_signal(perm_string key)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void NetScope::add_enumeration_set(netenum_t*enum_set)
|
||||
{
|
||||
enum_sets_.push_back(enum_set);
|
||||
}
|
||||
|
||||
bool NetScope::add_enumeration_name(netenum_t*enum_set, perm_string name)
|
||||
{
|
||||
netenum_t::iterator enum_val = enum_set->find_name(name);
|
||||
assert(enum_val != enum_set->end_name());
|
||||
|
||||
NetEConstEnum*val = new NetEConstEnum(this, name, enum_set, enum_val->second);
|
||||
|
||||
pair<map<perm_string,NetEConstEnum*>::iterator, bool> cur;
|
||||
cur = enum_names_.insert(make_pair(name,val));
|
||||
|
||||
// Return TRUE if the name is added (i.e. is NOT a duplicate.)
|
||||
return cur.second;
|
||||
}
|
||||
|
||||
const netenum_t*NetScope::enumeration_for_name(perm_string name)
|
||||
{
|
||||
NetEConstEnum*tmp = enum_names_[name];
|
||||
assert(tmp != 0);
|
||||
|
||||
return tmp->enumeration();
|
||||
}
|
||||
|
||||
void NetScope::add_class(netclass_t*net_class)
|
||||
{
|
||||
classes_[net_class->get_name()] = net_class;
|
||||
|
|
|
|||
|
|
@ -755,7 +755,7 @@ const netclass_t* NetNet::class_type(void) const
|
|||
|
||||
/*
|
||||
* "depth" is the number of index expressions that the user is using
|
||||
* to index this identifer. So consider if Net was declared like so:
|
||||
* to index this identifier. So consider if Net was declared like so:
|
||||
*
|
||||
* reg [5:0][3:0] foo;
|
||||
*
|
||||
|
|
|
|||
153
netlist.h
153
netlist.h
|
|
@ -76,6 +76,7 @@ class NetEvTrig;
|
|||
class NetEvWait;
|
||||
class PExpr;
|
||||
class PFunction;
|
||||
struct enum_type_t;
|
||||
class netclass_t;
|
||||
class netdarray_t;
|
||||
class netparray_t;
|
||||
|
|
@ -819,12 +820,53 @@ class NetBaseDef {
|
|||
NetProc*proc_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Some definitions (and methods to manipulate them) are common to a
|
||||
* couple of types. Keep them here.
|
||||
*/
|
||||
class Definitions {
|
||||
|
||||
public:
|
||||
Definitions();
|
||||
~Definitions();
|
||||
|
||||
// Add the enumeration to the set of enumerations in this
|
||||
// scope. Include a key that the elaboration can use to look
|
||||
// up this enumeration based on the pform type.
|
||||
void add_enumeration_set(const enum_type_t*key, netenum_t*enum_set);
|
||||
|
||||
bool add_enumeration_name(netenum_t*enum_set, perm_string enum_name);
|
||||
|
||||
// Look up the enumeration literal in this scope. if the name
|
||||
// is present, then return the enumeration type that declares it.
|
||||
const netenum_t* enumeration_for_name(perm_string name);
|
||||
|
||||
// Look up the enumeration set that was added with the given
|
||||
// key. This is used by enum_type_t::elaborate_type to locate
|
||||
// a previously elaborated enumeration.
|
||||
netenum_t* enumeration_for_key(const enum_type_t*key) const;
|
||||
|
||||
// Look up an enumeration literal in this scope. If the
|
||||
// literal is present, return the expression that defines its
|
||||
// value.
|
||||
const NetExpr* enumeration_expr(perm_string key);
|
||||
|
||||
protected:
|
||||
// Enumerations. The enum_sets_ is a list of all the
|
||||
// enumerations present in this scope. The enum_names_ is a
|
||||
// map of all the enumeration names back to the sets that
|
||||
// contain them.
|
||||
std::map<const enum_type_t*,netenum_t*> enum_sets_;
|
||||
std::map<perm_string,NetEConstEnum*> enum_names_;
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* This object type is used to contain a logical scope within a
|
||||
* design. The scope doesn't represent any executable hardware, but is
|
||||
* just a handle that netlist processors can use to grab at the design.
|
||||
*/
|
||||
class NetScope : public Attrib {
|
||||
class NetScope : public Definitions, public Attrib {
|
||||
|
||||
public:
|
||||
enum TYPE { MODULE, CLASS, TASK, FUNC, BEGIN_END, FORK_JOIN, GENBLOCK, PACKAGE };
|
||||
|
|
@ -897,11 +939,6 @@ class NetScope : public Attrib {
|
|||
void rem_signal(NetNet*);
|
||||
NetNet* find_signal(perm_string name);
|
||||
|
||||
void add_enumeration_set(netenum_t*enum_set);
|
||||
bool add_enumeration_name(netenum_t*enum_set, perm_string enum_name);
|
||||
|
||||
const netenum_t* enumeration_for_name(perm_string name);
|
||||
|
||||
void add_class(netclass_t*class_type);
|
||||
netclass_t* find_class(perm_string name);
|
||||
|
||||
|
|
@ -1153,13 +1190,6 @@ class NetScope : public Attrib {
|
|||
const PFunction*func_pform_;
|
||||
unsigned elab_stage_;
|
||||
|
||||
// Enumerations. The enum_sets_ is a list of all the
|
||||
// enumerations present in this scope. The enum_names_ is a
|
||||
// map of all the enumeration names back to the sets that
|
||||
// contain them.
|
||||
std::list<netenum_t*> enum_sets_;
|
||||
std::map<perm_string,NetEConstEnum*> enum_names_;
|
||||
|
||||
std::map<perm_string,netclass_t*> classes_;
|
||||
|
||||
NetScope*up_;
|
||||
|
|
@ -1973,12 +2003,11 @@ class NetEConst : public NetExpr {
|
|||
class NetEConstEnum : public NetEConst {
|
||||
|
||||
public:
|
||||
explicit NetEConstEnum(NetScope*scope, perm_string name,
|
||||
explicit NetEConstEnum(Definitions*scope, perm_string name,
|
||||
const netenum_t*enum_set, const verinum&val);
|
||||
~NetEConstEnum();
|
||||
|
||||
perm_string name() const;
|
||||
const NetScope*scope() const;
|
||||
const netenum_t*enumeration() const;
|
||||
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
|
|
@ -1987,7 +2016,7 @@ class NetEConstEnum : public NetEConst {
|
|||
virtual NetEConstEnum* dup_expr() const;
|
||||
|
||||
private:
|
||||
NetScope*scope_;
|
||||
Definitions*scope_;
|
||||
const netenum_t*enum_set_;
|
||||
perm_string name_;
|
||||
};
|
||||
|
|
@ -4176,37 +4205,53 @@ class NetESFunc : public NetExpr {
|
|||
*/
|
||||
enum ID { NOT_BUILT_IN = 0x0,
|
||||
/* Available in all version of Verilog/SystemVerilog. */
|
||||
ITOR = 0x00020001, /* $itor takes one argument. */
|
||||
RTOI = 0x00020002, /* $rtoi takes one argument. */
|
||||
ITOR = 0x00020001, /* $itor takes one argument. */
|
||||
RTOI = 0x00020002, /* $rtoi takes one argument. */
|
||||
/* Available in Verilog 2005 and later. */
|
||||
ACOS = 0x00020003, /* $acos takes one argument. */
|
||||
ACOSH = 0x00020004, /* $acosh takes one argument. */
|
||||
ASIN = 0x00020005, /* $asin takes one argument. */
|
||||
ASINH = 0x00020006, /* $asinh takes one argument. */
|
||||
ATAN = 0x00020007, /* $atan takes one argument. */
|
||||
ATANH = 0x00020008, /* $atanh takes one argument. */
|
||||
ATAN2 = 0x00040009, /* $atan2 takes two argument. */
|
||||
CEIL = 0x0002000a, /* $ceil takes one argument. */
|
||||
CLOG2 = 0x0002000b, /* $clog2 takes one argument. */
|
||||
COS = 0x0002000c, /* $cos takes one argument. */
|
||||
COSH = 0x0002000d, /* $cosh takes one argument. */
|
||||
EXP = 0x0002000e, /* $exp takes one argument. */
|
||||
FLOOR = 0x0002000f, /* $floor takes one argument. */
|
||||
HYPOT = 0x00040010, /* $hypot takes two argument. */
|
||||
LN = 0x00020011, /* $ln takes one argument. */
|
||||
LOG10 = 0x00020012, /* $log10 takes one argument. */
|
||||
POW = 0x00040013, /* $pow takes two argument. */
|
||||
SIN = 0x00020014, /* $sin takes one argument. */
|
||||
SINH = 0x00020015, /* $sinh takes one argument. */
|
||||
SQRT = 0x00020016, /* $sqrt takes one argument. */
|
||||
TAN = 0x00020017, /* $tan takes one argument. */
|
||||
TANH = 0x00020018, /* $tanh takes one argument. */
|
||||
ACOS = 0x00020003, /* $acos takes one argument. */
|
||||
ACOSH = 0x00020004, /* $acosh takes one argument. */
|
||||
ASIN = 0x00020005, /* $asin takes one argument. */
|
||||
ASINH = 0x00020006, /* $asinh takes one argument. */
|
||||
ATAN = 0x00020007, /* $atan takes one argument. */
|
||||
ATANH = 0x00020008, /* $atanh takes one argument. */
|
||||
ATAN2 = 0x00040009, /* $atan2 takes two argument. */
|
||||
CEIL = 0x0002000a, /* $ceil takes one argument. */
|
||||
CLOG2 = 0x0002000b, /* $clog2 takes one argument. */
|
||||
COS = 0x0002000c, /* $cos takes one argument. */
|
||||
COSH = 0x0002000d, /* $cosh takes one argument. */
|
||||
EXP = 0x0002000e, /* $exp takes one argument. */
|
||||
FLOOR = 0x0002000f, /* $floor takes one argument. */
|
||||
HYPOT = 0x00040010, /* $hypot takes two argument. */
|
||||
LN = 0x00020011, /* $ln takes one argument. */
|
||||
LOG10 = 0x00020012, /* $log10 takes one argument. */
|
||||
POW = 0x00040013, /* $pow takes two argument. */
|
||||
SIN = 0x00020014, /* $sin takes one argument. */
|
||||
SINH = 0x00020015, /* $sinh takes one argument. */
|
||||
SQRT = 0x00020016, /* $sqrt takes one argument. */
|
||||
TAN = 0x00020017, /* $tan takes one argument. */
|
||||
TANH = 0x00020018, /* $tanh takes one argument. */
|
||||
/* Added in SystemVerilog 2005 and later. */
|
||||
DIMS = 0x00020019, /* $dimensions takes one argument. */
|
||||
HIGH = 0x0006001a, /* $high takes one or two arguments. */
|
||||
INCR = 0x0006001b, /* $increment takes one or two arguments. */
|
||||
LEFT = 0x0006001c, /* $left takes one or two arguments. */
|
||||
LOW = 0x0006001d, /* $low takes one or two arguments. */
|
||||
RIGHT = 0x0006001e, /* $right takes one or two arguments. */
|
||||
SIZE = 0x0006001f, /* $size takes one or two arguments. */
|
||||
UPDIMS = 0x00020020, /* $unpacked_dimensions takes one argument. */
|
||||
ISUNKN = 0x00020021, /* $isunknown takes one argument. */
|
||||
ONEHT = 0x00020022, /* $onehot takes one argument. */
|
||||
ONEHT0 = 0x00020023, /* $onehot0 takes one argument. */
|
||||
/* Added in SystemVerilog 2009 and later. */
|
||||
CTONES = 0x00020024, /* $countones takes one argument. */
|
||||
/* Added in SystemVerilog 2012 and later. */
|
||||
CTBITS = 0xfffe0025, /* $countbits takes one or more arguments. */
|
||||
/* Added as Icarus extensions to Verilog-A. */
|
||||
ABS = 0x00020019, /* $abs takes one argument. */
|
||||
MAX = 0x0004001a, /* $max takes two argument. */
|
||||
MIN = 0x0004001b, /* $min takes two argument. */
|
||||
ABS = 0x00020026, /* $abs takes one argument. */
|
||||
MAX = 0x00040027, /* $max takes two argument. */
|
||||
MIN = 0x00040028, /* $min takes two argument. */
|
||||
/* A dummy value to properly close the enum. */
|
||||
DUMMY = 0xffffffff };
|
||||
DUMMY = 0xffffffff };
|
||||
|
||||
bool takes_nargs_(ID func, unsigned nargs) {
|
||||
if (nargs > 15) nargs = 15;
|
||||
|
|
@ -4237,6 +4282,24 @@ class NetESFunc : public NetExpr {
|
|||
NetExpr* evaluate_min_max_(ID id, const NetExpr*arg0,
|
||||
const NetExpr*arg1) const;
|
||||
|
||||
/* Constant SystemVerilog functions. */
|
||||
NetEConst* evaluate_countones_(const NetExpr*arg) const;
|
||||
NetEConst* evaluate_dimensions_(const NetExpr*arg) const;
|
||||
NetEConst* evaluate_isunknown_(const NetExpr*arg) const;
|
||||
NetEConst* evaluate_onehot_(const NetExpr*arg) const;
|
||||
NetEConst* evaluate_onehot0_(const NetExpr*arg) const;
|
||||
NetEConst* evaluate_unpacked_dimensions_(const NetExpr*arg) const;
|
||||
|
||||
/* This value is used as a default when the array functions are
|
||||
* called with a single argument. */
|
||||
static const NetEConst*const_one_;
|
||||
|
||||
NetEConst* evaluate_array_funcs_(ID id,
|
||||
const NetExpr*arg0,
|
||||
const NetExpr*arg1) const;
|
||||
NetEConst* evaluate_countbits_(const NetExpr*arg0,
|
||||
const NetExpr*arg1) const;
|
||||
|
||||
public:
|
||||
bool is_built_in() const { return built_in_id_() != NOT_BUILT_IN; };
|
||||
|
||||
|
|
@ -4465,7 +4528,7 @@ struct elaborator_work_item_t {
|
|||
* This class contains an entire design. It includes processes and a
|
||||
* netlist, and can be passed around from function to function.
|
||||
*/
|
||||
class Design {
|
||||
class Design : public Definitions {
|
||||
|
||||
public:
|
||||
Design();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2014 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
|
||||
|
|
@ -48,7 +48,7 @@ NetNet* sub_net_from(Design*des, NetScope*scope, long val, NetNet*sig)
|
|||
|
||||
} else {
|
||||
verinum zero ((int64_t)val);
|
||||
zero = pad_to_width(zero, sig->vector_width());
|
||||
zero = cast_to_width(zero, sig->vector_width());
|
||||
zero.has_sign(sig->get_signed());
|
||||
NetConst*zero_obj = new NetConst(scope, scope->local_symbol(), zero);
|
||||
zero_obj->set_line(*sig);
|
||||
|
|
@ -1360,7 +1360,7 @@ NetExpr*collapse_array_exprs(Design*des, NetScope*scope,
|
|||
/*
|
||||
* Given a list of indices, treat them as packed indices and convert
|
||||
* them to an expression that normalizes the list to a single index
|
||||
* expression over a canonical equivilent 1-dimensional array.
|
||||
* expression over a canonical equivalent 1-dimensional array.
|
||||
*/
|
||||
NetExpr*collapse_array_indices(Design*des, NetScope*scope, NetNet*net,
|
||||
const list<index_component_t>&indices)
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ bool ivl_type_s::type_compatible(ivl_type_t that) const
|
|||
return test_compatibility(that);
|
||||
}
|
||||
|
||||
bool ivl_type_s::test_compatibility(const ivl_type_s*that) const
|
||||
bool ivl_type_s::test_compatibility(const ivl_type_s* /*that*/) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
15
parse.y
15
parse.y
|
|
@ -1081,7 +1081,7 @@ description /* IEEE1800-2005: A.1.2 */
|
|||
| nature_declaration
|
||||
| package_declaration
|
||||
| discipline_declaration
|
||||
| timeunits_declaration
|
||||
| package_item
|
||||
| KK_attribute '(' IDENTIFIER ',' STRING ',' STRING ')'
|
||||
{ perm_string tmp3 = lex_strings.make($3);
|
||||
pform_set_type_attrib(tmp3, $5, $7);
|
||||
|
|
@ -2362,6 +2362,11 @@ struct_union_member /* IEEE 1800-2012 A.2.2.1 */
|
|||
tmp->names .reset($3);
|
||||
$$ = tmp;
|
||||
}
|
||||
| error ';'
|
||||
{ yyerror(@2, "Error in struct/union member.");
|
||||
yyerrok;
|
||||
$$ = 0;
|
||||
}
|
||||
;
|
||||
|
||||
case_item
|
||||
|
|
@ -3092,6 +3097,14 @@ expr_primary
|
|||
delete[]$1;
|
||||
}
|
||||
|
||||
/* There are a few special cases (notably $bits argument) where the
|
||||
expression may be a type name. Let the elaborator sort this out. */
|
||||
| TYPE_IDENTIFIER
|
||||
{ PETypename*tmp = new PETypename($1);
|
||||
FILE_NAME(tmp,@1);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
/* The hierarchy_identifier rule matches simple identifiers as well as
|
||||
indexed arrays and part selects */
|
||||
|
||||
|
|
|
|||
|
|
@ -24,10 +24,14 @@
|
|||
# include <string>
|
||||
# include <ostream>
|
||||
# include <map>
|
||||
# include <set>
|
||||
|
||||
class Design;
|
||||
class Module;
|
||||
class PPackage;
|
||||
class PUdp;
|
||||
class data_type_t;
|
||||
struct enum_type_t;
|
||||
|
||||
/*
|
||||
* These are maps of the modules and primitives parsed from the
|
||||
|
|
@ -36,10 +40,14 @@ class PUdp;
|
|||
*/
|
||||
extern std::map<perm_string,Module*> pform_modules;
|
||||
extern std::map<perm_string,PUdp*> pform_primitives;
|
||||
extern std::map<perm_string,data_type_t*> pform_typedefs;
|
||||
extern std::set<enum_type_t*> pform_enum_sets;
|
||||
|
||||
extern std::map<perm_string,PPackage*> pform_packages;
|
||||
extern void pform_dump(std::ostream&out, const PPackage*pac);
|
||||
|
||||
extern void elaborate_rootscope_enumerations(Design*des);
|
||||
|
||||
/*
|
||||
* This code actually invokes the parser to make modules. The first
|
||||
* parameter is the name of the file that is to be parsed. The
|
||||
|
|
|
|||
49
pform.cc
49
pform.cc
|
|
@ -46,12 +46,16 @@
|
|||
/*
|
||||
* The pform_modules is a map of the modules that have been defined in
|
||||
* the top level. This should not contain nested modules/programs.
|
||||
* pform_primitives is similar, but for UDP primitives.
|
||||
*/
|
||||
map<perm_string,Module*> pform_modules;
|
||||
/*
|
||||
*/
|
||||
map<perm_string,PUdp*> pform_primitives;
|
||||
|
||||
/*
|
||||
* typedefs in the $root scope go here.
|
||||
*/
|
||||
map<perm_string,data_type_t*>pform_typedefs;
|
||||
set<enum_type_t*>pform_enum_sets;
|
||||
|
||||
std::string vlltype::get_fileline() const
|
||||
{
|
||||
|
|
@ -484,7 +488,12 @@ static void pform_put_wire_in_scope(perm_string name, PWire*net)
|
|||
|
||||
static void pform_put_enum_type_in_scope(enum_type_t*enum_set)
|
||||
{
|
||||
lexical_scope->enum_sets.insert(enum_set);
|
||||
if (lexical_scope) {
|
||||
ivl_assert(*enum_set, lexical_scope);
|
||||
lexical_scope->enum_sets.insert(enum_set);
|
||||
} else {
|
||||
pform_enum_sets.insert(enum_set);
|
||||
}
|
||||
}
|
||||
|
||||
PWire*pform_get_make_wire_in_scope(perm_string name, NetNet::Type net_type, NetNet::PortType port_type, ivl_variable_type_t vt_type)
|
||||
|
|
@ -505,7 +514,13 @@ PWire*pform_get_make_wire_in_scope(perm_string name, NetNet::Type net_type, NetN
|
|||
|
||||
void pform_set_typedef(perm_string name, data_type_t*data_type)
|
||||
{
|
||||
data_type_t*&ref = lexical_scope->typedefs[name];
|
||||
// If we are in a lexical scope (i.e. a package or module)
|
||||
// then put the typedef into that scope. Otherwise, put it
|
||||
// into the $root scope.
|
||||
data_type_t*&ref = lexical_scope
|
||||
? lexical_scope->typedefs[name]
|
||||
: pform_typedefs[name];
|
||||
|
||||
ivl_assert(*data_type, ref == 0);
|
||||
ref = data_type;
|
||||
|
||||
|
|
@ -514,15 +529,25 @@ void pform_set_typedef(perm_string name, data_type_t*data_type)
|
|||
}
|
||||
}
|
||||
|
||||
static data_type_t* test_type_identifier_in_root(perm_string name)
|
||||
{
|
||||
map<perm_string,data_type_t*>::iterator cur = pform_typedefs.find(name);
|
||||
if (cur != pform_typedefs.end())
|
||||
return cur->second;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
data_type_t* pform_test_type_identifier(const char*txt)
|
||||
{
|
||||
// If there is no lexical_scope yet, then there is NO WAY the
|
||||
// identifier can be a type_identifier.
|
||||
if (lexical_scope == 0)
|
||||
return 0;
|
||||
|
||||
perm_string name = lex_strings.make(txt);
|
||||
|
||||
// If there is no lexical_scope yet, then look only in the
|
||||
// $root scope for typedefs.
|
||||
if (lexical_scope == 0) {
|
||||
return test_type_identifier_in_root(name);
|
||||
}
|
||||
|
||||
LexicalScope*cur_scope = lexical_scope;
|
||||
do {
|
||||
map<perm_string,data_type_t*>::iterator cur;
|
||||
|
|
@ -530,7 +555,7 @@ data_type_t* pform_test_type_identifier(const char*txt)
|
|||
// First look to see if this identifier is imported from
|
||||
// a package. If it is, see if it is a type in that
|
||||
// package. If it is, then great. If imported as
|
||||
// something other then a type, then give up now becase
|
||||
// something other than a type, then give up now because
|
||||
// the name has at least shadowed any other possible
|
||||
// meaning for this name.
|
||||
map<perm_string,PPackage*>::iterator cur_pkg;
|
||||
|
|
@ -552,6 +577,10 @@ data_type_t* pform_test_type_identifier(const char*txt)
|
|||
cur_scope = cur_scope->parent_scope();
|
||||
} while (cur_scope);
|
||||
|
||||
// See if there is a typedef in the $root scope.
|
||||
if (data_type_t*tmp = test_type_identifier_in_root(name))
|
||||
return tmp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -170,7 +170,10 @@ void uarray_type_t::pform_dump(ostream&out, unsigned indent) const
|
|||
void struct_type_t::pform_dump(ostream&out, unsigned indent) const
|
||||
{
|
||||
out << setw(indent) << "" << "Struct " << (packed_flag?"packed":"unpacked")
|
||||
<< " with " << members->size() << " members" << endl;
|
||||
<< " with " << (members.get()==0? 0 : members->size()) << " members" << endl;
|
||||
if (members.get()==0)
|
||||
return;
|
||||
|
||||
for (list<struct_member_t*>::iterator cur = members->begin()
|
||||
; cur != members->end() ; ++ cur) {
|
||||
struct_member_t*curp = *cur;
|
||||
|
|
@ -382,6 +385,11 @@ void PETernary::dump(ostream&out) const
|
|||
out << "(" << *expr_ << ")?(" << *tru_ << "):(" << *fal_ << ")";
|
||||
}
|
||||
|
||||
void PETypename::dump(ostream&fd) const
|
||||
{
|
||||
fd << "<type>";
|
||||
}
|
||||
|
||||
void PEUnary::dump(ostream&out) const
|
||||
{
|
||||
switch (op_) {
|
||||
|
|
|
|||
|
|
@ -26,8 +26,12 @@ ivl_variable_type_t struct_type_t::figure_packed_base_type(void) const
|
|||
if (! packed_flag)
|
||||
return IVL_VT_NO_TYPE;
|
||||
|
||||
if (members.get() == 0)
|
||||
return IVL_VT_NO_TYPE;
|
||||
|
||||
ivl_variable_type_t base_type = IVL_VT_BOOL;
|
||||
|
||||
ivl_assert(*this, members.get());
|
||||
for (list<struct_member_t*>::iterator cur = members->begin()
|
||||
; cur != members->end() ; ++ cur) {
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,15 @@ data_type_t::~data_type_t()
|
|||
{
|
||||
}
|
||||
|
||||
ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*scope)
|
||||
{
|
||||
if (cache_type_elaborate_)
|
||||
return cache_type_elaborate_;
|
||||
|
||||
cache_type_elaborate_ = elaborate_type_raw(des, scope);
|
||||
return cache_type_elaborate_;
|
||||
}
|
||||
|
||||
string_type_t::~string_type_t()
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,14 +88,21 @@ struct pform_tf_port_t {
|
|||
*/
|
||||
class data_type_t : public LineInfo {
|
||||
public:
|
||||
inline explicit data_type_t() : cache_type_elaborate_(0) { }
|
||||
virtual ~data_type_t() = 0;
|
||||
// This method is used to figure out the base type of a packed
|
||||
// compound object. Return IVL_VT_NO_TYPE if the type is not packed.
|
||||
virtual ivl_variable_type_t figure_packed_base_type(void)const;
|
||||
// This method is used by the pform dumper to diagnostic dump.
|
||||
virtual void pform_dump(std::ostream&out, unsigned indent) const;
|
||||
|
||||
ivl_type_s* elaborate_type(Design*des, NetScope*scope);
|
||||
|
||||
private:
|
||||
// Elaborate the type to an ivl_type_s type.
|
||||
virtual ivl_type_s* elaborate_type(Design*des, NetScope*scope) const;
|
||||
virtual ivl_type_s* elaborate_type_raw(Design*des, NetScope*scope) const;
|
||||
|
||||
ivl_type_s*cache_type_elaborate_;
|
||||
};
|
||||
|
||||
struct void_type_t : public data_type_t {
|
||||
|
|
@ -109,20 +116,14 @@ struct void_type_t : public data_type_t {
|
|||
* until it is elaborated in a scope.
|
||||
*/
|
||||
struct enum_type_t : public data_type_t {
|
||||
inline enum_type_t(void) : net_type(0) { }
|
||||
// Return the elaborated version of the type.
|
||||
virtual ivl_type_s*elaborate_type(Design*des, NetScope*scope) const;
|
||||
virtual ivl_type_s*elaborate_type_raw(Design*des, NetScope*scope) const;
|
||||
|
||||
ivl_variable_type_t base_type;
|
||||
bool signed_flag;
|
||||
std::auto_ptr< list<pform_range_t> > range;
|
||||
std::auto_ptr< list<named_pexpr_t> > names;
|
||||
LineInfo li;
|
||||
// This is the elaborated type. The enumeration type is
|
||||
// elaborated early so that names can be placed in the scope,
|
||||
// but that means the result needs to be saved for the actual
|
||||
// elaborate_type method to use.
|
||||
netenum_t*net_type;
|
||||
};
|
||||
|
||||
struct struct_member_t : public LineInfo {
|
||||
|
|
@ -134,7 +135,7 @@ struct struct_member_t : public LineInfo {
|
|||
struct struct_type_t : public data_type_t {
|
||||
virtual ivl_variable_type_t figure_packed_base_type(void)const;
|
||||
virtual void pform_dump(std::ostream&out, unsigned indent) const;
|
||||
virtual netstruct_t* elaborate_type(Design*des, NetScope*scope) const;
|
||||
virtual netstruct_t* elaborate_type_raw(Design*des, NetScope*scope) const;
|
||||
|
||||
bool packed_flag;
|
||||
bool union_flag;
|
||||
|
|
@ -147,7 +148,7 @@ struct atom2_type_t : public data_type_t {
|
|||
int type_code;
|
||||
bool signed_flag;
|
||||
|
||||
ivl_type_s* elaborate_type(Design*des, NetScope*scope) const;
|
||||
ivl_type_s* elaborate_type_raw(Design*des, NetScope*scope) const;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -174,7 +175,7 @@ struct vector_type_t : public data_type_t {
|
|||
std::list<pform_range_t>*pd)
|
||||
: base_type(bt), signed_flag(sf), reg_flag(false), integer_flag(false), implicit_flag(false), pdims(pd) { }
|
||||
virtual ivl_variable_type_t figure_packed_base_type(void)const;
|
||||
ivl_type_s* elaborate_type(Design*des, NetScope*scope) const;
|
||||
ivl_type_s* elaborate_type_raw(Design*des, NetScope*scope) const;
|
||||
|
||||
ivl_variable_type_t base_type;
|
||||
bool signed_flag;
|
||||
|
|
@ -216,7 +217,7 @@ struct uarray_type_t : public array_base_t {
|
|||
|
||||
public:
|
||||
virtual void pform_dump(std::ostream&out, unsigned indent) const;
|
||||
virtual ivl_type_s* elaborate_type(Design*des, NetScope*scope) const;
|
||||
virtual ivl_type_s* elaborate_type_raw(Design*des, NetScope*scope) const;
|
||||
};
|
||||
|
||||
struct real_type_t : public data_type_t {
|
||||
|
|
@ -224,14 +225,14 @@ struct real_type_t : public data_type_t {
|
|||
inline explicit real_type_t(type_t tc) : type_code(tc) { }
|
||||
type_t type_code;
|
||||
|
||||
ivl_type_s* elaborate_type(Design*des, NetScope*scope) const;
|
||||
ivl_type_s* elaborate_type_raw(Design*des, NetScope*scope) const;
|
||||
};
|
||||
|
||||
struct string_type_t : public data_type_t {
|
||||
inline explicit string_type_t() { }
|
||||
~string_type_t();
|
||||
|
||||
ivl_type_s* elaborate_type(Design*des, NetScope*scope) const;
|
||||
ivl_type_s* elaborate_type_raw(Design*des, NetScope*scope) const;
|
||||
};
|
||||
|
||||
struct class_type_t : public data_type_t {
|
||||
|
|
@ -271,7 +272,7 @@ struct class_type_t : public data_type_t {
|
|||
// without waiting for any constructor.
|
||||
std::vector<Statement*> initialize_static;
|
||||
|
||||
ivl_type_s* elaborate_type(Design*, NetScope*) const;
|
||||
ivl_type_s* elaborate_type_raw(Design*, NetScope*) const;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ bool NetCase::synth_async(Design*des, NetScope*scope,
|
|||
|
||||
unsigned mux_size = max_guard_value + 1;
|
||||
|
||||
// If the sel_width can select more then just the explicit
|
||||
// If the sel_width can select more than just the explicit
|
||||
// guard values, and there is a default statement, then adjust
|
||||
// the mux size to allow for the implicit selections.
|
||||
if (statement_default && ((1U<<sel_width) > mux_size)) {
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ int blif_errors = 0;
|
|||
|
||||
static void emit_blif(const char*blif_path, ivl_design_t des, ivl_scope_t model);
|
||||
|
||||
static int process_scan_fun(ivl_process_t net, void*raw)
|
||||
static int process_scan_fun(ivl_process_t net, void* /*raw*/)
|
||||
{
|
||||
fprintf(stderr, "%s:%u: sorry: BLIF: Processes not supported yet.\n",
|
||||
ivl_process_file(net), ivl_process_lineno(net));
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ int load_footprints(void)
|
|||
}
|
||||
|
||||
/*
|
||||
* The fpparse funciton calls back the callback_fp_element function
|
||||
* The fpparse function calls back the callback_fp_element function
|
||||
* for each Element that it parses. The check_footprint function
|
||||
* stores in the cur_footprint variable the name of the footprint that
|
||||
* we are trying to find in the file. The callback uses that name to
|
||||
|
|
|
|||
|
|
@ -267,8 +267,9 @@ static expr_sign_t expr_get_sign_type(ivl_expr_t expr, unsigned wid,
|
|||
break;
|
||||
}
|
||||
|
||||
/* Check for a self-determined context. */
|
||||
if ((rtn == NO_SIGN) && (wid != expr_wid) &&
|
||||
/* Check for a self-determined context. A zero width expression
|
||||
* is special and is not considered a self determined context. */
|
||||
if ((rtn == NO_SIGN) && (wid != expr_wid) && expr_wid &&
|
||||
! (is_full_prec && ((expr_wid < wid) || (type == IVL_EX_SIGNAL)))) {
|
||||
if (ivl_expr_signed(expr)) rtn = NEED_SIGNED;
|
||||
else rtn = NEED_UNSIGNED;
|
||||
|
|
|
|||
|
|
@ -917,8 +917,8 @@ static unsigned has_func_disable(ivl_scope_t scope, ivl_statement_t stmt)
|
|||
rtn = scope == ivl_stmt_call(stmt);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "%s:%u: vlog95 error: Unknown statment type (%d) "
|
||||
"in functin disable check.\n",
|
||||
fprintf(stderr, "%s:%u: vlog95 error: Unknown statement type (%d) "
|
||||
"in function disable check.\n",
|
||||
ivl_stmt_file(stmt),
|
||||
ivl_stmt_lineno(stmt),
|
||||
(int)ivl_statement_type(stmt));
|
||||
|
|
@ -1187,7 +1187,7 @@ int emit_scope(ivl_scope_t scope, ivl_scope_t parent)
|
|||
name_return);
|
||||
free(name_return);
|
||||
} else emit_stmt(scope, body);
|
||||
/* A non-block statment may need a named block for a return. */
|
||||
/* A non-block statement may need a named block for a return. */
|
||||
} else if (has_func_disable(scope, body)) {
|
||||
char *name_return = get_func_return_name(scope);
|
||||
fprintf(vlog_out, "%*cbegin: %s\n", indent, ' ',
|
||||
|
|
|
|||
|
|
@ -214,16 +214,27 @@ static void emit_stmt_lval_darray(ivl_scope_t scope, ivl_lval_t lval,
|
|||
* Class or class properties are not supported in vlog95, but this assignment
|
||||
* can be translated correctly.
|
||||
*/
|
||||
static void emit_stmt_lval_class(ivl_scope_t scope, ivl_lval_t lval,
|
||||
ivl_signal_t sig)
|
||||
static ivl_type_t emit_stmt_lval_class(ivl_scope_t scope, ivl_lval_t lval)
|
||||
{
|
||||
ivl_lval_t nest = ivl_lval_nest(lval);
|
||||
ivl_signal_t sig = ivl_lval_sig(lval);
|
||||
ivl_type_t type;
|
||||
int idx = ivl_lval_property_idx(lval);
|
||||
emit_scope_call_path(scope, ivl_signal_scope(sig));
|
||||
emit_id(ivl_signal_basename(sig));
|
||||
if (idx >= 0) {
|
||||
ivl_type_t sig_type = ivl_signal_net_type(sig);
|
||||
fprintf(vlog_out, ".%s", ivl_type_prop_name(sig_type, idx));
|
||||
|
||||
if (nest) {
|
||||
type = emit_stmt_lval_class(scope, nest);
|
||||
assert(type);
|
||||
} else {
|
||||
assert(sig);
|
||||
emit_scope_call_path(scope, ivl_signal_scope(sig));
|
||||
emit_id(ivl_signal_basename(sig));
|
||||
type = ivl_signal_net_type(sig);
|
||||
}
|
||||
|
||||
if (idx >= 0) {
|
||||
fprintf(vlog_out, ".%s", ivl_type_prop_name(type, idx));
|
||||
return ivl_type_prop_type(type, idx);
|
||||
} else return 0;
|
||||
}
|
||||
|
||||
static void emit_stmt_lval_piece(ivl_scope_t scope, ivl_lval_t lval)
|
||||
|
|
@ -234,14 +245,20 @@ static void emit_stmt_lval_piece(ivl_scope_t scope, ivl_lval_t lval)
|
|||
unsigned width = ivl_lval_width(lval);
|
||||
int msb, lsb;
|
||||
assert(width > 0);
|
||||
assert(sig);
|
||||
|
||||
/* A class supports a nested L-value so it may not have a signal
|
||||
* at this level. */
|
||||
if (! sig) {
|
||||
(void) emit_stmt_lval_class(scope, lval);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ivl_signal_data_type(sig)) {
|
||||
case IVL_VT_DARRAY:
|
||||
emit_stmt_lval_darray(scope, lval, sig);
|
||||
return;
|
||||
case IVL_VT_CLASS:
|
||||
emit_stmt_lval_class(scope, lval, sig);
|
||||
(void) emit_stmt_lval_class(scope, lval);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -566,7 +566,7 @@ int ExpFunc::emit(ostream&out, Entity*ent, Architecture*arc)
|
|||
out << ")";
|
||||
|
||||
} else {
|
||||
// If this function has an elaborated defintion, and if
|
||||
// If this function has an elaborated definition, and if
|
||||
// that definition is in a package, then include the
|
||||
// package name as a scope qualifier. This assures that
|
||||
// the SV elaborator finds the correct VHDL elaborated
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ class class_type : public __vpiHandle {
|
|||
void set_property(size_t idx, const std::string&name, const std::string&type);
|
||||
|
||||
// This method is called after all the properties are
|
||||
// defined. This calculates information about the defintion.
|
||||
// defined. This calculates information about the definition.
|
||||
void finish_setup(void);
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -1024,7 +1024,7 @@ includes an implicit pop, but sometimes it is necessary to pop
|
|||
explicitly.
|
||||
|
||||
The <skip> is the number of top positions on the stack to keep,
|
||||
beforing starting to pop. This allows for popping positions other then
|
||||
beforing starting to pop. This allows for popping positions other than
|
||||
the top of the stack.
|
||||
|
||||
* %pow <bit-l>, <bit-r>, <wid>
|
||||
|
|
|
|||
Loading…
Reference in New Issue