Elaborate nested l-values.
This gets nested l-values to (but just short of) the ivl_target API. Now the elaborator can process nested l-values, but I haven't figured out how to present that at the ivl_target.h API.
This commit is contained in:
parent
9bd9c8f301
commit
68d83383ff
2
PExpr.h
2
PExpr.h
|
|
@ -510,6 +510,8 @@ class PEIdent : public PExpr {
|
||||||
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
|
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||||
bool bidirectional_flag) const;
|
bool bidirectional_flag) const;
|
||||||
|
|
||||||
|
NetAssign_*scan_lname_for_nested_members_(Design*des, NetScope*scope,
|
||||||
|
const pform_name_t&path) const;
|
||||||
bool eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
bool eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
||||||
long&midx, long&lidx) const;
|
long&midx, long&lidx) const;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
41
elab_lval.cc
41
elab_lval.cc
|
|
@ -148,6 +148,44 @@ NetAssign_* PEConcat::elaborate_lval(Design*des,
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetAssign_*PEIdent::scan_lname_for_nested_members_(Design*des, NetScope*scope,
|
||||||
|
const pform_name_t&cur_path) const
|
||||||
|
{
|
||||||
|
if (cur_path.size() == 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
pform_name_t use_path = cur_path;
|
||||||
|
perm_string tmp_name = peek_tail_name(use_path);
|
||||||
|
use_path.pop_back();
|
||||||
|
|
||||||
|
NetNet* reg = 0;
|
||||||
|
const NetExpr*par = 0;
|
||||||
|
NetEvent* eve = 0;
|
||||||
|
symbol_search(this, des, scope, use_path, reg, par, eve);
|
||||||
|
|
||||||
|
if (reg == 0) {
|
||||||
|
NetAssign_*tmp = scan_lname_for_nested_members_(des, scope, use_path);
|
||||||
|
if (tmp == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
tmp = new NetAssign_(tmp);
|
||||||
|
tmp->set_property(tmp_name);
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reg->struct_type()) {
|
||||||
|
cerr << get_fileline() << ": sorry: "
|
||||||
|
<< "I don't know what to do with struct " << use_path << endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reg->class_type()) {
|
||||||
|
return elaborate_lval_net_class_member_(des, scope, reg, tmp_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle the ident as an l-value. This includes bit and part selects
|
* Handle the ident as an l-value. This includes bit and part selects
|
||||||
* of that ident.
|
* of that ident.
|
||||||
|
|
@ -194,6 +232,9 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||||
} else if (reg && reg->class_type()) {
|
} else if (reg && reg->class_type()) {
|
||||||
method_name = tmp_name;
|
method_name = tmp_name;
|
||||||
|
|
||||||
|
} else if (NetAssign_*subl = scan_lname_for_nested_members_(des, use_scope, path_)) {
|
||||||
|
return subl;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
reg = 0;
|
reg = 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2392,7 +2392,7 @@ NetProc* PAssign::elaborate_compressed_(Design*des, NetScope*scope) const
|
||||||
static bool lval_not_program_variable(const NetAssign_*lv)
|
static bool lval_not_program_variable(const NetAssign_*lv)
|
||||||
{
|
{
|
||||||
while (lv) {
|
while (lv) {
|
||||||
NetScope*sig_scope = lv->sig()->scope();
|
NetScope*sig_scope = lv->scope();
|
||||||
if (! sig_scope->program_block() && sig_scope->type()!=NetScope::CLASS)
|
if (! sig_scope->program_block() && sig_scope->type()!=NetScope::CLASS)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|
|
||||||
9
emit.cc
9
emit.cc
|
|
@ -527,6 +527,15 @@ int Design::emit(struct target_t*tgt) const
|
||||||
for (const NetAnalogTop*idx = aprocs_ ; idx ; idx = idx->next_)
|
for (const NetAnalogTop*idx = aprocs_ ; idx ; idx = idx->next_)
|
||||||
proc_rc &= idx->emit(tgt);
|
proc_rc &= idx->emit(tgt);
|
||||||
|
|
||||||
|
if (nodes_rc == false)
|
||||||
|
tgt->errors += 1;
|
||||||
|
if (tasks_rc == false)
|
||||||
|
tgt->errors += 1;
|
||||||
|
if (proc_rc == false)
|
||||||
|
tgt->errors += 1;
|
||||||
|
if (branches_rc == false)
|
||||||
|
tgt->errors += 1;
|
||||||
|
|
||||||
rc = tgt->end_design(this);
|
rc = tgt->end_design(this);
|
||||||
|
|
||||||
if (nodes_rc == false)
|
if (nodes_rc == false)
|
||||||
|
|
|
||||||
103
net_assign.cc
103
net_assign.cc
|
|
@ -22,6 +22,7 @@
|
||||||
# include "netlist.h"
|
# include "netlist.h"
|
||||||
# include "netclass.h"
|
# include "netclass.h"
|
||||||
# include "netdarray.h"
|
# include "netdarray.h"
|
||||||
|
# include "netenum.h"
|
||||||
# include "ivl_assert.h"
|
# include "ivl_assert.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -38,8 +39,14 @@ unsigned count_lval_width(const NetAssign_*idx)
|
||||||
return wid;
|
return wid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetAssign_::NetAssign_(NetAssign_*n)
|
||||||
|
: nest_(n), sig_(0), word_(0), base_(0), sel_type_(IVL_SEL_OTHER)
|
||||||
|
{
|
||||||
|
more = 0;
|
||||||
|
}
|
||||||
|
|
||||||
NetAssign_::NetAssign_(NetNet*s)
|
NetAssign_::NetAssign_(NetNet*s)
|
||||||
: sig_(s), word_(0), base_(0), sel_type_(IVL_SEL_OTHER)
|
: nest_(0), sig_(s), word_(0), base_(0), sel_type_(IVL_SEL_OTHER)
|
||||||
{
|
{
|
||||||
lwid_ = sig_->vector_width();
|
lwid_ = sig_->vector_width();
|
||||||
sig_->incr_lref();
|
sig_->incr_lref();
|
||||||
|
|
@ -59,6 +66,18 @@ NetAssign_::~NetAssign_()
|
||||||
delete word_;
|
delete word_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string NetAssign_::get_fileline() const
|
||||||
|
{
|
||||||
|
if (sig_) return sig_->get_fileline();
|
||||||
|
else return nest_->get_fileline();
|
||||||
|
}
|
||||||
|
|
||||||
|
NetScope*NetAssign_::scope() const
|
||||||
|
{
|
||||||
|
if (sig_) return sig_->scope();
|
||||||
|
else return nest_->scope();
|
||||||
|
}
|
||||||
|
|
||||||
void NetAssign_::set_word(NetExpr*r)
|
void NetAssign_::set_word(NetExpr*r)
|
||||||
{
|
{
|
||||||
assert(word_ == 0);
|
assert(word_ == 0);
|
||||||
|
|
@ -87,55 +106,65 @@ ivl_select_type_t NetAssign_::select_type() const
|
||||||
|
|
||||||
unsigned NetAssign_::lwidth() const
|
unsigned NetAssign_::lwidth() const
|
||||||
{
|
{
|
||||||
// If the signal is a class type, then the situation is either
|
// This gets me the type of the l-value expression, down to
|
||||||
// "a.b" or "a.b.<member>". If this is "a.b" (no
|
// the type of the member. If this returns nil, then resort to
|
||||||
// member/property reference, then return width==1. If this is
|
// the lwid_ value.
|
||||||
// "a.b.<member>", then get the type of the <member> property
|
ivl_type_t ntype = net_type();
|
||||||
// and return the width of that.
|
if (ntype == 0)
|
||||||
if (const netclass_t*class_type = sig_->class_type()) {
|
return lwid_;
|
||||||
if (member_.nil())
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
int pidx = class_type->property_idx_from_name(member_);
|
// If the type is a darray, and there is a word index, then we
|
||||||
ivl_assert(*sig_, pidx >= 0);
|
// actually want the width of the elements.
|
||||||
ivl_type_t ptype = class_type->get_prop_type(pidx);
|
if (const netdarray_t*darray = dynamic_cast<const netdarray_t*> (ntype)) {
|
||||||
return ptype->packed_width();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (const netdarray_t*darray = sig_->darray_type()) {
|
|
||||||
if (word_ == 0)
|
if (word_ == 0)
|
||||||
return 1;
|
return 1;
|
||||||
else
|
else
|
||||||
return darray->element_width();
|
return darray->element_width();
|
||||||
}
|
}
|
||||||
|
|
||||||
return lwid_;
|
return ntype->packed_width();
|
||||||
}
|
}
|
||||||
|
|
||||||
ivl_variable_type_t NetAssign_::expr_type() const
|
ivl_variable_type_t NetAssign_::expr_type() const
|
||||||
{
|
{
|
||||||
if (const netclass_t*class_type = sig_->class_type()) {
|
ivl_type_t ntype = net_type();
|
||||||
if (member_.nil())
|
if (const netdarray_t*darray = dynamic_cast<const netdarray_t*>(ntype)) {
|
||||||
return sig_->data_type();
|
|
||||||
|
|
||||||
int pidx = class_type->property_idx_from_name(member_);
|
|
||||||
ivl_assert(*sig_, pidx >= 0);
|
|
||||||
ivl_type_t tmp = class_type->get_prop_type(pidx);
|
|
||||||
return tmp->base_type();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (const netdarray_t*darray = sig_->darray_type()) {
|
|
||||||
if (word_ == 0)
|
if (word_ == 0)
|
||||||
return IVL_VT_DARRAY;
|
return IVL_VT_DARRAY;
|
||||||
else
|
else
|
||||||
return darray->element_base_type();
|
return darray->element_base_type();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ntype) return ntype->base_type();
|
||||||
|
|
||||||
|
ivl_assert(*this, sig_);
|
||||||
return sig_->data_type();
|
return sig_->data_type();
|
||||||
}
|
}
|
||||||
|
|
||||||
const ivl_type_s* NetAssign_::net_type() const
|
const ivl_type_s* NetAssign_::net_type() const
|
||||||
{
|
{
|
||||||
|
if (nest_) {
|
||||||
|
const ivl_type_s*ntype = nest_->net_type();
|
||||||
|
if (member_.nil())
|
||||||
|
return ntype;
|
||||||
|
|
||||||
|
if (const netclass_t*class_type = dynamic_cast<const netclass_t*>(ntype)) {
|
||||||
|
int pidx = class_type->property_idx_from_name(member_);
|
||||||
|
ivl_assert(*this, pidx >= 0);
|
||||||
|
ivl_type_t tmp = class_type->get_prop_type(pidx);
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const netdarray_t*darray = dynamic_cast<const netdarray_t*> (ntype)) {
|
||||||
|
if (word_ == 0)
|
||||||
|
return ntype;
|
||||||
|
else
|
||||||
|
return darray->element_type();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (const netclass_t*class_type = sig_->class_type()) {
|
if (const netclass_t*class_type = sig_->class_type()) {
|
||||||
if (member_.nil())
|
if (member_.nil())
|
||||||
return sig_->net_type();
|
return sig_->net_type();
|
||||||
|
|
@ -146,11 +175,11 @@ const ivl_type_s* NetAssign_::net_type() const
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dynamic_cast<const netdarray_t*> (sig_->net_type())) {
|
if (const netdarray_t*darray = dynamic_cast<const netdarray_t*> (sig_->net_type())) {
|
||||||
if (word_ == 0)
|
if (word_ == 0)
|
||||||
return sig_->net_type();
|
return sig_->net_type();
|
||||||
|
else
|
||||||
return 0;
|
return darray->element_type();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -159,11 +188,21 @@ const ivl_type_s* NetAssign_::net_type() const
|
||||||
const netenum_t*NetAssign_::enumeration() const
|
const netenum_t*NetAssign_::enumeration() const
|
||||||
{
|
{
|
||||||
const netenum_t*tmp = 0;
|
const netenum_t*tmp = 0;
|
||||||
|
ivl_type_t ntype = net_type();
|
||||||
|
if (ntype == 0) {
|
||||||
|
|
||||||
|
ivl_assert(*this, sig_);
|
||||||
|
|
||||||
// If the base signal is not an enumeration, return nil.
|
// If the base signal is not an enumeration, return nil.
|
||||||
if ( (tmp = sig_->enumeration()) == 0 )
|
if ( (tmp = sig_->enumeration()) == 0 )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
tmp = dynamic_cast<const netenum_t*>(ntype);
|
||||||
|
if (tmp == 0)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Part select of an enumeration is not an enumeration.
|
// Part select of an enumeration is not an enumeration.
|
||||||
if (base_ != 0)
|
if (base_ != 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -199,7 +238,7 @@ void NetAssign_::set_part(NetExpr*base, unsigned wid,
|
||||||
|
|
||||||
void NetAssign_::set_property(const perm_string&mname)
|
void NetAssign_::set_property(const perm_string&mname)
|
||||||
{
|
{
|
||||||
ivl_assert(*sig_, sig_->class_type());
|
//ivl_assert(*sig_, sig_->class_type());
|
||||||
member_ = mname;
|
member_ = mname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
11
netlist.h
11
netlist.h
|
|
@ -2545,14 +2545,21 @@ class NetAlloc : public NetProc {
|
||||||
class NetAssign_ {
|
class NetAssign_ {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NetAssign_(NetNet*sig);
|
explicit NetAssign_(NetAssign_*nest);
|
||||||
|
explicit NetAssign_(NetNet*sig);
|
||||||
~NetAssign_();
|
~NetAssign_();
|
||||||
|
|
||||||
|
// This is so NetAssign_ objects can be passed to ivl_assert
|
||||||
|
// and other macros that call this method.
|
||||||
|
string get_fileline() const;
|
||||||
|
|
||||||
// If this expression exists, then it is used to select a word
|
// If this expression exists, then it is used to select a word
|
||||||
// from an array/memory.
|
// from an array/memory.
|
||||||
NetExpr*word();
|
NetExpr*word();
|
||||||
const NetExpr*word() const;
|
const NetExpr*word() const;
|
||||||
|
|
||||||
|
NetScope*scope()const;
|
||||||
|
|
||||||
// Get the base index of the part select, or 0 if there is no
|
// Get the base index of the part select, or 0 if there is no
|
||||||
// part select.
|
// part select.
|
||||||
const NetExpr* get_base() const;
|
const NetExpr* get_base() const;
|
||||||
|
|
@ -2609,6 +2616,8 @@ class NetAssign_ {
|
||||||
void dump_lval(ostream&o) const;
|
void dump_lval(ostream&o) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Nested l-value. If this is set, sig_ mut NOT be setl
|
||||||
|
NetAssign_*nest_;
|
||||||
NetNet *sig_;
|
NetNet *sig_;
|
||||||
// Memory word index
|
// Memory word index
|
||||||
NetExpr*word_;
|
NetExpr*word_;
|
||||||
|
|
|
||||||
|
|
@ -136,8 +136,9 @@ bool dll_target::func_def(const NetScope*net)
|
||||||
* This private function makes the assignment lvals for the various
|
* This private function makes the assignment lvals for the various
|
||||||
* kinds of assignment statements.
|
* kinds of assignment statements.
|
||||||
*/
|
*/
|
||||||
void dll_target::make_assign_lvals_(const NetAssignBase*net)
|
bool dll_target::make_assign_lvals_(const NetAssignBase*net)
|
||||||
{
|
{
|
||||||
|
bool flag = true;
|
||||||
assert(stmt_cur_);
|
assert(stmt_cur_);
|
||||||
|
|
||||||
unsigned cnt = net->l_val_count();
|
unsigned cnt = net->l_val_count();
|
||||||
|
|
@ -188,9 +189,14 @@ void dll_target::make_assign_lvals_(const NetAssignBase*net)
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
assert(0);
|
cerr << net->get_fileline() << ": internal error: "
|
||||||
|
<< "I don't know how to handle nested l-values "
|
||||||
|
<< "in ivl_target.h API." << endl;
|
||||||
|
flag = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dll_target::proc_alloc(const NetAlloc*net)
|
void dll_target::proc_alloc(const NetAlloc*net)
|
||||||
|
|
@ -207,6 +213,8 @@ void dll_target::proc_alloc(const NetAlloc*net)
|
||||||
*/
|
*/
|
||||||
bool dll_target::proc_assign(const NetAssign*net)
|
bool dll_target::proc_assign(const NetAssign*net)
|
||||||
{
|
{
|
||||||
|
bool flag = true;
|
||||||
|
|
||||||
assert(stmt_cur_);
|
assert(stmt_cur_);
|
||||||
assert(stmt_cur_->type_ == IVL_ST_NONE);
|
assert(stmt_cur_->type_ == IVL_ST_NONE);
|
||||||
|
|
||||||
|
|
@ -216,7 +224,7 @@ bool dll_target::proc_assign(const NetAssign*net)
|
||||||
stmt_cur_->u_.assign_.delay = 0;
|
stmt_cur_->u_.assign_.delay = 0;
|
||||||
|
|
||||||
/* Make the lval fields. */
|
/* Make the lval fields. */
|
||||||
make_assign_lvals_(net);
|
flag &= make_assign_lvals_(net);
|
||||||
|
|
||||||
stmt_cur_->u_.assign_.oper = net->assign_operator();
|
stmt_cur_->u_.assign_.oper = net->assign_operator();
|
||||||
assert(expr_ == 0);
|
assert(expr_ == 0);
|
||||||
|
|
@ -231,7 +239,7 @@ bool dll_target::proc_assign(const NetAssign*net)
|
||||||
expr_ = 0;
|
expr_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
11
t-dll.cc
11
t-dll.cc
|
|
@ -710,11 +710,20 @@ bool dll_target::start_design(const Design*des)
|
||||||
*/
|
*/
|
||||||
int dll_target::end_design(const Design*)
|
int dll_target::end_design(const Design*)
|
||||||
{
|
{
|
||||||
|
int rc;
|
||||||
|
if (errors == 0) {
|
||||||
if (verbose_flag) {
|
if (verbose_flag) {
|
||||||
cout << " ... invoking target_design" << endl;
|
cout << " ... invoking target_design" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rc = (target_)(&des_);
|
rc = (target_)(&des_);
|
||||||
|
} else {
|
||||||
|
if (verbose_flag) {
|
||||||
|
cout << " ... skipping target_design due to errors." << endl;
|
||||||
|
}
|
||||||
|
rc = errors;
|
||||||
|
}
|
||||||
|
|
||||||
ivl_dlclose(dll_);
|
ivl_dlclose(dll_);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
t-dll.h
2
t-dll.h
|
|
@ -172,7 +172,7 @@ struct dll_target : public target_t, public expr_scan_t {
|
||||||
|
|
||||||
void add_root(const NetScope *s);
|
void add_root(const NetScope *s);
|
||||||
|
|
||||||
void make_assign_lvals_(const NetAssignBase*net);
|
bool make_assign_lvals_(const NetAssignBase*net);
|
||||||
void sub_off_from_expr_(long);
|
void sub_off_from_expr_(long);
|
||||||
void mul_expr_by_const_(long);
|
void mul_expr_by_const_(long);
|
||||||
|
|
||||||
|
|
|
||||||
4
target.h
4
target.h
|
|
@ -46,8 +46,12 @@ struct target {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct target_t {
|
struct target_t {
|
||||||
|
inline target_t() : errors(0) { }
|
||||||
virtual ~target_t();
|
virtual ~target_t();
|
||||||
|
|
||||||
|
/* Set this to count errors encountered during emit. */
|
||||||
|
int errors;
|
||||||
|
|
||||||
/* Start the design. This sets the main output file stream
|
/* Start the design. This sets the main output file stream
|
||||||
that the target should use. */
|
that the target should use. */
|
||||||
virtual bool start_design(const Design*) =0;
|
virtual bool start_design(const Design*) =0;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue