Skip to content

Commit

Permalink
Generalize user defined function return type handling.
Browse files Browse the repository at this point in the history
I'm gonna need functions to return class objects, so generalize
the output types of user defined functions.
  • Loading branch information
steveicarus committed Apr 20, 2013
1 parent c4257ec commit 20ee350
Show file tree
Hide file tree
Showing 27 changed files with 239 additions and 459 deletions.
4 changes: 2 additions & 2 deletions PFunction.cc
Expand Up @@ -25,7 +25,7 @@ PFunction::PFunction(perm_string name, LexicalScope*parent, bool is_auto__)
: PTaskFunc(name, parent), statement_(0)
{
is_auto_ = is_auto__;
return_type_.type = PTF_NONE;
return_type_ = 0;
}

PFunction::~PFunction()
Expand All @@ -39,7 +39,7 @@ void PFunction::set_statement(Statement*s)
statement_ = s;
}

void PFunction::set_return(PTaskFuncArg t)
void PFunction::set_return(const data_type_t*t)
{
return_type_ = t;
}
22 changes: 2 additions & 20 deletions PTask.h
Expand Up @@ -32,24 +32,6 @@ class PWire;
class Statement;
class PExpr;

enum PTaskFuncEnum {
PTF_NONE,
PTF_REG,
PTF_REG_S,
PTF_INTEGER,
PTF_REAL,
PTF_REALTIME,
PTF_TIME,
PTF_ATOM2,
PTF_ATOM2_S,
PTF_STRING,
PTF_VOID
};

struct PTaskFuncArg {
PTaskFuncEnum type;
std::list<pform_range_t>*range;
};

