Generalize user defined function return type handling.

I'm gonna need functions to return class objects, so generalize
the output types of user defined functions.
This commit is contained in:
Stephen Williams 2013-04-14 18:03:21 -07:00
parent c4257ecfc9
commit 20ee350601
27 changed files with 239 additions and 459 deletions

View File

@ -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()
@ -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
PTask.h
View File

@ -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 {
@ -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;
@ -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_;
};

View File

@ -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;
}
@ -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
@ -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)

View File

@ -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;
@ -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;
@ -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,
@ -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) {
@ -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);
@ -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;
@ -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();
@ -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();
@ -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();
@ -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);
@ -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

View File

@ -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;

View File

@ -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,

View File

@ -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;
ivl_type_t ret_type;
/* 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;
}
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);
@ -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

View File

@ -23,6 +23,7 @@
# include "netdarray.h"
# include "netscalar.h"
# include "netvector.h"
# include "netmisc.h"
# include <typeinfo>
# include "ivl_assert.h"
@ -77,6 +78,42 @@ ivl_type_s* class_type_t::elaborate_type(Design*, NetScope*scope) const
return scope->find_class(name);
}
ivl_type_s* vector_type_t::elaborate_type(Design*des, NetScope*scope) const
{
vector<netrange_t> packed;
if (pdims.get()) {
for (list<pform_range_t>::const_iterator cur = pdims->begin()
; cur != pdims->end() ; ++ cur) {
NetExpr*me = elab_and_eval(des, scope, cur->first, 0, true);
assert(me);
NetExpr*le = elab_and_eval(des, scope, cur->second, 0, true);
assert(le);
long mnum = 0, lnum = 0;
if ( ! eval_as_long(mnum, me) ) {
assert(0);
des->errors += 1;
}
if ( ! eval_as_long(lnum, le) ) {
assert(0);
des->errors += 1;
}
packed.push_back(netrange_t(mnum, lnum));
}
}
netvector_t*tmp = new netvector_t(packed, base_type);
tmp->set_signed(signed_flag);
tmp->set_isint(integer_flag);
return tmp;
}
ivl_type_s* real_type_t::elaborate_type(Design*, NetScope*) const
{
switch (type_code) {

View File

@ -3314,7 +3314,7 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope) const
return sys;
}
if (netclass_t*class_type = net->class_type()) {
if (const netclass_t*class_type = net->class_type()) {
NetScope*task = class_type->method_from_name(method_name);
if (task == 0) {
cerr << get_fileline() << ": internal error: "

View File

@ -165,7 +165,7 @@ typedef struct ivl_branch_s *ivl_branch_t;
typedef struct ivl_delaypath_s*ivl_delaypath_t;
typedef struct ivl_design_s *ivl_design_t;
typedef _CLASS ivl_discipline_s*ivl_discipline_t;
typedef _CLASS netenum_t *ivl_enumtype_t;
typedef const _CLASS netenum_t*ivl_enumtype_t;
typedef struct ivl_event_s *ivl_event_t;
typedef struct ivl_expr_s *ivl_expr_t;
typedef struct ivl_island_s *ivl_island_t;

View File

@ -102,7 +102,7 @@ unsigned NetAssign_::lwidth() const
return ptype->packed_width();
}
if (netdarray_t*darray = sig_->darray_type()) {
if (const netdarray_t*darray = sig_->darray_type()) {
if (word_ == 0)
return 1;
else
@ -122,7 +122,7 @@ ivl_variable_type_t NetAssign_::expr_type() const
return tmp->base_type();
}
if (netdarray_t*darray = sig_->darray_type()) {
if (const netdarray_t*darray = sig_->darray_type()) {
if (word_ == 0)
return IVL_VT_DARRAY;
else
@ -153,9 +153,9 @@ const ivl_type_s* NetAssign_::net_type() const
return 0;
}
netenum_t*NetAssign_::enumeration() const
const netenum_t*NetAssign_::enumeration() const
{
netenum_t*tmp = 0;
const netenum_t*tmp = 0;
// If the base signal is not an enumeration, return nil.
if ( (tmp = sig_->enumeration()) == 0 )

View File

@ -64,7 +64,7 @@ ivl_variable_type_t NetExpr::expr_type() const
return IVL_VT_LOGIC;
}
netenum_t*NetExpr::enumeration() const
const netenum_t*NetExpr::enumeration() const
{
return 0;
}
@ -246,7 +246,7 @@ void NetEConcat::set(unsigned idx, NetExpr*e)
expr_width( expr_width() + repeat_ * e->expr_width() );
}
NetEConstEnum::NetEConstEnum(NetScope*s, perm_string n, netenum_t*eset, const verinum&v)
NetEConstEnum::NetEConstEnum(NetScope*s, perm_string n, const netenum_t*eset, const verinum&v)
: NetEConst(v), scope_(s), enum_set_(eset), name_(n)
{
assert(has_width());
@ -256,7 +256,7 @@ NetEConstEnum::~NetEConstEnum()
{
}
netenum_t*NetEConstEnum::enumeration() const
const netenum_t*NetEConstEnum::enumeration() const
{
return enum_set_;
}
@ -307,7 +307,7 @@ const NetScope* NetECRealParam::scope() const
}
NetENetenum::NetENetenum(netenum_t*s)
NetENetenum::NetENetenum(const netenum_t*s)
: netenum_(s)
{
}
@ -316,7 +316,7 @@ NetENetenum::~NetENetenum()
{
}
netenum_t* NetENetenum::netenum() const
const netenum_t* NetENetenum::netenum() const
{
return netenum_;
}
@ -456,7 +456,7 @@ NetESFunc::NetESFunc(const char*n, ivl_type_t rtype, unsigned np)
ivl_assert(*this, 0);
}
NetESFunc::NetESFunc(const char*n, netenum_t*enum_type, unsigned np)
NetESFunc::NetESFunc(const char*n, const netenum_t*enum_type, unsigned np)
: name_(0), type_(enum_type->base_type()), enum_type_(enum_type), parms_(np)
{
name_ = lex_strings.add(n);
@ -506,7 +506,7 @@ ivl_variable_type_t NetESFunc::expr_type() const
return type_;
}
netenum_t* NetESFunc::enumeration() const
const netenum_t* NetESFunc::enumeration() const
{
return enum_type_;
}

View File

@ -570,7 +570,7 @@ bool NetScope::add_enumeration_name(netenum_t*enum_set, perm_string name)
return cur.second;
}
netenum_t*NetScope::enumeration_for_name(perm_string name)
const netenum_t*NetScope::enumeration_for_name(perm_string name)
{
NetEConstEnum*tmp = enum_names_[name];
assert(tmp != 0);

View File

@ -92,7 +92,7 @@ ivl_type_t netclass_t::get_prop_type(size_t idx) const
return property_table_[idx].type;
}
NetScope*netclass_t::method_from_name(perm_string name)
NetScope*netclass_t::method_from_name(perm_string name) const
{
NetScope*task = class_scope_->child( hname_t(name) );
if (task == 0) return 0;

View File

@ -59,7 +59,7 @@ class netclass_t : public ivl_type_s {
int property_idx_from_name(perm_string pname) const;
// The task method scopes from the method name.
NetScope*method_from_name(perm_string mname);
NetScope*method_from_name(perm_string mname) const;
void elaborate_sig(Design*des, PClass*pclass);
void elaborate(Design*des, PClass*pclass);

View File

@ -73,6 +73,32 @@ bool netenum_t::insert_name(size_t name_idx, perm_string name, const verinum&val
return res.second;
}
void netenum_t::insert_name_close(void)
{
for (size_t idx = 0 ; idx < names_.size() ; idx += 1) {
netenum_t::iterator cur = names_map_.find(names_[idx]);
vector<char>str (cur->second.len() + 1);
for (unsigned bit = 0 ; bit < cur->second.len() ; bit += 1) {
switch (cur->second.get(bit)) {
case verinum::V0:
str[bit] = '0';
break;
case verinum::V1:
str[bit] = '1';
break;
case verinum::Vx:
str[bit] = 'x';
break;
case verinum::Vz:
str[bit] = 'z';
break;
}
}
bits_[idx] = bits_strings.make(&str[0]);
}
}
netenum_t::iterator netenum_t::find_name(perm_string name) const
{
return names_map_.find(name);
@ -115,32 +141,7 @@ perm_string netenum_t::name_at(size_t idx) const
return names_[idx];
}
perm_string netenum_t::bits_at(size_t idx)
perm_string netenum_t::bits_at(size_t idx) const
{
assert(idx < names_.size());
if (bits_[idx] == 0) {
netenum_t::iterator cur = names_map_.find(names_[idx]);
vector<char>str (cur->second.len() + 1);
for (unsigned bit = 0 ; bit < cur->second.len() ; bit += 1) {
switch (cur->second.get(bit)) {
case verinum::V0:
str[bit] = '0';
break;
case verinum::V1:
str[bit] = '1';
break;
case verinum::Vx:
str[bit] = 'x';
break;
case verinum::Vz:
str[bit] = 'z';
break;
}
}
bits_[idx] = bits_strings.make(&str[0]);
}
return bits_[idx];
}

View File

@ -49,6 +49,9 @@ class netenum_t : public LineInfo, public ivl_type_s {
// enumeration value.
bool insert_name(size_t idx, perm_string name, const verinum&val);
// Indicate that there will be no more names to insert.
void insert_name_close(void);
typedef std::map<perm_string,verinum>::const_iterator iterator;
iterator find_name(perm_string name) const;
iterator end_name() const;
@ -59,7 +62,7 @@ class netenum_t : public LineInfo, public ivl_type_s {
iterator last_name() const;
perm_string name_at(size_t idx) const;
perm_string bits_at(size_t idx);
perm_string bits_at(size_t idx) const;
private:
ivl_variable_type_t base_type_;

View File

@ -530,7 +530,7 @@ void NetNet::calculate_slice_widths_from_packed_dims_(void)
}
NetNet::NetNet(NetScope*s, perm_string n, Type t,
const list<netrange_t>&unpacked, ivl_type_s*use_net_type)
const list<netrange_t>&unpacked, ivl_type_t use_net_type)
: NetObj(s, n, calculate_count(unpacked)),
type_(t), port_type_(NOT_A_PORT),
local_flag_(false), net_type_(use_net_type),
@ -762,7 +762,7 @@ bool NetNet::get_signed() const
bool NetNet::get_isint() const
{
if (netvector_t*vec = dynamic_cast<netvector_t*> (net_type_))
if (const netvector_t*vec = dynamic_cast<const netvector_t*> (net_type_))
return vec->get_isint();
else
return false;
@ -770,20 +770,20 @@ bool NetNet::get_isint() const
bool NetNet::get_scalar() const
{
if (netvector_t*vec = dynamic_cast<netvector_t*> (net_type_))
if (const netvector_t*vec = dynamic_cast<const netvector_t*> (net_type_))
return vec->get_scalar();
else
return false;
}
netenum_t*NetNet::enumeration(void) const
const netenum_t*NetNet::enumeration(void) const
{
return dynamic_cast<netenum_t*> (net_type_);
return dynamic_cast<const netenum_t*> (net_type_);
}
const netstruct_t*NetNet::struct_type(void) const
{
const ivl_type_s*cur_type = net_type_;
ivl_type_t cur_type = net_type_;
while (cur_type) {
if (const netdarray_t*da = dynamic_cast<const netdarray_t*> (cur_type)) {
cur_type = da->element_type();
@ -803,14 +803,14 @@ const netstruct_t*NetNet::struct_type(void) const
return 0;
}
netdarray_t* NetNet::darray_type(void) const
const netdarray_t* NetNet::darray_type(void) const
{
return dynamic_cast<netdarray_t*> (net_type_);
return dynamic_cast<const netdarray_t*> (net_type_);
}
netclass_t* NetNet::class_type(void) const
const netclass_t* NetNet::class_type(void) const
{
return dynamic_cast<netclass_t*> (net_type_);
return dynamic_cast<const netclass_t*> (net_type_);
}
/*
@ -2375,7 +2375,7 @@ perm_string NetESignal::name() const
return net_->name();
}
netenum_t* NetESignal::enumeration() const
const netenum_t* NetESignal::enumeration() const
{
return enum_type_;
}

View File

@ -604,7 +604,7 @@ class NetNet : public NetObj, public PortType {
// now, the unpacked type is not burried into an ivl_type_s object.
explicit NetNet(NetScope*s, perm_string n, Type t,
const std::list<netrange_t>&unpacked,
ivl_type_s*type =0);
ivl_type_t type =0);
// This form builds a NetNet from its record/enum/darray
// definition. They should probably be replaced with a single
@ -639,10 +639,10 @@ class NetNet : public NetObj, public PortType {
bool get_scalar() const;
inline const ivl_type_s* net_type(void) const { return net_type_; }
netenum_t*enumeration(void) const;
const netenum_t*enumeration(void) const;
const netstruct_t*struct_type(void) const;
netdarray_t*darray_type(void) const;
netclass_t*class_type(void) const;
const netdarray_t*darray_type(void) const;
const netclass_t*class_type(void) const;
/* Attach a discipline to the net. */
ivl_discipline_t get_discipline() const;
@ -729,7 +729,7 @@ class NetNet : public NetObj, public PortType {
Type type_ : 5;
PortType port_type_ : 3;
bool local_flag_: 1;
ivl_type_s*net_type_;
ivl_type_t net_type_;
ivl_discipline_t discipline_;
std::vector<netrange_t> unpacked_dims_;
@ -848,7 +848,7 @@ class NetScope : public Attrib {
void add_enumeration_set(netenum_t*enum_set);
bool add_enumeration_name(netenum_t*enum_set, perm_string enum_name);
netenum_t* enumeration_for_name(perm_string name);
const netenum_t* enumeration_for_name(perm_string name);
void add_class(netclass_t*class_type);
netclass_t* find_class(perm_string name);
@ -1810,7 +1810,7 @@ class NetExpr : public LineInfo {
// Return the enumeration set that defines this expressions
// enumeration type, or return nil if the expression is not
// part of the enumeration.
virtual netenum_t*enumeration() const;
virtual const netenum_t*enumeration() const;
// This method evaluates the expression and returns an
// equivalent expression that is reduced as far as compile
@ -1903,12 +1903,12 @@ class NetEConstEnum : public NetEConst {
public:
explicit NetEConstEnum(NetScope*scope, perm_string name,
netenum_t*enum_set, const verinum&val);
const netenum_t*enum_set, const verinum&val);
~NetEConstEnum();
perm_string name() const;
const NetScope*scope() const;
netenum_t*enumeration() const;
const netenum_t*enumeration() const;
virtual void expr_scan(struct expr_scan_t*) const;
virtual void dump(ostream&) const;
@ -1917,7 +1917,7 @@ class NetEConstEnum : public NetEConst {
private:
NetScope*scope_;
netenum_t*enum_set_;
const netenum_t*enum_set_;
perm_string name_;
};
@ -2496,7 +2496,7 @@ class NetAssign_ {
// Return the enumeration type of this l-value, or nil if it's
// not an enumeration.
netenum_t*enumeration() const;
const netenum_t*enumeration() const;
// Get the name of the underlying object.
perm_string name() const;
@ -3916,10 +3916,10 @@ class NetEEvent : public NetExpr {
class NetENetenum : public NetExpr {
public:
NetENetenum(netenum_t*);
NetENetenum(const netenum_t*);
~NetENetenum();
netenum_t* netenum() const;
const netenum_t* netenum() const;
virtual void expr_scan(struct expr_scan_t*) const;
virtual NetENetenum* dup_expr() const;
@ -3928,7 +3928,7 @@ class NetENetenum : public NetExpr {
virtual void dump(ostream&os) const;
private:
netenum_t*netenum_;
const netenum_t*netenum_;
};
class NetENew : public NetExpr {
@ -4032,7 +4032,7 @@ class NetESFunc : public NetExpr {
NetESFunc(const char*name, ivl_variable_type_t t,
unsigned width, unsigned nprms);
NetESFunc(const char*name, ivl_type_t rtype, unsigned nprms);
NetESFunc(const char*name, netenum_t*enum_type, unsigned nprms);
NetESFunc(const char*name, const netenum_t*enum_type, unsigned nprms);
~NetESFunc();
const char* name() const;
@ -4048,7 +4048,7 @@ class NetESFunc : public NetExpr {
virtual ivl_variable_type_t expr_type() const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual netenum_t* enumeration() const;
virtual const netenum_t* enumeration() const;
virtual void dump(ostream&) const;
virtual void expr_scan(struct expr_scan_t*) const;
@ -4073,7 +4073,7 @@ class NetESFunc : public NetExpr {
const char* name_;
ivl_variable_type_t type_;
netenum_t*enum_type_;
const netenum_t*enum_type_;
std::vector<NetExpr*>parms_;
ID built_in_id_() const;
@ -4252,7 +4252,7 @@ class NetESignal : public NetExpr {
virtual NetESignal* dup_expr() const;
NetNet* synthesize(Design*des, NetScope*scope, NetExpr*root);
NexusSet* nex_input(bool rem_out = true);
netenum_t*enumeration() const;
const netenum_t*enumeration() const;
virtual NetExpr*evaluate_function(const LineInfo&loc,
map<perm_string,LocalVar>&ctx) const;
@ -4277,7 +4277,7 @@ class NetESignal : public NetExpr {
private:
NetNet*net_;
netenum_t*enum_type_;
const netenum_t*enum_type_;
// Expression to select a word from the net.
NetExpr*word_;
};

144
parse.y
View File

@ -385,8 +385,6 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
Statement*statement;
vector<Statement*>*statement_list;
PTaskFuncArg function_type;
net_decl_assign_t*net_decl_assign;
enum_type_t*enum_type;
@ -596,7 +594,6 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
%type <vartype> integer_vector_type
%type <parmvalue> parameter_value_opt
%type <function_type> function_range_or_type_opt
%type <event_expr> event_expression_list
%type <event_expr> event_expression
%type <event_statement> event_control
@ -761,27 +758,36 @@ class_items /* IEEE1800-2005: A.1.2 */
class_item /* IEEE1800-2005: A.1.8 */
/* IEEE1800 A.1.8: class_constructor_declaration */
: method_qualifier_opt K_function K_new '(' tf_port_list_opt ')' ';'
: method_qualifier_opt K_function K_new
{ assert(current_function==0);
current_function = pform_push_constructor_scope(@3);
}
'(' tf_port_list_opt ')' ';'
function_item_list_opt
statement_or_null_list_opt
K_endfunction endnew_opt
{ yyerror(@3, "sorry: Class constructors not supported yet.");
yyerrok;
{ current_function->set_ports($6);
pform_set_constructor_return(current_function);
pform_set_this_class(@3, current_function);
current_function_set_statement($10? @10 : @3, $10);
pform_pop_scope();
current_function = 0;
}
/* IEEE1800 A.1.8: class_constructor_declaration with a call to
parent constructor. Note that the implicit_class_handle must
be K_super ("this.new" makes little sense) but that would
cause a conflict. */
/* XXXX
| method_qualifier_opt K_function K_new '(' tf_port_list_opt ')' ';'
function_item_list_opt
attribute_list_opt implicit_class_handle '.' K_new '(' expression_list_with_nuls ')'
statement_or_null_list_opt
K_endfunction endnew_opt
{ yyerror(@3, "sorry: Class constructors not supported yet.");
{ yyerror(@3, "sorry: Class constructors with parent not supported yet.");
yyerrok;
}
*/
/* Class properties... */
| property_qualifier_opt data_type list_of_variable_decl_assignments ';'
@ -934,6 +940,19 @@ data_type /* IEEE1800-2005: A.2.2.1 */
FILE_NAME(tmp, @1);
$$ = tmp;
}
| K_integer signed_unsigned_opt
{ list<pform_range_t>*pd = make_range_from_width(integer_width);
vector_type_t*tmp = new vector_type_t(IVL_VT_LOGIC, $2, pd);
tmp->reg_flag = true;
tmp->integer_flag = true;
$$ = tmp;
}
| K_time
{ list<pform_range_t>*pd = make_range_from_width(64);
vector_type_t*tmp = new vector_type_t(IVL_VT_LOGIC, true, pd);
tmp->reg_flag = true;
$$ = tmp;
}
| TYPE_IDENTIFIER range_opt
{ if ($2) $$ = new parray_type_t($1, $2);
else $$ = $1;
@ -1045,7 +1064,7 @@ for_step /* IEEE1800-2005: A.6.8 */
definitions in the func_body to take on the scope of the function
instead of the module. */
function_declaration /* IEEE1800-2005: A.2.6 */
: K_function K_automatic_opt function_range_or_type_opt IDENTIFIER ';'
: K_function K_automatic_opt data_type_or_implicit IDENTIFIER ';'
{ assert(current_function == 0);
current_function = pform_push_function_scope(@1, $4, $2);
}
@ -1070,7 +1089,7 @@ function_declaration /* IEEE1800-2005: A.2.6 */
if ($11) delete[]$11;
}
| K_function K_automatic_opt function_range_or_type_opt IDENTIFIER
| K_function K_automatic_opt data_type_or_implicit IDENTIFIER
{ assert(current_function == 0);
current_function = pform_push_function_scope(@1, $4, $2);
}
@ -1102,7 +1121,7 @@ function_declaration /* IEEE1800-2005: A.2.6 */
/* Detect and recover from some errors. */
| K_function K_automatic_opt function_range_or_type_opt IDENTIFIER error K_endfunction
| K_function K_automatic_opt data_type_or_implicit IDENTIFIER error K_endfunction
{ /* */
if (current_function) {
pform_pop_scope();
@ -1705,58 +1724,7 @@ tf_port_declaration /* IEEE1800-2005: A.2.7 */
tf_port_item /* IEEE1800-2005: A.2.7 */
/* Ports can be integer with a width of [31:0]. */
: port_direction_opt K_integer IDENTIFIER range_opt tf_port_item_expr_opt
{ list<pform_range_t>*range_stub = make_range_from_width(integer_width);
NetNet::PortType use_port_type = $1==NetNet::PIMPLICIT? NetNet::PINPUT : $1;
port_declaration_context.port_type = use_port_type;
port_declaration_context.var_type = IVL_VT_LOGIC;
port_declaration_context.sign_flag = true;
delete port_declaration_context.range;
port_declaration_context.range = copy_range(range_stub);
vector<PWire*>*tmp = pform_make_task_ports(@3, use_port_type,
IVL_VT_LOGIC, true,
range_stub,
list_from_identifier($3), true);
$$ = tmp;
if ($4) {
yyerror(@4, "sorry: Port variable dimensions not supported yet.");
delete $4;
}
if ($5) {
yyerror(@5, "sorry: Port default expressions not supported yet.");
delete $5;
}
}
/* Ports can be time with a width of [63:0] (unsigned). */
| port_direction_opt K_time IDENTIFIER range_opt tf_port_item_expr_opt
{ list<pform_range_t>*range_stub = make_range_from_width(64);
NetNet::PortType use_port_type = $1==NetNet::PIMPLICIT? NetNet::PINPUT : $1;
port_declaration_context.port_type = use_port_type;
port_declaration_context.var_type = IVL_VT_LOGIC;
port_declaration_context.sign_flag = false;
delete port_declaration_context.range;
port_declaration_context.range = copy_range(range_stub);
vector<PWire*>*tmp = pform_make_task_ports(@3, use_port_type, IVL_VT_LOGIC,
false, range_stub,
list_from_identifier($3));
$$ = tmp;
if ($4) {
yyerror(@4, "sorry: Port variable dimensions not supported yet.");
delete $4;
}
if ($5) {
yyerror(@5, "sorry: Port default expressions not supported yet.");
delete $5;
}
}
| port_direction_opt data_type_or_implicit IDENTIFIER range_opt tf_port_item_expr_opt
: port_direction_opt data_type_or_implicit IDENTIFIER range_opt tf_port_item_expr_opt
{ vector<PWire*>*tmp;
NetNet::PortType use_port_type = $1==NetNet::PIMPLICIT? NetNet::PINPUT : $1;
list<perm_string>* ilist = list_from_identifier($3);
@ -1987,22 +1955,10 @@ attribute
block_item_decl
/* Integer atom declarations are simpler in that they do not have
all the trappings of a general variable declaration. All of that
is implicit in the "integer" of the declaration. */
: K_integer signed_unsigned_opt register_variable_list ';'
{ pform_set_reg_integer($3, attributes_in_context);
}
| K_time register_variable_list ';'
{ pform_set_reg_time($2, attributes_in_context);
}
/* variable declarations. Note that data_type can be 0 if we are
recovering from an error. */
| data_type register_variable_list ';'
: data_type register_variable_list ';'
{ if ($1) pform_set_data_type(@1, $1, $2, NetNet::REG, attributes_in_context);
}
@ -5006,42 +4962,6 @@ dimensions
}
;
/* This is used to express the return type of a function. This is
not quite right, and should be replaced with a variant that uses
the data_type rule. This will get us by for now. */
function_range_or_type_opt
: unsigned_signed_opt range_opt
{ /* the default type is reg unsigned and no range */
$$.type = PTF_REG;
$$.range = $2;
if ($1)
$$.type = PTF_REG_S;
}
| K_reg unsigned_signed_opt range_opt
{ /* the default type is reg unsigned and no range */
$$.type = PTF_REG;
$$.range = $3;
if ($2)
$$.type = PTF_REG_S;
}
| bit_logic unsigned_signed_opt range_opt
{ /* the default type is bit/logic unsigned and no range */
$$.type = PTF_REG;
$$.range = $3;
if ($2)
$$.type = PTF_REG_S;
}
| K_integer { $$.range = 0; $$.type = PTF_INTEGER; }
| K_real { $$.range = 0; $$.type = PTF_REAL; }
| K_realtime { $$.range = 0; $$.type = PTF_REALTIME; }
| K_string { $$.range = 0; $$.type = PTF_STRING; }
| K_time { $$.range = 0; $$.type = PTF_TIME; }
| K_void { $$.range = 0; $$.type = PTF_VOID; }
| atom2_type { $$.range = make_range_from_width($1); $$.type = PTF_ATOM2_S; }
| atom2_type K_signed { $$.range = make_range_from_width($1); $$.type = PTF_ATOM2_S; }
| atom2_type K_unsigned { $$.range = make_range_from_width($1); $$.type = PTF_ATOM2; }
;
/* The register_variable rule is matched only when I am parsing
variables in a "reg" definition. I therefore know that I am
creating registers and I do not need to let the containing rule

View File

@ -368,7 +368,7 @@ PTask* pform_push_task_scope(const struct vlltype&loc, char*name, bool is_auto)
return task;
}
PFunction* pform_push_function_scope(const struct vlltype&loc, char*name,
PFunction* pform_push_function_scope(const struct vlltype&loc, const char*name,
bool is_auto)
{
perm_string func_name = lex_strings.make(name);
@ -2932,57 +2932,6 @@ void pform_set_port_type(const struct vlltype&li,
delete range;
}
static void pform_set_reg_integer(perm_string name, list<named_pexpr_t>*attr)
{
PWire*cur = pform_get_make_wire_in_scope(name, NetNet::INTEGER, NetNet::NOT_A_PORT, IVL_VT_LOGIC);
assert(cur);
pform_range_t rng;
rng.first = new PENumber(new verinum(integer_width-1, integer_width));
rng.second = new PENumber(new verinum((uint64_t)0, integer_width));
list<pform_range_t>rlist;
rlist.push_back(rng);
cur->set_range(rlist, SR_NET);
cur->set_signed(true);
pform_bind_attributes(cur->attributes, attr, true);
}
void pform_set_reg_integer(list<perm_string>*names, list<named_pexpr_t>*attr)
{
for (list<perm_string>::iterator cur = names->begin()
; cur != names->end() ; ++ cur ) {
perm_string txt = *cur;
pform_set_reg_integer(txt, attr);
}
delete names;
}
static void pform_set_reg_time(perm_string name, list<named_pexpr_t>*attr)
{
PWire*cur = pform_get_make_wire_in_scope(name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_LOGIC);
assert(cur);
pform_range_t rng;
rng.first = new PENumber(new verinum(TIME_WIDTH-1, integer_width));
rng.second = new PENumber(new verinum((uint64_t)0, integer_width));
list<pform_range_t>rlist;
rlist.push_back(rng);
cur->set_range(rlist, SR_NET);
pform_bind_attributes(cur->attributes, attr, true);
}
void pform_set_reg_time(list<perm_string>*names, list<named_pexpr_t>*attr)
{
for (list<perm_string>::iterator cur = names->begin()
; cur != names->end() ; ++ cur ) {
perm_string txt = *cur;
pform_set_reg_time(txt, attr);
}
delete names;
}
static void pform_set_integer_2atom(uint64_t width, bool signed_flag, perm_string name, NetNet::Type net_type, list<named_pexpr_t>*attr)
{
PWire*cur = pform_get_make_wire_in_scope(name, net_type, NetNet::NOT_A_PORT, IVL_VT_BOOL);
@ -3101,6 +3050,9 @@ void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, list<pe
}
if (vector_type_t*vec_type = dynamic_cast<vector_type_t*> (data_type)) {
if (net_type==NetNet::REG && vec_type->integer_flag)
net_type=NetNet::INTEGER;
pform_set_net_range(names, vec_type->pdims.get(),
vec_type->signed_flag,
vec_type->base_type, net_type, attr);

View File

@ -187,6 +187,7 @@ extern void pform_class_property(const struct vlltype&loc,
data_type_t*data_type,
std::list<decl_assignment_t*>*decls);
extern void pform_set_this_class(const struct vlltype&loc, PTaskFunc*net);
extern void pform_set_constructor_return(PFunction*net);
extern void pform_end_class_declaration(void);
@ -232,10 +233,11 @@ extern void pform_pop_scope();
extern LexicalScope* pform_peek_scope();
extern PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name);
extern PFunction*pform_push_constructor_scope(const struct vlltype&loc);
extern PPackage* pform_push_package_scope(const struct vlltype&loc, perm_string name);
extern PTask*pform_push_task_scope(const struct vlltype&loc, char*name,
bool is_auto);
extern PFunction*pform_push_function_scope(const struct vlltype&loc, char*name,
extern PFunction*pform_push_function_scope(const struct vlltype&loc, const char*name,
bool is_auto);
extern PBlock*pform_push_block_scope(char*name, PBlock::BL_TYPE tt);
@ -342,8 +344,6 @@ extern void pform_set_port_type(const struct vlltype&li,
extern void pform_set_reg_idx(perm_string name,
std::list<pform_range_t>*indices);
extern void pform_set_reg_integer(list<perm_string>*names, list<named_pexpr_t>*attr);
extern void pform_set_reg_time(list<perm_string>*names, list<named_pexpr_t>*attr);
extern void pform_set_data_type(const struct vlltype&li, data_type_t*, list<perm_string>*names, NetNet::Type net_type, list<named_pexpr_t>*attr);

View File

@ -423,6 +423,13 @@ void PWire::dump(ostream&out, unsigned ind) const
out << " signed";
}
if (get_isint()) {
out << " integer";
}
if (set_data_type_) {
out << " set_data_type_=" << typeid(*set_data_type_).name();
}
if (discipline_) {
out << " discipline<" << discipline_->name() << ">";
}
@ -867,47 +874,12 @@ void PForStatement::dump(ostream&out, unsigned ind) const
void PFunction::dump(ostream&out, unsigned ind) const
{
out << setw(ind) << "" << "function ";
if (is_auto_) cout << "automatic ";
switch (return_type_.type) {
case PTF_NONE:
out << "?none? ";
break;
case PTF_REG:
out << "reg ";
break;
case PTF_REG_S:
out << "reg_s ";
break;
case PTF_INTEGER:
out << "integer ";
break;
case PTF_REAL:
out << "real ";
break;
case PTF_REALTIME:
out << "realtime ";
break;
case PTF_TIME:
out << "time ";
break;
case PTF_ATOM2:
out << "int unsigned ";
break;
case PTF_ATOM2_S:
out << "int signed ";
break;
case PTF_STRING:
out << "string ";
break;
case PTF_VOID:
out << "void ";
break;
}
if (is_auto_) out << "automatic...";
if (return_type_.range) {
out << "[";
out << "] ";
}
if (return_type_)
return_type_->pform_dump(out, ind+8);
else
out << setw(ind+8) << "" << "<implicit type>" << endl;
out << pscope_name() << ";" << endl;
if (method_of())
@ -944,7 +916,7 @@ void PRepeat::dump(ostream&out, unsigned ind) const
void PTask::dump(ostream&out, unsigned ind) const
{
out << setw(ind) << "" << "task ";
if (is_auto_) cout << "automatic ";
if (is_auto_) out << "automatic ";
out << pscope_name() << ";" << endl;
if (method_of())
out << setw(ind) << "" << "method of " << method_of()->name << ";" << endl;

View File

@ -91,6 +91,22 @@ void pform_set_this_class(const struct vlltype&loc, PTaskFunc*net)
net->set_this(pform_cur_class->type, this_wire);
}
void pform_set_constructor_return(PFunction*net)
{
assert(pform_cur_class);
net->set_return(pform_cur_class->type);
}
/*
* A constructor is basically a function with special implications.
*/
PFunction*pform_push_constructor_scope(const struct vlltype&loc)
{
assert(pform_cur_class);
PFunction*func = pform_push_function_scope(loc, "new", true);
return func;
}
void pform_end_class_declaration(void)
{
assert(pform_cur_class);

View File

@ -144,12 +144,14 @@ struct atom2_type_t : public data_type_t {
struct vector_type_t : public data_type_t {
inline explicit vector_type_t(ivl_variable_type_t bt, bool sf,
std::list<pform_range_t>*pd)
: base_type(bt), signed_flag(sf), reg_flag(false), implicit_flag(false), pdims(pd) { }
: base_type(bt), signed_flag(sf), reg_flag(false), integer_flag(false), implicit_flag(false), pdims(pd) { }
virtual ivl_variable_type_t figure_packed_base_type(void)const;
ivl_type_s* elaborate_type(Design*des, NetScope*scope) const;
ivl_variable_type_t base_type;
bool signed_flag;
bool reg_flag; // True if "reg" was used
bool integer_flag; // True if "integer" was used
bool implicit_flag; // True if this type is implicitly logic/reg
std::auto_ptr< list<pform_range_t> > pdims;
};

View File

@ -11,4 +11,4 @@
./ivl -v -Ctgt-stub/stub.conf -C./scripts/devel-stub.conf -Pa.pf -Na.net -fDLL=tgt-stub/stub.tgt foo.vl |& tee foo.log
echo "*** ivl command completed, rc=$?"
echo "*** ivl command completed"

View File

@ -1232,6 +1232,8 @@ static void show_signal(ivl_signal_t net)
switch (ivl_signal_type(net)) {
case IVL_SIT_REG:
type = "reg";
if (ivl_signal_integer(net))
type = "integer";
break;
case IVL_SIT_TRI:
type = "tri";
@ -1351,6 +1353,11 @@ static void show_signal(ivl_signal_t net)
default:
break;
}
if (ivl_signal_integer(net) && ivl_signal_type(net)!=IVL_SIT_REG) {
fprintf(out, " ERROR: integers must be IVL_SIT_REG\n");
stub_errors += 1;
}
}
void test_expr_is_delay(ivl_expr_t expr)