Packed struct members in behavioral assign l-values.

This commit is contained in:
Stephen Williams 2012-01-03 17:38:08 -08:00
parent d2c3ff7999
commit 124314576d
3 changed files with 66 additions and 0 deletions

View File

@ -349,6 +349,9 @@ class PEIdent : public PExpr {
bool elaborate_lval_net_part_(Design*, NetScope*, NetAssign_*) const;
bool elaborate_lval_net_idx_(Design*, NetScope*, NetAssign_*,
index_component_t::ctype_t) const;
bool elaborate_lval_net_packed_member_(Design*, NetScope*,
NetAssign_*,
const perm_string&) const;
private:
NetExpr*elaborate_expr_param_(Design*des,

View File

@ -22,6 +22,7 @@
# include "PExpr.h"
# include "netlist.h"
# include "netmisc.h"
# include "netstruct.h"
# include "compiler.h"
# include <cstdlib>
# include <iostream>
@ -152,8 +153,26 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
NetNet* reg = 0;
const NetExpr*par = 0;
NetEvent* eve = 0;
perm_string method_name;
symbol_search(this, des, scope, path_, reg, par, eve);
/* If the signal is not found, check to see if this is a
member of a struct. Take the name of the form "a.b.member",
remove the member and store it into method_name, and retry
the search with "a.b". */
if (reg == 0 && path_.size() >= 2) {
pform_name_t use_path = path_;
method_name = peek_tail_name(use_path);
use_path.pop_back();
symbol_search(this, des, scope, use_path, reg, par, eve);
if (reg && reg->struct_type() == 0) {
method_name = perm_string();
reg = 0;
}
}
if (reg == 0) {
cerr << get_fileline() << ": error: Could not find variable ``"
<< path_ << "'' in ``" << scope_path(scope) <<
@ -193,6 +212,12 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
return 0;
}
if (reg->struct_type() && !method_name.nil()) {
NetAssign_*lv = new NetAssign_(reg);
elaborate_lval_net_packed_member_(des, scope, lv, method_name);
return lv;
}
if (reg->array_dimensions() > 0)
return elaborate_lval_net_word_(des, scope, reg);
@ -533,6 +558,38 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
return true;
}
bool PEIdent::elaborate_lval_net_packed_member_(Design*des,
NetScope*scope,
NetAssign_*lv,
const perm_string&member_name) const
{
NetNet*reg = lv->sig();
ivl_assert(*this, reg);
netstruct_t*struct_type = reg->struct_type();
ivl_assert(*this, struct_type);
if (! struct_type->packed()) {
cerr << get_fileline() << ": sorry: Only packed structures "
<< "are supported in l-value." << endl;
des->errors += 1;
return false;
}
unsigned long off;
const netstruct_t::member_t* member = struct_type->packed_member(member_name, off);
if (member == 0) {
cerr << get_fileline() << ": error: Member " << member_name
<< " is not a member of variable " << reg->name() << endl;
des->errors += 1;
return false;
}
lv->set_part(new NetEConst(verinum(off)), member->width());
return true;
}
NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool) const
{
cerr << get_fileline() << ": error: Constant values not allowed "

View File

@ -427,6 +427,12 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
method_name = peek_tail_name(use_path);
use_path.pop_back();
symbol_search(this, des, scope, use_path, sig, par, eve);
// Whoops, not a struct signal, so give up on this avenue.
if (sig && sig->struct_type() == 0) {
method_name = perm_string();
sig = 0;
}
}
if (sig == 0) {