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

View File

@ -137,25 +137,26 @@ ExpAggregate::choice_t::choice_t(Expression*exp)
}
ExpAggregate::choice_t::choice_t()
: expr_(0)
{
}
ExpAggregate::choice_t::choice_t(prange_t*rang)
: range_(rang)
{
}
ExpAggregate::choice_t::~choice_t()
{
if (expr_) delete expr_;
}
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*res = expr_;
if (detach_flag)
expr_ = 0;
Expression*res = detach_flag? expr_.release() : expr_.get();
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()
{
delete index_;

View File

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

View File

@ -43,6 +43,13 @@ int ExpName::elaborate_lval(Entity*ent, Architecture*arc, bool is_sequ)
{
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;
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;
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_)) {
/* IEEE 1076-2008, p.80:
* 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
{
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_)) {
ivl_assert(*this, cur->type);
return cur->type;

View File

@ -515,6 +515,11 @@ 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;
}
out << "\\" << name_ << " ";
if (index_) {
out << "[";

View File

@ -76,6 +76,11 @@ bool ExpName::evaluate(ScopeBase*scope, int64_t&val) const
const VType*type;
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);
if (rc == 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
{
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_);
if (gen) {
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)
{
if (prefix_.get()) {
prefix_->write_to_stream(fd);
fd << ".";
}
fd << name_;
if (index_) {
fd << "(";

View File

@ -167,6 +167,37 @@ static Expression*aggregate_or_primary(const YYLTYPE&loc, std::list<ExpAggregate
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,
const VType*type)
{
@ -561,6 +592,8 @@ choice
{ $$ = new ExpAggregate::choice_t($1);}
| K_others
{ $$ = new ExpAggregate::choice_t; }
| range /* discrete_range: range */
{ $$ = new ExpAggregate::choice_t($1); }
;
choices
@ -678,6 +711,22 @@ concurrent_conditional_signal_assignment /* IEEE 1076-2008 P11.6 */
SignalAssignment*tmpa = new SignalAssignment(name, tmp);
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;
}
;
@ -1445,6 +1494,13 @@ name
delete[]$1;
$$ = 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
function calls. The only way we can tell the difference is from
left context, namely whether the name is a type name or function
@ -1467,6 +1523,11 @@ name
delete[]$1;
$$ = 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. */
@ -1857,12 +1918,10 @@ secondary_unit
selected_name
: prefix '.' suffix
{
std::vector<perm_string>* tmp = $1;
tmp->push_back(lex_strings.make($3));
delete[] $3;
$$ = tmp;
{ std::vector<perm_string>* tmp = $1;
tmp->push_back(lex_strings.make($3));
delete[] $3;
$$ = tmp;
}
;