class PTaskFunc : public PScope, public LineInfo {

Expand Down Expand Up @@ -126,7 +108,7 @@ class PFunction : public PTaskFunc {
~PFunction();

void set_statement(Statement *s);
void set_return(PTaskFuncArg t);
void set_return(const data_type_t*t);

void elaborate_scope(Design*des, NetScope*scope) const;

Expand All @@ -141,7 +123,7 @@ class PFunction : public PTaskFunc {
void dump(ostream&, unsigned) const;

private:
PTaskFuncArg return_type_;
const data_type_t* return_type_;
Statement *statement_;
bool is_auto_;
};
Expand Down
15 changes: 14 additions & 1 deletion PWire.cc
Expand Up @@ -120,6 +120,7 @@ bool PWire::set_data_type(ivl_variable_type_t dt)

assert(data_type_ == IVL_VT_NO_TYPE);
data_type_ = dt;

return true;
}

Expand All @@ -140,7 +141,14 @@ bool PWire::get_signed() const

bool PWire::get_isint() const
{
return isint_;
if (isint_)
return true;

if (vector_type_t*tmp = dynamic_cast<vector_type_t*>(set_data_type_)) {
return tmp->integer_flag;
}

return false;
}

bool PWire::get_scalar() const
Expand Down Expand Up @@ -257,6 +265,11 @@ void PWire::set_data_type(data_type_t*type)
{
assert(set_data_type_ == 0);
set_data_type_ = type;

if (vector_type_t*tmp = dynamic_cast<vector_type_t*>(type)) {
if (tmp->integer_flag)
isint_ = true;
}
}

void PWire::set_discipline(ivl_discipline_t d)
Expand Down
22 changes: 11 additions & 11 deletions elab_expr.cc
Expand Up @@ -1134,7 +1134,7 @@ unsigned PECallFunction::test_width_method_(Design*des, NetScope*scope,
<< endl;
}

netclass_t* class_type = net->class_type();
const netclass_t* class_type = net->class_type();
member_type = class_type->get_property(member_name);
use_path = tmp_path;

Expand Down Expand Up @@ -1164,7 +1164,7 @@ unsigned PECallFunction::test_width_method_(Design*des, NetScope*scope,
return expr_width_;
}

if (netclass_t*class_type = net->class_type()) {
if (const netclass_t*class_type = net->class_type()) {
cerr << get_fileline() << ": PECallFunction::test_width_method_: "
<< "Try to find method " << method_name
<< " of class " << class_type->get_name() << endl;
Expand Down Expand Up @@ -1425,7 +1425,7 @@ NetExpr* PECallFunction::elaborate_access_func_(Design*des, NetScope*scope,
*/
static NetExpr* check_for_enum_methods(const LineInfo*li,
Design*des, NetScope*scope,
netenum_t*netenum,
const netenum_t*netenum,
pform_name_t use_path,
perm_string method_name,
NetExpr*expr,
Expand Down Expand Up @@ -1760,7 +1760,7 @@ static NetExpr* check_for_class_property(const LineInfo*li,
NetNet*net,
const name_component_t&comp)
{
netclass_t*class_type = net->class_type();
const netclass_t*class_type = net->class_type();
const ivl_type_s*ptype = class_type->get_property(comp.name);

if (ptype == 0) {
Expand Down Expand Up @@ -2055,7 +2055,7 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
}
}

if (netenum_t*netenum = net->enumeration()) {
if (const netenum_t*netenum = net->enumeration()) {
// We may need the net expression for the
// enumeration variable so get it.
NetESignal*expr = new NetESignal(net);
Expand All @@ -2082,7 +2082,7 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
}
}

if (netclass_t*class_type = net->class_type()) {
if (const netclass_t*class_type = net->class_type()) {
NetScope*func = class_type->method_from_name(method_name);
if (func == 0) {
return 0;
Expand Down Expand Up @@ -2595,7 +2595,7 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
ivl_assert(*this, 0);
}

if (netdarray_t*darray = net? net->darray_type() : 0) {
if (const netdarray_t*darray = net? net->darray_type() : 0) {
if (use_sel == index_component_t::SEL_BIT) {
expr_type_ = darray->element_base_type();
expr_width_ = darray->element_width();
Expand Down Expand Up @@ -2637,7 +2637,7 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
// The width of an enumeration literal is the width of the
// enumeration base.
if (const NetEConstEnum*par_enum = dynamic_cast<const NetEConstEnum*> (par)) {
netenum_t*use_enum = par_enum->enumeration();
const netenum_t*use_enum = par_enum->enumeration();
ivl_assert(*this, use_enum != 0);

expr_type_ = use_enum->base_type();
Expand Down Expand Up @@ -2714,7 +2714,7 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
}
}

if (netclass_t*class_type = net->class_type()) {
if (const netclass_t*class_type = net->class_type()) {
const ivl_type_s*ptype = class_type->get_property(method_name);
if (ptype) {
expr_type_ = ptype->base_type();
Expand Down Expand Up @@ -3037,7 +3037,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
if (net != 0) {
// If this net is actually an enum, the method may
// be an enumeration method.
if (netenum_t*netenum = net->enumeration()) {
if (const netenum_t*netenum = net->enumeration()) {
// We may need the net expression for the
// enumeration variable so get it.
NetESignal*expr = new NetESignal(net);
Expand Down Expand Up @@ -4177,7 +4177,7 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,

NetExpr*mux = elab_and_eval(des, scope, index_tail.msb, -1, need_const);

if (netdarray_t*darray = net->sig()->darray_type()) {
if (const netdarray_t*darray = net->sig()->darray_type()) {
// Special case: This is a select of a dynamic
// array. Generate a NetESelect and attach it to
// the NetESignal. This should be interpreted as
Expand Down
4 changes: 2 additions & 2 deletions elab_lval.cc
Expand Up @@ -790,12 +790,12 @@ bool PEIdent::elaborate_lval_net_class_member_(Design*des, NetScope*,
<< " of " << lv->sig()->name() << "." << endl;
}

netclass_t*class_type = lv->sig()->class_type();
const netclass_t*class_type = lv->sig()->class_type();
ivl_assert(*this, class_type);

/* Make sure the property is really present in the class. If
not, then generate an error message and return an error. */
const ivl_type_s*ptype = class_type->get_property(method_name);
ivl_type_t ptype = class_type->get_property(method_name);
if (ptype == 0) {
cerr << get_fileline() << ": error: Class " << class_type->get_name()
<< " does not have a property " << method_name << "." << endl;
Expand Down
2 changes: 2 additions & 0 deletions elab_scope.cc
Expand Up @@ -280,6 +280,8 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
if (cur_value.is_defined())
cur_value = cur_value + one_value;
}

use_enum->insert_name_close();
}

static void elaborate_scope_enumerations(Design*des, NetScope*scope,
Expand Down
153 changes: 13 additions & 140 deletions elab_sig.cc
Expand Up @@ -537,147 +537,20 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const

elaborate_sig_wires_(des, scope);

NetNet*ret_sig = 0;
netvector_t*ret_vec = 0;

/* Create the signals/variables of the return value and write
them into the function scope. */
switch (return_type_.type) {

case PTF_REG:
case PTF_REG_S:
if (return_type_.range) {
ivl_assert(*this, return_type_.range->size() == 1);
pform_range_t&return_range = return_type_.range->front();

NetExpr*me = elab_and_eval(des, scope,
return_range.first, -1,
true);
assert(me);
NetExpr*le = elab_and_eval(des, scope,
return_range.second, -1,
true);
assert(le);

long mnum = 0, lnum = 0;
if ( ! get_const_argument(me, mnum) ) {
cerr << me->get_fileline() << ": error: "
"Unable to evaluate constant expression "
<< *me << "." << endl;
des->errors += 1;
}

if ( ! get_const_argument(le, lnum) ) {
cerr << le->get_fileline() << ": error: "
"Unable to evaluate constant expression "
<< *le << "." << endl;
des->errors += 1;
}
ivl_type_t ret_type;

vector<netrange_t> packed;
packed.push_back(netrange_t(mnum, lnum));
ret_vec = new netvector_t(packed, IVL_VT_LOGIC);
ret_vec->set_signed(return_type_.type == PTF_REG_S);
ret_vec->set_scalar(false);
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec);

} else {
ret_vec = new netvector_t(IVL_VT_LOGIC);
ret_vec->set_signed(return_type_.type == PTF_REG_S);
ret_vec->set_scalar(true);
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec);
}
ret_sig->set_line(*this);
ret_sig->port_type(NetNet::POUTPUT);
break;

case PTF_INTEGER:
ret_vec = new netvector_t(IVL_VT_LOGIC, integer_width-1,0);
ret_vec->set_signed(true);
ret_vec->set_isint(true);
ret_vec->set_scalar(false);
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec);
ret_sig->set_line(*this);
ret_sig->port_type(NetNet::POUTPUT);
break;

case PTF_TIME:
ret_vec = new netvector_t(IVL_VT_LOGIC, 64-1,0);
ret_vec->set_isint(false);
ret_vec->set_scalar(false);
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec);
ret_sig->set_line(*this);
ret_sig->port_type(NetNet::POUTPUT);
break;

case PTF_REAL:
case PTF_REALTIME:
ret_vec = new netvector_t(IVL_VT_REAL);
ret_vec->set_signed(true);
ret_vec->set_isint(false);
ret_vec->set_scalar(true);
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec);
ret_sig->set_line(*this);
ret_sig->port_type(NetNet::POUTPUT);
break;

case PTF_ATOM2:
case PTF_ATOM2_S:
long use_wid;
{
ivl_assert(*this, return_type_.range->size() == 1);
pform_range_t&return_range = return_type_.range->front();
NetExpr*me = elab_and_eval(des, scope,
return_range.first, -1,
true);
ivl_assert(*this, me);
NetExpr*le = elab_and_eval(des, scope,
return_range.second, -1,
true);
ivl_assert(*this, le);

long mnum = 0, lnum = 0;
if ( ! get_const_argument(me, mnum) ) {
cerr << me->get_fileline() << ": error: "
"Unable to evaluate constant expression "
<< *me << "." << endl;
des->errors += 1;
}

if ( ! get_const_argument(le, lnum) ) {
cerr << le->get_fileline() << ": error: "
"Unable to evaluate constant expression "
<< *le << "." << endl;
des->errors += 1;
}

use_wid = mnum - lnum + 1;
}
ret_vec = new netvector_t(IVL_VT_BOOL, use_wid-1, 0);
ret_vec->set_isint(true);
ret_vec->set_scalar(false);
ret_vec->set_signed(return_type_.type == PTF_ATOM2_S? true : false);
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec);
ret_sig->set_line(*this);
ret_sig->port_type(NetNet::POUTPUT);
break;

case PTF_STRING:
cerr << get_fileline() << ": sorry: String functions are not supported yet" << endl;
break;

case PTF_VOID:
// Void functions have no return value, so there is no
// signal to create here.
break;

default:
/* If we do not have any ports or a return type this
* is probably a bad function definition. */
cerr << get_fileline() << ": error: Bad definition for "
<< "function " << scope->basename() << "?" << endl;
return;
if (return_type_) {
ret_type = return_type_->elaborate_type(des, scope);
} else {
netvector_t*tmp = new netvector_t(IVL_VT_LOGIC);
tmp->set_scalar(true);
ret_type = tmp;
}
list<netrange_t> ret_unpacked;
NetNet*ret_sig = new NetNet(scope, fname, NetNet::REG, ret_unpacked, ret_type);

ret_sig->set_line(*this);
ret_sig->port_type(NetNet::POUTPUT);

vector<NetNet*>ports;
elaborate_sig_ports_(des, scope, ports);
Expand Down Expand Up @@ -1290,7 +1163,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const

} else if (enum_type_t*enum_type = dynamic_cast<enum_type_t*>(set_data_type_)) {
list<named_pexpr_t>::const_iterator sample_name = enum_type->names->begin();
netenum_t*use_enum = scope->enumeration_for_name(sample_name->name);
const netenum_t*use_enum = scope->enumeration_for_name(sample_name->name);

if (debug_elaborate) {
cerr << get_fileline() << ": debug: Create signal " << wtype
Expand Down

0 comments on commit 20ee350

Please sign in to comment.