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;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
out << setw(indent) << "" << "Character '" << value_ << "'"
|
||||
|
|
@ -268,6 +261,15 @@ void ExpEdge::dump(ostream&out, int indent) const
|
|||
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
|
||||
{
|
||||
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)
|
||||
: 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)
|
||||
: value_(val)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -209,23 +209,6 @@ class ExpBitstring : public Expression {
|
|||
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 {
|
||||
|
||||
|
|
@ -292,6 +275,22 @@ class ExpEdge : public ExpUnary {
|
|||
private:
|
||||
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 {
|
||||
|
||||
|
|
|
|||
|
|
@ -180,19 +180,6 @@ int ExpBitstring::elaborate_expr(Entity*, Architecture*, const VType*)
|
|||
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)
|
||||
{
|
||||
assert(ltype != 0);
|
||||
|
|
@ -233,6 +220,18 @@ int ExpConditional::elaborate_expr(Entity*ent, Architecture*arc, const VType*lty
|
|||
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 errors = 0;
|
||||
|
|
|
|||
|
|
@ -145,17 +145,6 @@ int ExpBitstring::emit(ostream&out, Entity*, Architecture*)
|
|||
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*,
|
||||
const VTypePrimitive*etype)
|
||||
{
|
||||
|
|
@ -258,6 +247,34 @@ int ExpEdge::emit(ostream&out, Entity*ent, Architecture*arc)
|
|||
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*)
|
||||
{
|
||||
out << value_;
|
||||
|
|
|
|||
|
|
@ -1131,11 +1131,11 @@ name
|
|||
| IDENTIFIER '(' expression ')'
|
||||
{ perm_string name = lex_strings.make($1);
|
||||
delete[]$1;
|
||||
if (const VType*type = active_scope->find_type(name)) {
|
||||
ExpCast*tmp = new ExpCast(type, $3);
|
||||
if (active_scope->is_vector_name(name)) {
|
||||
ExpName*tmp = new ExpName(name, $3);
|
||||
$$ = tmp;
|
||||
} else {
|
||||
ExpName*tmp = new ExpName(name, $3);
|
||||
ExpFunc*tmp = new ExpFunc(name, $3);
|
||||
$$ = tmp;
|
||||
}
|
||||
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)
|
||||
{
|
||||
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)
|
||||
: ScopeBase(ref)
|
||||
{
|
||||
|
|
@ -163,31 +201,3 @@ ComponentBase* Scope::find_component(perm_string by_name)
|
|||
} else
|
||||
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);
|
||||
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:
|
||||
void cleanup();
|
||||
|
||||
|
|
@ -97,9 +100,6 @@ class Scope : public ScopeBase {
|
|||
|
||||
ComponentBase* find_component(perm_string by_name);
|
||||
|
||||
Signal* find_signal(perm_string by_name);
|
||||
Variable* find_variable(perm_string by_name);
|
||||
|
||||
public:
|
||||
void dump_scope(ostream&out) const;
|
||||
|
||||
|
|
@ -125,6 +125,10 @@ class ActiveScope : public ScopeBase {
|
|||
|
||||
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
|
||||
* in previous scopes. If it is found, it is erased (but the pointer
|
||||
|
|
|
|||
Loading…
Reference in New Issue