From 25dae60bb6e65c125ab0c80c651ac384e0f595d2 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 15 Jan 2022 23:09:19 +0100 Subject: [PATCH 1/5] Add support for explicit cast to packed struct and packed array Currently explicit cast is supported to atom2 and vector types. packed struct, packed array and enum are not supported. An explicit cast to packed type works the same for all packed types though. Add support for handling also packed structs, packed arrays and enums by make the code more generic and querying the packed base type from the ivl_type_t. To correctly handle enums a bit more work is necessary, which will be done in a follow up patch. Signed-off-by: Lars-Peter Clausen --- PExpr.h | 1 + elab_expr.cc | 19 ++++++++----------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/PExpr.h b/PExpr.h index 6420e057d..93ddae44d 100644 --- a/PExpr.h +++ b/PExpr.h @@ -1007,6 +1007,7 @@ class PECastType : public PExpr { private: data_type_t* target_; + ivl_type_t target_type_; PExpr* base_; }; diff --git a/elab_expr.cc b/elab_expr.cc index ca71a89b6..ffcbae2e2 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -3351,25 +3351,25 @@ NetExpr* PECastSize::elaborate_expr(Design*des, NetScope*scope, unsigned PECastType::test_width(Design*des, NetScope*scope, width_mode_t&) { - ivl_type_t t = target_->elaborate_type(des, scope); + target_type_ = target_->elaborate_type(des, scope); width_mode_t tmp_mode = PExpr::SIZED; base_->test_width(des, scope, tmp_mode); - if (const netdarray_t*use_darray = dynamic_cast(t)) { + if (const netdarray_t*use_darray = dynamic_cast(target_type_)) { expr_type_ = use_darray->element_base_type(); expr_width_ = use_darray->element_width(); - } else if (const netstring_t*use_string = dynamic_cast(t)) { + } else if (const netstring_t*use_string = dynamic_cast(target_type_)) { expr_type_ = use_string->base_type(); expr_width_ = 8; } else { - expr_type_ = t->base_type(); - expr_width_ = t->packed_width(); + expr_type_ = target_type_->base_type(); + expr_width_ = target_type_->packed_width(); } min_width_ = expr_width_; - signed_flag_ = t->get_signed(); + signed_flag_ = target_type_->get_signed(); return expr_width_; } @@ -3427,11 +3427,8 @@ NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope, } NetExpr*tmp = 0; - if (dynamic_cast(target_)) { - tmp = cast_to_int2(sub, expr_width_); - } - if (const vector_type_t*vec = dynamic_cast(target_)) { - switch (vec->base_type) { + if (target_type_ && target_type_->packed()) { + switch (target_type_->base_type()) { case IVL_VT_BOOL: tmp = cast_to_int2(sub, expr_width_); break; From 9b7c99b8a81a287e1d7b9de444ff67c69274eeaf Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 16 Jan 2022 10:04:58 +0100 Subject: [PATCH 2/5] NetEConstEnum: Remove unused scope_ field The scope_ field of the NetEConstEnum class is initialized in the constructor, but never used anywhere again. Remove it. Signed-off-by: Lars-Peter Clausen --- dup_expr.cc | 2 +- elab_expr.cc | 6 ++---- net_expr.cc | 4 ++-- net_scope.cc | 2 +- netlist.h | 5 ++--- 5 files changed, 8 insertions(+), 11 deletions(-) diff --git a/dup_expr.cc b/dup_expr.cc index 64afcba7e..16b79f196 100644 --- a/dup_expr.cc +++ b/dup_expr.cc @@ -148,7 +148,7 @@ NetEConst* NetEConst::dup_expr() const NetEConstEnum* NetEConstEnum::dup_expr() const { - NetEConstEnum*tmp = new NetEConstEnum(scope_, name_, enum_set_, value()); + NetEConstEnum*tmp = new NetEConstEnum(name_, enum_set_, value()); ivl_assert(*this, tmp); tmp->set_line(*this); return tmp; diff --git a/elab_expr.cc b/elab_expr.cc index ffcbae2e2..d3c89fe23 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -1969,8 +1969,7 @@ static NetExpr* check_for_enum_methods(const LineInfo*li, des->errors += 1; } netenum_t::iterator item = netenum->first_name(); - NetEConstEnum*tmp = new NetEConstEnum(scope, item->first, - netenum, item->second); + NetEConstEnum*tmp = new NetEConstEnum(item->first, netenum, item->second); tmp->set_line(*li); delete expr; // The elaborated enum variable is not needed. return tmp; @@ -1987,8 +1986,7 @@ static NetExpr* check_for_enum_methods(const LineInfo*li, des->errors += 1; } netenum_t::iterator item = netenum->last_name(); - NetEConstEnum*tmp = new NetEConstEnum(scope, item->first, - netenum, item->second); + NetEConstEnum*tmp = new NetEConstEnum(item->first, netenum, item->second); tmp->set_line(*li); delete expr; // The elaborated enum variable is not needed. return tmp; diff --git a/net_expr.cc b/net_expr.cc index f3c552fe6..4a0ee3008 100644 --- a/net_expr.cc +++ b/net_expr.cc @@ -263,8 +263,8 @@ void NetEConcat::set(unsigned idx, NetExpr*e) expr_width( expr_width() + repeat_ * e->expr_width() ); } -NetEConstEnum::NetEConstEnum(Definitions*s, perm_string n, const netenum_t*eset, const verinum&v) -: NetEConst(v), scope_(s), enum_set_(eset), name_(n) +NetEConstEnum::NetEConstEnum(perm_string n, const netenum_t*eset, const verinum&v) +: NetEConst(v), enum_set_(eset), name_(n) { assert(has_width()); } diff --git a/net_scope.cc b/net_scope.cc index d5e086c02..1a4216069 100644 --- a/net_scope.cc +++ b/net_scope.cc @@ -55,7 +55,7 @@ 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); + NetEConstEnum*val = new NetEConstEnum(name, enum_set, enum_val->second); pair::iterator, bool> cur; cur = enum_names_.insert(make_pair(name,val)); diff --git a/netlist.h b/netlist.h index db53c9f55..85dc8ce8b 100644 --- a/netlist.h +++ b/netlist.h @@ -2153,8 +2153,8 @@ class NetEConst : public NetExpr { class NetEConstEnum : public NetEConst { public: - explicit NetEConstEnum(Definitions*scope, perm_string name, - const netenum_t*enum_set, const verinum&val); + explicit NetEConstEnum(perm_string name, const netenum_t*enum_set, + const verinum&val); ~NetEConstEnum(); perm_string name() const; @@ -2166,7 +2166,6 @@ class NetEConstEnum : public NetEConst { virtual NetEConstEnum* dup_expr() const; private: - Definitions*scope_; const netenum_t*enum_set_; perm_string name_; }; From 053453c645f9ec539e2cf5d86f710458d56ed124 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 16 Jan 2022 10:08:29 +0100 Subject: [PATCH 3/5] Add support for explicit cast to enum Assigning a value to an enum signal that is not of the same type as the enum requires an explicit cast. To support this attach the type of a type cast to the resulting expression. This allows the assignment elaboration to confirm that value has been explicitly cast to the right type. Also handle the case where the value is a constant. In this case create a NetEConstEnum instead of a NetEConst as the resulting expression. Signed-off-by: Lars-Peter Clausen --- elab_expr.cc | 2 +- netmisc.h | 6 +++--- pad_to_width.cc | 15 +++++++++++---- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index d3c89fe23..a6cb6b447 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -3447,7 +3447,7 @@ NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope, // the signedness pushed down from the main expression. tmp = cast_to_width(sub, expr_width_, sub->has_sign(), *this); } - return pad_to_width(tmp, expr_wid, signed_flag_, *this); + return pad_to_width(tmp, expr_wid, signed_flag_, *this, target_type_); } if (dynamic_cast(target_)) { diff --git a/netmisc.h b/netmisc.h index 4a7d23f8a..17f3d20b9 100644 --- a/netmisc.h +++ b/netmisc.h @@ -161,13 +161,13 @@ inline NetScope* symbol_search(const LineInfo*li, * signed_flag. */ extern NetExpr*pad_to_width(NetExpr*expr, unsigned wid, bool signed_flag, - const LineInfo&info); + const LineInfo&info, ivl_type_t use_type = 0); /* * This version determines the extension method from the base expression type. */ -inline NetExpr*pad_to_width(NetExpr*expr, unsigned wid, const LineInfo&info) +inline NetExpr*pad_to_width(NetExpr*expr, unsigned wid, const LineInfo&info, ivl_type_t use_type = 0) { - return pad_to_width(expr, wid, expr->has_sign(), info); + return pad_to_width(expr, wid, expr->has_sign(), info, use_type); } /* diff --git a/pad_to_width.cc b/pad_to_width.cc index 32db9e6c4..5ec66a862 100644 --- a/pad_to_width.cc +++ b/pad_to_width.cc @@ -19,15 +19,16 @@ # include "config.h" +# include "netenum.h" # include "netlist.h" # include "netvector.h" # include "netmisc.h" NetExpr*pad_to_width(NetExpr*expr, unsigned wid, bool signed_flag, - const LineInfo&info) + const LineInfo&info, ivl_type_t use_type) { - if (wid <= expr->expr_width()) { + if (wid <= expr->expr_width() && !use_type) { expr->cast_signed(signed_flag); return expr; } @@ -38,13 +39,19 @@ NetExpr*pad_to_width(NetExpr*expr, unsigned wid, bool signed_flag, verinum oval = tmp->value(); oval.has_sign(signed_flag); oval = pad_to_width(oval, wid); - tmp = new NetEConst(oval); + if (const netenum_t *enum_type = dynamic_cast(use_type)) { + // The name of the enum is set to here, but the name is + // only used in debugging output, so this is ok + tmp = new NetEConstEnum(perm_string(), enum_type, oval); + } else { + tmp = new NetEConst(oval); + } tmp->set_line(info); delete expr; return tmp; } - NetESelect*tmp = new NetESelect(expr, 0, wid); + NetESelect*tmp = new NetESelect(expr, 0, wid, use_type); tmp->cast_signed(signed_flag); tmp->set_line(info); return tmp; From 1858c6a313373f0d1629d11dd85793152273bf8d Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 16 Jan 2022 10:52:46 +0100 Subject: [PATCH 4/5] Set regression test for explicit enum cast to supported Update the enum cast test to reflect that enum casts are now supported. Also add a small check to verify that the right value got assigned to the enum after the cast. Signed-off-by: Lars-Peter Clausen --- ivtest/ivltests/br_gh130b.v | 8 +++++++- ivtest/ivltests/br_gh386d.v | 10 +++++++++- ivtest/regress-fsv.list | 2 -- ivtest/regress-ivl1.list | 2 -- ivtest/regress-sv.list | 2 ++ ivtest/regress-vlog95.list | 2 ++ 6 files changed, 20 insertions(+), 6 deletions(-) diff --git a/ivtest/ivltests/br_gh130b.v b/ivtest/ivltests/br_gh130b.v index 7f40f0d22..cec7c6322 100644 --- a/ivtest/ivltests/br_gh130b.v +++ b/ivtest/ivltests/br_gh130b.v @@ -1,4 +1,4 @@ -// This is currently unsupported, but is legal code. +// Test that cast to enum works in procedural assignments module test(); typedef enum { a, b, c } enum_type; @@ -7,6 +7,12 @@ enum_type enum_value; initial begin enum_value = enum_type'(1); + + if (enum_value == b) begin + $display("PASSED"); + end else begin + $display("FAILED"); + end end endmodule diff --git a/ivtest/ivltests/br_gh386d.v b/ivtest/ivltests/br_gh386d.v index ccd5771a7..992752911 100644 --- a/ivtest/ivltests/br_gh386d.v +++ b/ivtest/ivltests/br_gh386d.v @@ -1,4 +1,4 @@ -// This is currently unsupported, but is legal code. +// Test that cast to enum works in continuous assignments module test(); typedef enum { a, b, c } enum_type; @@ -7,4 +7,12 @@ enum_type enum_value; assign enum_value = enum_type'(1); +initial begin + if (enum_value == b) begin + $display("PASSED"); + end else begin + $display("FAILED"); + end +end + endmodule diff --git a/ivtest/regress-fsv.list b/ivtest/regress-fsv.list index a6eb46a0e..777f40427 100644 --- a/ivtest/regress-fsv.list +++ b/ivtest/regress-fsv.list @@ -115,8 +115,6 @@ br605b normal ivltests br971 normal ivltests br1005 normal ivltests br1015b normal ivltests -br_gh130b normal ivltests -br_gh386d normal ivltests br_ml20150315b normal ivltests sv_deferred_assert1 normal ivltests sv_deferred_assert2 normal ivltests diff --git a/ivtest/regress-ivl1.list b/ivtest/regress-ivl1.list index 53304ecc0..97ead6058 100644 --- a/ivtest/regress-ivl1.list +++ b/ivtest/regress-ivl1.list @@ -294,8 +294,6 @@ br605b EF ivltests br971 EF ivltests br1005 CE,-g2009 ivltests br1015b CE,-g2009 ivltests -br_gh130b CE,-g2009 ivltests -br_gh386d CE,-g2009 ivltests br_ml20150315b CE,-g2009 ivltests sv_deferred_assert1 CE,-g2009 ivltests gold=sv_deferred_assert1.gold sv_deferred_assert2 CE,-g2009 ivltests gold=sv_deferred_assert2.gold diff --git a/ivtest/regress-sv.list b/ivtest/regress-sv.list index 80d054047..8d384ee36 100644 --- a/ivtest/regress-sv.list +++ b/ivtest/regress-sv.list @@ -149,6 +149,7 @@ br_gh112e normal,-g2009 ivltests br_gh112f normal,-g2009 ivltests br_gh129 normal,-g2009 ivltests br_gh130a CE,-g2009 ivltests +br_gh130b normal,-g2009 ivltests br_gh165 normal,-g2009 ivltests gold=br_gh165.gold br_gh164a normal,-g2009 ivltests br_gh164b normal,-g2009 ivltests @@ -184,6 +185,7 @@ br_gh374 normal,-g2009 ivltests gold=br_gh374.gold br_gh386a normal,-g2009 ivltests br_gh386b normal,-g2009 ivltests br_gh386c CE,-g2009 ivltests +br_gh386d normal,-g2009 ivltests br_gh388 normal,-g2009 ivltests gold=br_gh388.gold br_gh391 normal,-g2009 ivltests gold=br_gh391.gold br_gh411 normal,-g2009 ivltests diff --git a/ivtest/regress-vlog95.list b/ivtest/regress-vlog95.list index a595d4969..d891f46a0 100644 --- a/ivtest/regress-vlog95.list +++ b/ivtest/regress-vlog95.list @@ -733,6 +733,7 @@ br_gh99r normal,-pallowsigned=1 ivltests br_gh112e normal,-g2009,-pallowsigned=1 ivltests br_gh112f normal,-g2009,-pallowsigned=1 ivltests br_gh129 normal,-g2009,-pallowsigned=1 ivltests +br_gh130b normal,-g2009,-pallowsigned=1 ivltests br_gh198 normal,-pallowsigned=1 ivltests gold=br_gh198.gold br_gh199a normal,-pallowsigned=1 ivltests br_gh199b normal,-pallowsigned=1 ivltests @@ -743,6 +744,7 @@ br_gh283a normal,-pallowsigned=1 ivltests br_gh283b normal,-pallowsigned=1 ivltests br_gh283c normal,-pallowsigned=1 ivltests br_gh289b normal,-g2009,-pallowsigned=1 ivltests +br_gh386d normal,-g2009,-pallowsigned=1 ivltests br_gh477 normal,-g2009,-pallowsigned=1 ivltests br_gh540 normal,-g2009,-pallowsigned=1 ivltests ca_mult normal,-pallowsigned=1 ivltests gold=ca_mult.gold From 5fc1976496439c5f8acd1c2b78b059abadfc94f0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 17 Jan 2022 09:47:54 +0100 Subject: [PATCH 5/5] Add regression test for explicit cast to packed array and packed struct These test verify that explicit cast to packed array and packed struct types are supported and executed correctly. The tests are based on the test for integer casts. Just the type of the variables was changed to packed array and packed struct respectively. Signed-off-by: Lars-Peter Clausen --- ivtest/ivltests/sv_cast_packed_array.v | 43 +++++++++++++++++++++++ ivtest/ivltests/sv_cast_packed_struct.v | 45 +++++++++++++++++++++++++ ivtest/regress-sv.list | 2 ++ ivtest/regress-vlog95.list | 1 + 4 files changed, 91 insertions(+) create mode 100644 ivtest/ivltests/sv_cast_packed_array.v create mode 100644 ivtest/ivltests/sv_cast_packed_struct.v diff --git a/ivtest/ivltests/sv_cast_packed_array.v b/ivtest/ivltests/sv_cast_packed_array.v new file mode 100644 index 000000000..17c5e4b29 --- /dev/null +++ b/ivtest/ivltests/sv_cast_packed_array.v @@ -0,0 +1,43 @@ +// This tests SystemVerilog casting support +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2012 by Iztok Jeras. +// Extended by Maciej Suminski +// Copied and modified by Martin Whitaker +// Copied and modified again by Lars-Peter Clausen + +module test(); + + typedef logic [7:0] pa08; + typedef pa08 [1:0] pa16; + typedef pa16 [1:0] pa32; + typedef pa32 [1:0] pa64; + + // variables used in casting + pa08 var_08; + pa16 var_16; + pa32 var_32; + pa64 var_64; + real var_real; + + // error counter + bit err = 0; + + initial begin + var_08 = pa08'(4'h5); if (var_08 !== 8'h05) begin $display("FAILED -- var_08 = 'h%0h != 8'h05", var_08); err=1; end + var_16 = pa16'(var_08); if (var_16 !== 16'h05) begin $display("FAILED -- var_16 = 'h%0h != 16'h05", var_16); err=1; end + var_32 = pa32'(var_16); if (var_32 !== 32'h05) begin $display("FAILED -- var_32 = 'h%0h != 32'h05", var_32); err=1; end + var_64 = pa64'(var_32); if (var_64 !== 64'h05) begin $display("FAILED -- var_64 = 'h%0h != 64'h05", var_64); err=1; end + + var_real = 13.4; var_08 = pa08'(var_real); if (var_08 !== 13) begin $display("FAILED -- var_08 = %d != 13", var_08); err=1; end + var_real = 14.5; var_16 = pa16'(var_real); if (var_16 !== 15) begin $display("FAILED -- var_16 = %d != 15", var_16); err=1; end + var_real = 15.6; var_32 = pa32'(var_real); if (var_32 !== 16) begin $display("FAILED -- var_32 = %d != 16", var_32); err=1; end + var_real = -15.6; var_64 = pa64'(var_real); if (var_64 !== -16) begin $display("FAILED -- var_64 = %d != -16", var_64); err=1; end + + var_08 = pa08'(4'hf); if (var_08 !== 8'h0f) begin $display("FAILED -- var_08 = 'h%0h != 8'h0f", var_08); err=1; end + var_16 = pa08'(16'h0f0f); if (var_16 !== 16'h0f) begin $display("FAILED -- var_16 = 'h%0h != 16'h0f", var_16); err=1; end + + if (!err) $display("PASSED"); + end + +endmodule // test diff --git a/ivtest/ivltests/sv_cast_packed_struct.v b/ivtest/ivltests/sv_cast_packed_struct.v new file mode 100644 index 000000000..4fe55672c --- /dev/null +++ b/ivtest/ivltests/sv_cast_packed_struct.v @@ -0,0 +1,45 @@ +// This tests SystemVerilog casting support +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2012 by Iztok Jeras. +// Extended by Maciej Suminski +// Copied and modified by Martin Whitaker +// Copied and modified again by Lars-Peter Clausen + +module test(); + + typedef struct packed signed { logic [7:0] x; } s08; + typedef struct packed signed { logic [15:0] x; } s16; + typedef struct packed signed { int x; } s32; + typedef struct packed signed { int x; shortint y; byte z; logic [7:0] w; } s64; + + // variables used in casting + s08 var_08; + s16 var_16; + s32 var_32; + s64 var_64; + real var_real; + + // error counter + bit err = 0; + + initial begin + var_08 = s08'(4'sh5); if (var_08 !== 8'sh05) begin $display("FAILED -- var_08 = 'h%0h != 8'h05", var_08); err=1; end + var_16 = s16'(var_08); if (var_16 !== 16'sh05) begin $display("FAILED -- var_16 = 'h%0h != 16'h05", var_16); err=1; end + var_32 = s32'(var_16); if (var_32 !== 32'sh05) begin $display("FAILED -- var_32 = 'h%0h != 32'h05", var_32); err=1; end + var_64 = s64'(var_32); if (var_64 !== 64'sh05) begin $display("FAILED -- var_64 = 'h%0h != 64'h05", var_64); err=1; end + + var_real = 13.4; var_08 = s08'(var_real); if (var_08 !== 13) begin $display("FAILED -- var_08 = %d != 13", var_08); err=1; end + var_real = 14.5; var_16 = s16'(var_real); if (var_16 !== 15) begin $display("FAILED -- var_16 = %d != 15", var_16); err=1; end + var_real = 15.6; var_32 = s32'(var_real); if (var_32 !== 16) begin $display("FAILED -- var_32 = %d != 16", var_32); err=1; end + var_real = -15.6; var_64 = s64'(var_real); if (var_64 !== -16) begin $display("FAILED -- var_64 = %d != -16", var_64); err=1; end + + var_08 = s08'(4'hf); if (var_08 !== 8'sh0f) begin $display("FAILED -- var_08 = 'h%0h != 8'h0f", var_08); err=1; end + var_08 = s08'(4'shf); if (var_08 !== 8'shff) begin $display("FAILED -- var_08 = 'h%0h != 8'hff", var_08); err=1; end + var_16 = s08'(16'h0f0f); if (var_16 !== 16'sh0f) begin $display("FAILED -- var_16 = 'h%0h != 16'h0f", var_16); err=1; end + var_16 = s08'(4'shf) + 'd0; if (var_16 !== 16'shff) begin $display("FAILED -- var_16 = 'h%0h != 16'hff", var_16); err=1; end + + if (!err) $display("PASSED"); + end + +endmodule // test diff --git a/ivtest/regress-sv.list b/ivtest/regress-sv.list index 8d384ee36..b42729baf 100644 --- a/ivtest/regress-sv.list +++ b/ivtest/regress-sv.list @@ -390,6 +390,8 @@ sv-constants normal,-g2005-sv ivltests sv_array_assign_pattern2 normal,-g2009 ivltests sv_cast_integer normal,-g2005-sv ivltests sv_cast_integer2 normal,-g2005-sv ivltests +sv_cast_packed_array normal,-g2005-sv ivltests +sv_cast_packed_struct normal,-g2005-sv ivltests sv_cast_string normal,-g2005-sv ivltests sv_class1 normal,-g2009 ivltests sv_class2 normal,-g2009 ivltests diff --git a/ivtest/regress-vlog95.list b/ivtest/regress-vlog95.list index d891f46a0..402e8e351 100644 --- a/ivtest/regress-vlog95.list +++ b/ivtest/regress-vlog95.list @@ -118,6 +118,7 @@ cast_real_signed CE,-pallowsigned=1 ivltests cast_real_unsigned CE ivltests sv_cast_integer normal,-g2005-sv,-pallowsigned=1 ivltests sv_cast_integer2 normal,-g2005-sv,-pallowsigned=1 ivltests +sv_cast_packed_struct normal,-g2005-sv,-pallowsigned=1 ivltests sv_cast_string CE ivltests clog2 CE ivltests # Also big int delayed_sfunc CE ivltests