Add assign/deassign to bit/part selects and other fixes

This patch adds the ability to assign/deassign a bit or part select.
It also cleans up the code and fixes some problem in the forcing of
strength aware nets.
This commit is contained in:
Cary R 2008-04-09 18:56:42 -07:00 committed by Stephen Williams
parent 321114e4db
commit 9bb8e8146f
7 changed files with 226 additions and 57 deletions

View File

@ -802,7 +802,7 @@ static void force_vector_to_lval(ivl_statement_t net, struct vector_info rvec)
switch (ivl_statement_type(net)) { switch (ivl_statement_type(net)) {
case IVL_ST_CASSIGN: case IVL_ST_CASSIGN:
command_name = "%cassign/v"; command_name = "%cassign/v";
command_name_x0 = "ERROR"; command_name_x0 = "%cassign/x0";
break; break;
case IVL_ST_FORCE: case IVL_ST_FORCE:
command_name = "%force/v"; command_name = "%force/v";
@ -842,12 +842,6 @@ static void force_vector_to_lval(ivl_statement_t net, struct vector_info rvec)
if (part_off != 0 || use_wid != ivl_signal_width(lsig)) { if (part_off != 0 || use_wid != ivl_signal_width(lsig)) {
if (ivl_statement_type(net) == IVL_ST_CASSIGN) {
fprintf(stderr, "%s:%u: vvp-tgt sorry: cannot assign "
"signal to a bit/part select.\n",
ivl_stmt_file(net), ivl_stmt_lineno(net));
exit(1);
}
command_name = command_name_x0; command_name = command_name_x0;
fprintf(vvp_out, " %%ix/load 0, %u;\n", part_off); fprintf(vvp_out, " %%ix/load 0, %u;\n", part_off);
@ -967,15 +961,12 @@ static int show_stmt_deassign(ivl_statement_t net)
assert(lsig != 0); assert(lsig != 0);
assert(ivl_lval_mux(lval) == 0); assert(ivl_lval_mux(lval) == 0);
/* We do not currently support deassigning a bit or unsigned use_wid = ivl_lval_width(lval);
* part select. */
ivl_expr_t part_off_ex = ivl_lval_part_off(lval); ivl_expr_t part_off_ex = ivl_lval_part_off(lval);
if (ivl_signal_width(lsig) > ivl_lval_width(lval) || unsigned part_off = 0;
(part_off_ex && get_number_immediate(part_off_ex) != 0)) { if (part_off_ex != 0) {
fprintf(stderr, "%s:%u: vvp-tgt sorry: cannot deassign " assert(number_is_immediate(part_off_ex, 64));
"a bit/part select.\n", ivl_stmt_file(net), part_off = get_number_immediate(part_off_ex);
ivl_stmt_lineno(net));
exit(1);
} }
if (word_idx != 0) { if (word_idx != 0) {
@ -984,7 +975,8 @@ static int show_stmt_deassign(ivl_statement_t net)
} }
fprintf(vvp_out, " %%deassign v%p_%lu;\n", lsig, use_word); fprintf(vvp_out, " %%deassign v%p_%lu, %u, %u;\n",
lsig, use_word, part_off, use_wid);
} }
return 0; return 0;

View File

@ -52,6 +52,7 @@ extern bool of_BLEND_WR(vthread_t thr, vvp_code_t code);
extern bool of_BREAKPOINT(vthread_t thr, vvp_code_t code); extern bool of_BREAKPOINT(vthread_t thr, vvp_code_t code);
extern bool of_CASSIGN_LINK(vthread_t thr, vvp_code_t code); extern bool of_CASSIGN_LINK(vthread_t thr, vvp_code_t code);
extern bool of_CASSIGN_V(vthread_t thr, vvp_code_t code); extern bool of_CASSIGN_V(vthread_t thr, vvp_code_t code);
extern bool of_CASSIGN_X0(vthread_t thr, vvp_code_t code);
extern bool of_CMPIS(vthread_t thr, vvp_code_t code); extern bool of_CMPIS(vthread_t thr, vvp_code_t code);
extern bool of_CMPIU(vthread_t thr, vvp_code_t code); extern bool of_CMPIU(vthread_t thr, vvp_code_t code);
extern bool of_CMPS(vthread_t thr, vvp_code_t code); extern bool of_CMPS(vthread_t thr, vvp_code_t code);

View File

@ -101,6 +101,7 @@ const static struct opcode_table_s opcode_table[] = {
{ "%breakpoint", of_BREAKPOINT, 0, {OA_NONE, OA_NONE, OA_NONE} }, { "%breakpoint", of_BREAKPOINT, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%cassign/link",of_CASSIGN_LINK,2,{OA_FUNC_PTR,OA_FUNC_PTR2,OA_NONE} }, { "%cassign/link",of_CASSIGN_LINK,2,{OA_FUNC_PTR,OA_FUNC_PTR2,OA_NONE} },
{ "%cassign/v",of_CASSIGN_V,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} }, { "%cassign/v",of_CASSIGN_V,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
{ "%cassign/x0",of_CASSIGN_X0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
{ "%cmp/s", of_CMPS, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%cmp/s", of_CMPS, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%cmp/u", of_CMPU, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%cmp/u", of_CMPU, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%cmp/wr", of_CMPWR, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, { "%cmp/wr", of_CMPWR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
@ -113,7 +114,7 @@ const static struct opcode_table_s opcode_table[] = {
{ "%cvt/ir", of_CVT_IR, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, { "%cvt/ir", of_CVT_IR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%cvt/ri", of_CVT_RI, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, { "%cvt/ri", of_CVT_RI, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%cvt/vr", of_CVT_VR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%cvt/vr", of_CVT_VR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%deassign",of_DEASSIGN,1,{OA_FUNC_PTR, OA_NONE, OA_NONE} }, { "%deassign",of_DEASSIGN,3,{OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
{ "%delay", of_DELAY, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, { "%delay", of_DELAY, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%delayx", of_DELAYX, 1, {OA_NUMBER, OA_NONE, OA_NONE} }, { "%delayx", of_DELAYX, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
{ "%div", of_DIV, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%div", of_DIV, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },

View File

@ -168,6 +168,13 @@ variable. This is similar to %set, but it uses the cassign port
signal responds differently. See "VARIABLE STATEMENTS" in the signal responds differently. See "VARIABLE STATEMENTS" in the
README.txt file. README.txt file.
* %cassign/x0 <label>, <bit>, <wid>
Perform continuous assign of a constant value to part of the target
variable. This is similar to %set/x instruction, but it uses the
cassign port (port-1) of the signal functor instead of the normal
assign port (port-0), so the signal responds differently. See
"VARIABLE STATEMENTS" and "NET STATEMENTS" in the README.txt file.
* %cmp/u <bit-l>, <bit-r>, <wid> * %cmp/u <bit-l>, <bit-r>, <wid>
* %cmp/s <bit-l>, <bit-r>, <wid> * %cmp/s <bit-l>, <bit-r>, <wid>
@ -239,11 +246,15 @@ The %cvt/vr opcode converts a real word <bit-r> to a thread vector
starting at <bit-l> and with the width <wid>. Non-integer precision is starting at <bit-l> and with the width <wid>. Non-integer precision is
lost in the conversion. lost in the conversion.
* %deassign <var-label> * %deassign <var-label>, <base>, <width>
Deactivate and disconnect a procedural continuous assignment to a Deactivate and disconnect a procedural continuous assignment to a
variable. The <var-label> identifies the affected variable. variable. The <var-label> identifies the affected variable.
The <base> and <width> are used to determine what part of the signal
will be deactivated. For a full deactivation the <base> is 0 and
<width> is the entire signal width.
* %delay <delay> * %delay <delay>
This opcode pauses the thread, and causes it to be rescheduled for a This opcode pauses the thread, and causes it to be rescheduled for a
@ -291,8 +302,8 @@ in the README.txt file.
* %force/x0 <label>, <bit>, <wid> * %force/x0 <label>, <bit>, <wid>
Force a constant value to part target variable. This is similar to Force a constant value to part of the target variable. This is similar
%set/x instruction, but it uses the force port (port-2) of the signal to %set/x instruction, but it uses the force port (port-2) of the signal
functor instead of the normal assign port (port-0), so the signal functor instead of the normal assign port (port-0), so the signal
responds differently. See "VARIABLE STATEMENTS" and "NET STATEMENTS" responds differently. See "VARIABLE STATEMENTS" and "NET STATEMENTS"
in the README.txt file. in the README.txt file.

View File

@ -845,6 +845,40 @@ bool of_CASSIGN_V(vthread_t thr, vvp_code_t cp)
return true; return true;
} }
bool of_CASSIGN_X0(vthread_t thr, vvp_code_t cp)
{
vvp_net_t*net = cp->net;
unsigned base = cp->bit_idx[0];
unsigned wid = cp->bit_idx[1];
// Implicitly, we get the base into the target vector from the
// X0 register.
long index = thr->words[0].w_int;
vvp_fun_signal_vec*sig = dynamic_cast<vvp_fun_signal_vec*> (net->fun);
if (index < 0 && (wid <= (unsigned)-index))
return true;
if (index >= (long)sig->size())
return true;
if (index < 0) {
wid -= (unsigned) -index;
index = 0;
}
if (index+wid > sig->size())
wid = sig->size() - index;
vvp_vector4_t vector = vthread_bits_to_vector(thr, base, wid);
vvp_net_ptr_t ptr (net, 1);
vvp_send_vec4_pv(ptr, vector, index, wid, sig->size());
return true;
}
bool of_CMPS(vthread_t thr, vvp_code_t cp) bool of_CMPS(vthread_t thr, vvp_code_t cp)
{ {
vvp_bit4_t eq = BIT4_1; vvp_bit4_t eq = BIT4_1;
@ -1185,9 +1219,24 @@ bool of_CVT_VR(vthread_t thr, vvp_code_t cp)
bool of_DEASSIGN(vthread_t thr, vvp_code_t cp) bool of_DEASSIGN(vthread_t thr, vvp_code_t cp)
{ {
vvp_net_t*net = cp->net; vvp_net_t*net = cp->net;
unsigned base = cp->bit_idx[0];
unsigned width = cp->bit_idx[1];
vvp_fun_signal_vec*sig = reinterpret_cast<vvp_fun_signal_vec*>(net->fun);
assert(sig);
if (base >= sig->size()) return true;
if (base+width > sig->size()) width = sig->size() - base;
bool full_sig = base == 0 && width == sig->size();
/* Do we release all or part of the net? */
vvp_net_ptr_t ptr (net, 3); vvp_net_ptr_t ptr (net, 3);
vvp_send_long(ptr, 1); if (full_sig) {
vvp_send_long(ptr, 1);
} else {
vvp_send_long_pv(ptr, 1, base, width);
}
return true; return true;
} }
@ -1777,7 +1826,7 @@ bool of_FORCE_V(vthread_t thr, vvp_code_t cp)
/* Collect the thread bits into a vector4 item. */ /* Collect the thread bits into a vector4 item. */
vvp_vector4_t value = vthread_bits_to_vector(thr, base, wid); vvp_vector4_t value = vthread_bits_to_vector(thr, base, wid);
/* set the value into port 1 of the destination. */ /* Set the value into port 2 of the destination. */
vvp_net_ptr_t ptr (net, 2); vvp_net_ptr_t ptr (net, 2);
vvp_send_vec4(ptr, value); vvp_send_vec4(ptr, value);
@ -1787,7 +1836,7 @@ bool of_FORCE_V(vthread_t thr, vvp_code_t cp)
bool of_FORCE_X0(vthread_t thr, vvp_code_t cp) bool of_FORCE_X0(vthread_t thr, vvp_code_t cp)
{ {
vvp_net_t*net = cp->net; vvp_net_t*net = cp->net;
unsigned bit = cp->bit_idx[0]; unsigned base = cp->bit_idx[0];
unsigned wid = cp->bit_idx[1]; unsigned wid = cp->bit_idx[1];
// Implicitly, we get the base into the target vector from the // Implicitly, we get the base into the target vector from the
@ -1810,19 +1859,14 @@ bool of_FORCE_X0(vthread_t thr, vvp_code_t cp)
if (index+wid > sig->size()) if (index+wid > sig->size())
wid = sig->size() - index; wid = sig->size() - index;
vvp_vector4_t bit_vec(wid); vvp_vector4_t vector = vthread_bits_to_vector(thr, base, wid);
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
vvp_bit4_t bit_val = thr_get_bit(thr, bit);
bit_vec.set_bit(idx, bit_val);
if (bit >= 4)
bit += 1;
}
vvp_net_ptr_t ptr (net, 2); vvp_net_ptr_t ptr (net, 2);
vvp_send_vec4_pv(ptr, bit_vec, index, wid, sig->size()); vvp_send_vec4_pv(ptr, vector, index, wid, sig->size());
return true; return true;
} }
/* /*
* The %fork instruction causes a new child to be created and pushed * The %fork instruction causes a new child to be created and pushed
* in front of any existing child. This causes the new child to be the * in front of any existing child. This causes the new child to be the

View File

@ -1133,6 +1133,18 @@ bool vvp_vector2_t::is_NaN() const
return wid_ == 0; return wid_ == 0;
} }
bool vvp_vector2_t::is_zero() const
{
const unsigned words = (wid_ + BITS_PER_WORD-1) / BITS_PER_WORD;
for (unsigned idx = 0; idx < words; idx += 1) {
if (vec_[idx] == 0) continue;
return false;
}
return true;
}
/* /*
* Basic idea from "Introduction to Programming using SML" by * Basic idea from "Introduction to Programming using SML" by
* Michael R. Hansen and Hans Rischel page 261 and "Seminumerical * Michael R. Hansen and Hans Rischel page 261 and "Seminumerical
@ -1659,6 +1671,18 @@ vvp_fun_signal_base::vvp_fun_signal_base()
void vvp_fun_signal_base::deassign() void vvp_fun_signal_base::deassign()
{ {
continuous_assign_active_ = false; continuous_assign_active_ = false;
assign_mask_ = vvp_vector2_t();
}
void vvp_fun_signal_base::deassign_pv(unsigned base, unsigned wid)
{
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
assign_mask_.set_bit(base+idx, 0);
}
if (assign_mask_.is_zero()) {
assign_mask_ = vvp_vector2_t();
}
} }
/* /*
@ -1700,9 +1724,7 @@ void vvp_fun_signal_base::recv_long_pv(vvp_net_ptr_t ptr, long bit,
case 3: // Command port case 3: // Command port
switch (bit) { switch (bit) {
case 1: // deassign command case 1: // deassign command
fprintf(stderr, "Sorry: cannot deassign a partial signal\n"); deassign_pv(base, wid);
assert(0);
deassign();
break; break;
case 2: // release/net case 2: // release/net
release_pv(ptr, true, base, wid); release_pv(ptr, true, base, wid);
@ -1745,22 +1767,34 @@ void vvp_fun_signal::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
{ {
switch (ptr.port()) { switch (ptr.port()) {
case 0: // Normal input (feed from net, or set from process) case 0: // Normal input (feed from net, or set from process)
/* If continuous assign is active, then this is a var /* If we don't have a continuous assign mask then just
and the continuous assigned values overrides any copy the bits, otherwise we need to see if there are
normal input. So process input only if continuous any holes in the mask so we can set those bits. */
assignment is not active. */ if (assign_mask_.size() == 0) {
if (!continuous_assign_active_) {
if (needs_init_ || !bits4_.eeq(bit)) { if (needs_init_ || !bits4_.eeq(bit)) {
bits4_ = bit; bits4_ = bit;
needs_init_ = false; needs_init_ = false;
calculate_output_(ptr); calculate_output_(ptr);
} }
} else {
bool changed = false;
assert(bits4_.size() == assign_mask_.size());
for (unsigned idx = 0 ; idx < bit.size() ; idx += 1) {
if (idx >= bits4_.size()) break;
if (assign_mask_.value(idx)) continue;
bits4_.set_bit(idx, bit.value(idx));
changed = true;
}
if (changed) {
needs_init_ = false;
calculate_output_(ptr);
}
} }
break; break;
case 1: // Continuous assign value case 1: // Continuous assign value
continuous_assign_active_ = true;
bits4_ = bit; bits4_ = bit;
assign_mask_ = vvp_vector2_t(vvp_vector2_t::FILL1, size());
calculate_output_(ptr); calculate_output_(ptr);
break; break;
@ -1792,17 +1826,41 @@ void vvp_fun_signal::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
switch (ptr.port()) { switch (ptr.port()) {
case 0: // Normal input case 0: // Normal input
if (! continuous_assign_active_) { if (assign_mask_.size() == 0) {
for (unsigned idx = 0 ; idx < wid ; idx += 1) { for (unsigned idx = 0 ; idx < wid ; idx += 1) {
if (base+idx >= bits4_.size()) if (base+idx >= bits4_.size()) break;
break;
bits4_.set_bit(base+idx, bit.value(idx)); bits4_.set_bit(base+idx, bit.value(idx));
} }
needs_init_ = false; needs_init_ = false;
calculate_output_(ptr); calculate_output_(ptr);
} else {
bool changed = false;
assert(bits4_.size() == assign_mask_.size());
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
if (base+idx >= bits4_.size()) break;
if (assign_mask_.value(base+idx)) continue;
bits4_.set_bit(base+idx, bit.value(idx));
changed = true;
}
if (changed) {
needs_init_ = false;
calculate_output_(ptr);
}
} }
break; break;
case 1: // Continuous assign value
if (assign_mask_.size() == 0)
assign_mask_ = vvp_vector2_t(vvp_vector2_t::FILL0, size());
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
if (base+idx >= bits4_.size())
break;
bits4_.set_bit(base+idx, bit.value(idx));
assign_mask_.set_bit(base+idx, 1);
}
calculate_output_(ptr);
break;
case 2: // Force value case 2: // Force value
if (force_mask_.size() == 0) if (force_mask_.size() == 0)
@ -1870,6 +1928,7 @@ void vvp_fun_signal::release_pv(vvp_net_ptr_t ptr, bool net,
force_mask_.set_bit(base+idx, 0); force_mask_.set_bit(base+idx, 0);
if (!net) bits4_.set_bit(base+idx, force_.value(base+idx)); if (!net) bits4_.set_bit(base+idx, force_.value(base+idx));
} }
if (force_mask_.is_zero()) force_mask_ = vvp_vector2_t();
if (net) calculate_output_(ptr); if (net) calculate_output_(ptr);
} }
@ -1929,19 +1988,18 @@ void vvp_fun_signal8::recv_vec8(vvp_net_ptr_t ptr, vvp_vector8_t bit)
{ {
switch (ptr.port()) { switch (ptr.port()) {
case 0: // Normal input (feed from net, or set from process) case 0: // Normal input (feed from net, or set from process)
if (!continuous_assign_active_) { if (needs_init_ || !bits8_.eeq(bit)) {
if (needs_init_ || !bits8_.eeq(bit)) { bits8_ = bit;
bits8_ = bit; needs_init_ = false;
needs_init_ = false; calculate_output_(ptr);
calculate_output_(ptr);
}
} }
break; break;
case 1: // Continuous assign value case 1: // Continuous assign value
continuous_assign_active_ = true; /* This is a procedural continuous assign and it can
bits8_ = bit; * only be used on a register and a register is never
calculate_output_(ptr); * strength aware. */
assert(0);
break; break;
case 2: // Force value case 2: // Force value
@ -1964,6 +2022,57 @@ void vvp_fun_signal8::recv_vec8(vvp_net_ptr_t ptr, vvp_vector8_t bit)
} }
} }
void vvp_fun_signal8::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
unsigned base, unsigned wid, unsigned vwid)
{
recv_vec8_pv(ptr, bit, base, wid, vwid);
}
void vvp_fun_signal8::recv_vec8_pv(vvp_net_ptr_t ptr, vvp_vector8_t bit,
unsigned base, unsigned wid, unsigned vwid)
{
assert(bit.size() == wid);
assert(bits8_.size() == vwid);
switch (ptr.port()) {
case 0: // Normal input
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
if (base+idx >= bits8_.size()) break;
bits8_.set_bit(base+idx, bit.value(idx));
}
needs_init_ = false;
calculate_output_(ptr);
break;
case 1: // Continuous assign value
/* This is a procedural continuous assign and it can
* only be used on a register and a register is never
* strength aware. */
assert(0);
break;
case 2: // Force value
if (force_mask_.size() == 0)
force_mask_ = vvp_vector2_t(vvp_vector2_t::FILL0, size());
if (force_.size() == 0)
force_ = vvp_vector8_t(vvp_vector4_t(vwid, BIT4_Z));
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
force_mask_.set_bit(base+idx, 1);
force_.set_bit(base+idx, bit.value(idx));
}
calculate_output_(ptr);
break;
default:
fprintf(stderr, "Unsupported port type %d.\n", ptr.port());
assert(0);
break;
}
}
void vvp_fun_signal8::calculate_output_(vvp_net_ptr_t ptr) void vvp_fun_signal8::calculate_output_(vvp_net_ptr_t ptr)
{ {
if (force_mask_.size()) { if (force_mask_.size()) {
@ -2003,6 +2112,7 @@ void vvp_fun_signal8::release_pv(vvp_net_ptr_t ptr, bool net,
force_mask_.set_bit(base+idx, 0); force_mask_.set_bit(base+idx, 0);
if (!net) bits8_.set_bit(base+idx, force_.value(base+idx)); if (!net) bits8_.set_bit(base+idx, force_.value(base+idx));
} }
if (force_mask_.is_zero()) force_mask_ = vvp_vector2_t();
if (net) calculate_output_(ptr); if (net) calculate_output_(ptr);
} }
@ -2025,9 +2135,14 @@ vvp_bit4_t vvp_fun_signal8::value(unsigned idx) const
vvp_vector4_t vvp_fun_signal8::vec4_value() const vvp_vector4_t vvp_fun_signal8::vec4_value() const
{ {
if (force_mask_.size()) if (force_mask_.size()) {
return reduce4(force_); vvp_vector8_t bits (bits8_);
else for (unsigned idx = 0 ; idx < bits.size() ; idx += 1) {
if (force_mask_.value(idx))
bits.set_bit(idx, force_.value(idx));
}
return reduce4(bits);
} else
return reduce4(bits8_); return reduce4(bits8_);
} }

View File

@ -306,6 +306,7 @@ class vvp_vector2_t {
vvp_vector2_t&operator = (const vvp_vector2_t&); vvp_vector2_t&operator = (const vvp_vector2_t&);
bool is_NaN() const; bool is_NaN() const;
bool is_zero() const;
unsigned size() const; unsigned size() const;
int value(unsigned idx) const; int value(unsigned idx) const;
void set_bit(unsigned idx, int bit); void set_bit(unsigned idx, int bit);
@ -834,8 +835,10 @@ class vvp_fun_signal_base : public vvp_net_fun_t, public vvp_vpi_callback {
bool needs_init_; bool needs_init_;
bool continuous_assign_active_; bool continuous_assign_active_;
vvp_vector2_t force_mask_; vvp_vector2_t force_mask_;
vvp_vector2_t assign_mask_;
void deassign(); void deassign();
void deassign_pv(unsigned base, unsigned wid);
virtual void release(vvp_net_ptr_t ptr, bool net) =0; virtual void release(vvp_net_ptr_t ptr, bool net) =0;
virtual void release_pv(vvp_net_ptr_t ptr, bool net, virtual void release_pv(vvp_net_ptr_t ptr, bool net,
unsigned base, unsigned wid) =0; unsigned base, unsigned wid) =0;
@ -896,8 +899,10 @@ class vvp_fun_signal8 : public vvp_fun_signal_vec {
void recv_vec8(vvp_net_ptr_t port, vvp_vector8_t bit); void recv_vec8(vvp_net_ptr_t port, vvp_vector8_t bit);
// Part select variants of above // Part select variants of above
//void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit, void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
// unsigned base, unsigned wid, unsigned vwid); unsigned base, unsigned wid, unsigned vwid);
void recv_vec8_pv(vvp_net_ptr_t port, vvp_vector8_t bit,
unsigned base, unsigned wid, unsigned vwid);
// Get information about the vector value. // Get information about the vector value.
unsigned size() const; unsigned size() const;