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;
out << "// " << get_fileline() << endl;
out << "always @(";
out << "always begin" << endl;
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();
it != options_.end(); ++it) {
ExpConditional::case_t*cas = *it;
@ -192,6 +179,21 @@ int CondSignalAssignment::emit(ostream&out, Entity*ent, Architecture*arc)
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;
return errors;

View File

@ -436,29 +436,6 @@ void ExpRelation::dump(ostream&out, int indent) const
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
{
out << setw(indent) << "" << name_ << "=>";

View File

@ -24,6 +24,7 @@
# include "subprogram.h"
# include "parse_types.h"
# include "scope.h"
# include "library.h"
# include <iostream>
# include <typeinfo>
# include <cstring>
@ -569,6 +570,32 @@ const VType* ExpFunc::func_ret_type() const
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)
: value_(val)
{
@ -818,6 +845,15 @@ ExpUNot::~ExpUNot()
{
}
ExpUMinus::ExpUMinus(Expression*op1)
: ExpUnary(op1)
{
}
ExpUMinus::~ExpUMinus()
{
}
ExpCast::ExpCast(Expression*base, const VType*type) :
base_(base), type_(type)
{

View File

@ -620,12 +620,15 @@ class ExpFunc : public Expression {
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;
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:
perm_string name_;
std::vector<Expression*> argv_;
SubprogramHeader*def_;
mutable SubprogramHeader*def_;
};
class ExpInteger : public Expression {
@ -948,6 +951,19 @@ class ExpUNot : public ExpUnary {
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.
*/

View File

@ -119,6 +119,35 @@ void ExpShift::dump(ostream&out, int indent) const
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
{
out << setw(indent) << "" << "Time ";

View File

@ -26,7 +26,6 @@
# include "entity.h"
# include "vsignal.h"
# include "subprogram.h"
# include "library.h"
# include "std_types.h"
# include <iostream>
# 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
// also an array, but with different bounds.
int64_t use_msb, use_lsb;
bool flag;
bool flag = true;
flag = range->msb()->evaluate(ent, scope, use_msb);
ivl_assert(*this, flag);
flag = range->lsb()->evaluate(ent, scope, use_lsb);
ivl_assert(*this, flag);
flag &= range->msb()->evaluate(ent, scope, use_msb);
flag &= range->lsb()->evaluate(ent, scope, use_lsb);
if(flag)
type = new VTypeArray(array->element_type(), use_msb, use_lsb);
}
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_lsb = prange->lsb();
ivl_assert(*this, host->dimensions() == 1);
ivl_assert(*this, host->dimensions().size() == 1);
vector<VTypeArray::range_t> range (1);
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
{
// Ranges
while (const VTypeRange*tmp = dynamic_cast<const VTypeRange*> (t1))
t1 = tmp->base_type();
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))
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;
}
@ -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])) {
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);
sizes[i] = new ExpArithmetic(ExpArithmetic::MINUS, dim.msb(), dim.lsb());
} else {
@ -733,7 +783,7 @@ int ExpConcat::elaborate_expr_array_(Entity*ent, ScopeBase*scope, const VTypeArr
int errors = 0;
// 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);
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
{
SubprogramHeader*prog = def_;
if(!def_)
def_ = match_signature(ent, scope);
if(!prog) {
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();
return def_ ? def_->exact_return_type(argv_, ent, scope) : NULL;
}
int ExpFunc::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*)
{
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
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);
def_ = match_signature(ent, scope);
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;
}
// Elaborate arguments
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.
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);
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 errors = 0;
assert(arr->dimensions() == 1);
assert(arr->dimensions().size() == 1);
const VTypePrimitive*etype = dynamic_cast<const VTypePrimitive*> (arr->basic_type());
assert(etype);
@ -1048,6 +1048,15 @@ int ExpUNot::emit(ostream&out, Entity*ent, ScopeBase*scope) const
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 errors = 0;

View File

@ -85,7 +85,7 @@ bool ExpAttribute::test_array_type(const VType*type) const
return false;
}
if (arr->dimensions() > 1) {
if (arr->dimensions().size() > 1) {
cerr << endl << get_fileline() << ": error: "
<< "Cannot apply the '" << name_
<< " attribute to multidimensional arrays" << endl;
@ -144,19 +144,6 @@ bool ExpName::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const
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) {
const VType*type;
Expression*exp;

View File

@ -327,6 +327,13 @@ void ExpUNot::write_to_stream(ostream&fd) const
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
{
// Type casting is introduced only for a few specific cases in

View File

@ -25,6 +25,7 @@
# include "compiler.h"
# include "package.h"
# include "std_types.h"
# include "std_funcs.h"
# include <fstream>
# include <list>
# 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_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 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.
if (use_library == "ieee") {
import_ieee_use(res, use_package, use_name);
import_ieee_use(loc, res, use_package, use_name);
return;
}
// 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)
@ -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") {
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") {
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;
}
@ -361,9 +394,11 @@ static void import_ieee_use(ActiveScope*res, perm_string package, perm_string na
import_ieee_use_numeric_std(res, name);
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") {
// 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);
return;
} 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;
}
}

View File

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

View File

@ -24,7 +24,7 @@
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);
}
@ -68,28 +68,51 @@ class SubprogramSizeCast : public SubprogramStdHeader {
: SubprogramStdHeader(nam, NULL, target) {
ports_ = new list<InterfacePort*>();
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,
std::ostream&out, Entity*ent, ScopeBase*scope) 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 << "'";
int emit_name(const std::vector<Expression*>&,
std::ostream&, Entity*, ScopeBase*) const {
return 0;
}
int emit_args(const std::vector<Expression*>&argv,
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.
*/
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"),
empty_perm_string,
args, &primitive_STDLOGIC_VECTOR));
@ -215,6 +244,13 @@ void preload_std_funcs(void)
* function shift_right (arg: signed; count: natural) return signed;
*/
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_NATURAL));
register_std_subprogram(new SubprogramBuiltin(perm_string::literal("shift_right"),
@ -224,12 +260,16 @@ void preload_std_funcs(void)
/* function 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
* 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));
/* numeric_bit library

View File

@ -28,6 +28,9 @@ void preload_std_funcs();
// Destroys subprogram headers for standard VHDL library functions.
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.
SubHeaderList find_std_subprogram(perm_string name);

View File

@ -172,6 +172,24 @@ const VType*SubprogramHeader::peek_param_type(int idx) const
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 {
if(return_type_ && return_type_->is_unbounded())
return true;

View File

@ -80,6 +80,10 @@ class SubprogramHeader : public LineInfo {
const VType*peek_param_type(int idx) const;
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 const Package*get_package() const { return package_; }

View File

@ -226,7 +226,7 @@ class VTypeArray : public VType {
void show(std::ostream&) 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
{ return ranges_[idx]; }
@ -253,6 +253,8 @@ class VTypeArray : public VType {
// To handle subtypes
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
// constant integers.
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);
if (base) {
assert(dimensions() == 1);
assert(dimensions().size() == 1);
// If this is a string type without any boundaries specified, then
// 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;
}
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) {
emit_name(out, name);
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
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;
int this_width = get_width(NULL);