From 42239a84982ef4b55cdeb296e24c793beaf9f38f Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 2 Apr 2012 19:53:04 -0700 Subject: [PATCH] Add code to test the width of individual structure elements. This patch adds code to correctly set the type and width of individual structure elements. Note the sign information is not currently available. --- elab_expr.cc | 62 +++++++++++++++++++++++++++++++++++++++++++++------- netstruct.h | 5 ++++- 2 files changed, 58 insertions(+), 9 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index 980446132..992fc5d0e 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -1419,24 +1419,38 @@ static NetExpr* check_for_enum_methods(const LineInfo*li, return sys_expr; } -static NetExpr* check_for_struct_members(const LineInfo*li, - Design*des, NetScope*, - NetNet*net, perm_string method_name) +/* + * If the method matches a structure member then return the member otherwise + * return 0. Also return the offset of the member. + */ +static const netstruct_t::member_t*get_struct_member(const LineInfo*li, + Design*des, NetScope*, + NetNet*net, + perm_string method_name, + unsigned long&off) { netstruct_t*type = net->struct_type(); ivl_assert(*li, type); if (! type->packed()) { - cerr << li->get_fileline() << ": sorry: unpacked structures not supported here. " + cerr << li->get_fileline() + << ": sorry: unpacked structures not supported here. " << "Method=" << method_name << endl; des->errors += 1; return 0; } + return type->packed_member(method_name, off); +} + +static NetExpr* check_for_struct_members(const LineInfo*li, + Design*des, NetScope*, + NetNet*net, perm_string method_name) +{ unsigned long off; - const netstruct_t::member_t*mem = type->packed_member(method_name, off); - if (mem == 0) - return 0; + const netstruct_t::member_t*mem = get_struct_member(li, des, 0, net, + method_name, off); + if (mem == 0) return 0; if (debug_elaborate) { cerr << li->get_fileline() << ": debug: Found struct member " <name @@ -2010,7 +2024,8 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode) const NetExpr*ex1, *ex2; - symbol_search(0, des, scope, path_, net, par, eve, ex1, ex2); + NetScope*found_in = symbol_search(0, des, scope, path_, net, par, eve, + ex1, ex2); // If there is a part/bit select expression, then process it // here. This constrains the results no matter what kind the @@ -2146,6 +2161,37 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode) return expr_width_; } + // If this is SystemVerilog then maybe this is a structure element. + if (gn_system_verilog() && found_in==0 && path_.size() >= 2) { + pform_name_t use_path = path_; + perm_string method_name = peek_tail_name(use_path); + use_path.pop_back(); + + found_in = symbol_search(this, des, scope, use_path, + net, par, eve, ex1, ex2); + + // Check to see if we have a net and if so is it a structure? + if (net != 0) { + // If this net is a struct, the method name may be + // a struct member. + if (net->struct_type() != 0) { + ivl_assert(*this, use_path.back().index.empty()); + + const netstruct_t::member_t*mem; + unsigned long unused; + mem = get_struct_member(this, des, scope, net, + method_name, unused); + if (mem) { + expr_type_ = mem->data_type(); + expr_width_ = mem->width(); + min_width_ = expr_width_; + signed_flag_ = mem->get_signed(); + return expr_width_; + } + } + } + } + // Not a net, and not a parameter? Give up on the type, but // set the width to 0. expr_type_ = IVL_VT_NO_TYPE; diff --git a/netstruct.h b/netstruct.h index 6dc3a439f..b84df6a4a 100644 --- a/netstruct.h +++ b/netstruct.h @@ -1,7 +1,7 @@ #ifndef __netstruct_H #define __netstruct_H /* - * Copyright (c) 2011 Stephen Williams (steve@icarus.com) + * Copyright (c) 2011-2012 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -32,6 +32,9 @@ class netstruct_t : public LineInfo { long msb; long lsb; long width() const; + ivl_variable_type_t data_type() const { return type; }; + // We need to keep the individual element sign information. + bool get_signed() const { return false; }; }; public: