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,
|
||||
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,
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
* of that ident.
|
||||
|
|
@ -194,6 +232,9 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
|||
} else if (reg && reg->class_type()) {
|
||||
method_name = tmp_name;
|
||||
|
||||
} else if (NetAssign_*subl = scan_lname_for_nested_members_(des, use_scope, path_)) {
|
||||
return subl;
|
||||
|
||||
} else {
|
||||
reg = 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2392,7 +2392,7 @@ NetProc* PAssign::elaborate_compressed_(Design*des, NetScope*scope) const
|
|||
static bool lval_not_program_variable(const NetAssign_*lv)
|
||||
{
|
||||
while (lv) {
|
||||
NetScope*sig_scope = lv->sig()->scope();
|
||||
NetScope*sig_scope = lv->scope();
|
||||
if (! sig_scope->program_block() && sig_scope->type()!=NetScope::CLASS)
|
||||
return true;
|
||||
|
||||
|
|
|
|||
11
emit.cc
11
emit.cc
|
|
@ -527,6 +527,15 @@ int Design::emit(struct target_t*tgt) const
|
|||
for (const NetAnalogTop*idx = aprocs_ ; idx ; idx = idx->next_)
|
||||
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);
|
||||
|
||||
if (nodes_rc == false)
|
||||
|
|
@ -534,7 +543,7 @@ int Design::emit(struct target_t*tgt) const
|
|||
if (tasks_rc == false)
|
||||
return -2;
|
||||
if (proc_rc == false)
|
||||
return -3;
|
||||
return -3;
|
||||
if (branches_rc == false)
|
||||
return -4;
|
||||
|
||||
|
|
|
|||
109
net_assign.cc
109
net_assign.cc
|
|
@ -22,6 +22,7 @@
|
|||
# include "netlist.h"
|
||||
# include "netclass.h"
|
||||
# include "netdarray.h"
|
||||
# include "netenum.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
/*
|
||||
|
|
@ -38,8 +39,14 @@ unsigned count_lval_width(const NetAssign_*idx)
|
|||
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)
|
||||
: 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();
|
||||
sig_->incr_lref();
|
||||
|
|
@ -59,6 +66,18 @@ NetAssign_::~NetAssign_()
|
|||
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)
|
||||
{
|
||||
assert(word_ == 0);
|
||||
|
|
@ -87,55 +106,65 @@ ivl_select_type_t NetAssign_::select_type() const
|
|||
|
||||
unsigned NetAssign_::lwidth() const
|
||||
{
|
||||
// If the signal is a class type, then the situation is either
|
||||
// "a.b" or "a.b.<member>". If this is "a.b" (no
|
||||
// member/property reference, then return width==1. If this is
|
||||
// "a.b.<member>", then get the type of the <member> property
|
||||
// and return the width of that.
|
||||
if (const netclass_t*class_type = sig_->class_type()) {
|
||||
if (member_.nil())
|
||||
return 1;
|
||||
// This gets me the type of the l-value expression, down to
|
||||
// the type of the member. If this returns nil, then resort to
|
||||
// the lwid_ value.
|
||||
ivl_type_t ntype = net_type();
|
||||
if (ntype == 0)
|
||||
return lwid_;
|
||||
|
||||
int pidx = class_type->property_idx_from_name(member_);
|
||||
ivl_assert(*sig_, pidx >= 0);
|
||||
ivl_type_t ptype = class_type->get_prop_type(pidx);
|
||||
return ptype->packed_width();
|
||||
}
|
||||
|
||||
if (const netdarray_t*darray = sig_->darray_type()) {
|
||||
// If the type is a darray, and there is a word index, then we
|
||||
// actually want the width of the elements.
|
||||
if (const netdarray_t*darray = dynamic_cast<const netdarray_t*> (ntype)) {
|
||||
if (word_ == 0)
|
||||
return 1;
|
||||
else
|
||||
return darray->element_width();
|
||||
}
|
||||
|
||||
return lwid_;
|
||||
return ntype->packed_width();
|
||||
}
|
||||
|
||||
ivl_variable_type_t NetAssign_::expr_type() const
|
||||
{
|
||||
if (const netclass_t*class_type = sig_->class_type()) {
|
||||
if (member_.nil())
|
||||
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()) {
|
||||
ivl_type_t ntype = net_type();
|
||||
if (const netdarray_t*darray = dynamic_cast<const netdarray_t*>(ntype)) {
|
||||
if (word_ == 0)
|
||||
return IVL_VT_DARRAY;
|
||||
else
|
||||
return darray->element_base_type();
|
||||
}
|
||||
|
||||
if (ntype) return ntype->base_type();
|
||||
|
||||
ivl_assert(*this, sig_);
|
||||
return sig_->data_type();
|
||||
}
|
||||
|
||||
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 (member_.nil())
|
||||
return sig_->net_type();
|
||||
|
|
@ -146,11 +175,11 @@ const ivl_type_s* NetAssign_::net_type() const
|
|||
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)
|
||||
return sig_->net_type();
|
||||
|
||||
return 0;
|
||||
else
|
||||
return darray->element_type();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -159,10 +188,20 @@ const ivl_type_s* NetAssign_::net_type() const
|
|||
const netenum_t*NetAssign_::enumeration() const
|
||||
{
|
||||
const netenum_t*tmp = 0;
|
||||
ivl_type_t ntype = net_type();
|
||||
if (ntype == 0) {
|
||||
|
||||
// If the base signal is not an enumeration, return nil.
|
||||
if ( (tmp = sig_->enumeration()) == 0 )
|
||||
return 0;
|
||||
ivl_assert(*this, sig_);
|
||||
|
||||
// If the base signal is not an enumeration, return nil.
|
||||
if ( (tmp = sig_->enumeration()) == 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.
|
||||
if (base_ != 0)
|
||||
|
|
@ -199,7 +238,7 @@ void NetAssign_::set_part(NetExpr*base, unsigned wid,
|
|||
|
||||
void NetAssign_::set_property(const perm_string&mname)
|
||||
{
|
||||
ivl_assert(*sig_, sig_->class_type());
|
||||
//ivl_assert(*sig_, sig_->class_type());
|
||||
member_ = mname;
|
||||
}
|
||||
|
||||
|
|
|
|||
11
netlist.h
11
netlist.h
|
|
@ -2545,14 +2545,21 @@ class NetAlloc : public NetProc {
|
|||
class NetAssign_ {
|
||||
|
||||
public:
|
||||
NetAssign_(NetNet*sig);
|
||||
explicit NetAssign_(NetAssign_*nest);
|
||||
explicit NetAssign_(NetNet*sig);
|
||||
~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
|
||||
// from an array/memory.
|
||||
NetExpr*word();
|
||||
const NetExpr*word() const;
|
||||
|
||||
NetScope*scope()const;
|
||||
|
||||
// Get the base index of the part select, or 0 if there is no
|
||||
// part select.
|
||||
const NetExpr* get_base() const;
|
||||
|
|
@ -2609,6 +2616,8 @@ class NetAssign_ {
|
|||
void dump_lval(ostream&o) const;
|
||||
|
||||
private:
|
||||
// Nested l-value. If this is set, sig_ mut NOT be setl
|
||||
NetAssign_*nest_;
|
||||
NetNet *sig_;
|
||||
// Memory word index
|
||||
NetExpr*word_;
|
||||
|
|
|
|||
|
|
@ -136,8 +136,9 @@ bool dll_target::func_def(const NetScope*net)
|
|||
* This private function makes the assignment lvals for the various
|
||||
* 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_);
|
||||
|
||||
unsigned cnt = net->l_val_count();
|
||||
|
|
@ -188,9 +189,14 @@ void dll_target::make_assign_lvals_(const NetAssignBase*net)
|
|||
}
|
||||
|
||||
} 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)
|
||||
|
|
@ -207,6 +213,8 @@ void dll_target::proc_alloc(const NetAlloc*net)
|
|||
*/
|
||||
bool dll_target::proc_assign(const NetAssign*net)
|
||||
{
|
||||
bool flag = true;
|
||||
|
||||
assert(stmt_cur_);
|
||||
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;
|
||||
|
||||
/* Make the lval fields. */
|
||||
make_assign_lvals_(net);
|
||||
flag &= make_assign_lvals_(net);
|
||||
|
||||
stmt_cur_->u_.assign_.oper = net->assign_operator();
|
||||
assert(expr_ == 0);
|
||||
|
|
@ -231,7 +239,7 @@ bool dll_target::proc_assign(const NetAssign*net)
|
|||
expr_ = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
return flag;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
15
t-dll.cc
15
t-dll.cc
|
|
@ -710,11 +710,20 @@ bool dll_target::start_design(const Design*des)
|
|||
*/
|
||||
int dll_target::end_design(const Design*)
|
||||
{
|
||||
if (verbose_flag) {
|
||||
cout << " ... invoking target_design" << endl;
|
||||
int rc;
|
||||
if (errors == 0) {
|
||||
if (verbose_flag) {
|
||||
cout << " ... invoking target_design" << endl;
|
||||
}
|
||||
|
||||
rc = (target_)(&des_);
|
||||
} else {
|
||||
if (verbose_flag) {
|
||||
cout << " ... skipping target_design due to errors." << endl;
|
||||
}
|
||||
rc = errors;
|
||||
}
|
||||
|
||||
int rc = (target_)(&des_);
|
||||
ivl_dlclose(dll_);
|
||||
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 make_assign_lvals_(const NetAssignBase*net);
|
||||
bool make_assign_lvals_(const NetAssignBase*net);
|
||||
void sub_off_from_expr_(long);
|
||||
void mul_expr_by_const_(long);
|
||||
|
||||
|
|
|
|||
4
target.h
4
target.h
|
|
@ -46,8 +46,12 @@ struct target {
|
|||
*/
|
||||
|
||||
struct target_t {
|
||||
inline target_t() : errors(0) { }
|
||||
virtual ~target_t();
|
||||
|
||||
/* Set this to count errors encountered during emit. */
|
||||
int errors;
|
||||
|
||||
/* Start the design. This sets the main output file stream
|
||||
that the target should use. */
|
||||
virtual bool start_design(const Design*) =0;
|
||||
|
|
|
|||
Loading…
Reference in New Issue