From 6ec31517a9ccdb0e312eeacd24ac38d309a10bf3 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Mon, 16 Dec 2013 04:36:13 +0200 Subject: [PATCH] Implement $bits(type) to get the size of a type In the process, I implemented a means to get at previously elaborated types from the pform type pointer. --- PExpr.h | 2 ++ PFunction.cc | 2 +- PTask.h | 4 ++-- elab_expr.cc | 29 ++++++++++++++++++++--------- elab_sig.cc | 7 ++++--- elab_type.cc | 18 +++++++++--------- pform_types.cc | 9 +++++++++ pform_types.h | 25 ++++++++++++++++--------- 8 files changed, 63 insertions(+), 33 deletions(-) diff --git a/PExpr.h b/PExpr.h index 910f8a1b8..fa44c70b5 100644 --- a/PExpr.h +++ b/PExpr.h @@ -671,6 +671,8 @@ class PETypename : public PExpr { virtual NetExpr*elaborate_expr(Design*des, NetScope*scope, ivl_type_t type, unsigned flags) const; + inline data_type_t* get_type() const { return data_type_; } + private: data_type_t*data_type_; }; diff --git a/PFunction.cc b/PFunction.cc index e15fab119..a5dc8f351 100644 --- a/PFunction.cc +++ b/PFunction.cc @@ -65,7 +65,7 @@ void PFunction::push_statement_front(Statement*stmt) blk->push_statement_front(stmt); } -void PFunction::set_return(const data_type_t*t) +void PFunction::set_return(data_type_t*t) { return_type_ = t; } diff --git a/PTask.h b/PTask.h index 87b0df958..9e417615f 100644 --- a/PTask.h +++ b/PTask.h @@ -114,7 +114,7 @@ class PFunction : public PTaskFunc { ~PFunction(); void set_statement(Statement *s); - void set_return(const data_type_t*t); + void set_return(data_type_t*t); inline Statement* get_statement() { return statement_; } @@ -141,7 +141,7 @@ class PFunction : public PTaskFunc { void dump(ostream&, unsigned) const; private: - const data_type_t* return_type_; + data_type_t* return_type_; Statement *statement_; bool is_auto_; }; diff --git a/elab_expr.cc b/elab_expr.cc index 67397c26e..71e584d67 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -1397,18 +1397,29 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope, PExpr*expr = parms_[0]; + uint64_t use_width = 0; if (PETypename*type_expr = dynamic_cast(expr)) { - cerr << get_fileline() << ": sorry: " - << "I don't yet support typename argumets to $bits." << endl; - des->errors += 1; - return 0; - } else { - verinum val ( (uint64_t)expr->expr_width(), integer_width); - NetEConst*sub = new NetEConst(val); - sub->set_line(*this); + ivl_type_t tmp_type = type_expr->get_type()->elaborate_type(des, scope); + ivl_assert(*this, tmp_type); + use_width = tmp_type->packed_width(); + if (debug_elaborate) { + cerr << get_fileline() << ": PECallFunction::elaborate_sfunc_: " + << " Packed width of type argument is " << use_width << endl; + } - return cast_to_width_(sub, expr_wid); + } else { + use_width = expr->expr_width(); + if (debug_elaborate) { + cerr << get_fileline() << ": PECallFunction::elaborate_sfunc_: " + << " Width of expression argument is " << use_width << endl; + } } + + verinum val (use_width, integer_width); + NetEConst*sub = new NetEConst(val); + sub->set_line(*this); + + return cast_to_width_(sub, expr_wid); } /* Interpret the internal $is_signed system function to return diff --git a/elab_sig.cc b/elab_sig.cc index d60e2a1f5..1b5c90f7a 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -563,7 +563,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const // Special case: this is a constructor, so the return // signal is also the first argument. For example, the // source code for the definition may be: - // function new(...); + // function new(...); // endfunction // In this case, the "@" port is the synthetic "this" // argument and we also use it as a return value at the @@ -876,7 +876,7 @@ static ivl_type_s*elaborate_type(Design*des, NetScope*scope, data_type_t*pform_type) { if (struct_type_t*struct_type = dynamic_cast(pform_type)) { - netstruct_t*use_type = struct_type->elaborate_type(des, scope); + ivl_type_s*use_type = struct_type->elaborate_type(des, scope); return use_type; } @@ -1210,7 +1210,8 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const } else if (struct_type_t*struct_type = dynamic_cast(set_data_type_)) { // If this is a struct type, then build the net with the // struct type. - netstruct_t*use_type = struct_type->elaborate_type(des, scope); + ivl_type_s*tmp_type = struct_type->elaborate_type(des, scope); + netstruct_t*use_type = dynamic_cast(tmp_type); if (debug_elaborate) { cerr << get_fileline() << ": debug: Create signal " << wtype; if (use_type->packed()) diff --git a/elab_type.cc b/elab_type.cc index 997069ea0..8f4b8068e 100644 --- a/elab_type.cc +++ b/elab_type.cc @@ -31,7 +31,7 @@ using namespace std; -ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*) const +ivl_type_s* data_type_t::elaborate_type_raw(Design*des, NetScope*) const { cerr << get_fileline() << ": internal error: " << "Elaborate method not implemented for " << typeid(*this).name() @@ -40,7 +40,7 @@ ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*) const return 0; } -ivl_type_s* atom2_type_t::elaborate_type(Design*des, NetScope*) const +ivl_type_s* atom2_type_t::elaborate_type_raw(Design*des, NetScope*) const { switch (type_code) { case 64: @@ -75,18 +75,18 @@ ivl_type_s* atom2_type_t::elaborate_type(Design*des, NetScope*) const } } -ivl_type_s* class_type_t::elaborate_type(Design*, NetScope*scope) const +ivl_type_s* class_type_t::elaborate_type_raw(Design*, NetScope*scope) const { return scope->find_class(name); } -ivl_type_s* enum_type_t::elaborate_type(Design*des, NetScope*scope) const +ivl_type_s* enum_type_t::elaborate_type_raw(Design*des, NetScope*scope) const { ivl_assert(*this, net_type); return net_type; } -ivl_type_s* vector_type_t::elaborate_type(Design*des, NetScope*scope) const +ivl_type_s* vector_type_t::elaborate_type_raw(Design*des, NetScope*scope) const { vector packed; @@ -122,7 +122,7 @@ ivl_type_s* vector_type_t::elaborate_type(Design*des, NetScope*scope) const return tmp; } -ivl_type_s* real_type_t::elaborate_type(Design*, NetScope*) const +ivl_type_s* real_type_t::elaborate_type_raw(Design*, NetScope*) const { switch (type_code) { case REAL: @@ -133,12 +133,12 @@ ivl_type_s* real_type_t::elaborate_type(Design*, NetScope*) const return 0; } -ivl_type_s* string_type_t::elaborate_type(Design*, NetScope*) const +ivl_type_s* string_type_t::elaborate_type_raw(Design*, NetScope*) const { return &netstring_t::type_string; } -netstruct_t* struct_type_t::elaborate_type(Design*des, NetScope*scope) const +netstruct_t* struct_type_t::elaborate_type_raw(Design*des, NetScope*scope) const { netstruct_t*res = new netstruct_t; @@ -173,7 +173,7 @@ netstruct_t* struct_type_t::elaborate_type(Design*des, NetScope*scope) const return res; } -ivl_type_s* uarray_type_t::elaborate_type(Design*des, NetScope*scope) const +ivl_type_s* uarray_type_t::elaborate_type_raw(Design*des, NetScope*scope) const { ivl_type_t btype = base_type->elaborate_type(des, scope); diff --git a/pform_types.cc b/pform_types.cc index 5a7868bef..c809ffbf6 100644 --- a/pform_types.cc +++ b/pform_types.cc @@ -24,6 +24,15 @@ data_type_t::~data_type_t() { } +ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*scope) +{ + if (cache_type_elaborate_) + return cache_type_elaborate_; + + cache_type_elaborate_ = elaborate_type_raw(des, scope); + return cache_type_elaborate_; +} + string_type_t::~string_type_t() { } diff --git a/pform_types.h b/pform_types.h index 207e47700..94ea7266c 100644 --- a/pform_types.h +++ b/pform_types.h @@ -88,14 +88,21 @@ struct pform_tf_port_t { */ class data_type_t : public LineInfo { public: + inline explicit data_type_t() : cache_type_elaborate_(0) { } virtual ~data_type_t() = 0; // This method is used to figure out the base type of a packed // compound object. Return IVL_VT_NO_TYPE if the type is not packed. virtual ivl_variable_type_t figure_packed_base_type(void)const; // This method is used by the pform dumper to diagnostic dump. virtual void pform_dump(std::ostream&out, unsigned indent) const; + + ivl_type_s* elaborate_type(Design*des, NetScope*scope); + + private: // Elaborate the type to an ivl_type_s type. - virtual ivl_type_s* elaborate_type(Design*des, NetScope*scope) const; + virtual ivl_type_s* elaborate_type_raw(Design*des, NetScope*scope) const; + + ivl_type_s*cache_type_elaborate_; }; struct void_type_t : public data_type_t { @@ -111,7 +118,7 @@ struct void_type_t : public data_type_t { struct enum_type_t : public data_type_t { inline enum_type_t(void) : net_type(0) { } // Return the elaborated version of the type. - virtual ivl_type_s*elaborate_type(Design*des, NetScope*scope) const; + virtual ivl_type_s*elaborate_type_raw(Design*des, NetScope*scope) const; ivl_variable_type_t base_type; bool signed_flag; @@ -134,7 +141,7 @@ struct struct_member_t : public LineInfo { struct struct_type_t : public data_type_t { virtual ivl_variable_type_t figure_packed_base_type(void)const; virtual void pform_dump(std::ostream&out, unsigned indent) const; - virtual netstruct_t* elaborate_type(Design*des, NetScope*scope) const; + virtual netstruct_t* elaborate_type_raw(Design*des, NetScope*scope) const; bool packed_flag; bool union_flag; @@ -147,7 +154,7 @@ struct atom2_type_t : public data_type_t { int type_code; bool signed_flag; - ivl_type_s* elaborate_type(Design*des, NetScope*scope) const; + ivl_type_s* elaborate_type_raw(Design*des, NetScope*scope) const; }; /* @@ -174,7 +181,7 @@ struct vector_type_t : public data_type_t { std::list*pd) : base_type(bt), signed_flag(sf), reg_flag(false), integer_flag(false), implicit_flag(false), pdims(pd) { } virtual ivl_variable_type_t figure_packed_base_type(void)const; - ivl_type_s* elaborate_type(Design*des, NetScope*scope) const; + ivl_type_s* elaborate_type_raw(Design*des, NetScope*scope) const; ivl_variable_type_t base_type; bool signed_flag; @@ -216,7 +223,7 @@ struct uarray_type_t : public array_base_t { public: virtual void pform_dump(std::ostream&out, unsigned indent) const; - virtual ivl_type_s* elaborate_type(Design*des, NetScope*scope) const; + virtual ivl_type_s* elaborate_type_raw(Design*des, NetScope*scope) const; }; struct real_type_t : public data_type_t { @@ -224,14 +231,14 @@ struct real_type_t : public data_type_t { inline explicit real_type_t(type_t tc) : type_code(tc) { } type_t type_code; - ivl_type_s* elaborate_type(Design*des, NetScope*scope) const; + ivl_type_s* elaborate_type_raw(Design*des, NetScope*scope) const; }; struct string_type_t : public data_type_t { inline explicit string_type_t() { } ~string_type_t(); - ivl_type_s* elaborate_type(Design*des, NetScope*scope) const; + ivl_type_s* elaborate_type_raw(Design*des, NetScope*scope) const; }; struct class_type_t : public data_type_t { @@ -271,7 +278,7 @@ struct class_type_t : public data_type_t { // without waiting for any constructor. std::vector initialize_static; - ivl_type_s* elaborate_type(Design*, NetScope*) const; + ivl_type_s* elaborate_type_raw(Design*, NetScope*) const; }; /*