Merge pull request #685 from larsclausen/signed-method
Handle signedness and width expansion for class properties and methods
This commit is contained in:
commit
72b0498af4
22
PExpr.h
22
PExpr.h
|
|
@ -430,6 +430,9 @@ class PEIdent : public PExpr {
|
||||||
NetAssign_*) const;
|
NetAssign_*) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
NetExpr* elaborate_expr_(Design *des, NetScope *scope,
|
||||||
|
unsigned expr_wid, unsigned flags) const;
|
||||||
|
|
||||||
NetExpr*elaborate_expr_param_or_specparam_(Design*des,
|
NetExpr*elaborate_expr_param_or_specparam_(Design*des,
|
||||||
NetScope*scope,
|
NetScope*scope,
|
||||||
const NetExpr*par,
|
const NetExpr*par,
|
||||||
|
|
@ -926,22 +929,25 @@ class PECallFunction : public PExpr {
|
||||||
|
|
||||||
NetExpr* cast_to_width_(NetExpr*expr, unsigned wid) const;
|
NetExpr* cast_to_width_(NetExpr*expr, unsigned wid) const;
|
||||||
|
|
||||||
|
NetExpr* elaborate_expr_(Design *des, NetScope *scope,
|
||||||
|
unsigned flags) const;
|
||||||
|
|
||||||
NetExpr*elaborate_expr_pkg_(Design*des, NetScope*scope,
|
NetExpr*elaborate_expr_pkg_(Design*des, NetScope*scope,
|
||||||
unsigned expr_wid, unsigned flags)const;
|
unsigned flags)const;
|
||||||
|
|
||||||
NetExpr* elaborate_expr_method_(Design*des, NetScope*scope,
|
NetExpr* elaborate_expr_method_(Design*des, NetScope*scope,
|
||||||
symbol_search_results&search_results,
|
symbol_search_results&search_results)
|
||||||
unsigned expr_wid) const;
|
const;
|
||||||
NetExpr* elaborate_expr_method_par_(Design*des, NetScope*scope,
|
NetExpr* elaborate_expr_method_par_(Design*des, NetScope*scope,
|
||||||
symbol_search_results&search_results,
|
symbol_search_results&search_results)
|
||||||
unsigned expr_wid) const;
|
const;
|
||||||
|
|
||||||
|
|
||||||
NetExpr* elaborate_sfunc_(Design*des, NetScope*scope,
|
NetExpr* elaborate_sfunc_(Design*des, NetScope*scope,
|
||||||
unsigned expr_wid,
|
unsigned expr_wid,
|
||||||
unsigned flags) const;
|
unsigned flags) const;
|
||||||
NetExpr* elaborate_access_func_(Design*des, NetScope*scope, ivl_nature_t,
|
NetExpr* elaborate_access_func_(Design*des, NetScope*scope, ivl_nature_t)
|
||||||
unsigned expr_wid) const;
|
const;
|
||||||
unsigned test_width_sfunc_(Design*des, NetScope*scope,
|
unsigned test_width_sfunc_(Design*des, NetScope*scope,
|
||||||
width_mode_t&mode);
|
width_mode_t&mode);
|
||||||
unsigned test_width_method_(Design*des, NetScope*scope,
|
unsigned test_width_method_(Design*des, NetScope*scope,
|
||||||
|
|
@ -949,7 +955,7 @@ class PECallFunction : public PExpr {
|
||||||
width_mode_t&mode);
|
width_mode_t&mode);
|
||||||
|
|
||||||
NetExpr*elaborate_base_(Design*des, NetScope*scope, NetScope*dscope,
|
NetExpr*elaborate_base_(Design*des, NetScope*scope, NetScope*dscope,
|
||||||
unsigned expr_wid, unsigned flags) const;
|
unsigned flags) const;
|
||||||
|
|
||||||
unsigned elaborate_arguments_(Design*des, NetScope*scope,
|
unsigned elaborate_arguments_(Design*des, NetScope*scope,
|
||||||
NetFuncDef*def, bool need_const,
|
NetFuncDef*def, bool need_const,
|
||||||
|
|
|
||||||
|
|
@ -249,9 +249,7 @@ class PCallTask : public Statement {
|
||||||
const char*sys_task_name) const;
|
const char*sys_task_name) const;
|
||||||
NetProc*elaborate_method_func_(NetScope*scope,
|
NetProc*elaborate_method_func_(NetScope*scope,
|
||||||
NetNet*net,
|
NetNet*net,
|
||||||
ivl_variable_type_t type,
|
ivl_type_t type,
|
||||||
unsigned width,
|
|
||||||
bool signed_flag,
|
|
||||||
perm_string method_name,
|
perm_string method_name,
|
||||||
const char*sys_task_name) const;
|
const char*sys_task_name) const;
|
||||||
bool test_task_calls_ok_(Design*des, NetScope*scope) const;
|
bool test_task_calls_ok_(Design*des, NetScope*scope) const;
|
||||||
|
|
|
||||||
147
elab_expr.cc
147
elab_expr.cc
|
|
@ -1873,8 +1873,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope,
|
||||||
}
|
}
|
||||||
|
|
||||||
NetExpr* PECallFunction::elaborate_access_func_(Design*des, NetScope*scope,
|
NetExpr* PECallFunction::elaborate_access_func_(Design*des, NetScope*scope,
|
||||||
ivl_nature_t nature,
|
ivl_nature_t nature) const
|
||||||
unsigned expr_wid) const
|
|
||||||
{
|
{
|
||||||
// An access function must have 1 or 2 arguments.
|
// An access function must have 1 or 2 arguments.
|
||||||
ivl_assert(*this, parms_.size()==2 || parms_.size()==1);
|
ivl_assert(*this, parms_.size()==2 || parms_.size()==1);
|
||||||
|
|
@ -1925,8 +1924,7 @@ NetExpr* PECallFunction::elaborate_access_func_(Design*des, NetScope*scope,
|
||||||
|
|
||||||
NetExpr*tmp = new NetEAccess(branch, nature);
|
NetExpr*tmp = new NetEAccess(branch, nature);
|
||||||
tmp->set_line(*this);
|
tmp->set_line(*this);
|
||||||
|
return tmp;
|
||||||
return pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -1938,7 +1936,6 @@ static NetExpr* check_for_enum_methods(const LineInfo*li,
|
||||||
const pform_name_t&use_path,
|
const pform_name_t&use_path,
|
||||||
perm_string method_name,
|
perm_string method_name,
|
||||||
NetExpr*expr,
|
NetExpr*expr,
|
||||||
unsigned rtn_wid,
|
|
||||||
PExpr*parg, unsigned args)
|
PExpr*parg, unsigned args)
|
||||||
{
|
{
|
||||||
if (debug_elaborate) {
|
if (debug_elaborate) {
|
||||||
|
|
@ -1948,8 +1945,6 @@ static NetExpr* check_for_enum_methods(const LineInfo*li,
|
||||||
<< endl;
|
<< endl;
|
||||||
cerr << li->get_fileline() << ": " << __func__ << ": "
|
cerr << li->get_fileline() << ": " << __func__ << ": "
|
||||||
<< "use_path=" << use_path << endl;
|
<< "use_path=" << use_path << endl;
|
||||||
cerr << li->get_fileline() << ": " << __func__ << ": "
|
|
||||||
<< "rtn_wid=" << rtn_wid << endl;
|
|
||||||
cerr << li->get_fileline() << ": " << __func__ << ": "
|
cerr << li->get_fileline() << ": " << __func__ << ": "
|
||||||
<< "expr=" << *expr << endl;
|
<< "expr=" << *expr << endl;
|
||||||
}
|
}
|
||||||
|
|
@ -2569,7 +2564,6 @@ NetExpr* PEIdent::elaborate_expr_class_field_(Design*des, NetScope*scope,
|
||||||
}
|
}
|
||||||
|
|
||||||
NetExpr* PECallFunction::elaborate_expr_pkg_(Design*des, NetScope*scope,
|
NetExpr* PECallFunction::elaborate_expr_pkg_(Design*des, NetScope*scope,
|
||||||
unsigned expr_wid,
|
|
||||||
unsigned flags) const
|
unsigned flags) const
|
||||||
{
|
{
|
||||||
if (debug_elaborate) {
|
if (debug_elaborate) {
|
||||||
|
|
@ -2594,7 +2588,7 @@ NetExpr* PECallFunction::elaborate_expr_pkg_(Design*des, NetScope*scope,
|
||||||
if (! check_call_matches_definition_(des, dscope))
|
if (! check_call_matches_definition_(des, dscope))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return elaborate_base_(des, scope, dscope, expr_wid, flags);
|
return elaborate_base_(des, scope, dscope, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
||||||
|
|
@ -2611,14 +2605,24 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
||||||
<< " at " << package_->get_fileline() << endl;
|
<< " at " << package_->get_fileline() << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (package_)
|
|
||||||
return elaborate_expr_pkg_(des, scope, expr_wid, flags);
|
|
||||||
|
|
||||||
flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
|
|
||||||
|
|
||||||
if (peek_tail_name(path_)[0] == '$')
|
if (peek_tail_name(path_)[0] == '$')
|
||||||
return elaborate_sfunc_(des, scope, expr_wid, flags);
|
return elaborate_sfunc_(des, scope, expr_wid, flags);
|
||||||
|
|
||||||
|
NetExpr *result = elaborate_expr_(des, scope, flags);
|
||||||
|
if (!result || !type_is_vectorable(expr_type_))
|
||||||
|
return result;
|
||||||
|
|
||||||
|
return pad_to_width(result, expr_wid, signed_flag_, *this);
|
||||||
|
}
|
||||||
|
|
||||||
|
NetExpr* PECallFunction::elaborate_expr_(Design*des, NetScope*scope,
|
||||||
|
unsigned flags) const
|
||||||
|
{
|
||||||
|
if (package_)
|
||||||
|
return elaborate_expr_pkg_(des, scope, flags);
|
||||||
|
|
||||||
|
flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
|
||||||
|
|
||||||
// Search for the symbol. This should turn up a scope.
|
// Search for the symbol. This should turn up a scope.
|
||||||
symbol_search_results search_results;
|
symbol_search_results search_results;
|
||||||
bool search_flag = symbol_search(this, des, scope, path_, &search_results);
|
bool search_flag = symbol_search(this, des, scope, path_, &search_results);
|
||||||
|
|
@ -2655,7 +2659,7 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
||||||
|
|
||||||
// Maybe this is a method of an object? Give it a try.
|
// Maybe this is a method of an object? Give it a try.
|
||||||
if (!search_results.path_tail.empty()) {
|
if (!search_results.path_tail.empty()) {
|
||||||
NetExpr*tmp = elaborate_expr_method_(des, scope, search_results, expr_wid);
|
NetExpr*tmp = elaborate_expr_method_(des, scope, search_results);
|
||||||
if (tmp) {
|
if (tmp) {
|
||||||
if (debug_elaborate) {
|
if (debug_elaborate) {
|
||||||
cerr << get_fileline() << ": PECallFunction::elaborate_expr: "
|
cerr << get_fileline() << ": PECallFunction::elaborate_expr: "
|
||||||
|
|
@ -2688,8 +2692,7 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
||||||
// way.
|
// way.
|
||||||
ivl_nature_t access_nature = find_access_function(path_);
|
ivl_nature_t access_nature = find_access_function(path_);
|
||||||
if (access_nature)
|
if (access_nature)
|
||||||
return elaborate_access_func_(des, scope, access_nature,
|
return elaborate_access_func_(des, scope, access_nature);
|
||||||
expr_wid);
|
|
||||||
|
|
||||||
// Nothing was found so report this as an error.
|
// Nothing was found so report this as an error.
|
||||||
cerr << get_fileline() << ": error: No function named `" << path_
|
cerr << get_fileline() << ": error: No function named `" << path_
|
||||||
|
|
@ -2726,8 +2729,7 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
||||||
use_search_results.net = scope->find_signal(perm_string::literal(THIS_TOKEN));
|
use_search_results.net = scope->find_signal(perm_string::literal(THIS_TOKEN));
|
||||||
ivl_assert(*this, use_search_results.net);
|
ivl_assert(*this, use_search_results.net);
|
||||||
|
|
||||||
NetExpr*tmp = elaborate_expr_method_(des, scope, use_search_results, expr_wid);
|
return elaborate_expr_method_(des, scope, use_search_results);
|
||||||
return tmp;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2753,7 +2755,7 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
||||||
scope->is_const_func(false);
|
scope->is_const_func(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return elaborate_base_(des, scope, dscope, expr_wid, flags);
|
return elaborate_base_(des, scope, dscope, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
||||||
|
|
@ -2766,7 +2768,7 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
||||||
}
|
}
|
||||||
|
|
||||||
NetExpr* PECallFunction::elaborate_base_(Design*des, NetScope*scope, NetScope*dscope,
|
NetExpr* PECallFunction::elaborate_base_(Design*des, NetScope*scope, NetScope*dscope,
|
||||||
unsigned expr_wid, unsigned flags) const
|
unsigned flags) const
|
||||||
{
|
{
|
||||||
|
|
||||||
if (! check_call_matches_definition_(des, dscope))
|
if (! check_call_matches_definition_(des, dscope))
|
||||||
|
|
@ -2845,11 +2847,7 @@ NetExpr* PECallFunction::elaborate_base_(Design*des, NetScope*scope, NetScope*ds
|
||||||
NetESignal*eres = new NetESignal(res);
|
NetESignal*eres = new NetESignal(res);
|
||||||
NetEUFunc*func = new NetEUFunc(scope, dscope, eres, parms, need_const);
|
NetEUFunc*func = new NetEUFunc(scope, dscope, eres, parms, need_const);
|
||||||
func->set_line(*this);
|
func->set_line(*this);
|
||||||
|
return func;
|
||||||
if(res->darray_type())
|
|
||||||
return func;
|
|
||||||
|
|
||||||
return pad_to_width(func, expr_wid, signed_flag_, *this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cerr << get_fileline() << ": internal error: Unable to locate "
|
cerr << get_fileline() << ": internal error: Unable to locate "
|
||||||
|
|
@ -2960,8 +2958,8 @@ unsigned PECallFunction::elaborate_arguments_(Design*des, NetScope*scope,
|
||||||
* "len" in path_tail, and if x is a string object, we can handle the case.
|
* "len" in path_tail, and if x is a string object, we can handle the case.
|
||||||
*/
|
*/
|
||||||
NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
|
NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
|
||||||
symbol_search_results&search_results,
|
symbol_search_results&search_results)
|
||||||
unsigned expr_wid) const
|
const
|
||||||
{
|
{
|
||||||
if (!gn_system_verilog()) {
|
if (!gn_system_verilog()) {
|
||||||
cerr << get_fileline() << ": error: "
|
cerr << get_fileline() << ": error: "
|
||||||
|
|
@ -3000,7 +2998,7 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (search_results.par_val && search_results.par_type) {
|
if (search_results.par_val && search_results.par_type) {
|
||||||
return elaborate_expr_method_par_(des, scope, search_results, expr_wid);
|
return elaborate_expr_method_par_(des, scope, search_results);
|
||||||
}
|
}
|
||||||
|
|
||||||
NetExpr* sub_expr = 0;
|
NetExpr* sub_expr = 0;
|
||||||
|
|
@ -3058,7 +3056,7 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
|
||||||
<< "takes no arguments" << endl;
|
<< "takes no arguments" << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
}
|
}
|
||||||
NetESFunc*sys_expr = new NetESFunc("$size", IVL_VT_BOOL, 32, 1);
|
NetESFunc*sys_expr = new NetESFunc("$size", &netvector_t::atom2u32, 1);
|
||||||
sys_expr->set_line(*this);
|
sys_expr->set_line(*this);
|
||||||
sys_expr->parm(0, sub_expr);
|
sys_expr->parm(0, sub_expr);
|
||||||
return sys_expr;
|
return sys_expr;
|
||||||
|
|
@ -3076,19 +3074,20 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
|
||||||
|
|
||||||
// Get the method name that we are looking for.
|
// Get the method name that we are looking for.
|
||||||
perm_string method_name = search_results.path_tail.back().name;
|
perm_string method_name = search_results.path_tail.back().name;
|
||||||
|
|
||||||
if (method_name == "size") {
|
if (method_name == "size") {
|
||||||
if (parms_.size() != 0) {
|
if (parms_.size() != 0) {
|
||||||
cerr << get_fileline() << ": error: size() method "
|
cerr << get_fileline() << ": error: size() method "
|
||||||
<< "takes no arguments" << endl;
|
<< "takes no arguments" << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
}
|
}
|
||||||
NetESFunc*sys_expr = new NetESFunc("$size", IVL_VT_BOOL, 32, 1);
|
NetESFunc*sys_expr = new NetESFunc("$size", &netvector_t::atom2u32, 1);
|
||||||
sys_expr->set_line(*this);
|
sys_expr->set_line(*this);
|
||||||
sys_expr->parm(0, sub_expr);
|
sys_expr->parm(0, sub_expr);
|
||||||
return sys_expr;
|
return sys_expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const netqueue_t*queue = search_results.net->queue_type();
|
||||||
|
ivl_type_t element_type = queue->element_type();
|
||||||
if (method_name == "pop_back") {
|
if (method_name == "pop_back") {
|
||||||
if (parms_.size() != 0) {
|
if (parms_.size() != 0) {
|
||||||
cerr << get_fileline() << ": error: pop_back() method "
|
cerr << get_fileline() << ": error: pop_back() method "
|
||||||
|
|
@ -3096,7 +3095,7 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
}
|
}
|
||||||
NetESFunc*sys_expr = new NetESFunc("$ivl_queue_method$pop_back",
|
NetESFunc*sys_expr = new NetESFunc("$ivl_queue_method$pop_back",
|
||||||
expr_type_, expr_width_, 1);
|
element_type, 1);
|
||||||
sys_expr->set_line(*this);
|
sys_expr->set_line(*this);
|
||||||
sys_expr->parm(0, sub_expr);
|
sys_expr->parm(0, sub_expr);
|
||||||
return sys_expr;
|
return sys_expr;
|
||||||
|
|
@ -3109,7 +3108,7 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
}
|
}
|
||||||
NetESFunc*sys_expr = new NetESFunc("$ivl_queue_method$pop_front",
|
NetESFunc*sys_expr = new NetESFunc("$ivl_queue_method$pop_front",
|
||||||
expr_type_, expr_width_, 1);
|
element_type, 1);
|
||||||
sys_expr->set_line(*this);
|
sys_expr->set_line(*this);
|
||||||
sys_expr->parm(0, sub_expr);
|
sys_expr->parm(0, sub_expr);
|
||||||
return sys_expr;
|
return sys_expr;
|
||||||
|
|
@ -3134,8 +3133,7 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
|
||||||
return check_for_enum_methods(this, des, scope,
|
return check_for_enum_methods(this, des, scope,
|
||||||
netenum, path_,
|
netenum, path_,
|
||||||
method_name, sub_expr,
|
method_name, sub_expr,
|
||||||
expr_wid, tmp,
|
tmp, parms_.size());
|
||||||
parms_.size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Class methods. Generate function call to the class method.
|
// Class methods. Generate function call to the class method.
|
||||||
|
|
@ -3186,35 +3184,35 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
|
||||||
|
|
||||||
if (method_name == "len") {
|
if (method_name == "len") {
|
||||||
NetESFunc*sys_expr = new NetESFunc("$ivl_string_method$len",
|
NetESFunc*sys_expr = new NetESFunc("$ivl_string_method$len",
|
||||||
IVL_VT_BOOL, 32, 1);
|
&netvector_t::atom2u32, 1);
|
||||||
sys_expr->parm(0, sub_expr);
|
sys_expr->parm(0, sub_expr);
|
||||||
return sys_expr;
|
return sys_expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (method_name == "atoi") {
|
if (method_name == "atoi") {
|
||||||
NetESFunc*sys_expr = new NetESFunc("$ivl_string_method$atoi",
|
NetESFunc*sys_expr = new NetESFunc("$ivl_string_method$atoi",
|
||||||
IVL_VT_BOOL, integer_width, 1);
|
netvector_t::integer_type(), 1);
|
||||||
sys_expr->parm(0, sub_expr);
|
sys_expr->parm(0, sub_expr);
|
||||||
return sys_expr;
|
return sys_expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (method_name == "atoreal") {
|
if (method_name == "atoreal") {
|
||||||
NetESFunc*sys_expr = new NetESFunc("$ivl_string_method$atoreal",
|
NetESFunc*sys_expr = new NetESFunc("$ivl_string_method$atoreal",
|
||||||
IVL_VT_REAL, 1, 1);
|
&netreal_t::type_real, 1);
|
||||||
sys_expr->parm(0, sub_expr);
|
sys_expr->parm(0, sub_expr);
|
||||||
return sys_expr;
|
return sys_expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (method_name == "atohex") {
|
if (method_name == "atohex") {
|
||||||
NetESFunc*sys_expr = new NetESFunc("$ivl_string_method$atohex",
|
NetESFunc*sys_expr = new NetESFunc("$ivl_string_method$atohex",
|
||||||
IVL_VT_BOOL, integer_width, 1);
|
netvector_t::integer_type(), 1);
|
||||||
sys_expr->parm(0, sub_expr);
|
sys_expr->parm(0, sub_expr);
|
||||||
return sys_expr;
|
return sys_expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (method_name == "substr") {
|
if (method_name == "substr") {
|
||||||
NetESFunc*sys_expr = new NetESFunc("$ivl_string_method$substr",
|
NetESFunc*sys_expr = new NetESFunc("$ivl_string_method$substr",
|
||||||
IVL_VT_STRING, 1, 3);
|
&netstring_t::type_string, 3);
|
||||||
sys_expr->set_line(*this);
|
sys_expr->set_line(*this);
|
||||||
|
|
||||||
// First argument is the source string.
|
// First argument is the source string.
|
||||||
|
|
@ -3249,8 +3247,8 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
|
||||||
* stable in the sense that they generate a constant value for a constant input.
|
* stable in the sense that they generate a constant value for a constant input.
|
||||||
*/
|
*/
|
||||||
NetExpr* PECallFunction::elaborate_expr_method_par_(Design*des, NetScope*scope,
|
NetExpr* PECallFunction::elaborate_expr_method_par_(Design*des, NetScope*scope,
|
||||||
symbol_search_results&search_results,
|
symbol_search_results&search_results)
|
||||||
unsigned expr_wid) const
|
const
|
||||||
{
|
{
|
||||||
ivl_assert(*this, search_results.par_val);
|
ivl_assert(*this, search_results.par_val);
|
||||||
ivl_assert(*this, search_results.par_type);
|
ivl_assert(*this, search_results.par_type);
|
||||||
|
|
@ -3272,13 +3270,13 @@ NetExpr* PECallFunction::elaborate_expr_method_par_(Design*des, NetScope*scope,
|
||||||
if (method_name=="len") {
|
if (method_name=="len") {
|
||||||
NetEConst*use_val = make_const_val(par_value.size());
|
NetEConst*use_val = make_const_val(par_value.size());
|
||||||
use_val->set_line(*this);
|
use_val->set_line(*this);
|
||||||
return pad_to_width(use_val, expr_wid, *this);
|
return use_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (method_name == "atoi") {
|
if (method_name == "atoi") {
|
||||||
NetEConst*use_val = make_const_val(atoi(par_value.c_str()));
|
NetEConst*use_val = make_const_val(atoi(par_value.c_str()));
|
||||||
use_val->set_line(*this);
|
use_val->set_line(*this);
|
||||||
return pad_to_width(use_val, expr_wid, true, *this);
|
return use_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (method_name == "atoreal") {
|
if (method_name == "atoreal") {
|
||||||
|
|
@ -3290,7 +3288,7 @@ NetExpr* PECallFunction::elaborate_expr_method_par_(Design*des, NetScope*scope,
|
||||||
if (method_name == "atohex") {
|
if (method_name == "atohex") {
|
||||||
NetEConst*use_val = make_const_val(strtoul(par_value.c_str(),0,16));
|
NetEConst*use_val = make_const_val(strtoul(par_value.c_str(),0,16));
|
||||||
use_val->set_line(*this);
|
use_val->set_line(*this);
|
||||||
return pad_to_width(use_val, expr_wid, true, *this);
|
return use_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returning 0 here will cause the caller to print an error
|
// Returning 0 here will cause the caller to print an error
|
||||||
|
|
@ -3964,6 +3962,16 @@ unsigned PEIdent::test_width_method_(Design*des, NetScope*scope, width_mode_t&)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (const struct netqueue_t *queue = net->queue_type()) {
|
||||||
|
if (member_name == "pop_back" || member_name == "pop_front") {
|
||||||
|
expr_type_ = queue->element_base_type();
|
||||||
|
expr_width_ = queue->element_width();
|
||||||
|
min_width_ = expr_width_;
|
||||||
|
signed_flag_ = queue->get_signed();
|
||||||
|
return expr_width_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Look for the enumeration attributes.
|
// Look for the enumeration attributes.
|
||||||
if (const netenum_t*netenum = net->enumeration()) {
|
if (const netenum_t*netenum = net->enumeration()) {
|
||||||
if (member_name == "num") {
|
if (member_name == "num") {
|
||||||
|
|
@ -4531,6 +4539,18 @@ NetExpr* PEIdent::elaborate_expr_class_member_(Design*des, NetScope*scope,
|
||||||
*/
|
*/
|
||||||
NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||||
unsigned expr_wid, unsigned flags) const
|
unsigned expr_wid, unsigned flags) const
|
||||||
|
{
|
||||||
|
NetExpr *result;
|
||||||
|
|
||||||
|
result = elaborate_expr_(des, scope, expr_wid, flags);
|
||||||
|
if (!result || !type_is_vectorable(expr_type_))
|
||||||
|
return result;
|
||||||
|
|
||||||
|
return pad_to_width(result, expr_wid, signed_flag_, *this);
|
||||||
|
}
|
||||||
|
|
||||||
|
NetExpr* PEIdent::elaborate_expr_(Design*des, NetScope*scope,
|
||||||
|
unsigned expr_wid, unsigned flags) const
|
||||||
{
|
{
|
||||||
ivl_assert(*this, scope);
|
ivl_assert(*this, scope);
|
||||||
|
|
||||||
|
|
@ -4596,13 +4616,9 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetExpr*tmp = elaborate_expr_param_or_specparam_(des, scope, sr.par_val,
|
return elaborate_expr_param_or_specparam_(des, scope, sr.par_val,
|
||||||
sr.scope, sr.par_type,
|
sr.scope, sr.par_type,
|
||||||
expr_wid, flags);
|
expr_wid, flags);
|
||||||
|
|
||||||
if (!tmp) return 0;
|
|
||||||
|
|
||||||
return pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the identifier names a signal (a variable or a net)
|
// If the identifier names a signal (a variable or a net)
|
||||||
|
|
@ -4637,11 +4653,9 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetExpr*tmp = check_for_struct_members(this, des, use_scope,
|
return check_for_struct_members(this, des, use_scope, sr.net,
|
||||||
sr.net, sr.path_head.back().index,
|
sr.path_head.back().index,
|
||||||
sr.path_tail);
|
sr.path_tail);
|
||||||
if (!tmp) return 0;
|
|
||||||
else return pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is an array object, and there are members in
|
// If this is an array object, and there are members in
|
||||||
|
|
@ -4657,7 +4671,9 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||||
ivl_assert(*this, sr.path_tail.size() == 1);
|
ivl_assert(*this, sr.path_tail.size() == 1);
|
||||||
const name_component_t member_comp = sr.path_tail.front();
|
const name_component_t member_comp = sr.path_tail.front();
|
||||||
if (member_comp.name == "size") {
|
if (member_comp.name == "size") {
|
||||||
NetESFunc*fun = new NetESFunc("$size", IVL_VT_BOOL, 32, 1);
|
NetESFunc*fun = new NetESFunc("$size",
|
||||||
|
&netvector_t::atom2s32,
|
||||||
|
1);
|
||||||
fun->set_line(*this);
|
fun->set_line(*this);
|
||||||
|
|
||||||
NetESignal*arg = new NetESignal(sr.net);
|
NetESignal*arg = new NetESignal(sr.net);
|
||||||
|
|
@ -4773,11 +4789,10 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||||
ivl_assert(*this, sr.path_tail.size() == 1);
|
ivl_assert(*this, sr.path_tail.size() == 1);
|
||||||
const name_component_t member_comp = sr.path_tail.front();
|
const name_component_t member_comp = sr.path_tail.front();
|
||||||
const netqueue_t*queue = sr.net->queue_type();
|
const netqueue_t*queue = sr.net->queue_type();
|
||||||
ivl_variable_type_t qelem_type = queue->element_base_type();
|
ivl_type_t element_type = queue->element_type();
|
||||||
unsigned qelem_width = queue->element_width();
|
|
||||||
if (member_comp.name == "pop_back") {
|
if (member_comp.name == "pop_back") {
|
||||||
NetESFunc*fun = new NetESFunc("$ivl_queue_method$pop_back",
|
NetESFunc*fun = new NetESFunc("$ivl_queue_method$pop_back",
|
||||||
qelem_type, qelem_width, 1);
|
element_type, 1);
|
||||||
fun->set_line(*this);
|
fun->set_line(*this);
|
||||||
|
|
||||||
NetESignal*arg = new NetESignal(sr.net);
|
NetESignal*arg = new NetESignal(sr.net);
|
||||||
|
|
@ -4789,7 +4804,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||||
|
|
||||||
if (member_comp.name == "pop_front") {
|
if (member_comp.name == "pop_front") {
|
||||||
NetESFunc*fun = new NetESFunc("$ivl_queue_method$pop_front",
|
NetESFunc*fun = new NetESFunc("$ivl_queue_method$pop_front",
|
||||||
qelem_type, qelem_width, 1);
|
element_type, 1);
|
||||||
fun->set_line(*this);
|
fun->set_line(*this);
|
||||||
|
|
||||||
NetESignal*arg = new NetESignal(sr.net);
|
NetESignal*arg = new NetESignal(sr.net);
|
||||||
|
|
@ -4849,7 +4864,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||||
return check_for_enum_methods(this, des, use_scope,
|
return check_for_enum_methods(this, des, use_scope,
|
||||||
netenum, sr.path_head,
|
netenum, sr.path_head,
|
||||||
member_comp.name,
|
member_comp.name,
|
||||||
expr, expr_wid, NULL, 0);
|
expr, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ivl_assert(*this, sr.path_tail.empty());
|
ivl_assert(*this, sr.path_tail.empty());
|
||||||
|
|
@ -4865,7 +4880,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||||
<< ", tmp=" << *tmp << endl;
|
<< ", tmp=" << *tmp << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the identifier is a named event
|
// If the identifier is a named event
|
||||||
|
|
@ -5496,8 +5511,6 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
|
||||||
<< "Elaborate parameter <" << path_
|
<< "Elaborate parameter <" << path_
|
||||||
<< "> as enumeration constant." << *etmp << endl;
|
<< "> as enumeration constant." << *etmp << endl;
|
||||||
tmp = etmp->dup_expr();
|
tmp = etmp->dup_expr();
|
||||||
tmp = pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
perm_string name = peek_tail_name(path_);
|
perm_string name = peek_tail_name(path_);
|
||||||
|
|
||||||
|
|
|
||||||
28
elaborate.cc
28
elaborate.cc
|
|
@ -3676,9 +3676,7 @@ NetProc* PCallTask::elaborate_queue_method_(Design*des, NetScope*scope,
|
||||||
*/
|
*/
|
||||||
NetProc* PCallTask::elaborate_method_func_(NetScope*scope,
|
NetProc* PCallTask::elaborate_method_func_(NetScope*scope,
|
||||||
NetNet*net,
|
NetNet*net,
|
||||||
ivl_variable_type_t type,
|
ivl_type_t type,
|
||||||
unsigned width,
|
|
||||||
bool signed_flag,
|
|
||||||
perm_string method_name,
|
perm_string method_name,
|
||||||
const char*sys_task_name) const
|
const char*sys_task_name) const
|
||||||
{
|
{
|
||||||
|
|
@ -3686,15 +3684,14 @@ NetProc* PCallTask::elaborate_method_func_(NetScope*scope,
|
||||||
<< method_name << "' is being called as a task." << endl;
|
<< method_name << "' is being called as a task." << endl;
|
||||||
|
|
||||||
// Generate the function.
|
// Generate the function.
|
||||||
NetESFunc*sys_expr = new NetESFunc(sys_task_name, type, width, 1);
|
NetESFunc*sys_expr = new NetESFunc(sys_task_name, type, 1);
|
||||||
sys_expr->set_line(*this);
|
sys_expr->set_line(*this);
|
||||||
NetESignal*arg = new NetESignal(net);
|
NetESignal*arg = new NetESignal(net);
|
||||||
arg->set_line(*net);
|
arg->set_line(*net);
|
||||||
sys_expr->parm(0, arg);
|
sys_expr->parm(0, arg);
|
||||||
// Create a L-value that matches the function return type.
|
// Create a L-value that matches the function return type.
|
||||||
NetNet*tmp;
|
NetNet*tmp;
|
||||||
netvector_t*tmp_vec = new netvector_t(type, width-1, 0, signed_flag);
|
tmp = new NetNet(scope, scope->local_symbol(), NetNet::REG, type);
|
||||||
tmp = new NetNet(scope, scope->local_symbol(), NetNet::REG, tmp_vec);
|
|
||||||
tmp->set_line(*this);
|
tmp->set_line(*this);
|
||||||
NetAssign_*lv = new NetAssign_(tmp);
|
NetAssign_*lv = new NetAssign_(tmp);
|
||||||
// Generate an assign to the fake L-value.
|
// Generate an assign to the fake L-value.
|
||||||
|
|
@ -3782,9 +3779,8 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope,
|
||||||
else if (method_name=="size")
|
else if (method_name=="size")
|
||||||
// This returns an int. It could be removed, but keep for now.
|
// This returns an int. It could be removed, but keep for now.
|
||||||
return elaborate_method_func_(scope, net,
|
return elaborate_method_func_(scope, net,
|
||||||
IVL_VT_BOOL, 32,
|
&netvector_t::atom2s32,
|
||||||
true, method_name,
|
method_name, "$size");
|
||||||
"$size");
|
|
||||||
else if (method_name=="reverse") {
|
else if (method_name=="reverse") {
|
||||||
cerr << get_fileline() << ": sorry: 'reverse()' "
|
cerr << get_fileline() << ": sorry: 'reverse()' "
|
||||||
"array sorting method is not currently supported."
|
"array sorting method is not currently supported."
|
||||||
|
|
@ -3825,15 +3821,13 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope,
|
||||||
"$ivl_queue_method$insert");
|
"$ivl_queue_method$insert");
|
||||||
else if (method_name == "pop_front")
|
else if (method_name == "pop_front")
|
||||||
return elaborate_method_func_(scope, net,
|
return elaborate_method_func_(scope, net,
|
||||||
use_darray->element_base_type(),
|
use_darray->element_type(),
|
||||||
use_darray->element_width(),
|
method_name,
|
||||||
false, method_name,
|
|
||||||
"$ivl_queue_method$pop_front");
|
"$ivl_queue_method$pop_front");
|
||||||
else if (method_name == "pop_back")
|
else if (method_name == "pop_back")
|
||||||
return elaborate_method_func_(scope, net,
|
return elaborate_method_func_(scope, net,
|
||||||
use_darray->element_base_type(),
|
use_darray->element_type(),
|
||||||
use_darray->element_width(),
|
method_name,
|
||||||
false, method_name,
|
|
||||||
"$ivl_queue_method$pop_back");
|
"$ivl_queue_method$pop_back");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5324,12 +5318,12 @@ NetProc* PForeach::elaborate(Design*des, NetScope*scope) const
|
||||||
idx_exp->set_line(*this);
|
idx_exp->set_line(*this);
|
||||||
|
|
||||||
// Make an initialization expression for the index.
|
// Make an initialization expression for the index.
|
||||||
NetESFunc*init_expr = new NetESFunc("$low", IVL_VT_BOOL, 32, 1);
|
NetESFunc*init_expr = new NetESFunc("$low", &netvector_t::atom2s32, 1);
|
||||||
init_expr->set_line(*this);
|
init_expr->set_line(*this);
|
||||||
init_expr->parm(0, array_exp);
|
init_expr->parm(0, array_exp);
|
||||||
|
|
||||||
// Make a condition expression: idx <= $high(array)
|
// Make a condition expression: idx <= $high(array)
|
||||||
NetESFunc*high_exp = new NetESFunc("$high", IVL_VT_BOOL, 32, 1);
|
NetESFunc*high_exp = new NetESFunc("$high", &netvector_t::atom2s32, 1);
|
||||||
high_exp->set_line(*this);
|
high_exp->set_line(*this);
|
||||||
high_exp->parm(0, array_exp);
|
high_exp->parm(0, array_exp);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,156 @@
|
||||||
|
// Check that the signedness of methods on the built-in enum type is handled
|
||||||
|
// correctly when calling the method with parenthesis.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
bit failed = 1'b0;
|
||||||
|
|
||||||
|
`define check(x) \
|
||||||
|
if (!(x)) begin \
|
||||||
|
$display("FAILED(%0d): ", `__LINE__, `"x`"); \
|
||||||
|
failed = 1'b1; \
|
||||||
|
end
|
||||||
|
|
||||||
|
int unsigned x = 10;
|
||||||
|
int y = 10;
|
||||||
|
int z;
|
||||||
|
|
||||||
|
enum shortint {
|
||||||
|
A = -1,
|
||||||
|
B = -2,
|
||||||
|
C = -3
|
||||||
|
} es;
|
||||||
|
|
||||||
|
enum bit [15:0] {
|
||||||
|
X = 65535,
|
||||||
|
Y = 65534,
|
||||||
|
Z = 65533
|
||||||
|
} eu;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
es = B;
|
||||||
|
eu = Y;
|
||||||
|
|
||||||
|
// These all evaluate as signed
|
||||||
|
`check($signed(eu.first()) < 0)
|
||||||
|
`check(es.first() < 0)
|
||||||
|
|
||||||
|
`check($signed(eu.last()) < 0)
|
||||||
|
`check(es.last() < 0)
|
||||||
|
|
||||||
|
`check($signed(eu.prev()) < 0)
|
||||||
|
`check(es.prev() < 0)
|
||||||
|
|
||||||
|
`check($signed(eu.next()) < 0)
|
||||||
|
`check(es.next() < 0)
|
||||||
|
|
||||||
|
// These all evaluate as unsigned
|
||||||
|
`check(eu.first() > 0)
|
||||||
|
`check({es.first()} > 0)
|
||||||
|
`check($unsigned(es.first()) > 0)
|
||||||
|
`check(es.first() > 16'h0)
|
||||||
|
|
||||||
|
`check(eu.last() > 0)
|
||||||
|
`check({es.last()} > 0)
|
||||||
|
`check($unsigned(es.last()) > 0)
|
||||||
|
`check(es.last() > 16'h0)
|
||||||
|
|
||||||
|
`check(eu.prev() > 0)
|
||||||
|
`check({es.prev()} > 0)
|
||||||
|
`check($unsigned(es.prev()) > 0)
|
||||||
|
`check(es.prev() > 16'h0)
|
||||||
|
|
||||||
|
`check(eu.next() > 0)
|
||||||
|
`check({es.next()} > 0)
|
||||||
|
`check($unsigned(es.next()) > 0)
|
||||||
|
`check(es.next() > 16'h0)
|
||||||
|
|
||||||
|
// In arithmetic expressions if one operand is unsigned all operands are
|
||||||
|
// considered unsigned
|
||||||
|
z = eu.first() + x;
|
||||||
|
`check(z === 65545)
|
||||||
|
z = eu.first() + y;
|
||||||
|
`check(z === 65545)
|
||||||
|
|
||||||
|
z = eu.last() + x;
|
||||||
|
`check(z === 65543)
|
||||||
|
z = eu.last() + y;
|
||||||
|
`check(z === 65543)
|
||||||
|
|
||||||
|
z = eu.prev() + x;
|
||||||
|
`check(z === 65545)
|
||||||
|
z = eu.prev() + y;
|
||||||
|
`check(z === 65545)
|
||||||
|
|
||||||
|
z = eu.next() + x;
|
||||||
|
`check(z === 65543)
|
||||||
|
z = eu.next() + y;
|
||||||
|
`check(z === 65543)
|
||||||
|
|
||||||
|
z = es.first() + x;
|
||||||
|
`check(z === 65545)
|
||||||
|
z = es.first() + y;
|
||||||
|
`check(z === 9)
|
||||||
|
|
||||||
|
z = es.last() + x;
|
||||||
|
`check(z === 65543)
|
||||||
|
z = es.last() + y;
|
||||||
|
`check(z === 7)
|
||||||
|
|
||||||
|
z = es.prev() + x;
|
||||||
|
`check(z === 65545)
|
||||||
|
z = es.prev() + y;
|
||||||
|
`check(z === 9)
|
||||||
|
|
||||||
|
z = es.next() + x;
|
||||||
|
`check(z === 65543)
|
||||||
|
z = es.next() + y;
|
||||||
|
`check(z === 7)
|
||||||
|
|
||||||
|
// For ternary operators if one operand is unsigned the result is unsigend
|
||||||
|
z = x ? eu.first() : x;
|
||||||
|
`check(z === 65535)
|
||||||
|
z = x ? eu.first() : y;
|
||||||
|
`check(z === 65535)
|
||||||
|
|
||||||
|
z = x ? eu.last() : x;
|
||||||
|
`check(z === 65533)
|
||||||
|
z = x ? eu.last() : y;
|
||||||
|
`check(z === 65533)
|
||||||
|
|
||||||
|
z = x ? eu.prev() : x;
|
||||||
|
`check(z === 65535)
|
||||||
|
z = x ? eu.prev() : y;
|
||||||
|
`check(z === 65535)
|
||||||
|
|
||||||
|
z = x ? eu.next() : x;
|
||||||
|
`check(z === 65533)
|
||||||
|
z = x ? eu.next() : y;
|
||||||
|
`check(z === 65533)
|
||||||
|
|
||||||
|
z = x ? es.first() : x;
|
||||||
|
`check(z === 65535)
|
||||||
|
z = x ? es.first() : y;
|
||||||
|
`check(z === -1)
|
||||||
|
|
||||||
|
z = x ? es.last() : x;
|
||||||
|
`check(z === 65533)
|
||||||
|
z = x ? es.last() : y;
|
||||||
|
`check(z === -3)
|
||||||
|
|
||||||
|
z = x ? es.prev() : x;
|
||||||
|
`check(z === 65535)
|
||||||
|
z = x ? es.prev() : y;
|
||||||
|
`check(z === -1)
|
||||||
|
|
||||||
|
z = x ? es.next() : x;
|
||||||
|
`check(z === 65533)
|
||||||
|
z = x ? es.next() : y;
|
||||||
|
`check(z === -3)
|
||||||
|
|
||||||
|
if (!failed) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
// Check that the signedness of methods on the built-in enum type is handled
|
||||||
|
// correctly when calling the function with parenthesis and passing the result
|
||||||
|
// to a system function.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
enum shortint {
|
||||||
|
A = -1,
|
||||||
|
B = -2,
|
||||||
|
C = -3
|
||||||
|
} es;
|
||||||
|
|
||||||
|
enum bit [15:0] {
|
||||||
|
X = 65535,
|
||||||
|
Y = 65534,
|
||||||
|
Z = 65533
|
||||||
|
} eu;
|
||||||
|
|
||||||
|
string s;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
es = B;
|
||||||
|
eu = Y;
|
||||||
|
|
||||||
|
s = $sformatf("%0d %0d %0d %0d %0d %0d %0d %0d",
|
||||||
|
es.first(), es.last(), es.prev(), es.next(),
|
||||||
|
eu.first(), eu.last(), eu.prev(), eu.next());
|
||||||
|
if (s == "-1 -3 -1 -3 65535 65533 65535 65533") begin
|
||||||
|
$display("PASSED");
|
||||||
|
end else begin
|
||||||
|
$display("FAILED s=%s", s);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,156 @@
|
||||||
|
// Check that the signedness of methods on the built-in enum type is handled
|
||||||
|
// correctly when calling the method without parenthesis.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
bit failed = 1'b0;
|
||||||
|
|
||||||
|
`define check(x) \
|
||||||
|
if (!(x)) begin \
|
||||||
|
$display("FAILED(%0d): ", `__LINE__, `"x`"); \
|
||||||
|
failed = 1'b1; \
|
||||||
|
end
|
||||||
|
|
||||||
|
int unsigned x = 10;
|
||||||
|
int y = 10;
|
||||||
|
int z;
|
||||||
|
|
||||||
|
enum shortint {
|
||||||
|
A = -1,
|
||||||
|
B = -2,
|
||||||
|
C = -3
|
||||||
|
} es;
|
||||||
|
|
||||||
|
enum bit [15:0] {
|
||||||
|
X = 65535,
|
||||||
|
Y = 65534,
|
||||||
|
Z = 65533
|
||||||
|
} eu;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
es = B;
|
||||||
|
eu = Y;
|
||||||
|
|
||||||
|
// These all evaluate as signed
|
||||||
|
`check($signed(eu.first) < 0)
|
||||||
|
`check(es.first < 0)
|
||||||
|
|
||||||
|
`check($signed(eu.last) < 0)
|
||||||
|
`check(es.last < 0)
|
||||||
|
|
||||||
|
`check($signed(eu.prev) < 0)
|
||||||
|
`check(es.prev < 0)
|
||||||
|
|
||||||
|
`check($signed(eu.next) < 0)
|
||||||
|
`check(es.next < 0)
|
||||||
|
|
||||||
|
// These all evaluate as unsigned
|
||||||
|
`check(eu.first > 0)
|
||||||
|
`check({es.first} > 0)
|
||||||
|
`check($unsigned(es.first) > 0)
|
||||||
|
`check(es.first > 16'h0)
|
||||||
|
|
||||||
|
`check(eu.last > 0)
|
||||||
|
`check({es.last} > 0)
|
||||||
|
`check($unsigned(es.last) > 0)
|
||||||
|
`check(es.last > 16'h0)
|
||||||
|
|
||||||
|
`check(eu.prev > 0)
|
||||||
|
`check({es.prev} > 0)
|
||||||
|
`check($unsigned(es.prev) > 0)
|
||||||
|
`check(es.prev > 16'h0)
|
||||||
|
|
||||||
|
`check(eu.next > 0)
|
||||||
|
`check({es.next} > 0)
|
||||||
|
`check($unsigned(es.next) > 0)
|
||||||
|
`check(es.next > 16'h0)
|
||||||
|
|
||||||
|
// In arithmetic expressions if one operand is unsigned all operands are
|
||||||
|
// considered unsigned
|
||||||
|
z = eu.first + x;
|
||||||
|
`check(z === 65545)
|
||||||
|
z = eu.first + y;
|
||||||
|
`check(z === 65545)
|
||||||
|
|
||||||
|
z = eu.last + x;
|
||||||
|
`check(z === 65543)
|
||||||
|
z = eu.last + y;
|
||||||
|
`check(z === 65543)
|
||||||
|
|
||||||
|
z = eu.prev + x;
|
||||||
|
`check(z === 65545)
|
||||||
|
z = eu.prev + y;
|
||||||
|
`check(z === 65545)
|
||||||
|
|
||||||
|
z = eu.next + x;
|
||||||
|
`check(z === 65543)
|
||||||
|
z = eu.next + y;
|
||||||
|
`check(z === 65543)
|
||||||
|
|
||||||
|
z = es.first + x;
|
||||||
|
`check(z === 65545)
|
||||||
|
z = es.first + y;
|
||||||
|
`check(z === 9)
|
||||||
|
|
||||||
|
z = es.last + x;
|
||||||
|
`check(z === 65543)
|
||||||
|
z = es.last + y;
|
||||||
|
`check(z === 7)
|
||||||
|
|
||||||
|
z = es.prev + x;
|
||||||
|
`check(z === 65545)
|
||||||
|
z = es.prev + y;
|
||||||
|
`check(z === 9)
|
||||||
|
|
||||||
|
z = es.next + x;
|
||||||
|
`check(z === 65543)
|
||||||
|
z = es.next + y;
|
||||||
|
`check(z === 7)
|
||||||
|
|
||||||
|
// For ternary operators if one operand is unsigned the result is unsigend
|
||||||
|
z = x ? eu.first : x;
|
||||||
|
`check(z === 65535)
|
||||||
|
z = x ? eu.first : y;
|
||||||
|
`check(z === 65535)
|
||||||
|
|
||||||
|
z = x ? eu.last : x;
|
||||||
|
`check(z === 65533)
|
||||||
|
z = x ? eu.last : y;
|
||||||
|
`check(z === 65533)
|
||||||
|
|
||||||
|
z = x ? eu.prev : x;
|
||||||
|
`check(z === 65535)
|
||||||
|
z = x ? eu.prev : y;
|
||||||
|
`check(z === 65535)
|
||||||
|
|
||||||
|
z = x ? eu.next : x;
|
||||||
|
`check(z === 65533)
|
||||||
|
z = x ? eu.next : y;
|
||||||
|
`check(z === 65533)
|
||||||
|
|
||||||
|
z = x ? es.first : x;
|
||||||
|
`check(z === 65535)
|
||||||
|
z = x ? es.first : y;
|
||||||
|
`check(z === -1)
|
||||||
|
|
||||||
|
z = x ? es.last : x;
|
||||||
|
`check(z === 65533)
|
||||||
|
z = x ? es.last : y;
|
||||||
|
`check(z === -3)
|
||||||
|
|
||||||
|
z = x ? es.prev : x;
|
||||||
|
`check(z === 65535)
|
||||||
|
z = x ? es.prev : y;
|
||||||
|
`check(z === -1)
|
||||||
|
|
||||||
|
z = x ? es.next : x;
|
||||||
|
`check(z === 65533)
|
||||||
|
z = x ? es.next : y;
|
||||||
|
`check(z === -3)
|
||||||
|
|
||||||
|
if (!failed) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
// Check that the signedness of methods on the built-in enum type is handled
|
||||||
|
// correctly when calling the function without parenthesis and passing the
|
||||||
|
// result to a system function.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
enum shortint {
|
||||||
|
A = -1,
|
||||||
|
B = -2,
|
||||||
|
C = -3
|
||||||
|
} es;
|
||||||
|
|
||||||
|
enum bit [15:0] {
|
||||||
|
X = 65535,
|
||||||
|
Y = 65534,
|
||||||
|
Z = 65533
|
||||||
|
} eu;
|
||||||
|
|
||||||
|
string s;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
es = B;
|
||||||
|
eu = Y;
|
||||||
|
|
||||||
|
s = $sformatf("%0d %0d %0d %0d %0d %0d %0d %0d",
|
||||||
|
es.first, es.last, es.prev, es.next,
|
||||||
|
eu.first, eu.last, eu.prev, eu.next);
|
||||||
|
if (s == "-1 -3 -1 -3 65535 65533 65535 65533") begin
|
||||||
|
$display("PASSED");
|
||||||
|
end else begin
|
||||||
|
$display("FAILED s=%s", s);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
// Check that the signedness of methods on user defined classes is handled
|
||||||
|
// correctly.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
bit failed = 1'b0;
|
||||||
|
|
||||||
|
`define check(x) \
|
||||||
|
if (!(x)) begin \
|
||||||
|
$display("FAILED(%0d): ", `__LINE__, `"x`"); \
|
||||||
|
failed = 1'b1; \
|
||||||
|
end
|
||||||
|
|
||||||
|
class C;
|
||||||
|
function shortint s;
|
||||||
|
return -1;
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function bit [15:0] u;
|
||||||
|
return -1;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
C c;
|
||||||
|
|
||||||
|
int unsigned x = 10;
|
||||||
|
int y = 10;
|
||||||
|
int z;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
c = new;
|
||||||
|
|
||||||
|
// These all evaluate as signed
|
||||||
|
`check($signed(c.u()) < 0)
|
||||||
|
`check(c.s() < 0)
|
||||||
|
|
||||||
|
// These all evaluate as unsigned
|
||||||
|
`check(c.u() > 0)
|
||||||
|
`check({c.s()} > 0)
|
||||||
|
`check($unsigned(c.s()) > 0)
|
||||||
|
`check(c.s() > 16'h0)
|
||||||
|
|
||||||
|
// In arithmetic expressions if one operand is unsigned all operands are
|
||||||
|
// considered unsigned
|
||||||
|
z = c.u() + x;
|
||||||
|
`check(z === 65545)
|
||||||
|
z = c.u() + y;
|
||||||
|
`check(z === 65545)
|
||||||
|
|
||||||
|
z = c.s() + x;
|
||||||
|
`check(z === 65545)
|
||||||
|
z = c.s() + y;
|
||||||
|
`check(z === 9)
|
||||||
|
|
||||||
|
// For ternary operators if one operand is unsigned the result is unsigend
|
||||||
|
z = x ? c.u() : x;
|
||||||
|
`check(z === 65535)
|
||||||
|
z = x ? c.u() : y;
|
||||||
|
`check(z === 65535)
|
||||||
|
|
||||||
|
z = x ? c.s() : x;
|
||||||
|
`check(z === 65535)
|
||||||
|
z = x ? c.s() : y;
|
||||||
|
`check(z === -1)
|
||||||
|
|
||||||
|
if (!failed) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
// Check that the signedness of methods on user defined classes is handled
|
||||||
|
// correctly when passing the result to a system function.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
class C;
|
||||||
|
function shortint s;
|
||||||
|
return -1;
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function bit [15:0] u;
|
||||||
|
return -1;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
C c;
|
||||||
|
string s;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
c = new;
|
||||||
|
|
||||||
|
s = $sformatf("%0d %0d", c.s(), c.u());
|
||||||
|
if (s == "-1 65535") begin
|
||||||
|
$display("PASSED");
|
||||||
|
end else begin
|
||||||
|
$display("FAILED s=%s", s);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
// Check that the signedness of class properties are handled correctly when
|
||||||
|
// accessing the property on a class object.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
bit failed = 1'b0;
|
||||||
|
|
||||||
|
`define check(x) \
|
||||||
|
if (!(x)) begin \
|
||||||
|
$display("FAILED(%0d): ", `__LINE__, `"x`"); \
|
||||||
|
failed = 1'b1; \
|
||||||
|
end
|
||||||
|
|
||||||
|
class C;
|
||||||
|
shortint s = -1;
|
||||||
|
bit [15:0] u = -1;
|
||||||
|
endclass
|
||||||
|
|
||||||
|
C c;
|
||||||
|
|
||||||
|
int unsigned x = 10;
|
||||||
|
int y = 10;
|
||||||
|
int z;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
c = new;
|
||||||
|
|
||||||
|
// These all evaluate as signed
|
||||||
|
`check(c.s < 0)
|
||||||
|
`check($signed(c.u) < 0)
|
||||||
|
|
||||||
|
// These all evaluate as unsigned
|
||||||
|
`check(c.u > 0)
|
||||||
|
`check({c.s} > 0)
|
||||||
|
`check($unsigned(c.s) > 0)
|
||||||
|
`check(c.s > 16'h0)
|
||||||
|
|
||||||
|
// In arithmetic expressions if one operand is unsigned all operands are
|
||||||
|
// considered unsigned
|
||||||
|
z = c.u + x;
|
||||||
|
`check(z === 65545)
|
||||||
|
z = c.u + y;
|
||||||
|
`check(z === 65545)
|
||||||
|
|
||||||
|
z = c.s + x;
|
||||||
|
`check(z === 65545)
|
||||||
|
z = c.s + y;
|
||||||
|
`check(z === 9)
|
||||||
|
|
||||||
|
// For ternary operators if one operand is unsigned the result is unsigend
|
||||||
|
z = x ? c.u : x;
|
||||||
|
`check(z === 65535)
|
||||||
|
z = x ? c.u : y;
|
||||||
|
`check(z === 65535)
|
||||||
|
|
||||||
|
z = x ? c.s : x;
|
||||||
|
`check(z === 65535)
|
||||||
|
z = x ? c.s : y;
|
||||||
|
`check(z === -1)
|
||||||
|
|
||||||
|
if (!failed) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
// Check that the signedness of class properties are handled correctly when
|
||||||
|
// accessing the property on a class object and passing it to a system function.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
class C;
|
||||||
|
shortint s = -1;
|
||||||
|
bit [15:0] u = -1;
|
||||||
|
endclass
|
||||||
|
|
||||||
|
C c;
|
||||||
|
string s;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
c = new;
|
||||||
|
|
||||||
|
s = $sformatf("%0d %0d", c.s, c.u);
|
||||||
|
if (s == "-1 65535") begin
|
||||||
|
$display("PASSED");
|
||||||
|
end else begin
|
||||||
|
$display("FAILED s=%s", s);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
// Check that the signedness of class properties are handled correctly when
|
||||||
|
// accessing the property in a class method.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
bit failed = 1'b0;
|
||||||
|
|
||||||
|
`define check(x) \
|
||||||
|
if (!(x)) begin \
|
||||||
|
$display("FAILED: ", `"x`", `__LINE__); \
|
||||||
|
failed = 1'b1; \
|
||||||
|
end
|
||||||
|
|
||||||
|
int unsigned x = 10;
|
||||||
|
int y = 10;
|
||||||
|
int z;
|
||||||
|
|
||||||
|
class C;
|
||||||
|
shortint s = -1;
|
||||||
|
bit [15:0] u = -1;
|
||||||
|
|
||||||
|
task test;
|
||||||
|
|
||||||
|
// These all evaluate as signed
|
||||||
|
`check(s < 0)
|
||||||
|
`check($signed(u) < 0)
|
||||||
|
|
||||||
|
// These all evaluate as unsigned
|
||||||
|
`check(u > 0)
|
||||||
|
`check({s} > 0)
|
||||||
|
`check($unsigned(s) > 0)
|
||||||
|
`check(s > 16'h0)
|
||||||
|
|
||||||
|
// In arithmetic expressions if one operand is unsigned all operands are
|
||||||
|
// considered unsigned
|
||||||
|
z = u + x;
|
||||||
|
`check(z === 65545)
|
||||||
|
z = u + y;
|
||||||
|
`check(z === 65545)
|
||||||
|
|
||||||
|
z = s + x;
|
||||||
|
`check(z === 65545)
|
||||||
|
z = s + y;
|
||||||
|
`check(z === 9)
|
||||||
|
|
||||||
|
// For ternary operators if one operand is unsigned the result is unsigend
|
||||||
|
z = x ? u : x;
|
||||||
|
`check(z === 65535)
|
||||||
|
z = x ? u : y;
|
||||||
|
`check(z === 65535)
|
||||||
|
|
||||||
|
z = x ? s : x;
|
||||||
|
`check(z === 65535)
|
||||||
|
z = x ? s : y;
|
||||||
|
`check(z === -1)
|
||||||
|
|
||||||
|
if (!failed) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
|
endclass
|
||||||
|
|
||||||
|
C c;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
c = new;
|
||||||
|
c.test();
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
// Check that the signedness of class properties are handled correctly when
|
||||||
|
// accessing the property in a class method and passing it to a system function.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
class C;
|
||||||
|
shortint s = -1;
|
||||||
|
bit [15:0] u = -1;
|
||||||
|
|
||||||
|
task test;
|
||||||
|
string str;
|
||||||
|
|
||||||
|
str = $sformatf("%0d %0d", s, u);
|
||||||
|
if (str == "-1 65535") begin
|
||||||
|
$display("PASSED");
|
||||||
|
end else begin
|
||||||
|
$display("FAILED s=%s", s);
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
|
endclass
|
||||||
|
|
||||||
|
C c;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
c = new;
|
||||||
|
c.test();
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,99 @@
|
||||||
|
// Check that the signedness of the element type of a queue is correctly handled
|
||||||
|
// whenn calling one of the pop methods with parenthesis.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
bit failed = 1'b0;
|
||||||
|
|
||||||
|
`define check(x) \
|
||||||
|
if (!(x)) begin \
|
||||||
|
$display("FAILED(%0d): ", `__LINE__, `"x`"); \
|
||||||
|
failed = 1'b1; \
|
||||||
|
end
|
||||||
|
|
||||||
|
int unsigned x = 10;
|
||||||
|
int y = 10;
|
||||||
|
int z;
|
||||||
|
longint w;
|
||||||
|
|
||||||
|
shortint qs[$];
|
||||||
|
bit [15:0] qu[$];
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
for (int i = 0; i < 16; i++) begin
|
||||||
|
qu.push_back(-1);
|
||||||
|
qs.push_back(-1);
|
||||||
|
end
|
||||||
|
|
||||||
|
// These all evaluate as signed
|
||||||
|
`check($signed(qu.pop_back()) < 0)
|
||||||
|
`check(qs.pop_back() < 0)
|
||||||
|
|
||||||
|
`check($signed(qu.pop_front()) < 0)
|
||||||
|
`check(qs.pop_front() < 0)
|
||||||
|
|
||||||
|
// These all evaluate as unsigned
|
||||||
|
`check(qu.pop_back() > 0)
|
||||||
|
`check({qs.pop_back()} > 0)
|
||||||
|
`check($unsigned(qs.pop_back()) > 0)
|
||||||
|
`check(qs.pop_back() > 16'h0)
|
||||||
|
|
||||||
|
`check(qu.pop_front() > 0)
|
||||||
|
`check({qs.pop_front()} > 0)
|
||||||
|
`check($unsigned(qs.pop_front()) > 0)
|
||||||
|
`check(qs.pop_front() > 16'h0)
|
||||||
|
|
||||||
|
// In arithmetic expressions if one operand is unsigned all operands are
|
||||||
|
// considered unsigned
|
||||||
|
z = qu.pop_back() + x;
|
||||||
|
`check(z === 65545)
|
||||||
|
z = qu.pop_back() + y;
|
||||||
|
`check(z === 65545)
|
||||||
|
|
||||||
|
z = qu.pop_front() + x;
|
||||||
|
`check(z === 65545)
|
||||||
|
z = qu.pop_front() + y;
|
||||||
|
`check(z === 65545)
|
||||||
|
|
||||||
|
z = qs.pop_back() + x;
|
||||||
|
`check(z === 65545)
|
||||||
|
z = qs.pop_back() + y;
|
||||||
|
`check(z === 9)
|
||||||
|
|
||||||
|
z = qs.pop_front() + x;
|
||||||
|
`check(z === 65545)
|
||||||
|
z = qs.pop_front() + y;
|
||||||
|
`check(z === 9)
|
||||||
|
|
||||||
|
// For ternary operators if one operand is unsigned the result is unsigend
|
||||||
|
z = x ? qu.pop_back() : x;
|
||||||
|
`check(z === 65535)
|
||||||
|
z = x ? qu.pop_back() : y;
|
||||||
|
`check(z === 65535)
|
||||||
|
|
||||||
|
z = x ? qu.pop_front() : x;
|
||||||
|
`check(z === 65535)
|
||||||
|
z = x ? qu.pop_front() : y;
|
||||||
|
`check(z === 65535)
|
||||||
|
|
||||||
|
z = x ? qs.pop_back() : x;
|
||||||
|
`check(z === 65535)
|
||||||
|
z = x ? qs.pop_back() : y;
|
||||||
|
`check(z === -1)
|
||||||
|
|
||||||
|
z = x ? qs.pop_front() : x;
|
||||||
|
`check(z === 65535)
|
||||||
|
z = x ? qs.pop_front() : y;
|
||||||
|
`check(z === -1)
|
||||||
|
|
||||||
|
// Size return value is always positive, but check that it gets padded
|
||||||
|
// properly
|
||||||
|
w = x ? qu.size() : 64'h123;
|
||||||
|
`check(w === 64'h4)
|
||||||
|
|
||||||
|
if (!failed) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
// Check that the signedness of the element type of a queue is correctly handled
|
||||||
|
// when passing the result of one of the pop methods as an argument to a system
|
||||||
|
// function.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
shortint qs[$];
|
||||||
|
bit [15:0] qu[$];
|
||||||
|
|
||||||
|
string s;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
qs.push_back(-1);
|
||||||
|
qs.push_back(-2);
|
||||||
|
qu.push_back(-1);
|
||||||
|
qu.push_back(-2);
|
||||||
|
|
||||||
|
// Values popped from qs should be treated as signed, values popped from qu
|
||||||
|
// should be treated as unsigned
|
||||||
|
s = $sformatf("%0d %0d %0d %0d", qs.pop_front(), qs.pop_back(),
|
||||||
|
qu.pop_front(), qu.pop_back());
|
||||||
|
if (s == "-1 -2 65535 65534") begin
|
||||||
|
$display("PASSED");
|
||||||
|
end else begin
|
||||||
|
$display("FAILED s=%s", s);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,99 @@
|
||||||
|
// Check that the signedness of the element type of a queue is correctly handled
|
||||||
|
// whenn calling one of the pop methods with parenthesis.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
bit failed = 1'b0;
|
||||||
|
|
||||||
|
`define check(x) \
|
||||||
|
if (!(x)) begin \
|
||||||
|
$display("FAILED(%0d): ", `__LINE__, `"x`"); \
|
||||||
|
failed = 1'b1; \
|
||||||
|
end
|
||||||
|
|
||||||
|
int unsigned x = 10;
|
||||||
|
int y = 10;
|
||||||
|
int z;
|
||||||
|
longint w;
|
||||||
|
|
||||||
|
shortint qs[$];
|
||||||
|
bit [15:0] qu[$];
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
for (int i = 0; i < 16; i++) begin
|
||||||
|
qu.push_back(-1);
|
||||||
|
qs.push_back(-1);
|
||||||
|
end
|
||||||
|
|
||||||
|
// These all evaluate as signed
|
||||||
|
`check($signed(qu.pop_back) < 0)
|
||||||
|
`check(qs.pop_back < 0)
|
||||||
|
|
||||||
|
`check($signed(qu.pop_front) < 0)
|
||||||
|
`check(qs.pop_front < 0)
|
||||||
|
|
||||||
|
// These all evaluate as unsigned
|
||||||
|
`check(qu.pop_back > 0)
|
||||||
|
`check({qs.pop_back} > 0)
|
||||||
|
`check($unsigned(qs.pop_back) > 0)
|
||||||
|
`check(qs.pop_back > 16'h0)
|
||||||
|
|
||||||
|
`check(qu.pop_front > 0)
|
||||||
|
`check({qs.pop_front} > 0)
|
||||||
|
`check($unsigned(qs.pop_front) > 0)
|
||||||
|
`check(qs.pop_front > 16'h0)
|
||||||
|
|
||||||
|
// In arithmetic expressions if one operand is unsigned all operands are
|
||||||
|
// considered unsigned
|
||||||
|
z = qu.pop_back + x;
|
||||||
|
`check(z === 65545)
|
||||||
|
z = qu.pop_back + y;
|
||||||
|
`check(z === 65545)
|
||||||
|
|
||||||
|
z = qu.pop_front + x;
|
||||||
|
`check(z === 65545)
|
||||||
|
z = qu.pop_front + y;
|
||||||
|
`check(z === 65545)
|
||||||
|
|
||||||
|
z = qs.pop_back + x;
|
||||||
|
`check(z === 65545)
|
||||||
|
z = qs.pop_back + y;
|
||||||
|
`check(z === 9)
|
||||||
|
|
||||||
|
z = qs.pop_front + x;
|
||||||
|
`check(z === 65545)
|
||||||
|
z = qs.pop_front + y;
|
||||||
|
`check(z === 9)
|
||||||
|
|
||||||
|
// For ternary operators if one operand is unsigned the result is unsigend
|
||||||
|
z = x ? qu.pop_back : x;
|
||||||
|
`check(z === 65535)
|
||||||
|
z = x ? qu.pop_back : y;
|
||||||
|
`check(z === 65535)
|
||||||
|
|
||||||
|
z = x ? qu.pop_front : x;
|
||||||
|
`check(z === 65535)
|
||||||
|
z = x ? qu.pop_front : y;
|
||||||
|
`check(z === 65535)
|
||||||
|
|
||||||
|
z = x ? qs.pop_back : x;
|
||||||
|
`check(z === 65535)
|
||||||
|
z = x ? qs.pop_back : y;
|
||||||
|
`check(z === -1)
|
||||||
|
|
||||||
|
z = x ? qs.pop_front : x;
|
||||||
|
`check(z === 65535)
|
||||||
|
z = x ? qs.pop_front : y;
|
||||||
|
`check(z === -1)
|
||||||
|
|
||||||
|
// Size return value is always positive, but check that it gets padded
|
||||||
|
// properly
|
||||||
|
w = x ? qu.size : 64'h123;
|
||||||
|
`check(w === 64'h4)
|
||||||
|
|
||||||
|
if (!failed) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
// Check that the signedness of the element type of a queue is correctly handled
|
||||||
|
// when passing the result of one of the pop methods as an argument to a system
|
||||||
|
// function.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
shortint qs[$];
|
||||||
|
bit [15:0] qu[$];
|
||||||
|
|
||||||
|
string s;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
qs.push_back(-1);
|
||||||
|
qs.push_back(-2);
|
||||||
|
qu.push_back(-1);
|
||||||
|
qu.push_back(-2);
|
||||||
|
|
||||||
|
// Values popped from qs should be treated as signed, values popped from qu
|
||||||
|
// should be treated as unsigned
|
||||||
|
s = $sformatf("%0d %0d %0d %0d", qs.pop_front, qs.pop_back,
|
||||||
|
qu.pop_front, qu.pop_back);
|
||||||
|
if (s == "-1 -2 65535 65534") begin
|
||||||
|
$display("PASSED");
|
||||||
|
end else begin
|
||||||
|
$display("FAILED s=%s", s);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -265,6 +265,10 @@ enum_in_struct normal,-g2005-sv ivltests
|
||||||
enum_in_class normal,-g2005-sv ivltests
|
enum_in_class normal,-g2005-sv ivltests
|
||||||
enum_in_class_name_coll CE,-g2005-sv ivltests
|
enum_in_class_name_coll CE,-g2005-sv ivltests
|
||||||
enum_line_info CE,-g2005-sv ivltests gold=enum_line_info.gold
|
enum_line_info CE,-g2005-sv ivltests gold=enum_line_info.gold
|
||||||
|
enum_method_signed1 normal,-g2005-sv ivltests
|
||||||
|
enum_method_signed2 normal,-g2005-sv ivltests
|
||||||
|
enum_method_signed3 normal,-g2005-sv ivltests
|
||||||
|
enum_method_signed4 normal,-g2005-sv ivltests
|
||||||
enum_next normal,-g2005-sv ivltests
|
enum_next normal,-g2005-sv ivltests
|
||||||
enum_order normal,-g2005-sv ivltests
|
enum_order normal,-g2005-sv ivltests
|
||||||
enum_ports normal,-g2005-sv ivltests
|
enum_ports normal,-g2005-sv ivltests
|
||||||
|
|
@ -488,6 +492,12 @@ sv_class_extends_scoped normal,-g2009 ivltests
|
||||||
sv_class_localparam normal,-g2009 ivltests
|
sv_class_localparam normal,-g2009 ivltests
|
||||||
sv_class_new_init normal,-g2009 ivltests
|
sv_class_new_init normal,-g2009 ivltests
|
||||||
sv_class_in_module_decl normal,-g2009 ivltests
|
sv_class_in_module_decl normal,-g2009 ivltests
|
||||||
|
sv_class_method_signed1 normal,-g2009 ivltests
|
||||||
|
sv_class_method_signed2 normal,-g2009 ivltests
|
||||||
|
sv_class_property_signed1 normal,-g2009 ivltests
|
||||||
|
sv_class_property_signed2 normal,-g2009 ivltests
|
||||||
|
sv_class_property_signed3 normal,-g2009 ivltests
|
||||||
|
sv_class_property_signed4 normal,-g2009 ivltests
|
||||||
sv_class_static_prop1 normal,-g2009 ivltests
|
sv_class_static_prop1 normal,-g2009 ivltests
|
||||||
sv_class_static_prop2 normal,-g2009 ivltests
|
sv_class_static_prop2 normal,-g2009 ivltests
|
||||||
sv_class_static_prop3 normal,-g2009 ivltests
|
sv_class_static_prop3 normal,-g2009 ivltests
|
||||||
|
|
@ -571,6 +581,10 @@ sv_queue_parray_fail CE,-g2009 ivltests gold=sv_queue_parray_fail.gold
|
||||||
sv_queue_real normal,-g2009,-pfileline=1 ivltests gold=sv_queue_real.gold
|
sv_queue_real normal,-g2009,-pfileline=1 ivltests gold=sv_queue_real.gold
|
||||||
sv_queue_real_bounded normal,-g2009,-pfileline=1 ivltests gold=sv_queue_real_bounded.gold
|
sv_queue_real_bounded normal,-g2009,-pfileline=1 ivltests gold=sv_queue_real_bounded.gold
|
||||||
sv_queue_real_fail CE,-g2009 ivltests gold=sv_queue_real_fail.gold
|
sv_queue_real_fail CE,-g2009 ivltests gold=sv_queue_real_fail.gold
|
||||||
|
sv_queue_method_signed1 normal,-g2009 ivltests
|
||||||
|
sv_queue_method_signed2 normal,-g2009 ivltests
|
||||||
|
sv_queue_method_signed3 normal,-g2009 ivltests
|
||||||
|
sv_queue_method_signed4 normal,-g2009 ivltests
|
||||||
sv_queue_string normal,-g2009,-pfileline=1 ivltests gold=sv_queue_string.gold
|
sv_queue_string normal,-g2009,-pfileline=1 ivltests gold=sv_queue_string.gold
|
||||||
sv_queue_string_bounded normal,-g2009,-pfileline=1 ivltests gold=sv_queue_string_bounded.gold
|
sv_queue_string_bounded normal,-g2009,-pfileline=1 ivltests gold=sv_queue_string_bounded.gold
|
||||||
sv_queue_string_fail CE,-g2009 ivltests gold=sv_queue_string_fail.gold
|
sv_queue_string_fail CE,-g2009 ivltests gold=sv_queue_string_fail.gold
|
||||||
|
|
|
||||||
|
|
@ -384,6 +384,12 @@ sv_class_extends_scoped CE,-g2009 ivltests
|
||||||
sv_class_localparam CE,-g2009 ivltests
|
sv_class_localparam CE,-g2009 ivltests
|
||||||
sv_class_new_init CE,-g2009 ivltests
|
sv_class_new_init CE,-g2009 ivltests
|
||||||
sv_class_in_module_decl CE,-g2009 ivltests
|
sv_class_in_module_decl CE,-g2009 ivltests
|
||||||
|
sv_class_method_signed1 CE,-g2009,-pallowsigned=1 ivltests
|
||||||
|
sv_class_method_signed2 CE,-g2009,-pallowsigned=1 ivltests
|
||||||
|
sv_class_property_signed1 CE,-g2009,-pallowsigned=1 ivltests
|
||||||
|
sv_class_property_signed2 CE,-g2009,-pallowsigned=1 ivltests
|
||||||
|
sv_class_property_signed3 CE,-g2009,-pallowsigned=1 ivltests
|
||||||
|
sv_class_property_signed4 CE,-g2009,-pallowsigned=1 ivltests
|
||||||
sv_class_static_prop1 CE,-g2009 ivltests
|
sv_class_static_prop1 CE,-g2009 ivltests
|
||||||
sv_class_static_prop2 CE,-g2009 ivltests
|
sv_class_static_prop2 CE,-g2009 ivltests
|
||||||
sv_class_static_prop3 CE,-g2009 ivltests
|
sv_class_static_prop3 CE,-g2009 ivltests
|
||||||
|
|
@ -438,6 +444,10 @@ br_gh436 CE,-g2012,-pallowsigned=1 ivltests # queues/strings
|
||||||
br_gh672 CE,-g2009 ivltests # join_none
|
br_gh672 CE,-g2009 ivltests # join_none
|
||||||
br_mw20200501 CE,-g2009 ivltests # queues
|
br_mw20200501 CE,-g2009 ivltests # queues
|
||||||
disable_fork_cmd CE,-g2009 ivltests # disable fork and join_*
|
disable_fork_cmd CE,-g2009 ivltests # disable fork and join_*
|
||||||
|
enum_method_signed1 CE,-g2009,-pallowsigned=1 ivltests
|
||||||
|
enum_method_signed2 CE,-g2009,-pallowsigned=1 ivltests
|
||||||
|
enum_method_signed3 CE,-g2009,-pallowsigned=1 ivltests
|
||||||
|
enum_method_signed4 CE,-g2009,-pallowsigned=1 ivltests
|
||||||
enum_next CE,-g2009,-pallowsigned=1 ivltests # enum
|
enum_next CE,-g2009,-pallowsigned=1 ivltests # enum
|
||||||
enum_test1 CE,-g2009 ivltests # enum
|
enum_test1 CE,-g2009 ivltests # enum
|
||||||
fork_join_any CE,-g2009,-pallowsigned=1 ivltests # join_any
|
fork_join_any CE,-g2009,-pallowsigned=1 ivltests # join_any
|
||||||
|
|
@ -611,6 +621,10 @@ br_gh433 CE,-g2009,-pallowsigned=1 ivltests
|
||||||
sv_queue1 CE,-g2009,-pallowsigned=1 ivltests
|
sv_queue1 CE,-g2009,-pallowsigned=1 ivltests
|
||||||
sv_queue2 CE,-g2009,-pallowsigned=1 ivltests
|
sv_queue2 CE,-g2009,-pallowsigned=1 ivltests
|
||||||
sv_queue3 CE,-g2009 ivltests
|
sv_queue3 CE,-g2009 ivltests
|
||||||
|
sv_queue_method_signed1 CE,-g2009,-pallowsigned=1 ivltests
|
||||||
|
sv_queue_method_signed2 CE,-g2009,-pallowsigned=1 ivltests
|
||||||
|
sv_queue_method_signed3 CE,-g2009,-pallowsigned=1 ivltests
|
||||||
|
sv_queue_method_signed4 CE,-g2009,-pallowsigned=1 ivltests
|
||||||
sv_queue_real CE,-g2009 ivltests
|
sv_queue_real CE,-g2009 ivltests
|
||||||
sv_queue_real_bounded CE,-g2009 ivltests
|
sv_queue_real_bounded CE,-g2009 ivltests
|
||||||
sv_queue_real_fail CE,-g2009 ivltests
|
sv_queue_real_fail CE,-g2009 ivltests
|
||||||
|
|
|
||||||
24
net_expr.cc
24
net_expr.cc
|
|
@ -487,28 +487,13 @@ NetESFunc::NetESFunc(const char*n, ivl_variable_type_t t,
|
||||||
}
|
}
|
||||||
|
|
||||||
NetESFunc::NetESFunc(const char*n, ivl_type_t rtype, unsigned np)
|
NetESFunc::NetESFunc(const char*n, ivl_type_t rtype, unsigned np)
|
||||||
: NetExpr(rtype), name_(0), type_(IVL_VT_NO_TYPE), enum_type_(0), parms_(np), is_overridden_(false)
|
: NetExpr(rtype), name_(0), type_(rtype->base_type()),
|
||||||
|
enum_type_(dynamic_cast<const netenum_t*>(rtype)), parms_(np),
|
||||||
|
is_overridden_(false)
|
||||||
{
|
{
|
||||||
name_ = lex_strings.add(n);
|
name_ = lex_strings.add(n);
|
||||||
expr_width(rtype->packed_width());
|
expr_width(rtype->packed_width());
|
||||||
// FIXME: For now, assume that all uses of this constructor
|
cast_signed_base_(rtype->get_signed());
|
||||||
// are for the IVL_VT_DARRAY type. Eventually, the type_
|
|
||||||
// member will go away.
|
|
||||||
if (dynamic_cast<const netdarray_t*>(rtype))
|
|
||||||
type_ = IVL_VT_DARRAY;
|
|
||||||
else if (dynamic_cast<const netclass_t*>(rtype))
|
|
||||||
type_ = IVL_VT_CLASS;
|
|
||||||
else if (dynamic_cast<const netstring_t*>(rtype))
|
|
||||||
type_ = IVL_VT_STRING;
|
|
||||||
else
|
|
||||||
ivl_assert(*this, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
NetESFunc::NetESFunc(const char*n, const netenum_t*enum_type, unsigned np)
|
|
||||||
: name_(0), type_(enum_type->base_type()), enum_type_(enum_type), parms_(np), is_overridden_(false)
|
|
||||||
{
|
|
||||||
name_ = lex_strings.add(n);
|
|
||||||
expr_width(enum_type->packed_width());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NetESFunc::~NetESFunc()
|
NetESFunc::~NetESFunc()
|
||||||
|
|
@ -576,6 +561,7 @@ ivl_variable_type_t NetEShallowCopy::expr_type() const
|
||||||
NetEAccess::NetEAccess(NetBranch*br, ivl_nature_t nat)
|
NetEAccess::NetEAccess(NetBranch*br, ivl_nature_t nat)
|
||||||
: branch_(br), nature_(nat)
|
: branch_(br), nature_(nat)
|
||||||
{
|
{
|
||||||
|
cast_signed_base_(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
NetEAccess::~NetEAccess()
|
NetEAccess::~NetEAccess()
|
||||||
|
|
|
||||||
40
netlist.cc
40
netlist.cc
|
|
@ -549,6 +549,9 @@ template <class T> static unsigned calculate_count(T*type)
|
||||||
void NetNet::calculate_slice_widths_from_packed_dims_(void)
|
void NetNet::calculate_slice_widths_from_packed_dims_(void)
|
||||||
{
|
{
|
||||||
ivl_assert(*this, net_type_);
|
ivl_assert(*this, net_type_);
|
||||||
|
if (!net_type_->packed())
|
||||||
|
return;
|
||||||
|
|
||||||
slice_dims_ = net_type_->slice_dimensions();
|
slice_dims_ = net_type_->slice_dimensions();
|
||||||
|
|
||||||
// Special case: There are no actual packed dimensions, so
|
// Special case: There are no actual packed dimensions, so
|
||||||
|
|
@ -598,42 +601,10 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t,
|
||||||
s->add_signal(this);
|
s->add_signal(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
NetNet::NetNet(NetScope*s, perm_string n, Type t, ivl_type_t type)
|
||||||
* When we create a netnet for a packed struct, create a single
|
|
||||||
* vector with the msb_/lsb_ chosen to name enough bits for the entire
|
|
||||||
* packed structure.
|
|
||||||
*/
|
|
||||||
NetNet::NetNet(NetScope*s, perm_string n, Type t, netstruct_t*ty)
|
|
||||||
: NetObj(s, n, 1),
|
: NetObj(s, n, 1),
|
||||||
type_(t), port_type_(NOT_A_PORT),
|
type_(t), port_type_(NOT_A_PORT),
|
||||||
local_flag_(false), net_type_(ty),
|
local_flag_(false), net_type_(type),
|
||||||
discipline_(0),
|
|
||||||
eref_count_(0), lref_count_(0)
|
|
||||||
{
|
|
||||||
//XXXX packed_dims_.push_back(netrange_t(calculate_count(ty)-1, 0));
|
|
||||||
calculate_slice_widths_from_packed_dims_();
|
|
||||||
|
|
||||||
initialize_dir_();
|
|
||||||
|
|
||||||
s->add_signal(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
NetNet::NetNet(NetScope*s, perm_string n, Type t, netdarray_t*ty)
|
|
||||||
: NetObj(s, n, 1),
|
|
||||||
type_(t), port_type_(NOT_A_PORT),
|
|
||||||
local_flag_(false), net_type_(ty),
|
|
||||||
discipline_(0),
|
|
||||||
eref_count_(0), lref_count_(0)
|
|
||||||
{
|
|
||||||
initialize_dir_();
|
|
||||||
|
|
||||||
s->add_signal(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
NetNet::NetNet(NetScope*s, perm_string n, Type t, netvector_t*ty)
|
|
||||||
: NetObj(s, n, 1),
|
|
||||||
type_(t), port_type_(NOT_A_PORT),
|
|
||||||
local_flag_(false), net_type_(ty),
|
|
||||||
discipline_(0),
|
discipline_(0),
|
||||||
eref_count_(0), lref_count_(0)
|
eref_count_(0), lref_count_(0)
|
||||||
{
|
{
|
||||||
|
|
@ -2188,6 +2159,7 @@ NetEUFunc::NetEUFunc(NetScope*scope, NetScope*def, NetESignal*res,
|
||||||
: scope_(scope), func_(def), result_sig_(res), parms_(p), need_const_(nc)
|
: scope_(scope), func_(def), result_sig_(res), parms_(p), need_const_(nc)
|
||||||
{
|
{
|
||||||
expr_width(result_sig_->expr_width());
|
expr_width(result_sig_->expr_width());
|
||||||
|
cast_signed_base_(result_sig_->has_sign());
|
||||||
}
|
}
|
||||||
|
|
||||||
NetEUFunc::~NetEUFunc()
|
NetEUFunc::~NetEUFunc()
|
||||||
|
|
|
||||||
|
|
@ -679,12 +679,7 @@ class NetNet : public NetObj, public PortType {
|
||||||
const std::list<netrange_t>&unpacked,
|
const std::list<netrange_t>&unpacked,
|
||||||
ivl_type_t type);
|
ivl_type_t type);
|
||||||
|
|
||||||
// This form builds a NetNet from its record/enum/darray
|
explicit NetNet(NetScope*s, perm_string n, Type t, ivl_type_t type);
|
||||||
// definition. They should probably be replaced with a single
|
|
||||||
// version that takes an ivl_type_s* base.
|
|
||||||
explicit NetNet(NetScope*s, perm_string n, Type t, netstruct_t*type);
|
|
||||||
explicit NetNet(NetScope*s, perm_string n, Type t, netdarray_t*type);
|
|
||||||
explicit NetNet(NetScope*s, perm_string n, Type t, netvector_t*type);
|
|
||||||
|
|
||||||
virtual ~NetNet();
|
virtual ~NetNet();
|
||||||
|
|
||||||
|
|
@ -4646,7 +4641,6 @@ class NetESFunc : public NetExpr {
|
||||||
NetESFunc(const char*name, ivl_variable_type_t t,
|
NetESFunc(const char*name, ivl_variable_type_t t,
|
||||||
unsigned width, unsigned nprms, bool is_overridden =false);
|
unsigned width, unsigned nprms, bool is_overridden =false);
|
||||||
NetESFunc(const char*name, ivl_type_t rtype, unsigned nprms);
|
NetESFunc(const char*name, ivl_type_t rtype, unsigned nprms);
|
||||||
NetESFunc(const char*name, const netenum_t*enum_type, unsigned nprms);
|
|
||||||
~NetESFunc();
|
~NetESFunc();
|
||||||
|
|
||||||
const char* name() const;
|
const char* name() const;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue