Warn that a signed part select may not work for signals < 32 bits.

If a signed signal is driving a part select in a CA and the width
is less than 32 bits. the value will be zero extended and will
not work for negative values. This patch adds a warning that this
could happen. This will be fixed in development.
This commit is contained in:
Cary R 2009-09-18 15:43:09 -07:00 committed by Stephen Williams
parent 09fa57742a
commit e1af002a32
5 changed files with 23 additions and 7 deletions

View File

@ -1089,7 +1089,8 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root)
if (base_ != 0) {
off = base_->synthesize(des, scope, root);
NetPartSelect*sel = new NetPartSelect(sub, off, expr_width());
NetPartSelect*sel = new NetPartSelect(sub, off, expr_width(),
base_->has_sign());
sel->set_line(*this);
des->add_node(sel);

View File

@ -885,7 +885,7 @@ const NetDelaySrc* NetNet::delay_path(unsigned idx) const
NetPartSelect::NetPartSelect(NetNet*sig, unsigned off, unsigned wid,
NetPartSelect::dir_t dir__)
: NetNode(sig->scope(), sig->scope()->local_symbol(), 2),
off_(off), wid_(wid), dir_(dir__)
off_(off), wid_(wid), dir_(dir__), signed_flag_(false)
{
set_line(*sig);
@ -904,9 +904,9 @@ NetPartSelect::NetPartSelect(NetNet*sig, unsigned off, unsigned wid,
}
NetPartSelect::NetPartSelect(NetNet*sig, NetNet*sel,
unsigned wid)
unsigned wid, bool signed_flag)
: NetNode(sig->scope(), sig->scope()->local_symbol(), 3),
off_(0), wid_(wid), dir_(VP)
off_(0), wid_(wid), dir_(VP), signed_flag_(signed_flag)
{
switch (dir_) {
case NetPartSelect::VP:

View File

@ -1795,12 +1795,14 @@ class NetPartSelect : public NetNode {
explicit NetPartSelect(NetNet*sig,
unsigned off, unsigned wid, dir_t dir);
explicit NetPartSelect(NetNet*sig, NetNet*sel,
unsigned wid);
unsigned wid, bool signed_flag = false);
~NetPartSelect();
unsigned base() const;
unsigned width() const;
dir_t dir() const;
/* Is the select signal signed? */
bool signed_flag() const { return signed_flag_; }
virtual void dump_node(ostream&, unsigned ind) const;
bool emit_node(struct target_t*tgt) const;
@ -1809,6 +1811,7 @@ class NetPartSelect : public NetNode {
unsigned off_;
unsigned wid_;
dir_t dir_;
bool signed_flag_;
};
/*

View File

@ -2153,8 +2153,12 @@ bool dll_target::part_select(const NetPartSelect*net)
obj->scope = find_scope(des_, net->scope());
assert(obj->scope);
/* Part selects are always unsigned. */
obj->u_.part.signed_flag = 0;
/* Part selects are always unsigned, so we use this to indicate
* if the part select base signal is signed or not. */
if (net->signed_flag())
obj->u_.part.signed_flag = 1;
else
obj->u_.part.signed_flag = 0;
/* Choose the width of the part select. */
obj->width = net->width();

View File

@ -1654,6 +1654,14 @@ static void draw_lpm_part(ivl_lpm_t net)
fprintf(vvp_out, ", %u, %u;\n", base, width);
} else {
const char*sel_symbol = draw_net_input(sel);
/* We need to enhance .part/v to support a signed index. */
if (ivl_lpm_signed(net) && width_of_nexus(sel) < 8*sizeof(int)) {
fprintf(stderr, "%s:%u: tgt-vvp warning: V0.9 may give "
"incorrect results for a select with a "
"signed index less than %zu bits.\n",
ivl_lpm_file(net), ivl_lpm_lineno(net),
8*sizeof(int));
}
fprintf(vvp_out, "L_%p%s .part/v %s",
net, dly, draw_net_input(ivl_lpm_data(net,0)));
fprintf(vvp_out, ", %s", sel_symbol);