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:
parent
5e7f61ea42
commit
7eb89c5548
|
|
@ -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_)
|
||||||
|
|
|
||||||
|
|
@ -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_;
|
||||||
|
|
|
||||||
|
|
@ -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_;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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 << "[";
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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 << "(";
|
||||||
|
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue