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:
parent
bc5fe9676e
commit
f32ede23b7
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@
|
|||
# include "vhdlreal.h"
|
||||
# include "architec.h"
|
||||
# include "expression.h"
|
||||
|
||||
class VType;
|
||||
|
||||
# include "parse.h"
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue