Handle a few built-in functions internally.
The "unsigned" and "std_logic_vector" functions are internal functions and VHDL and can be handled internally in the code generator.
This commit is contained in:
parent
7556a37859
commit
4464c5849b
|
|
@ -219,13 +219,6 @@ void ExpBitstring::dump(ostream&out, int indent) const
|
||||||
out << "\"" << endl;
|
out << "\"" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExpCast::dump(ostream&out, int indent) const
|
|
||||||
{
|
|
||||||
out << setw(indent) << "" << "Cast to " << *res_type_
|
|
||||||
<< " at " << get_fileline() << endl;
|
|
||||||
arg_->dump(out, indent+4);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ExpCharacter::dump(ostream&out, int indent) const
|
void ExpCharacter::dump(ostream&out, int indent) const
|
||||||
{
|
{
|
||||||
out << setw(indent) << "" << "Character '" << value_ << "'"
|
out << setw(indent) << "" << "Character '" << value_ << "'"
|
||||||
|
|
@ -268,6 +261,15 @@ void ExpEdge::dump(ostream&out, int indent) const
|
||||||
dump_operand1(out, indent+3);
|
dump_operand1(out, indent+3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ExpFunc::dump(ostream&out, int indent) const
|
||||||
|
{
|
||||||
|
out << setw(indent) << "" << "function " << name_
|
||||||
|
<< " has " << argv_.size() << " arguments:" << endl;
|
||||||
|
for (size_t idx = 0 ; idx < argv_.size() ; idx += 1) {
|
||||||
|
argv_[idx]->dump(out, indent+2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ExpInteger::dump(ostream&out, int indent) const
|
void ExpInteger::dump(ostream&out, int indent) const
|
||||||
{
|
{
|
||||||
out << setw(indent) << "" << "Integer " << value_
|
out << setw(indent) << "" << "Integer " << value_
|
||||||
|
|
|
||||||
|
|
@ -184,15 +184,6 @@ ExpBitstring::~ExpBitstring()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpCast::ExpCast(const VType*typ, Expression*arg)
|
|
||||||
: res_type_(typ), arg_(arg)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ExpCast::~ExpCast()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ExpCharacter::ExpCharacter(char val)
|
ExpCharacter::ExpCharacter(char val)
|
||||||
: value_(val)
|
: value_(val)
|
||||||
{
|
{
|
||||||
|
|
@ -233,6 +224,23 @@ ExpEdge::~ExpEdge()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExpFunc::ExpFunc(perm_string nn)
|
||||||
|
: name_(nn), argv_(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpFunc::ExpFunc(perm_string nn, Expression*arg)
|
||||||
|
: name_(nn), argv_(1)
|
||||||
|
{
|
||||||
|
argv_[0] = arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpFunc::~ExpFunc()
|
||||||
|
{
|
||||||
|
for (size_t idx = 0 ; idx < argv_.size() ; idx += 1)
|
||||||
|
delete argv_[idx];
|
||||||
|
}
|
||||||
|
|
||||||
ExpInteger::ExpInteger(int64_t val)
|
ExpInteger::ExpInteger(int64_t val)
|
||||||
: value_(val)
|
: value_(val)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -209,23 +209,6 @@ class ExpBitstring : public Expression {
|
||||||
std::vector<char>value_;
|
std::vector<char>value_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ExpCast : public Expression {
|
|
||||||
|
|
||||||
public:
|
|
||||||
ExpCast(const VType*typ, Expression*arg);
|
|
||||||
~ExpCast();
|
|
||||||
|
|
||||||
const VType*probe_type(Entity*ent, Architecture*arc) const;
|
|
||||||
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
|
|
||||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
|
||||||
void dump(ostream&out, int indent = 0) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// This is the target, result type to cast to.
|
|
||||||
const VType*res_type_;
|
|
||||||
// This is the expression being cast.
|
|
||||||
Expression*arg_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ExpCharacter : public Expression {
|
class ExpCharacter : public Expression {
|
||||||
|
|
||||||
|
|
@ -292,6 +275,22 @@ class ExpEdge : public ExpUnary {
|
||||||
private:
|
private:
|
||||||
fun_t fun_;
|
fun_t fun_;
|
||||||
};
|
};
|
||||||
|
class ExpFunc : public Expression {
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ExpFunc(perm_string nn);
|
||||||
|
ExpFunc(perm_string nn, Expression*arg);
|
||||||
|
~ExpFunc();
|
||||||
|
|
||||||
|
public: // Base methods
|
||||||
|
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
|
||||||
|
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||||
|
void dump(ostream&out, int indent = 0) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
perm_string name_;
|
||||||
|
std::vector<Expression*> argv_;
|
||||||
|
};
|
||||||
|
|
||||||
class ExpInteger : public Expression {
|
class ExpInteger : public Expression {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -180,19 +180,6 @@ int ExpBitstring::elaborate_expr(Entity*, Architecture*, const VType*)
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
const VType* ExpCast::probe_type(Entity*, Architecture*) const
|
|
||||||
{
|
|
||||||
return res_type_;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ExpCast::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
|
|
||||||
{
|
|
||||||
int errors = 0;
|
|
||||||
const VType*sub_type = arg_->probe_type(ent, arc);
|
|
||||||
errors += arg_->elaborate_expr(ent, arc, sub_type);
|
|
||||||
return errors;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ExpCharacter::elaborate_expr(Entity*, Architecture*, const VType*ltype)
|
int ExpCharacter::elaborate_expr(Entity*, Architecture*, const VType*ltype)
|
||||||
{
|
{
|
||||||
assert(ltype != 0);
|
assert(ltype != 0);
|
||||||
|
|
@ -233,6 +220,18 @@ int ExpConditional::elaborate_expr(Entity*ent, Architecture*arc, const VType*lty
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ExpFunc::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
|
||||||
|
{
|
||||||
|
int errors = 0;
|
||||||
|
|
||||||
|
for (size_t idx = 0 ; idx < argv_.size() ; idx += 1) {
|
||||||
|
const VType*tmp = argv_[idx]->probe_type(ent, arc);
|
||||||
|
errors += argv_[idx]->elaborate_expr(ent, arc, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
int ExpInteger::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
|
int ExpInteger::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
|
||||||
{
|
{
|
||||||
int errors = 0;
|
int errors = 0;
|
||||||
|
|
|
||||||
|
|
@ -145,17 +145,6 @@ int ExpBitstring::emit(ostream&out, Entity*, Architecture*)
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ExpCast::emit(ostream&out, Entity*ent, Architecture*arc)
|
|
||||||
{
|
|
||||||
int errors = 0;
|
|
||||||
cerr << get_fileline() << ": sorry: I do not know how to emit cast expressions yet." << endl;
|
|
||||||
errors += 1;
|
|
||||||
|
|
||||||
out << "/* Cast to type=" << *res_type_ << " */ ";
|
|
||||||
errors += arg_->emit(out, ent, arc);
|
|
||||||
return errors;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ExpCharacter::emit_primitive_bit_(ostream&out, Entity*, Architecture*,
|
int ExpCharacter::emit_primitive_bit_(ostream&out, Entity*, Architecture*,
|
||||||
const VTypePrimitive*etype)
|
const VTypePrimitive*etype)
|
||||||
{
|
{
|
||||||
|
|
@ -258,6 +247,34 @@ int ExpEdge::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ExpFunc::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||||
|
{
|
||||||
|
int errors = 0;
|
||||||
|
|
||||||
|
if (name_ == "unsigned" && argv_.size()==1) {
|
||||||
|
// Handle the special case that this is a cast to
|
||||||
|
// unsigned. This function is brought in as part of the
|
||||||
|
// std numeric library, but we interpret it as the same
|
||||||
|
// as the $unsigned function.
|
||||||
|
out << "$unsigned(";
|
||||||
|
errors += argv_[0]->emit(out, ent, arc);
|
||||||
|
out << ")";
|
||||||
|
|
||||||
|
} else if (name_ == "std_logic_vector" && argv_.size() == 1) {
|
||||||
|
// Special case: The std_logic_vector function casts its
|
||||||
|
// argument to std_logic_vector. Internally, we don't
|
||||||
|
// have to do anything for that to work.
|
||||||
|
out << "(";
|
||||||
|
errors += argv_[0]->emit(out, ent, arc);
|
||||||
|
out << ")";
|
||||||
|
} else {
|
||||||
|
cerr << get_fileline() << ": sorry: Don't know how to emit function '" << name_ << "'" << endl;
|
||||||
|
errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
int ExpInteger::emit(ostream&out, Entity*, Architecture*)
|
int ExpInteger::emit(ostream&out, Entity*, Architecture*)
|
||||||
{
|
{
|
||||||
out << value_;
|
out << value_;
|
||||||
|
|
|
||||||
|
|
@ -1131,11 +1131,11 @@ name
|
||||||
| IDENTIFIER '(' expression ')'
|
| IDENTIFIER '(' expression ')'
|
||||||
{ perm_string name = lex_strings.make($1);
|
{ perm_string name = lex_strings.make($1);
|
||||||
delete[]$1;
|
delete[]$1;
|
||||||
if (const VType*type = active_scope->find_type(name)) {
|
if (active_scope->is_vector_name(name)) {
|
||||||
ExpCast*tmp = new ExpCast(type, $3);
|
ExpName*tmp = new ExpName(name, $3);
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
} else {
|
} else {
|
||||||
ExpName*tmp = new ExpName(name, $3);
|
ExpFunc*tmp = new ExpFunc(name, $3);
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
FILE_NAME($$, @1);
|
FILE_NAME($$, @1);
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,34 @@ bool ScopeBase::find_constant(perm_string by_name, const VType*&typ, Expression*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Signal* ScopeBase::find_signal(perm_string by_name) const
|
||||||
|
{
|
||||||
|
map<perm_string,Signal*>::const_iterator cur = new_signals_.find(by_name);
|
||||||
|
if (cur == new_signals_.end()) {
|
||||||
|
cur = old_signals_.find(by_name);
|
||||||
|
if (cur == old_signals_.end())
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return cur->second;
|
||||||
|
} else {
|
||||||
|
return cur->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Variable* ScopeBase::find_variable(perm_string by_name) const
|
||||||
|
{
|
||||||
|
map<perm_string,Variable*>::const_iterator cur = new_variables_.find(by_name);
|
||||||
|
if (cur == new_variables_.end()) {
|
||||||
|
cur = old_variables_.find(by_name);
|
||||||
|
if (cur == old_variables_.end())
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return cur->second;
|
||||||
|
} else {
|
||||||
|
return cur->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ScopeBase::do_use_from(const ScopeBase*that)
|
void ScopeBase::do_use_from(const ScopeBase*that)
|
||||||
{
|
{
|
||||||
for (map<perm_string,ComponentBase*>::const_iterator cur = that->old_components_.begin()
|
for (map<perm_string,ComponentBase*>::const_iterator cur = that->old_components_.begin()
|
||||||
|
|
@ -142,6 +170,16 @@ void ScopeBase::do_use_from(const ScopeBase*that)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ActiveScope::is_vector_name(perm_string name) const
|
||||||
|
{
|
||||||
|
if (find_signal(name))
|
||||||
|
return true;
|
||||||
|
if (find_variable(name))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Scope::Scope(const ScopeBase&ref)
|
Scope::Scope(const ScopeBase&ref)
|
||||||
: ScopeBase(ref)
|
: ScopeBase(ref)
|
||||||
{
|
{
|
||||||
|
|
@ -163,31 +201,3 @@ ComponentBase* Scope::find_component(perm_string by_name)
|
||||||
} else
|
} else
|
||||||
return cur->second;
|
return cur->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
Signal* Scope::find_signal(perm_string by_name)
|
|
||||||
{
|
|
||||||
map<perm_string,Signal*>::const_iterator cur = new_signals_.find(by_name);
|
|
||||||
if (cur == new_signals_.end()) {
|
|
||||||
cur = old_signals_.find(by_name);
|
|
||||||
if (cur == old_signals_.end())
|
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
return cur->second;
|
|
||||||
} else {
|
|
||||||
return cur->second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Variable* Scope::find_variable(perm_string by_name)
|
|
||||||
{
|
|
||||||
map<perm_string,Variable*>::const_iterator cur = new_variables_.find(by_name);
|
|
||||||
if (cur == new_variables_.end()) {
|
|
||||||
cur = old_variables_.find(by_name);
|
|
||||||
if (cur == old_variables_.end())
|
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
return cur->second;
|
|
||||||
} else {
|
|
||||||
return cur->second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,9 @@ class ScopeBase {
|
||||||
|
|
||||||
const VType* find_type(perm_string by_name);
|
const VType* find_type(perm_string by_name);
|
||||||
bool find_constant(perm_string by_name, const VType*&typ, Expression*&exp);
|
bool find_constant(perm_string by_name, const VType*&typ, Expression*&exp);
|
||||||
|
Signal* find_signal(perm_string by_name) const;
|
||||||
|
Variable* find_variable(perm_string by_name) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void cleanup();
|
void cleanup();
|
||||||
|
|
||||||
|
|
@ -97,9 +100,6 @@ class Scope : public ScopeBase {
|
||||||
|
|
||||||
ComponentBase* find_component(perm_string by_name);
|
ComponentBase* find_component(perm_string by_name);
|
||||||
|
|
||||||
Signal* find_signal(perm_string by_name);
|
|
||||||
Variable* find_variable(perm_string by_name);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void dump_scope(ostream&out) const;
|
void dump_scope(ostream&out) const;
|
||||||
|
|
||||||
|
|
@ -125,6 +125,10 @@ class ActiveScope : public ScopeBase {
|
||||||
|
|
||||||
void use_from(const ScopeBase*that) { do_use_from(that); }
|
void use_from(const ScopeBase*that) { do_use_from(that); }
|
||||||
|
|
||||||
|
// This function returns true if the name is a vectorable
|
||||||
|
// name. The parser uses this to distinguish between function
|
||||||
|
// calls and array index operations.
|
||||||
|
bool is_vector_name(perm_string name) const;
|
||||||
|
|
||||||
/* All bind_name function check if the given name was present
|
/* All bind_name function check if the given name was present
|
||||||
* in previous scopes. If it is found, it is erased (but the pointer
|
* in previous scopes. If it is found, it is erased (but the pointer
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue