Merge pull request #122 from orsonmmz/resize_fix

vhdlpp update
This commit is contained in:
Stephen Williams 2016-09-02 10:01:02 -07:00 committed by GitHub
commit 301e85a8ca
19 changed files with 333 additions and 147 deletions

View File

@ -152,22 +152,9 @@ int CondSignalAssignment::emit(ostream&out, Entity*ent, Architecture*arc)
int errors = 0; int errors = 0;
out << "// " << get_fileline() << endl; out << "// " << get_fileline() << endl;
out << "always @("; out << "always begin" << endl;
bool first = true; bool first = true;
for(list<const ExpName*>::const_iterator it = sens_list_.begin();
it != sens_list_.end(); ++it) {
if(first)
first = false;
else
out << ",";
errors += (*it)->emit(out, ent, arc);
}
out << ") begin" << endl;
first = true;
for(list<ExpConditional::case_t*>::iterator it = options_.begin(); for(list<ExpConditional::case_t*>::iterator it = options_.begin();
it != options_.end(); ++it) { it != options_.end(); ++it) {
ExpConditional::case_t*cas = *it; ExpConditional::case_t*cas = *it;
@ -192,6 +179,21 @@ int CondSignalAssignment::emit(ostream&out, Entity*ent, Architecture*arc)
out << ";" << endl; out << ";" << endl;
} }
// Sensitivity list
first = true;
out << "@(";
for(list<const ExpName*>::const_iterator it = sens_list_.begin();
it != sens_list_.end(); ++it) {
if(first)
first = false;
else
out << ",";
errors += (*it)->emit(out, ent, arc);
}
out << ");" << endl;
out << "end" << endl; out << "end" << endl;
return errors; return errors;

View File

