Handle VHDL records.
Elaborate records and emit them as packed SV records. Also handle record members so handle name prefixes. While we are at it, handle some cases of array aggregate expressions.
This commit is contained in:
parent
ae06863db1
commit
71d2401221
|
|
@ -28,6 +28,19 @@ int Architecture::elaborate(Entity*entity)
|
|||
{
|
||||
int errors = 0;
|
||||
|
||||
// Constant assignments in the architecture get their types
|
||||
// from the constant declaration itself. Elaborate the value
|
||||
// expression with the declared type.
|
||||
|
||||
for (map<perm_string,struct const_t*>::iterator cur = old_constants_.begin()
|
||||
; cur != old_constants_.end() ; ++cur) {
|
||||
cur->second->val->elaborate_expr(entity, this, cur->second->typ);
|
||||
}
|
||||
for (map<perm_string,struct const_t*>::iterator cur = new_constants_.begin()
|
||||
; cur != new_constants_.end() ; ++cur) {
|
||||
cur->second->val->elaborate_expr(entity, this, cur->second->typ);
|
||||
}
|
||||
|
||||
for (list<Architecture::Statement*>::iterator cur = statements_.begin()
|
||||
; cur != statements_.end() ; ++cur) {
|
||||
|
||||
|
|
@ -35,7 +48,12 @@ int Architecture::elaborate(Entity*entity)
|
|||
errors += cur_errors;
|
||||
}
|
||||
|
||||
cerr << errors << " errors in " << name_ << " architecture of " << entity->get_name() << "." << endl;
|
||||
if (errors > 0) {
|
||||
cerr << errors << " errors in "
|
||||
<< name_ << " architecture of "
|
||||
<< entity->get_name() << "." << endl;
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -491,6 +491,8 @@ class ExpName : public Expression {
|
|||
const VType* probe_prefix_type_(Entity*ent, Architecture*arc) const;
|
||||
const VType* probe_prefixed_type_(Entity*ent, Architecture*arc) const;
|
||||
|
||||
int emit_as_prefix_(ostream&out, Entity*ent, Architecture*arc);
|
||||
|
||||
private:
|
||||
std::auto_ptr<ExpName> prefix_;
|
||||
perm_string name_;
|
||||
|
|
|
|||
|
|
@ -306,8 +306,8 @@ int ExpAggregate::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype
|
|||
|
||||
/*
|
||||
* Elaboration of array aggregates is elaboration of the element
|
||||
* expressions using the element type as the ltype for the
|
||||
* subexpression.
|
||||
* expressions (the elements_ member) using the element type as the
|
||||
* ltype for the subexpression.
|
||||
*/
|
||||
int ExpAggregate::elaborate_expr_array_(Entity*ent, Architecture*arc, const VTypeArray*ltype)
|
||||
{
|
||||
|
|
@ -315,22 +315,42 @@ int ExpAggregate::elaborate_expr_array_(Entity*ent, Architecture*arc, const VTyp
|
|||
int errors = 0;
|
||||
size_t choice_count = 0;
|
||||
|
||||
// Figure out how many total elements we have here. Note that
|
||||
// each parsed element may be bound to multiple choices, so
|
||||
// account for that.
|
||||
for (size_t edx = 0 ; edx < elements_.size() ; edx += 1) {
|
||||
element_t*ecur = elements_[edx];
|
||||
choice_count += ecur->count_choices();
|
||||
if (ecur->count_choices() == 0)
|
||||
choice_count += 1;
|
||||
else
|
||||
choice_count += ecur->count_choices();
|
||||
}
|
||||
|
||||
aggregate_.resize(choice_count);
|
||||
|
||||
// Translate the elements_ array to the aggregate_ array. In
|
||||
// the target array, each expression is attached to a single
|
||||
// choice.
|
||||
size_t cdx = 0;
|
||||
for (size_t edx = 0 ; edx < elements_.size() ; edx += 1) {
|
||||
element_t*ecur = elements_[edx];
|
||||
ecur->map_choices(&aggregate_[cdx]);
|
||||
cdx += ecur->count_choices();
|
||||
if (ecur->count_choices() == 0) {
|
||||
// positional associations have no "choice"
|
||||
// associated with them.
|
||||
aggregate_[cdx].choice = 0;
|
||||
aggregate_[cdx].expr = ecur->extract_expression();
|
||||
aggregate_[cdx].alias_flag;
|
||||
cdx += 1;
|
||||
} else {
|
||||
ecur->map_choices(&aggregate_[cdx]);
|
||||
cdx += ecur->count_choices();
|
||||
}
|
||||
}
|
||||
|
||||
ivl_assert(*this, cdx == choice_count);
|
||||
|
||||
// Now run through the more convenient mapping and elaborate
|
||||
// all the expressions that I find.
|
||||
for (size_t idx = 0 ; idx < aggregate_.size() ; idx += 1) {
|
||||
if (aggregate_[idx].alias_flag)
|
||||
continue;
|
||||
|
|
@ -338,7 +358,9 @@ int ExpAggregate::elaborate_expr_array_(Entity*ent, Architecture*arc, const VTyp
|
|||
errors += aggregate_[idx].expr->elaborate_expr(ent, arc, element_type);
|
||||
}
|
||||
|
||||
// done with the obsolete elements_ vector.
|
||||
elements_.clear();
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2011-2012 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -70,10 +70,19 @@ int ExpUnary::emit_operand1(ostream&out, Entity*ent, Architecture*arc)
|
|||
|
||||
int ExpAggregate::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
{
|
||||
if (peek_type() == 0) {
|
||||
out << "/* " << get_fileline() << ": internal error: "
|
||||
<< "Aggregate literal needs well defined type." << endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (const VTypeArray*atype = dynamic_cast<const VTypeArray*> (peek_type()))
|
||||
return emit_array_(out, ent, arc, atype);
|
||||
|
||||
return Expression::emit(out, ent, arc);
|
||||
out << "/* " << get_fileline() << ": internal error: "
|
||||
<< "I don't know how to elaborate aggregate in " << typeid(peek_type()).name()
|
||||
<< " type context. */";
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const VTypeArray*atype)
|
||||
|
|
@ -126,27 +135,7 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
|
|||
const VTypeArray::range_t&rang = atype->dimension(0);
|
||||
assert(! rang.is_box());
|
||||
|
||||
map<int64_t,choice_element*> element_map;
|
||||
choice_element*element_other = 0;
|
||||
|
||||
for (size_t idx = 0 ; idx < aggregate_.size() ; idx += 1) {
|
||||
if (aggregate_[idx].choice->others()) {
|
||||
ivl_assert(*this, element_other == 0);
|
||||
element_other = &aggregate_[idx];
|
||||
continue;
|
||||
}
|
||||
|
||||
Expression*tmp = aggregate_[idx].choice->simple_expression(false);
|
||||
int64_t tmp_val;
|
||||
if (! tmp->evaluate(ent, arc, tmp_val)) {
|
||||
cerr << tmp->get_fileline() << ": error: Unable to evaluate aggregate choice expression." << endl;
|
||||
errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
element_map[tmp_val] = &aggregate_[idx];
|
||||
}
|
||||
|
||||
// Fully calculate the range numbers.
|
||||
int64_t use_msb, use_lsb;
|
||||
bool rc;
|
||||
rc = rang.msb()->evaluate(ent, arc, use_msb);
|
||||
|
|
@ -155,16 +144,68 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
|
|||
ivl_assert(*this, rc);
|
||||
ivl_assert(*this, use_msb >= use_lsb);
|
||||
|
||||
map<int64_t,choice_element*> element_map;
|
||||
choice_element*element_other = 0;
|
||||
|
||||
bool positional_section = true;
|
||||
int64_t positional_idx = use_msb;
|
||||
|
||||
for (size_t idx = 0 ; idx < aggregate_.size() ; idx += 1) {
|
||||
|
||||
if (aggregate_[idx].choice == 0) {
|
||||
// positional association!
|
||||
if (!positional_section) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "All positional associations must be before"
|
||||
<< " any named associations." << endl;
|
||||
errors += 1;
|
||||
}
|
||||
element_map[positional_idx] = &aggregate_[idx];
|
||||
positional_idx -= 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (aggregate_[idx].choice->others()) {
|
||||
ivl_assert(*this, element_other == 0);
|
||||
element_other = &aggregate_[idx];
|
||||
continue;
|
||||
}
|
||||
|
||||
int64_t tmp_val;
|
||||
Expression*tmp = aggregate_[idx].choice->simple_expression(false);
|
||||
|
||||
// Named aggregate element. Once we see one of
|
||||
// these, we can no longer accept positional
|
||||
// elements so disable further positional
|
||||
// processing.
|
||||
positional_section = false;
|
||||
if (! tmp->evaluate(ent, arc, tmp_val)) {
|
||||
cerr << tmp->get_fileline() << ": error: "
|
||||
<< "Unable to evaluate aggregate choice expression." << endl;
|
||||
errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
element_map[tmp_val] = &aggregate_[idx];
|
||||
}
|
||||
|
||||
// Emit the elements as a concatenation. This works great for
|
||||
// vectors of bits. We implement VHDL arrays as packed arrays,
|
||||
// so this should be generally correct.
|
||||
out << "{";
|
||||
for (int64_t idx = use_msb ; idx >= use_lsb ; idx -= 1) {
|
||||
choice_element*cur = element_map[idx];
|
||||
if (cur == 0)
|
||||
cur = element_other;
|
||||
ivl_assert(*this, cur != 0);
|
||||
|
||||
if (idx < use_msb)
|
||||
out << ", ";
|
||||
errors += cur->expr->emit(out, ent, arc);
|
||||
if (cur == 0) {
|
||||
out << "/* Missing element " << idx << " */";
|
||||
errors += 1;
|
||||
} else {
|
||||
errors += cur->expr->emit(out, ent, arc);
|
||||
}
|
||||
}
|
||||
out << "}";
|
||||
|
||||
|
|
@ -511,13 +552,25 @@ int ExpLogical::emit(ostream&out, Entity*ent, Architecture*arc)
|
|||
return errors;
|
||||
}
|
||||
|
||||
int ExpName::emit_as_prefix_(ostream&out, Entity*ent, Architecture*arc)
|
||||
{
|
||||
int errors = 0;
|
||||
if (prefix_.get()) {
|
||||
errors += prefix_->emit_as_prefix_(out, ent, arc);
|
||||
}
|
||||
|
||||
out << "\\" << name_ << " ";
|
||||
ivl_assert(*this, index_ == 0);
|
||||
out << ".";
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpName::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
if (prefix_.get()) {
|
||||
cerr << get_fileline() << ": sorry: I don't know how to emit ExpName prefix parts." << endl;
|
||||
errors += 1;
|
||||
errors += prefix_->emit_as_prefix_(out, ent, arc);
|
||||
}
|
||||
|
||||
out << "\\" << name_ << " ";
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2011-2012 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -162,14 +162,24 @@ int VTypeRange::emit_decl(ostream&out, perm_string name, bool reg_flag) const
|
|||
int VTypeRecord::emit_def(ostream&out, perm_string name) const
|
||||
{
|
||||
int errors = 0;
|
||||
assert(0);
|
||||
out << "struct packed {";
|
||||
|
||||
for (vector<element_t*>::const_iterator cur = elements_.begin()
|
||||
; cur != elements_.end() ; ++cur) {
|
||||
perm_string element_name = (*cur)->peek_name();
|
||||
const VType*element_type = (*cur)->peek_type();
|
||||
element_type->emit_def(out, element_name);
|
||||
out << "; ";
|
||||
}
|
||||
|
||||
out << "} ";
|
||||
return errors;
|
||||
}
|
||||
|
||||
int VTypeRecord::emit_decl(ostream&out, perm_string name, bool reg_flag) const
|
||||
{
|
||||
int errors = 0;
|
||||
assert(0);
|
||||
errors += emit_def(out, name);
|
||||
return errors;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue