diff --git a/PWire.cc b/PWire.cc index da424e6d4..4ad7fb391 100644 --- a/PWire.cc +++ b/PWire.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2007 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2009 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 @@ -29,8 +29,8 @@ PWire::PWire(perm_string n, : name_(n), type_(t), port_type_(pt), data_type_(dt), signed_(false), isint_(false), port_msb_(0), port_lsb_(0), port_set_(false), - net_msb_(0), net_lsb_(0), net_set_(false), error_cnt_(0), - lidx_(0), ridx_(0), discipline_(0) + net_msb_(0), net_lsb_(0), net_set_(false), is_scalar_(false), + error_cnt_(0), lidx_(0), ridx_(0), discipline_(0) { if (t == NetNet::INTEGER) { type_ = NetNet::REG; @@ -135,7 +135,12 @@ bool PWire::get_isint() const return isint_; } -void PWire::set_range(PExpr*m, PExpr*l, PWSRType type) +bool PWire::get_scalar() const +{ + return is_scalar_; +} + +void PWire::set_range(PExpr*m, PExpr*l, PWSRType type, bool is_scalar) { switch (type) { case SR_PORT: @@ -147,6 +152,7 @@ void PWire::set_range(PExpr*m, PExpr*l, PWSRType type) port_msb_ = m; port_lsb_ = l; port_set_ = true; + is_scalar_ = is_scalar; } return; @@ -159,6 +165,7 @@ void PWire::set_range(PExpr*m, PExpr*l, PWSRType type) net_msb_ = m; net_lsb_ = l; net_set_ = true; + is_scalar_ = is_scalar; } return; @@ -181,6 +188,7 @@ void PWire::set_range(PExpr*m, PExpr*l, PWSRType type) net_msb_ = m; net_lsb_ = l; net_set_ = true; + is_scalar_ = is_scalar; } return; } diff --git a/PWire.h b/PWire.h index 697fd732e..d87738e08 100644 --- a/PWire.h +++ b/PWire.h @@ -1,7 +1,7 @@ #ifndef __PWire_H #define __PWire_H /* - * Copyright (c) 1998-2007 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2009 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 @@ -70,11 +70,12 @@ class PWire : public LineInfo { void set_signed(bool flag); bool get_signed() const; bool get_isint() const; + bool get_scalar() const; bool set_data_type(ivl_variable_type_t dt); ivl_variable_type_t get_data_type() const; - void set_range(PExpr*msb, PExpr*lsb, PWSRType type); + void set_range(PExpr*msb, PExpr*lsb, PWSRType type, bool is_scalar); void set_memory_idx(PExpr*ldx, PExpr*rdx); @@ -104,6 +105,7 @@ class PWire : public LineInfo { PExpr*net_msb_; PExpr*net_lsb_; bool net_set_; + bool is_scalar_; unsigned error_cnt_; // If this wire is actually a memory, these indices will give diff --git a/elab_expr.cc b/elab_expr.cc index f775141e1..3eeb7a0a0 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -2642,11 +2642,13 @@ NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope, if (name_tail.index.size() > 1) word_sel = name_tail.index.back().sel; - if (res->expr_type() == IVL_VT_REAL && + if (net->get_scalar() && word_sel != index_component_t::SEL_NONE) { - cerr << get_fileline() << ": error: " - << "can not select part of real array word: " - << net->name() <<"[" << *word_index << "]" << endl; + cerr << get_fileline() << ": error: can not select part of "; + if (res->expr_type() == IVL_VT_REAL) cerr << "real"; + else cerr << "scalar"; + cerr << " array word: " << net->name() + <<"[" << *word_index << "]" << endl; des->errors += 1; delete res; return 0; @@ -2946,10 +2948,12 @@ NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope, if (! path_.back().index.empty()) use_sel = path_.back().index.back().sel; - if (node->expr_type() == IVL_VT_REAL && + if (net->get_scalar() && use_sel != index_component_t::SEL_NONE) { - cerr << get_fileline() << ": error: " - << "can not select part of real: " << net->name() << endl; + cerr << get_fileline() << ": error: can not select part of "; + if (node->expr_type() == IVL_VT_REAL) cerr << "real: "; + else cerr << "scalar: "; + cerr << net->name() << endl; des->errors += 1; return 0; } diff --git a/elab_lval.cc b/elab_lval.cc index 63f0c40c2..7478eab8c 100644 --- a/elab_lval.cc +++ b/elab_lval.cc @@ -199,10 +199,12 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, return elaborate_lval_net_word_(des, scope, reg); // This must be after the array word elaboration above! - if (reg->data_type() == IVL_VT_REAL && + if (reg->get_scalar() && use_sel != index_component_t::SEL_NONE) { - cerr << get_fileline() << ": error: " - << "can not select part of real: " << reg->name() << endl; + cerr << get_fileline() << ": error: can not select part of "; + if (reg->data_type() == IVL_VT_REAL) cerr << "real: "; + else cerr << "scalar: "; + cerr << reg->name() << endl; des->errors += 1; return 0; } @@ -301,12 +303,13 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des, if (name_tail.index.size() > 1) use_sel = name_tail.index.back().sel; - if (reg->data_type() == IVL_VT_REAL && + if (reg->get_scalar() && use_sel != index_component_t::SEL_NONE) { - perm_string name = peek_tail_name(path_); - cerr << get_fileline() << ": error: " - << "can not select part of real array word: " - << reg->name() << "[" << *word << "]" << endl; + cerr << get_fileline() << ": error: can not select part of "; + if (reg->data_type() == IVL_VT_REAL) cerr << "real"; + else cerr << "scalar"; + cerr << " array word: " << reg->name() + << "[" << *word << "]" << endl; des->errors += 1; return 0; } diff --git a/elab_net.cc b/elab_net.cc index 40cbc7383..143674c6e 100644 --- a/elab_net.cc +++ b/elab_net.cc @@ -466,10 +466,13 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, /* The array has a part/bit select at the end. */ if (name_tail.index.size() > sig->array_dimensions()) { - if (sig->data_type() == IVL_VT_REAL) { + if (sig->get_scalar()) { cerr << get_fileline() << ": error: " - << "can not select part of real array word: " - << sig->name() << "[" << widx_val << "]" << endl; + << "can not select part of "; + if (sig->data_type() == IVL_VT_REAL) cerr << "real"; + else cerr << "scalar"; + cerr << " array word: " << sig->name() + << "[" << widx_val << "]" << endl; des->errors += 1; return 0; } @@ -489,10 +492,12 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, lidx = lidx_tmp; } } else if (!name_tail.index.empty()) { - if (sig->data_type() == IVL_VT_REAL) { + if (sig->get_scalar()) { cerr << get_fileline() << ": error: " - << "can not select part of real: " - << sig->name() << endl; + << "can not select part of "; + if (sig->data_type() == IVL_VT_REAL) cerr << "real: "; + else cerr << "scalar: "; + cerr << sig->name() << endl; des->errors += 1; return 0; } diff --git a/elab_sig.cc b/elab_sig.cc index 1b26ca920..c4310a745 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -599,9 +599,11 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const } ret_sig = new NetNet(scope, fname, NetNet::REG, mnum, lnum); + ret_sig->set_scalar(false); } else { ret_sig = new NetNet(scope, fname, NetNet::REG); + ret_sig->set_scalar(true); } ret_sig->set_line(*this); ret_sig->set_signed(return_type_.type == PTF_REG_S); @@ -614,6 +616,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const ret_sig->set_line(*this); ret_sig->set_signed(true); ret_sig->set_isint(true); + ret_sig->set_scalar(false); ret_sig->port_type(NetNet::POUTPUT); ret_sig->data_type(IVL_VT_LOGIC); break; @@ -623,6 +626,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const ret_sig->set_line(*this); ret_sig->set_signed(false); ret_sig->set_isint(false); + ret_sig->set_scalar(false); ret_sig->port_type(NetNet::POUTPUT); ret_sig->data_type(IVL_VT_LOGIC); break; @@ -633,6 +637,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const ret_sig->set_line(*this); ret_sig->set_signed(true); ret_sig->set_isint(false); + ret_sig->set_scalar(true); ret_sig->port_type(NetNet::POUTPUT); ret_sig->data_type(IVL_VT_REAL); break; @@ -850,10 +855,15 @@ void PWhile::elaborate_sig(Design*des, NetScope*scope) const NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const { NetNet::Type wtype = type_; - if (wtype == NetNet::IMPLICIT) + bool is_implicit_scalar = false; + if (wtype == NetNet::IMPLICIT) { wtype = NetNet::WIRE; - if (wtype == NetNet::IMPLICIT_REG) + is_implicit_scalar = true; + } + if (wtype == NetNet::IMPLICIT_REG) { wtype = NetNet::REG; + is_implicit_scalar = true; + } unsigned wid = 1; long lsb = 0, msb = 0; @@ -902,6 +912,8 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const delete texpr; nmsb = pmsb; nlsb = plsb; + /* An implicit port can have a range so note that here. */ + is_implicit_scalar = false; } if (!port_set_) assert(port_msb_ == 0 && port_lsb_ == 0); if (port_msb_ == 0) assert(port_lsb_ == 0); @@ -1095,8 +1107,11 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const } if (debug_elaborate) { - cerr << get_fileline() << ": debug: Create signal " - << wtype << " ["< 0) { cerr << " [" << array_s0 << ":" << array_e0 << "]" << endl; } @@ -1126,6 +1141,8 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const sig->port_type(port_type_); sig->set_signed(get_signed()); sig->set_isint(get_isint()); + if (is_implicit_scalar) sig->set_scalar(true); + else sig->set_scalar(get_scalar()); if (ivl_discipline_t dis = get_discipline()) { sig->set_discipline(dis); diff --git a/netlist.cc b/netlist.cc index d76b6d443..4a69c5e80 100644 --- a/netlist.cc +++ b/netlist.cc @@ -491,8 +491,8 @@ const Link& NetDelaySrc::condit_pin() const NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins) : NetObj(s, n, 1), type_(t), port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE), - signed_(false), isint_(false), discipline_(0), msb_(npins-1), lsb_(0), - dimensions_(0), + signed_(false), isint_(false), is_scalar_(false), + discipline_(0), msb_(npins-1), lsb_(0), dimensions_(0), s0_(0), e0_(0), local_flag_(false), eref_count_(0), lref_count_(0) { assert(s); @@ -544,7 +544,8 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, long ms, long ls) : NetObj(s, n, 1), type_(t), port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE), signed_(false), - isint_(false), discipline_(0), msb_(ms), lsb_(ls), dimensions_(0), s0_(0), e0_(0), + isint_(false), is_scalar_(false), discipline_(0), msb_(ms), lsb_(ls), + dimensions_(0), s0_(0), e0_(0), local_flag_(false), eref_count_(0), lref_count_(0) { assert(s); @@ -594,7 +595,8 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, : NetObj(s, n, calculate_count(array_s, array_e)), type_(t), port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE), signed_(false), isint_(false), - discipline_(0), msb_(ms), lsb_(ls), dimensions_(1), s0_(array_s), e0_(array_e), + is_scalar_(false), discipline_(0), msb_(ms), lsb_(ls), + dimensions_(1), s0_(array_s), e0_(array_e), local_flag_(false), eref_count_(0), lref_count_(0) { ivl_assert(*this, s); @@ -727,6 +729,16 @@ void NetNet::set_isint(bool flag) isint_ = flag; } +bool NetNet::get_scalar() const +{ + return is_scalar_; +} + +void NetNet::set_scalar(bool flag) +{ + is_scalar_ = flag; +} + ivl_discipline_t NetNet::get_discipline() const { return discipline_; diff --git a/netlist.h b/netlist.h index a105a0506..8375aad00 100644 --- a/netlist.h +++ b/netlist.h @@ -581,6 +581,9 @@ class NetNet : public NetObj { bool get_isint() const; void set_isint(bool); + bool get_scalar() const; + void set_scalar(bool); + /* Attach a discipline to the net. */ ivl_discipline_t get_discipline() const; void set_discipline(ivl_discipline_t dis); @@ -650,6 +653,7 @@ class NetNet : public NetObj { ivl_variable_type_t data_type_; bool signed_; bool isint_; // original type of integer + bool is_scalar_; ivl_discipline_t discipline_; long msb_, lsb_; diff --git a/pform.cc b/pform.cc index 0127297a1..eee85f1ad 100644 --- a/pform.cc +++ b/pform.cc @@ -1031,13 +1031,13 @@ static void pform_set_net_range(perm_string name, if (range == 0) { /* This is the special case that we really mean a scalar. Set a fake range. */ - cur->set_range(0, 0, rt); + cur->set_range(0, 0, rt, true); } else { assert(range->count() == 2); assert((*range)[0]); assert((*range)[1]); - cur->set_range((*range)[0], (*range)[1], rt); + cur->set_range((*range)[0], (*range)[1], rt, false); } cur->set_signed(signed_flag); @@ -1399,14 +1399,16 @@ void pform_module_define_port(const struct vlltype&li, if (range == 0) { cur->set_range(0, 0, (type == NetNet::IMPLICIT) ? SR_PORT : - SR_BOTH); + SR_BOTH, + true); } else { assert(range->count() == 2); assert((*range)[0]); assert((*range)[1]); cur->set_range((*range)[0], (*range)[1], - (type == NetNet::IMPLICIT) ? SR_PORT : SR_BOTH); + (type == NetNet::IMPLICIT) ? SR_PORT : SR_BOTH, + false); } if (attr) { @@ -1486,7 +1488,7 @@ void pform_makewire(const vlltype&li, perm_string name, << " to " << dt << "." << endl; } ivl_assert(*cur, flag); - cur->set_range(0, 0, SR_NET); + cur->set_range(0, 0, SR_NET, true); cur->set_signed(true); break; default: @@ -1676,7 +1678,7 @@ svector*pform_make_task_ports(NetNet::PortType pt, /* If there is a range involved, it needs to be set. */ if (range) - curw->set_range((*range)[0], (*range)[1], SR_PORT); + curw->set_range((*range)[0], (*range)[1], SR_PORT, false); svector*tmp = new svector(*res, curw); @@ -1936,7 +1938,7 @@ static void pform_set_reg_integer(perm_string name) cur->set_range(new PENumber(new verinum(integer_width-1, integer_width)), new PENumber(new verinum((uint64_t)0, integer_width)), - SR_NET); + SR_NET, false); cur->set_signed(true); } @@ -1967,7 +1969,7 @@ static void pform_set_reg_time(perm_string name) cur->set_range(new PENumber(new verinum(TIME_WIDTH-1, integer_width)), new PENumber(new verinum((uint64_t)0, integer_width)), - SR_NET); + SR_NET, false); } void pform_set_reg_time(list*names)