vhdlpp: Alternative way of accessing constant arrays of vectors.

This commit is contained in:
Maciej Suminski 2015-02-20 18:37:22 +01:00
parent 1852c5ab9d
commit a42b056b24
2 changed files with 65 additions and 0 deletions

View File

@ -649,6 +649,12 @@ class ExpName : public Expression {
int emit_as_prefix_(ostream&out, Entity*ent, ScopeBase*scope);
// Constant arrays of vectors are flattened into a single localparam,
// therefore indices of such localparam point to a bit, not a word.
// The following workaround expands expressions to a concatenation of
// bits making the requested word.
bool emit_const_array_workaround_(ostream&out, Entity*ent, ScopeBase*scope) const;
private:
std::auto_ptr<ExpName> prefix_;
perm_string name_;

View File

@ -715,6 +715,9 @@ int ExpName::emit(ostream&out, Entity*ent, ScopeBase*scope)
errors += prefix_->emit_as_prefix_(out, ent, scope);
}
if(index_ && emit_const_array_workaround_(out, ent, scope))
return errors;
const GenerateStatement*gs = 0;
Architecture*arc = dynamic_cast<Architecture*>(scope);
if (arc && (gs = arc->probe_genvar_emit(name_)))
@ -736,6 +739,62 @@ int ExpName::emit(ostream&out, Entity*ent, ScopeBase*scope)
return errors;
}
bool ExpName::emit_const_array_workaround_(ostream&out, Entity*ent, ScopeBase*scope) const
{
const VType*type = NULL;
Expression*exp = NULL;
if(!scope)
return false;
if(!scope->find_constant(name_, type, exp))
return false;
const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type);
ivl_assert(*this, arr); // if there is an index, it should be an array, right?
const VType*element = arr->element_type();
const VTypeArray*arr_element = dynamic_cast<const VTypeArray*>(element);
if(!arr_element) {
// index adjustments are not necessary, it is not an array of vectors
return false;
}
ivl_assert(*this, arr_element->dimensions() == 1);
if(arr_element->dimensions() != 1) {
cerr << get_fileline() << ": Sorry, only one-dimensional constant arrays are handled." << endl;
return false;
}
int64_t start_val;
bool start_rc = arr_element->dimension(0).msb()->evaluate(ent, scope, start_val);
int64_t finish_val;
bool finish_rc = arr_element->dimension(0).lsb()->evaluate(ent, scope, finish_val);
if(!start_rc || !finish_rc) {
cerr << get_fileline() << ": Could not evaluate the word size." << endl;
return false;
}
int word_size = abs(start_val - finish_val) + 1;
if(start_val > finish_val)
swap(start_val, finish_val);
out << "{";
for(int i = finish_val; i >= start_val; --i) {
if(i != finish_val)
out << ",";
out << "\\" << name_ << " [" << word_size << "*";
index_->emit(out, ent, scope);
out << "+" << i << "]";
}
out << "}";
return true;
}
bool ExpName::is_primary(void) const
{
return true;