From 15ccd8f4c9b589c4049b9cf4be50cc91f27497b6 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Thu, 4 Sep 2014 20:52:51 -0700 Subject: [PATCH] Handle foreach array name as class property. --- Statement.h | 2 +- elaborate.cc | 84 +++++++++++++++++++++++++++++++++++++++++++++++----- netclass.h | 3 +- 3 files changed, 79 insertions(+), 10 deletions(-) diff --git a/Statement.h b/Statement.h index 1785d9b6f..a9dcf1297 100644 --- a/Statement.h +++ b/Statement.h @@ -455,7 +455,7 @@ class PForeach : public Statement { private: NetProc* elaborate_static_array_(Design*des, NetScope*scope, - NetNet*array_sig) const; + const std::vector&dims) const; private: perm_string array_var_; diff --git a/elaborate.cc b/elaborate.cc index 9050f7065..281b2ecb9 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -4605,6 +4605,27 @@ NetForce* PForce::elaborate(Design*des, NetScope*scope) const return dev; } +static void find_property_in_class(const LineInfo&loc, const NetScope*scope, perm_string name, const netclass_t*&found_in, int&property) +{ + // Search up for the containing class. + while (scope && scope->type() != NetScope::CLASS) + scope = scope->parent(); + + found_in = 0; + property = -1; + + if (scope==0) return; + + found_in = scope->class_def(); + ivl_assert(loc, found_in); + + property = found_in->property_idx_from_name(name); + if (property < 0) { + found_in = 0; + return; + } +} + /* * The foreach statement can be written as a for statement like so: * @@ -4616,14 +4637,57 @@ NetForce* PForce::elaborate(Design*des, NetScope*scope) const */ NetProc* PForeach::elaborate(Design*des, NetScope*scope) const { - // Get the signal for the array variable + // Locate the signal for the array variable pform_name_t array_name; array_name.push_back(name_component_t(array_var_)); NetNet*array_sig = des->find_signal(scope, array_name); + // And if necessary, look for the class property that is + // referenced. + const netclass_t*class_scope = 0; + int class_property = -1; + if (array_sig == 0) + find_property_in_class(*this, scope, array_var_, class_scope, class_property); + + if (debug_elaborate && array_sig) { + cerr << get_fileline() << ": PForeach::elaborate: " + << "Found array_sig in " << scope_path(array_sig->scope()) << "." << endl; + } + + if (debug_elaborate && class_scope) { + cerr << get_fileline() << ": PForeach::elaborate: " + << "Found array_sig property (" << class_property + << ") in class " << class_scope->get_name() + << " as " << *class_scope->get_prop_type(class_property) << "." << endl; + } + + if (class_scope!=0 && class_property >= 0) { + ivl_type_t ptype = class_scope->get_prop_type(class_property); + const netsarray_t*atype = dynamic_cast (ptype); + if (atype == 0) { + cerr << get_fileline() << ": error: " + << "I can't handle the type of " << array_var_ + << " as a foreach loop." << endl; + des->errors += 1; + return 0; + } + + const std::vector&dims = atype->static_dimensions(); + if (dims.size() < index_vars_.size()) { + cerr << get_fileline() << ": error: " + << "class " << class_scope->get_name() + << " property " << array_var_ + << " has too few dimensions for foreach dimension list." << endl; + des->errors += 1; + return 0; + } + + return elaborate_static_array_(des, scope, dims); + } + if (array_sig == 0) { cerr << get_fileline() << ": error:" - << " Unable to find " << array_name + << " Unable to find foreach array " << array_name << " in scope " << scope_path(scope) << "." << endl; des->errors += 1; @@ -4643,11 +4707,15 @@ NetProc* PForeach::elaborate(Design*des, NetScope*scope) const // Classic arrays are processed this way. if (array_sig->data_type()==IVL_VT_BOOL) - return elaborate_static_array_(des, scope, array_sig); + return elaborate_static_array_(des, scope, array_sig->unpacked_dims()); if (array_sig->data_type()==IVL_VT_LOGIC) - return elaborate_static_array_(des, scope, array_sig); + return elaborate_static_array_(des, scope, array_sig->unpacked_dims()); if (array_sig->unpacked_dimensions() >= index_vars_.size()) - return elaborate_static_array_(des, scope, array_sig); + return elaborate_static_array_(des, scope, array_sig->unpacked_dims()); + + + // At this point, we know that the array is dynamic so we + // handle that slightly differently, using run-time tests. if (index_vars_.size() != 1) { cerr << get_fileline() << ": sorry: " @@ -4703,7 +4771,7 @@ NetProc* PForeach::elaborate(Design*des, NetScope*scope) const * and possibly do some optimizations. */ NetProc* PForeach::elaborate_static_array_(Design*des, NetScope*scope, - NetNet*array_sig) const + const vector&dims) const { if (debug_elaborate) { cerr << get_fileline() << ": PForeach::elaborate_static_array_: " @@ -4711,13 +4779,13 @@ NetProc* PForeach::elaborate_static_array_(Design*des, NetScope*scope, } ivl_assert(*this, index_vars_.size() > 0); - ivl_assert(*this, array_sig->unpacked_dims().size() == index_vars_.size()); + ivl_assert(*this, dims.size() == index_vars_.size()); NetProc*sub = statement_->elaborate(des, scope); NetForLoop*stmt = 0; for (int idx_idx = index_vars_.size()-1 ; idx_idx >= 0 ; idx_idx -= 1) { - const netrange_t&idx_range = array_sig->unpacked_dims()[idx_idx]; + const netrange_t&idx_range = dims[idx_idx]; // Get the $high and $low constant values for this slice // of the array. diff --git a/netclass.h b/netclass.h index 8679fa4f9..8305da4ef 100644 --- a/netclass.h +++ b/netclass.h @@ -84,7 +84,8 @@ class netclass_t : public ivl_type_s { bool test_for_missing_initializers(void) const; - // Map the name of a property to its index. + // Map the name of a property to its index. Return <0 if the + // name is not a property in the class. int property_idx_from_name(perm_string pname) const; // The task method scopes from the method name.