Skip to content
Browse files

Parse support for dynamic arrays.

This includes limited support for dynamic arrays down to the code
generator, and some stubs in the vvp code generator and vvp run time.
  • Loading branch information...
1 parent a337a93 commit 14f229de308148bffef6b3770bfe26221ac8a10a @steveicarus committed Jul 13, 2012
Showing with 902 additions and 141 deletions.
  1. +1 −1 Makefile.in
  2. +10 −0 PExpr.cc
  3. +19 −1 PExpr.h
  4. +1 −0 PWire.h
  5. +21 −3 design_dump.cc
  6. +120 −3 elab_expr.cc
  7. +2 −2 elab_lval.cc
  8. +51 −17 elab_sig.cc
  9. +1 −0 ivl_target.h
  10. +32 −0 netdarray.cc
  11. +40 −0 netdarray.h
  12. +2 −1 netenum.h
  13. +60 −24 netlist.cc
  14. +7 −6 netlist.h
  15. +17 −15 netmisc.cc
  16. +1 −1 netstruct.h
  17. +13 −13 nettypes.cc
  18. +32 −9 nettypes.h
  19. +5 −5 parse.y
  20. +5 −0 pform_dump.cc
  21. +1 −0 sv_vpi_user.h
  22. +6 −6 t-dll-api.cc
  23. +9 −22 t-dll.cc
  24. +1 −2 t-dll.h
  25. +1 −1 tgt-stub/expression.c
  26. +21 −6 tgt-stub/stub.c
  27. +5 −0 tgt-vvp/vvp_scope.c
  28. +2 −1 vpi/Makefile.in
  29. +91 −0 vpi/sys_darray.c
  30. +2 −0 vpi/sys_table.c
  31. +6 −0 vpi_user.h
  32. +1 −1 vvp/Makefile.in
  33. +1 −0 vvp/compile.h
  34. +1 −0 vvp/lexor.lex
  35. +4 −1 vvp/parse.y
  36. +87 −0 vvp/vpi_darray.cc
  37. +2 −0 vvp/vpi_priv.h
  38. +7 −0 vvp/vvp_net.cc
  39. +23 −0 vvp/vvp_net.h
  40. +74 −0 vvp/vvp_net_sig.cc
  41. +57 −0 vvp/vvp_net_sig.h
  42. +24 −0 vvp/vvp_object.h
  43. +36 −0 vvp/words.cc
View
2 Makefile.in
@@ -108,7 +108,7 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
elab_scope.o elab_sig.o elab_sig_analog.o emit.o eval.o eval_attrib.o \
eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \
load_module.o netlist.o netmisc.o nettypes.o net_analog.o net_assign.o \
- net_design.o \
+ net_design.o netdarray.o \
netenum.o netstruct.o net_event.o net_expr.o net_func.o net_func_eval.o \
net_link.o net_modulo.o \
net_nex_input.o net_nex_output.o net_proc.o net_scope.o net_tran.o \
View
10 PExpr.cc
@@ -371,6 +371,16 @@ bool PEIdent::has_aa_term(Design*des, NetScope*scope) const
return false;
}
+PENew::PENew(PExpr*size_expr)
+: size_(size_expr)
+{
+}
+
+PENew::~PENew()
+{
+ delete size_;
+}
+
PENumber::PENumber(verinum*vp)
: value_(vp)
{
View
20 PExpr.h
@@ -439,6 +439,18 @@ class PEIdent : public PExpr {
long&midx, long&lidx) const;
};
+class PENew : public PExpr {
+
+ public:
+ explicit PENew (PExpr*s);
+ ~PENew();
+
+ virtual void dump(ostream&) const;
+
+ private:
+ PExpr*size_;
+};
+
class PENumber : public PExpr {
public:
@@ -720,9 +732,13 @@ class PECallFunction : public PExpr {
NetExpr* cast_to_width_(NetExpr*expr, unsigned wid) const;
+ NetExpr*elaborate_expr_method_(Design*des, NetScope*scope,
+ unsigned expr_wid) const;
+#if 0
+ NetExpr*elaborate_expr_string_method_(Design*des, NetScope*scope) const;
NetExpr*elaborate_expr_enum_method_(Design*des, NetScope*scope,
unsigned expr_wid) const;
- NetExpr*elaborate_expr_string_method_(Design*des, NetScope*scope) const;
+#endif
NetExpr* elaborate_sfunc_(Design*des, NetScope*scope,
unsigned expr_wid,
@@ -731,6 +747,8 @@ class PECallFunction : public PExpr {
unsigned expr_wid) const;
unsigned test_width_sfunc_(Design*des, NetScope*scope,
width_mode_t&mode);
+ unsigned test_width_method_(Design*des, NetScope*scope,
+ width_mode_t&mode);
};
/*
View
1 PWire.h
@@ -33,6 +33,7 @@ class ostream;
class PExpr;
class Design;
+class netdarray_t;
/*
* The different type of PWire::set_range() calls.
View
24 design_dump.cc
@@ -28,6 +28,7 @@
# include "netlist.h"
# include "compiler.h"
# include "discipline.h"
+# include "netdarray.h"
# include "ivl_assert.h"
# include "PExpr.h"
@@ -104,6 +105,9 @@ ostream& operator << (ostream&o, ivl_variable_type_t val)
case IVL_VT_STRING:
o << "string";
break;
+ case IVL_VT_DARRAY:
+ o << "darray";
+ break;
}
return o;
}
@@ -193,11 +197,21 @@ void NetDelaySrc::dump(ostream&o, unsigned ind) const
dump_node_pins(o, ind+4);
}
+static inline ostream&operator<<(ostream&out, const netrange_t&that)
+{
+ if (that.defined())
+ out << "[" << that.get_msb() << ":" << that.get_lsb() << "]";
+ else
+ out << "[]";
+
+ return out;
+}
+
ostream&operator<<(ostream&out, const list<netrange_t>&rlist)
{
for (list<netrange_t>::const_iterator cur = rlist.begin()
; cur != rlist.end() ; ++cur) {
- out << "[" << cur->msb << ":" << cur->lsb << "]";
+ out << *cur;
}
return out;
}
@@ -206,7 +220,7 @@ ostream&operator<<(ostream&out, const vector<netrange_t>&rlist)
{
for (vector<netrange_t>::const_iterator cur = rlist.begin()
; cur != rlist.end() ; ++cur) {
- out << "[" << cur->msb << ":" << cur->lsb << "]";
+ out << *cur;
}
return out;
}
@@ -244,7 +258,11 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
if (ivl_discipline_t dis = get_discipline())
o << " discipline=" << dis->name();
- o << " packed dims: " << packed_dims_;
+ if (netdarray_t*darray = darray_type())
+ o << " dynamic array of " << darray->data_type();
+
+ if (!packed_dims_.empty())
+ o << " packed dims: " << packed_dims_;
o << " (eref=" << peek_eref() << ", lref=" << peek_lref() << ")";
if (scope())
View
123 elab_expr.cc
@@ -96,6 +96,7 @@ NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
break;
case IVL_VT_VOID:
case IVL_VT_NO_TYPE:
+ case IVL_VT_DARRAY:
ivl_assert(*expr, 0);
break;
}
@@ -1021,6 +1022,15 @@ unsigned PECallFunction::test_width(Design*des, NetScope*scope,
return expr_width_;
}
+ if (test_width_method_(des, scope, mode)) {
+ if (debug_elaborate)
+ cerr << get_fileline() << ": debug: test_width "
+ << "of method returns width " << expr_width_
+ << ", type=" << expr_type_
+ << "." << endl;
+ return expr_width_;
+ }
+
if (debug_elaborate)
cerr << get_fileline() << ": debug: test_width "
<< "cannot find definition of " << path_
@@ -1050,6 +1060,46 @@ unsigned PECallFunction::test_width(Design*des, NetScope*scope,
return 0;
}
+unsigned PECallFunction::test_width_method_(Design*des, NetScope*scope,
+ width_mode_t&mode)
+{
+ if (!gn_system_verilog())
+ return 0;
+
+ // This is only useful if the path is at least 2 elements. For
+ // example, foo.bar() is a method, bar() is not.
+ if (path_.size() < 2)
+ return 0;
+
+ pform_name_t use_path = path_;
+ perm_string method_name = peek_tail_name(use_path);
+ use_path.pop_back();
+
+ NetNet *net;
+ const NetExpr *par;
+ NetEvent *eve;
+ const NetExpr *ex1, *ex2;
+
+ symbol_search(this, des, scope, use_path,
+ net, par, eve, ex1, ex2);
+
+ if (net == 0)
+ return 0;
+
+ netdarray_t*darray = net->darray_type();
+
+ // function int size()
+ if (darray && method_name == "size") {
+ expr_type_ = IVL_VT_BOOL;
+ expr_width_ = 32;
+ min_width_ = expr_width_;
+ signed_flag_= true;
+ return expr_width_;
+ }
+
+ return 0;
+}
+
NetExpr*PECallFunction::cast_to_width_(NetExpr*expr, unsigned wid) const
{
/* If the expression is a const, then replace it with a new
@@ -1582,6 +1632,13 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
return elaborate_access_func_(des, scope, access_nature,
expr_wid);
+ // Maybe this is a method attached to a signal? If this
+ // is SystemVerilog then try that possibility.
+ if (gn_system_verilog()) {
+ NetExpr*tmp = elaborate_expr_method_(des, scope, expr_wid);
+ if (tmp) return tmp;
+ }
+#if 0
// Maybe this is a method attached to an enumeration name? If
// this is system verilog, then test to see if the name is
// really a method attached to an object.
@@ -1597,7 +1654,7 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
NetExpr*tmp = elaborate_expr_string_method_(des, scope);
if (tmp) return tmp;
}
-
+#endif
// Nothing was found so report this as an error.
cerr << get_fileline() << ": error: No function named `" << path_
<< "' found in this context (" << scope_path(scope) << ")."
@@ -1736,6 +1793,64 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
return 0;
}
+NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
+ unsigned expr_wid) const
+{
+ pform_name_t use_path = path_;
+ perm_string method_name = peek_tail_name(use_path);
+ use_path.pop_back();
+
+ NetNet *net;
+ const NetExpr *par;
+ NetEvent *eve;
+ const NetExpr *ex1, *ex2;
+
+ symbol_search(this, des, scope, use_path,
+ net, par, eve, ex1, ex2);
+
+ if (net == 0)
+ return 0;
+
+ if (net->data_type() == IVL_VT_STRING) {
+
+ if (method_name == "len") {
+ NetESFunc*sys_expr = new NetESFunc("$ivl_string_method$len",
+ IVL_VT_BOOL, 32, 1);
+ sys_expr->parm(0, new NetESignal(net));
+ return sys_expr;
+ }
+ }
+
+ if (netenum_t*netenum = net->enumeration()) {
+ // We may need the net expression for the
+ // enumeration variable so get it.
+ NetESignal*expr = new NetESignal(net);
+ expr->set_line(*this);
+ // This expression cannot be a select!
+ assert(use_path.back().index.empty());
+
+ PExpr*tmp = parms_.size() ? parms_[0] : 0;
+ return check_for_enum_methods(this, des, scope,
+ netenum, use_path,
+ method_name, expr,
+ expr_wid, tmp,
+ parms_.size());
+ }
+
+ if (net->darray_type()) {
+
+ if (method_name == "size") {
+ NetESFunc*sys_expr = new NetESFunc("$ivl_darray_method$size",
+ IVL_VT_BOOL, 32, 1);
+ sys_expr->parm(0, new NetESignal(net));
+ sys_expr->set_line(*this);
+ return sys_expr;
+ }
+ }
+
+ return 0;
+}
+#if 0
NetExpr* PECallFunction::elaborate_expr_enum_method_(Design*des, NetScope*scope,
unsigned expr_wid) const
{
@@ -1775,7 +1890,8 @@ NetExpr* PECallFunction::elaborate_expr_enum_method_(Design*des, NetScope*scope,
return 0;
}
-
+#endif
+#if 0
NetExpr* PECallFunction::elaborate_expr_string_method_(Design*des, NetScope*scope) const
{
pform_name_t use_path = path_;
@@ -1808,6 +1924,7 @@ NetExpr* PECallFunction::elaborate_expr_string_method_(Design*des, NetScope*scop
return 0;
}
+#endif
unsigned PECastSize::test_width(Design*des, NetScope*scope, width_mode_t&)
{
@@ -3455,7 +3572,7 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
// We want the last range, which is where we work.
const netrange_t&rng = packed.back();
- if (rng.msb < rng.lsb) {
+ if (rng.get_msb() < rng.get_lsb()) {
offset = -wid + 1;
}
View
4 elab_lval.cc
@@ -574,9 +574,9 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
// We want the last range, which is where we work.
const netrange_t&rng = packed.back();
- if (((rng.msb < rng.lsb) &&
+ if (((rng.get_msb() < rng.get_lsb()) &&
use_sel == index_component_t::SEL_IDX_UP) ||
- ((rng.msb > rng.lsb) &&
+ ((rng.get_msb() > rng.get_lsb()) &&
use_sel == index_component_t::SEL_IDX_DO)) {
offset = -wid + 1;
}
View
68 elab_sig.cc
@@ -32,7 +32,9 @@
# include "compiler.h"
# include "netlist.h"
# include "netmisc.h"
+# include "netenum.h"
# include "netstruct.h"
+# include "netdarray.h"
# include "util.h"
# include "ivl_assert.h"
@@ -821,10 +823,10 @@ static bool evaluate_ranges(Design*des, NetScope*scope,
for (list<pform_range_t>::const_iterator cur = rlist.begin()
; cur != rlist.end() ; ++cur) {
- netrange_t lrng;
+ long use_msb, use_lsb;
NetExpr*texpr = elab_and_eval(des, scope, cur->first, -1, true);
- if (! eval_as_long(lrng.msb, texpr)) {
+ if (! eval_as_long(use_msb, texpr)) {
cerr << cur->first->get_fileline() << ": error: "
"Range expressions must be constant." << endl;
cerr << cur->first->get_fileline() << " : "
@@ -837,7 +839,7 @@ static bool evaluate_ranges(Design*des, NetScope*scope,
delete texpr;
texpr = elab_and_eval(des, scope, cur->second, -1, true);
- if (! eval_as_long(lrng.lsb, texpr)) {
+ if (! eval_as_long(use_lsb, texpr)) {
cerr << cur->second->get_fileline() << ": error: "
"Range expressions must be constant." << endl;
cerr << cur->second->get_fileline() << " : "
@@ -849,7 +851,7 @@ static bool evaluate_ranges(Design*des, NetScope*scope,
delete texpr;
- llist.push_back(lrng);
+ llist.push_back(netrange_t(use_msb, use_lsb));
}
return bad_msb | bad_lsb;
@@ -899,9 +901,9 @@ bool test_ranges_eeq(const list<netrange_t>&lef, const list<netrange_t>&rig)
list<netrange_t>::const_iterator lcur = lef.begin();
list<netrange_t>::const_iterator rcur = rig.begin();
while (lcur != lef.end()) {
- if (lcur->msb != rcur->msb)
+ if (lcur->get_msb() != rcur->get_msb())
return false;
- if (lcur->lsb != rcur->lsb)
+ if (lcur->get_lsb() != rcur->get_lsb())
return false;
++ lcur;
@@ -1049,12 +1051,26 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
list<netrange_t>unpacked_dimensions;
+ netdarray_t*netarray = 0;
for (list<pform_range_t>::const_iterator cur = unpacked_.begin()
; cur != unpacked_.end() ; ++cur) {
PExpr*use_lidx = cur->first;
PExpr*use_ridx = cur->second;
- assert(use_lidx && use_ridx);
+
+ // Special case: If we encounter an undefined
+ // dimensions, then turn this into a dynamic array and
+ // put all the packed dimensions there.
+ if (use_lidx==0 && use_ridx==0) {
+ ivl_assert(*this, netarray==0);
+ netarray = new netdarray_t(packed_dimensions, data_type_);
+ packed_dimensions.clear();
+ continue;
+ }
+
+ // Cannot handle dynamic arrays of arrays yet.
+ ivl_assert(*this, netarray==0);
+ ivl_assert(*this, use_lidx && use_ridx);
NetExpr*lexp = elab_and_eval(des, scope, use_lidx, -1, true);
NetExpr*rexp = elab_and_eval(des, scope, use_ridx, -1, true);
@@ -1157,6 +1173,34 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
sig = new NetNet(scope, name_, wtype, use_type);
+ } else if (enum_type_) {
+ ivl_assert(*this, struct_type_ == 0);
+ ivl_assert(*this, ! enum_type_->names->empty());
+ list<named_pexpr_t>::const_iterator sample_name = enum_type_->names->begin();
+ netenum_t*use_enum = scope->enumeration_for_name(sample_name->name);
+
+ if (debug_elaborate) {
+ cerr << get_fileline() << ": debug: Create signal " << wtype
+ << " enumeration "
+ << name_ << " in scope " << scope_path(scope) << endl;
+ }
+
+ sig = new NetNet(scope, name_, wtype, packed_dimensions, unpacked_dimensions, use_enum);
+
+ } else if (netarray) {
+ ivl_assert(*this, struct_type_==0);
+ ivl_assert(*this, enum_type_==0);
+
+ if (debug_elaborate) {
+ cerr << get_fileline() << ": debug: Create signal " << wtype
+ << " dynamic array "
+ << name_ << " in scope " << scope_path(scope) << endl;
+ }
+
+ ivl_assert(*this, packed_dimensions.empty());
+ ivl_assert(*this, unpacked_dimensions.empty());
+ sig = new NetNet(scope, name_, wtype, netarray);
+
} else {
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Create signal " << wtype;
@@ -1170,16 +1214,6 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
sig = new NetNet(scope, name_, wtype, packed_dimensions, unpacked_dimensions);
}
- // If this is an enumeration, then set the enumeration set for
- // the new signal. This turns it into an enumeration.
- if (enum_type_) {
- ivl_assert(*this, struct_type_ == 0);
- ivl_assert(*this, ! enum_type_->names->empty());
- list<named_pexpr_t>::const_iterator sample_name = enum_type_->names->begin();
- netenum_t*use_enum = scope->enumeration_for_name(sample_name->name);
- sig->set_enumeration(use_enum);
- }
-
if (wtype == NetNet::WIRE) sig->devirtualize_pins();
ivl_variable_type_t use_data_type = data_type_;
View
1 ivl_target.h
@@ -435,6 +435,7 @@ typedef enum ivl_variable_type_e {
IVL_VT_BOOL = 3,
IVL_VT_LOGIC = 4,
IVL_VT_STRING = 5,
+ IVL_VT_DARRAY = 6, /* Array (esp. dynamic array) */
IVL_VT_VECTOR = IVL_VT_LOGIC /* For compatibility */
} ivl_variable_type_t;
View
32 netdarray.cc
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2012 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
+ * General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+# include "netdarray.h"
+
+using namespace std;
+
+netdarray_t::netdarray_t(const std::list<netrange_t>&packed,
+ ivl_variable_type_t type)
+: packed_dims_(packed), type_(type)
+{
+}
+
+netdarray_t::~netdarray_t()
+{
+}
View
40 netdarray.h
@@ -0,0 +1,40 @@
+#ifndef __netdarray_H
+#define __netdarray_H
+/*
+ * Copyright (c) 2012 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
+ * General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+# include "nettypes.h"
+# include "ivl_target.h"
+# include <list>
+
+class netdarray_t : public nettype_base_t {
+
+ public:
+ explicit netdarray_t(const std::list<netrange_t>&packed,
+ ivl_variable_type_t type);
+ ~netdarray_t();
+
+ ivl_variable_type_t data_type() const { return type_; }
+
+ private:
+ std::list<netrange_t> packed_dims_;
+ ivl_variable_type_t type_;
+};
+
+#endif
View
3 netenum.h
@@ -20,6 +20,7 @@
*/
# include "ivl_target.h"
+# include "nettypes.h"
# include "verinum.h"
# include "StringHeap.h"
# include "LineInfo.h"
@@ -28,7 +29,7 @@
class NetScope;
-class netenum_t : public LineInfo {
+class netenum_t : public LineInfo, public nettype_base_t {
public:
explicit netenum_t(ivl_variable_type_t base_type, bool signed_flag,
View
84 netlist.cc
@@ -27,6 +27,8 @@
# include "compiler.h"
# include "netlist.h"
# include "netmisc.h"
+# include "netdarray.h"
+# include "netenum.h"
# include "netstruct.h"
# include "ivl_assert.h"
@@ -465,7 +467,7 @@ 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), is_scalar_(false), local_flag_(false),
- enumeration_(0), struct_type_(0), discipline_(0),
+ net_type_(0), discipline_(0),
eref_count_(0), lref_count_(0),
port_index_(-1)
{
@@ -515,7 +517,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t,
: NetObj(s, n, 1), type_(t),
port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE), signed_(false),
isint_(false), is_scalar_(false), local_flag_(false),
- enumeration_(0), struct_type_(0), discipline_(0),
+ net_type_(0), discipline_(0),
eref_count_(0), lref_count_(0)
{
packed_dims_ = packed;
@@ -548,6 +550,11 @@ static unsigned calculate_count(const list<netrange_t>&unpacked)
unsigned long sum = 1;
for (list<netrange_t>::const_iterator cur = unpacked.begin()
; cur != unpacked.end() ; ++cur) {
+ // Special case: If there are any undefined dimensions,
+ // then give up on trying to create pins for the net.
+ if (! cur->defined())
+ return 0;
+
sum *= cur->width();
}
@@ -559,11 +566,12 @@ static unsigned calculate_count(const list<netrange_t>&unpacked)
NetNet::NetNet(NetScope*s, perm_string n, Type t,
const list<netrange_t>&packed,
- const list<netrange_t>&unpacked)
+ const list<netrange_t>&unpacked,
+ nettype_base_t*net_type)
: NetObj(s, n, calculate_count(unpacked)),
type_(t), port_type_(NOT_A_PORT),
data_type_(IVL_VT_NO_TYPE), signed_(false), isint_(false),
- is_scalar_(false), local_flag_(false), enumeration_(0), struct_type_(0),
+ is_scalar_(false), local_flag_(false), net_type_(net_type),
discipline_(0), unpacked_dims_(unpacked.size()),
eref_count_(0), lref_count_(0)
{
@@ -577,7 +585,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t,
ivl_assert(*this, s);
if (pin_count() == 0) {
- cerr << "Array too big " << unpacked << endl;
+ cerr << "Invalid array dimensions: " << unpacked << endl;
ivl_assert(*this, 0);
}
@@ -621,7 +629,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, netstruct_t*ty)
: NetObj(s, n, 1),
type_(t), port_type_(NOT_A_PORT),
data_type_(IVL_VT_NO_TYPE), signed_(false), isint_(false),
- is_scalar_(false), local_flag_(false), enumeration_(0), struct_type_(ty),
+ is_scalar_(false), local_flag_(false), net_type_(ty),
discipline_(0),
eref_count_(0), lref_count_(0)
{
@@ -648,6 +656,36 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, netstruct_t*ty)
s->add_signal(this);
}
+NetNet::NetNet(NetScope*s, perm_string n, Type t, netdarray_t*ty)
+: NetObj(s, n, 1),
+ type_(t), port_type_(NOT_A_PORT),
+ data_type_(IVL_VT_NO_TYPE), signed_(false), isint_(false),
+ is_scalar_(false), local_flag_(false), net_type_(ty),
+ discipline_(0),
+ eref_count_(0), lref_count_(0)
+{
+ Link::DIR dir = Link::PASSIVE;
+
+ switch (t) {
+ case REG:
+ case IMPLICIT_REG:
+ dir = Link::OUTPUT;
+ break;
+ case SUPPLY0:
+ dir = Link::OUTPUT;
+ break;
+ case SUPPLY1:
+ dir = Link::OUTPUT;
+ break;
+ default:
+ break;
+ }
+
+ initialize_dir_(dir);
+
+ s->add_signal(this);
+}
+
NetNet::~NetNet()
{
if (eref_count_ > 0) {
@@ -769,19 +807,17 @@ void NetNet::set_scalar(bool flag)
netenum_t*NetNet::enumeration(void) const
{
- return enumeration_;
+ return dynamic_cast<netenum_t*> (net_type_);
}
-void NetNet::set_enumeration(netenum_t*es)
+netstruct_t*NetNet::struct_type(void) const
{
- ivl_assert(*this, struct_type_ == 0);
- ivl_assert(*this, enumeration_ == 0);
- enumeration_ = es;
+ return dynamic_cast<netstruct_t*> (net_type_);
}
-netstruct_t*NetNet::struct_type(void) const
+netdarray_t* NetNet::darray_type(void) const
{
- return struct_type_;
+ return dynamic_cast<netdarray_t*> (net_type_);
}
ivl_discipline_t NetNet::get_discipline() const
@@ -800,10 +836,10 @@ bool NetNet::sb_is_valid(const list<long>&indices, long sb) const
ivl_assert(*this, indices.size()+1 == packed_dims_.size());
assert(packed_dims_.size() == 1);
const netrange_t&rng = packed_dims_.back();
- if (rng.msb >= rng.lsb)
- return (sb <= rng.msb) && (sb >= rng.lsb);
+ if (rng.get_msb() >= rng.get_lsb())
+ return (sb <= rng.get_msb()) && (sb >= rng.get_lsb());
else
- return (sb <= rng.lsb) && (sb >= rng.msb);
+ return (sb <= rng.get_lsb()) && (sb >= rng.get_msb());
}
long NetNet::sb_to_idx(const list<long>&indices, long sb) const
@@ -815,10 +851,10 @@ long NetNet::sb_to_idx(const list<long>&indices, long sb) const
long acc_off;
long acc_wid = pcur->width();
- if (pcur->msb >= pcur->lsb)
- acc_off = sb - pcur->lsb;
+ if (pcur->get_msb() >= pcur->get_lsb())
+ acc_off = sb - pcur->get_lsb();
else
- acc_off = pcur->lsb - sb;
+ acc_off = pcur->get_lsb() - sb;
// The acc_off is the possition within the innermost
// dimension. If this is a multi-dimension packed array then
@@ -830,10 +866,10 @@ long NetNet::sb_to_idx(const list<long>&indices, long sb) const
-- pcur;
long tmp_off;
- if (pcur->msb >= pcur->lsb)
- tmp_off = *icur - pcur->lsb;
+ if (pcur->get_msb() >= pcur->get_lsb())
+ tmp_off = *icur - pcur->get_lsb();
else
- tmp_off = pcur->lsb - *icur;
+ tmp_off = pcur->get_lsb() - *icur;
acc_off += tmp_off * acc_wid;
acc_wid *= pcur->width();
@@ -2399,14 +2435,14 @@ long NetESignal::lsi() const
{
const list<netrange_t>&packed = net_->packed_dims();
ivl_assert(*this, packed.size() == 1);
- return packed.back().lsb;
+ return packed.back().get_lsb();
}
long NetESignal::msi() const
{
const list<netrange_t>&packed = net_->packed_dims();
ivl_assert(*this, packed.size() == 1);
- return packed.back().msb;
+ return packed.back().get_msb();
}
ivl_variable_type_t NetESignal::expr_type() const
View
13 netlist.h
@@ -76,6 +76,7 @@ class NetEvTrig;
class NetEvWait;
class PExpr;
class PFunction;
+class netdarray_t;
class netenum_t;
class netstruct_t;
@@ -607,10 +608,12 @@ class NetNet : public NetObj, public PortType {
const std::list<netrange_t>&packed);
explicit NetNet(NetScope*s, perm_string n, Type t,
const std::list<netrange_t>&packed,
- const std::list<netrange_t>&unpacked);
+ const std::list<netrange_t>&unpacked,
+ nettype_base_t*type =0);
- // This form builds a NetNet from its record definition.
+ // This form builds a NetNet from its record/enum definition.
explicit NetNet(NetScope*s, perm_string n, Type t, netstruct_t*type);
+ explicit NetNet(NetScope*s, perm_string n, Type t, netdarray_t*type);
virtual ~NetNet();
@@ -641,10 +644,9 @@ class NetNet : public NetObj, public PortType {
bool get_scalar() const;
void set_scalar(bool);
- void set_enumeration(netenum_t*enum_set);
netenum_t*enumeration(void) const;
-
netstruct_t*struct_type(void) const;
+ netdarray_t*darray_type(void) const;
/* Attach a discipline to the net. */
ivl_discipline_t get_discipline() const;
@@ -730,8 +732,7 @@ class NetNet : public NetObj, public PortType {
bool isint_ : 1; // original type of integer
bool is_scalar_ : 1;
bool local_flag_: 1;
- netenum_t*enumeration_;
- netstruct_t*struct_type_;
+ nettype_base_t*net_type_;
ivl_discipline_t discipline_;
std::list<netrange_t> packed_dims_;
View
32 netmisc.cc
@@ -325,7 +325,7 @@ NetExpr *normalize_variable_base(NetExpr *base,
{
ivl_assert(*base, dims.size() == 1);
const netrange_t&rng = dims.back();
- return normalize_variable_base(base, rng.msb, rng.lsb, wid, is_up);
+ return normalize_variable_base(base, rng.get_msb(), rng.get_lsb(), wid, is_up);
}
NetExpr *normalize_variable_bit_base(const list<long>&indices, NetExpr*base,
@@ -338,9 +338,9 @@ NetExpr *normalize_variable_bit_base(const list<long>&indices, NetExpr*base,
// addressing. We need that address as a slice offset to
// calculate the proper complete address
const netrange_t&rng = packed_dims.back();
- long slice_off = reg->sb_to_idx(indices, rng.lsb);
+ long slice_off = reg->sb_to_idx(indices, rng.get_lsb());
- return normalize_variable_base(base, rng.msb, rng.lsb, 1, true, slice_off);
+ return normalize_variable_base(base, rng.get_msb(), rng.get_lsb(), 1, true, slice_off);
}
NetExpr *normalize_variable_part_base(const list<long>&indices, NetExpr*base,
@@ -354,9 +354,9 @@ NetExpr *normalize_variable_part_base(const list<long>&indices, NetExpr*base,
// addressing. We need that address as a slice offset to
// calculate the proper complete address
const netrange_t&rng = packed_dims.back();
- long slice_off = reg->sb_to_idx(indices, rng.lsb);
+ long slice_off = reg->sb_to_idx(indices, rng.get_lsb());
- return normalize_variable_base(base, rng.msb, rng.lsb, wid, is_up, slice_off);
+ return normalize_variable_base(base, rng.get_msb(), rng.get_lsb(), wid, is_up, slice_off);
}
NetExpr *normalize_variable_slice_base(const list<long>&indices, NetExpr*base,
@@ -371,10 +371,10 @@ NetExpr *normalize_variable_slice_base(const list<long>&indices, NetExpr*base,
}
long sb;
- if (pcur->msb >= pcur->lsb)
- sb = pcur->lsb;
+ if (pcur->get_msb() >= pcur->get_lsb())
+ sb = pcur->get_lsb();
else
- sb = pcur->msb;
+ sb = pcur->get_msb();
long loff;
reg->sb_to_slice(indices, sb, loff, lwid);
@@ -492,10 +492,10 @@ NetExpr* normalize_variable_unpacked(const NetNet*net, list<long>&indices)
; cur != indices.end() ; ++cur, ++idx) {
long tmp = *cur;
- if (dims[idx].lsb <= dims[idx].msb)
- tmp -= dims[idx].lsb;
+ if (dims[idx].get_lsb() <= dims[idx].get_msb())
+ tmp -= dims[idx].get_lsb();
else
- tmp -= dims[idx].msb;
+ tmp -= dims[idx].get_msb();
// Notice of this index is out of range.
if (tmp < 0 || tmp >= (long)dims[idx].width()) {
@@ -531,15 +531,17 @@ NetExpr* normalize_variable_unpacked(const NetNet*net, list<NetExpr*>&indices)
return 0;
int64_t use_base;
- if (dims[idx].lsb <= dims[idx].msb)
- use_base = dims[idx].lsb;
+ if (! dims[idx].defined())
+ use_base = 0;
+ else if (dims[idx].get_lsb() <= dims[idx].get_msb())
+ use_base = dims[idx].get_lsb();
else
- use_base = dims[idx].msb;
+ use_base = dims[idx].get_msb();
int64_t use_stride = stride[idx];
// Account for that we are doing arithmatic and should
- // have a proper width to make sure there ar no
+ // have a proper width to make sure there are no
// losses. So calculate a min_wid width.
unsigned tmp_wid;
unsigned min_wid = tmp->expr_width();
View
2 netstruct.h
@@ -24,7 +24,7 @@
# include "ivl_target.h"
# include "nettypes.h"
-class netstruct_t : public LineInfo {
+class netstruct_t : public LineInfo, public nettype_base_t {
public:
struct member_t {
View
26 nettypes.cc
@@ -22,16 +22,16 @@
using namespace std;
+nettype_base_t::~nettype_base_t()
+{
+}
+
unsigned long netrange_width(const list<netrange_t>&packed)
{
unsigned wid = 1;
for (list<netrange_t>::const_iterator cur = packed.begin()
; cur != packed.end() ; ++cur) {
- unsigned use_wid;
- if (cur->msb >= cur->lsb)
- use_wid = cur->msb - cur->lsb + 1;
- else
- use_wid = cur->lsb - cur->msb + 1;
+ unsigned use_wid = cur->width();
wid *= use_wid;
}
@@ -60,16 +60,16 @@ bool prefix_to_slice(const std::list<netrange_t>&dims,
lwid = acc_wid;
-- pcur;
- if (sb < pcur->msb && sb < pcur->lsb)
+ if (sb < pcur->get_msb() && sb < pcur->get_lsb())
return false;
- if (sb > pcur->msb && sb > pcur->lsb)
+ if (sb > pcur->get_msb() && sb > pcur->get_lsb())
return false;
long acc_off = 0;
- if (pcur->msb >= pcur->lsb)
- acc_off += (sb - pcur->lsb) * acc_wid;
+ if (pcur->get_msb() >= pcur->get_lsb())
+ acc_off += (sb - pcur->get_lsb()) * acc_wid;
else
- acc_off += (sb - pcur->msb) * acc_wid;
+ acc_off += (sb - pcur->get_msb()) * acc_wid;
if (prefix.size() == 0) {
loff = acc_off;
@@ -83,10 +83,10 @@ bool prefix_to_slice(const std::list<netrange_t>&dims,
-- pcur;
-- icur;
acc_wid *= pcur->width();
- if (pcur->msb >= pcur->lsb)
- acc_off += (*icur - pcur->lsb) * acc_wid;
+ if (pcur->get_msb() >= pcur->get_lsb())
+ acc_off += (*icur - pcur->get_lsb()) * acc_wid;
else
- acc_off += (*icur - pcur->msb) * acc_wid;
+ acc_off += (*icur - pcur->get_msb()) * acc_wid;
} while (icur != prefix.begin());
View
41 nettypes.h
@@ -20,25 +20,48 @@
*/
# include <list>
+# include <climits>
+# include <cassert>
+
+/*
+ * This is a fully abstract type that is a type that can be attached
+ * to a NetNet object.
+ */
+class nettype_base_t {
+ public:
+ virtual ~nettype_base_t() =0;
+};
class netrange_t {
public:
- inline netrange_t() : msb(0), lsb(0) { }
- inline netrange_t(long m, long l) : msb(m), lsb(l) { }
-
+ // Create an undefined range. An undefined range is a range
+ // used to declare dynamic arrays, etc.
+ inline netrange_t() : msb_(LONG_MAX), lsb_(LONG_MAX) { }
+ // Create a properly defined netrange
+ inline netrange_t(long m, long l) : msb_(m), lsb_(l) { }
+ // Copy constructure.
inline netrange_t(const netrange_t&that)
- : msb(that.msb), lsb(that.lsb) { }
+ : msb_(that.msb_), lsb_(that.lsb_) { }
inline netrange_t& operator = (const netrange_t&that)
- { msb = that.msb; lsb = that.lsb; return *this; }
+ { msb_ = that.msb_; lsb_ = that.lsb_; return *this; }
- public:
- long msb;
- long lsb;
+ inline bool defined() const
+ { return msb_!=LONG_MAX || msb_!= LONG_MAX; }
inline unsigned long width()const
- { if (msb >= lsb) return msb-lsb+1; else return lsb-msb+1; }
+ { if (!defined()) return 0;
+ else if (msb_ >= lsb_) return msb_-lsb_+1;
+ else return lsb_-msb_+1;
+ }
+
+ inline long get_msb() const { assert(defined()); return msb_; }
+ inline long get_lsb() const { assert(defined()); return lsb_; }
+
+ private:
+ long msb_;
+ long lsb_;
};
extern unsigned long netrange_width(const std::list<netrange_t>&dims);
View
10 parse.y
@@ -938,12 +938,13 @@ endnew_opt : ':' K_new | ;
dynamic_array_new /* IEEE1800-2005: A.2.4 */
: K_new '[' expression ']'
- { yyerror(@1, "sorry: Dynamic array new expression not supported.");
- $$ = 0;
+ { //yyerror(@1, "sorry: Dynamic array new expression not supported.");
+ $$ = new PENew($3);
}
| K_new '[' expression ']' '(' expression ')'
- { yyerror(@1, "sorry: Dynamic array new expression not supported.");
- $$ = 0;
+ { yyerror(@1, "sorry: Dynamic array new expression with initializer not supported.");
+ delete $6;
+ $$ = new PENew($3);
}
;
@@ -1742,7 +1743,6 @@ variable_dimension /* IEEE1800-2005: A.2.5 */
| '[' ']'
{ list<pform_range_t> *tmp = new list<pform_range_t>;
pform_range_t index (0,0);
- yyerror("sorry: Dynamic array ranges not supported.");
tmp->push_back(index);
$$ = tmp;
}
View
5 pform_dump.cc
@@ -233,6 +233,11 @@ void PEFNumber::dump(ostream &out) const
out << value();
}
+void PENew::dump(ostream&out) const
+{
+ out << "new [" << *size_ << "]";
+}
+
void PENumber::dump(ostream&out) const
{
out << value();
View
1 sv_vpi_user.h
@@ -50,6 +50,7 @@ EXTERN_C_START
#define vpiLogicVar vpiReg
#define vpiStringVar 616
#define vpiBitVar 620
+#define vpiArrayVar vpiRegArray
/********* TYPESPECS *************/
#define vpiEnumTypespec 633
View
12 t-dll-api.cc
@@ -2049,13 +2049,13 @@ extern "C" ivl_nexus_t ivl_scope_mod_port(ivl_scope_t net, unsigned idx)
extern "C" unsigned ivl_scope_sigs(ivl_scope_t net)
{
assert(net);
- return net->nsigs_;
+ return net->sigs_.size();
}
extern "C" ivl_signal_t ivl_scope_sig(ivl_scope_t net, unsigned idx)
{
assert(net);
- assert(idx < net->nsigs_);
+ assert(idx < net->sigs_.size());
return net->sigs_[idx];
}
@@ -2196,13 +2196,13 @@ extern "C" unsigned ivl_signal_packed_dimensions(ivl_signal_t net)
extern "C" int ivl_signal_packed_msb(ivl_signal_t net, unsigned dim)
{
assert(dim < net->packed_dims.size());
- return net->packed_dims[dim].msb;
+ return net->packed_dims[dim].get_msb();
}
extern "C" int ivl_signal_packed_lsb(ivl_signal_t net, unsigned dim)
{
assert(dim < net->packed_dims.size());
- return net->packed_dims[dim].lsb;
+ return net->packed_dims[dim].get_lsb();
}
extern "C" int ivl_signal_msb(ivl_signal_t net)
@@ -2211,7 +2211,7 @@ extern "C" int ivl_signal_msb(ivl_signal_t net)
return 0;
assert(net->packed_dims.size() == 1);
- return net->packed_dims[0].msb;
+ return net->packed_dims[0].get_msb();
}
extern "C" int ivl_signal_lsb(ivl_signal_t net)
@@ -2220,7 +2220,7 @@ extern "C" int ivl_signal_lsb(ivl_signal_t net)
return 0;
assert(net->packed_dims.size() == 1);
- return net->packed_dims[0].lsb;
+ return net->packed_dims[0].get_lsb();
}
extern "C" ivl_scope_t ivl_signal_scope(ivl_signal_t net)
View
31 t-dll.cc
@@ -257,7 +257,7 @@ ivl_signal_t dll_target::find_signal(ivl_design_s &des, const NetNet*net)
perm_string nname = net->name();
- for (unsigned idx = 0 ; idx < scope->nsigs_ ; idx += 1) {
+ for (unsigned idx = 0 ; idx < scope->sigs_.size() ; idx += 1) {
if (strcmp(scope->sigs_[idx]->name_, nname) == 0)
return scope->sigs_[idx];
}
@@ -533,8 +533,6 @@ void dll_target::add_root(ivl_design_s &des__, const NetScope *s)
root_->name_ = name;
FILE_NAME(root_, s);
root_->parent = 0;
- root_->nsigs_ = 0;
- root_->sigs_ = 0;
root_->nlog_ = 0;
root_->log_ = 0;
root_->nevent_ = 0;
@@ -2280,8 +2278,6 @@ void dll_target::scope(const NetScope*net)
scop->parent = find_scope(des_, net->parent());
assert(scop->parent);
scop->parent->children[net->fullname()] = scop;
- scop->nsigs_ = 0;
- scop->sigs_ = 0;
scop->nlog_ = 0;
scop->log_ = 0;
scop->nevent_ = 0;
@@ -2371,20 +2367,7 @@ void dll_target::signal(const NetNet*net)
assert(obj->scope_);
FILE_NAME(obj, net);
- if (obj->scope_->nsigs_ == 0) {
- assert(obj->scope_->sigs_ == 0);
- obj->scope_->nsigs_ = 1;
- obj->scope_->sigs_ = (ivl_signal_t*)malloc(sizeof(ivl_signal_t));
-
- } else {
- assert(obj->scope_->sigs_);
- obj->scope_->nsigs_ += 1;
- obj->scope_->sigs_ = (ivl_signal_t*)
- realloc(obj->scope_->sigs_,
- obj->scope_->nsigs_*sizeof(ivl_signal_t));
- }
-
- obj->scope_->sigs_[obj->scope_->nsigs_-1] = obj;
+ obj->scope_->sigs_.push_back(obj);
/* Save the primitive properties of the signal in the
@@ -2490,6 +2473,10 @@ void dll_target::signal(const NetNet*net)
obj->nattr = net->attr_cnt();
obj->attr = fill_in_attributes(net);
+ /* If this is a dynamic array, then set the type to DARRAY. */
+ if (net->darray_type()) {
+ obj->data_type = IVL_VT_DARRAY;
+ }
/* Get the nexus objects for all the pins of the signal. If
the signal has only one pin, then write the single
@@ -2502,11 +2489,11 @@ void dll_target::signal(const NetNet*net)
if (obj->array_dimensions_ == 1) {
const vector<netrange_t>& dims = net->unpacked_dims();
- if (dims[0].msb < dims[0].lsb) {
- obj->array_base = dims[0].msb;
+ if (dims[0].get_msb() < dims[0].get_lsb()) {
+ obj->array_base = dims[0].get_msb();
obj->array_addr_swapped = false;
} else {
- obj->array_base = dims[0].lsb;
+ obj->array_base = dims[0].get_lsb();
obj->array_addr_swapped = true;
}
obj->array_words = net->unpacked_count();
View
3 t-dll.h
@@ -627,8 +627,7 @@ struct ivl_scope_s {
std::vector<ivl_enumtype_t> enumerations_;
- unsigned nsigs_;
- ivl_signal_t*sigs_;
+ std::vector<ivl_signal_t> sigs_;
unsigned nlog_;
ivl_net_logic_t*log_;
View
2 tgt-stub/expression.c
@@ -178,7 +178,7 @@ static void show_select_expression(ivl_expr_t net, unsigned ind)
differently. */
fprintf(out, "%*s<substring: width=%u bits, %u bytes>\n", ind, "", width, width/8);
if (width%8 != 0)
- fprintf(out, "%*sERROR: Width should be a multiple of 8 bits.\n", ind, "", width);
+ fprintf(out, "%*sERROR: Width should be a multiple of 8 bits.\n", ind, "");
show_expression(oper1, ind+3);
show_expression(oper2, ind+3);
View
27 tgt-stub/stub.c
@@ -169,6 +169,9 @@ const char*data_type_string(ivl_variable_type_t vtype)
case IVL_VT_STRING:
vt = "string";
break;
+ case IVL_VT_DARRAY:
+ vt = "darray";
+ break;
}
return vt;
@@ -1260,26 +1263,29 @@ static void show_signal(ivl_signal_t net)
break;
}
+ data_type = "?data?";
switch (ivl_signal_data_type(net)) {
+ case IVL_VT_NO_TYPE:
+ data_type = "<no-type>";
+ break;
case IVL_VT_BOOL:
data_type = "bool";
break;
-
case IVL_VT_LOGIC:
data_type = "logic";
break;
-
case IVL_VT_REAL:
data_type = "real";
break;
-
case IVL_VT_STRING:
data_type = "string";
break;
-
- default:
- data_type = "?data?";
+ case IVL_VT_DARRAY:
+ data_type = "darray";
+ break;
+ case IVL_VT_VOID:
+ data_type = "void";
break;
}
@@ -1362,6 +1368,15 @@ static void show_signal(ivl_signal_t net)
}
}
+ switch (ivl_signal_data_type(net)) {
+ case IVL_VT_NO_TYPE:
+ case IVL_VT_VOID:
+ fprintf(out, " ERROR: Invalid type for signal: %s\n", data_type);
+ stub_errors += 1;
+ break;
+ default:
+ break;
+ }
}
void test_expr_is_delay(ivl_expr_t expr)
View
5 tgt-vvp/vvp_scope.c
@@ -502,6 +502,11 @@ static void draw_reg_in_scope(ivl_signal_t sig)
vvp_mangle_name(ivl_signal_basename(sig)),
swapped ? first: last, swapped ? last : first, msb, lsb);
+ } else if (ivl_signal_data_type(sig) == IVL_VT_DARRAY) {
+ fprintf(vvp_out, "v%p_0 .var/darray \"%s\";%s\n", sig,
+ vvp_mangle_name(ivl_signal_basename(sig)),
+ ivl_signal_local(sig)? " Local signal" : "");
+
} else if (ivl_signal_data_type(sig) == IVL_VT_STRING) {
fprintf(vvp_out, "v%p_0 .var/str \"%s\";%s\n", sig,
vvp_mangle_name(ivl_signal_basename(sig)),
View
3 vpi/Makefile.in
@@ -52,7 +52,8 @@ CXXFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CXX@ @CXXFLAGS@
LDFLAGS = @LDFLAGS@
# Object files for system.vpi
-O = sys_table.o sys_convert.o sys_deposit.o sys_display.o sys_fileio.o \
+O = sys_table.o sys_convert.o sys_darray.o sys_deposit.o sys_display.o \
+ sys_fileio.o \
sys_finish.o sys_icarus.o sys_plusargs.o sys_queue.o sys_random.o \
sys_random_mti.o sys_readmem.o sys_readmem_lex.o sys_scanf.o sys_sdf.o \
sys_string.o sys_time.o sys_vcd.o sys_vcdoff.o vcd_priv.o mt19937int.o \
View
91 vpi/sys_darray.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2012 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
+ * General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+# include "sys_priv.h"
+# include <assert.h>
+
+static PLI_INT32 one_darray_arg_compiletf(ICARUS_VPI_CONST PLI_BYTE8*name)
+{
+ vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
+ vpiHandle argv;
+ vpiHandle arg;
+
+ argv = vpi_iterate(vpiArgument, callh);
+ if (argv == 0) {
+ vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
+ (int)vpi_get(vpiLineNo, callh));
+ vpi_printf("%s requires a string argument.\n", name);
+ vpi_control(vpiFinish, 1);
+ return 0;
+ }
+
+ arg = vpi_scan(argv);
+ if (arg == 0) return 0;
+
+ arg = vpi_scan(argv);
+ if (arg != 0) {
+ vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
+ (int)vpi_get(vpiLineNo, callh));
+ vpi_printf("%s has too many arguments.\n", name);
+ vpi_control(vpiFinish, 1);
+ return 0;
+ }
+
+ return 0;
+}
+
+static PLI_INT32 size_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
+{
+ vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
+ vpiHandle argv;
+ vpiHandle arg;
+
+ argv = vpi_iterate(vpiArgument, callh);
+ assert(argv);
+ arg = vpi_scan(argv);
+ assert(arg);
+ vpi_free_object(argv);
+
+ int res = vpi_get(vpiSize, arg);
+
+ s_vpi_value value;
+ value.format = vpiIntVal;
+ value.value.integer = res;
+
+ vpi_put_value(callh, &value, 0, vpiNoDelay);
+
+ return 0;
+}
+
+void sys_darray_register(void)
+{
+ s_vpi_systf_data tf_data;
+ vpiHandle res;
+
+ tf_data.type = vpiSysFunc;
+ tf_data.sysfunctype = vpiIntFunc;
+ tf_data.tfname = "$ivl_darray_method$size";
+ tf_data.calltf = size_calltf;
+ tf_data.compiletf = one_darray_arg_compiletf;
+ tf_data.sizetf = 0;
+ tf_data.user_data = "$ivl_darray_method$size";
+ res = vpi_register_systf(&tf_data);
+ vpip_make_systf_system_defined(res);
+}
View
2 vpi/sys_table.c
@@ -24,6 +24,7 @@
# include <string.h>
extern void sys_convert_register();
+extern void sys_darray_register();
extern void sys_fileio_register();
extern void sys_finish_register();
extern void sys_deposit_register();
@@ -196,6 +197,7 @@ static void sys_lxt_or_vcd_register()
void (*vlog_startup_routines[])() = {
sys_convert_register,
+ sys_darray_register,
sys_fileio_register,
sys_finish_register,
sys_deposit_register,
View
6 vpi_user.h
@@ -310,6 +310,12 @@ typedef struct t_vpi_delay {
#define vpiVariables 100
#define vpiExpr 102
+/********************** object types added with 1364-2001 *********************/
+
+# define vpiRegArray 116
+
+/********************** object types added with 1364-2005 *********************/
+
#define vpiCallback 1000
/* PROPERTIES */
View
2 vvp/Makefile.in
@@ -66,7 +66,7 @@ dllib=@DLLIB@
MDIR1 = -DMODULE_DIR1='"$(libdir)/ivl$(suffix)"'
-V = vpi_modules.o vpi_callback.o vpi_const.o vpi_event.o vpi_iter.o vpi_mcd.o \
+V = vpi_modules.o vpi_callback.o vpi_const.o vpi_darray.o vpi_event.o vpi_iter.o vpi_mcd.o \
vpi_priv.o vpi_scope.o vpi_real.o vpi_signal.o vpi_string.o vpi_tasks.o vpi_time.o \
vpi_vthr_vector.o vpip_bin.o vpip_hex.o vpip_oct.o \
vpip_to_dec.o vpip_format.o vvp_vpi.o
View
1 vvp/compile.h
@@ -458,6 +458,7 @@ extern void compile_variable(char*label, char*name,
extern void compile_var_real(char*label, char*name);
extern void compile_var_string(char*label, char*name);
+extern void compile_var_darray(char*label, char*name);
/*
* This function is used to create a scope port
View
1 vvp/lexor.lex
@@ -195,6 +195,7 @@ static char* strdupnew(char const *str)
".ufunc" { return K_UFUNC; }
".ufunc/e" { return K_UFUNC_E; }
".var" { return K_VAR; }
+".var/darray" { return K_VAR_DARRAY; }
".var/real" { return K_VAR_R; }
".var/s" { return K_VAR_S; }
".var/str" { return K_VAR_STR; }
View
5 vvp/parse.y
@@ -91,7 +91,7 @@ static struct __vpiModPath*modpath_dst = 0;
%token K_RESOLV K_SCOPE K_SFUNC K_SFUNC_E K_SHIFTL K_SHIFTR K_SHIFTRS
%token K_THREAD K_TIMESCALE K_TRAN K_TRANIF0 K_TRANIF1 K_TRANVP
%token K_UFUNC K_UFUNC_E K_UDP K_UDP_C K_UDP_S
-%token K_VAR K_VAR_S K_VAR_STR K_VAR_I K_VAR_R K_VAR_2S K_VAR_2U
+%token K_VAR K_VAR_DARRAY K_VAR_S K_VAR_STR K_VAR_I K_VAR_R K_VAR_2S K_VAR_2U
%token K_vpi_call K_vpi_call_w K_vpi_call_i
%token K_vpi_func K_vpi_func_r
%token K_disable K_fork
@@ -702,6 +702,9 @@ statement
| T_LABEL K_VAR_STR T_STRING ';'
{ compile_var_string($1, $3); }
+ | T_LABEL K_VAR_DARRAY T_STRING ';'
+ { compile_var_darray($1, $3); }
+
/* Net statements are similar to .var statements, except that they
declare nets, and they have an input list. */
View
87 vvp/vpi_darray.cc
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2012 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
+ * General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+# include "compile.h"
+# include "vpi_priv.h"
+# include "vvp_net_sig.h"
+# include "schedule.h"
+#ifdef CHECK_WITH_VALGRIND
+# include "vvp_cleanup.h"
+#endif
+# include <cstdio>
+# include <cstdlib>
+# include <cstring>
+# include <cassert>
+# include "ivl_alloc.h"
+
+using namespace std;
+
+class __vpiDarrayVar : public __vpiHandle {
+
+ public:
+ __vpiDarrayVar(__vpiScope*scope, const char*name, vvp_net_t*net);
+
+ int get_type_code(void) const;
+ int vpi_get(int code);
+ void vpi_get_value(p_vpi_value val);
+
+ inline vvp_net_t* get_net() const { return net_; }
+
+ private:
+ struct __vpiScope* scope_;
+ const char*name_;
+ vvp_net_t*net_;
+};
+
+__vpiDarrayVar::__vpiDarrayVar(__vpiScope*sc, const char*na, vvp_net_t*ne)
+: scope_(sc), name_(na), net_(ne)
+{
+}
+
+int __vpiDarrayVar::get_type_code(void) const
+{ return vpiArrayVar; }
+
+
+int __vpiDarrayVar::vpi_get(int code)
+{
+ vvp_fun_signal_object*fun = dynamic_cast<vvp_fun_signal_object*> (net_->fun);
+ assert(fun);
+ vvp_object_t val = fun->get_object();
+
+ switch (code) {
+ default:
+ return 0;
+ }
+}
+
+void __vpiDarrayVar::vpi_get_value(p_vpi_value val)
+{
+ val->format = vpiSuppressVal;
+}
+
+vpiHandle vpip_make_darray_var(const char*name, vvp_net_t*net)
+{
+ struct __vpiScope*scope = vpip_peek_current_scope();
+ const char*use_name = name ? vpip_name_string(name) : 0;
+
+ struct __vpiDarrayVar*obj = new __vpiDarrayVar(scope, use_name, net);
+
+ return obj;
+}
View
2 vvp/vpi_priv.h
@@ -497,6 +497,8 @@ class __vpiStringVar : public __vpiHandle {
extern vpiHandle vpip_make_string_var(const char*name, vvp_net_t*net);
+extern vpiHandle vpip_make_darray_var(const char*name, vvp_net_t*net);
+
/*
* When a loaded VPI module announces a system task/function, one
* __vpiUserSystf object is created to hold the definition of that
View
7 vvp/vvp_net.cc
@@ -2963,6 +2963,13 @@ void vvp_net_fun_t::recv_string(vvp_net_ptr_t, const std::string&bit, vvp_contex
assert(0);
}
+void vvp_net_fun_t::recv_object(vvp_net_ptr_t, vvp_object_t, vvp_context_t)
+{
+ fprintf(stderr, "internal error: %s: recv_object(...) not implemented\n",
+ typeid(*this).name());
+ assert(0);
+}
+
void vvp_net_fun_t::force_flag(void)
{
}
View
23 vvp/vvp_net.h
@@ -23,6 +23,7 @@
# include "vpi_user.h"
# include "vvp_vpi_callback.h"
# include "permaheap.h"
+# include "vvp_object.h"
# include <cstddef>
# include <cstdlib>
# include <cstring>
@@ -1083,6 +1084,7 @@ class vvp_net_t {
void send_real(double val, vvp_context_t context);
void send_long(long val);
void send_string(const std::string&val, vvp_context_t context);
+ void send_object(vvp_object_t val, vvp_context_t context);
void send_vec4_pv(const vvp_vector4_t&val,
unsigned base, unsigned wid, unsigned vwid,
@@ -1159,6 +1161,8 @@ class vvp_net_fun_t {
virtual void recv_long(vvp_net_ptr_t port, long bit);
virtual void recv_string(vvp_net_ptr_t port, const std::string&bit,
vvp_context_t context);
+ virtual void recv_object(vvp_net_ptr_t port, vvp_object_t bit,
+ vvp_context_t context);
// Part select variants of above
virtual void recv_vec4_pv(vvp_net_ptr_t p, const vvp_vector4_t&bit,
@@ -1529,6 +1533,18 @@ inline void vvp_send_string(vvp_net_ptr_t ptr, const std::string&val, vvp_contex
}
}
+inline void vvp_send_object(vvp_net_ptr_t ptr, vvp_object_t val, vvp_context_t context)
+{
+ while (vvp_net_t*cur = ptr.ptr()) {
+ vvp_net_ptr_t next = cur->port[ptr.port()];
+
+ if (cur->fun)
+ cur->fun->recv_object(ptr, val, context);
+
+ ptr = next;
+ }
+}
+
/*
* Part-vector versions of above functions. This function uses the
* corresponding recv_vec4_pv method in the vvp_net_fun_t functor to
@@ -1676,6 +1692,13 @@ inline void vvp_net_t::send_string(const std::string&val, vvp_context_t context)
}
+inline void vvp_net_t::send_object(vvp_object_t val, vvp_context_t context)
+{
+ assert(!fil);
+ vvp_send_object(out_, val, context);
+}
+
+
inline bool vvp_net_fil_t::test_force_mask(unsigned bit) const
{
if (bit >= force_mask_.size())
View
74 vvp/vvp_net_sig.cc
@@ -665,6 +665,80 @@ void vvp_fun_signal_string_aa::operator delete(void*)
assert(0);
}
+ /* OBJECT signals */
+
+vvp_fun_signal_object_sa::vvp_fun_signal_object_sa()
+{
+}
+
+void vvp_fun_signal_object_sa::recv_object(vvp_net_ptr_t ptr, vvp_object_t bit,
+ vvp_context_t)
+{
+ assert(ptr.port() == 0);
+
+ if (needs_init_ || value_ != bit) {
+ value_ = bit;
+ needs_init_ = false;
+
+ ptr.ptr()->send_object(bit, 0);
+ }
+}
+
+vvp_fun_signal_object_aa::vvp_fun_signal_object_aa()
+{
+ context_idx_ = vpip_add_item_to_context(this, vpip_peek_context_scope());
+}
+
+vvp_fun_signal_object_aa::~vvp_fun_signal_object_aa()
+{
+ assert(0);
+}
+
+void vvp_fun_signal_object_aa::alloc_instance(vvp_context_t)
+{
+ assert(0);
+}
+
+void vvp_fun_signal_object_aa::reset_instance(vvp_context_t)
+{
+ assert(0);
+}
+
+unsigned vvp_fun_signal_object_aa::value_size() const
+{
+ assert(0);
+ return 1;
+}
+
+vvp_bit4_t vvp_fun_signal_object_aa::value(unsigned) const
+{
+ assert(0);
+ return BIT4_X;
+}
+
+vvp_scalar_t vvp_fun_signal_object_aa::scalar_value(unsigned) const
+{
+ assert(0);
+ return vvp_scalar_t();
+}
+
+void vvp_fun_signal_object_aa::vec4_value(vvp_vector4_t&) const
+{
+ assert(0);
+}
+
+void* vvp_fun_signal_object_aa::operator new(std::size_t size)
+{
+ return vvp_net_fun_t::heap_.alloc(size);
+}
+
+void vvp_fun_signal_object_aa::operator delete(void*)
+{
+ assert(0);
+}
+
+ /* **** */
+
vvp_fun_force::vvp_fun_force()
{
}
View
57 vvp/vvp_net_sig.h
@@ -22,6 +22,7 @@
# include "config.h"
# include "vpi_user.h"
# include "vvp_net.h"
+# include "vvp_object.h"
# include <string>
# include <cstddef>
# include <cstdlib>
@@ -318,6 +319,62 @@ class vvp_fun_signal_string_aa : public vvp_fun_signal_string, public automatic_
unsigned context_idx_;
};
+class vvp_fun_signal_object : public vvp_fun_signal_base {
+
+ public:
+ explicit vvp_fun_signal_object() {};
+
+ unsigned size() const { return 1; }
+
+ inline vvp_object_t get_object() const { return value_; }
+
+ protected:
+ vvp_object_t value_;
+};
+
+/*
+ * Statically allocated vvp_fun_signal_string.
+ */
+class vvp_fun_signal_object_sa : public vvp_fun_signal_object {
+
+ public:
+ explicit vvp_fun_signal_object_sa();
+
+ void recv_object(vvp_net_ptr_t port, vvp_object_t bit,
+ vvp_context_t context);
+};
+
+/*
+ * Automatically allocated vvp_fun_signal_real.
+ */
+class vvp_fun_signal_object_aa : public vvp_fun_signal_object, public automatic_signal_base, public automatic_hooks_s {
+
+ public:
+ explicit vvp_fun_signal_object_aa();
+ ~vvp_fun_signal_object_aa();
+
+ void alloc_instance(vvp_context_t context);
+ void reset_instance(vvp_context_t context);
+#ifdef CHECK_WITH_VALGRIND
+ void free_instance(vvp_context_t context);
+#endif
+
+ // Get information about the vector value.
+ unsigned value_size() const;
+ vvp_bit4_t value(unsigned idx) const;
+ vvp_scalar_t scalar_value(unsigned idx) const;
+ void vec4_value(vvp_vector4_t&) const;
+ //double real_value() const;
+ //void get_signal_value(struct t_vpi_value*vp);
+
+ public: // These objects are only permallocated.
+ static void* operator new(std::size_t size);
+ static void operator delete(void*obj);
+
+ private:
+ unsigned context_idx_;
+};
+
/* vvp_wire
* The vvp_wire is different from vvp_variable objects in that it
View
24 vvp/vvp_object.h
@@ -0,0 +1,24 @@
+#ifndef __vvp_object_H
+#define __vvp_object_H
+/*
+ * Copyright (c) 2012 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
+ * General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+typedef class vvp_object*vvp_object_t;
+
+#endif
View
36 vvp/words.cc
@@ -114,6 +114,42 @@ void compile_var_string(char*label, char*name)
__compile_var_string(label, name, 0, 0);
}
+static void __compile_var_darray(char*label, char*name,
+ vvp_array_t array, unsigned long array_addr)
+{
+ vvp_net_t*net = new vvp_net_t;
+
+ if (vpip_peek_current_scope()->is_automatic) {
+ vvp_fun_signal_object_aa*tmp = new vvp_fun_signal_object_aa;
+ net->fil = tmp;
+ net->fun = tmp;
+ } else {
+ net->fil = 0;
+ net->fun = new vvp_fun_signal_object_sa;
+ }
+
+ define_functor_symbol(label, net);
+
+ vpiHandle obj = vpip_make_darray_var(name, net);
+ compile_vpi_symbol(label, obj);
+
+ if (name) {
+ assert(!array);
+ vpip_attach_to_current_scope(obj);
+ }
+ if (array) {
+ assert(!name);
+ array_attach_word(array, array_addr, obj);
+ }
+ delete[]label;
+ delete[] name;
+}
+
+void compile_var_darray(char*label, char*name)
+{
+ __compile_var_darray(label, name, 0, 0);
+}
+
/*
* A variable is a special functor, so we allocate that functor and
* write the label into the symbol table.

0 comments on commit 14f229d

Please sign in to comment.
Something went wrong with that request. Please try again.