Add event control for vectors and parts of a vectors.
This patch adds full event control for vectors and parts of a vector. It also fixes the other non-blocking part select code to correctly handle a negative offset ([1:-2] of a [4:0] will have an offset of -2).
This commit is contained in:
parent
38e62bb1d2
commit
8ffec473ef
|
|
@ -293,7 +293,7 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
|
|||
|
||||
static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
|
||||
unsigned delay, ivl_expr_t dexp,
|
||||
unsigned width)
|
||||
unsigned width, unsigned nevents)
|
||||
{
|
||||
ivl_signal_t sig = ivl_lval_sig(lval);
|
||||
ivl_expr_t part_off_ex = ivl_lval_part_off(lval);
|
||||
|
|
@ -303,6 +303,14 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
|
|||
const unsigned long use_word = 0;
|
||||
|
||||
if (ivl_signal_dimensions(sig) > 0) {
|
||||
|
||||
if (nevents) {
|
||||
fprintf(stderr, "vvp-tgt sorry: non-blocking event "
|
||||
"controls are not supported on arrays!\n");
|
||||
exit(1);
|
||||
}
|
||||
assert(nevents == 0);
|
||||
|
||||
assert(word_ix);
|
||||
assign_to_array_word(sig, word_ix, bit, delay, dexp, part_off_ex, width);
|
||||
return;
|
||||
|
|
@ -320,16 +328,7 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
|
|||
|
||||
if (part_off_ex) {
|
||||
unsigned skip_assign = transient_id++;
|
||||
if (dexp == 0) {
|
||||
/* Constant delay... */
|
||||
draw_eval_expr_into_integer(part_off_ex, 1);
|
||||
/* If the index expression has XZ bits, skip the assign. */
|
||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign);
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
|
||||
fprintf(vvp_out, " %%assign/v0/x1 v%p_%lu, %u, %u;\n",
|
||||
sig, use_word, delay, bit);
|
||||
fprintf(vvp_out, "t_%u ;\n", skip_assign);
|
||||
} else {
|
||||
if (dexp != 0) {
|
||||
/* Calculated delay... */
|
||||
int delay_index = allocate_word();
|
||||
draw_eval_expr_into_integer(dexp, delay_index);
|
||||
|
|
@ -341,6 +340,24 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
|
|||
sig, use_word, delay_index, bit);
|
||||
fprintf(vvp_out, "t_%u ;\n", skip_assign);
|
||||
clr_word(delay_index);
|
||||
} else if (nevents != 0) {
|
||||
/* Event control delay... */
|
||||
draw_eval_expr_into_integer(part_off_ex, 1);
|
||||
/* If the index expression has XZ bits, skip the assign. */
|
||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign);
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
|
||||
fprintf(vvp_out, " %%assign/v0/x1/e v%p_%lu, %u;\n",
|
||||
sig, use_word, bit);
|
||||
fprintf(vvp_out, "t_%u ;\n", skip_assign);
|
||||
} else {
|
||||
/* Constant delay... */
|
||||
draw_eval_expr_into_integer(part_off_ex, 1);
|
||||
/* If the index expression has XZ bits, skip the assign. */
|
||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign);
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
|
||||
fprintf(vvp_out, " %%assign/v0/x1 v%p_%lu, %u, %u;\n",
|
||||
sig, use_word, delay, bit);
|
||||
fprintf(vvp_out, "t_%u ;\n", skip_assign);
|
||||
}
|
||||
|
||||
} else if (part_off>0 || ivl_lval_width(lval)!=ivl_signal_width(sig)) {
|
||||
|
|
@ -349,14 +366,7 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
|
|||
single-bit set instruction. */
|
||||
assert(ivl_lval_width(lval) == width);
|
||||
|
||||
if (dexp == 0) {
|
||||
/* Constant delay... */
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
|
||||
fprintf(vvp_out, " %%ix/load 1, %u;\n", part_off);
|
||||
fprintf(vvp_out, " %%assign/v0/x1 v%p_%lu, %u, %u;\n",
|
||||
sig, use_word, delay, bit);
|
||||
|
||||
} else {
|
||||
if (dexp != 0) {
|
||||
/* Calculated delay... */
|
||||
int delay_index = allocate_word();
|
||||
draw_eval_expr_into_integer(dexp, delay_index);
|
||||
|
|
@ -365,14 +375,33 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
|
|||
fprintf(vvp_out, " %%assign/v0/x1/d v%p_%lu, %d, %u;\n",
|
||||
sig, use_word, delay_index, bit);
|
||||
clr_word(delay_index);
|
||||
} else if (nevents != 0) {
|
||||
/* Event control delay... */
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
|
||||
fprintf(vvp_out, " %%ix/load 1, %u;\n", part_off);
|
||||
fprintf(vvp_out, " %%assign/v0/x1/e v%p_%lu, %u;\n",
|
||||
sig, use_word, bit);
|
||||
} else {
|
||||
/* Constant delay... */
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
|
||||
fprintf(vvp_out, " %%ix/load 1, %u;\n", part_off);
|
||||
fprintf(vvp_out, " %%assign/v0/x1 v%p_%lu, %u, %u;\n",
|
||||
sig, use_word, delay, bit);
|
||||
}
|
||||
|
||||
} else if (dexp != 0) {
|
||||
/* Calculated delay... */
|
||||
draw_eval_expr_into_integer(dexp, 1);
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
|
||||
fprintf(vvp_out, " %%assign/v0/d v%p_%lu, 1, %u;\n",
|
||||
sig, use_word, bit);
|
||||
} else if (nevents != 0) {
|
||||
/* Event control delay... */
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
|
||||
fprintf(vvp_out, " %%assign/v0/e v%p_%lu, %u;\n",
|
||||
sig, use_word, bit);
|
||||
} else {
|
||||
/* Constant delay... */
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
|
||||
fprintf(vvp_out, " %%assign/v0 v%p_%lu, %u, %u;\n",
|
||||
sig, use_word, delay, bit);
|
||||
|
|
@ -562,7 +591,7 @@ static int show_stmt_assign_nb_real(ivl_statement_t net)
|
|||
|
||||
/* We need to calculate the delay expression. */
|
||||
if (del) {
|
||||
assert(nevents == 0 && ivl_stmt_cond_expr(net) == 0);
|
||||
assert(nevents == 0);
|
||||
int delay_index = allocate_word();
|
||||
draw_eval_expr_into_integer(del, delay_index);
|
||||
fprintf(vvp_out, " %%assign/wr/d v%p_%lu, %d, %u;\n",
|
||||
|
|
@ -629,6 +658,8 @@ static int show_stmt_assign_nb(ivl_statement_t net)
|
|||
} else {
|
||||
fprintf(vvp_out, " %%evctl/i %s, %lu;\n", name, count);
|
||||
}
|
||||
} else {
|
||||
assert(ivl_stmt_cond_expr(net) == 0);
|
||||
}
|
||||
|
||||
unsigned long delay = 0;
|
||||
|
|
@ -644,16 +675,6 @@ static int show_stmt_assign_nb(ivl_statement_t net)
|
|||
}
|
||||
}
|
||||
|
||||
if (nevents) {
|
||||
fprintf(stderr, "%s:%u: vvp-tgt sorry: non-blocking ",
|
||||
ivl_stmt_file(net), ivl_stmt_lineno(net));
|
||||
if (ivl_stmt_cond_expr(net)) {
|
||||
fprintf(stderr, "repeat ");
|
||||
}
|
||||
fprintf(stderr, "event controls are not supported!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (del && (ivl_expr_type(del) == IVL_EX_ULONG)) {
|
||||
delay = ivl_expr_uvalue(del);
|
||||
del = 0;
|
||||
|
|
@ -675,7 +696,7 @@ static int show_stmt_assign_nb(ivl_statement_t net)
|
|||
unsigned bidx;
|
||||
|
||||
bidx = res.base < 4? res.base : (res.base+cur_rbit);
|
||||
assign_to_lvector(lval, bidx, delay, del, bit_limit);
|
||||
assign_to_lvector(lval, bidx, delay, del, bit_limit, nevents);
|
||||
|
||||
cur_rbit += bit_limit;
|
||||
|
||||
|
|
|
|||
|
|
@ -45,8 +45,10 @@ extern bool of_ASSIGN_D(vthread_t thr, vvp_code_t code);
|
|||
extern bool of_ASSIGN_MV(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ASSIGN_V0(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ASSIGN_V0D(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ASSIGN_V0E(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ASSIGN_V0X1(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ASSIGN_V0X1D(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ASSIGN_V0X1E(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ASSIGN_WR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ASSIGN_WRD(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ASSIGN_WRE(vthread_t thr, vvp_code_t code);
|
||||
|
|
|
|||
|
|
@ -90,8 +90,10 @@ const static struct opcode_table_s opcode_table[] = {
|
|||
{ "%assign/av/d",of_ASSIGN_AVD,3,{OA_ARR_PTR,OA_BIT1, OA_BIT2} },
|
||||
{ "%assign/v0",of_ASSIGN_V0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
|
||||
{ "%assign/v0/d",of_ASSIGN_V0D,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
|
||||
{ "%assign/v0/e",of_ASSIGN_V0E,2,{OA_FUNC_PTR,OA_BIT1, OA_NONE} },
|
||||
{ "%assign/v0/x1",of_ASSIGN_V0X1,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
|
||||
{ "%assign/v0/x1/d",of_ASSIGN_V0X1D,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
|
||||
{ "%assign/v0/x1/e",of_ASSIGN_V0X1E,2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} },
|
||||
{ "%assign/wr", of_ASSIGN_WR, 3,{OA_VPI_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%assign/wr/d",of_ASSIGN_WRD,3,{OA_VPI_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%assign/wr/e",of_ASSIGN_WRE,2,{OA_VPI_PTR, OA_BIT1, OA_NONE} },
|
||||
|
|
|
|||
59
vvp/event.cc
59
vvp/event.cc
|
|
@ -62,6 +62,16 @@ evctl::evctl(unsigned long ecount)
|
|||
next = 0;
|
||||
}
|
||||
|
||||
bool evctl::dec_and_run()
|
||||
{
|
||||
assert(ecount_ != 0);
|
||||
|
||||
ecount_ -= 1;
|
||||
if (ecount_ == 0) run_run();
|
||||
|
||||
return ecount_ == 0;
|
||||
}
|
||||
|
||||
evctl_real::evctl_real(struct __vpiHandle*handle, double value,
|
||||
unsigned long ecount)
|
||||
:evctl(ecount)
|
||||
|
|
@ -70,21 +80,13 @@ evctl_real::evctl_real(struct __vpiHandle*handle, double value,
|
|||
value_ = value;
|
||||
}
|
||||
|
||||
bool evctl_real::dec_and_run()
|
||||
void evctl_real::run_run()
|
||||
{
|
||||
assert(ecount_ != 0);
|
||||
t_vpi_value val;
|
||||
|
||||
ecount_ -= 1;
|
||||
|
||||
if (ecount_ == 0) {
|
||||
t_vpi_value val;
|
||||
|
||||
val.format = vpiRealVal;
|
||||
val.value.real = value_;
|
||||
vpi_put_value(handle_, &val, 0, vpiNoDelay);
|
||||
}
|
||||
|
||||
return ecount_ == 0;
|
||||
val.format = vpiRealVal;
|
||||
val.value.real = value_;
|
||||
vpi_put_value(handle_, &val, 0, vpiNoDelay);
|
||||
}
|
||||
|
||||
void schedule_evctl(struct __vpiHandle*handle, double value,
|
||||
|
|
@ -98,6 +100,37 @@ void schedule_evctl(struct __vpiHandle*handle, double value,
|
|||
ep->last = &((*(ep->last))->next);
|
||||
}
|
||||
|
||||
evctl_vector::evctl_vector(vvp_net_ptr_t ptr, const vvp_vector4_t&value,
|
||||
unsigned off, unsigned wid, unsigned long ecount)
|
||||
:evctl(ecount), value_(value)
|
||||
{
|
||||
ptr_ = ptr;
|
||||
off_ = off;
|
||||
wid_ = wid;
|
||||
}
|
||||
|
||||
void evctl_vector::run_run()
|
||||
{
|
||||
if (wid_ != 0) {
|
||||
vvp_send_vec4_pv(ptr_, value_, off_, value_.size(), wid_);
|
||||
} else {
|
||||
vvp_send_vec4(ptr_, value_);
|
||||
}
|
||||
}
|
||||
|
||||
void schedule_evctl(vvp_net_ptr_t ptr, const vvp_vector4_t&value,
|
||||
unsigned offset, unsigned wid,
|
||||
vvp_net_t*event, unsigned long ecount)
|
||||
{
|
||||
// Get the functor we are going to wait on.
|
||||
waitable_hooks_s*ep = dynamic_cast<waitable_hooks_s*> (event->fun);
|
||||
assert(ep);
|
||||
// Now add this call to the end of the event list.
|
||||
*(ep->last) = new evctl_vector(ptr, value, offset, wid, ecount);
|
||||
ep->last = &((*(ep->last))->next);
|
||||
}
|
||||
|
||||
|
||||
inline vvp_fun_edge::edge_t VVP_EDGE(vvp_bit4_t from, vvp_bit4_t to)
|
||||
{
|
||||
return 1 << ((from << 2) | to);
|
||||
|
|
|
|||
24
vvp/event.h
24
vvp/event.h
|
|
@ -26,7 +26,8 @@ class evctl {
|
|||
|
||||
public:
|
||||
explicit evctl(unsigned long ecount);
|
||||
virtual bool dec_and_run() = 0;
|
||||
bool dec_and_run();
|
||||
virtual void run_run() = 0;
|
||||
virtual ~evctl() {}
|
||||
evctl*next;
|
||||
|
||||
|
|
@ -40,16 +41,35 @@ class evctl_real : public evctl {
|
|||
explicit evctl_real(struct __vpiHandle*handle, double value,
|
||||
unsigned long ecount);
|
||||
virtual ~evctl_real() {}
|
||||
bool dec_and_run();
|
||||
void run_run();
|
||||
|
||||
private:
|
||||
__vpiHandle*handle_;
|
||||
double value_;
|
||||
};
|
||||
|
||||
class evctl_vector : public evctl {
|
||||
|
||||
public:
|
||||
explicit evctl_vector(vvp_net_ptr_t ptr, const vvp_vector4_t&value,
|
||||
unsigned off, unsigned wid, unsigned long ecount);
|
||||
virtual ~evctl_vector() {}
|
||||
void run_run();
|
||||
|
||||
private:
|
||||
vvp_net_ptr_t ptr_;
|
||||
vvp_vector4_t value_;
|
||||
unsigned off_;
|
||||
unsigned wid_;
|
||||
};
|
||||
|
||||
extern void schedule_evctl(struct __vpiHandle*handle, double value,
|
||||
vvp_net_t*event, unsigned long ecount);
|
||||
|
||||
extern void schedule_evctl(vvp_net_ptr_t ptr, const vvp_vector4_t&value,
|
||||
unsigned offset, unsigned wid,
|
||||
vvp_net_t*event, unsigned long ecount);
|
||||
|
||||
/*
|
||||
* Event / edge detection functors
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ word address.
|
|||
|
||||
* %assign/v0 <var-label>, <delay>, <bit>
|
||||
* %assign/v0/d <var-label>, <delayx>, <bit>
|
||||
* %assign/v0/e <var-label>, <bit>
|
||||
|
||||
The %assign/v0 instruction is a vector version of non-blocking
|
||||
assignment. The <delay> is the number of clock ticks in the future
|
||||
|
|
@ -93,11 +94,16 @@ The %assign/v0/d variation gets the delay instead from an integer
|
|||
register that is given by the <delayx> value. This should not be 0, of
|
||||
course, because integer 0 is taken with the vector width.
|
||||
|
||||
The %assign/v0/e variation uses the information in the thread
|
||||
event control registers to determine when to perform the assign.
|
||||
%evctl is used to set the event control information.
|
||||
|
||||
The <var-label> references a .var object that can receive non-blocking
|
||||
assignments. For blocking assignments, see %set/v.
|
||||
|
||||
* %assign/v0/x1 <var-label>, <delay>, <bit>
|
||||
* %assign/v0/x1/d <var-label>, <delayx>, <bit>
|
||||
* %assign/v0/x1/e <var-label>, <bit>
|
||||
|
||||
This is similar to the %assign/v0 instruction, but adds the index-1
|
||||
index register with the canonical index of the destination where the
|
||||
|
|
|
|||
107
vvp/vthread.cc
107
vvp/vthread.cc
|
|
@ -744,6 +744,33 @@ bool of_ASSIGN_V0D(vthread_t thr, vvp_code_t cp)
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is %assign/v0/e <label>, <bit>
|
||||
* Index register 0 contains a vector width.
|
||||
*/
|
||||
bool of_ASSIGN_V0E(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
assert(thr->event != 0);
|
||||
unsigned wid = thr->words[0].w_int;
|
||||
assert(wid > 0);
|
||||
unsigned bit = cp->bit_idx[0];
|
||||
|
||||
vvp_net_ptr_t ptr (cp->net, 0);
|
||||
|
||||
// If the count is zero then just put the value.
|
||||
vvp_vector4_t value = vthread_bits_to_vector(thr, bit, wid);
|
||||
if (thr->ecount == 0) {
|
||||
schedule_assign_plucked_vector(ptr, 0, value, 0, wid);
|
||||
} else {
|
||||
schedule_evctl(ptr, value, 0, 0, thr->event, thr->ecount);
|
||||
}
|
||||
|
||||
thr->event = 0;
|
||||
thr->ecount = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is %assign/v0/x1 <label>, <delay>, <bit>
|
||||
* Index register 0 contains a vector part width.
|
||||
|
|
@ -752,7 +779,7 @@ bool of_ASSIGN_V0D(vthread_t thr, vvp_code_t cp)
|
|||
bool of_ASSIGN_V0X1(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
unsigned wid = thr->words[0].w_int;
|
||||
unsigned off = thr->words[1].w_int;
|
||||
long off = thr->words[1].w_int;
|
||||
unsigned delay = cp->bit_idx[0];
|
||||
unsigned bit = cp->bit_idx[1];
|
||||
|
||||
|
|
@ -761,8 +788,16 @@ bool of_ASSIGN_V0X1(vthread_t thr, vvp_code_t cp)
|
|||
assert(sig);
|
||||
assert(wid > 0);
|
||||
|
||||
if (off >= sig->size())
|
||||
return true;
|
||||
// We fell off the MSB end.
|
||||
if (off >= (long)sig->size()) return true;
|
||||
else if (off < 0 ) {
|
||||
// We fell off the LSB end.
|
||||
if ((unsigned)-off > wid ) return true;
|
||||
// Trim the bits before the LSB
|
||||
wid += off;
|
||||
bit -= off;
|
||||
off = 0;
|
||||
}
|
||||
|
||||
vvp_vector4_t value = vthread_bits_to_vector(thr, bit, wid);
|
||||
|
||||
|
|
@ -773,14 +808,14 @@ bool of_ASSIGN_V0X1(vthread_t thr, vvp_code_t cp)
|
|||
}
|
||||
|
||||
/*
|
||||
* This is %assign/v0/x1 <label>, <delayx>, <bit>
|
||||
* This is %assign/v0/x1/d <label>, <delayx>, <bit>
|
||||
* Index register 0 contains a vector part width.
|
||||
* Index register 1 contains the offset into the destination vector.
|
||||
*/
|
||||
bool of_ASSIGN_V0X1D(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
unsigned wid = thr->words[0].w_int;
|
||||
unsigned off = thr->words[1].w_int;
|
||||
long off = thr->words[1].w_int;
|
||||
unsigned delay = thr->words[cp->bit_idx[0]].w_int;
|
||||
unsigned bit = cp->bit_idx[1];
|
||||
|
||||
|
|
@ -789,8 +824,16 @@ bool of_ASSIGN_V0X1D(vthread_t thr, vvp_code_t cp)
|
|||
assert(sig);
|
||||
assert(wid > 0);
|
||||
|
||||
if (off >= sig->size())
|
||||
return true;
|
||||
// We fell off the MSB end.
|
||||
if (off >= (long)sig->size()) return true;
|
||||
else if (off < 0 ) {
|
||||
// We fell off the LSB end.
|
||||
if ((unsigned)-off > wid ) return true;
|
||||
// Trim the bits before the LSB
|
||||
wid += off;
|
||||
bit -= off;
|
||||
off = 0;
|
||||
}
|
||||
|
||||
vvp_vector4_t value = vthread_bits_to_vector(thr, bit, wid);
|
||||
|
||||
|
|
@ -800,6 +843,56 @@ bool of_ASSIGN_V0X1D(vthread_t thr, vvp_code_t cp)
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is %assign/v0/x1/e <label>, <bit>
|
||||
* Index register 0 contains a vector part width.
|
||||
* Index register 1 contains the offset into the destination vector.
|
||||
*/
|
||||
bool of_ASSIGN_V0X1E(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
unsigned wid = thr->words[0].w_int;
|
||||
long off = thr->words[1].w_int;
|
||||
unsigned bit = cp->bit_idx[0];
|
||||
|
||||
vvp_fun_signal_vec*sig
|
||||
= reinterpret_cast<vvp_fun_signal_vec*> (cp->net->fun);
|
||||
assert(sig);
|
||||
assert(wid > 0);
|
||||
|
||||
// We fell off the MSB end.
|
||||
if (off >= (long)sig->size()) {
|
||||
thr->event = 0;
|
||||
thr->ecount = 0;
|
||||
return true;
|
||||
} else if (off < 0 ) {
|
||||
// We fell off the LSB end.
|
||||
if ((unsigned)-off > wid ) {
|
||||
thr->event = 0;
|
||||
thr->ecount = 0;
|
||||
return true;
|
||||
}
|
||||
// Trim the bits before the LSB
|
||||
wid += off;
|
||||
bit -= off;
|
||||
off = 0;
|
||||
}
|
||||
|
||||
vvp_vector4_t value = vthread_bits_to_vector(thr, bit, wid);
|
||||
|
||||
vvp_net_ptr_t ptr (cp->net, 0);
|
||||
if (thr->ecount == 0) {
|
||||
schedule_assign_vector(ptr, off, sig->size(), value, 0);
|
||||
} else {
|
||||
schedule_evctl(ptr, value, off, sig->size(), thr->event,
|
||||
thr->ecount);
|
||||
}
|
||||
|
||||
thr->event = 0;
|
||||
thr->ecount = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is %assign/wr <vpi-label>, <delay>, <index>
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue