Handle foreach array name as class property.
This commit is contained in:
parent
d1a35d5152
commit
15ccd8f4c9
|
|
@ -455,7 +455,7 @@ class PForeach : public Statement {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NetProc* elaborate_static_array_(Design*des, NetScope*scope,
|
NetProc* elaborate_static_array_(Design*des, NetScope*scope,
|
||||||
NetNet*array_sig) const;
|
const std::vector<netrange_t>&dims) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
perm_string array_var_;
|
perm_string array_var_;
|
||||||
|
|
|
||||||
84
elaborate.cc
84
elaborate.cc
|
|
@ -4605,6 +4605,27 @@ NetForce* PForce::elaborate(Design*des, NetScope*scope) const
|
||||||
return dev;
|
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:
|
* 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
|
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;
|
pform_name_t array_name;
|
||||||
array_name.push_back(name_component_t(array_var_));
|
array_name.push_back(name_component_t(array_var_));
|
||||||
NetNet*array_sig = des->find_signal(scope, array_name);
|
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<const netsarray_t*> (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<netrange_t>&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) {
|
if (array_sig == 0) {
|
||||||
cerr << get_fileline() << ": error:"
|
cerr << get_fileline() << ": error:"
|
||||||
<< " Unable to find " << array_name
|
<< " Unable to find foreach array " << array_name
|
||||||
<< " in scope " << scope_path(scope)
|
<< " in scope " << scope_path(scope)
|
||||||
<< "." << endl;
|
<< "." << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
|
|
@ -4643,11 +4707,15 @@ NetProc* PForeach::elaborate(Design*des, NetScope*scope) const
|
||||||
|
|
||||||
// Classic arrays are processed this way.
|
// Classic arrays are processed this way.
|
||||||
if (array_sig->data_type()==IVL_VT_BOOL)
|
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)
|
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())
|
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) {
|
if (index_vars_.size() != 1) {
|
||||||
cerr << get_fileline() << ": sorry: "
|
cerr << get_fileline() << ": sorry: "
|
||||||
|
|
@ -4703,7 +4771,7 @@ NetProc* PForeach::elaborate(Design*des, NetScope*scope) const
|
||||||
* and possibly do some optimizations.
|
* and possibly do some optimizations.
|
||||||
*/
|
*/
|
||||||
NetProc* PForeach::elaborate_static_array_(Design*des, NetScope*scope,
|
NetProc* PForeach::elaborate_static_array_(Design*des, NetScope*scope,
|
||||||
NetNet*array_sig) const
|
const vector<netrange_t>&dims) const
|
||||||
{
|
{
|
||||||
if (debug_elaborate) {
|
if (debug_elaborate) {
|
||||||
cerr << get_fileline() << ": PForeach::elaborate_static_array_: "
|
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, 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);
|
NetProc*sub = statement_->elaborate(des, scope);
|
||||||
NetForLoop*stmt = 0;
|
NetForLoop*stmt = 0;
|
||||||
|
|
||||||
for (int idx_idx = index_vars_.size()-1 ; idx_idx >= 0 ; idx_idx -= 1) {
|
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
|
// Get the $high and $low constant values for this slice
|
||||||
// of the array.
|
// of the array.
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,8 @@ class netclass_t : public ivl_type_s {
|
||||||
|
|
||||||
bool test_for_missing_initializers(void) const;
|
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;
|
int property_idx_from_name(perm_string pname) const;
|
||||||
|
|
||||||
// The task method scopes from the method name.
|
// The task method scopes from the method name.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue