Do type mapping in the parser.

In VHDL, types are declared before they are used, so it is possible
to do type binding during parse. This makes the parser a little bit
cleaner.
This commit is contained in:
Stephen Williams 2011-02-13 16:37:10 -08:00
parent bc5fe9676e
commit f32ede23b7
8 changed files with 97 additions and 14 deletions

View File

@ -21,6 +21,7 @@
# include "entity.h" # include "entity.h"
# include "architec.h" # include "architec.h"
# include "expression.h" # include "expression.h"
# include "vtype.h"
# include <fstream> # include <fstream>
# include <iomanip> # include <iomanip>
# include <typeinfo> # include <typeinfo>
@ -66,7 +67,7 @@ void Entity::dump(ostream&out) const
InterfacePort*item = *cur; InterfacePort*item = *cur;
out << setw(6) << "" << item->name out << setw(6) << "" << item->name
<< " : " << item->mode << " : " << item->mode
<< ", type=" << item->type_name << ", type=" << (item->type? typeid(*item->type).name() : "NOTYPE")
<< ", file=" << item->get_fileline() << endl; << ", file=" << item->get_fileline() << endl;
} }
} }

View File

@ -28,6 +28,7 @@
typedef enum { PORT_NONE=0, PORT_IN, PORT_OUT } port_mode_t; typedef enum { PORT_NONE=0, PORT_IN, PORT_OUT } port_mode_t;
class Architecture; class Architecture;
class VType;
class InterfacePort : public LineInfo { class InterfacePort : public LineInfo {
public: public:
@ -36,7 +37,7 @@ class InterfacePort : public LineInfo {
// Name of the port from the source code // Name of the port from the source code
perm_string name; perm_string name;
// Name of interface type as given in the source code. // Name of interface type as given in the source code.
perm_string type_name; const VType*type;
}; };
class Entity : public LineInfo { class Entity : public LineInfo {

View File

@ -22,6 +22,7 @@
# include "architec.h" # include "architec.h"
# include "vtype.h" # include "vtype.h"
# include <iostream> # include <iostream>
# include <typeinfo>
# include <fstream> # include <fstream>
# include <iomanip> # include <iomanip>
# include <cstring> # include <cstring>
@ -92,11 +93,12 @@ int Entity::elaborate_ports_(void)
cur_decl.msb = 0; cur_decl.msb = 0;
cur_decl.lsb = 0; cur_decl.lsb = 0;
const VType*type = global_types[cur_port->type_name]; const VType*type = cur_port->type;
if (type == 0) { if (type == 0) {
cerr << get_fileline() << ": error: " cerr << get_fileline() << ": error: "
<< "No such type mark " << cur_port->type_name << "Giving up on unknown type for port " << cur_port->name
<< "." << endl; << "." << endl;
errors += 1;
continue; continue;
} }
@ -119,7 +121,7 @@ int Entity::elaborate_ports_(void)
} else { } else {
cerr << get_fileline() << ": error: " cerr << get_fileline() << ": error: "
<< "I don't know how to map port " << cur_port->name << "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; errors += 1;
} }

View File

@ -92,6 +92,8 @@ int main(int argc, char*argv[])
} }
preload_global_types();
for (int idx = optind ; idx < argc ; idx += 1) { for (int idx = optind ; idx < argc ; idx += 1) {
parse_errors = 0; parse_errors = 0;
FILE*fd = fopen(argv[idx], "r"); FILE*fd = fopen(argv[idx], "r");
@ -116,8 +118,6 @@ int main(int argc, char*argv[])
if (dump_design_entities_path) if (dump_design_entities_path)
dump_design_entities(dump_design_entities_path); dump_design_entities(dump_design_entities_path);
preload_global_types();
int errors = 0; int errors = 0;
errors = elaborate_entities(); errors = elaborate_entities();
if (errors > 0) { if (errors > 0) {

View File

@ -27,6 +27,7 @@
# include "parse_misc.h" # include "parse_misc.h"
# include "architec.h" # include "architec.h"
# include "expression.h" # include "expression.h"
# include "vtype.h"
# include <cstdarg> # include <cstdarg>
# include <list> # include <list>
@ -54,6 +55,8 @@ int parse_errors = 0;
Expression*expr; Expression*expr;
std::list<Expression*>* expr_list; std::list<Expression*>* expr_list;
const VType* vtype;
InterfacePort*interface_element; InterfacePort*interface_element;
std::list<InterfacePort*>* interface_list; std::list<InterfacePort*>* interface_list;
@ -108,6 +111,8 @@ int parse_errors = 0;
%type <expr_list> waveform waveform_elements %type <expr_list> waveform waveform_elements
%type <vtype> subtype_indication
%type <text> identifier_opt %type <text> identifier_opt
%% %%
@ -170,6 +175,10 @@ concurrent_statement
: concurrent_signal_assignment_statement : concurrent_signal_assignment_statement
; ;
constraint
: '(' simple_expression direction simple_expression ')'
;
context_clause : context_items | ; context_clause : context_items | ;
context_item context_item
@ -193,6 +202,8 @@ design_units
| design_unit | design_unit
; ;
direction : K_to | K_downto ;
/* As an entity is declared, add it to the map of design entities. */ /* As an entity is declared, add it to the map of design entities. */
entity_declaration entity_declaration
: K_entity IDENTIFIER K_is entity_header K_end K_entity_opt ';' : 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. // Save the entity in the entity map.
design_entities[tmp->get_name()] = tmp; 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 entity_header
@ -273,14 +289,13 @@ identifier_opt : IDENTIFIER { $$ = $1; } | { $$ = 0; } ;
/* The interface_element is also an interface_declaration */ /* The interface_element is also an interface_declaration */
interface_element interface_element
: IDENTIFIER ':' mode IDENTIFIER : IDENTIFIER ':' mode subtype_indication
{ InterfacePort*tmp = new InterfacePort; { InterfacePort*tmp = new InterfacePort;
FILE_NAME(tmp, @1); FILE_NAME(tmp, @1);
tmp->mode = $3; tmp->mode = $3;
tmp->name = lex_strings.make($1); tmp->name = lex_strings.make($1);
tmp->type_name = lex_strings.make($4); tmp->type = $4;
delete[]$1; delete[]$1;
delete[]$4;
$$ = tmp; $$ = tmp;
} }
; ;
@ -326,6 +341,11 @@ mode
port_clause port_clause
: K_port '(' interface_list ')' ';' : K_port '(' interface_list ')' ';'
{ $$ = $3; } { $$ = $3; }
| K_port '(' error ')' ';'
{ errormsg(@1, "Syntax error in port list\n");
yyerrok;
$$ = 0;
}
; ;
primary primary
@ -353,6 +373,19 @@ shift_expression : simple_expression { $$ = $1; } ;
simple_expression : term { $$ = $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; } ; term : factor { $$ = $1; } ;
use_clause use_clause

View File

@ -30,6 +30,9 @@
# include "vhdlreal.h" # include "vhdlreal.h"
# include "architec.h" # include "architec.h"
# include "expression.h" # include "expression.h"
class VType;
# include "parse.h" # include "parse.h"
#endif #endif

View File

@ -34,6 +34,10 @@ void preload_global_types(void)
global_types[perm_string::literal("bit")] = &primitive_BIT; global_types[perm_string::literal("bit")] = &primitive_BIT;
global_types[perm_string::literal("integer")] = &primitive_INTEGER; global_types[perm_string::literal("integer")] = &primitive_INTEGER;
global_types[perm_string::literal("std_logic")] = &primitive_STDLOGIC; global_types[perm_string::literal("std_logic")] = &primitive_STDLOGIC;
{ vector<VTypeArray::range_t> 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() VTypePrimitive::~VTypePrimitive()
{ {
} }
VTypeArray::VTypeArray(const VType*element, const vector<VTypeArray::range_t>&r)
: etype_(element), ranges_(r)
{
}
VTypeArray::~VTypeArray()
{
}

View File

@ -20,8 +20,15 @@
*/ */
# include <map> # include <map>
# include <vector>
# include <climits>
# include "StringHeap.h" # 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 { class VType {
public: public:
@ -62,18 +69,41 @@ extern const VTypePrimitive primitive_BIT;
extern const VTypePrimitive primitive_INTEGER; extern const VTypePrimitive primitive_INTEGER;
extern const VTypePrimitive primitive_STDLOGIC; 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 { class VTypeArray : public VType {
public: 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<range_t>&r);
~VTypeArray(); ~VTypeArray();
size_t dimensions() const; size_t dimensions() const;
VType* element_type() const; const VType* element_type() const;
private: private:
size_t dimensions_; const VType*etype_;
VType*etype_;
std::vector<range_t> ranges_;
}; };
#endif #endif