Merge pull request #43 from orsonmmz/record_elab

Elaboration & emit functions for aggregate expressions used as record initializers.
This commit is contained in:
Stephen Williams 2014-09-18 12:59:28 -07:00
commit e1ec27e18c
6 changed files with 87 additions and 18 deletions

View File

@ -283,7 +283,9 @@ class ExpAggregate : public Expression {
private:
int elaborate_expr_array_(Entity*ent, Architecture*arc, const VTypeArray*ltype);
int elaborate_expr_record_(Entity*ent, Architecture*arc, const VTypeRecord*ltype);
int emit_array_(ostream&out, Entity*ent, Architecture*arc, const VTypeArray*ltype);
int emit_record_(ostream&out, Entity*ent, Architecture*arc, const VTypeRecord*ltype);
private:
// This is the elements as directly parsed.
@ -575,6 +577,7 @@ class ExpName : public Expression {
bool symbolic_compare(const Expression*that) const;
void dump(ostream&out, int indent = 0) const;
const char* name() const;
inline perm_string peek_name() const { return name_; }
void set_range(Expression*msb, Expression*lsb);

View File

@ -56,6 +56,10 @@ const VType* Expression::fit_type(Entity*ent, Architecture*arc, const VTypeArray
const VType*ExpName::elaborate_adjust_type_with_range_(Entity*, Architecture*arc, const VType*type)
{
// Unfold typedefs
while (const VTypeDef*tdef = dynamic_cast<const VTypeDef*>(type)) {
type = tdef->peek_definition();
}
if (const VTypeArray*array = dynamic_cast<const VTypeArray*>(type)) {
if (index_ && !lsb_) {
@ -411,6 +415,9 @@ int ExpAggregate::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype
if (const VTypeArray*larray = dynamic_cast<const VTypeArray*>(ltype)) {
return elaborate_expr_array_(ent, arc, larray);
}
else if(const VTypeRecord*lrecord = dynamic_cast<const VTypeRecord*>(ltype)) {
return elaborate_expr_record_(ent, arc, lrecord);
}
cerr << get_fileline() << ": internal error: I don't know how to elaborate aggregate expressions. type=" << typeid(*ltype).name() << endl;
return 1;
@ -476,6 +483,46 @@ int ExpAggregate::elaborate_expr_array_(Entity*ent, Architecture*arc, const VTyp
return errors;
}
int ExpAggregate::elaborate_expr_record_(Entity*ent, Architecture*arc, const VTypeRecord*ltype)
{
int errors = 0;
aggregate_.resize(elements_.size());
choice_element tmp;
int idx;
// Translate the elements_ array to the aggregate_ array. In
// the target array, each expression is attached to a single
// choice.
for (size_t edx = 0 ; edx < elements_.size() ; edx += 1) {
element_t*ecur = elements_[edx];
// it is invalid to have more than one choice in record assignment
ivl_assert(*this, ecur->count_choices() == 1);
ecur->map_choices(&tmp);
choice_t*ch = tmp.choice;
ivl_assert(*this, !ch->others());
ivl_assert(*this, !tmp.alias_flag);
// Get the appropriate type for a field
const ExpName*field = dynamic_cast<const ExpName*>(ch->simple_expression(false));
ivl_assert(*this, field);
perm_string field_name = field->peek_name();
const VTypeRecord::element_t*el = ltype->element_by_name(field_name, &idx);
aggregate_[idx] = tmp;
errors += aggregate_[idx].expr->elaborate_expr(ent, arc, el->peek_type());
}
// done with the obsolete elements_ vector.
elements_.clear();
return errors;
}
void ExpAggregate::element_t::map_choices(ExpAggregate::choice_element*dst)
{
for (size_t idx = 0 ; idx < fields_.size() ; idx += 1) {

View File

@ -95,6 +95,8 @@ int ExpAggregate::emit(ostream&out, Entity*ent, Architecture*arc)
if (const VTypeArray*atype = dynamic_cast<const VTypeArray*> (use_type))
return emit_array_(out, ent, arc, atype);
else if (const VTypeRecord*arecord = dynamic_cast<const VTypeRecord*> (use_type))
return emit_record_(out, ent, arc, arecord);
out << "/* " << get_fileline() << ": internal error: "
<< "I don't know how to elab/emit aggregate in " << typeid(use_type).name()
@ -271,6 +273,34 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
return errors;
}
int ExpAggregate::emit_record_(ostream&out, Entity*ent, Architecture*arc, const VTypeRecord*)
{
int errors = 0;
out << "{";
for (size_t idx = 0 ; idx < aggregate_.size() ; idx += 1) {
ivl_assert(*this, !aggregate_[idx].choice->others());
ivl_assert(*this, !aggregate_[idx].choice->range_expressions());
//Expression*name = aggregate_[idx].choice->simple_expression(false);
//ivl_assert(*this, name);
Expression*val = aggregate_[idx].expr;
ivl_assert(*this, val);
if(idx != 0)
out << ",";
//errors += name->emit(out, ent, arc);
//out << ": ";
errors += val->emit(out, ent, arc);
}
out << "}";
return errors;
}
int ExpAttribute::emit(ostream&out, Entity*ent, Architecture*arc)
{
int errors = 0;

View File

@ -37,21 +37,7 @@ SigVarBase::~SigVarBase()
void SigVarBase::elaborate_init_expr(Entity*ent, Architecture*arc)
{
if(init_expr_) {
// convert the initializing string to bitstring if applicable
const ExpString*string = dynamic_cast<const ExpString*>(init_expr_);
if(string) {
const std::vector<char>& val = string->get_value();
char buf[val.size() + 1];
std::copy(val.begin(), val.end(), buf);
buf[val.size()] = 0;
ExpBitstring*bitstring = new ExpBitstring(buf);
delete init_expr_;
init_expr_ = bitstring;
}
else {
init_expr_->elaborate_expr(ent, arc, peek_type());
}
}
}

View File

@ -205,13 +205,17 @@ void VTypeRecord::show(ostream&out) const
write_to_stream(out);
}
const VTypeRecord::element_t* VTypeRecord::element_by_name(perm_string name) const
const VTypeRecord::element_t* VTypeRecord::element_by_name(perm_string name, int*index) const
{
for (vector<element_t*>::const_iterator cur = elements_.begin()
; cur != elements_.end() ; ++cur) {
element_t*curp = *cur;
if (curp->peek_name() == name)
if (curp->peek_name() == name) {
if (index)
*index = std::distance(elements_.begin(), cur);
return curp;
}
}
return 0;

View File

@ -288,8 +288,7 @@ class VTypeRecord : public VType {
int emit_def(std::ostream&out, perm_string name) const;
bool can_be_packed() const { return true; }
const element_t* element_by_name(perm_string name) const;
const element_t* element_by_name(perm_string name, int*index = NULL) const;
private:
std::vector<element_t*> elements_;