vhdlpp: Alternative way of accessing constant arrays of vectors.
This commit is contained in:
parent
1852c5ab9d
commit
a42b056b24
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue