vhdlpp: Array attributes can be evaluated in packages/functions.

This commit is contained in:
Maciej Suminski 2015-01-26 17:09:00 +01:00
parent 25c3798248
commit abbcea64d0
1 changed files with 42 additions and 13 deletions

View File

@ -1,5 +1,7 @@
/* /*
* Copyright (c) 2011-2013 Stephen Williams (steve@icarus.com) * Copyright (c) 2011-2013 Stephen Williams (steve@icarus.com)
* Copyright CERN 2015
* @author Maciej Suminski (maciej.suminski@cern.ch)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -76,18 +78,31 @@ bool ExpArithmetic::evaluate(ScopeBase*scope, int64_t&val) const
return true; return true;
} }
bool ExpAttribute::evaluate(ScopeBase*, int64_t&val) const bool ExpAttribute::evaluate(ScopeBase*scope, int64_t&val) const
{ {
/* Special Case: The length attribute can be calculated all /* Special Case: The array attributes can sometimes be calculated all
the down to a literal integer at compile time, and all it the down to a literal integer at compile time, and all it
needs is the type of the base expression. (The base needs is the type of the base expression. (The base
expression doesn't even need to be evaluated.) */ expression doesn't even need to be evaluated.) */
if (name_ == "length") { if (name_ == "length" || name_ == "right" || name_ == "left") {
const VType*base_type = base_->peek_type(); const VType*base_type = base_->peek_type();
//if (base_type == 0)
// base_type = base_->probe_type(ent,arc);
ivl_assert(*this, base_type); if(!base_type) {
const ExpName*name = NULL;
if(scope && (name = dynamic_cast<const ExpName*>(base_))) {
const perm_string& n = name->peek_name();
if(const Variable*var = scope->find_variable(n))
base_type = var->peek_type();
else if(const Signal*sig = scope->find_signal(n))
base_type = sig->peek_type();
else if(const InterfacePort*port = scope->find_param(n))
base_type = port->type;
}
}
if(!base_type)
return false; // I tried really hard, sorry
const VTypeArray*arr = dynamic_cast<const VTypeArray*>(base_type); const VTypeArray*arr = dynamic_cast<const VTypeArray*>(base_type);
if (arr == 0) { if (arr == 0) {
@ -97,13 +112,27 @@ bool ExpAttribute::evaluate(ScopeBase*, int64_t&val) const
return false; return false;
} }
int64_t size = 1; if(name_ == "length") {
for (size_t idx = 0 ; idx < arr->dimensions() ; idx += 1) { int64_t size = 1;
const VTypeArray::range_t&dim = arr->dimension(idx); for (size_t idx = 0 ; idx < arr->dimensions() ; idx += 1) {
ivl_assert(*this, ! dim.is_box()); const VTypeArray::range_t&dim = arr->dimension(idx);
size *= 1 + labs(dim.msb() - dim.lsb()); int64_t msb_val, lsb_val;
}
val = size; if(dim.is_box())
return false;
dim.msb()->evaluate(scope, msb_val);
dim.lsb()->evaluate(scope, lsb_val);
size *= 1 + labs(msb_val - lsb_val);
}
val = size;
} else if(name_ == "left") {
arr->dimension(0).msb()->evaluate(scope, val);
} else if(name_ == "right") {
arr->dimension(0).lsb()->evaluate(scope, val);
} else ivl_assert(*this, false);
return true; return true;
} }