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:
Stephen Williams 2011-08-28 15:30:45 -07:00
parent 7556a37859
commit 4464c5849b
8 changed files with 130 additions and 91 deletions

View File

@ -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_

View File

@ -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)
{ {

View File

@ -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 {

View File

@ -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;

View File

@ -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_;

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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