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"
|
||||
// Need this for parse_errors?
|
||||
# include "parse_api.h"
|
||||
# include <cassert>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
|
@ -38,6 +39,54 @@ Architecture::~Architecture()
|
|||
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()
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ class ComponentBase;
|
|||
class Entity;
|
||||
class Expression;
|
||||
class ExpName;
|
||||
class GenerateStatement;
|
||||
class SequentialStmt;
|
||||
class Signal;
|
||||
class named_expr_t;
|
||||
|
|
@ -71,6 +72,18 @@ class Architecture : public Scope, public LineInfo {
|
|||
// Elaborate this architecture in the context of the given 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
|
||||
// of the specified entity. This method is used by the
|
||||
// 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
|
||||
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
|
||||
};
|
||||
|
||||
|
|
@ -98,9 +123,9 @@ class GenerateStatement : public Architecture::Statement {
|
|||
GenerateStatement(perm_string gname, std::list<Architecture::Statement*>&s);
|
||||
~GenerateStatement();
|
||||
|
||||
protected:
|
||||
inline perm_string get_name() { return name_; }
|
||||
inline perm_string get_name() const { return name_; }
|
||||
|
||||
protected:
|
||||
int elaborate_statements(Entity*ent, Architecture*arc);
|
||||
int emit_statements(ostream&out, Entity*ent, Architecture*arc);
|
||||
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 errors = 0;
|
||||
arc->push_genvar_type(genvar_, lsb_->probe_type(ent, arc));
|
||||
errors += elaborate_statements(ent, arc);
|
||||
arc->pop_genvar_type();
|
||||
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 errors = 0;
|
||||
out << "genvar \\" << genvar_ << " ;" << endl;
|
||||
out << "for (\\" << genvar_ << " = ";
|
||||
out << "genvar \\" << get_name() << ":" << genvar_ << " ;" << endl;
|
||||
out << "for (\\" << get_name() << ":" << genvar_ << " = ";
|
||||
errors += lsb_->emit(out, ent, arc);
|
||||
out << "; \\" << genvar_ << " <= ";
|
||||
out << "; \\" << get_name() << ":" << genvar_ << " <= ";
|
||||
errors += msb_->emit(out, ent, arc);
|
||||
out << "; \\" << genvar_ << " = \\" << genvar_ << " + 1)"
|
||||
out << "; \\" << get_name() << ":" << genvar_ << " = \\" << get_name() << ":" << genvar_ << " + 1)"
|
||||
<< " begin : \\" << get_name() << endl;
|
||||
|
||||
arc->push_genvar_emit(genvar_, this);
|
||||
|
||||
errors += emit_statements(out, ent, arc);
|
||||
|
||||
arc->pop_genvar_emit();
|
||||
out << "end" << endl;
|
||||
|
||||
return errors;
|
||||
|
|
|
|||
|
|
@ -700,6 +700,10 @@ const VType* ExpName::probe_prefixed_type_(Entity*ent, Architecture*arc) const
|
|||
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
|
||||
// the name of a member.
|
||||
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))
|
||||
return ctype;
|
||||
|
||||
if (const VType*gtype = arc->probe_genvar_type(name_)) {
|
||||
return gtype;
|
||||
}
|
||||
|
||||
cerr << get_fileline() << ": error: Signal/variable " << name_
|
||||
<< " not found in this context." << endl;
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -628,7 +628,12 @@ int ExpName::emit(ostream&out, Entity*ent, Architecture*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_) {
|
||||
out << "[";
|
||||
errors += index_->emit(out, ent, arc);
|
||||
|
|
|
|||
Loading…
Reference in New Issue