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:
parent
7f6199fbcb
commit
7d552980a6
|
|
@ -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 = "?";
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
if(strchr(yytext, '.')) {
|
||||
yylval.real = new vhdlreal(yytext);
|
||||
return REAL_LITERAL;
|
||||
} else {
|
||||
yylval.integer = new vhdlint(yytext);
|
||||
return INT_LITERAL;
|
||||
}
|
||||
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 (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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
Loading…
Reference in New Issue