Elaborate array subtypes of ports.

There are internal types that are unbounded arrays. Allow subtype
syntax that creates bounded versions of these arrays, and elaborate
them as vectors at port boundaries. This makes some interesting types
work out.

Also start replacing vhdlint and vhdlreal with int64_t and double,
which are reasonable values for universal_integer and universal_real
from the VHDL standard. I need these cleaned up because the ints in
particular are used for the literal expressions in array index constraints.
This commit is contained in:
Stephen Williams 2011-02-13 19:01:21 -08:00
parent 7f6199fbcb
commit 7d552980a6
11 changed files with 230 additions and 29 deletions

View File

@ -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 << "<nil>";
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 = "?";

View File

@ -26,6 +26,7 @@
# include <fstream>
# include <iomanip>
# include <cstring>
# include <cassert>
using namespace std;
@ -118,6 +119,27 @@ int Entity::elaborate_ports_(void)
break;
}
} else if (const VTypeArray*arr_type = dynamic_cast<const VTypeArray*>(type)) {
const VTypePrimitive*base = dynamic_cast<const VTypePrimitive*>(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

View File

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

View File

@ -21,6 +21,7 @@
# include "StringHeap.h"
# include "LineInfo.h"
# include <inttypes.h>
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

View File

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

View File

@ -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;
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(strchr(yytext, '.')) {
yylval.real = new vhdlreal(yytext);
return REAL_LITERAL;
} else {
yylval.integer = new vhdlint(yytext);
return INT_LITERAL;
}
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;
}
}

View File

@ -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<Expression*>* expr_list;
@ -91,14 +92,16 @@ int parse_errors = 0;
%token K_xnor K_xor
/* Identifiers that are not keywords are identifiers. */
%token <text> IDENTIFIER
%token <integer> INT_LITERAL
%token <real> REAL_LITERAL
%token <uni_integer> INT_LITERAL
%token <uni_real> REAL_LITERAL
%token <text> STRING_LITERAL CHARACTER_LITERAL
/* compound symbols */
%token LEQ GEQ VASSIGN NE BOX EXP ARROW DLT DGT
/* The rules may have types. */
%type <flag> direction
%type <interface_element> interface_element
%type <interface_list> interface_list entity_header port_clause
%type <port_mode> 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;
}

View File

@ -22,8 +22,11 @@
# include "parse_api.h"
# include "entity.h"
# include "architec.h"
# include "expression.h"
# include "vtype.h"
# include "compiler.h"
# include <iostream>
# include <cassert>
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<const VTypeArray*> (base_type);
if (base_array) {
assert(array_left && array_right);
vector<VTypeArray::range_t> 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;
}

View File

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

View File

@ -18,6 +18,7 @@
*/
# include "vtype.h"
# include <typeinfo>
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<VTypeArray::range_t>&r)
: etype_(element), ranges_(r)
{
@ -62,3 +86,27 @@ VTypeArray::VTypeArray(const VType*element, const vector<VTypeArray::range_t>&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<range_t>::const_iterator cur = ranges_.begin()
; cur != ranges_.end() ; ++cur) {
out << "(" << cur->msb() << " downto " << cur->lsb() << ")";
}
out << " of ";
if (etype_)
etype_->show(out);
else
out << "<nil>";
}

View File

@ -19,6 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include <iostream>
# include <map>
# include <vector>
# include <climits>
@ -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<range_t>&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: