Handle genvar variables in expressions.
In generate for blocks, there is a genvar that can be used in expressions within the generate block. Generate this genvar in the generated output, matched to the generate scope.
This commit is contained in:
parent
9cca1378bb
commit
c14134aa2e
|
|
@ -22,6 +22,7 @@
|
||||||
# include "parse_types.h"
|
# include "parse_types.h"
|
||||||
// Need this for parse_errors?
|
// Need this for parse_errors?
|
||||||
# include "parse_api.h"
|
# include "parse_api.h"
|
||||||
|
# include <cassert>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
@ -38,6 +39,54 @@ Architecture::~Architecture()
|
||||||
ScopeBase::cleanup();
|
ScopeBase::cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Architecture::push_genvar_type(perm_string gname, const VType*gtype)
|
||||||
|
{
|
||||||
|
genvar_type_t tmp;
|
||||||
|
tmp.name = gname;
|
||||||
|
tmp.vtype = gtype;
|
||||||
|
genvar_type_stack_.push_back(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Architecture::pop_genvar_type(void)
|
||||||
|
{
|
||||||
|
assert(! genvar_type_stack_.empty());
|
||||||
|
genvar_type_stack_.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
const VType* Architecture::probe_genvar_type(perm_string gname)
|
||||||
|
{
|
||||||
|
for (std::list<genvar_type_t>::reverse_iterator cur = genvar_type_stack_.rbegin()
|
||||||
|
; cur != genvar_type_stack_.rend() ; ++cur) {
|
||||||
|
if (cur->name == gname)
|
||||||
|
return cur->vtype;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Architecture::push_genvar_emit(perm_string gname, const GenerateStatement*gen)
|
||||||
|
{
|
||||||
|
genvar_emit_t tmp;
|
||||||
|
tmp.name = gname;
|
||||||
|
tmp.gen = gen;
|
||||||
|
genvar_emit_stack_.push_back(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Architecture::pop_genvar_emit(void)
|
||||||
|
{
|
||||||
|
assert(! genvar_emit_stack_.empty());
|
||||||
|
genvar_emit_stack_.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
const GenerateStatement* Architecture::probe_genvar_emit(perm_string gname)
|
||||||
|
{
|
||||||
|
for (std::list<genvar_emit_t>::reverse_iterator cur = genvar_emit_stack_.rbegin()
|
||||||
|
; cur != genvar_emit_stack_.rend() ; ++cur) {
|
||||||
|
if (cur->name == gname)
|
||||||
|
return cur->gen;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
Architecture::Statement::Statement()
|
Architecture::Statement::Statement()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ class ComponentBase;
|
||||||
class Entity;
|
class Entity;
|
||||||
class Expression;
|
class Expression;
|
||||||
class ExpName;
|
class ExpName;
|
||||||
|
class GenerateStatement;
|
||||||
class SequentialStmt;
|
class SequentialStmt;
|
||||||
class Signal;
|
class Signal;
|
||||||
class named_expr_t;
|
class named_expr_t;
|
||||||
|
|
@ -71,6 +72,18 @@ class Architecture : public Scope, public LineInfo {
|
||||||
// Elaborate this architecture in the context of the given entity.
|
// Elaborate this architecture in the context of the given entity.
|
||||||
int elaborate(Entity*entity);
|
int elaborate(Entity*entity);
|
||||||
|
|
||||||
|
// These methods are used while in the scope of a generate
|
||||||
|
// block to mark that a name is a genvar at this point.
|
||||||
|
const VType* probe_genvar_type(perm_string);
|
||||||
|
void push_genvar_type(perm_string gname, const VType*gtype);
|
||||||
|
void pop_genvar_type(void);
|
||||||
|
|
||||||
|
// These methods are used during EMIT to check for names that
|
||||||
|
// are genvar names.
|
||||||
|
const GenerateStatement* probe_genvar_emit(perm_string);
|
||||||
|
void push_genvar_emit(perm_string gname, const GenerateStatement*);
|
||||||
|
void pop_genvar_emit(void);
|
||||||
|
|
||||||
// Emit this architecture to the given out file in the context
|
// Emit this architecture to the given out file in the context
|
||||||
// of the specified entity. This method is used by the
|
// of the specified entity. This method is used by the
|
||||||
// elaborate code to display generated code to the specified
|
// elaborate code to display generated code to the specified
|
||||||
|
|
@ -85,6 +98,18 @@ class Architecture : public Scope, public LineInfo {
|
||||||
// Concurrent statements local to this architecture
|
// Concurrent statements local to this architecture
|
||||||
std::list<Architecture::Statement*> statements_;
|
std::list<Architecture::Statement*> statements_;
|
||||||
|
|
||||||
|
struct genvar_type_t {
|
||||||
|
perm_string name;
|
||||||
|
const VType*vtype;
|
||||||
|
};
|
||||||
|
std::list<genvar_type_t> genvar_type_stack_;
|
||||||
|
|
||||||
|
struct genvar_emit_t {
|
||||||
|
perm_string name;
|
||||||
|
const GenerateStatement*gen;
|
||||||
|
};
|
||||||
|
std::list<genvar_emit_t> genvar_emit_stack_;
|
||||||
|
|
||||||
private: // Not implemented
|
private: // Not implemented
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -98,9 +123,9 @@ class GenerateStatement : public Architecture::Statement {
|
||||||
GenerateStatement(perm_string gname, std::list<Architecture::Statement*>&s);
|
GenerateStatement(perm_string gname, std::list<Architecture::Statement*>&s);
|
||||||
~GenerateStatement();
|
~GenerateStatement();
|
||||||
|
|
||||||
protected:
|
inline perm_string get_name() const { return name_; }
|
||||||
inline perm_string get_name() { return name_; }
|
|
||||||
|
|
||||||
|
protected:
|
||||||
int elaborate_statements(Entity*ent, Architecture*arc);
|
int elaborate_statements(Entity*ent, Architecture*arc);
|
||||||
int emit_statements(ostream&out, Entity*ent, Architecture*arc);
|
int emit_statements(ostream&out, Entity*ent, Architecture*arc);
|
||||||
void dump_statements(ostream&out, int indent) const;
|
void dump_statements(ostream&out, int indent) const;
|
||||||
|
|
|
||||||
|
|
@ -133,7 +133,9 @@ int GenerateStatement::elaborate_statements(Entity*ent, Architecture*arc)
|
||||||
int ForGenerate::elaborate(Entity*ent, Architecture*arc)
|
int ForGenerate::elaborate(Entity*ent, Architecture*arc)
|
||||||
{
|
{
|
||||||
int errors = 0;
|
int errors = 0;
|
||||||
|
arc->push_genvar_type(genvar_, lsb_->probe_type(ent, arc));
|
||||||
errors += elaborate_statements(ent, arc);
|
errors += elaborate_statements(ent, arc);
|
||||||
|
arc->pop_genvar_type();
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -183,16 +183,19 @@ int GenerateStatement::emit_statements(ostream&out, Entity*ent, Architecture*arc
|
||||||
int ForGenerate::emit(ostream&out, Entity*ent, Architecture*arc)
|
int ForGenerate::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||||
{
|
{
|
||||||
int errors = 0;
|
int errors = 0;
|
||||||
out << "genvar \\" << genvar_ << " ;" << endl;
|
out << "genvar \\" << get_name() << ":" << genvar_ << " ;" << endl;
|
||||||
out << "for (\\" << genvar_ << " = ";
|
out << "for (\\" << get_name() << ":" << genvar_ << " = ";
|
||||||
errors += lsb_->emit(out, ent, arc);
|
errors += lsb_->emit(out, ent, arc);
|
||||||
out << "; \\" << genvar_ << " <= ";
|
out << "; \\" << get_name() << ":" << genvar_ << " <= ";
|
||||||
errors += msb_->emit(out, ent, arc);
|
errors += msb_->emit(out, ent, arc);
|
||||||
out << "; \\" << genvar_ << " = \\" << genvar_ << " + 1)"
|
out << "; \\" << get_name() << ":" << genvar_ << " = \\" << get_name() << ":" << genvar_ << " + 1)"
|
||||||
<< " begin : \\" << get_name() << endl;
|
<< " begin : \\" << get_name() << endl;
|
||||||
|
|
||||||
|
arc->push_genvar_emit(genvar_, this);
|
||||||
|
|
||||||
errors += emit_statements(out, ent, arc);
|
errors += emit_statements(out, ent, arc);
|
||||||
|
|
||||||
|
arc->pop_genvar_emit();
|
||||||
out << "end" << endl;
|
out << "end" << endl;
|
||||||
|
|
||||||
return errors;
|
return errors;
|
||||||
|
|
|
||||||
|
|
@ -700,6 +700,10 @@ const VType* ExpName::probe_prefixed_type_(Entity*ent, Architecture*arc) const
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (const VTypeDef*def = dynamic_cast<const VTypeDef*> (prefix_type)) {
|
||||||
|
prefix_type = def->peek_definition();
|
||||||
|
}
|
||||||
|
|
||||||
// If the prefix type is a record, then the current name is
|
// If the prefix type is a record, then the current name is
|
||||||
// the name of a member.
|
// the name of a member.
|
||||||
if (const VTypeRecord*pref_record = dynamic_cast<const VTypeRecord*> (prefix_type)) {
|
if (const VTypeRecord*pref_record = dynamic_cast<const VTypeRecord*> (prefix_type)) {
|
||||||
|
|
@ -745,6 +749,10 @@ const VType* ExpName::probe_type(Entity*ent, Architecture*arc) const
|
||||||
if (arc->find_constant(name_, ctype, cval))
|
if (arc->find_constant(name_, ctype, cval))
|
||||||
return ctype;
|
return ctype;
|
||||||
|
|
||||||
|
if (const VType*gtype = arc->probe_genvar_type(name_)) {
|
||||||
|
return gtype;
|
||||||
|
}
|
||||||
|
|
||||||
cerr << get_fileline() << ": error: Signal/variable " << name_
|
cerr << get_fileline() << ": error: Signal/variable " << name_
|
||||||
<< " not found in this context." << endl;
|
<< " not found in this context." << endl;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -628,7 +628,12 @@ int ExpName::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||||
errors += prefix_->emit_as_prefix_(out, ent, arc);
|
errors += prefix_->emit_as_prefix_(out, ent, arc);
|
||||||
}
|
}
|
||||||
|
|
||||||
out << "\\" << name_ << " ";
|
const GenerateStatement*gs = 0;
|
||||||
|
if (arc && (gs = arc->probe_genvar_emit(name_)))
|
||||||
|
out << "\\" << gs->get_name() << ":" << name_ << " ";
|
||||||
|
else
|
||||||
|
out << "\\" << name_ << " ";
|
||||||
|
|
||||||
if (index_) {
|
if (index_) {
|
||||||
out << "[";
|
out << "[";
|
||||||
errors += index_->emit(out, ent, arc);
|
errors += index_->emit(out, ent, arc);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue