diff --git a/design_dump.cc b/design_dump.cc index 538d41211..290b8428b 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -1584,6 +1584,11 @@ void NetESFunc::dump(ostream&o) const o << ")"; } +void NetEShallowCopy::dump(ostream&o) const +{ + o << ""; +} + void NetESignal::dump(ostream&o) const { if (has_sign()) diff --git a/dup_expr.cc b/dup_expr.cc index 084e433c2..30b0c22fb 100644 --- a/dup_expr.cc +++ b/dup_expr.cc @@ -227,6 +227,12 @@ NetESFunc* NetESFunc::dup_expr() const return tmp; } +NetEShallowCopy* NetEShallowCopy::dup_expr() const +{ + ivl_assert(*this, 0); + return 0; +} + NetESignal* NetESignal::dup_expr() const { NetESignal*tmp = new NetESignal(net_, word_); diff --git a/elab_expr.cc b/elab_expr.cc index 10a5df314..edb0c163a 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -4535,11 +4535,19 @@ unsigned PENewCopy::test_width(Design*, NetScope*, width_mode_t&) return 1; } -NetExpr* PENewCopy::elaborate_expr(Design*des, NetScope*, ivl_type_t, unsigned) const +NetExpr* PENewCopy::elaborate_expr(Design*des, NetScope*scope, ivl_type_t obj_type, unsigned) const { - cerr << get_fileline() << ": sorry: Shallow copy \"new\" not implemented." << endl; - des->errors += 1; - return 0; + NetExpr*copy_arg = src_->elaborate_expr(des, scope, obj_type, 0); + if (copy_arg == 0) + return 0; + + NetENew*obj_new = new NetENew(obj_type); + obj_new->set_line(*this); + + NetEShallowCopy*copy = new NetEShallowCopy(obj_new, copy_arg); + copy->set_line(*this); + + return copy; } /* diff --git a/emit.cc b/emit.cc index cab1d30d5..227ccabb0 100644 --- a/emit.cc +++ b/emit.cc @@ -610,6 +610,21 @@ void NetESFunc::expr_scan(struct expr_scan_t*tgt) const tgt->expr_sfunc(this); } +void NetEShallowCopy::expr_scan(struct expr_scan_t*tgt) const +{ + tgt->expr_scopy(this); +} + +void NetEShallowCopy::expr_scan_oper1(struct expr_scan_t*tgt) const +{ + arg1_->expr_scan(tgt); +} + +void NetEShallowCopy::expr_scan_oper2(struct expr_scan_t*tgt) const +{ + arg2_->expr_scan(tgt); +} + void NetEUFunc::expr_scan(struct expr_scan_t*tgt) const { tgt->expr_ufunc(this); diff --git a/ivl_target.h b/ivl_target.h index 18131b50c..31a571bbe 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -232,6 +232,7 @@ typedef enum ivl_expr_type_e { IVL_EX_SCOPE = 6, IVL_EX_SELECT = 7, IVL_EX_SFUNC = 8, + IVL_EX_SHALLOWCOPY = 25, IVL_EX_SIGNAL = 9, IVL_EX_STRING = 10, IVL_EX_TERNARY = 11, diff --git a/net_expr.cc b/net_expr.cc index dc0f2068c..0057e5dec 100644 --- a/net_expr.cc +++ b/net_expr.cc @@ -511,6 +511,20 @@ const netenum_t* NetESFunc::enumeration() const return enum_type_; } +NetEShallowCopy::NetEShallowCopy(NetExpr*arg1, NetExpr*arg2) +: arg1_(arg1), arg2_(arg2) +{ +} + +NetEShallowCopy::~NetEShallowCopy() +{ +} + +ivl_variable_type_t NetEShallowCopy::expr_type() const +{ + return arg1_->expr_type(); +} + NetEAccess::NetEAccess(NetBranch*br, ivl_nature_t nat) : branch_(br), nature_(nat) { diff --git a/net_nex_input.cc b/net_nex_input.cc index d75b3c7c1..b0a3e61e2 100644 --- a/net_nex_input.cc +++ b/net_nex_input.cc @@ -155,6 +155,11 @@ NexusSet* NetESFunc::nex_input(bool rem_out) return result; } +NexusSet* NetEShallowCopy::nex_input(bool) +{ + return new NexusSet; +} + NexusSet* NetESignal::nex_input(bool rem_out) { /* diff --git a/netlist.h b/netlist.h index 7803c2d6a..936c94d14 100644 --- a/netlist.h +++ b/netlist.h @@ -4101,6 +4101,28 @@ class NetESFunc : public NetExpr { NetESFunc& operator= (const NetESFunc&); }; +class NetEShallowCopy : public NetExpr { + public: + // Make a shallow copy from arg2 into arg1. + explicit NetEShallowCopy(NetExpr*arg1, NetExpr*arg2); + ~NetEShallowCopy(); + + virtual ivl_variable_type_t expr_type() const; + + virtual void expr_scan(struct expr_scan_t*) const; + virtual NetEShallowCopy* dup_expr() const; + virtual NexusSet* nex_input(bool rem_out = true); + + virtual void dump(ostream&os) const; + + void expr_scan_oper1(struct expr_scan_t*) const; + void expr_scan_oper2(struct expr_scan_t*) const; + + private: + NetExpr*arg1_; + NetExpr*arg2_; +}; + /* * This class represents the ternary (?:) operator. It has 3 * expressions, one of which is a condition used to select which of diff --git a/t-dll-api.cc b/t-dll-api.cc index 0aa7dd577..f090536e6 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -497,6 +497,9 @@ extern "C" ivl_expr_t ivl_expr_oper1(ivl_expr_t net) case IVL_EX_NEW: return net->u_.new_.size; + case IVL_EX_SHALLOWCOPY: + return net->u_.shallow_.dest; + case IVL_EX_SIGNAL: return net->u_.signal_.word; @@ -520,6 +523,9 @@ extern "C" ivl_expr_t ivl_expr_oper2(ivl_expr_t net) case IVL_EX_SELECT: return net->u_.select_.base_; + case IVL_EX_SHALLOWCOPY: + return net->u_.shallow_.src; + case IVL_EX_TERNARY: return net->u_.ternary_.true_e; diff --git a/t-dll-expr.cc b/t-dll-expr.cc index 3f7f53709..019ca9773 100644 --- a/t-dll-expr.cc +++ b/t-dll-expr.cc @@ -405,6 +405,28 @@ void dll_target::expr_scope(const NetEScope*net) expr_->u_.scope_.scope = lookup_scope_(net->scope()); } +void dll_target::expr_scopy(const NetEShallowCopy*net) +{ + assert(expr_ == 0); + + net->expr_scan_oper1(this); + ivl_expr_t expr1 = expr_; + expr_ = 0; + + net->expr_scan_oper2(this); + ivl_expr_t expr2 = expr_; + expr_ = 0; + + expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s)); + expr_->type_ = IVL_EX_SHALLOWCOPY; + FILE_NAME(expr_, net); + expr_->value_ = net->expr_type(); + expr_->net_type = net->net_type(); + + expr_->u_.shallow_.dest = expr1; + expr_->u_.shallow_.src = expr2; +} + void dll_target::expr_netenum(const NetENetenum*net) { assert(expr_ == 0); diff --git a/t-dll.h b/t-dll.h index 2876a5aa2..a4cd38c4f 100644 --- a/t-dll.h +++ b/t-dll.h @@ -145,6 +145,7 @@ struct dll_target : public target_t, public expr_scan_t { void expr_rparam(const NetECRealParam*); void expr_event(const NetEEvent*); void expr_scope(const NetEScope*); + void expr_scopy(const NetEShallowCopy*); void expr_netenum(const NetENetenum*); void expr_select(const NetESelect*); void expr_sfunc(const NetESFunc*); @@ -243,6 +244,11 @@ struct ivl_expr_s { ivl_expr_t base_; } select_; + struct { + ivl_expr_t dest; + ivl_expr_t src; + } shallow_; + struct { ivl_branch_t branch; ivl_nature_t nature; diff --git a/target.cc b/target.cc index 77dabeb7c..f3a3acd79 100644 --- a/target.cc +++ b/target.cc @@ -508,6 +508,12 @@ void expr_scan_t::expr_scope(const NetEScope*) "unhandled expr_scope." << endl; } +void expr_scan_t::expr_scopy(const NetEShallowCopy*) +{ + cerr << "expr_scan_t (" << typeid(*this).name() << "): " + "unhandled expr_scopy." << endl; +} + void expr_scan_t::expr_select(const NetESelect*) { cerr << "expr_scan_t (" << typeid(*this).name() << "): " diff --git a/target.h b/target.h index a82924b13..d65ffb50b 100644 --- a/target.h +++ b/target.h @@ -161,6 +161,7 @@ struct expr_scan_t { virtual void expr_concat(const NetEConcat*); virtual void expr_event(const NetEEvent*); virtual void expr_scope(const NetEScope*); + virtual void expr_scopy(const NetEShallowCopy*); virtual void expr_select(const NetESelect*); virtual void expr_sfunc(const NetESFunc*); virtual void expr_signal(const NetESignal*); diff --git a/tgt-stub/expression.c b/tgt-stub/expression.c index 1bff24c82..b711d9f93 100644 --- a/tgt-stub/expression.c +++ b/tgt-stub/expression.c @@ -273,6 +273,25 @@ static void show_select_expression(ivl_expr_t net, unsigned ind) } } +static void show_shallowcopy(ivl_expr_t net, unsigned ind) +{ + ivl_expr_t oper1 = ivl_expr_oper1(net); + ivl_expr_t oper2 = ivl_expr_oper2(net); + fprintf(out, "%*s\n", ind, ""); + show_expression(oper1, ind+3); + show_expression(oper2, ind+3); + + if (ivl_expr_value(oper1) != ivl_expr_value(oper2)) { + fprintf(out, "%*sERROR: Shallow copy operand types must match.\n", ind+3,""); + stub_errors += 1; + } + + if (ivl_expr_value(oper1)!=IVL_VT_CLASS && ivl_expr_value(oper1)!=IVL_VT_DARRAY) { + fprintf(out, "%*sERROR: Operand 1 type is %s\n", ind+3, "", vt_type_string(oper1)); + stub_errors += 1; + } +} + static void show_signal_expression(ivl_expr_t net, unsigned ind) { unsigned width = ivl_expr_width(net); @@ -502,6 +521,10 @@ void show_expression(ivl_expr_t net, unsigned ind) } break; + case IVL_EX_SHALLOWCOPY: + show_shallowcopy(net, ind); + break; + default: fprintf(out, "%*s\n", ind, "", code); break;