Parse name prefix syntax for record member reference.

When signals/variables are records, they are often referenced by
their members, using a prefix.name syntax. Parse that syntax and
generate "sorry" messages in elaboration.
This commit is contained in:
Stephen Williams 2012-03-31 16:29:40 -07:00
parent 5e7f61ea42
commit 7eb89c5548
8 changed files with 138 additions and 14 deletions

View File

@ -208,11 +208,16 @@ void ExpAggregate::choice_t::dump(ostream&out, int indent) const
return; return;
} }
if (expr_) { if (expr_.get()) {
expr_->dump(out, indent); expr_->dump(out, indent);
return; return;
} }
if (range_.get()) {
range_->dump(out, indent);
return;
}
out << setw(indent) << "" << "?choice_t?" << endl; out << setw(indent) << "" << "?choice_t?" << endl;
} }
@ -375,6 +380,8 @@ void ExpName::dump(ostream&out, int indent) const
{ {
out << setw(indent) << "" << "ExpName(\"" << name_ << "\")" out << setw(indent) << "" << "ExpName(\"" << name_ << "\")"
<< " at " << get_fileline() << endl; << " at " << get_fileline() << endl;
if (prefix_.get())
prefix_->dump(out, indent+8);
if (index_) if (index_)
index_->dump(out, indent+6); index_->dump(out, indent+6);
if (lsb_) if (lsb_)

View File

@ -137,25 +137,26 @@ ExpAggregate::choice_t::choice_t(Expression*exp)
} }
ExpAggregate::choice_t::choice_t() ExpAggregate::choice_t::choice_t()
: expr_(0) {
}
ExpAggregate::choice_t::choice_t(prange_t*rang)
: range_(rang)
{ {
} }
ExpAggregate::choice_t::~choice_t() ExpAggregate::choice_t::~choice_t()
{ {
if (expr_) delete expr_;
} }
bool ExpAggregate::choice_t::others() const bool ExpAggregate::choice_t::others() const
{ {
return expr_ == 0; return expr_.get() == 0 && range_.get() == 0;
} }
Expression*ExpAggregate::choice_t::simple_expression(bool detach_flag) Expression*ExpAggregate::choice_t::simple_expression(bool detach_flag)
{ {
Expression*res = expr_; Expression*res = detach_flag? expr_.release() : expr_.get();
if (detach_flag)
expr_ = 0;
return res; return res;
} }
@ -371,6 +372,16 @@ ExpName::ExpName(perm_string nn, Expression*msb, Expression*lsb)
{ {
} }
ExpName::ExpName(ExpName*prefix, perm_string nn)
: prefix_(prefix), name_(nn), index_(0), lsb_(0)
{
}
ExpName::ExpName(ExpName*prefix, perm_string nn, Expression*msb, Expression*lsb)
: prefix_(prefix), name_(nn), index_(msb), lsb_(lsb)
{
}
ExpName::~ExpName() ExpName::~ExpName()
{ {
delete index_; delete index_;

View File

@ -24,8 +24,10 @@
# include "entity.h" # include "entity.h"
# include <inttypes.h> # include <inttypes.h>
# include <list> # include <list>
# include <memory>
# include <vector> # include <vector>
class prange_t;
class Entity; class Entity;
class Architecture; class Architecture;
class ScopeBase; class ScopeBase;
@ -185,6 +187,8 @@ class ExpAggregate : public Expression {
explicit choice_t(Expression*exp); explicit choice_t(Expression*exp);
// Create a named choice // Create a named choice
explicit choice_t(perm_string name); explicit choice_t(perm_string name);
// discreate_range choice
explicit choice_t(prange_t*ran);
~choice_t(); ~choice_t();
// true if this represents an "others" choice // true if this represents an "others" choice
@ -195,7 +199,8 @@ class ExpAggregate : public Expression {
void dump(ostream&out, int indent) const; void dump(ostream&out, int indent) const;
private: private:
Expression*expr_; std::auto_ptr<Expression>expr_;
std::auto_ptr<prange_t> range_;
private: // not implemented private: // not implemented
choice_t(const choice_t&); choice_t(const choice_t&);
choice_t& operator= (const choice_t&); choice_t& operator= (const choice_t&);
@ -461,6 +466,8 @@ class ExpName : public Expression {
explicit ExpName(perm_string nn); explicit ExpName(perm_string nn);
ExpName(perm_string nn, std::list<Expression*>*indices); ExpName(perm_string nn, std::list<Expression*>*indices);
ExpName(perm_string nn, Expression*msb, Expression*lsb); ExpName(perm_string nn, Expression*msb, Expression*lsb);
ExpName(ExpName*prefix, perm_string nn);
ExpName(ExpName*prefix, perm_string nn, Expression*msb, Expression*lsb);
~ExpName(); ~ExpName();
public: // Base methods public: // Base methods
@ -478,6 +485,7 @@ class ExpName : public Expression {
const char* name() const; const char* name() const;
private: private:
std::auto_ptr<ExpName> prefix_;
perm_string name_; perm_string name_;
Expression*index_; Expression*index_;
Expression*lsb_; Expression*lsb_;

View File

@ -43,6 +43,13 @@ int ExpName::elaborate_lval(Entity*ent, Architecture*arc, bool is_sequ)
{ {
int errors = 0; int errors = 0;
if (prefix_.get()) {
cerr << get_fileline() << ": sorry: I don't know how to elaborate "
<< "ExpName prefix of " << name_
<< " in l-value expressions." << endl;
errors += 1;
}
const VType*found_type = 0; const VType*found_type = 0;
if (const InterfacePort*cur = ent->find_port(name_)) { if (const InterfacePort*cur = ent->find_port(name_)) {
@ -116,6 +123,12 @@ int ExpName::elaborate_rval(Entity*ent, Architecture*arc, const InterfacePort*lv
{ {
int errors = 0; int errors = 0;
if (prefix_.get()) {
cerr << get_fileline() << ": sorry: I don't know how to elaborate "
<< "ExpName prefix parts in r-value expressions." << endl;
errors += 1;
}
if (const InterfacePort*cur = ent->find_port(name_)) { if (const InterfacePort*cur = ent->find_port(name_)) {
/* IEEE 1076-2008, p.80: /* IEEE 1076-2008, p.80:
* For a formal port IN, associated port should be IN, OUT, INOUT or BUFFER * For a formal port IN, associated port should be IN, OUT, INOUT or BUFFER
@ -398,6 +411,12 @@ int ExpLogical::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
const VType* ExpName::probe_type(Entity*ent, Architecture*arc) const const VType* ExpName::probe_type(Entity*ent, Architecture*arc) const
{ {
if (prefix_.get()) {
cerr << get_fileline() << ": sorry: I don't know how to probe type "
<< "of " << name_ << " with prefix parts." << endl;
return 0;
}
if (const InterfacePort*cur = ent->find_port(name_)) { if (const InterfacePort*cur = ent->find_port(name_)) {
ivl_assert(*this, cur->type); ivl_assert(*this, cur->type);
return cur->type; return cur->type;

View File

@ -515,6 +515,11 @@ int ExpName::emit(ostream&out, Entity*ent, Architecture*arc)
{ {
int errors = 0; int errors = 0;
if (prefix_.get()) {
cerr << get_fileline() << ": sorry: I don't know how to emit ExpName prefix parts." << endl;
errors += 1;
}
out << "\\" << name_ << " "; out << "\\" << name_ << " ";
if (index_) { if (index_) {
out << "["; out << "[";

View File

@ -76,6 +76,11 @@ bool ExpName::evaluate(ScopeBase*scope, int64_t&val) const
const VType*type; const VType*type;
Expression*exp; Expression*exp;
if (prefix_.get()) {
cerr << get_fileline() << ": sorry: I don't know how to evaluate ExpName prefix parts." << endl;
return false;
}
bool rc = scope->find_constant(name_, type, exp); bool rc = scope->find_constant(name_, type, exp);
if (rc == false) if (rc == false)
return false; return false;
@ -85,6 +90,11 @@ bool ExpName::evaluate(ScopeBase*scope, int64_t&val) const
bool ExpName::evaluate(Entity*ent, Architecture*arc, int64_t&val) const bool ExpName::evaluate(Entity*ent, Architecture*arc, int64_t&val) const
{ {
if (prefix_.get()) {
cerr << get_fileline() << ": sorry: I don't know how to evaluate ExpName prefix parts." << endl;
return false;
}
const InterfacePort*gen = ent->find_generic(name_); const InterfacePort*gen = ent->find_generic(name_);
if (gen) { if (gen) {
cerr << get_fileline() << ": sorry: I don't necessarily handle generic overrides." << endl; cerr << get_fileline() << ": sorry: I don't necessarily handle generic overrides." << endl;

View File

@ -108,6 +108,11 @@ void ExpLogical::write_to_stream(ostream&)
void ExpName::write_to_stream(ostream&fd) void ExpName::write_to_stream(ostream&fd)
{ {
if (prefix_.get()) {
prefix_->write_to_stream(fd);
fd << ".";
}
fd << name_; fd << name_;
if (index_) { if (index_) {
fd << "("; fd << "(";

View File

@ -167,6 +167,37 @@ static Expression*aggregate_or_primary(const YYLTYPE&loc, std::list<ExpAggregate
return el1->extract_expression(); return el1->extract_expression();
} }
static ExpName*make_name_from_prefix(const YYLTYPE&loc, const vector<perm_string>*names)
{
ExpName*cur = new ExpName(names->at(0));
FILE_NAME(cur, loc);
for (size_t idx = 1 ; idx < names->size() ; idx += 1) {
ExpName*tmp = new ExpName(cur, names->at(idx));
FILE_NAME(tmp, loc);
cur = tmp;
}
return cur;
}
static ExpName*make_name_from_prefix(const YYLTYPE&loc, const vector<perm_string>*names, Expression*msb, Expression*lsb)
{
ExpName*cur = new ExpName(names->at(0));
FILE_NAME(cur, loc);
for (size_t idx = 1 ; idx < (names->size()-1) ; idx += 1) {
ExpName*tmp = new ExpName(cur, names->at(idx));
FILE_NAME(tmp, loc);
cur = tmp;
}
ExpName*result = new ExpName(cur, names->back(), msb, lsb);
FILE_NAME(result, loc);
return result;
}
static list<VTypeRecord::element_t*>* record_elements(list<perm_string>*names, static list<VTypeRecord::element_t*>* record_elements(list<perm_string>*names,
const VType*type) const VType*type)
{ {
@ -561,6 +592,8 @@ choice
{ $$ = new ExpAggregate::choice_t($1);} { $$ = new ExpAggregate::choice_t($1);}
| K_others | K_others
{ $$ = new ExpAggregate::choice_t; } { $$ = new ExpAggregate::choice_t; }
| range /* discrete_range: range */
{ $$ = new ExpAggregate::choice_t($1); }
; ;
choices choices
@ -678,6 +711,22 @@ concurrent_conditional_signal_assignment /* IEEE 1076-2008 P11.6 */
SignalAssignment*tmpa = new SignalAssignment(name, tmp); SignalAssignment*tmpa = new SignalAssignment(name, tmp);
FILE_NAME(tmpa, @1); FILE_NAME(tmpa, @1);
$$ = tmpa;
}
/* Error recovery rules. */
| name LEQ error K_when expression else_when_waveforms ';'
{ errormsg(@3, "Syntax error in waveform of conditional signal assignment.\n");
ExpConditional*tmp = new ExpConditional($5, 0, $6);
FILE_NAME(tmp, @3);
delete $6;
ExpName*name = dynamic_cast<ExpName*> ($1);
assert(name);
SignalAssignment*tmpa = new SignalAssignment(name, tmp);
FILE_NAME(tmpa, @1);
$$ = tmpa; $$ = tmpa;
} }
; ;
@ -1445,6 +1494,13 @@ name
delete[]$1; delete[]$1;
$$ = tmp; $$ = tmp;
} }
| selected_name
{ ExpName*tmp = make_name_from_prefix(@1, $1);
delete $1;
$$ = tmp;
}
/* Note that this rule can match array element selects and various /* Note that this rule can match array element selects and various
function calls. The only way we can tell the difference is from function calls. The only way we can tell the difference is from
left context, namely whether the name is a type name or function left context, namely whether the name is a type name or function
@ -1467,6 +1523,11 @@ name
delete[]$1; delete[]$1;
$$ = tmp; $$ = tmp;
} }
| selected_name '(' range ')'
{ ExpName*tmp = make_name_from_prefix(@1, $1, $3->msb(), $3->lsb());
delete $1;
$$ = tmp;
}
; ;
/* Handle name lists as lists of expressions. */ /* Handle name lists as lists of expressions. */
@ -1857,12 +1918,10 @@ secondary_unit
selected_name selected_name
: prefix '.' suffix : prefix '.' suffix
{ { std::vector<perm_string>* tmp = $1;
std::vector<perm_string>* tmp = $1; tmp->push_back(lex_strings.make($3));
tmp->push_back(lex_strings.make($3)); delete[] $3;
delete[] $3; $$ = tmp;
$$ = tmp;
} }
; ;