From 13f861a963df3acec3768df72018db985008721d Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 31 Oct 2014 09:55:36 +0100 Subject: [PATCH] ivl: Added PECastType to handle type casting. --- PExpr.cc | 9 +++++++++ PExpr.h | 22 +++++++++++++++++++++ elab_expr.cc | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++ pform_dump.cc | 8 ++++++++ 4 files changed, 94 insertions(+) diff --git a/PExpr.cc b/PExpr.cc index 4c7f303f6..7e0e3693f 100644 --- a/PExpr.cc +++ b/PExpr.cc @@ -146,6 +146,15 @@ PECastSize::~PECastSize() { } +PECastType::PECastType(data_type_t*t, PExpr*b) +: target_(t), base_(b) +{ +} + +PECastType::~PECastType() +{ +} + PEBComp::PEBComp(char op, PExpr*l, PExpr*r) : PEBinary(op, l, r) { diff --git a/PExpr.h b/PExpr.h index 44c4008a5..004c619a7 100644 --- a/PExpr.h +++ b/PExpr.h @@ -986,6 +986,28 @@ class PECastSize : public PExpr { PExpr* base_; }; +/* + * Support the SystemVerilog cast to a different type. + */ +class PECastType : public PExpr { + + public: + explicit PECastType(data_type_t*target, PExpr*base); + ~PECastType(); + + void dump(ostream &out) const; + + virtual NetExpr*elaborate_expr(Design*des, NetScope*scope, + unsigned expr_wid, unsigned flags) const; + + virtual unsigned test_width(Design*des, NetScope*scope, + width_mode_t&mode); + + private: + data_type_t* target_; + PExpr* base_; +}; + /* * This class is used for error recovery. All methods do nothing and return * null or default values. diff --git a/elab_expr.cc b/elab_expr.cc index c64582df4..e8507e904 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -36,6 +36,7 @@ # include "netmisc.h" # include "netdarray.h" # include "netstruct.h" +# include "netscalar.h" # include "util.h" # include "ivl_assert.h" @@ -2431,6 +2432,60 @@ NetExpr* PECastSize::elaborate_expr(Design*des, NetScope*scope, return sel; } +unsigned PECastType::test_width(Design*des, NetScope*scope, width_mode_t&wid) +{ + ivl_type_t t = target_->elaborate_type(des, scope); + base_->test_width(des, scope, wid); + + if(const netdarray_t*use_darray = dynamic_cast (t)) { + expr_type_ = use_darray->element_base_type(); + expr_width_ = use_darray->element_width(); + signed_flag_= false; + } + + else if(const netstring_t*use_string = dynamic_cast (t)) { + expr_type_ = use_string->base_type(); + expr_width_ = 1; + signed_flag_= false; + } + + else if(const netstruct_t*use_struct = dynamic_cast (t)) { + ivl_assert(*this, use_struct->packed()); + expr_type_ = use_struct->base_type(); + expr_width_ = use_struct->packed_width(); + signed_flag_= false; + } + + else if(const netvector_t*use_vector = dynamic_cast (t)) { + ivl_assert(*this, use_vector->packed()); + expr_type_ = use_vector->base_type(); + expr_width_ = use_vector->packed_width(); + signed_flag_= false; + } + + else { + expr_width_ = t->packed_width(); + } + + min_width_ = expr_width_; + return expr_width_; +} + +NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope, + unsigned, unsigned) const +{ + if(dynamic_cast(target_)) + { + NetExpr*expr = base_->elaborate_expr(des, scope, base_->expr_width(), NO_FLAGS); + return cast_to_real(expr); + } + + cerr << get_fileline() << "sorry: I don't know how to cast expression." << endl; + ivl_assert(*this, false); + + return expr; +} + unsigned PEConcat::test_width(Design*des, NetScope*scope, width_mode_t&) { expr_width_ = 0; diff --git a/pform_dump.cc b/pform_dump.cc index 981fbecd2..4cbd994ec 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -323,6 +323,14 @@ void PECastSize::dump(ostream &out) const out << ")"; } +void PECastType::dump(ostream &out) const +{ + target_->pform_dump(out, 0); + out << "'("; + base_->dump(out); + out << ")"; +} + void PEEvent::dump(ostream&out) const { switch (type_) {