commit
301e85a8ca
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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_ << "=>";
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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 ";
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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_; }
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue