diff --git a/vhdlpp/debug.cc b/vhdlpp/debug.cc index cb8e83442..31ec3330c 100644 --- a/vhdlpp/debug.cc +++ b/vhdlpp/debug.cc @@ -67,8 +67,12 @@ void Entity::dump(ostream&out) const InterfacePort*item = *cur; out << setw(6) << "" << item->name << " : " << item->mode - << ", type=" << (item->type? typeid(*item->type).name() : "NOTYPE") - << ", file=" << item->get_fileline() << endl; + << ", type="; + if (item->type) + item->type->show(out); + else + out << ""; + out << ", file=" << item->get_fileline() << endl; } } @@ -112,6 +116,11 @@ void Expression::dump(ostream&out, int indent) const << " at " << get_fileline()<< endl; } +void ExpInteger::dump(ostream&out, int indent) const +{ + out << setw(indent) << "" << "Integer" << endl; +} + void ExpLogical::dump(ostream&out, int indent) const { const char*fun_name = "?"; diff --git a/vhdlpp/entity_elaborate.cc b/vhdlpp/entity_elaborate.cc index ed7708942..b1858776b 100644 --- a/vhdlpp/entity_elaborate.cc +++ b/vhdlpp/entity_elaborate.cc @@ -26,6 +26,7 @@ # include # include # include +# include using namespace std; @@ -118,6 +119,27 @@ int Entity::elaborate_ports_(void) break; } + } else if (const VTypeArray*arr_type = dynamic_cast(type)) { + const VTypePrimitive*base = dynamic_cast(arr_type->element_type()); + assert(base != 0); + + switch (base->type()) { + case VTypePrimitive::BOOLEAN: + case VTypePrimitive::BIT: + cur_decl.type = VBOOL; + break; + case VTypePrimitive::STDLOGIC: + cur_decl.type = VLOGIC; + break; + case VTypePrimitive::INTEGER: + cur_decl.type = VLOGIC; + assert(0); + break; + } + + cur_decl.msb = arr_type->dimension(0).msb(); + cur_decl.lsb = arr_type->dimension(0).lsb(); + } else { cerr << get_fileline() << ": error: " << "I don't know how to map port " << cur_port->name diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index 3a08b33b9..563de85a6 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -27,6 +27,26 @@ Expression::~Expression() { } +bool Expression::evaluate(int64_t&) const +{ + return false; +} + +ExpInteger::ExpInteger(int64_t val) +: value_(val) +{ +} + +ExpInteger::~ExpInteger() +{ +} + +bool ExpInteger::evaluate(int64_t&val) const +{ + val = value_; + return true; +} + ExpLogical::ExpLogical(ExpLogical::fun_t ty, Expression*op1, Expression*op2) : fun_(ty), operand1_(op1), operand2_(op2) { diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index dae333c5c..2be9b628c 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -21,6 +21,7 @@ # include "StringHeap.h" # include "LineInfo.h" +# include class Entity; class Architecture; @@ -39,10 +40,16 @@ class Expression : public LineInfo { // The emit virtual method is called bu architecture emit to // output the generated code for the expression. The derived // class fills in the details of what exactly happend. - virtual int emit(ostream&out, Entity*ent, Architecture*arc); + virtual int emit(ostream&out, Entity*ent, Architecture*arc) =0; + + // The evaluate virtual method tries to evaluate expressions + // to constant literal values. Return true and set the val + // argument if the evaluation works, or return false if it + // cannot be done. + virtual bool evaluate(int64_t&val) const; // Debug dump of the expression. - virtual void dump(ostream&out, int indent) const; + virtual void dump(ostream&out, int indent) const =0; private: @@ -51,6 +58,20 @@ class Expression : public LineInfo { Expression& operator = (const Expression&); }; +class ExpInteger : public Expression { + + public: + ExpInteger(int64_t val); + ~ExpInteger(); + + int emit(ostream&out, Entity*ent, Architecture*arc); + bool evaluate(int64_t&val) const; + void dump(ostream&out, int indent) const; + + private: + int64_t value_; +}; + class ExpLogical : public Expression { public: @@ -86,4 +107,5 @@ class ExpName : public Expression { perm_string name_; }; + #endif diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index 97280ccf7..43cda40ad 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -31,6 +31,13 @@ int Expression::emit(ostream&out, Entity*, Architecture*) return 1; } +int ExpInteger::emit(ostream&out, Entity*, Architecture*) +{ + out << " /* " << get_fileline() << ": internal error: " + << "INTEGER LITERAL */ "; + return 1; +} + int ExpLogical::emit(ostream&out, Entity*ent, Architecture*arc) { int errors = 0; diff --git a/vhdlpp/lexor.lex b/vhdlpp/lexor.lex index 5a22fc8a8..18531b560 100644 --- a/vhdlpp/lexor.lex +++ b/vhdlpp/lexor.lex @@ -135,19 +135,26 @@ based_integer [0-9a-fA-F](_?[0-9a-fA-F])* return IDENTIFIER; } - {decimal_literal} { - if(!are_underscores_correct(yytext)) - std::cerr << "An invalid underscore in the decimal literal:" - << yytext << std::endl; - - if(strchr(yytext, '.')) { - yylval.real = new vhdlreal(yytext); - return REAL_LITERAL; - } else { - yylval.integer = new vhdlint(yytext); - return INT_LITERAL; - } + char*tmp = new char[strlen(yytext)+1]; + char*dst, *src; + int rc = INT_LITERAL; + for (dst = tmp, src = yytext ; *src ; ++src) { + if (*src == '_') + continue; + if (*src == '.') + rc = REAL_LITERAL; + *dst++ = *src; + } + *dst = 0; + + if (rc == REAL_LITERAL) { + yylval.uni_real = strtod(tmp, 0); + } else { + yylval.uni_integer = strtoimax(tmp, 0, 10); + } + delete[]tmp; + return rc; } {based_literal} { @@ -158,13 +165,13 @@ based_integer [0-9a-fA-F](_?[0-9a-fA-F])* if(strchr(yytext, '.')) { double val = make_double_from_based(yytext); - yylval.real = new vhdlreal(val); + yylval.uni_real = val; return REAL_LITERAL; } else { int64_t val = make_long_from_based(yytext); - yylval.integer = new vhdlint(val); + yylval.uni_integer = val; return INT_LITERAL; } } diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index b503b53be..8e2e67dbe 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -49,8 +49,9 @@ int parse_errors = 0; port_mode_t port_mode; char*text; - vhdlint* integer; - vhdlreal* real; + bool flag; + int64_t uni_integer; + double uni_real; Expression*expr; std::list* expr_list; @@ -91,14 +92,16 @@ int parse_errors = 0; %token K_xnor K_xor /* Identifiers that are not keywords are identifiers. */ %token IDENTIFIER -%token INT_LITERAL -%token REAL_LITERAL +%token INT_LITERAL +%token REAL_LITERAL %token STRING_LITERAL CHARACTER_LITERAL /* compound symbols */ %token LEQ GEQ VASSIGN NE BOX EXP ARROW DLT DGT /* The rules may have types. */ +%type direction + %type interface_element %type interface_list entity_header port_clause %type mode @@ -175,10 +178,6 @@ concurrent_statement : concurrent_signal_assignment_statement ; -constraint - : '(' simple_expression direction simple_expression ')' - ; - context_clause : context_items | ; context_item @@ -202,7 +201,8 @@ design_units | design_unit ; -direction : K_to | K_downto ; + /* Indicate the direction as a flag, with "downto" being TRUE. */ +direction : K_to { $$ = false; } | K_downto { $$ = true; } ; /* As an entity is declared, add it to the map of design entities. */ entity_declaration @@ -355,6 +355,11 @@ primary delete[]$1; $$ = tmp; } + | INT_LITERAL + { ExpInteger*tmp = new ExpInteger($1); + FILE_NAME(tmp, @1); + $$ = tmp; + } ; relation : shift_expression { $$ = $1; } ; @@ -379,8 +384,8 @@ subtype_indication delete[]$1; $$ = tmp; } - | IDENTIFIER constraint - { const VType*tmp = global_types[lex_strings.make($1)]; + | IDENTIFIER '(' simple_expression direction simple_expression ')' + { const VType*tmp = calculate_subtype($1, $3, $4, $5); delete[]$1; $$ = tmp; } diff --git a/vhdlpp/parse_misc.cc b/vhdlpp/parse_misc.cc index 10b159af7..ac3acb562 100644 --- a/vhdlpp/parse_misc.cc +++ b/vhdlpp/parse_misc.cc @@ -22,8 +22,11 @@ # include "parse_api.h" # include "entity.h" # include "architec.h" +# include "expression.h" +# include "vtype.h" # include "compiler.h" # include +# include using namespace std; @@ -49,3 +52,38 @@ void bind_architecture_to_entity(const char*ename, Architecture*arch) return; } } + +const VType* calculate_subtype(const char*base_name, + Expression*array_left, + bool downto, + Expression*array_right) +{ + const VType*base_type = global_types[lex_strings.make(base_name)]; + + assert(array_left==0 || array_right!=0); + + const VTypeArray*base_array = dynamic_cast (base_type); + if (base_array) { + assert(array_left && array_right); + + vector range (base_array->dimensions()); + + // For now, I only know how to handle 1 dimension + assert(base_array->dimensions() == 1); + + int64_t left_val; + int64_t right_val; + bool rc = array_left->evaluate(left_val); + assert(rc); + + rc = array_right->evaluate(right_val); + assert(rc); + + range[0] = VTypeArray::range_t(left_val, right_val); + + VTypeArray*subtype = new VTypeArray(base_array->element_type(), range); + return subtype; + } + + return base_type; +} diff --git a/vhdlpp/parse_misc.h b/vhdlpp/parse_misc.h index 9f2d0416d..794d6754d 100644 --- a/vhdlpp/parse_misc.h +++ b/vhdlpp/parse_misc.h @@ -20,7 +20,14 @@ */ class Architecture; +class Expression; +class VType; extern void bind_architecture_to_entity(const char*ename, Architecture*arch); +extern const VType* calculate_subtype(const char*base_name, + Expression*array_left, + bool downto, + Expression*array_right); + #endif diff --git a/vhdlpp/vtype.cc b/vhdlpp/vtype.cc index adec5a144..45ec781c3 100644 --- a/vhdlpp/vtype.cc +++ b/vhdlpp/vtype.cc @@ -18,6 +18,7 @@ */ # include "vtype.h" +# include using namespace std; @@ -45,6 +46,11 @@ VType::~VType() { } +void VType::show(ostream&out) const +{ + out << typeid(*this).name(); +} + VTypePrimitive::VTypePrimitive(VTypePrimitive::type_t tt) : type_(tt) { @@ -54,6 +60,24 @@ VTypePrimitive::~VTypePrimitive() { } +void VTypePrimitive::show(ostream&out) const +{ + switch (type_) { + case BOOLEAN: + out << "BOOLEAN"; + break; + case BIT: + out << "BIT"; + break; + case INTEGER: + out << "INTEGER"; + break; + case STDLOGIC: + out << "std_logic"; + break; + } +} + VTypeArray::VTypeArray(const VType*element, const vector&r) : etype_(element), ranges_(r) { @@ -62,3 +86,27 @@ VTypeArray::VTypeArray(const VType*element, const vector&r) VTypeArray::~VTypeArray() { } + +size_t VTypeArray::dimensions() const +{ + return ranges_.size(); +} + +const VType* VTypeArray::element_type() const +{ + return etype_; +} + +void VTypeArray::show(ostream&out) const +{ + out << "array "; + for (vector::const_iterator cur = ranges_.begin() + ; cur != ranges_.end() ; ++cur) { + out << "(" << cur->msb() << " downto " << cur->lsb() << ")"; + } + out << " of "; + if (etype_) + etype_->show(out); + else + out << ""; +} diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index a62ec50f0..23e382b55 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -19,6 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ +# include # include # include # include @@ -34,8 +35,16 @@ class VType { public: VType() { } virtual ~VType() =0; + + virtual void show(std::ostream&) const; }; +inline std::ostream&operator << (std::ostream&out, const VType&item) +{ + item.show(out); + return out; +} + /* * The global_types variable maps type names to a type * definition. This is after the "use" statements bring in the types @@ -58,6 +67,8 @@ class VTypePrimitive : public VType { VTypePrimitive(type_t); ~VTypePrimitive(); + void show(std::ostream&) const; + type_t type() const { return type_; } private: @@ -97,7 +108,12 @@ class VTypeArray : public VType { VTypeArray(const VType*etype, const std::vector&r); ~VTypeArray(); + void show(std::ostream&) const; + size_t dimensions() const; + const range_t&dimension(size_t idx) const + { return ranges_[idx]; } + const VType* element_type() const; private: