Merge branch 'master' of github.com:steveicarus/iverilog
This commit is contained in:
commit
f147cf9c61
|
|
@ -3719,7 +3719,7 @@ NetProc* PCallTask::elaborate_build_call_(Design*des, NetScope*scope,
|
|||
|
||||
} else if (task->type() == NetScope::FUNC) {
|
||||
NetFuncDef*tmp = task->func_def();
|
||||
if (tmp->return_sig() != 0) {
|
||||
if (!tmp->is_void()) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Calling a non-void function as a task." << endl;
|
||||
des->errors += 1;
|
||||
|
|
|
|||
14
netlist.cc
14
netlist.cc
|
|
@ -2524,6 +2524,20 @@ NetETernary::~NetETernary()
|
|||
delete false_val_;
|
||||
}
|
||||
|
||||
const netenum_t* NetETernary::enumeration() const
|
||||
{
|
||||
// If the condition can evaluate to an ambiguous value,
|
||||
// the result may be blended, and so is not guaranteed
|
||||
// to be a valid enumeration value.
|
||||
if (cond_->expr_type() != IVL_VT_BOOL)
|
||||
return 0;
|
||||
|
||||
if (true_val_->enumeration() != false_val_->enumeration())
|
||||
return 0;
|
||||
|
||||
return true_val_->enumeration();
|
||||
}
|
||||
|
||||
const NetExpr* NetETernary::cond_expr() const
|
||||
{
|
||||
return cond_;
|
||||
|
|
|
|||
|
|
@ -4757,6 +4757,8 @@ class NetETernary : public NetExpr {
|
|||
NetETernary(NetExpr*c, NetExpr*t, NetExpr*f, unsigned wid, bool signed_flag);
|
||||
~NetETernary();
|
||||
|
||||
const netenum_t* enumeration() const;
|
||||
|
||||
const NetExpr*cond_expr() const;
|
||||
const NetExpr*true_expr() const;
|
||||
const NetExpr*false_expr() const;
|
||||
|
|
|
|||
3
parse.y
3
parse.y
|
|
@ -3718,6 +3718,7 @@ expr_mintypmax
|
|||
expression_list_with_nuls
|
||||
: expression_list_with_nuls ',' expression
|
||||
{ list<PExpr*>*tmp = $1;
|
||||
if (tmp->empty()) tmp->push_back(0);
|
||||
tmp->push_back($3);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
|
@ -3728,11 +3729,11 @@ expression_list_with_nuls
|
|||
}
|
||||
|
|
||||
{ list<PExpr*>*tmp = new list<PExpr*>;
|
||||
tmp->push_back(0);
|
||||
$$ = tmp;
|
||||
}
|
||||
| expression_list_with_nuls ','
|
||||
{ list<PExpr*>*tmp = $1;
|
||||
if (tmp->empty()) tmp->push_back(0);
|
||||
tmp->push_back(0);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2018 Cary R. (cygcary@yahoo.com)
|
||||
* Copyright (C) 2011-2019 Cary R. (cygcary@yahoo.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -138,6 +138,8 @@ static expr_sign_t expr_get_unary_sign_type(ivl_expr_t expr)
|
|||
case 'X':
|
||||
/* The reduction operators always act as if the argument is
|
||||
* unsigned. */
|
||||
case '!':
|
||||
/* The logical negation operator works on either type. */
|
||||
break;
|
||||
case 'r':
|
||||
/* For a cast to real the expression should be signed and no
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2010-2016 Cary R. (cygcary@yahoo.com)
|
||||
* Copyright (C) 2010-2019 Cary R. (cygcary@yahoo.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -26,6 +26,10 @@ const char *func_rtn_name = 0;
|
|||
|
||||
static void emit_func_return(ivl_signal_t sig)
|
||||
{
|
||||
// Handle SV void functions.
|
||||
if (sig == 0)
|
||||
return;
|
||||
|
||||
if (ivl_signal_dimensions(sig) > 0) {
|
||||
fprintf(stderr, "%s:%u: vlog95 error: A function cannot return "
|
||||
"an array.\n", ivl_signal_file(sig),
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2017 Cary R. (cygcary@yahoo.com)
|
||||
* Copyright (C) 2011-2019 Cary R. (cygcary@yahoo.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -667,6 +667,7 @@ static unsigned is_wait(ivl_scope_t scope, ivl_statement_t stmt)
|
|||
static unsigned utask_in_port_idx(ivl_scope_t scope, ivl_statement_t stmt)
|
||||
{
|
||||
unsigned idx, ports = ivl_scope_ports(scope);
|
||||
unsigned first_arg = is_void_function(scope) ? 1 : 0;
|
||||
ivl_lval_t lval = ivl_stmt_lval(stmt, 0);
|
||||
ivl_signal_t lsig = ivl_lval_sig(lval);
|
||||
const char *sig_name;
|
||||
|
|
@ -682,7 +683,7 @@ static unsigned utask_in_port_idx(ivl_scope_t scope, ivl_statement_t stmt)
|
|||
if (scope != ivl_signal_scope(lsig)) return ports;
|
||||
/* It must be an input or inout port of the task. */
|
||||
sig_name = ivl_signal_basename(lsig);
|
||||
for (idx = 0; idx < ports; idx += 1) {
|
||||
for (idx = first_arg; idx < ports; idx += 1) {
|
||||
ivl_signal_t port = ivl_scope_port(scope, idx);
|
||||
ivl_signal_port_t port_type = ivl_signal_port(port);
|
||||
if ((port_type != IVL_SIP_INPUT) &&
|
||||
|
|
@ -699,6 +700,7 @@ static unsigned utask_in_port_idx(ivl_scope_t scope, ivl_statement_t stmt)
|
|||
static unsigned utask_out_port_idx(ivl_scope_t scope, ivl_statement_t stmt)
|
||||
{
|
||||
unsigned idx, ports = ivl_scope_ports(scope);
|
||||
unsigned first_arg = is_void_function(scope) ? 1 : 0;
|
||||
ivl_expr_t rval = ivl_stmt_rval(stmt);
|
||||
ivl_signal_t rsig = 0;
|
||||
ivl_expr_type_t expr_type = ivl_expr_type(rval);
|
||||
|
|
@ -731,7 +733,7 @@ static unsigned utask_out_port_idx(ivl_scope_t scope, ivl_statement_t stmt)
|
|||
if (ivl_signal_dimensions(rsig)) return ports;
|
||||
/* It must be an output or inout port of the task. */
|
||||
sig_name = ivl_signal_basename(rsig);
|
||||
for (idx = 0; idx < ports; idx += 1) {
|
||||
for (idx = first_arg; idx < ports; idx += 1) {
|
||||
ivl_signal_t port = ivl_scope_port(scope, idx);
|
||||
ivl_signal_port_t port_type = ivl_signal_port(port);
|
||||
if ((port_type != IVL_SIP_OUTPUT) &&
|
||||
|
|
@ -794,6 +796,7 @@ static unsigned is_utask_call_with_args(ivl_scope_t scope,
|
|||
unsigned lineno = ivl_stmt_lineno(stmt);
|
||||
unsigned start, stop, is_auto = 0;
|
||||
ivl_scope_t task_scope = 0;
|
||||
unsigned is_void_func = 0;
|
||||
port_expr_t port_exprs;
|
||||
/* Check to see if the block is of the basic form first. */
|
||||
for (idx = 0; idx < count; idx += 1) {
|
||||
|
|
@ -809,7 +812,8 @@ static unsigned is_utask_call_with_args(ivl_scope_t scope,
|
|||
if (ivl_statement_type(tmp) == IVL_ST_UTASK && !task_scope) {
|
||||
task_idx = idx;
|
||||
task_scope = ivl_stmt_call(tmp);
|
||||
assert(ivl_scope_type(task_scope) == IVL_SCT_TASK);
|
||||
is_void_func = is_void_function(task_scope);
|
||||
assert(ivl_scope_type(task_scope) == IVL_SCT_TASK || is_void_func);
|
||||
continue;
|
||||
}
|
||||
/* For an automatic task the FREE must be last. */
|
||||
|
|
@ -871,7 +875,8 @@ static unsigned is_utask_call_with_args(ivl_scope_t scope,
|
|||
}
|
||||
|
||||
/* Verify that all the ports were defined. */
|
||||
for (idx = 0; idx < ports; idx += 1) {
|
||||
start = is_void_func ? 1 : 0;
|
||||
for (idx = start; idx < ports; idx += 1) {
|
||||
if (port_exprs[idx].type == IVL_SIP_NONE) {
|
||||
free(port_exprs);
|
||||
return 0;
|
||||
|
|
@ -880,14 +885,18 @@ static unsigned is_utask_call_with_args(ivl_scope_t scope,
|
|||
|
||||
/* Now that we have the arguments figured out, print the task call. */
|
||||
fprintf(vlog_out, "%*c", get_indent(), ' ');
|
||||
if (is_void_func)
|
||||
fprintf(vlog_out, "if (");
|
||||
emit_scope_path(scope, task_scope);
|
||||
fprintf(vlog_out, "(");
|
||||
emit_port(scope, port_exprs[0]);
|
||||
for (idx = 1; idx < ports; idx += 1) {
|
||||
emit_port(scope, port_exprs[start]);
|
||||
for (idx = start + 1; idx < ports; idx += 1) {
|
||||
fprintf(vlog_out, ", ");
|
||||
emit_port(scope, port_exprs[idx]);
|
||||
}
|
||||
free(port_exprs);
|
||||
if (is_void_func)
|
||||
fprintf(vlog_out, ")");
|
||||
fprintf(vlog_out, ");");
|
||||
emit_stmt_file_line(stmt);
|
||||
fprintf(vlog_out, "\n");
|
||||
|
|
@ -1419,10 +1428,16 @@ static void emit_stmt_trigger(ivl_scope_t scope, ivl_statement_t stmt)
|
|||
static void emit_stmt_utask(ivl_scope_t scope, ivl_statement_t stmt)
|
||||
{
|
||||
ivl_scope_t task_scope = ivl_stmt_call(stmt);
|
||||
assert(ivl_scope_type(task_scope) == IVL_SCT_TASK);
|
||||
assert(ivl_scope_ports(task_scope) == 0);
|
||||
assert((ivl_scope_type(task_scope) == IVL_SCT_TASK
|
||||
&& ivl_scope_ports(task_scope) == 0)
|
||||
|| (is_void_function(task_scope)
|
||||
&& ivl_scope_ports(task_scope) == 1));
|
||||
fprintf(vlog_out, "%*c", get_indent(), ' ');
|
||||
if (is_void_function(task_scope))
|
||||
fprintf(vlog_out, "if (");
|
||||
emit_scope_path(scope, task_scope);
|
||||
if (is_void_function(task_scope))
|
||||
fprintf(vlog_out, "(1'bx))");
|
||||
fprintf(vlog_out, ";");
|
||||
emit_stmt_file_line(stmt);
|
||||
fprintf(vlog_out, "\n");
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef IVL_vlog95_priv_H
|
||||
#define IVL_vlog95_priv_H
|
||||
/*
|
||||
* Copyright (C) 2010-2017 Cary R. (cygcary@yahoo.com)
|
||||
* Copyright (C) 2010-2019 Cary R. (cygcary@yahoo.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -162,4 +162,10 @@ extern void free_emitted_scope_list(void);
|
|||
*/
|
||||
extern void dump_nexus_information(ivl_scope_t scope, ivl_nexus_t nex);
|
||||
|
||||
static inline unsigned is_void_function(ivl_scope_t scope)
|
||||
{
|
||||
return ivl_scope_type(scope) == IVL_SCT_FUNCTION
|
||||
&& ivl_scope_port(scope, 0) == 0;
|
||||
}
|
||||
|
||||
#endif /* IVL_vlog95_priv_H */
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ void sdf_iopath_delays(int vpi_edge, const char*src, const char*dst,
|
|||
delays.time_type = vpiScaledRealTime;
|
||||
delays.mtm_flag = 0;
|
||||
delays.append_flag = 0;
|
||||
delays.plusere_flag = 0;
|
||||
delays.pulsere_flag = 0;
|
||||
vpi_get_delays(path, &delays);
|
||||
|
||||
for (idx = 0 ; idx < delval_list->count ; idx += 1) {
|
||||
|
|
|
|||
|
|
@ -231,7 +231,7 @@ typedef struct t_vpi_delay {
|
|||
PLI_INT32 time_type; /* vpiScaledRealTime, vpiSimTime */
|
||||
PLI_INT32 mtm_flag;
|
||||
PLI_INT32 append_flag;
|
||||
PLI_INT32 plusere_flag;
|
||||
PLI_INT32 pulsere_flag;
|
||||
} s_vpi_delay, *p_vpi_delay;
|
||||
|
||||
|
||||
|
|
|
|||
10
vvp/arith.cc
10
vvp/arith.cc
|
|
@ -955,13 +955,14 @@ void vvp_shiftl::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|||
|
||||
vvp_vector4_t out (op_a_.size());
|
||||
|
||||
bool overflow_flag;
|
||||
unsigned long shift;
|
||||
if (! vector4_to_value(op_b_, shift)) {
|
||||
if (! vector4_to_value(op_b_, overflow_flag, shift)) {
|
||||
ptr.ptr()->send_vec4(x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (shift > out.size())
|
||||
if (overflow_flag || shift > out.size())
|
||||
shift = out.size();
|
||||
|
||||
for (unsigned idx = 0 ; idx < shift ; idx += 1)
|
||||
|
|
@ -989,13 +990,14 @@ void vvp_shiftr::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|||
|
||||
vvp_vector4_t out (op_a_.size());
|
||||
|
||||
bool overflow_flag;
|
||||
unsigned long shift;
|
||||
if (! vector4_to_value(op_b_, shift)) {
|
||||
if (! vector4_to_value(op_b_, overflow_flag, shift)) {
|
||||
ptr.ptr()->send_vec4(x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (shift > out.size())
|
||||
if (overflow_flag || shift > out.size())
|
||||
shift = out.size();
|
||||
|
||||
for (unsigned idx = shift ; idx < out.size() ; idx += 1)
|
||||
|
|
|
|||
|
|
@ -621,12 +621,13 @@ or z, then the index register gets the value 0. The %ix/vec4/s
|
|||
instruction is the same, except that it assumes the source vector is
|
||||
sign extended to fit the index register.
|
||||
|
||||
The instruction also writes into bit 4 a 1 if any of the bits of the
|
||||
The instruction also writes into flag 4 a 1 if any of the bits of the
|
||||
input vector are x or z. This is a flag that the 0 value written into
|
||||
the index register is really the result of calculating from unknown
|
||||
bits.
|
||||
bits. It writes an X into flag 4 if the vec4 value overflows the index
|
||||
register.
|
||||
|
||||
4: unknown value
|
||||
4: unknown value or overflow
|
||||
5: (reserved)
|
||||
6: (reserved)
|
||||
|
||||
|
|
@ -634,8 +635,8 @@ bits.
|
|||
* %ix/getv/s <idx>, <functor-label>
|
||||
|
||||
These instructions are like the %ix/vec4 instructions, except that they
|
||||
read directly from a functor label instead of from thread bits. They
|
||||
set bit 4 just like %ix/get.
|
||||
read directly from a functor label instead of from thread bits. They set
|
||||
flag 4 just like %ix/get (overflow is not currently checked by ix/getv/s).
|
||||
|
||||
* %ix/load <idx>, <low>, <high>
|
||||
|
||||
|
|
@ -1106,8 +1107,6 @@ The instruction also checks flag bit 4. If it is true, the result is
|
|||
replaced with X instead of a shifted result. This is intended to
|
||||
detect that the index contents were not valid.
|
||||
|
||||
For a negative shift, %shiftr will pad the value with 'bx.
|
||||
|
||||
* %split/vec4 <wid>
|
||||
|
||||
Pull the top vec4 vector from the stack and split it into two
|
||||
|
|
|
|||
|
|
@ -3311,8 +3311,9 @@ bool of_IX_GETV(vthread_t thr, vvp_code_t cp)
|
|||
|
||||
vvp_vector4_t vec;
|
||||
sig->vec4_value(vec);
|
||||
bool overflow_flag;
|
||||
uint64_t val;
|
||||
bool known_flag = vector4_to_value(vec, val);
|
||||
bool known_flag = vector4_to_value(vec, overflow_flag, val);
|
||||
|
||||
if (known_flag)
|
||||
thr->words[index].w_uint = val;
|
||||
|
|
@ -3320,7 +3321,7 @@ bool of_IX_GETV(vthread_t thr, vvp_code_t cp)
|
|||
thr->words[index].w_uint = 0;
|
||||
|
||||
/* Set bit 4 as a flag if the input is unknown. */
|
||||
thr->flags[4] = known_flag ? BIT4_0 : BIT4_1;
|
||||
thr->flags[4] = known_flag ? (overflow_flag ? BIT4_X : BIT4_0) : BIT4_1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -3376,12 +3377,19 @@ static uint64_t vec4_to_index(vthread_t thr, bool signed_flag)
|
|||
thr->flags[4] = BIT4_0;
|
||||
|
||||
assert(sizeof(bits[0]) <= sizeof(v));
|
||||
//assert(val_size <= 8*sizeof(v));
|
||||
|
||||
v = 0;
|
||||
for (unsigned idx = 0 ; idx < val_size ; idx += 8*sizeof(bits[0])) {
|
||||
uint64_t tmp = bits[idx/8/sizeof(bits[0])];
|
||||
if (idx < 8*sizeof(v)) {
|
||||
v |= tmp << idx;
|
||||
} else {
|
||||
bool overflow = signed_flag && (v >> 63) ? ~tmp != 0 : tmp != 0;
|
||||
if (overflow) {
|
||||
thr->flags[4] = BIT4_X;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set the high bits that are not necessarily filled in by the
|
||||
|
|
@ -5402,16 +5410,16 @@ bool of_SET_DAR_OBJ_STR(vthread_t thr, vvp_code_t cp)
|
|||
bool of_SHIFTL(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
int use_index = cp->number;
|
||||
int shift = thr->words[use_index].w_int;
|
||||
uint64_t shift = thr->words[use_index].w_uint;
|
||||
|
||||
vvp_vector4_t&val = thr->peek_vec4();
|
||||
int wid = val.size();
|
||||
unsigned wid = val.size();
|
||||
|
||||
if (thr->flags[4] == BIT4_1) {
|
||||
// The result is 'bx if the shift amount is undefined
|
||||
val = vvp_vector4_t(wid, BIT4_X);
|
||||
|
||||
} else if (shift >= wid) {
|
||||
} else if (thr->flags[4] == BIT4_X || shift >= wid) {
|
||||
// Shift is so big that all value is shifted out. Write
|
||||
// a constant 0 result.
|
||||
val = vvp_vector4_t(wid, BIT4_0);
|
||||
|
|
@ -5421,18 +5429,6 @@ bool of_SHIFTL(vthread_t thr, vvp_code_t cp)
|
|||
vvp_vector4_t tmp (shift, BIT4_0);
|
||||
val.set_vec(0, tmp);
|
||||
val.set_vec(shift, blk);
|
||||
|
||||
} else if (shift < -wid) {
|
||||
val = vvp_vector4_t(wid, BIT4_X);
|
||||
|
||||
} else if (shift < 0) {
|
||||
// Negative left shift is a right shift.
|
||||
// For a negative shift, we pad with 'bx.
|
||||
int use_shift = -shift;
|
||||
vvp_vector4_t blk = val.subvalue(use_shift, wid-use_shift);
|
||||
vvp_vector4_t tmp (use_shift, BIT4_X);
|
||||
val.set_vec(0, blk);
|
||||
val.set_vec(wid-use_shift, tmp);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -5447,15 +5443,15 @@ bool of_SHIFTL(vthread_t thr, vvp_code_t cp)
|
|||
bool of_SHIFTR(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
int use_index = cp->number;
|
||||
int shift = thr->words[use_index].w_int;
|
||||
uint64_t shift = thr->words[use_index].w_uint;
|
||||
|
||||
vvp_vector4_t val = thr->pop_vec4();
|
||||
int wid = val.size();
|
||||
unsigned wid = val.size();
|
||||
|
||||
if (thr->flags[4] == BIT4_1) {
|
||||
val = vvp_vector4_t(wid, BIT4_X);
|
||||
|
||||
} else if (shift > wid) {
|
||||
} else if (thr->flags[4] == BIT4_X || shift > wid) {
|
||||
val = vvp_vector4_t(wid, BIT4_0);
|
||||
|
||||
} else if (shift > 0) {
|
||||
|
|
@ -5463,18 +5459,6 @@ bool of_SHIFTR(vthread_t thr, vvp_code_t cp)
|
|||
vvp_vector4_t tmp (shift, BIT4_0);
|
||||
val.set_vec(0, blk);
|
||||
val.set_vec(wid-shift, tmp);
|
||||
|
||||
} else if (shift < -wid) {
|
||||
val = vvp_vector4_t(wid, BIT4_X);
|
||||
|
||||
} else if (shift < 0) {
|
||||
// Negative right shift is a left shift.
|
||||
// For a negative shift, we pad with 'bx.
|
||||
int use_shift = -shift;
|
||||
vvp_vector4_t blk = val.subvalue(0, wid-use_shift);
|
||||
vvp_vector4_t tmp (use_shift, BIT4_X);
|
||||
val.set_vec(0, tmp);
|
||||
val.set_vec(use_shift, blk);
|
||||
}
|
||||
|
||||
thr->push_vec4(val);
|
||||
|
|
@ -5487,17 +5471,17 @@ bool of_SHIFTR(vthread_t thr, vvp_code_t cp)
|
|||
bool of_SHIFTR_S(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
int use_index = cp->number;
|
||||
int shift = thr->words[use_index].w_int;
|
||||
uint64_t shift = thr->words[use_index].w_uint;
|
||||
|
||||
vvp_vector4_t val = thr->pop_vec4();
|
||||
int wid = val.size();
|
||||
unsigned wid = val.size();
|
||||
|
||||
vvp_bit4_t sign_bit = val.value(val.size()-1);
|
||||
|
||||
if (thr->flags[4] == BIT4_1) {
|
||||
val = vvp_vector4_t(wid, BIT4_X);
|
||||
|
||||
} else if (shift > wid) {
|
||||
} else if (thr->flags[4] == BIT4_X || shift > wid) {
|
||||
val = vvp_vector4_t(wid, sign_bit);
|
||||
|
||||
} else if (shift > 0) {
|
||||
|
|
@ -5505,16 +5489,6 @@ bool of_SHIFTR_S(vthread_t thr, vvp_code_t cp)
|
|||
vvp_vector4_t tmp (shift, sign_bit);
|
||||
val.set_vec(0, blk);
|
||||
val.set_vec(wid-shift, tmp);
|
||||
|
||||
} else if (shift < -wid) {
|
||||
val = vvp_vector4_t(wid, BIT4_X);
|
||||
|
||||
} else if (shift < 0) {
|
||||
int use_shift = -shift;
|
||||
vvp_vector4_t blk = val.subvalue(0, wid-use_shift);
|
||||
vvp_vector4_t tmp(use_shift, BIT4_X);
|
||||
val.set_vec(0, tmp);
|
||||
val.set_vec(use_shift, blk);
|
||||
}
|
||||
|
||||
thr->push_vec4(val);
|
||||
|
|
|
|||
|
|
@ -2042,20 +2042,21 @@ template bool vector4_to_value(const vvp_vector4_t&vec, uint32_t&val,
|
|||
template bool vector4_to_value(const vvp_vector4_t&vec, uint64_t&val,
|
||||
bool is_signed, bool is_arithmetic);
|
||||
|
||||
template <class T> bool vector4_to_value(const vvp_vector4_t&vec, T&val)
|
||||
template <class T> bool vector4_to_value(const vvp_vector4_t&vec,
|
||||
bool&overflow_flag, T&val)
|
||||
{
|
||||
T res = 0;
|
||||
T msk = 1;
|
||||
|
||||
overflow_flag = false;
|
||||
unsigned size = vec.size();
|
||||
for (unsigned idx = 0 ; idx < size ; idx += 1) {
|
||||
switch (vec.value(idx)) {
|
||||
case BIT4_0:
|
||||
break;
|
||||
case BIT4_1:
|
||||
// On overflow, return the maximum value of type T
|
||||
if (msk == 0)
|
||||
res = ~msk;
|
||||
overflow_flag = true;
|
||||
else
|
||||
res |= msk;
|
||||
break;
|
||||
|
|
@ -2070,9 +2071,11 @@ template <class T> bool vector4_to_value(const vvp_vector4_t&vec, T&val)
|
|||
return true;
|
||||
}
|
||||
|
||||
template bool vector4_to_value(const vvp_vector4_t&vec, unsigned long&val);
|
||||
template bool vector4_to_value(const vvp_vector4_t&vec, bool&overflow_flag,
|
||||
unsigned long&val);
|
||||
#ifndef UL_AND_TIME64_SAME
|
||||
template bool vector4_to_value(const vvp_vector4_t&vec, vvp_time64_t&val);
|
||||
template bool vector4_to_value(const vvp_vector4_t&vec, bool&overflow_flag,
|
||||
vvp_time64_t&val);
|
||||
#endif
|
||||
|
||||
bool vector4_to_value(const vvp_vector4_t&vec, double&val, bool signed_flag)
|
||||
|
|
|
|||
|
|
@ -558,7 +558,14 @@ template <class T> extern bool vector4_to_value(const vvp_vector4_t&a, T&val,
|
|||
bool is_signed,
|
||||
bool is_arithmetic =true);
|
||||
|
||||
template <class T> extern bool vector4_to_value(const vvp_vector4_t&a, T&val);
|
||||
template <class T> extern bool vector4_to_value(const vvp_vector4_t&a,
|
||||
bool&overflow_flag, T&val);
|
||||
|
||||
template <class T> inline bool vector4_to_value(const vvp_vector4_t&a, T&val)
|
||||
{
|
||||
bool overflow_flag;
|
||||
return vector4_to_value(a, overflow_flag, val);
|
||||
}
|
||||
|
||||
extern bool vector4_to_value(const vvp_vector4_t&a, double&val, bool is_signed);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue