vhdlpp: Support for accessing words in constant arrays.
This commit is contained in:
parent
0f0bef32f2
commit
9ca754b6db
|
|
@ -922,13 +922,87 @@ const VType* ExpName::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*)co
|
|||
return probe_type(ent, scope);
|
||||
}
|
||||
|
||||
int ExpName::elaborate_expr(Entity*, ScopeBase*, const VType*ltype)
|
||||
int ExpName::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
|
||||
{
|
||||
const VType*type = NULL;
|
||||
Expression*exp = NULL;
|
||||
|
||||
if (ltype) {
|
||||
ivl_assert(*this, ltype != 0);
|
||||
set_type(ltype);
|
||||
}
|
||||
|
||||
// Currently constant arrays of vectors are flattened to single one-dimensional
|
||||
// localparams. If the user wants to access a particular word, then it is
|
||||
// necessary to extract the adequate part of the localparam.
|
||||
// e.g.
|
||||
// declarations:
|
||||
// == VHDL ==
|
||||
// type uns_array is array (natural range <>) of unsigned(7 downto 0);
|
||||
// constant const_array : uns_array(2 downto 0) :=
|
||||
// (0 => "00110011", 1 => "101010101", 2=> "00001111");
|
||||
// == SystemVerilog ==
|
||||
// localparam const_array = { 8'b00110011, 8'b10101010, 8'b00001111 };
|
||||
//
|
||||
// access:
|
||||
// == VHDL ==
|
||||
// target_var := const_array(1);
|
||||
// == SystemVerilog ==
|
||||
// target_var = const_array[15:8]; // <- indices adjusted to pick the word
|
||||
|
||||
if(index_ && scope) {
|
||||
if(!scope->find_constant(name_, type, exp))
|
||||
return 0;
|
||||
|
||||
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 0;
|
||||
}
|
||||
|
||||
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 1;
|
||||
}
|
||||
|
||||
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 1;
|
||||
}
|
||||
|
||||
int word_size = abs(start_val - finish_val) + 1;
|
||||
|
||||
ExpInteger*size = new ExpInteger(word_size);
|
||||
Expression*new_index, *new_lsb;
|
||||
|
||||
// new indices = [index_ * word_size + word_size : lsb_ * word_size]
|
||||
if(lsb_) {
|
||||
ExpArithmetic*tmp = new ExpArithmetic(ExpArithmetic::MULT, index_->clone(), size->clone());
|
||||
new_index = new ExpArithmetic(ExpArithmetic::PLUS, tmp, size->clone());
|
||||
new_lsb = new ExpArithmetic(ExpArithmetic::MULT, lsb_->clone(), size->clone());
|
||||
} else {
|
||||
new_lsb = new ExpArithmetic(ExpArithmetic::MULT, index_->clone(), size->clone());
|
||||
new_index = new ExpArithmetic(ExpArithmetic::PLUS, new_lsb->clone(), size->clone());
|
||||
}
|
||||
delete index_;
|
||||
delete lsb_;
|
||||
delete size;
|
||||
|
||||
index_ = new_index;
|
||||
lsb_ = new_lsb;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue