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;
|
||||
}
|
||||
|
||||
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_)
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 << "[";
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 << "(";
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue