diff --git a/vhdlpp/debug.cc b/vhdlpp/debug.cc index 6dfe102a9..cb8e83442 100644 --- a/vhdlpp/debug.cc +++ b/vhdlpp/debug.cc @@ -21,6 +21,7 @@ # include "entity.h" # include "architec.h" # include "expression.h" +# include "vtype.h" # include # include # include @@ -66,7 +67,7 @@ void Entity::dump(ostream&out) const InterfacePort*item = *cur; out << setw(6) << "" << item->name << " : " << item->mode - << ", type=" << item->type_name + << ", type=" << (item->type? typeid(*item->type).name() : "NOTYPE") << ", file=" << item->get_fileline() << endl; } } diff --git a/vhdlpp/entity.h b/vhdlpp/entity.h index a6ec469c1..0c14fad76 100644 --- a/vhdlpp/entity.h +++ b/vhdlpp/entity.h @@ -28,6 +28,7 @@ typedef enum { PORT_NONE=0, PORT_IN, PORT_OUT } port_mode_t; class Architecture; +class VType; class InterfacePort : public LineInfo { public: @@ -36,7 +37,7 @@ class InterfacePort : public LineInfo { // Name of the port from the source code perm_string name; // Name of interface type as given in the source code. - perm_string type_name; + const VType*type; }; class Entity : public LineInfo { diff --git a/vhdlpp/entity_elaborate.cc b/vhdlpp/entity_elaborate.cc index e8edc2a81..ed7708942 100644 --- a/vhdlpp/entity_elaborate.cc +++ b/vhdlpp/entity_elaborate.cc @@ -22,6 +22,7 @@ # include "architec.h" # include "vtype.h" # include +# include # include # include # include @@ -92,11 +93,12 @@ int Entity::elaborate_ports_(void) cur_decl.msb = 0; cur_decl.lsb = 0; - const VType*type = global_types[cur_port->type_name]; + const VType*type = cur_port->type; if (type == 0) { cerr << get_fileline() << ": error: " - << "No such type mark " << cur_port->type_name + << "Giving up on unknown type for port " << cur_port->name << "." << endl; + errors += 1; continue; } @@ -119,7 +121,7 @@ int Entity::elaborate_ports_(void) } else { cerr << get_fileline() << ": error: " << "I don't know how to map port " << cur_port->name - << " type " << cur_port->type_name << "." << endl; + << " type " << typeid(*cur_port->type).name() << "." << endl; errors += 1; } diff --git a/vhdlpp/main.cc b/vhdlpp/main.cc index 7b3cad2e0..c230160fd 100644 --- a/vhdlpp/main.cc +++ b/vhdlpp/main.cc @@ -92,6 +92,8 @@ int main(int argc, char*argv[]) } + preload_global_types(); + for (int idx = optind ; idx < argc ; idx += 1) { parse_errors = 0; FILE*fd = fopen(argv[idx], "r"); @@ -116,8 +118,6 @@ int main(int argc, char*argv[]) if (dump_design_entities_path) dump_design_entities(dump_design_entities_path); - preload_global_types(); - int errors = 0; errors = elaborate_entities(); if (errors > 0) { diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index b9fac72d4..b503b53be 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -27,6 +27,7 @@ # include "parse_misc.h" # include "architec.h" # include "expression.h" +# include "vtype.h" # include # include @@ -54,6 +55,8 @@ int parse_errors = 0; Expression*expr; std::list* expr_list; + const VType* vtype; + InterfacePort*interface_element; std::list* interface_list; @@ -108,6 +111,8 @@ int parse_errors = 0; %type waveform waveform_elements +%type subtype_indication + %type identifier_opt %% @@ -170,6 +175,10 @@ concurrent_statement : concurrent_signal_assignment_statement ; +constraint + : '(' simple_expression direction simple_expression ')' + ; + context_clause : context_items | ; context_item @@ -193,6 +202,8 @@ design_units | design_unit ; +direction : K_to | K_downto ; + /* As an entity is declared, add it to the map of design entities. */ entity_declaration : K_entity IDENTIFIER K_is entity_header K_end K_entity_opt ';' @@ -222,6 +233,11 @@ entity_declaration // Save the entity in the entity map. design_entities[tmp->get_name()] = tmp; } + | K_entity error K_end K_entity_opt identifier_opt ';' + { errormsg(@1, "Too many errors, giving up on entity declaration.\n"); + yyerrok; + if ($5) delete[]$5; + } ; entity_header @@ -273,14 +289,13 @@ identifier_opt : IDENTIFIER { $$ = $1; } | { $$ = 0; } ; /* The interface_element is also an interface_declaration */ interface_element - : IDENTIFIER ':' mode IDENTIFIER + : IDENTIFIER ':' mode subtype_indication { InterfacePort*tmp = new InterfacePort; FILE_NAME(tmp, @1); tmp->mode = $3; tmp->name = lex_strings.make($1); - tmp->type_name = lex_strings.make($4); + tmp->type = $4; delete[]$1; - delete[]$4; $$ = tmp; } ; @@ -326,6 +341,11 @@ mode port_clause : K_port '(' interface_list ')' ';' { $$ = $3; } + | K_port '(' error ')' ';' + { errormsg(@1, "Syntax error in port list\n"); + yyerrok; + $$ = 0; + } ; primary @@ -353,6 +373,19 @@ shift_expression : simple_expression { $$ = $1; } ; simple_expression : term { $$ = $1; } ; +subtype_indication + : IDENTIFIER + { const VType*tmp = global_types[lex_strings.make($1)]; + delete[]$1; + $$ = tmp; + } + | IDENTIFIER constraint + { const VType*tmp = global_types[lex_strings.make($1)]; + delete[]$1; + $$ = tmp; + } + ; + term : factor { $$ = $1; } ; use_clause diff --git a/vhdlpp/parse_wrap.h b/vhdlpp/parse_wrap.h index 08315d467..797441159 100644 --- a/vhdlpp/parse_wrap.h +++ b/vhdlpp/parse_wrap.h @@ -30,6 +30,9 @@ # include "vhdlreal.h" # include "architec.h" # include "expression.h" + +class VType; + # include "parse.h" #endif diff --git a/vhdlpp/vtype.cc b/vhdlpp/vtype.cc index 4b36a5fb6..adec5a144 100644 --- a/vhdlpp/vtype.cc +++ b/vhdlpp/vtype.cc @@ -34,6 +34,10 @@ void preload_global_types(void) global_types[perm_string::literal("bit")] = &primitive_BIT; global_types[perm_string::literal("integer")] = &primitive_INTEGER; global_types[perm_string::literal("std_logic")] = &primitive_STDLOGIC; + + { vector dims (1); + global_types[perm_string::literal("unsigned")] = new VTypeArray(&primitive_BIT, dims); + } } @@ -49,3 +53,12 @@ VTypePrimitive::VTypePrimitive(VTypePrimitive::type_t tt) VTypePrimitive::~VTypePrimitive() { } + +VTypeArray::VTypeArray(const VType*element, const vector&r) +: etype_(element), ranges_(r) +{ +} + +VTypeArray::~VTypeArray() +{ +} diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index 8b3239999..a62ec50f0 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -20,8 +20,15 @@ */ # include +# include +# include # include "StringHeap.h" +/* + * A description of a VHDL type consists of a graph of VType + * objects. Derived types are specific kinds of types, and those that + * are compound may in turn reference other types. + */ class VType { public: @@ -62,18 +69,41 @@ extern const VTypePrimitive primitive_BIT; extern const VTypePrimitive primitive_INTEGER; extern const VTypePrimitive primitive_STDLOGIC; +/* + * An array is a compound N-dimensional array of element type. The + * construction of the array is from an element type and a vector of + * ranges. The array type can be left incomplete by leaving some + * ranges as "box" ranges, meaning present but not defined. + */ class VTypeArray : public VType { public: - VTypeArray(size_t dimensions, VType*etype); + class range_t { + public: + range_t() : msb_(INT_MAX), lsb_(INT_MIN) { } + range_t(int m, int l) : msb_(m), lsb_(l) { } + + bool is_box() const { return msb_==INT_MAX && lsb_==INT_MIN; } + + int msb() const { return msb_; } + int lsb() const { return lsb_; } + + private: + int msb_; + int lsb_; + }; + + public: + VTypeArray(const VType*etype, const std::vector&r); ~VTypeArray(); size_t dimensions() const; - VType* element_type() const; + const VType* element_type() const; private: - size_t dimensions_; - VType*etype_; + const VType*etype_; + + std::vector ranges_; }; #endif