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:
parent
09fa57742a
commit
e1af002a32
|
|
@ -1089,7 +1089,8 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root)
|
||||||
if (base_ != 0) {
|
if (base_ != 0) {
|
||||||
off = base_->synthesize(des, scope, root);
|
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);
|
sel->set_line(*this);
|
||||||
des->add_node(sel);
|
des->add_node(sel);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -885,7 +885,7 @@ const NetDelaySrc* NetNet::delay_path(unsigned idx) const
|
||||||
NetPartSelect::NetPartSelect(NetNet*sig, unsigned off, unsigned wid,
|
NetPartSelect::NetPartSelect(NetNet*sig, unsigned off, unsigned wid,
|
||||||
NetPartSelect::dir_t dir__)
|
NetPartSelect::dir_t dir__)
|
||||||
: NetNode(sig->scope(), sig->scope()->local_symbol(), 2),
|
: 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);
|
set_line(*sig);
|
||||||
|
|
||||||
|
|
@ -904,9 +904,9 @@ NetPartSelect::NetPartSelect(NetNet*sig, unsigned off, unsigned wid,
|
||||||
}
|
}
|
||||||
|
|
||||||
NetPartSelect::NetPartSelect(NetNet*sig, NetNet*sel,
|
NetPartSelect::NetPartSelect(NetNet*sig, NetNet*sel,
|
||||||
unsigned wid)
|
unsigned wid, bool signed_flag)
|
||||||
: NetNode(sig->scope(), sig->scope()->local_symbol(), 3),
|
: 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_) {
|
switch (dir_) {
|
||||||
case NetPartSelect::VP:
|
case NetPartSelect::VP:
|
||||||
|
|
|
||||||
|
|
@ -1795,12 +1795,14 @@ class NetPartSelect : public NetNode {
|
||||||
explicit NetPartSelect(NetNet*sig,
|
explicit NetPartSelect(NetNet*sig,
|
||||||
unsigned off, unsigned wid, dir_t dir);
|
unsigned off, unsigned wid, dir_t dir);
|
||||||
explicit NetPartSelect(NetNet*sig, NetNet*sel,
|
explicit NetPartSelect(NetNet*sig, NetNet*sel,
|
||||||
unsigned wid);
|
unsigned wid, bool signed_flag = false);
|
||||||
~NetPartSelect();
|
~NetPartSelect();
|
||||||
|
|
||||||
unsigned base() const;
|
unsigned base() const;
|
||||||
unsigned width() const;
|
unsigned width() const;
|
||||||
dir_t dir() 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;
|
virtual void dump_node(ostream&, unsigned ind) const;
|
||||||
bool emit_node(struct target_t*tgt) const;
|
bool emit_node(struct target_t*tgt) const;
|
||||||
|
|
@ -1809,6 +1811,7 @@ class NetPartSelect : public NetNode {
|
||||||
unsigned off_;
|
unsigned off_;
|
||||||
unsigned wid_;
|
unsigned wid_;
|
||||||
dir_t dir_;
|
dir_t dir_;
|
||||||
|
bool signed_flag_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
8
t-dll.cc
8
t-dll.cc
|
|
@ -2153,8 +2153,12 @@ bool dll_target::part_select(const NetPartSelect*net)
|
||||||
obj->scope = find_scope(des_, net->scope());
|
obj->scope = find_scope(des_, net->scope());
|
||||||
assert(obj->scope);
|
assert(obj->scope);
|
||||||
|
|
||||||
/* Part selects are always unsigned. */
|
/* Part selects are always unsigned, so we use this to indicate
|
||||||
obj->u_.part.signed_flag = 0;
|
* 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. */
|
/* Choose the width of the part select. */
|
||||||
obj->width = net->width();
|
obj->width = net->width();
|
||||||
|
|
|
||||||
|
|
@ -1654,6 +1654,14 @@ static void draw_lpm_part(ivl_lpm_t net)
|
||||||
fprintf(vvp_out, ", %u, %u;\n", base, width);
|
fprintf(vvp_out, ", %u, %u;\n", base, width);
|
||||||
} else {
|
} else {
|
||||||
const char*sel_symbol = draw_net_input(sel);
|
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",
|
fprintf(vvp_out, "L_%p%s .part/v %s",
|
||||||
net, dly, draw_net_input(ivl_lpm_data(net,0)));
|
net, dly, draw_net_input(ivl_lpm_data(net,0)));
|
||||||
fprintf(vvp_out, ", %s", sel_symbol);
|
fprintf(vvp_out, ", %s", sel_symbol);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue