commit
ced9759c65
|
|
@ -27,6 +27,11 @@ LineInfo::LineInfo()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LineInfo::LineInfo(const LineInfo&that) :
|
||||||
|
file_(that.file_), lineno_(that.lineno_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
LineInfo::~LineInfo()
|
LineInfo::~LineInfo()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ using namespace std;
|
||||||
class LineInfo {
|
class LineInfo {
|
||||||
public:
|
public:
|
||||||
LineInfo();
|
LineInfo();
|
||||||
|
LineInfo(const LineInfo&that);
|
||||||
virtual ~LineInfo();
|
virtual ~LineInfo();
|
||||||
|
|
||||||
// Get a fully formatted file/lineno
|
// Get a fully formatted file/lineno
|
||||||
|
|
|
||||||
|
|
@ -150,6 +150,22 @@ int ComponentInstantiation::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||||
|
|
||||||
arc->set_cur_component(this);
|
arc->set_cur_component(this);
|
||||||
|
|
||||||
|
if(ComponentBase*comp = arc->find_component(cname_)) {
|
||||||
|
const std::vector<InterfacePort*>& generics = comp->get_generics();
|
||||||
|
|
||||||
|
if(generics.size() != generic_map_.size())
|
||||||
|
// Display an error for generics that do not have neither
|
||||||
|
// default nor component specific value defined
|
||||||
|
for(vector<InterfacePort*>::const_iterator it = generics.begin();
|
||||||
|
it != generics.end(); ++it) {
|
||||||
|
if(!(*it)->expr && generic_map_.count((*it)->name) == 0) {
|
||||||
|
cerr << get_fileline() << ": generic " << (*it)->name <<
|
||||||
|
"value is not defined" << endl;
|
||||||
|
++errors;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
out << cname_;
|
out << cname_;
|
||||||
if (! generic_map_.empty()) {
|
if (! generic_map_.empty()) {
|
||||||
out << " #(";
|
out << " #(";
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@
|
||||||
# include "StringHeap.h"
|
# include "StringHeap.h"
|
||||||
# include "LineInfo.h"
|
# include "LineInfo.h"
|
||||||
|
|
||||||
typedef enum { PORT_NONE=0, PORT_IN, PORT_OUT } port_mode_t;
|
typedef enum { PORT_NONE=0, PORT_IN, PORT_OUT, PORT_INOUT } port_mode_t;
|
||||||
|
|
||||||
class Architecture;
|
class Architecture;
|
||||||
class Expression;
|
class Expression;
|
||||||
|
|
@ -63,6 +63,7 @@ class ComponentBase : public LineInfo {
|
||||||
|
|
||||||
const InterfacePort* find_port(perm_string by_name) const;
|
const InterfacePort* find_port(perm_string by_name) const;
|
||||||
const InterfacePort* find_generic(perm_string by_name) const;
|
const InterfacePort* find_generic(perm_string by_name) const;
|
||||||
|
const std::vector<InterfacePort*>& get_generics() const { return parms_; }
|
||||||
|
|
||||||
// Declare the ports for the entity. The parser calls this
|
// Declare the ports for the entity. The parser calls this
|
||||||
// method with a list of interface elements that were parsed
|
// method with a list of interface elements that were parsed
|
||||||
|
|
|
||||||
|
|
@ -50,10 +50,13 @@ int Entity::emit(ostream&out)
|
||||||
const InterfacePort*curp = *cur;
|
const InterfacePort*curp = *cur;
|
||||||
if (cur != parms_.begin())
|
if (cur != parms_.begin())
|
||||||
out << ", ";
|
out << ", ";
|
||||||
out << "parameter \\" << curp->name << " ";
|
out << "parameter \\" << curp->name << " = ";
|
||||||
if(curp->expr) {
|
if(curp->expr) {
|
||||||
out << "= ";
|
|
||||||
errors += curp->expr->emit(out, this, 0);
|
errors += curp->expr->emit(out, this, 0);
|
||||||
|
} else {
|
||||||
|
// Unlike VHDL, Verilog module parameter port list
|
||||||
|
// elements are always assignments. Fill in the blank.
|
||||||
|
out << "1'bx";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out << ") ";
|
out << ") ";
|
||||||
|
|
@ -74,17 +77,21 @@ int Entity::emit(ostream&out)
|
||||||
|
|
||||||
switch (port->mode) {
|
switch (port->mode) {
|
||||||
case PORT_NONE: // Should not happen
|
case PORT_NONE: // Should not happen
|
||||||
|
cerr << get_fileline() << ": error: Undefined port direction." << endl;
|
||||||
out << "NO_PORT " << port->name;
|
out << "NO_PORT " << port->name;
|
||||||
break;
|
break;
|
||||||
case PORT_IN:
|
case PORT_IN:
|
||||||
out << "input ";
|
out << "input ";
|
||||||
errors += decl.emit(out, port->name);
|
|
||||||
break;
|
break;
|
||||||
case PORT_OUT:
|
case PORT_OUT:
|
||||||
out << "output ";
|
out << "output ";
|
||||||
errors += decl.emit(out, port->name);
|
break;
|
||||||
|
case PORT_INOUT:
|
||||||
|
out << "inout ";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errors += decl.emit(out, port->name);
|
||||||
}
|
}
|
||||||
cout << ")";
|
cout << ")";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,9 @@ void ComponentBase::write_to_stream(ostream&fd) const
|
||||||
case PORT_OUT:
|
case PORT_OUT:
|
||||||
fd << "out ";
|
fd << "out ";
|
||||||
break;
|
break;
|
||||||
|
case PORT_INOUT:
|
||||||
|
fd << "inout ";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
item->type->write_to_stream(fd);
|
item->type->write_to_stream(fd);
|
||||||
|
|
|
||||||
|
|
@ -311,6 +311,7 @@ ExpConditional::else_t::else_t(Expression*cond, std::list<Expression*>*tru)
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpConditional::else_t::else_t(const else_t&other)
|
ExpConditional::else_t::else_t(const else_t&other)
|
||||||
|
: LineInfo(other)
|
||||||
{
|
{
|
||||||
cond_ = other.cond_->clone();
|
cond_ = other.cond_->clone();
|
||||||
for(std::list<Expression*>::const_iterator it = other.true_clause_.begin();
|
for(std::list<Expression*>::const_iterator it = other.true_clause_.begin();
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,7 @@ int ExpName::elaborate_lval_(Entity*ent, ScopeBase*scope, bool is_sequ, ExpName*
|
||||||
const VType*found_type = 0;
|
const VType*found_type = 0;
|
||||||
|
|
||||||
if (const InterfacePort*cur = ent->find_port(name_)) {
|
if (const InterfacePort*cur = ent->find_port(name_)) {
|
||||||
if (cur->mode != PORT_OUT) {
|
if (cur->mode != PORT_OUT && cur->mode != PORT_INOUT) {
|
||||||
cerr << get_fileline() << ": error: Assignment to "
|
cerr << get_fileline() << ": error: Assignment to "
|
||||||
"input port " << name_ << "." << endl;
|
"input port " << name_ << "." << endl;
|
||||||
return errors + 1;
|
return errors + 1;
|
||||||
|
|
@ -216,7 +216,7 @@ int ExpName::elaborate_lval(Entity*ent, ScopeBase*scope, bool is_sequ)
|
||||||
const VType*found_type = 0;
|
const VType*found_type = 0;
|
||||||
|
|
||||||
if (const InterfacePort*cur = ent->find_port(name_)) {
|
if (const InterfacePort*cur = ent->find_port(name_)) {
|
||||||
if (cur->mode != PORT_OUT) {
|
if (cur->mode != PORT_OUT && cur->mode != PORT_INOUT) {
|
||||||
cerr << get_fileline() << ": error: Assignment to "
|
cerr << get_fileline() << ": error: Assignment to "
|
||||||
"input port " << name_ << "." << endl;
|
"input port " << name_ << "." << endl;
|
||||||
return errors += 1;
|
return errors += 1;
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ bool ExpAttribute::evaluate(ScopeBase*scope, int64_t&val) const
|
||||||
const VTypeArray*arr = dynamic_cast<const VTypeArray*>(base_type);
|
const VTypeArray*arr = dynamic_cast<const VTypeArray*>(base_type);
|
||||||
if (arr == 0) {
|
if (arr == 0) {
|
||||||
cerr << endl << get_fileline() << ": error: "
|
cerr << endl << get_fileline() << ": error: "
|
||||||
<< "Cannot apply the 'length attribute to non-array objects"
|
<< "Cannot apply the '" << name_ << " attribute to non-array objects"
|
||||||
<< endl;
|
<< endl;
|
||||||
ivl_assert(*this, false);
|
ivl_assert(*this, false);
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,9 @@ void Package::write_to_stream(ostream&fd) const
|
||||||
if (is_global_type(cur->first))
|
if (is_global_type(cur->first))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if(!dynamic_cast<const VTypeDef*>(cur->second))
|
||||||
|
fd << "sub";
|
||||||
|
|
||||||
fd << "type " << cur->first << " is ";
|
fd << "type " << cur->first << " is ";
|
||||||
cur->second->write_type_to_stream(fd);
|
cur->second->write_type_to_stream(fd);
|
||||||
fd << "; -- imported" << endl;
|
fd << "; -- imported" << endl;
|
||||||
|
|
@ -85,6 +88,9 @@ void Package::write_to_stream(ostream&fd) const
|
||||||
if (is_global_type(cur->first))
|
if (is_global_type(cur->first))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if(!dynamic_cast<const VTypeDef*>(cur->second))
|
||||||
|
fd << "sub";
|
||||||
|
|
||||||
fd << "type " << cur->first << " is ";
|
fd << "type " << cur->first << " is ";
|
||||||
cur->second->write_type_to_stream(fd);
|
cur->second->write_type_to_stream(fd);
|
||||||
fd << ";" << endl;
|
fd << ";" << endl;
|
||||||
|
|
|
||||||
|
|
@ -1584,6 +1584,7 @@ loop_statement
|
||||||
mode
|
mode
|
||||||
: K_in { $$ = PORT_IN; }
|
: K_in { $$ = PORT_IN; }
|
||||||
| K_out { $$ = PORT_OUT; }
|
| K_out { $$ = PORT_OUT; }
|
||||||
|
| K_inout { $$ = PORT_INOUT; }
|
||||||
;
|
;
|
||||||
|
|
||||||
mode_opt : mode {$$ = $1;} | {$$ = PORT_NONE;} ;
|
mode_opt : mode {$$ = $1;} | {$$ = PORT_NONE;} ;
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,9 @@ int Subprogram::emit_package(ostream&fd) const
|
||||||
case PORT_OUT:
|
case PORT_OUT:
|
||||||
fd << "output ";
|
fd << "output ";
|
||||||
break;
|
break;
|
||||||
|
case PORT_INOUT:
|
||||||
|
fd << "inout ";
|
||||||
|
break;
|
||||||
case PORT_NONE:
|
case PORT_NONE:
|
||||||
fd << "inout /* PORT_NONE? */ ";
|
fd << "inout /* PORT_NONE? */ ";
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -273,11 +273,9 @@ void VTypeArray::evaluate_ranges(ScopeBase*scope) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VTypeRange::VTypeRange(const VType*base, int64_t max_val, int64_t min_val)
|
VTypeRange::VTypeRange(const VType*base, int64_t end_val, int64_t start_val)
|
||||||
: base_(base)
|
: base_(base), end_(end_val), start_(start_val)
|
||||||
{
|
{
|
||||||
max_ = max_val;
|
|
||||||
min_ = min_val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VTypeRange::~VTypeRange()
|
VTypeRange::~VTypeRange()
|
||||||
|
|
|
||||||
|
|
@ -275,10 +275,10 @@ class VTypeArray : public VType {
|
||||||
class VTypeRange : public VType {
|
class VTypeRange : public VType {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VTypeRange(const VType*base, int64_t max_val, int64_t min_val);
|
VTypeRange(const VType*base, int64_t end, int64_t start);
|
||||||
~VTypeRange();
|
~VTypeRange();
|
||||||
|
|
||||||
VType*clone() const { return new VTypeRange(base_->clone(), max_, min_); }
|
VType*clone() const { return new VTypeRange(base_->clone(), start_, end_); }
|
||||||
|
|
||||||
// Get the type that is limited by the range.
|
// Get the type that is limited by the range.
|
||||||
inline const VType* base_type() const { return base_; }
|
inline const VType* base_type() const { return base_; }
|
||||||
|
|
@ -289,7 +289,7 @@ class VTypeRange : public VType {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const VType*base_;
|
const VType*base_;
|
||||||
int64_t max_, min_;
|
int64_t end_, start_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class VTypeEnum : public VType {
|
class VTypeEnum : public VType {
|
||||||
|
|
|
||||||
|
|
@ -45,9 +45,11 @@ void VTypeArray::write_to_stream(ostream&fd) const
|
||||||
write_range_to_stream_(fd);
|
write_range_to_stream_(fd);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else if (etype_ == &primitive_CHARACTER &&
|
} else if (etype_ == &primitive_CHARACTER) {
|
||||||
ranges_.size() == 1 && ranges_[0].is_box()) {
|
|
||||||
fd << "string";
|
fd << "string";
|
||||||
|
if (!ranges_.empty() && !ranges_[0].is_box()) {
|
||||||
|
write_range_to_stream_(fd);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -104,6 +106,13 @@ void VTypeArray::write_type_to_stream(ostream&fd) const
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else if (etype_ == &primitive_CHARACTER) {
|
||||||
|
fd << "string";
|
||||||
|
if (! ranges_.empty() && ! ranges_[0].is_box()) {
|
||||||
|
write_range_to_stream_(fd);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
fd << "array ";
|
fd << "array ";
|
||||||
|
|
||||||
|
|
@ -171,14 +180,16 @@ void VTypeRange::write_to_stream(ostream&fd) const
|
||||||
// Detect some special cases that can be written as ieee or
|
// Detect some special cases that can be written as ieee or
|
||||||
// standard types.
|
// standard types.
|
||||||
if (const VTypePrimitive*tmp = dynamic_cast<const VTypePrimitive*> (base_)) {
|
if (const VTypePrimitive*tmp = dynamic_cast<const VTypePrimitive*> (base_)) {
|
||||||
if (min_==0 && max_==INT64_MAX && tmp->type()==VTypePrimitive::INTEGER) {
|
if (start_==0 && end_==INT64_MAX && tmp->type()==VTypePrimitive::INTEGER) {
|
||||||
fd << "natural";
|
fd << "natural";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
base_->write_to_stream(fd);
|
base_->write_to_stream(fd);
|
||||||
fd << " range " << min_ << " to " << max_;
|
fd << " range " << start_;
|
||||||
|
fd << (start_ < end_ ? " to " : " downto ");
|
||||||
|
fd << end_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VTypeRecord::write_to_stream(ostream&fd) const
|
void VTypeRecord::write_to_stream(ostream&fd) const
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue