Skip to content

Commit

Permalink
Fix for pr2922063.
Browse files Browse the repository at this point in the history
When handling the $signed/$unsigned system functions, the compiler
was applying the new signed/unsigned property to the NetExpr object
representing the input argument. This caused the input argument to
be evaluated incorrectly. This patch fixes this by applying the new
property to the NetExpr object created to pad the result to the
required size.

In testing this fix, it was also discovered that the width of the
input argument expression was not being calculated correctly. This
patch also fixes this issue.
  • Loading branch information
martinwhitaker authored and steveicarus committed Jan 23, 2010
1 parent b855b03 commit 14b2037
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 22 deletions.
2 changes: 2 additions & 0 deletions PExpr.h
Expand Up @@ -682,6 +682,8 @@ class PECallFunction : public PExpr {

bool check_call_matches_definition_(Design*des, NetScope*dscope) const;

NetExpr* cast_to_width_(NetExpr*expr, int wid, bool signed_flag) const;

NetExpr* elaborate_sfunc_(Design*des, NetScope*scope, int expr_wid) const;
NetExpr* elaborate_access_func_(Design*des, NetScope*scope, ivl_nature_t) const;
unsigned test_width_sfunc_(Design*des, NetScope*scope,
Expand Down
68 changes: 48 additions & 20 deletions elab_expr.cc
Expand Up @@ -1087,14 +1087,20 @@ unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope,
if (expr == 0)
return 0;

expr_width_ = expr->test_width(des, scope, min, lval, expr_type__, unsized_flag);
// The argument width is self-determined.
expr_width_ = expr->test_width(des, scope, 0, 0, expr_type__, unsized_flag);
expr_type_ = expr_type__;

// The result width is context dependent.
if (expr_width_ > min)
min = expr_width_;

if (debug_elaborate)
cerr << get_fileline() << ": debug: test_width"
<< " of $signed/$unsigned returns test_width"
<< " of subexpression." << endl;
return expr_width_;
cerr << get_fileline() << ": debug: $signed/$unsigned"
<< " argument width = " << expr_width_
<< ", result width = " << min << "." << endl;

return min;
}

// Run through the arguments of the system function and make
Expand Down Expand Up @@ -1208,6 +1214,34 @@ unsigned PECallFunction::test_width(Design*des, NetScope*scope,
return 0;
}

NetExpr*PECallFunction::cast_to_width_(NetExpr*expr, int wid, bool signed_flag) const
{
/* If the expression is a const, then replace it with a new
const. This is a more efficient result. */
if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr)) {
tmp->cast_signed(signed_flag);
if (wid > (int)(tmp->expr_width())) {
verinum oval = pad_to_width(tmp->value(), wid);
tmp = new NetEConst(oval);
tmp->set_line(*this);
delete expr;
}
return tmp;
}

if (wid < 0)
wid = expr->expr_width();

if (debug_elaborate)
cerr << get_fileline() << ": debug: cast to " << wid
<< " bits" << endl;

NetESelect*tmp = new NetESelect(expr, 0, wid);
tmp->set_line(*this);
tmp->cast_signed(signed_flag);
return tmp;
}

/*
* Given a call to a system function, generate the proper expression
* nodes to represent the call in the netlist. Since we don't support
Expand All @@ -1217,11 +1251,9 @@ unsigned PECallFunction::test_width(Design*des, NetScope*scope,
NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope, int expr_wid) const
{

/* Catch the special case that the system function is the
$signed function. This function is special, in that it does
not lead to executable code but takes the single parameter
and makes it into a signed expression. No bits are changed,
it just changes the interpretation. */
/* Catch the special case that the system function is the $signed
function. Its argument will be evaluated as a self-determined
expression. */
if (strcmp(peek_tail_name(path_), "$signed") == 0) {
if ((parms_.size() != 1) || (parms_[0] == 0)) {
cerr << get_fileline() << ": error: The $signed() function "
Expand All @@ -1231,11 +1263,11 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope, int expr_w
}

PExpr*expr = parms_[0];
NetExpr*sub = expr->elaborate_expr(des, scope, -1, true);
sub->cast_signed(true);
return sub;
NetExpr*sub = expr->elaborate_expr(des, scope, expr_width_, true);

return cast_to_width_(sub, expr_wid, true);
}
/* add $unsigned to match $signed */
/* As above, for the $unsigned function. */
if (strcmp(peek_tail_name(path_), "$unsigned") == 0) {
if ((parms_.size() != 1) || (parms_[0] == 0)) {
cerr << get_fileline() << ": error: The $unsigned() function "
Expand All @@ -1245,13 +1277,9 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope, int expr_w
}

PExpr*expr = parms_[0];
NetExpr*sub = expr->elaborate_expr(des, scope, -1, true);
sub->cast_signed(false);
NetExpr*sub = expr->elaborate_expr(des, scope, expr_width_, true);

if (expr_wid > 0 && (unsigned)expr_wid > sub->expr_width())
sub = pad_to_width(sub, expr_wid, *this);

return sub;
return cast_to_width_(sub, expr_wid, false);
}

/* Interpret the internal $sizeof system function to return
Expand Down
6 changes: 4 additions & 2 deletions tgt-vvp/draw_vpi.c
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003-2009 Stephen Williams (steve@icarus.com)
* Copyright (c) 2003-2010 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
Expand Down Expand Up @@ -184,7 +184,9 @@ static int get_vpi_taskfunc_signal_arg(struct args_info *result,
if (ivl_expr_oper1(vexpr)) return 0;

bexpr = ivl_expr_oper2(expr);
assert(bexpr);

/* This is a pad operation. */
if (!bexpr) return 0;

/* This is a constant bit/part select. */
if (number_is_immediate(bexpr, 64, 1)) {
Expand Down

0 comments on commit 14b2037

Please sign in to comment.