@ -436,29 +436,6 @@ void ExpRelation::dump(ostream&out, int indent) const
dump_operands(out, indent+4); dump_operands(out, indent+4);
} }
void ExpString::dump(ostream&out, int indent) const
{
out << setw(indent) << "" << "String \"" << value_;
out << "\"" << " at " << get_fileline() << endl;
}
void ExpUAbs::dump(ostream&out, int indent) const
{
out << setw(indent) << "" << "abs() at " << get_fileline() << endl;
dump_operand1(out, indent+4);
}
void ExpUnary::dump_operand1(ostream&out, int indent) const
{
operand1_->dump(out, indent);
}
void ExpUNot::dump(ostream&out, int indent) const
{
out << setw(indent) << "" << "not() at " << get_fileline() << endl;
dump_operand1(out, indent+4);
}
void named_expr_t::dump(ostream&out, int indent) const void named_expr_t::dump(ostream&out, int indent) const
{ {
out << setw(indent) << "" << name_ << "=>"; out << setw(indent) << "" << name_ << "=>";

View File

@ -24,6 +24,7 @@
# include "subprogram.h" # include "subprogram.h"
# include "parse_types.h" # include "parse_types.h"
# include "scope.h" # include "scope.h"
# include "library.h"
# include <iostream> # include <iostream>
# include <typeinfo> # include <typeinfo>
# include <cstring> # include <cstring>
@ -569,6 +570,32 @@ const VType* ExpFunc::func_ret_type() const
return def_ ? def_->peek_return_type() : NULL; return def_ ? def_->peek_return_type() : NULL;
} }
SubprogramHeader*ExpFunc::match_signature(Entity*ent, ScopeBase*scope) const
{
SubprogramHeader*prog = NULL;
list<const VType*> arg_types;
// Create a list of argument types to find a matching subprogram
for(vector<Expression*>::const_iterator it = argv_.begin();
it != argv_.end(); ++it) {
arg_types.push_back((*it)->probe_type(ent, scope));
}
prog = scope->match_subprogram(name_, &arg_types);
if(!prog)
prog = library_match_subprogram(name_, &arg_types);
if(!prog) {
cerr << get_fileline() << ": sorry: could not find function ";
emit_subprogram_sig(cerr, name_, arg_types);
cerr << endl;
ivl_assert(*this, false);
}
return prog;
}
ExpInteger::ExpInteger(int64_t val) ExpInteger::ExpInteger(int64_t val)
: value_(val) : value_(val)
{ {
@ -818,6 +845,15 @@ ExpUNot::~ExpUNot()
{ {
} }
ExpUMinus::ExpUMinus(Expression*op1)
: ExpUnary(op1)
{
}
ExpUMinus::~ExpUMinus()
{
}
ExpCast::ExpCast(Expression*base, const VType*type) : ExpCast::ExpCast(Expression*base, const VType*type) :
base_(base), type_(type) base_(base), type_(type)
{ {

View File

@ -620,12 +620,15 @@ class ExpFunc : public Expression {
void write_to_stream(std::ostream&fd) const; void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope) const; int emit(ostream&out, Entity*ent, ScopeBase*scope) const;
void dump(ostream&out, int indent = 0) const; void dump(ostream&out, int indent = 0) const;
void visit(ExprVisitor& func); // NOTE: does not handle expressions in subprogram void visit(ExprVisitor& func); // NOTE: does not handle expressions in subprogram body
// Returns a subprogram header that matches the function call
SubprogramHeader*match_signature(Entity*ent, ScopeBase*scope) const;
private: private:
perm_string name_; perm_string name_;
std::vector<Expression*> argv_; std::vector<Expression*> argv_;
SubprogramHeader*def_; mutable SubprogramHeader*def_;
}; };
class ExpInteger : public Expression { class ExpInteger : public Expression {
@ -948,6 +951,19 @@ class ExpUNot : public ExpUnary {
void dump(ostream&out, int indent = 0) const; void dump(ostream&out, int indent = 0) const;
}; };
class ExpUMinus : public ExpUnary {
public:
explicit ExpUMinus(Expression*op1);
~ExpUMinus();
Expression*clone() const { return new ExpUMinus(peek_operand()->clone()); }
void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope) const;
void dump(ostream&out, int indent = 0) const;
};
/* /*
* Class that wraps other expressions to cast them to other types. * Class that wraps other expressions to cast them to other types.
*/ */

View File

@ -119,6 +119,35 @@ void ExpShift::dump(ostream&out, int indent) const
dump_operands(out, indent+4); dump_operands(out, indent+4);
} }
void ExpString::dump(ostream&out, int indent) const
{
out << setw(indent) << "" << "String \"" << value_;
out << "\"" << " at " << get_fileline() << endl;
}
void ExpUAbs::dump(ostream&out, int indent) const
{
out << setw(indent) << "" << "abs() at " << get_fileline() << endl;
dump_operand1(out, indent+4);
}
void ExpUnary::dump_operand1(ostream&out, int indent) const
{
operand1_->dump(out, indent);
}
void ExpUNot::dump(ostream&out, int indent) const
{
out << setw(indent) << "" << "not() at " << get_fileline() << endl;
dump_operand1(out, indent+4);
}
void ExpUMinus::dump(ostream&out, int indent) const
{
out << setw(indent) << "" << "unary_minus() at " << get_fileline() << endl;
dump_operand1(out, indent+4);
}
void ExpTime::dump(ostream&out, int indent) const void ExpTime::dump(ostream&out, int indent) const
{ {
out << setw(indent) << "" << "Time "; out << setw(indent) << "" << "Time ";

View File

@ -26,7 +26,6 @@
# include "entity.h" # include "entity.h"
# include "vsignal.h" # include "vsignal.h"
# include "subprogram.h" # include "subprogram.h"
# include "library.h"
# include "std_types.h" # include "std_types.h"
# include <iostream> # include <iostream>
# include <typeinfo> # include <typeinfo>
@ -74,13 +73,12 @@ const VType*ExpName::elaborate_adjust_type_with_range_(Entity*ent, ScopeBase*sco
// If the name is an array, then a part select is // If the name is an array, then a part select is
// also an array, but with different bounds. // also an array, but with different bounds.
int64_t use_msb, use_lsb; int64_t use_msb, use_lsb;
bool flag; bool flag = true;
flag = range->msb()->evaluate(ent, scope, use_msb); flag &= range->msb()->evaluate(ent, scope, use_msb);
ivl_assert(*this, flag); flag &= range->lsb()->evaluate(ent, scope, use_lsb);
flag = range->lsb()->evaluate(ent, scope, use_lsb);
ivl_assert(*this, flag);
if(flag)
type = new VTypeArray(array->element_type(), use_msb, use_lsb); type = new VTypeArray(array->element_type(), use_msb, use_lsb);
} }
else if(idx) { else if(idx) {
@ -419,7 +417,7 @@ const VType*ExpAggregate::fit_type(Entity*, ScopeBase*, const VTypeArray*host) c
Expression*use_msb = prange->msb(); Expression*use_msb = prange->msb();
Expression*use_lsb = prange->lsb(); Expression*use_lsb = prange->lsb();
ivl_assert(*this, host->dimensions() == 1); ivl_assert(*this, host->dimensions().size() == 1);
vector<VTypeArray::range_t> range (1); vector<VTypeArray::range_t> range (1);
range[0] = VTypeArray::range_t(use_msb, use_lsb); range[0] = VTypeArray::range_t(use_msb, use_lsb);
@ -580,6 +578,7 @@ int ExpArithmetic::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype
const VType* ExpArithmetic::resolve_operand_types_(const VType*t1, const VType*t2) const const VType* ExpArithmetic::resolve_operand_types_(const VType*t1, const VType*t2) const
{ {
// Ranges
while (const VTypeRange*tmp = dynamic_cast<const VTypeRange*> (t1)) while (const VTypeRange*tmp = dynamic_cast<const VTypeRange*> (t1))
t1 = tmp->base_type(); t1 = tmp->base_type();
while (const VTypeRange*tmp = dynamic_cast<const VTypeRange*> (t2)) while (const VTypeRange*tmp = dynamic_cast<const VTypeRange*> (t2))
@ -588,6 +587,57 @@ const VType* ExpArithmetic::resolve_operand_types_(const VType*t1, const VType*t
if (t1->type_match(t2)) if (t1->type_match(t2))
return t1; return t1;
// Signed & unsigned (resized to the widest argument)
const VTypeArray*t1_arr = dynamic_cast<const VTypeArray*>(t1);
const VTypeArray*t2_arr = dynamic_cast<const VTypeArray*>(t2);
if(t1_arr && t2_arr) {
const VTypeArray*t1_parent = t1_arr->get_parent_type();
const VTypeArray*t2_parent = t2_arr->get_parent_type();
if(t1_parent == t2_parent
&& (t1_parent == &primitive_SIGNED || t1_parent == &primitive_UNSIGNED)) {
int t1_size = t1_arr->get_width(NULL);
int t2_size = t2_arr->get_width(NULL);
// Easy, the same sizes, so we do not need to resize
if(t1_size == t2_size && t1_size > 0)
return t1; // == t2
VTypeArray*resolved = new VTypeArray(t1_parent->element_type(),
std::max(t1_size, t2_size) - 1, 0, t1_parent->signed_vector());
resolved->set_parent_type(t1_parent);
return resolved;
}
} else if(t1_arr) {
if(const VTypePrimitive*prim = dynamic_cast<const VTypePrimitive*>(t2)) {
const VTypeArray*t1_parent = t1_arr->get_parent_type();
VTypePrimitive::type_t t2_type = prim->type();
if((t2_type == VTypePrimitive::NATURAL || t2_type == VTypePrimitive::INTEGER)
&& t1_parent == &primitive_SIGNED)
return t1;
if((t2_type == VTypePrimitive::NATURAL) && t1_parent == &primitive_UNSIGNED)
return t1;
}
} else if(t2_arr) {
if(const VTypePrimitive*prim = dynamic_cast<const VTypePrimitive*>(t1)) {
const VTypeArray*t2_parent = t2_arr->get_parent_type();
VTypePrimitive::type_t t1_type = prim->type();
if((t1_type == VTypePrimitive::NATURAL || t1_type == VTypePrimitive::INTEGER)
&& t2_parent == &primitive_SIGNED)
return t2;
if((t1_type == VTypePrimitive::NATURAL) && t2_parent == &primitive_UNSIGNED)
return t2;
}
}
return 0; return 0;
} }
@ -678,7 +728,7 @@ const VType*ExpConcat::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*at
if(const VTypeArray*arr = dynamic_cast<const VTypeArray*>(types[i])) { if(const VTypeArray*arr = dynamic_cast<const VTypeArray*>(types[i])) {
types[i] = arr->element_type(); types[i] = arr->element_type();
ivl_assert(*this, arr->dimensions() == 1); ivl_assert(*this, arr->dimensions().size() == 1);
const VTypeArray::range_t&dim = arr->dimension(0); const VTypeArray::range_t&dim = arr->dimension(0);
sizes[i] = new ExpArithmetic(ExpArithmetic::MINUS, dim.msb(), dim.lsb()); sizes[i] = new ExpArithmetic(ExpArithmetic::MINUS, dim.msb(), dim.lsb());
} else { } else {
@ -733,7 +783,7 @@ int ExpConcat::elaborate_expr_array_(Entity*ent, ScopeBase*scope, const VTypeArr
int errors = 0; int errors = 0;
// For now, only support single-dimension arrays here. // For now, only support single-dimension arrays here.
ivl_assert(*this, atype->dimensions() == 1); ivl_assert(*this, atype->dimensions().size() == 1);
const VType*type1 = operand1_->fit_type(ent, scope, atype); const VType*type1 = operand1_->fit_type(ent, scope, atype);
ivl_assert(*this, type1); ivl_assert(*this, type1);
@ -791,55 +841,23 @@ int ExpConditional::case_t::elaborate_expr(Entity*ent, ScopeBase*scope, const VT
const VType*ExpFunc::probe_type(Entity*ent, ScopeBase*scope) const const VType*ExpFunc::probe_type(Entity*ent, ScopeBase*scope) const
{ {
SubprogramHeader*prog = def_; if(!def_)
def_ = match_signature(ent, scope);
if(!prog) { return def_ ? def_->exact_return_type(argv_, ent, scope) : NULL;
list<const VType*> arg_types;
for(vector<Expression*>::const_iterator it = argv_.begin();
it != argv_.end(); ++it) {
arg_types.push_back((*it)->probe_type(ent, scope));
}
prog = scope->match_subprogram(name_, &arg_types);
if(!prog)
prog = library_match_subprogram(name_, &arg_types);
if(!prog) {
cerr << get_fileline() << ": sorry: could not find function ";
emit_subprogram_sig(cerr, name_, arg_types);
cerr << endl;
ivl_assert(*this, false);
}
}
return prog->peek_return_type();
} }
int ExpFunc::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*) int ExpFunc::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*)
{ {
int errors = 0; int errors = 0;
ivl_assert(*this, def_ == 0); // do not elaborate twice if(def_)
return 0;
// Create a list of argument types to find a matching subprogram def_ = match_signature(ent, scope);
list<const VType*> arg_types;
for(vector<Expression*>::iterator it = argv_.begin();
it != argv_.end(); ++it)
arg_types.push_back((*it)->probe_type(ent, scope));
def_ = scope->match_subprogram(name_, &arg_types);
if(!def_) if(!def_)
def_ = library_match_subprogram(name_, &arg_types);
if(!def_) {
cerr << get_fileline() << ": error: could not find function ";
emit_subprogram_sig(cerr, name_, arg_types);
cerr << endl;
return 1; return 1;
}
// Elaborate arguments // Elaborate arguments
for (size_t idx = 0; idx < argv_.size(); ++idx) { for (size_t idx = 0; idx < argv_.size(); ++idx) {

View File

@ -140,7 +140,7 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, ScopeBase*scope, const VT
// Special case: The aggregate is a single "others" item. // Special case: The aggregate is a single "others" item.
if (aggregate_.size() == 1 && aggregate_[0].choice->others()) { if (aggregate_.size() == 1 && aggregate_[0].choice->others()) {
assert(atype->dimensions() == 1); assert(atype->dimensions().size() == 1);
const VTypeArray::range_t&rang = atype->dimension(0); const VTypeArray::range_t&rang = atype->dimension(0);
assert(! rang.is_box()); assert(! rang.is_box());
@ -978,7 +978,7 @@ int ExpString::emit(ostream& out, Entity*ent, ScopeBase*scope) const
int ExpString::emit_as_array_(ostream& out, Entity*, ScopeBase*, const VTypeArray*arr) const int ExpString::emit_as_array_(ostream& out, Entity*, ScopeBase*, const VTypeArray*arr) const
{ {
int errors = 0; int errors = 0;
assert(arr->dimensions() == 1); assert(arr->dimensions().size() == 1);
const VTypePrimitive*etype = dynamic_cast<const VTypePrimitive*> (arr->basic_type()); const VTypePrimitive*etype = dynamic_cast<const VTypePrimitive*> (arr->basic_type());
assert(etype); assert(etype);
@ -1048,6 +1048,15 @@ int ExpUNot::emit(ostream&out, Entity*ent, ScopeBase*scope) const
return errors; return errors;
} }
int ExpUMinus::emit(ostream&out, Entity*ent, ScopeBase*scope) const
{
int errors = 0;
out << "-(";
errors += emit_operand1(out, ent, scope);
out << ")";
return errors;
}
int ExpCast::emit(ostream&out, Entity*ent, ScopeBase*scope) const int ExpCast::emit(ostream&out, Entity*ent, ScopeBase*scope) const
{ {
int errors = 0; int errors = 0;

View File

@ -85,7 +85,7 @@ bool ExpAttribute::test_array_type(const VType*type) const
return false; return false;
} }
if (arr->dimensions() > 1) { if (arr->dimensions().size() > 1) {
cerr << endl << get_fileline() << ": error: " cerr << endl << get_fileline() << ": error: "
<< "Cannot apply the '" << name_ << "Cannot apply the '" << name_
<< " attribute to multidimensional arrays" << endl; << " attribute to multidimensional arrays" << endl;
@ -144,19 +144,6 @@ bool ExpName::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const
return false; return false;
} }
if (ent) {
const InterfacePort*gen = ent->find_generic(name_);
if (gen) {
// Evaluate the default expression and use that.
if (gen->expr && gen->expr->evaluate(ent, scope, val))
return true;
cerr << get_fileline() << ": sorry: I could not evaluate "
<< "generic override." << endl;
return false;
}
}
if (scope) { if (scope) {
const VType*type; const VType*type;
Expression*exp; Expression*exp;

View File

@ -327,6 +327,13 @@ void ExpUNot::write_to_stream(ostream&fd) const
write_to_stream_operand1(fd); write_to_stream_operand1(fd);
} }
void ExpUMinus::write_to_stream(ostream&fd) const
{
fd << "-(";
write_to_stream_operand1(fd);
fd << ")";
}
void ExpCast::write_to_stream(ostream&fd) const void ExpCast::write_to_stream(ostream&fd) const
{ {
// Type casting is introduced only for a few specific cases in // Type casting is introduced only for a few specific cases in

View File

@ -25,6 +25,7 @@
# include "compiler.h" # include "compiler.h"
# include "package.h" # include "package.h"
# include "std_types.h" # include "std_types.h"
# include "std_funcs.h"
# include <fstream> # include <fstream>
# include <list> # include <list>
# include <map> # include <map>
@ -110,7 +111,7 @@ static string make_library_package_path(perm_string lib_name, perm_string name)
} }
static void import_ieee(void); static void import_ieee(void);
static void import_ieee_use(ActiveScope*res, perm_string package, perm_string name); static void import_ieee_use(const YYLTYPE&loc, ActiveScope*res, perm_string package, perm_string name);
static void import_std_use(const YYLTYPE&loc, ActiveScope*res, perm_string package, perm_string name); static void import_std_use(const YYLTYPE&loc, ActiveScope*res, perm_string package, perm_string name);
static void dump_library_package(ostream&file, perm_string lname, perm_string pname, Package*pack) static void dump_library_package(ostream&file, perm_string lname, perm_string pname, Package*pack)
@ -242,7 +243,7 @@ void library_use(const YYLTYPE&loc, ActiveScope*res,
// Special case handling for the IEEE library. // Special case handling for the IEEE library.
if (use_library == "ieee") { if (use_library == "ieee") {
import_ieee_use(res, use_package, use_name); import_ieee_use(loc, res, use_package, use_name);
return; return;
} }
// Special case handling for the STD library. // Special case handling for the STD library.
@ -312,8 +313,30 @@ static void import_ieee_use_std_logic_1164(ActiveScope*res, perm_string name)
} }
} }
static void import_ieee_use_std_logic_arith(ActiveScope*, perm_string) static void import_ieee_use_std_logic_misc(ActiveScope*, perm_string name)
{ {
bool all_flag = name=="all";
list<InterfacePort*>*args;
if (all_flag || name == "or_reduce") {
/* function or_reduce(arg : std_logic_vector) return std_logic;
*/
args = new list<InterfacePort*>();
args->push_back(new InterfacePort(&primitive_STDLOGIC_VECTOR));
register_std_subprogram(new SubprogramBuiltin(perm_string::literal("or_reduce"),
perm_string::literal("|"),
args, &primitive_STDLOGIC));
}
if (all_flag || name == "and_reduce") {
/* function and_reduce(arg : std_logic_vector) return std_logic;
*/
args = new list<InterfacePort*>();
args->push_back(new InterfacePort(&primitive_STDLOGIC_VECTOR));
register_std_subprogram(new SubprogramBuiltin(perm_string::literal("and_reduce"),
perm_string::literal("&"),
args, &primitive_STDLOGIC));
}
} }
static void import_ieee_use_numeric_bit(ActiveScope*res, perm_string name) static void import_ieee_use_numeric_bit(ActiveScope*res, perm_string name)
@ -340,7 +363,7 @@ static void import_ieee_use_numeric_std(ActiveScope*res, perm_string name)
} }
} }
static void import_ieee_use(ActiveScope*res, perm_string package, perm_string name) static void import_ieee_use(const YYLTYPE&loc, ActiveScope*res, perm_string package, perm_string name)
{ {
if (package == "std_logic_1164") { if (package == "std_logic_1164") {
import_ieee_use_std_logic_1164(res, name); import_ieee_use_std_logic_1164(res, name);
@ -348,7 +371,17 @@ static void import_ieee_use(ActiveScope*res, perm_string package, perm_string na
} }
if (package == "std_logic_arith") { if (package == "std_logic_arith") {
import_ieee_use_std_logic_arith(res, name); // arithmetic operators for std_logic_vector
return;
}
if (package == "std_logic_misc") {
import_ieee_use_std_logic_misc(res, name);
return;
}
if (package == "std_logic_unsigned") {
// arithmetic operators for std_logic_vector
return; return;
} }
@ -361,9 +394,11 @@ static void import_ieee_use(ActiveScope*res, perm_string package, perm_string na
import_ieee_use_numeric_std(res, name); import_ieee_use_numeric_std(res, name);
return; return;
} }
cerr << "Warning: Package ieee." << package.str() <<" is not yet supported" << endl;
} }
static void import_std_use(const YYLTYPE&loc, ActiveScope*res, perm_string package, perm_string name) static void import_std_use(const YYLTYPE&loc, ActiveScope*res, perm_string package, perm_string /*name*/)
{ {
if (package == "standard") { if (package == "standard") {
// do nothing // do nothing
@ -375,7 +410,7 @@ static void import_std_use(const YYLTYPE&loc, ActiveScope*res, perm_string packa
res->use_name(type_FILE_OPEN_STATUS.peek_name(), &type_FILE_OPEN_STATUS); res->use_name(type_FILE_OPEN_STATUS.peek_name(), &type_FILE_OPEN_STATUS);
return; return;
} else { } else {
sorrymsg(loc, "package %s of library %s not yet supported", package.str(), name.str()); cerr << "Warning: Package std." << package.str() <<" is not yet supported" << endl;
return; return;
} }
} }

View File

@ -2484,11 +2484,6 @@ shift_expression
} }
; ;
sign
: '+'
| '-'
;
signal_declaration_assign_opt signal_declaration_assign_opt
: VASSIGN expression { $$ = $2; } : VASSIGN expression { $$ = $2; }
| { $$ = 0; } | { $$ = 0; }
@ -2514,10 +2509,10 @@ signal_declaration_assign_opt
* list fixes up the associations. * list fixes up the associations.
*/ */
simple_expression simple_expression
: sign simple_expression_2 : '-' simple_expression_2
{ sorrymsg(@1, "Unary expression +- not supported.\n"); { $$ = new ExpUMinus($2); }
$$ = $2; | '+' simple_expression_2
} { $$ = $2; }
| simple_expression_2 | simple_expression_2
{ $$ = $1; } { $$ = $1; }
; ;

View File

@ -77,7 +77,7 @@ static const VType* calculate_subtype_array(const YYLTYPE&loc, const char*base_n
const VType*base_type = parse_type_by_name(lex_strings.make(base_name)); const VType*base_type = parse_type_by_name(lex_strings.make(base_name));
if (base_type == 0) { if (base_type == 0) {
errormsg(loc, "Unable to find base type %s of array.\n", base_name); errormsg(loc, "Unable to find array base type '%s'.\n", base_name);
return 0; return 0;
} }
@ -97,7 +97,7 @@ static const VType* calculate_subtype_array(const YYLTYPE&loc, const char*base_n
vector<VTypeArray::range_t> range (base_array->dimensions()); vector<VTypeArray::range_t> range (base_array->dimensions());
// For now, I only know how to handle 1 dimension // For now, I only know how to handle 1 dimension
assert(base_array->dimensions() == 1); assert(base_array->dimensions().size() == 1);
range[0] = VTypeArray::range_t(array_left, array_right, downto); range[0] = VTypeArray::range_t(array_left, array_right, downto);
@ -141,7 +141,7 @@ const VType* calculate_subtype_range(const YYLTYPE&loc, const char*base_name,
const VType*base_type = parse_type_by_name(lex_strings.make(base_name)); const VType*base_type = parse_type_by_name(lex_strings.make(base_name));
if (base_type == 0) { if (base_type == 0) {
errormsg(loc, "Unable to find base type %s of range.\n", base_name); errormsg(loc, "Unable to find range base type '%s'.\n", base_name);
return 0; return 0;
} }

View File

@ -24,7 +24,7 @@
static std::map<perm_string,SubHeaderList> std_subprograms; static std::map<perm_string,SubHeaderList> std_subprograms;
static inline void register_std_subprogram(SubprogramHeader*header) void register_std_subprogram(SubprogramHeader*header)
{ {
std_subprograms[header->name()].push_back(header); std_subprograms[header->name()].push_back(header);
} }
@ -68,28 +68,51 @@ class SubprogramSizeCast : public SubprogramStdHeader {
: SubprogramStdHeader(nam, NULL, target) { : SubprogramStdHeader(nam, NULL, target) {
ports_ = new list<InterfacePort*>(); ports_ = new list<InterfacePort*>();
ports_->push_back(new InterfacePort(base)); ports_->push_back(new InterfacePort(base));
ports_->push_back(new InterfacePort(&primitive_INTEGER)); ports_->push_back(new InterfacePort(&primitive_NATURAL));
} }
int emit_name(const std::vector<Expression*>&argv, int emit_name(const std::vector<Expression*>&,
std::ostream&out, Entity*ent, ScopeBase*scope) const { std::ostream&, Entity*, ScopeBase*) const {
int64_t use_size;
bool rc = argv[1]->evaluate(ent, scope, use_size);
if(!rc) {
cerr << get_fileline() << ": sorry: Could not evaluate the "
<< "expression size. Size casting impossible." << endl;
return 1;
}
out << use_size << "'";
return 0; return 0;
} }
int emit_args(const std::vector<Expression*>&argv, int emit_args(const std::vector<Expression*>&argv,
std::ostream&out, Entity*ent, ScopeBase*scope) const { std::ostream&out, Entity*ent, ScopeBase*scope) const {
int64_t new_size, old_size;
return argv[0]->emit(out, ent, scope); const VType*type = argv[0]->probe_type(ent, scope);
if(!type) {
cerr << get_fileline() << ": sorry: Could not determine "
<< "the argument type. Size casting impossible." << endl;
return 1;
}
old_size = type->get_width(scope);
if(old_size <= 0) {
cerr << get_fileline() << ": sorry: Could not determine "
<< "the argument size. Size casting impossible." << endl;
return 1;
}
if(!argv[1]->evaluate(ent, scope, new_size)) {
cerr << get_fileline() << ": sorry: Could not evaluate the requested"
<< "expression size. Size casting impossible." << endl;
return 1;
}
out << new_size << "'(" << old_size << "'(";
if(const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type))
out << (arr->signed_vector() ? "$signed" : "$unsigned");
out << "(";
bool res = argv[0]->emit(out, ent, scope);
out << ")))";
return res;
} }
}; };
@ -187,7 +210,13 @@ void preload_std_funcs(void)
have to do anything for that to work. have to do anything for that to work.
*/ */
args = new list<InterfacePort*>(); args = new list<InterfacePort*>();
args->push_back(new InterfacePort(&primitive_STDLOGIC_VECTOR)); args->push_back(new InterfacePort(&primitive_SIGNED));
register_std_subprogram(new SubprogramBuiltin(perm_string::literal("std_logic_vector"),
empty_perm_string,
args, &primitive_STDLOGIC_VECTOR));
args = new list<InterfacePort*>();
args->push_back(new InterfacePort(&primitive_UNSIGNED));
register_std_subprogram(new SubprogramBuiltin(perm_string::literal("std_logic_vector"), register_std_subprogram(new SubprogramBuiltin(perm_string::literal("std_logic_vector"),
empty_perm_string, empty_perm_string,
args, &primitive_STDLOGIC_VECTOR)); args, &primitive_STDLOGIC_VECTOR));
@ -215,6 +244,13 @@ void preload_std_funcs(void)
* function shift_right (arg: signed; count: natural) return signed; * function shift_right (arg: signed; count: natural) return signed;
*/ */
args = new list<InterfacePort*>(); args = new list<InterfacePort*>();
args->push_back(new InterfacePort(&primitive_UNSIGNED));
args->push_back(new InterfacePort(&primitive_NATURAL));
register_std_subprogram(new SubprogramBuiltin(perm_string::literal("shift_right"),
perm_string::literal("$ivlh_shift_right"),
args, &primitive_UNSIGNED));
args = new list<InterfacePort*>();
args->push_back(new InterfacePort(&primitive_SIGNED)); args->push_back(new InterfacePort(&primitive_SIGNED));
args->push_back(new InterfacePort(&primitive_NATURAL)); args->push_back(new InterfacePort(&primitive_NATURAL));
register_std_subprogram(new SubprogramBuiltin(perm_string::literal("shift_right"), register_std_subprogram(new SubprogramBuiltin(perm_string::literal("shift_right"),
@ -224,12 +260,16 @@ void preload_std_funcs(void)
/* function resize /* function resize
*/ */
register_std_subprogram(new SubprogramSizeCast(perm_string::literal("resize"), register_std_subprogram(new SubprogramSizeCast(perm_string::literal("resize"),
&primitive_STDLOGIC_VECTOR, &primitive_STDLOGIC_VECTOR)); &primitive_UNSIGNED, &primitive_UNSIGNED));
register_std_subprogram(new SubprogramSizeCast(perm_string::literal("resize"),
&primitive_SIGNED, &primitive_SIGNED));
/* std_logic_arith library /* std_logic_arith library
* function conv_std_logic_vector(arg: integer; size: integer) return std_logic_vector; * function conv_std_logic_vector(arg: integer; size: integer) return std_logic_vector;
*/ */
register_std_subprogram(new SubprogramSizeCast(perm_string::literal("conv_std_logic_vector"), register_std_subprogram(new SubprogramSizeCast(
perm_string::literal("conv_std_logic_vector"),
&primitive_INTEGER, &primitive_STDLOGIC_VECTOR)); &primitive_INTEGER, &primitive_STDLOGIC_VECTOR));
/* numeric_bit library /* numeric_bit library

View File

@ -28,6 +28,9 @@ void preload_std_funcs();
// Destroys subprogram headers for standard VHDL library functions. // Destroys subprogram headers for standard VHDL library functions.
void delete_std_funcs(); void delete_std_funcs();
// Adds a subprogram to the standard library subprogram set
void register_std_subprogram(SubprogramHeader*header);
// Returns subprogram header for a requested function or NULL if it does not exist. // Returns subprogram header for a requested function or NULL if it does not exist.
SubHeaderList find_std_subprogram(perm_string name); SubHeaderList find_std_subprogram(perm_string name);

View File

@ -172,6 +172,24 @@ const VType*SubprogramHeader::peek_param_type(int idx) const
return NULL; return NULL;
} }
const VType*SubprogramHeader::exact_return_type(const std::vector<Expression*>&argv, Entity*ent, ScopeBase*scope)
{
const VTypeArray*orig_ret = dynamic_cast<const VTypeArray*>(return_type_);
if(!orig_ret)
return return_type_;
const VTypeArray*arg = dynamic_cast<const VTypeArray*>(argv[0]->fit_type(ent, scope, orig_ret));
if(!arg)
return return_type_;
VTypeArray*ret = new VTypeArray(orig_ret->element_type(), arg->dimensions(), orig_ret->signed_vector());
ret->set_parent_type(orig_ret);
return ret;
}
bool SubprogramHeader::unbounded() const { bool SubprogramHeader::unbounded() const {
if(return_type_ && return_type_->is_unbounded()) if(return_type_ && return_type_->is_unbounded())
return true; return true;

View File

@ -80,6 +80,10 @@ class SubprogramHeader : public LineInfo {
const VType*peek_param_type(int idx) const; const VType*peek_param_type(int idx) const;
const VType*peek_return_type() const { return return_type_; } const VType*peek_return_type() const { return return_type_; }
// Computes the exact return type (e.g. std_logic_vector(7 downto 0)
// instead of generic std_logic_vector)
virtual const VType*exact_return_type(const std::vector<Expression*>&, Entity*, ScopeBase*);
inline void set_package(const Package*pkg) { assert(!package_); package_ = pkg; } inline void set_package(const Package*pkg) { assert(!package_); package_ = pkg; }
inline const Package*get_package() const { return package_; } inline const Package*get_package() const { return package_; }

View File

@ -226,7 +226,7 @@ class VTypeArray : public VType {
void show(std::ostream&) const; void show(std::ostream&) const;
int get_width(ScopeBase*scope) const; int get_width(ScopeBase*scope) const;
inline size_t dimensions() const { return ranges_.size(); }; const std::vector<range_t>&dimensions() const { return ranges_; };
const range_t&dimension(size_t idx) const const range_t&dimension(size_t idx) const
{ return ranges_[idx]; } { return ranges_[idx]; }
@ -253,6 +253,8 @@ class VTypeArray : public VType {
// To handle subtypes // To handle subtypes
inline void set_parent_type(const VTypeArray*parent) { parent_ = parent; } inline void set_parent_type(const VTypeArray*parent) { parent_ = parent; }
const VTypeArray*get_parent_type() const { return parent_; }
// Wherever it is possible, replaces range lsb & msb expressions with // Wherever it is possible, replaces range lsb & msb expressions with
// constant integers. // constant integers.
void evaluate_ranges(ScopeBase*scope); void evaluate_ranges(ScopeBase*scope);

View File

@ -65,7 +65,7 @@ int VTypeArray::emit_def(ostream&out, perm_string name) const
const VTypePrimitive*base = dynamic_cast<const VTypePrimitive*> (raw_base); const VTypePrimitive*base = dynamic_cast<const VTypePrimitive*> (raw_base);
if (base) { if (base) {
assert(dimensions() == 1); assert(dimensions().size() == 1);
// If this is a string type without any boundaries specified, then // If this is a string type without any boundaries specified, then
// there is a direct counterpart in SV called.. 'string' // there is a direct counterpart in SV called.. 'string'
@ -127,7 +127,7 @@ int VTypeArray::emit_with_dims_(std::ostream&out, bool packed, perm_string name)
name_emitted = true; name_emitted = true;
} }
for(unsigned i = 0; i < cur->dimensions(); ++i) { for(unsigned i = 0; i < cur->dimensions().size(); ++i) {
if(cur->dimension(i).is_box() && !name_emitted) { if(cur->dimension(i).is_box() && !name_emitted) {
emit_name(out, name); emit_name(out, name);
name_emitted = true; name_emitted = true;

View File

@ -70,7 +70,15 @@ bool VTypeArray::type_match(const VType*that) const
// Check if both arrays are of the same size // Check if both arrays are of the same size
if(const VTypeArray*arr = dynamic_cast<const VTypeArray*>(that)) { if(const VTypeArray*arr = dynamic_cast<const VTypeArray*>(that)) {
if(!element_type()->type_match(arr->element_type())) const VTypeArray*this_parent = this;
while(const VTypeArray*tmp = this_parent->get_parent_type())
this_parent = tmp;
const VTypeArray*that_parent = arr;
while(const VTypeArray*tmp = that_parent->get_parent_type())
that_parent = tmp;
if(this_parent != that_parent)
return false; return false;
int this_width = get_width(NULL); int this_width = get_width(NULL);