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 "architec.h"
# include "expression.h"
# include "vtype.h"
# include <fstream>
# include <iomanip>
# include <typeinfo>
@ -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;
}
}

View File

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

View File

@ -22,6 +22,7 @@
# include "architec.h"
# include "vtype.h"
# include <iostream>
# include <typeinfo>
# include <fstream>
# include <iomanip>
# include <cstring>
@ -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;
}

View File

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

View File

@ -27,6 +27,7 @@
# include "parse_misc.h"
# include "architec.h"
# include "expression.h"
# include "vtype.h"
# include <cstdarg>
# include <list>
@ -54,6 +55,8 @@ int parse_errors = 0;
Expression*expr;
std::list<Expression*>* expr_list;
const VType* vtype;
InterfacePort*interface_element;
std::list<InterfacePort*>* interface_list;
@ -108,6 +111,8 @@ int parse_errors = 0;
%type <expr_list> waveform waveform_elements
%type <vtype> subtype_indication
%type <text> 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

View File

@ -30,6 +30,9 @@
# include "vhdlreal.h"
# include "architec.h"
# include "expression.h"
class VType;
# include "parse.h"
#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("integer")] = &primitive_INTEGER;
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()
{
}
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 <vector>
# include <climits>
# 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<range_t>&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<range_t> ranges_;
};
#endif