diff --git a/.gitignore b/.gitignore index ba885fa6d..678da57ec 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ tags TAGS cscope.* *.patch +*.orig # Object files and libraries *.[oa] diff --git a/PExpr.h b/PExpr.h index 59e64abdb..e2365c897 100644 --- a/PExpr.h +++ b/PExpr.h @@ -494,6 +494,8 @@ class PENull : public PExpr { 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; virtual NetExpr*elaborate_expr(Design*des, NetScope*, unsigned expr_wid, unsigned flags) const; diff --git a/elab_expr.cc b/elab_expr.cc index 7513c1701..0b302525c 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -4015,8 +4015,7 @@ NetExpr* PENew::elaborate_expr(Design*des, NetScope*scope, /* * This method should never actually be called. */ -NetExpr* PENew::elaborate_expr(Design*des, NetScope*scope, - unsigned, unsigned flags) const +NetExpr* PENew::elaborate_expr(Design*, NetScope*, unsigned, unsigned) const { ivl_assert(*this, 0); return 0; @@ -4053,6 +4052,13 @@ unsigned PENull::test_width(Design*, NetScope*, width_mode_t&) return expr_width_; } +NetExpr* PENull::elaborate_expr(Design*, NetScope*, ivl_type_t, unsigned) const +{ + NetENull*tmp = new NetENull; + tmp->set_line(*this); + return tmp; +} + NetExpr* PENull::elaborate_expr(Design*, NetScope*, unsigned, unsigned) const { NetENull*tmp = new NetENull; diff --git a/elaborate.cc b/elaborate.cc index 9a67f6976..076260c0b 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -2385,6 +2385,9 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const handle it with this code instead. */ rv = elaborate_rval_(des, scope, lv->sig()->net_type()); + } else if (lv->more==0 && dynamic_cast (rval())) { + rv = elaborate_rval_(des, scope, lv->sig()->net_type()); + } else if (lv->more==0 && dynamic_cast (rval())) { rv = elaborate_rval_(des, scope, lv->sig()->net_type()); diff --git a/tgt-vvp/eval_object.c b/tgt-vvp/eval_object.c index 2e60db26f..d5a40ec28 100644 --- a/tgt-vvp/eval_object.c +++ b/tgt-vvp/eval_object.c @@ -73,6 +73,12 @@ static int eval_class_new(ivl_expr_t ex) return 0; } +static int eval_object_null(ivl_expr_t ex) +{ + fprintf(vvp_out, " %%null;\n"); + return 0; +} + int draw_eval_object(ivl_expr_t ex) { switch (ivl_expr_type(ex)) { @@ -88,6 +94,10 @@ int draw_eval_object(ivl_expr_t ex) ivl_expr_value(ex)); return 0; } + + case IVL_EX_NULL: + return eval_object_null(ex); + default: fprintf(vvp_out, "; ERROR: Invalid expression type %u\n", ivl_expr_type(ex)); return 1; diff --git a/vvp/codes.h b/vvp/codes.h index 30a891b37..21e27a178 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -153,6 +153,7 @@ extern bool of_NEW_DARRAY(vthread_t thr, vvp_code_t code); extern bool of_NOOP(vthread_t thr, vvp_code_t code); extern bool of_NOR(vthread_t thr, vvp_code_t code); extern bool of_NORR(vthread_t thr, vvp_code_t code); +extern bool of_NULL(vthread_t thr, vvp_code_t code); extern bool of_OR(vthread_t thr, vvp_code_t code); extern bool of_ORR(vthread_t thr, vvp_code_t code); extern bool of_PAD(vthread_t thr, vvp_code_t code); diff --git a/vvp/compile.cc b/vvp/compile.cc index ff5aac013..e0bd89529 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -201,6 +201,7 @@ static const struct opcode_table_s opcode_table[] = { { "%noop", of_NOOP, 0, {OA_NONE, OA_NONE, OA_NONE} }, { "%nor", of_NOR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%nor/r", of_NORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, + { "%null", of_NULL, 0, {OA_NONE, OA_NONE, OA_NONE} }, { "%or", of_OR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%or/r", of_ORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%pad", of_PAD, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, diff --git a/vvp/opcodes.txt b/vvp/opcodes.txt index 79ea00cc2..28326dab8 100644 --- a/vvp/opcodes.txt +++ b/vvp/opcodes.txt @@ -386,7 +386,14 @@ supports run-time calculated delays. * %delete/obj Arrange for the dynamic object at the target label to be deleted. -This has no effect on the object or string stack. +This has no effect on the object or string stack. Note that this is +the same as: + + %null ; + %store/obj + +but that idiom is expected to be common enough that it warrants an +optimized shorthand. * %disable @@ -802,6 +809,11 @@ The actual operation performed is the inverted or of all the bits in the vector. +* %null + +Push a null object and push it to the object stack. The null object +can be used with any class or darray object, so it is not typed. + * %or , , Perform the bitwise or of the vectors. Each bit in the is diff --git a/vvp/vthread.cc b/vvp/vthread.cc index b107fab78..3092a0b1a 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -4146,6 +4146,17 @@ bool of_NORR(vthread_t thr, vvp_code_t cp) return true; } +/* + * Push a null to the object stack. + */ +bool of_NULL(vthread_t thr, vvp_code_t cp) +{ + vvp_object_t tmp; + thr->push_object(tmp); + return true; +} + + bool of_ANDR(vthread_t thr, vvp_code_t cp) { assert(cp->bit_idx[0] >= 4);