Merge branch 'vvp-net-out-rework'
This commit is contained in:
commit
b0d5a3b8a2
|
|
@ -1739,6 +1739,7 @@ extern int ivl_scope_time_units(ivl_scope_t net);
|
|||
* Returns the file and line where this signal is defined.
|
||||
*/
|
||||
|
||||
extern ivl_scope_t ivl_signal_scope(ivl_signal_t net);
|
||||
extern ivl_nexus_t ivl_signal_nex(ivl_signal_t net, unsigned word);
|
||||
extern int ivl_signal_array_base(ivl_signal_t net);
|
||||
extern unsigned ivl_signal_array_count(ivl_signal_t net);
|
||||
|
|
|
|||
|
|
@ -1926,6 +1926,12 @@ extern "C" int ivl_signal_lsb(ivl_signal_t net)
|
|||
return net->lsb_index;
|
||||
}
|
||||
|
||||
extern "C" ivl_scope_t ivl_signal_scope(ivl_signal_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->scope_;
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_signal_width(ivl_signal_t net)
|
||||
{
|
||||
return net->width_;
|
||||
|
|
|
|||
|
|
@ -479,6 +479,12 @@ static void draw_net_in_scope(ivl_signal_t sig)
|
|||
iword, msb, lsb, driver,
|
||||
nex_data->drivers_count,
|
||||
strength_aware_flag?", strength-aware":"");
|
||||
|
||||
} else if (ivl_signal_local(sig) && ivl_scope_is_auto(ivl_signal_scope(sig))) {
|
||||
assert(word_count == 1);
|
||||
fprintf(vvp_out, "; Elide net v%p_%u name=%s\n",
|
||||
sig, iword, ivl_signal_basename(sig));
|
||||
|
||||
} else {
|
||||
/* If this is an isolated word, it uses its
|
||||
own name. */
|
||||
|
|
@ -897,15 +903,15 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr)
|
|||
|
||||
sig = ivl_expr_signal(rise_exp);
|
||||
assert(ivl_signal_dimensions(sig) == 0);
|
||||
fprintf(vvp_out, ", v%p_0", sig);
|
||||
fprintf(vvp_out, ", %s", draw_net_input(ivl_signal_nex(sig,0)));
|
||||
|
||||
sig = ivl_expr_signal(fall_exp);
|
||||
assert(ivl_signal_dimensions(sig) == 0);
|
||||
fprintf(vvp_out, ", v%p_0", sig);
|
||||
fprintf(vvp_out, ", %s", draw_net_input(ivl_signal_nex(sig,0)));
|
||||
|
||||
sig = ivl_expr_signal(decay_exp);
|
||||
assert(ivl_signal_dimensions(sig) == 0);
|
||||
fprintf(vvp_out, ", v%p_0;\n", sig);
|
||||
fprintf(vvp_out, ", %s;\n", draw_net_input(ivl_signal_nex(sig,0)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ concat.o \
|
|||
dff.o extend.o npmos.o part.o reduce.o resolv.o sfunc.o stop.o symbols.o \
|
||||
ufunc.o codes.o \
|
||||
vthread.o schedule.o statistics.o tables.o udp.o vvp_island.o vvp_net.o \
|
||||
event.o logic.o delay.o words.o island_tran.o $V
|
||||
vvp_net_sig.o event.o logic.o delay.o words.o island_tran.o $V
|
||||
|
||||
ifeq (@WIN32@,yes)
|
||||
# Under Windows (mingw) I need to make the ivl.exe in two steps.
|
||||
|
|
|
|||
98
vvp/arith.cc
98
vvp/arith.cc
|
|
@ -82,14 +82,14 @@ void vvp_arith_abs::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|||
break;
|
||||
}
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, out, 0);
|
||||
ptr.ptr()->send_vec4(out, 0);
|
||||
}
|
||||
|
||||
void vvp_arith_abs::recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
double out = fabs(bit);
|
||||
vvp_send_real(ptr.ptr()->out, out, 0);
|
||||
ptr.ptr()->send_real(out, 0);
|
||||
}
|
||||
|
||||
vvp_arith_cast_int::vvp_arith_cast_int(unsigned wid)
|
||||
|
|
@ -104,7 +104,7 @@ vvp_arith_cast_int::~vvp_arith_cast_int()
|
|||
void vvp_arith_cast_int::recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
vvp_send_vec4(ptr.ptr()->out, vvp_vector4_t(wid_, bit), 0);
|
||||
ptr.ptr()->send_vec4(vvp_vector4_t(wid_, bit), 0);
|
||||
}
|
||||
|
||||
vvp_arith_cast_real::vvp_arith_cast_real(bool signed_flag)
|
||||
|
|
@ -121,7 +121,7 @@ void vvp_arith_cast_real::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|||
{
|
||||
double val;
|
||||
vector4_to_value(bit, val, signed_);
|
||||
vvp_send_real(ptr.ptr()->out, val, 0);
|
||||
ptr.ptr()->send_real(val, 0);
|
||||
}
|
||||
|
||||
// Division
|
||||
|
|
@ -139,13 +139,13 @@ void vvp_arith_div::wide4_(vvp_net_ptr_t ptr)
|
|||
{
|
||||
vvp_vector2_t a2 (op_a_);
|
||||
if (a2.is_NaN()) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
ptr.ptr()->send_vec4(x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
vvp_vector2_t b2 (op_b_);
|
||||
if (b2.is_NaN() || b2.is_zero()) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
ptr.ptr()->send_vec4(x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -162,7 +162,7 @@ void vvp_arith_div::wide4_(vvp_net_ptr_t ptr)
|
|||
}
|
||||
vvp_vector2_t res = a2 / b2;
|
||||
if (negate) res = -res;
|
||||
vvp_send_vec4(ptr.ptr()->out, vector2_to_vector4(res, wid_), 0);
|
||||
ptr.ptr()->send_vec4(vector2_to_vector4(res, wid_), 0);
|
||||
}
|
||||
|
||||
void vvp_arith_div::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
|
|
@ -177,13 +177,13 @@ void vvp_arith_div::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|||
|
||||
unsigned long a;
|
||||
if (! vector4_to_value(op_a_, a)) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
ptr.ptr()->send_vec4(x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned long b;
|
||||
if (! vector4_to_value(op_b_, b)) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
ptr.ptr()->send_vec4(x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -216,7 +216,7 @@ void vvp_arith_div::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|||
for (unsigned idx = 0 ; idx < wid_ ; idx += 1)
|
||||
xval.set_bit(idx, BIT4_X);
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, xval, 0);
|
||||
ptr.ptr()->send_vec4(xval, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -236,7 +236,7 @@ void vvp_arith_div::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|||
val >>= 1;
|
||||
}
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, vval, 0);
|
||||
ptr.ptr()->send_vec4(vval, 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -253,13 +253,13 @@ void vvp_arith_mod::wide_(vvp_net_ptr_t ptr)
|
|||
{
|
||||
vvp_vector2_t a2 (op_a_);
|
||||
if (a2.is_NaN()) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
ptr.ptr()->send_vec4(x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
vvp_vector2_t b2 (op_b_);
|
||||
if (b2.is_NaN() || b2.is_zero()) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
ptr.ptr()->send_vec4(x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -275,7 +275,7 @@ void vvp_arith_mod::wide_(vvp_net_ptr_t ptr)
|
|||
}
|
||||
vvp_vector2_t res = a2 % b2;
|
||||
if (negate) res = -res;
|
||||
vvp_send_vec4(ptr.ptr()->out, vector2_to_vector4(res, res.size()), 0);
|
||||
ptr.ptr()->send_vec4(vector2_to_vector4(res, res.size()), 0);
|
||||
}
|
||||
|
||||
void vvp_arith_mod::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
|
|
@ -290,13 +290,13 @@ void vvp_arith_mod::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|||
|
||||
unsigned long a;
|
||||
if (! vector4_to_value(op_a_, a)) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
ptr.ptr()->send_vec4(x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned long b;
|
||||
if (! vector4_to_value(op_b_, b)) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
ptr.ptr()->send_vec4(x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -328,7 +328,7 @@ void vvp_arith_mod::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|||
for (unsigned idx = 0 ; idx < wid_ ; idx += 1)
|
||||
xval.set_bit(idx, BIT4_X);
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, xval, 0);
|
||||
ptr.ptr()->send_vec4(xval, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -348,7 +348,7 @@ void vvp_arith_mod::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|||
val >>= 1;
|
||||
}
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, vval, 0);
|
||||
ptr.ptr()->send_vec4(vval, 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -369,14 +369,14 @@ void vvp_arith_mult::wide_(vvp_net_ptr_t ptr)
|
|||
vvp_vector2_t b2 (op_b_);
|
||||
|
||||
if (a2.is_NaN() || b2.is_NaN()) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
ptr.ptr()->send_vec4(x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
vvp_vector2_t result = a2 * b2;
|
||||
|
||||
vvp_vector4_t res4 = vector2_to_vector4(result, wid_);
|
||||
vvp_send_vec4(ptr.ptr()->out, res4, 0);
|
||||
ptr.ptr()->send_vec4(res4, 0);
|
||||
}
|
||||
|
||||
void vvp_arith_mult::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
|
|
@ -391,13 +391,13 @@ void vvp_arith_mult::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|||
|
||||
long a;
|
||||
if (! vector4_to_value(op_a_, a, false, true)) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
ptr.ptr()->send_vec4(x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
long b;
|
||||
if (! vector4_to_value(op_b_, b, false, true)) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
ptr.ptr()->send_vec4(x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -414,7 +414,7 @@ void vvp_arith_mult::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|||
val >>= 1;
|
||||
}
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, vval, 0);
|
||||
ptr.ptr()->send_vec4(vval, 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -437,7 +437,7 @@ void vvp_arith_pow::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|||
vvp_vector4_t res4;
|
||||
if (signed_flag_) {
|
||||
if (op_a_.has_xz() || op_b_.has_xz()) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
ptr.ptr()->send_vec4(x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -451,7 +451,7 @@ void vvp_arith_pow::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|||
vvp_vector2_t b2 (op_b_);
|
||||
|
||||
if (a2.is_NaN() || b2.is_NaN()) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
ptr.ptr()->send_vec4(x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -459,7 +459,7 @@ void vvp_arith_pow::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|||
res4 = vector2_to_vector4(result, wid_);
|
||||
}
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, res4, 0);
|
||||
ptr.ptr()->send_vec4(res4, 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -494,14 +494,14 @@ void vvp_arith_sum::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|||
vvp_bit4_t cur = add_with_carry(a, b, carry);
|
||||
|
||||
if (cur == BIT4_X) {
|
||||
vvp_send_vec4(net->out, x_val_, 0);
|
||||
net->send_vec4(x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
value.set_bit(idx, cur);
|
||||
}
|
||||
|
||||
vvp_send_vec4(net->out, value, 0);
|
||||
net->send_vec4(value, 0);
|
||||
}
|
||||
|
||||
vvp_arith_sub::vvp_arith_sub(unsigned wid)
|
||||
|
|
@ -539,14 +539,14 @@ void vvp_arith_sub::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|||
vvp_bit4_t cur = add_with_carry(a, b, carry);
|
||||
|
||||
if (cur == BIT4_X) {
|
||||
vvp_send_vec4(net->out, x_val_, 0);
|
||||
net->send_vec4(x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
value.set_bit(idx, cur);
|
||||
}
|
||||
|
||||
vvp_send_vec4(net->out, value, 0);
|
||||
net->send_vec4(value, 0);
|
||||
}
|
||||
|
||||
vvp_cmp_eeq::vvp_cmp_eeq(unsigned wid)
|
||||
|
|
@ -571,7 +571,7 @@ void vvp_cmp_eeq::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|||
|
||||
|
||||
vvp_net_t*net = ptr.ptr();
|
||||
vvp_send_vec4(net->out, eeq, 0);
|
||||
net->send_vec4(eeq, 0);
|
||||
}
|
||||
|
||||
vvp_cmp_nee::vvp_cmp_nee(unsigned wid)
|
||||
|
|
@ -596,7 +596,7 @@ void vvp_cmp_nee::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|||
|
||||
|
||||
vvp_net_t*net = ptr.ptr();
|
||||
vvp_send_vec4(net->out, eeq, 0);
|
||||
net->send_vec4(eeq, 0);
|
||||
}
|
||||
|
||||
vvp_cmp_eq::vvp_cmp_eq(unsigned wid)
|
||||
|
|
@ -643,7 +643,7 @@ void vvp_cmp_eq::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|||
}
|
||||
|
||||
vvp_net_t*net = ptr.ptr();
|
||||
vvp_send_vec4(net->out, res, 0);
|
||||
net->send_vec4(res, 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -691,7 +691,7 @@ void vvp_cmp_ne::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|||
}
|
||||
|
||||
vvp_net_t*net = ptr.ptr();
|
||||
vvp_send_vec4(net->out, res, 0);
|
||||
net->send_vec4(res, 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -712,7 +712,7 @@ void vvp_cmp_gtge_base_::recv_vec4_base_(vvp_net_ptr_t ptr,
|
|||
: compare_gtge(op_a_, op_b_, out_if_equal);
|
||||
vvp_vector4_t val (1);
|
||||
val.set_bit(0, out);
|
||||
vvp_send_vec4(ptr.ptr()->out, val, 0);
|
||||
ptr.ptr()->send_vec4(val, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -759,7 +759,7 @@ void vvp_shiftl::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|||
|
||||
unsigned long shift;
|
||||
if (! vector4_to_value(op_b_, shift)) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
ptr.ptr()->send_vec4(x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -772,7 +772,7 @@ void vvp_shiftl::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|||
for (unsigned idx = shift ; idx < out.size() ; idx += 1)
|
||||
out.set_bit(idx, op_a_.value(idx-shift));
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, out, 0);
|
||||
ptr.ptr()->send_vec4(out, 0);
|
||||
}
|
||||
|
||||
vvp_shiftr::vvp_shiftr(unsigned wid, bool signed_flag)
|
||||
|
|
@ -793,7 +793,7 @@ void vvp_shiftr::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|||
|
||||
unsigned long shift;
|
||||
if (! vector4_to_value(op_b_, shift)) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
ptr.ptr()->send_vec4(x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -810,7 +810,7 @@ void vvp_shiftr::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|||
for (unsigned idx = 0 ; idx < shift ; idx += 1)
|
||||
out.set_bit(idx+out.size()-shift, pad);
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, out, 0);
|
||||
ptr.ptr()->send_vec4(out, 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -851,7 +851,7 @@ void vvp_arith_mult_real::recv_real(vvp_net_ptr_t ptr, double bit,
|
|||
dispatch_operand_(ptr, bit);
|
||||
|
||||
double val = op_a_ * op_b_;
|
||||
vvp_send_real(ptr.ptr()->out, val, 0);
|
||||
ptr.ptr()->send_real(val, 0);
|
||||
}
|
||||
|
||||
/* Real power. */
|
||||
|
|
@ -869,7 +869,7 @@ void vvp_arith_pow_real::recv_real(vvp_net_ptr_t ptr, double bit,
|
|||
dispatch_operand_(ptr, bit);
|
||||
|
||||
double val = pow(op_a_, op_b_);
|
||||
vvp_send_real(ptr.ptr()->out, val, 0);
|
||||
ptr.ptr()->send_real(val, 0);
|
||||
}
|
||||
|
||||
/* Real division. */
|
||||
|
|
@ -887,7 +887,7 @@ void vvp_arith_div_real::recv_real(vvp_net_ptr_t ptr, double bit,
|
|||
dispatch_operand_(ptr, bit);
|
||||
|
||||
double val = op_a_ / op_b_;
|
||||
vvp_send_real(ptr.ptr()->out, val, 0);
|
||||
ptr.ptr()->send_real(val, 0);
|
||||
}
|
||||
|
||||
/* Real modulus. */
|
||||
|
|
@ -905,7 +905,7 @@ void vvp_arith_mod_real::recv_real(vvp_net_ptr_t ptr, double bit,
|
|||
dispatch_operand_(ptr, bit);
|
||||
|
||||
double val = fmod(op_a_, op_b_);
|
||||
vvp_send_real(ptr.ptr()->out, val, 0);
|
||||
ptr.ptr()->send_real(val, 0);
|
||||
}
|
||||
|
||||
/* Real summation. */
|
||||
|
|
@ -923,7 +923,7 @@ void vvp_arith_sum_real::recv_real(vvp_net_ptr_t ptr, double bit,
|
|||
dispatch_operand_(ptr, bit);
|
||||
|
||||
double val = op_a_ + op_b_;
|
||||
vvp_send_real(ptr.ptr()->out, val, 0);
|
||||
ptr.ptr()->send_real(val, 0);
|
||||
}
|
||||
|
||||
/* Real subtraction. */
|
||||
|
|
@ -941,7 +941,7 @@ void vvp_arith_sub_real::recv_real(vvp_net_ptr_t ptr, double bit,
|
|||
dispatch_operand_(ptr, bit);
|
||||
|
||||
double val = op_a_ - op_b_;
|
||||
vvp_send_real(ptr.ptr()->out, val, 0);
|
||||
ptr.ptr()->send_real(val, 0);
|
||||
}
|
||||
|
||||
/* Real compare equal. */
|
||||
|
|
@ -958,7 +958,7 @@ void vvp_cmp_eq_real::recv_real(vvp_net_ptr_t ptr, const double bit,
|
|||
if (op_a_ == op_b_) res.set_bit(0, BIT4_1);
|
||||
else res.set_bit(0, BIT4_0);
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, res, 0);
|
||||
ptr.ptr()->send_vec4(res, 0);
|
||||
}
|
||||
|
||||
/* Real compare not equal. */
|
||||
|
|
@ -975,7 +975,7 @@ void vvp_cmp_ne_real::recv_real(vvp_net_ptr_t ptr, const double bit,
|
|||
if (op_a_ != op_b_) res.set_bit(0, BIT4_1);
|
||||
else res.set_bit(0, BIT4_0);
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, res, 0);
|
||||
ptr.ptr()->send_vec4(res, 0);
|
||||
}
|
||||
|
||||
/* Real compare greater than or equal. */
|
||||
|
|
@ -992,7 +992,7 @@ void vvp_cmp_ge_real::recv_real(vvp_net_ptr_t ptr, const double bit,
|
|||
if (op_a_ >= op_b_) res.set_bit(0, BIT4_1);
|
||||
else res.set_bit(0, BIT4_0);
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, res, 0);
|
||||
ptr.ptr()->send_vec4(res, 0);
|
||||
}
|
||||
|
||||
/* Real compare greater than. */
|
||||
|
|
@ -1009,5 +1009,5 @@ void vvp_cmp_gt_real::recv_real(vvp_net_ptr_t ptr, const double bit,
|
|||
if (op_a_ > op_b_) res.set_bit(0, BIT4_1);
|
||||
else res.set_bit(0, BIT4_0);
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, res, 0);
|
||||
ptr.ptr()->send_vec4(res, 0);
|
||||
}
|
||||
|
|
|
|||
52
vvp/array.cc
52
vvp/array.cc
|
|
@ -21,6 +21,7 @@
|
|||
#include "symbols.h"
|
||||
#include "schedule.h"
|
||||
#include "vpi_priv.h"
|
||||
#include "vvp_net_sig.h"
|
||||
#include "config.h"
|
||||
#ifdef CHECK_WITH_VALGRIND
|
||||
#include "vvp_cleanup.h"
|
||||
|
|
@ -886,8 +887,7 @@ void array_set_word(vvp_array_t arr,
|
|||
struct __vpiSignal*vsig = vpip_signal_from_handle(word);
|
||||
assert(vsig);
|
||||
|
||||
vvp_net_ptr_t ptr (vsig->node, 0);
|
||||
vvp_send_vec4_pv(ptr, val, part_off, val.size(), vpip_size(vsig), 0);
|
||||
vsig->node->send_vec4_pv(val, part_off, val.size(), vpip_size(vsig), 0);
|
||||
array_word_change(arr, address);
|
||||
}
|
||||
|
||||
|
|
@ -917,17 +917,18 @@ vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address)
|
|||
// width by looking at a word that we know is present.
|
||||
assert(arr->array_count > 0);
|
||||
vpiHandle word = arr->nets[0];
|
||||
assert(word);
|
||||
struct __vpiSignal*vsig = vpip_signal_from_handle(word);
|
||||
assert(vsig);
|
||||
vvp_fun_signal_vec*sig = dynamic_cast<vvp_fun_signal_vec*> (vsig->node->fun);
|
||||
vvp_signal_value*sig = dynamic_cast<vvp_signal_value*> (vsig->node->fil);
|
||||
assert(sig);
|
||||
return vvp_vector4_t(sig->size(), BIT4_X);
|
||||
return vvp_vector4_t(sig->value_size(), BIT4_X);
|
||||
}
|
||||
|
||||
vpiHandle word = arr->nets[address];
|
||||
struct __vpiSignal*vsig = vpip_signal_from_handle(word);
|
||||
assert(vsig);
|
||||
vvp_fun_signal_vec*sig = dynamic_cast<vvp_fun_signal_vec*> (vsig->node->fun);
|
||||
vvp_signal_value*sig = dynamic_cast<vvp_signal_value*> (vsig->node->fil);
|
||||
assert(sig);
|
||||
|
||||
vvp_vector4_t val = sig->vec4_value();
|
||||
|
|
@ -946,7 +947,7 @@ double array_get_word_r(vvp_array_t arr, unsigned address)
|
|||
vpiHandle word = arr->nets[address];
|
||||
struct __vpiRealVar*vsig = vpip_realvar_from_handle(word);
|
||||
assert(vsig);
|
||||
vvp_fun_signal_real*sig = dynamic_cast<vvp_fun_signal_real*> (vsig->net->fun);
|
||||
vvp_signal_value*sig = dynamic_cast<vvp_signal_value*> (vsig->net->fil);
|
||||
assert(sig);
|
||||
|
||||
double val = sig->real_value();
|
||||
|
|
@ -1023,7 +1024,7 @@ void array_alias_word(vvp_array_t array, unsigned long addr, vpiHandle word)
|
|||
array->nets[addr] = word;
|
||||
}
|
||||
|
||||
void array_attach_word(vvp_array_t array, unsigned long addr, vpiHandle word)
|
||||
void array_attach_word(vvp_array_t array, unsigned addr, vpiHandle word)
|
||||
{
|
||||
assert(addr < array->array_count);
|
||||
assert(array->nets);
|
||||
|
|
@ -1032,7 +1033,7 @@ void array_attach_word(vvp_array_t array, unsigned long addr, vpiHandle word)
|
|||
if (struct __vpiSignal*sig = vpip_signal_from_handle(word)) {
|
||||
vvp_net_t*net = sig->node;
|
||||
assert(net);
|
||||
vvp_fun_signal_base*fun = dynamic_cast<vvp_fun_signal_base*>(net->fun);
|
||||
vvp_vpi_callback*fun = dynamic_cast<vvp_vpi_callback*>(net->fil);
|
||||
assert(fun);
|
||||
fun->attach_as_word(array, addr);
|
||||
sig->is_netarray = 1;
|
||||
|
|
@ -1044,7 +1045,7 @@ void array_attach_word(vvp_array_t array, unsigned long addr, vpiHandle word)
|
|||
if (struct __vpiRealVar*sig = (struct __vpiRealVar*)word) {
|
||||
vvp_net_t*net = sig->net;
|
||||
assert(net);
|
||||
vvp_fun_signal_base*fun = dynamic_cast<vvp_fun_signal_base*>(net->fun);
|
||||
vvp_vpi_callback*fun = dynamic_cast<vvp_vpi_callback*>(net->fil);
|
||||
assert(fun);
|
||||
fun->attach_as_word(array, addr);
|
||||
sig->is_netarray = 1;
|
||||
|
|
@ -1192,12 +1193,13 @@ void vvp_fun_arrayport_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit
|
|||
|
||||
case 0: // Address input
|
||||
addr_valid_flag = vector4_to_value(bit, addr_);
|
||||
if (! addr_valid_flag) addr_ = arr_->array_count;
|
||||
if (vpi_array_is_real(arr_)) {
|
||||
vvp_send_real(net_->out, array_get_word_r(arr_, addr_), 0);
|
||||
} else {
|
||||
vvp_send_vec4(net_->out, array_get_word(arr_, addr_), 0);
|
||||
}
|
||||
if (! addr_valid_flag)
|
||||
addr_ = arr_->array_count;
|
||||
if (vpi_array_is_real(arr_))
|
||||
port.ptr()->send_real(array_get_word_r(arr_, addr_), 0);
|
||||
else
|
||||
port.ptr()->send_vec4(array_get_word(arr_,addr_), 0);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -1211,9 +1213,9 @@ void vvp_fun_arrayport_sa::check_word_change(unsigned long addr)
|
|||
if (addr != addr_) return;
|
||||
|
||||
if (vpi_array_is_real(arr_)) {
|
||||
vvp_send_real(net_->out, array_get_word_r(arr_, addr_), 0);
|
||||
net_->send_real(array_get_word_r(arr_, addr_), 0);
|
||||
} else {
|
||||
vvp_send_vec4(net_->out, array_get_word(arr_, addr_), 0);
|
||||
net_->send_vec4(array_get_word(arr_, addr_), 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1298,13 +1300,11 @@ void vvp_fun_arrayport_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit
|
|||
addr_valid_flag = vector4_to_value(bit, *addr);
|
||||
if (! addr_valid_flag) *addr = arr_->array_count;
|
||||
if (vpi_array_is_real(arr_)) {
|
||||
vvp_send_real(port.ptr()->out,
|
||||
array_get_word_r(arr_, *addr),
|
||||
context);
|
||||
port.ptr()->send_real(array_get_word_r(arr_, *addr),
|
||||
context);
|
||||
} else {
|
||||
vvp_send_vec4(port.ptr()->out,
|
||||
array_get_word(arr_, *addr),
|
||||
context);
|
||||
port.ptr()->send_vec4(array_get_word(arr_, *addr),
|
||||
context);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -1330,10 +1330,10 @@ void vvp_fun_arrayport_aa::check_word_change(unsigned long addr)
|
|||
return;
|
||||
|
||||
if (vpi_array_is_real(arr_)) {
|
||||
vvp_send_real(net_->out, array_get_word_r(arr_, addr),
|
||||
vthread_get_wt_context());
|
||||
net_->send_real(array_get_word_r(arr_, addr),
|
||||
vthread_get_wt_context());
|
||||
} else {
|
||||
vvp_send_vec4(net_->out, array_get_word(arr_, addr),
|
||||
net_->send_vec4(array_get_word(arr_, addr),
|
||||
vthread_get_wt_context());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,8 +34,7 @@ extern vpiHandle array_index_iterate(int code, vpiHandle ref);
|
|||
|
||||
extern void array_word_change(vvp_array_t array, unsigned long addr);
|
||||
|
||||
extern void array_attach_word(vvp_array_t array, unsigned long addr,
|
||||
vpiHandle word);
|
||||
extern void array_attach_word(vvp_array_t array, unsigned addr, vpiHandle word);
|
||||
extern void array_alias_word(vvp_array_t array, unsigned long addr,
|
||||
vpiHandle word);
|
||||
|
||||
|
|
|
|||
|
|
@ -79,5 +79,5 @@ void vvp_fun_bufif::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|||
}
|
||||
}
|
||||
|
||||
vvp_send_vec8(ptr.ptr()->out, out);
|
||||
ptr.ptr()->send_vec8(out);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -370,9 +370,7 @@ bool vvp_net_resolv_list_s::resolve(bool mes)
|
|||
|
||||
if (tmp) {
|
||||
// Link the input port to the located output.
|
||||
vvp_net_t*net = port.ptr();
|
||||
net->port[port.port()] = tmp->out;
|
||||
tmp->out = port;
|
||||
tmp->link(port);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -732,12 +730,27 @@ void compile_vpi_time_precision(long pre)
|
|||
*
|
||||
* The real value is sign * (mant ** exp).
|
||||
*/
|
||||
double crstring_to_double(char*label)
|
||||
bool crstring_test(const char*str)
|
||||
{
|
||||
char*cp = label+3;
|
||||
if (strncmp(str, "Cr<", 3) != 0) return false;
|
||||
const char*tp = strchr(str, '>');
|
||||
if (tp == 0) return false;
|
||||
if (tp[1] != 0) return false;
|
||||
|
||||
if ((strspn(str+3, "0123456789abcdefmg")+3) != (tp - str))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
double crstring_to_double(const char*label)
|
||||
{
|
||||
const char*cp = label+3;
|
||||
assert(*cp == 'm');
|
||||
cp += 1;
|
||||
uint64_t mant = strtoull(cp, &cp, 16);
|
||||
char*ep;
|
||||
uint64_t mant = strtoull(cp, &ep, 16);
|
||||
cp = ep;
|
||||
assert(*cp == 'g');
|
||||
cp += 1;
|
||||
int exp = strtoul(cp, 0, 16);
|
||||
|
|
@ -776,13 +789,9 @@ double crstring_to_double(char*label)
|
|||
void input_connect(vvp_net_t*fdx, unsigned port, char*label)
|
||||
{
|
||||
vvp_net_ptr_t ifdx = vvp_net_ptr_t(fdx, port);
|
||||
char*tp;
|
||||
|
||||
/* Is this a vvp_vector4_t constant value? */
|
||||
if ((strncmp(label, "C4<", 3) == 0)
|
||||
&& ((tp = strchr(label,'>')))
|
||||
&& (tp[1] == 0)
|
||||
&& (strspn(label+3, "01xz")+3 == (unsigned)(tp-label))) {
|
||||
if (c4string_test(label)) {
|
||||
|
||||
vvp_vector4_t tmp = c4string_to_vector4(label);
|
||||
|
||||
|
|
@ -800,40 +809,9 @@ void input_connect(vvp_net_t*fdx, unsigned port, char*label)
|
|||
}
|
||||
|
||||
/* Is this a vvp_vector8_t constant value? */
|
||||
if ((strncmp(label, "C8<", 3) == 0)
|
||||
&& ((tp = strchr(label,'>')))
|
||||
&& (tp[1] == 0)
|
||||
&& (strspn(label+3, "01234567xz")+3 == (unsigned)(tp-label))) {
|
||||
|
||||
size_t vsize = tp-label-3;
|
||||
assert(vsize%3 == 0);
|
||||
vsize /= 3;
|
||||
|
||||
vvp_vector8_t tmp (vsize);
|
||||
|
||||
for (unsigned idx = 0 ; idx < vsize ; idx += 1) {
|
||||
vvp_bit4_t bit = BIT4_Z;
|
||||
unsigned dr0 = label[3+idx*3+0] - '0';
|
||||
unsigned dr1 = label[3+idx*3+1] - '0';
|
||||
|
||||
switch (label[3+idx*3+2]) {
|
||||
case '0':
|
||||
bit = BIT4_0;
|
||||
break;
|
||||
case '1':
|
||||
bit = BIT4_1;
|
||||
break;
|
||||
case 'x':
|
||||
bit = BIT4_X;
|
||||
break;
|
||||
case 'z':
|
||||
bit = BIT4_Z;
|
||||
break;
|
||||
}
|
||||
|
||||
tmp.set_bit(vsize-idx-1, vvp_scalar_t(bit, dr0, dr1));
|
||||
}
|
||||
if (c8string_test(label)) {
|
||||
|
||||
vvp_vector8_t tmp = c8string_to_vector8(label);
|
||||
schedule_set_vector(ifdx, tmp);
|
||||
|
||||
free(label);
|
||||
|
|
@ -842,10 +820,7 @@ void input_connect(vvp_net_t*fdx, unsigned port, char*label)
|
|||
|
||||
/* Handle the Cr<> constant driver, which is a real-value
|
||||
driver. */
|
||||
if ((strncmp(label, "Cr<", 3) == 0)
|
||||
&& ((tp = strchr(label,'>')))
|
||||
&& (tp[1] == 0)
|
||||
&& (strspn(label+3, "0123456789abcdefmg")+3 == (unsigned)(tp-label))) {
|
||||
if (crstring_test(label)) {
|
||||
|
||||
double tmp = crstring_to_double(label);
|
||||
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ void vvp_fun_concat::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
val_.set_bit(off+idx, bit.value(idx));
|
||||
}
|
||||
|
||||
vvp_send_vec4(port.ptr()->out, val_, 0);
|
||||
port.ptr()->send_vec4(val_, 0);
|
||||
}
|
||||
|
||||
void compile_concat(char*label, unsigned w0, unsigned w1,
|
||||
|
|
@ -107,7 +107,7 @@ void vvp_fun_repeat::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
|
||||
}
|
||||
|
||||
vvp_send_vec4(port.ptr()->out, val, 0);
|
||||
port.ptr()->send_vec4(val, 0);
|
||||
}
|
||||
|
||||
void compile_repeat(char*label, long width, long repeat, struct symb_s arg)
|
||||
|
|
|
|||
14
vvp/delay.cc
14
vvp/delay.cc
|
|
@ -295,7 +295,7 @@ void vvp_fun_delay::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
if (use_delay == 0) {
|
||||
cur_vec4_ = bit;
|
||||
initial_ = false;
|
||||
vvp_send_vec4(net_->out, cur_vec4_, 0);
|
||||
net_->send_vec4(cur_vec4_, 0);
|
||||
} else {
|
||||
struct event_*cur = new struct event_(use_simtime);
|
||||
cur->run_run_ptr = &vvp_fun_delay::run_run_vec4_;
|
||||
|
|
@ -353,7 +353,7 @@ void vvp_fun_delay::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
|
|||
if (use_delay == 0) {
|
||||
cur_vec8_ = bit;
|
||||
initial_ = false;
|
||||
vvp_send_vec8(net_->out, cur_vec8_);
|
||||
net_->send_vec8(cur_vec8_);
|
||||
} else {
|
||||
struct event_*cur = new struct event_(use_simtime);
|
||||
cur->ptr_vec8 = bit;
|
||||
|
|
@ -412,7 +412,7 @@ void vvp_fun_delay::recv_real(vvp_net_ptr_t port, double bit,
|
|||
if (use_delay == 0) {
|
||||
cur_real_ = bit;
|
||||
initial_ = false;
|
||||
vvp_send_real(net_->out, cur_real_, 0);
|
||||
net_->send_real(cur_real_, 0);
|
||||
} else {
|
||||
struct event_*cur = new struct event_(use_simtime);
|
||||
cur->run_run_ptr = &vvp_fun_delay::run_run_real_;
|
||||
|
|
@ -441,19 +441,19 @@ void vvp_fun_delay::run_run()
|
|||
void vvp_fun_delay::run_run_vec4_(struct event_*cur)
|
||||
{
|
||||
cur_vec4_ = cur->ptr_vec4;
|
||||
vvp_send_vec4(net_->out, cur_vec4_, 0);
|
||||
net_->send_vec4(cur_vec4_, 0);
|
||||
}
|
||||
|
||||
void vvp_fun_delay::run_run_vec8_(struct vvp_fun_delay::event_*cur)
|
||||
{
|
||||
cur_vec8_ = cur->ptr_vec8;
|
||||
vvp_send_vec8(net_->out, cur_vec8_);
|
||||
net_->send_vec8(cur_vec8_);
|
||||
}
|
||||
|
||||
void vvp_fun_delay::run_run_real_(struct vvp_fun_delay::event_*cur)
|
||||
{
|
||||
cur_real_ = cur->ptr_real;
|
||||
vvp_send_real(net_->out, cur_real_, 0);
|
||||
net_->send_real(cur_real_, 0);
|
||||
}
|
||||
|
||||
vvp_fun_modpath::vvp_fun_modpath(vvp_net_t*net)
|
||||
|
|
@ -617,7 +617,7 @@ void vvp_fun_modpath::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
|
||||
void vvp_fun_modpath::run_run()
|
||||
{
|
||||
vvp_send_vec4(net_->out, cur_vec4_, 0);
|
||||
net_->send_vec4(cur_vec4_, 0);
|
||||
}
|
||||
|
||||
vvp_fun_modpath_src::vvp_fun_modpath_src(vvp_time64_t del[12])
|
||||
|
|
|
|||
16
vvp/dff.cc
16
vvp/dff.cc
|
|
@ -24,6 +24,7 @@
|
|||
# include <stdio.h>
|
||||
# include <assert.h>
|
||||
# include <stdlib.h>
|
||||
# include <iostream>
|
||||
#ifdef HAVE_MALLOC_H
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
|
|
@ -58,7 +59,7 @@ void vvp_dff::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
tmp = clk_cur_;
|
||||
clk_cur_ = bit.value(0);
|
||||
if (clk_cur_ == BIT4_1 && tmp != BIT4_1)
|
||||
vvp_send_vec4(port.ptr()->out, d_, 0);
|
||||
port.ptr()->send_vec4(d_, 0);
|
||||
break;
|
||||
|
||||
case 2: // CE
|
||||
|
|
@ -67,8 +68,17 @@ void vvp_dff::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
break;
|
||||
|
||||
case 3: // Asynch-D
|
||||
d_ = bit;
|
||||
vvp_send_vec4(port.ptr()->out, d_, 0);
|
||||
// FIXME! The code generator is writing an input C4<z>
|
||||
// no matter what the intent of this device. This is
|
||||
// almost certainly NOT correct, nor do we want to
|
||||
// propagate that. But that needs to be fixed later.
|
||||
if (bit.size() == 1 && bit.value(0)==BIT4_Z)
|
||||
break;
|
||||
if (d_.size() > bit.size())
|
||||
d_ .copy_bits(bit);
|
||||
else
|
||||
d_ = bit;
|
||||
port.ptr()->send_vec4(d_, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
49
vvp/event.cc
49
vvp/event.cc
|
|
@ -267,7 +267,18 @@ void vvp_fun_edge_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
{
|
||||
if (recv_vec4_(port, bit, bits_[port.port()], threads_)) {
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, bit, 0);
|
||||
net->send_vec4(bit, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void vvp_fun_edge_sa::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t)
|
||||
{
|
||||
assert(base == 0);
|
||||
if (recv_vec4_(port, bit, bits_[port.port()], threads_)) {
|
||||
vvp_net_t*net = port.ptr();
|
||||
net->send_vec4_pv(bit, base, wid, vwid, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -327,7 +338,7 @@ void vvp_fun_edge_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
|
||||
if (recv_vec4_(port, bit, state->bits[port.port()], state->threads)) {
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, bit, context);
|
||||
net->send_vec4(bit, context);
|
||||
}
|
||||
} else {
|
||||
context = context_scope_->live_contexts;
|
||||
|
|
@ -418,7 +429,25 @@ void vvp_fun_anyedge_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
{
|
||||
if (recv_vec4_(port, bit, bits_[port.port()], threads_)) {
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, bit, 0);
|
||||
net->send_vec4(bit, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void vvp_fun_anyedge_sa::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t)
|
||||
{
|
||||
vvp_vector4_t tmp = bits_[port.port()];
|
||||
if (tmp.size() == 0)
|
||||
tmp = vvp_vector4_t(vwid, BIT4_Z);
|
||||
assert(wid == bit.size());
|
||||
assert(base+wid <= vwid);
|
||||
assert(tmp.size() == vwid);
|
||||
tmp.set_vec(base, bit);
|
||||
|
||||
if (recv_vec4_(port, tmp, bits_[port.port()], threads_)) {
|
||||
vvp_net_t*net = port.ptr();
|
||||
net->send_vec4(bit, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -427,7 +456,7 @@ void vvp_fun_anyedge_sa::recv_real(vvp_net_ptr_t port, double bit,
|
|||
{
|
||||
if (recv_real_(port, bit, bitsr_[port.port()], threads_)) {
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, vvp_vector4_t(), 0);
|
||||
net->send_vec4(vvp_vector4_t(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -488,7 +517,7 @@ void vvp_fun_anyedge_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
|
||||
if (recv_vec4_(port, bit, state->bits[port.port()], state->threads)) {
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, bit, context);
|
||||
net->send_vec4(bit, context);
|
||||
}
|
||||
} else {
|
||||
context = context_scope_->live_contexts;
|
||||
|
|
@ -509,7 +538,7 @@ void vvp_fun_anyedge_aa::recv_real(vvp_net_ptr_t port, double bit,
|
|||
|
||||
if (recv_real_(port, bit, state->bitsr[port.port()], state->threads)) {
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, vvp_vector4_t(), context);
|
||||
net->send_vec4(vvp_vector4_t(), context);
|
||||
}
|
||||
} else {
|
||||
context = context_scope_->live_contexts;
|
||||
|
|
@ -551,7 +580,7 @@ void vvp_fun_event_or_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
{
|
||||
run_waiting_threads_(threads_);
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, bit, 0);
|
||||
net->send_vec4(bit, 0);
|
||||
}
|
||||
|
||||
vvp_fun_event_or_aa::vvp_fun_event_or_aa()
|
||||
|
|
@ -606,7 +635,7 @@ void vvp_fun_event_or_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
|
||||
run_waiting_threads_(state->threads);
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, bit, context);
|
||||
net->send_vec4(bit, context);
|
||||
} else {
|
||||
context = context_scope_->live_contexts;
|
||||
while (context) {
|
||||
|
|
@ -647,7 +676,7 @@ void vvp_named_event_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
{
|
||||
run_waiting_threads_(threads_);
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, bit, 0);
|
||||
net->send_vec4(bit, 0);
|
||||
|
||||
vpip_run_named_event_callbacks(handle_);
|
||||
}
|
||||
|
|
@ -705,7 +734,7 @@ void vvp_named_event_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
|
||||
run_waiting_threads_(state->threads);
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, bit, context);
|
||||
net->send_vec4(bit, context);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -182,6 +182,9 @@ class vvp_fun_edge_sa : public vvp_fun_edge {
|
|||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t context);
|
||||
|
||||
private:
|
||||
vthread_t threads_;
|
||||
|
|
@ -252,6 +255,9 @@ class vvp_fun_anyedge_sa : public vvp_fun_anyedge {
|
|||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t context);
|
||||
|
||||
void recv_real(vvp_net_ptr_t port, double bit,
|
||||
vvp_context_t context);
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ void vvp_fun_extend_signed::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bi
|
|||
vvp_context_t)
|
||||
{
|
||||
if (bit.size() >= width_) {
|
||||
vvp_send_vec4(port.ptr()->out, bit, 0);
|
||||
port.ptr()->send_vec4(bit, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -49,5 +49,5 @@ void vvp_fun_extend_signed::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bi
|
|||
for (unsigned idx = bit.size() ; idx < res.size() ; idx += 1)
|
||||
res.set_bit(idx, pad);
|
||||
|
||||
vvp_send_vec4(port.ptr()->out, res, 0);
|
||||
port.ptr()->send_vec4(res, 0);
|
||||
}
|
||||
|
|
|
|||
32
vvp/logic.cc
32
vvp/logic.cc
|
|
@ -108,7 +108,7 @@ void vvp_fun_and::run_run()
|
|||
result.set_bit(idx, bitbit);
|
||||
}
|
||||
|
||||
vvp_send_vec4(ptr->out, result, 0);
|
||||
ptr->send_vec4(result, 0);
|
||||
}
|
||||
|
||||
vvp_fun_buf::vvp_fun_buf()
|
||||
|
|
@ -149,7 +149,7 @@ void vvp_fun_buf::run_run()
|
|||
|
||||
vvp_vector4_t tmp (input_);
|
||||
tmp.change_z2x();
|
||||
vvp_send_vec4(ptr->out, tmp, 0);
|
||||
ptr->send_vec4(tmp, 0);
|
||||
}
|
||||
|
||||
vvp_fun_bufz::vvp_fun_bufz()
|
||||
|
|
@ -171,7 +171,7 @@ void vvp_fun_bufz::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|||
if (ptr.port() != 0)
|
||||
return;
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, bit, 0);
|
||||
ptr.ptr()->send_vec4(bit, 0);
|
||||
}
|
||||
|
||||
void vvp_fun_bufz::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
|
||||
|
|
@ -179,7 +179,7 @@ void vvp_fun_bufz::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
|
|||
if (ptr.port() != 0)
|
||||
return;
|
||||
|
||||
vvp_send_vec8(ptr.ptr()->out, bit);
|
||||
ptr.ptr()->send_vec8(bit);
|
||||
}
|
||||
|
||||
void vvp_fun_bufz::recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
|
|
@ -188,7 +188,7 @@ void vvp_fun_bufz::recv_real(vvp_net_ptr_t ptr, double bit,
|
|||
if (ptr.port() != 0)
|
||||
return;
|
||||
|
||||
vvp_send_real(ptr.ptr()->out, bit, 0);
|
||||
ptr.ptr()->send_real(bit, 0);
|
||||
}
|
||||
|
||||
vvp_fun_muxr::vvp_fun_muxr()
|
||||
|
|
@ -267,16 +267,16 @@ void vvp_fun_muxr::run_run()
|
|||
|
||||
switch (select_) {
|
||||
case SEL_PORT0:
|
||||
vvp_send_real(ptr->out, a_, 0);
|
||||
ptr->send_real(a_, 0);
|
||||
break;
|
||||
case SEL_PORT1:
|
||||
vvp_send_real(ptr->out, b_, 0);
|
||||
ptr->send_real(b_, 0);
|
||||
break;
|
||||
default:
|
||||
if (a_ == b_) {
|
||||
vvp_send_real(ptr->out, a_, 0);
|
||||
ptr->send_real(a_, 0);
|
||||
} else {
|
||||
vvp_send_real(ptr->out, 0.0, 0); // Should this be NaN?
|
||||
ptr->send_real(0.0, 0); // Should this be NaN?
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -347,10 +347,10 @@ void vvp_fun_muxz::run_run()
|
|||
|
||||
switch (select_) {
|
||||
case SEL_PORT0:
|
||||
vvp_send_vec4(ptr->out, a_, 0);
|
||||
ptr->send_vec4(a_, 0);
|
||||
break;
|
||||
case SEL_PORT1:
|
||||
vvp_send_vec4(ptr->out, b_, 0);
|
||||
ptr->send_vec4(b_, 0);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
|
|
@ -373,7 +373,7 @@ void vvp_fun_muxz::run_run()
|
|||
for (unsigned idx = min_size ; idx < max_size ; idx += 1)
|
||||
res.set_bit(idx, BIT4_X);
|
||||
|
||||
vvp_send_vec4(ptr->out, res, 0);
|
||||
ptr->send_vec4(res, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -421,7 +421,7 @@ void vvp_fun_not::run_run()
|
|||
result.set_bit(idx, bitbit);
|
||||
}
|
||||
|
||||
vvp_send_vec4(ptr->out, result, 0);
|
||||
ptr->send_vec4(result, 0);
|
||||
}
|
||||
|
||||
vvp_fun_or::vvp_fun_or(unsigned wid, bool invert)
|
||||
|
|
@ -457,7 +457,7 @@ void vvp_fun_or::run_run()
|
|||
result.set_bit(idx, bitbit);
|
||||
}
|
||||
|
||||
vvp_send_vec4(ptr->out, result, 0);
|
||||
ptr->send_vec4(result, 0);
|
||||
}
|
||||
|
||||
vvp_fun_xor::vvp_fun_xor(unsigned wid, bool invert)
|
||||
|
|
@ -493,7 +493,7 @@ void vvp_fun_xor::run_run()
|
|||
result.set_bit(idx, bitbit);
|
||||
}
|
||||
|
||||
vvp_send_vec4(ptr->out, result, 0);
|
||||
ptr->send_vec4(result, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -607,7 +607,7 @@ void compile_functor(char*label, char*type, unsigned width,
|
|||
net_drv->fun = obj_drv;
|
||||
|
||||
/* Point the gate to the drive node. */
|
||||
net->out = vvp_net_ptr_t(net_drv, 0);
|
||||
net->link(vvp_net_ptr_t(net_drv, 0));
|
||||
|
||||
define_functor_symbol(label, net_drv);
|
||||
free(label);
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ void vvp_fun_pmos_::generate_output_(vvp_net_ptr_t ptr)
|
|||
}
|
||||
|
||||
if (out.size() > 0)
|
||||
vvp_send_vec8(ptr.ptr()->out, out);
|
||||
ptr.ptr()->send_vec8(out);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -178,7 +178,7 @@ void vvp_fun_cmos_::generate_output_(vvp_net_ptr_t ptr)
|
|||
}
|
||||
|
||||
if (out.size() > 0)
|
||||
vvp_send_vec8(ptr.ptr()->out, out);
|
||||
ptr.ptr()->send_vec8(out);
|
||||
}
|
||||
|
||||
vvp_fun_cmos::vvp_fun_cmos()
|
||||
|
|
|
|||
13
vvp/part.cc
13
vvp/part.cc
|
|
@ -96,8 +96,7 @@ void vvp_fun_part_sa::run_run()
|
|||
{
|
||||
vvp_net_t*ptr = net_;
|
||||
net_ = 0;
|
||||
|
||||
vvp_send_vec4(ptr->out, val_, 0);
|
||||
ptr->send_vec4(val_, 0);
|
||||
}
|
||||
|
||||
vvp_fun_part_aa::vvp_fun_part_aa(unsigned base, unsigned wid)
|
||||
|
|
@ -149,7 +148,7 @@ void vvp_fun_part_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
}
|
||||
if (!val->eeq( tmp )) {
|
||||
*val = tmp;
|
||||
vvp_send_vec4(port.ptr()->out, tmp, context);
|
||||
port.ptr()->send_vec4(tmp, context);
|
||||
}
|
||||
} else {
|
||||
context = context_scope_->live_contexts;
|
||||
|
|
@ -211,7 +210,7 @@ void vvp_fun_part_pv::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
}
|
||||
assert(bit.size() == wid_);
|
||||
|
||||
vvp_send_vec4_pv(port.ptr()->out, bit, base_, wid_, vwid_, context);
|
||||
port.ptr()->send_vec4_pv(bit, base_, wid_, vwid_, context);
|
||||
}
|
||||
|
||||
void vvp_fun_part_pv::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
|
||||
|
|
@ -226,7 +225,7 @@ void vvp_fun_part_pv::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
|
|||
}
|
||||
assert(bit.size() == wid_);
|
||||
|
||||
vvp_send_vec8_pv(port.ptr()->out, bit, base_, wid_, vwid_);
|
||||
port.ptr()->send_vec8_pv(bit, base_, wid_, vwid_);
|
||||
}
|
||||
|
||||
vvp_fun_part_var::vvp_fun_part_var(unsigned w, bool is_signed)
|
||||
|
|
@ -291,7 +290,7 @@ void vvp_fun_part_var_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
vvp_context_t)
|
||||
{
|
||||
if (recv_vec4_(port, bit, base_, source_, ref_)) {
|
||||
vvp_send_vec4(port.ptr()->out, ref_, 0);
|
||||
port.ptr()->send_vec4(ref_, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -361,7 +360,7 @@ void vvp_fun_part_var_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
if (recv_vec4_(port, bit, state->base, state->source, state->ref)) {
|
||||
vvp_send_vec4(port.ptr()->out, state->ref, context);
|
||||
port.ptr()->send_vec4(state->ref, context);
|
||||
}
|
||||
} else {
|
||||
context = context_scope_->live_contexts;
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ void vvp_reduce_base::recv_vec4(vvp_net_ptr_t prt, const vvp_vector4_t&bit,
|
|||
bits_ = bit;
|
||||
vvp_bit4_t res = calculate_result();
|
||||
vvp_vector4_t rv (1, res);
|
||||
vvp_send_vec4(prt.ptr()->out, rv, context);
|
||||
prt.ptr()->send_vec4(rv, context);
|
||||
}
|
||||
|
||||
void vvp_reduce_base::recv_vec4_pv(vvp_net_ptr_t prt, const vvp_vector4_t&bit,
|
||||
|
|
@ -82,7 +82,7 @@ void vvp_reduce_base::recv_vec4_pv(vvp_net_ptr_t prt, const vvp_vector4_t&bit,
|
|||
bits_.set_vec(base, bit);
|
||||
vvp_bit4_t res = calculate_result();
|
||||
vvp_vector4_t rv (1, res);
|
||||
vvp_send_vec4(prt.ptr()->out, rv, context);
|
||||
prt.ptr()->send_vec4(rv, context);
|
||||
}
|
||||
|
||||
class vvp_reduce_and : public vvp_reduce_base {
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ void resolv_functor::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
|
|||
<< " in=" << val_[0] << ", " << val_[1]
|
||||
<< ", " << val_[2] << ", " << val_[3] << endl;
|
||||
|
||||
vvp_send_vec8(ptr->out, out);
|
||||
ptr->send_vec8(out);
|
||||
}
|
||||
|
||||
void resolv_functor::recv_vec8_pv(vvp_net_ptr_t port, const vvp_vector8_t&bit,
|
||||
|
|
@ -146,7 +146,7 @@ void resolv_wired_logic::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
out = wired_logic_math_(out, val_[idx]);
|
||||
}
|
||||
|
||||
vvp_send_vec4(ptr->out, out, 0);
|
||||
ptr->send_vec4(out, 0);
|
||||
}
|
||||
|
||||
vvp_vector4_t resolv_triand::wired_logic_math_(vvp_vector4_t&a, vvp_vector4_t&b)
|
||||
|
|
|
|||
|
|
@ -257,6 +257,27 @@ void assign_array_word_s::operator delete(void*ptr)
|
|||
|
||||
unsigned long count_assign_aword_pool(void) { return array_w_heap.pool; }
|
||||
|
||||
/*
|
||||
* This class supports the propagation of vec4 outputs from a
|
||||
* vvp_net_t object.
|
||||
*/
|
||||
struct propagate_vector4_event_s : public event_s {
|
||||
propagate_vector4_event_s(const vvp_vector4_t&that, unsigned adr, unsigned wid)
|
||||
: val(that,adr,wid) { }
|
||||
|
||||
/* Propagate the output of this net. */
|
||||
vvp_net_t*net;
|
||||
/* value to propagate */
|
||||
vvp_vector4_t val;
|
||||
/* Action */
|
||||
void run_run(void);
|
||||
};
|
||||
|
||||
void propagate_vector4_event_s::run_run(void)
|
||||
{
|
||||
net->send_vec4(val, 0);
|
||||
}
|
||||
|
||||
struct assign_array_r_word_s : public event_s {
|
||||
vvp_array_t mem;
|
||||
unsigned adr;
|
||||
|
|
@ -626,6 +647,17 @@ void schedule_assign_plucked_vector(vvp_net_ptr_t ptr,
|
|||
schedule_event_(cur, delay, SEQ_NBASSIGN);
|
||||
}
|
||||
|
||||
void schedule_propagate_plucked_vector(vvp_net_t*net,
|
||||
vvp_time64_t delay,
|
||||
const vvp_vector4_t&src,
|
||||
unsigned adr, unsigned wid)
|
||||
{
|
||||
struct propagate_vector4_event_s*cur
|
||||
= new struct propagate_vector4_event_s(src,adr,wid);
|
||||
cur->net = net;
|
||||
schedule_event_(cur, delay, SEQ_NBASSIGN);
|
||||
}
|
||||
|
||||
void schedule_assign_array_word(vvp_array_t mem,
|
||||
unsigned word_addr,
|
||||
unsigned off,
|
||||
|
|
@ -687,6 +719,15 @@ void schedule_init_vector(vvp_net_ptr_t ptr, vvp_vector4_t bit)
|
|||
schedule_init_list = cur;
|
||||
}
|
||||
|
||||
void schedule_init_vector(vvp_net_ptr_t ptr, vvp_vector8_t bit)
|
||||
{
|
||||
struct assign_vector8_event_s*cur = new struct assign_vector8_event_s;
|
||||
cur->ptr = ptr;
|
||||
cur->val = bit;
|
||||
cur->next = schedule_init_list;
|
||||
schedule_init_list = cur;
|
||||
}
|
||||
|
||||
void schedule_init_vector(vvp_net_ptr_t ptr, double bit)
|
||||
{
|
||||
struct assign_real_event_s*cur = new struct assign_real_event_s;
|
||||
|
|
|
|||
|
|
@ -62,6 +62,14 @@ extern void schedule_assign_array_word(vvp_array_t mem,
|
|||
unsigned word_address,
|
||||
double val,
|
||||
vvp_time64_t delay);
|
||||
/*
|
||||
* Create an event to propagate the output of a net.
|
||||
*/
|
||||
extern void schedule_propagate_plucked_vector(vvp_net_t*ptr,
|
||||
vvp_time64_t delay,
|
||||
const vvp_vector4_t&val,
|
||||
unsigned adr, unsigned wid);
|
||||
|
||||
/*
|
||||
* This is very similar to schedule_assign_vector, but generates an
|
||||
* event in the active queue. It is used at link time to assign a
|
||||
|
|
@ -83,6 +91,7 @@ extern void schedule_set_vector(vvp_net_ptr_t ptr, double val);
|
|||
* (propagated as events) through the rest of the net.
|
||||
*/
|
||||
extern void schedule_init_vector(vvp_net_ptr_t ptr, vvp_vector4_t val);
|
||||
extern void schedule_init_vector(vvp_net_ptr_t ptr, vvp_vector8_t val);
|
||||
extern void schedule_init_vector(vvp_net_ptr_t ptr, double val);
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -989,7 +989,7 @@ void compile_udp_functor(char*label, char*type,
|
|||
delete delay;
|
||||
net_drv->fun = obj_drv;
|
||||
|
||||
ptr->out = vvp_net_ptr_t(net_drv,0);
|
||||
ptr->link(vvp_net_ptr_t(net_drv,0));
|
||||
define_functor_symbol(label, net_drv);
|
||||
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
# include "symbols.h"
|
||||
# include "codes.h"
|
||||
# include "ufunc.h"
|
||||
# include "vvp_net_sig.h"
|
||||
# include "vthread.h"
|
||||
# include "schedule.h"
|
||||
#ifdef HAVE_MALLOC_H
|
||||
|
|
@ -83,11 +84,10 @@ void ufunc_core::finish_thread(vthread_t thr)
|
|||
{
|
||||
thread_ = 0;
|
||||
if (vvp_fun_signal_real*sig = dynamic_cast<vvp_fun_signal_real*>(result_->fun))
|
||||
|
||||
propagate_real(sig->real_value());
|
||||
propagate_real(sig->real_unfiltered_value());
|
||||
|
||||
if (vvp_fun_signal_vec*sig = dynamic_cast<vvp_fun_signal_vec*>(result_->fun))
|
||||
propagate_vec4(sig->vec4_value());
|
||||
propagate_vec4(sig->vec4_unfiltered_value());
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
# include "vvp_net.h"
|
||||
# include "schedule.h"
|
||||
# include "event.h"
|
||||
# include "vvp_net_sig.h"
|
||||
# include "config.h"
|
||||
# include <stdio.h>
|
||||
# include <assert.h>
|
||||
|
|
@ -156,12 +157,12 @@ static struct __vpiCallback* make_value_change(p_cb_data data)
|
|||
struct __vpiSignal*sig;
|
||||
sig = reinterpret_cast<__vpiSignal*>(data->obj);
|
||||
|
||||
vvp_fun_signal_base*sig_fun;
|
||||
sig_fun = dynamic_cast<vvp_fun_signal_base*>(sig->node->fun);
|
||||
assert(sig_fun);
|
||||
vvp_net_fil_t*sig_fil;
|
||||
sig_fil = dynamic_cast<vvp_net_fil_t*>(sig->node->fil);
|
||||
assert(sig_fil);
|
||||
|
||||
/* Attach the __vpiCallback object to the signal. */
|
||||
sig_fun->add_vpi_callback(obj);
|
||||
sig_fil->add_vpi_callback(obj);
|
||||
break;
|
||||
|
||||
case vpiRealVar:
|
||||
|
|
@ -503,11 +504,21 @@ void callback_execute(struct __vpiCallback*cur)
|
|||
vvp_vpi_callback::vvp_vpi_callback()
|
||||
{
|
||||
vpi_callbacks_ = 0;
|
||||
array_ = 0;
|
||||
array_word_ = 0;
|
||||
}
|
||||
|
||||
vvp_vpi_callback::~vvp_vpi_callback()
|
||||
{
|
||||
assert(vpi_callbacks_ == 0);
|
||||
assert(array_ == 0);
|
||||
}
|
||||
|
||||
void vvp_vpi_callback::attach_as_word(vvp_array_t arr, unsigned long addr)
|
||||
{
|
||||
assert(array_ == 0);
|
||||
array_ = arr;
|
||||
array_word_ = addr;
|
||||
}
|
||||
|
||||
void vvp_vpi_callback::add_vpi_callback(__vpiCallback*cb)
|
||||
|
|
@ -535,6 +546,8 @@ void vvp_vpi_callback::clear_all_callbacks()
|
|||
*/
|
||||
void vvp_vpi_callback::run_vpi_callbacks()
|
||||
{
|
||||
if (array_) array_word_change(array_, array_word_);
|
||||
|
||||
struct __vpiCallback *next = vpi_callbacks_;
|
||||
struct __vpiCallback *prev = 0;
|
||||
|
||||
|
|
@ -564,32 +577,7 @@ void vvp_vpi_callback::run_vpi_callbacks()
|
|||
}
|
||||
}
|
||||
|
||||
vvp_vpi_callback_wordable::vvp_vpi_callback_wordable()
|
||||
{
|
||||
array_ = 0;
|
||||
array_word_ = 0;
|
||||
}
|
||||
|
||||
vvp_vpi_callback_wordable::~vvp_vpi_callback_wordable()
|
||||
{
|
||||
assert(array_ == 0);
|
||||
}
|
||||
|
||||
void vvp_vpi_callback_wordable::run_vpi_callbacks()
|
||||
{
|
||||
if (array_) array_word_change(array_, array_word_);
|
||||
|
||||
vvp_vpi_callback::run_vpi_callbacks();
|
||||
}
|
||||
|
||||
void vvp_vpi_callback_wordable::attach_as_word(vvp_array_t arr, unsigned long addr)
|
||||
{
|
||||
assert(array_ == 0);
|
||||
array_ = arr;
|
||||
array_word_ = addr;
|
||||
}
|
||||
|
||||
void vvp_fun_signal4::get_value(struct t_vpi_value*vp)
|
||||
void vvp_signal_value::get_signal_value(struct t_vpi_value*vp)
|
||||
{
|
||||
switch (vp->format) {
|
||||
case vpiScalarVal:
|
||||
|
|
@ -607,7 +595,7 @@ void vvp_fun_signal4::get_value(struct t_vpi_value*vp)
|
|||
case vpiVectorVal:
|
||||
case vpiStringVal:
|
||||
case vpiRealVal: {
|
||||
unsigned wid = size();
|
||||
unsigned wid = value_size();
|
||||
vvp_vector4_t vec4(wid);
|
||||
for (unsigned idx = 0; idx < wid; idx += 1) {
|
||||
vec4.set_bit(idx, value(idx));
|
||||
|
|
@ -626,22 +614,7 @@ void vvp_fun_signal4::get_value(struct t_vpi_value*vp)
|
|||
}
|
||||
}
|
||||
|
||||
void vvp_fun_signal8::get_value(struct t_vpi_value*vp)
|
||||
{
|
||||
switch (vp->format) {
|
||||
case vpiScalarVal:
|
||||
vp->value.scalar = value(0);
|
||||
break;
|
||||
case vpiSuppressVal:
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "vpi_callback: value "
|
||||
"format %d not supported (fun_signal8)\n",
|
||||
vp->format);
|
||||
}
|
||||
}
|
||||
|
||||
void vvp_fun_signal_real::get_value(struct t_vpi_value*vp)
|
||||
static void real_signal_value(struct t_vpi_value*vp, double rval)
|
||||
{
|
||||
char*rbuf = need_result_buf(64 + 1, RBUF_VAL);
|
||||
|
||||
|
|
@ -650,25 +623,25 @@ void vvp_fun_signal_real::get_value(struct t_vpi_value*vp)
|
|||
vp->format = vpiRealVal;
|
||||
|
||||
case vpiRealVal:
|
||||
vp->value.real = real_value();
|
||||
vp->value.real = rval;
|
||||
break;
|
||||
|
||||
case vpiIntVal:
|
||||
vp->value.integer = (int)(real_value() + 0.5);
|
||||
vp->value.integer = (int)(rval + 0.5);
|
||||
break;
|
||||
|
||||
case vpiDecStrVal:
|
||||
sprintf(rbuf, "%0.0f", real_value());
|
||||
sprintf(rbuf, "%0.0f", rval);
|
||||
vp->value.str = rbuf;
|
||||
break;
|
||||
|
||||
case vpiHexStrVal:
|
||||
sprintf(rbuf, "%lx", (long)real_value());
|
||||
sprintf(rbuf, "%lx", (long)rval);
|
||||
vp->value.str = rbuf;
|
||||
break;
|
||||
|
||||
case vpiBinStrVal: {
|
||||
unsigned long val = (unsigned long)real_value();
|
||||
unsigned long val = (unsigned long)rval;
|
||||
unsigned len = 0;
|
||||
|
||||
while (val > 0) {
|
||||
|
|
@ -676,7 +649,7 @@ void vvp_fun_signal_real::get_value(struct t_vpi_value*vp)
|
|||
val /= 2;
|
||||
}
|
||||
|
||||
val = (unsigned long)real_value();
|
||||
val = (unsigned long)rval;
|
||||
for (unsigned idx = 0 ; idx < len ; idx += 1) {
|
||||
rbuf[len-idx-1] = (val & 1)? '1' : '0';
|
||||
val /= 2;
|
||||
|
|
@ -700,3 +673,28 @@ void vvp_fun_signal_real::get_value(struct t_vpi_value*vp)
|
|||
vp->format);
|
||||
}
|
||||
}
|
||||
|
||||
void vvp_fun_signal_real_aa::get_signal_value(struct t_vpi_value*vp)
|
||||
{
|
||||
real_signal_value(vp, real_value());
|
||||
}
|
||||
|
||||
void vvp_wire_real::get_signal_value(struct t_vpi_value*vp)
|
||||
{
|
||||
real_signal_value(vp, real_value());
|
||||
}
|
||||
|
||||
void vvp_wire_vec4::get_value(struct t_vpi_value*value)
|
||||
{
|
||||
get_signal_value(value);
|
||||
}
|
||||
|
||||
void vvp_wire_vec8::get_value(struct t_vpi_value*value)
|
||||
{
|
||||
get_signal_value(value);
|
||||
}
|
||||
|
||||
void vvp_wire_real::get_value(struct t_vpi_value*value)
|
||||
{
|
||||
get_signal_value(value);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
# include "compile.h"
|
||||
# include "vpi_priv.h"
|
||||
# include "vvp_net_sig.h"
|
||||
# include "schedule.h"
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
|
|
@ -131,10 +132,10 @@ static void real_var_get_value(vpiHandle ref, s_vpi_value*vp)
|
|||
|
||||
struct __vpiRealVar*rfp
|
||||
= (struct __vpiRealVar*)ref;
|
||||
vvp_fun_signal_real*fun
|
||||
= dynamic_cast<vvp_fun_signal_real*>(rfp->net->fun);
|
||||
vvp_signal_value*fil
|
||||
= dynamic_cast<vvp_signal_value*>(rfp->net->fil);
|
||||
|
||||
fun->get_value(vp);
|
||||
fil->get_signal_value(vp);
|
||||
}
|
||||
|
||||
static vpiHandle real_var_put_value(vpiHandle ref, p_vpi_value vp, int)
|
||||
|
|
@ -170,10 +171,10 @@ void vpip_real_value_change(struct __vpiCallback*cbh,
|
|||
{
|
||||
struct __vpiRealVar*rfp
|
||||
= (struct __vpiRealVar*)ref;
|
||||
vvp_fun_signal_real*fun
|
||||
= dynamic_cast<vvp_fun_signal_real*>(rfp->net->fun);
|
||||
vvp_vpi_callback*obj = dynamic_cast<vvp_vpi_callback*>(rfp->net->fil);
|
||||
assert(obj);
|
||||
|
||||
fun->add_vpi_callback(cbh);
|
||||
obj->add_vpi_callback(cbh);
|
||||
}
|
||||
|
||||
vpiHandle vpip_make_real_var(const char*name, vvp_net_t*net)
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
# include "compile.h"
|
||||
# include "vpi_priv.h"
|
||||
# include "vvp_net_sig.h"
|
||||
# include "schedule.h"
|
||||
# include "statistics.h"
|
||||
# include "config.h"
|
||||
|
|
@ -134,13 +135,13 @@ char *generic_get_str(int code, vpiHandle ref, const char *name, const char *ind
|
|||
* They work with full or partial signals.
|
||||
*/
|
||||
|
||||
static void format_vpiBinStrVal(vvp_fun_signal_vec*sig, int base, unsigned wid,
|
||||
static void format_vpiBinStrVal(vvp_signal_value*sig, int base, unsigned wid,
|
||||
s_vpi_value*vp)
|
||||
{
|
||||
char *rbuf = need_result_buf(wid+1, RBUF_VAL);
|
||||
long end = base + (signed)wid;
|
||||
long offset = end - 1;
|
||||
long ssize = (signed)sig->size();
|
||||
long ssize = (signed)sig->value_size();
|
||||
|
||||
for (long idx = base ; idx < end ; idx += 1) {
|
||||
if (idx < 0 || idx >= ssize) {
|
||||
|
|
@ -154,13 +155,13 @@ static void format_vpiBinStrVal(vvp_fun_signal_vec*sig, int base, unsigned wid,
|
|||
vp->value.str = rbuf;
|
||||
}
|
||||
|
||||
static void format_vpiOctStrVal(vvp_fun_signal_vec*sig, int base, unsigned wid,
|
||||
static void format_vpiOctStrVal(vvp_signal_value*sig, int base, unsigned wid,
|
||||
s_vpi_value*vp)
|
||||
{
|
||||
unsigned dwid = (wid + 2) / 3;
|
||||
char *rbuf = need_result_buf(dwid+1, RBUF_VAL);
|
||||
long end = base + (signed)wid;
|
||||
long ssize = (signed)sig->size();
|
||||
long ssize = (signed)sig->value_size();
|
||||
unsigned val = 0;
|
||||
|
||||
rbuf[dwid] = 0;
|
||||
|
|
@ -210,13 +211,13 @@ static void format_vpiOctStrVal(vvp_fun_signal_vec*sig, int base, unsigned wid,
|
|||
vp->value.str = rbuf;
|
||||
}
|
||||
|
||||
static void format_vpiHexStrVal(vvp_fun_signal_vec*sig, int base, unsigned wid,
|
||||
static void format_vpiHexStrVal(vvp_signal_value*sig, int base, unsigned wid,
|
||||
s_vpi_value*vp)
|
||||
{
|
||||
unsigned dwid = (wid + 3) / 4;
|
||||
char *rbuf = need_result_buf(dwid+1, RBUF_VAL);
|
||||
long end = base + (signed)wid;
|
||||
long ssize = (signed)sig->size();
|
||||
long ssize = (signed)sig->value_size();
|
||||
unsigned val = 0;
|
||||
|
||||
rbuf[dwid] = 0;
|
||||
|
|
@ -270,12 +271,12 @@ static void format_vpiHexStrVal(vvp_fun_signal_vec*sig, int base, unsigned wid,
|
|||
vp->value.str = rbuf;
|
||||
}
|
||||
|
||||
static void format_vpiDecStrVal(vvp_fun_signal_vec*sig, int base, unsigned wid,
|
||||
static void format_vpiDecStrVal(vvp_signal_value*sig, int base, unsigned wid,
|
||||
int signed_flag, s_vpi_value*vp)
|
||||
{
|
||||
unsigned hwid = (sig->size()+2) / 3 + 1;
|
||||
unsigned hwid = (sig->value_size()+2) / 3 + 1;
|
||||
char *rbuf = need_result_buf(hwid, RBUF_VAL);
|
||||
long ssize = (signed)sig->size();
|
||||
long ssize = (signed)sig->value_size();
|
||||
long end = base + (signed)wid;
|
||||
|
||||
/* Do we have an end outside of the real signal vector. */
|
||||
|
|
@ -313,7 +314,7 @@ static void format_vpiDecStrVal(vvp_fun_signal_vec*sig, int base, unsigned wid,
|
|||
vp->value.str = rbuf;
|
||||
}
|
||||
|
||||
static void format_vpiIntVal(vvp_fun_signal_vec*sig, int base, unsigned wid,
|
||||
static void format_vpiIntVal(vvp_signal_value*sig, int base, unsigned wid,
|
||||
int signed_flag, s_vpi_value*vp)
|
||||
{
|
||||
vvp_vector4_t sub = sig->vec4_value().subvalue(base, wid);
|
||||
|
|
@ -322,11 +323,11 @@ static void format_vpiIntVal(vvp_fun_signal_vec*sig, int base, unsigned wid,
|
|||
vp->value.integer = val;
|
||||
}
|
||||
|
||||
static void format_vpiRealVal(vvp_fun_signal_vec*sig, int base, unsigned wid,
|
||||
static void format_vpiRealVal(vvp_signal_value*sig, int base, unsigned wid,
|
||||
int signed_flag, s_vpi_value*vp)
|
||||
{
|
||||
vvp_vector4_t vec4(wid);
|
||||
long ssize = (signed)sig->size();
|
||||
long ssize = (signed)sig->value_size();
|
||||
long end = base + (signed)wid;
|
||||
if (end > ssize) end = ssize;
|
||||
|
||||
|
|
@ -338,7 +339,7 @@ static void format_vpiRealVal(vvp_fun_signal_vec*sig, int base, unsigned wid,
|
|||
vector4_to_value(vec4, vp->value.real, signed_flag);
|
||||
}
|
||||
|
||||
static void format_vpiStringVal(vvp_fun_signal_vec*sig, int base, unsigned wid,
|
||||
static void format_vpiStringVal(vvp_signal_value*sig, int base, unsigned wid,
|
||||
s_vpi_value*vp)
|
||||
{
|
||||
/* The result will use a character for each 8 bits of the
|
||||
|
|
@ -351,7 +352,7 @@ static void format_vpiStringVal(vvp_fun_signal_vec*sig, int base, unsigned wid,
|
|||
for (long idx = base+(signed)wid-1; idx >= base; idx -= 1) {
|
||||
tmp <<= 1;
|
||||
|
||||
if (idx >=0 && idx < (signed)sig->size() &&
|
||||
if (idx >=0 && idx < (signed)sig->value_size() &&
|
||||
sig->value(idx) == BIT4_1) {
|
||||
tmp |= 1;
|
||||
}
|
||||
|
|
@ -371,10 +372,10 @@ static void format_vpiStringVal(vvp_fun_signal_vec*sig, int base, unsigned wid,
|
|||
vp->value.str = rbuf;
|
||||
}
|
||||
|
||||
static void format_vpiScalarVal(vvp_fun_signal_vec*sig, int base,
|
||||
static void format_vpiScalarVal(vvp_signal_value*sig, int base,
|
||||
s_vpi_value*vp)
|
||||
{
|
||||
if (base >= 0 && base < (signed)sig->size()) {
|
||||
if (base >= 0 && base < (signed)sig->value_size()) {
|
||||
switch (sig->value(base)) {
|
||||
case BIT4_0:
|
||||
vp->value.scalar = vpi0;
|
||||
|
|
@ -398,7 +399,7 @@ static void format_vpiScalarVal(vvp_fun_signal_vec*sig, int base,
|
|||
}
|
||||
}
|
||||
|
||||
static void format_vpiStrengthVal(vvp_fun_signal_vec*sig, int base,
|
||||
static void format_vpiStrengthVal(vvp_signal_value*sig, int base,
|
||||
unsigned wid, s_vpi_value*vp)
|
||||
{
|
||||
long end = base + (signed)wid;
|
||||
|
|
@ -408,7 +409,7 @@ static void format_vpiStrengthVal(vvp_fun_signal_vec*sig, int base,
|
|||
need_result_buf(wid * sizeof(s_vpi_strengthval), RBUF_VAL);
|
||||
|
||||
for (long idx = base ; idx < end ; idx += 1) {
|
||||
if (idx >=0 && idx < (signed)sig->size()) {
|
||||
if (idx >=0 && idx < (signed)sig->value_size()) {
|
||||
vvp_scalar_t val = sig->scalar_value(idx);
|
||||
|
||||
/* vvp_scalar_t strengths are 0-7, but the vpi strength
|
||||
|
|
@ -452,7 +453,7 @@ static void format_vpiStrengthVal(vvp_fun_signal_vec*sig, int base,
|
|||
vp->value.strength = op;
|
||||
}
|
||||
|
||||
static void format_vpiVectorVal(vvp_fun_signal_vec*sig, int base, unsigned wid,
|
||||
static void format_vpiVectorVal(vvp_signal_value*sig, int base, unsigned wid,
|
||||
s_vpi_value*vp)
|
||||
{
|
||||
long end = base + (signed)wid;
|
||||
|
|
@ -465,7 +466,7 @@ static void format_vpiVectorVal(vvp_fun_signal_vec*sig, int base, unsigned wid,
|
|||
|
||||
op->aval = op->bval = 0;
|
||||
for (long idx = base ; idx < end ; idx += 1) {
|
||||
if (base >= 0 && base < (signed)sig->size()) {
|
||||
if (base >= 0 && base < (signed)sig->value_size()) {
|
||||
switch (sig->value(idx)) {
|
||||
case BIT4_0:
|
||||
op->aval &= ~(1 << obit);
|
||||
|
|
@ -659,7 +660,7 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
|
|||
|
||||
unsigned wid = signal_width(rfp);
|
||||
|
||||
vvp_fun_signal_vec*vsig = dynamic_cast<vvp_fun_signal_vec*>(rfp->node->fun);
|
||||
vvp_signal_value*vsig = dynamic_cast<vvp_signal_value*>(rfp->node->fil);
|
||||
assert(vsig);
|
||||
|
||||
switch (vp->format) {
|
||||
|
|
@ -757,9 +758,12 @@ static vpiHandle signal_put_value(vpiHandle ref, s_vpi_value*vp, int flags)
|
|||
value. Instead, issue a release "command" to the signal
|
||||
node to cause it to release a forced value. */
|
||||
if (flags == vpiReleaseFlag) {
|
||||
vvp_net_ptr_t dest_cmd(rfp->node, 3);
|
||||
/* Assume this is a net. (XXXX Are we sure?) */
|
||||
vvp_send_long(dest_cmd, 2 /* release/net */);
|
||||
vvp_net_fil_t*sig
|
||||
= reinterpret_cast<vvp_net_fil_t*>(rfp->node->fil);
|
||||
assert(sig);
|
||||
|
||||
vvp_net_ptr_t ptr(rfp->node, 0);
|
||||
sig->release(ptr, false);
|
||||
return ref;
|
||||
}
|
||||
|
||||
|
|
@ -1111,7 +1115,7 @@ static void PV_get_value(vpiHandle ref, p_vpi_value vp)
|
|||
assert(ref->vpi_type->type_code == vpiPartSelect);
|
||||
struct __vpiPV*rfp = (struct __vpiPV*)ref;
|
||||
|
||||
vvp_fun_signal_vec*sig = dynamic_cast<vvp_fun_signal_vec*>(rfp->net->fun);
|
||||
vvp_signal_value*sig = dynamic_cast<vvp_signal_value*>(rfp->net->fil);
|
||||
assert(sig);
|
||||
|
||||
switch (vp->format) {
|
||||
|
|
@ -1168,10 +1172,10 @@ static vpiHandle PV_put_value(vpiHandle ref, p_vpi_value vp, int)
|
|||
{
|
||||
assert(ref->vpi_type->type_code == vpiPartSelect);
|
||||
struct __vpiPV*rfp = (struct __vpiPV*)ref;
|
||||
vvp_fun_signal_vec*sig = dynamic_cast<vvp_fun_signal_vec*>(rfp->net->fun);
|
||||
vvp_signal_value*sig = dynamic_cast<vvp_signal_value*>(rfp->net->fil);
|
||||
assert(sig);
|
||||
|
||||
unsigned sig_size = sig->size();
|
||||
unsigned sig_size = sig->value_size();
|
||||
unsigned width = rfp->width;
|
||||
int base = PV_get_base(rfp);
|
||||
if (base >= (signed) sig_size) return 0;
|
||||
|
|
@ -1314,12 +1318,12 @@ void vpip_part_select_value_change(struct __vpiCallback*cbh, vpiHandle ref)
|
|||
struct __vpiPV*obj = vpip_PV_from_handle(ref);
|
||||
assert(obj);
|
||||
|
||||
vvp_fun_signal_base*sig_fun;
|
||||
sig_fun = dynamic_cast<vvp_fun_signal_base*>(obj->net->fun);
|
||||
assert(sig_fun);
|
||||
vvp_vpi_callback*sig_fil;
|
||||
sig_fil = dynamic_cast<vvp_vpi_callback*>(obj->net->fil);
|
||||
assert(sig_fil);
|
||||
|
||||
/* Attach the __vpiCallback object to the signal. */
|
||||
sig_fun->add_vpi_callback(cbh);
|
||||
sig_fil->add_vpi_callback(cbh);
|
||||
}
|
||||
|
||||
#ifdef CHECK_WITH_VALGRIND
|
||||
|
|
|
|||
|
|
@ -426,7 +426,7 @@ static vpiHandle sysfunc_put_4net_value(vpiHandle ref, p_vpi_value vp, int)
|
|||
assert(0);
|
||||
}
|
||||
|
||||
vvp_send_vec4(rfp->fnet->out, val, vthread_get_wt_context());
|
||||
rfp->fnet->send_vec4(val, vthread_get_wt_context());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -450,7 +450,7 @@ static vpiHandle sysfunc_put_rnet_value(vpiHandle ref, p_vpi_value vp, int)
|
|||
assert(0);
|
||||
}
|
||||
|
||||
vvp_send_real(rfp->fnet->out, val, vthread_get_wt_context());
|
||||
rfp->fnet->send_real(val, vthread_get_wt_context());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
330
vvp/vthread.cc
330
vvp/vthread.cc
|
|
@ -24,6 +24,7 @@
|
|||
# include "ufunc.h"
|
||||
# include "event.h"
|
||||
# include "vpi_priv.h"
|
||||
# include "vvp_net_sig.h"
|
||||
#ifdef CHECK_WITH_VALGRIND
|
||||
# include "vvp_cleanup.h"
|
||||
#endif
|
||||
|
|
@ -178,6 +179,19 @@ void vthread_put_real(struct vthread_s*thr, unsigned addr, double val)
|
|||
thr->words[addr].w_real = val;
|
||||
}
|
||||
|
||||
template <class T> T coerce_to_width(const T&that, unsigned width)
|
||||
{
|
||||
if (that.size() == width)
|
||||
return that;
|
||||
|
||||
assert(that.size() > width);
|
||||
T res (width);
|
||||
for (unsigned idx = 0 ; idx < width ; idx += 1)
|
||||
res.set_bit(idx, that.value(idx));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static unsigned long* vector_to_array(struct vthread_s*thr,
|
||||
unsigned addr, unsigned wid)
|
||||
{
|
||||
|
|
@ -550,41 +564,6 @@ void vthread_run(vthread_t thr)
|
|||
running_thread = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unlink a ptr object from the driver. The input is the driver in the
|
||||
* form of a vvp_net_t pointer. The .out member of that object is the
|
||||
* driver. The dst_ptr argument is the receiver pin to be located and
|
||||
* removed from the fan-out list.
|
||||
*/
|
||||
static void unlink_from_driver(vvp_net_t*src, vvp_net_ptr_t dst_ptr)
|
||||
{
|
||||
vvp_net_t*net = dst_ptr.ptr();
|
||||
unsigned net_port = dst_ptr.port();
|
||||
|
||||
if (src->out == dst_ptr) {
|
||||
/* If the drive fan-out list starts with this pointer,
|
||||
then the unlink is easy. Pull the list forward. */
|
||||
src->out = net->port[net_port];
|
||||
} else {
|
||||
/* Scan the linked list, looking for the net_ptr_t
|
||||
pointer *before* the one we wish to remove. */
|
||||
vvp_net_ptr_t cur = src->out;
|
||||
assert(!cur.nil());
|
||||
vvp_net_t*cur_net = cur.ptr();
|
||||
unsigned cur_port = cur.port();
|
||||
while (cur_net->port[cur_port] != dst_ptr) {
|
||||
cur = cur_net->port[cur_port];
|
||||
assert(!cur.nil());
|
||||
cur_net = cur.ptr();
|
||||
cur_port = cur.port();
|
||||
}
|
||||
/* Unlink. */
|
||||
cur_net->port[cur_port] = net->port[net_port];
|
||||
}
|
||||
|
||||
net->port[net_port] = vvp_net_ptr_t(0,0);
|
||||
}
|
||||
|
||||
/*
|
||||
* The CHUNK_LINK instruction is a special next pointer for linking
|
||||
* chunks of code space. It's like a simplified %jmp.
|
||||
|
|
@ -1078,12 +1057,11 @@ bool of_ASSIGN_V0X1(vthread_t thr, vvp_code_t cp)
|
|||
unsigned delay = cp->bit_idx[0];
|
||||
unsigned bit = cp->bit_idx[1];
|
||||
|
||||
vvp_fun_signal_vec*sig
|
||||
= reinterpret_cast<vvp_fun_signal_vec*> (cp->net->fun);
|
||||
vvp_signal_value*sig = dynamic_cast<vvp_signal_value*> (cp->net->fil);
|
||||
assert(sig);
|
||||
|
||||
// We fell off the MSB end.
|
||||
if (off >= (long)sig->size()) return true;
|
||||
if (off >= (long)sig->value_size()) return true;
|
||||
else if (off < 0 ) {
|
||||
// We fell off the LSB end.
|
||||
if ((unsigned)-off >= wid ) return true;
|
||||
|
|
@ -1098,7 +1076,7 @@ bool of_ASSIGN_V0X1(vthread_t thr, vvp_code_t cp)
|
|||
vvp_vector4_t value = vthread_bits_to_vector(thr, bit, wid);
|
||||
|
||||
vvp_net_ptr_t ptr (cp->net, 0);
|
||||
schedule_assign_vector(ptr, off, sig->size(), value, delay);
|
||||
schedule_assign_vector(ptr, off, sig->value_size(), value, delay);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1115,12 +1093,11 @@ bool of_ASSIGN_V0X1D(vthread_t thr, vvp_code_t cp)
|
|||
vvp_time64_t delay = thr->words[cp->bit_idx[0]].w_int;
|
||||
unsigned bit = cp->bit_idx[1];
|
||||
|
||||
vvp_fun_signal_vec*sig
|
||||
= reinterpret_cast<vvp_fun_signal_vec*> (cp->net->fun);
|
||||
vvp_signal_value*sig = dynamic_cast<vvp_signal_value*> (cp->net->fil);
|
||||
assert(sig);
|
||||
|
||||
// We fell off the MSB end.
|
||||
if (off >= (long)sig->size()) return true;
|
||||
if (off >= (long)sig->value_size()) return true;
|
||||
else if (off < 0 ) {
|
||||
// We fell off the LSB end.
|
||||
if ((unsigned)-off >= wid ) return true;
|
||||
|
|
@ -1135,7 +1112,7 @@ bool of_ASSIGN_V0X1D(vthread_t thr, vvp_code_t cp)
|
|||
vvp_vector4_t value = vthread_bits_to_vector(thr, bit, wid);
|
||||
|
||||
vvp_net_ptr_t ptr (cp->net, 0);
|
||||
schedule_assign_vector(ptr, off, sig->size(), value, delay);
|
||||
schedule_assign_vector(ptr, off, sig->value_size(), value, delay);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1151,12 +1128,11 @@ bool of_ASSIGN_V0X1E(vthread_t thr, vvp_code_t cp)
|
|||
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);
|
||||
vvp_signal_value*sig = dynamic_cast<vvp_signal_value*> (cp->net->fil);
|
||||
assert(sig);
|
||||
|
||||
// We fell off the MSB end.
|
||||
if (off >= (long)sig->size()) {
|
||||
if (off >= (long)sig->value_size()) {
|
||||
thr->event = 0;
|
||||
thr->ecount = 0;
|
||||
return true;
|
||||
|
|
@ -1180,9 +1156,9 @@ bool of_ASSIGN_V0X1E(vthread_t thr, vvp_code_t cp)
|
|||
vvp_net_ptr_t ptr (cp->net, 0);
|
||||
// If the count is zero then just put the value.
|
||||
if (thr->ecount == 0) {
|
||||
schedule_assign_vector(ptr, off, sig->size(), value, 0);
|
||||
schedule_assign_vector(ptr, off, sig->value_size(), value, 0);
|
||||
} else {
|
||||
schedule_evctl(ptr, value, off, sig->size(), thr->event,
|
||||
schedule_evctl(ptr, value, off, sig->value_size(), thr->event,
|
||||
thr->ecount);
|
||||
}
|
||||
|
||||
|
|
@ -1321,7 +1297,7 @@ bool of_CASSIGN_LINK(vthread_t thr, vvp_code_t cp)
|
|||
vvp_net_t*src = cp->net2;
|
||||
|
||||
vvp_fun_signal_base*sig
|
||||
= reinterpret_cast<vvp_fun_signal_base*>(dst->fun);
|
||||
= dynamic_cast<vvp_fun_signal_base*>(dst->fun);
|
||||
assert(sig);
|
||||
|
||||
/* Detect the special case that we are already continuous
|
||||
|
|
@ -1333,7 +1309,7 @@ bool of_CASSIGN_LINK(vthread_t thr, vvp_code_t cp)
|
|||
unlink it. We can have only 1 cassign at a time. */
|
||||
if (sig->cassign_link != 0) {
|
||||
vvp_net_ptr_t tmp (dst, 1);
|
||||
unlink_from_driver(sig->cassign_link, tmp);
|
||||
sig->cassign_link->unlink(tmp);
|
||||
}
|
||||
|
||||
sig->cassign_link = src;
|
||||
|
|
@ -1341,8 +1317,7 @@ bool of_CASSIGN_LINK(vthread_t thr, vvp_code_t cp)
|
|||
/* Link the output of the src to the port[1] (the cassign
|
||||
port) of the destination. */
|
||||
vvp_net_ptr_t dst_ptr (dst, 1);
|
||||
dst->port[1] = src->out;
|
||||
src->out = dst_ptr;
|
||||
src->link(dst_ptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1397,12 +1372,12 @@ bool of_CASSIGN_X0(vthread_t thr, vvp_code_t cp)
|
|||
// X0 register.
|
||||
long index = thr->words[0].w_int;
|
||||
|
||||
vvp_fun_signal_vec*sig = dynamic_cast<vvp_fun_signal_vec*> (net->fun);
|
||||
vvp_signal_value*sig = dynamic_cast<vvp_signal_value*> (net->fil);
|
||||
|
||||
if (index < 0 && (wid <= (unsigned)-index))
|
||||
return true;
|
||||
|
||||
if (index >= (long)sig->size())
|
||||
if (index >= (long)sig->value_size())
|
||||
return true;
|
||||
|
||||
if (index < 0) {
|
||||
|
|
@ -1410,13 +1385,13 @@ bool of_CASSIGN_X0(vthread_t thr, vvp_code_t cp)
|
|||
index = 0;
|
||||
}
|
||||
|
||||
if (index+wid > sig->size())
|
||||
wid = sig->size() - index;
|
||||
if (index+wid > sig->value_size())
|
||||
wid = sig->value_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(), 0);
|
||||
vvp_send_vec4_pv(ptr, vector, index, wid, sig->value_size(), 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1828,13 +1803,15 @@ bool of_DEASSIGN(vthread_t thr, vvp_code_t cp)
|
|||
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);
|
||||
vvp_signal_value*fil = dynamic_cast<vvp_signal_value*> (net->fil);
|
||||
assert(fil);
|
||||
vvp_fun_signal_vec*sig = dynamic_cast<vvp_fun_signal_vec*>(net->fun);
|
||||
assert(sig);
|
||||
|
||||
if (base >= sig->size()) return true;
|
||||
if (base+width > sig->size()) width = sig->size() - base;
|
||||
if (base >= fil->value_size()) return true;
|
||||
if (base+width > fil->value_size()) width = fil->value_size() - base;
|
||||
|
||||
bool full_sig = base == 0 && width == sig->size();
|
||||
bool full_sig = base == 0 && width == fil->value_size();
|
||||
|
||||
// This is the net that is forcing me...
|
||||
if (vvp_net_t*src = sig->cassign_link) {
|
||||
|
|
@ -1845,16 +1822,15 @@ bool of_DEASSIGN(vthread_t thr, vvp_code_t cp)
|
|||
}
|
||||
// And this is the pointer to be removed.
|
||||
vvp_net_ptr_t dst_ptr (net, 1);
|
||||
unlink_from_driver(src, dst_ptr);
|
||||
src->unlink(dst_ptr);
|
||||
sig->cassign_link = 0;
|
||||
}
|
||||
|
||||
/* Do we release all or part of the net? */
|
||||
vvp_net_ptr_t ptr (net, 3);
|
||||
if (full_sig) {
|
||||
vvp_send_long(ptr, 1);
|
||||
sig->deassign();
|
||||
} else {
|
||||
vvp_send_long_pv(ptr, 1, base, width);
|
||||
sig->deassign_pv(base, width);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -1864,19 +1840,18 @@ bool of_DEASSIGN_WR(vthread_t thr, vvp_code_t cp)
|
|||
{
|
||||
vvp_net_t*net = cp->net;
|
||||
|
||||
vvp_fun_signal_real*sig = reinterpret_cast<vvp_fun_signal_real*>(net->fun);
|
||||
vvp_fun_signal_real*sig = dynamic_cast<vvp_fun_signal_real*>(net->fun);
|
||||
assert(sig);
|
||||
|
||||
// This is the net that is forcing me...
|
||||
if (vvp_net_t*src = sig->cassign_link) {
|
||||
// And this is the pointer to be removed.
|
||||
vvp_net_ptr_t dst_ptr (net, 1);
|
||||
unlink_from_driver(src, dst_ptr);
|
||||
src->unlink(dst_ptr);
|
||||
sig->cassign_link = 0;
|
||||
}
|
||||
|
||||
vvp_net_ptr_t ptr (net, 3);
|
||||
vvp_send_long(ptr, 1);
|
||||
sig->deassign();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2391,42 +2366,6 @@ bool of_EVCTLS(vthread_t thr, vvp_code_t cp)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void unlink_force(vvp_net_t*net)
|
||||
{
|
||||
vvp_fun_signal_base*sig
|
||||
= reinterpret_cast<vvp_fun_signal_base*>(net->fun);
|
||||
/* This node must be a signal... */
|
||||
assert(sig);
|
||||
/* This signal is being forced. */
|
||||
assert(sig->force_link);
|
||||
|
||||
vvp_net_t*src = sig->force_link;
|
||||
sig->force_link = 0;
|
||||
|
||||
/* We are looking for this pointer. */
|
||||
vvp_net_ptr_t net_ptr (net, 2);
|
||||
|
||||
/* If net is first in the fan-out list, then simply pull it
|
||||
from the front. */
|
||||
if (src->out == net_ptr) {
|
||||
src->out = net->port[2];
|
||||
net->port[2] = vvp_net_ptr_t();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Look for the pointer in the fan-out chain */
|
||||
vvp_net_ptr_t cur_ptr = src->out;
|
||||
assert(!cur_ptr.nil());
|
||||
while (cur_ptr.ptr()->port[cur_ptr.port()] != net_ptr) {
|
||||
cur_ptr = cur_ptr.ptr()->port[cur_ptr.port()];
|
||||
assert( !cur_ptr.nil() );
|
||||
}
|
||||
|
||||
/* Remove as if from a singly-linked list. */
|
||||
cur_ptr.ptr()->port[cur_ptr.port()] = net->port[2];
|
||||
net->port[2] = vvp_net_ptr_t();
|
||||
}
|
||||
|
||||
/*
|
||||
* the %force/link instruction connects a source node to a
|
||||
* destination node. The destination node must be a signal, as it is
|
||||
|
|
@ -2439,26 +2378,8 @@ bool of_FORCE_LINK(vthread_t thr, vvp_code_t cp)
|
|||
vvp_net_t*dst = cp->net;
|
||||
vvp_net_t*src = cp->net2;
|
||||
|
||||
vvp_fun_signal_base*sig
|
||||
= reinterpret_cast<vvp_fun_signal_base*>(dst->fun);
|
||||
assert(sig);
|
||||
|
||||
/* Detect the special case that we are already forced the
|
||||
source onto the destination. */
|
||||
if (sig->force_link == src)
|
||||
return true;
|
||||
|
||||
/* If there is a linked force already, then unlink it. */
|
||||
if (sig->force_link)
|
||||
unlink_force(dst);
|
||||
|
||||
sig->force_link = src;
|
||||
|
||||
/* Link the output of the src to the port[2] (the force
|
||||
port) of the destination. */
|
||||
vvp_net_ptr_t dst_ptr (dst, 2);
|
||||
dst->port[2] = src->out;
|
||||
src->out = dst_ptr;
|
||||
assert(dst->fil);
|
||||
dst->fil->force_link(dst, src);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2484,9 +2405,13 @@ bool of_FORCE_V(vthread_t thr, vvp_code_t cp)
|
|||
/* Collect the thread bits into a vector4 item. */
|
||||
vvp_vector4_t value = vthread_bits_to_vector(thr, base, wid);
|
||||
|
||||
/* Set the value into port 2 of the destination. */
|
||||
vvp_net_ptr_t ptr (net, 2);
|
||||
vvp_send_vec4(ptr, value, 0);
|
||||
/* Send the force value to the filter on the node. */
|
||||
|
||||
assert(net->fil);
|
||||
if (value.size() != net->fil->filter_size())
|
||||
value = coerce_to_width(value, net->fil->filter_size());
|
||||
|
||||
net->force_vec4(value, vvp_vector2_t(vvp_vector2_t::FILL1, net->fil->filter_size()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2496,9 +2421,7 @@ bool of_FORCE_WR(vthread_t thr, vvp_code_t cp)
|
|||
vvp_net_t*net = cp->net;
|
||||
double value = thr->words[cp->bit_idx[0]].w_real;
|
||||
|
||||
/* Set the value into port 2 of the destination. */
|
||||
vvp_net_ptr_t ptr (net, 2);
|
||||
vvp_send_real(ptr, value, 0);
|
||||
net->force_real(value, vvp_vector2_t(vvp_vector2_t::FILL1, 1));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2510,30 +2433,38 @@ bool of_FORCE_X0(vthread_t thr, vvp_code_t cp)
|
|||
unsigned base = cp->bit_idx[0];
|
||||
unsigned wid = cp->bit_idx[1];
|
||||
|
||||
assert(net->fil);
|
||||
|
||||
// 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;
|
||||
unsigned use_size = net->fil->filter_size();
|
||||
|
||||
|
||||
if (index >= (long)use_size)
|
||||
return true;
|
||||
|
||||
if (index+wid > use_size)
|
||||
wid = use_size - index;
|
||||
|
||||
vvp_vector2_t mask(vvp_vector2_t::FILL0, use_size);
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1)
|
||||
mask.set_bit(index+idx, 1);
|
||||
|
||||
vvp_vector4_t vector = vthread_bits_to_vector(thr, base, wid);
|
||||
vvp_vector4_t value(use_size, BIT4_Z);
|
||||
value.set_vec(index, vector);
|
||||
|
||||
vvp_net_ptr_t ptr (net, 2);
|
||||
vvp_send_vec4_pv(ptr, vector, index, wid, sig->size(), 0);
|
||||
net->force_vec4(value, mask);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2749,10 +2680,11 @@ bool of_IX_GETV(vthread_t thr, vvp_code_t cp)
|
|||
unsigned index = cp->bit_idx[0];
|
||||
vvp_net_t*net = cp->net;
|
||||
|
||||
vvp_fun_signal_vec*sig = dynamic_cast<vvp_fun_signal_vec*>(net->fun);
|
||||
vvp_signal_value*sig = dynamic_cast<vvp_signal_value*>(net->fil);
|
||||
if (sig == 0) {
|
||||
assert(net->fil);
|
||||
cerr << "%%ix/getv error: Net arg not a vector signal? "
|
||||
<< typeid(*net->fun).name() << endl;
|
||||
<< typeid(*net->fil).name() << endl;
|
||||
}
|
||||
assert(sig);
|
||||
|
||||
|
|
@ -2776,10 +2708,12 @@ bool of_IX_GETVS(vthread_t thr, vvp_code_t cp)
|
|||
unsigned index = cp->bit_idx[0];
|
||||
vvp_net_t*net = cp->net;
|
||||
|
||||
vvp_fun_signal_vec*sig = dynamic_cast<vvp_fun_signal_vec*>(net->fun);
|
||||
vvp_signal_value*sig = dynamic_cast<vvp_signal_value*>(net->fil);
|
||||
if (sig == 0) {
|
||||
cerr << "%%ix/getv/s error: Net arg not a vector signal? "
|
||||
<< typeid(*net->fun).name() << endl;
|
||||
<< "fun=" << typeid(*net->fil).name()
|
||||
<< ", fil=" << (net->fil? typeid(*net->fil).name() : "<>")
|
||||
<< endl;
|
||||
}
|
||||
assert(sig);
|
||||
|
||||
|
|
@ -3127,10 +3061,10 @@ static vvp_vector4_t load_base(vthread_t thr, vvp_code_t cp)
|
|||
|
||||
/* For the %load to work, the functor must actually be a
|
||||
signal functor. Only signals save their vector value. */
|
||||
vvp_fun_signal_vec*sig = dynamic_cast<vvp_fun_signal_vec*> (net->fun);
|
||||
vvp_signal_value*sig = dynamic_cast<vvp_signal_value*> (net->fil);
|
||||
if (sig == 0) {
|
||||
cerr << "%%load/v error: Net arg not a vector signal? "
|
||||
<< typeid(*net->fun).name() << endl;
|
||||
cerr << "%%load/v error: Net arg not a signal? "
|
||||
<< typeid(*net->fil).name() << endl;
|
||||
assert(sig);
|
||||
}
|
||||
|
||||
|
|
@ -3229,13 +3163,13 @@ bool of_LOAD_X1P(vthread_t thr, vvp_code_t cp)
|
|||
|
||||
// For the %load to work, the functor must actually be a
|
||||
// signal functor. Only signals save their vector value.
|
||||
vvp_fun_signal_vec*sig = dynamic_cast<vvp_fun_signal_vec*> (net->fun);
|
||||
vvp_signal_value*sig = dynamic_cast<vvp_signal_value*> (net->fil);
|
||||
assert(sig);
|
||||
|
||||
for (long idx = 0 ; idx < wid ; idx += 1) {
|
||||
long use_index = index + idx;
|
||||
vvp_bit4_t val;
|
||||
if (use_index < 0 || use_index >= (signed)sig->size())
|
||||
if (use_index < 0 || use_index >= (signed)sig->value_size())
|
||||
val = BIT4_X;
|
||||
else
|
||||
val = sig->value(use_index);
|
||||
|
|
@ -4076,79 +4010,43 @@ bool of_POW_WR(vthread_t thr, vvp_code_t cp)
|
|||
* the release/reg command instead. These are very similar to the
|
||||
* %deassign instruction.
|
||||
*/
|
||||
bool of_RELEASE_NET(vthread_t thr, vvp_code_t cp)
|
||||
static bool do_release_vec(vthread_t thr, vvp_code_t cp, bool net_flag)
|
||||
{
|
||||
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);
|
||||
assert(net->fil);
|
||||
|
||||
if (base >= sig->size()) return true;
|
||||
if (base+width > sig->size()) width = sig->size() - base;
|
||||
if (base >= net->fil->filter_size()) return true;
|
||||
if (base+width > net->fil->filter_size())
|
||||
width = net->fil->filter_size() - base;
|
||||
|
||||
bool full_sig = base == 0 && width == sig->size();
|
||||
bool full_sig = base == 0 && width == net->fil->filter_size();
|
||||
|
||||
if (sig->force_link) {
|
||||
if (!full_sig) {
|
||||
fprintf(stderr, "Sorry: when a signal is forcing a "
|
||||
"net, I cannot release part of it.\n");
|
||||
exit(1);
|
||||
}
|
||||
unlink_force(net);
|
||||
}
|
||||
assert(sig->force_link == 0);
|
||||
// XXXX Can't really do this if this is a partial release?
|
||||
net->fil->force_unlink();
|
||||
|
||||
/* Do we release all or part of the net? */
|
||||
vvp_net_ptr_t ptr (net, 3);
|
||||
vvp_net_ptr_t ptr (net, 0);
|
||||
if (full_sig) {
|
||||
vvp_send_long(ptr, 2);
|
||||
net->fil->release(ptr, net_flag);
|
||||
} else {
|
||||
vvp_send_long_pv(ptr, 2, base, width);
|
||||
net->fil->release_pv(ptr, base, width, net_flag);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_RELEASE_NET(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
return do_release_vec(thr, cp, true);
|
||||
}
|
||||
|
||||
|
||||
bool of_RELEASE_REG(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
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();
|
||||
|
||||
// This is the net that is forcing me...
|
||||
if (vvp_net_t*src = sig->force_link) {
|
||||
if (!full_sig) {
|
||||
fprintf(stderr, "Sorry: when a signal is forcing a "
|
||||
"register, I cannot release part of it.\n");
|
||||
exit(1);
|
||||
}
|
||||
// And this is the pointer to be removed.
|
||||
vvp_net_ptr_t dst_ptr (net, 2);
|
||||
unlink_from_driver(src, dst_ptr);
|
||||
sig->force_link = 0;
|
||||
}
|
||||
|
||||
// Send a command to this signal to unforce itself.
|
||||
/* Do we release all or part of the net? */
|
||||
vvp_net_ptr_t ptr (net, 3);
|
||||
if (full_sig) {
|
||||
vvp_send_long(ptr, 3);
|
||||
} else {
|
||||
vvp_send_long_pv(ptr, 3, base, width);
|
||||
}
|
||||
|
||||
return true;
|
||||
return do_release_vec(thr, cp, false);
|
||||
}
|
||||
|
||||
/* The type is 1 for registers and 0 for everything else. */
|
||||
|
|
@ -4157,21 +4055,12 @@ bool of_RELEASE_WR(vthread_t thr, vvp_code_t cp)
|
|||
vvp_net_t*net = cp->net;
|
||||
unsigned type = cp->bit_idx[0];
|
||||
|
||||
vvp_fun_signal_real*sig = reinterpret_cast<vvp_fun_signal_real*>(net->fun);
|
||||
assert(sig);
|
||||
|
||||
// This is the net that is forcing me...
|
||||
if (vvp_net_t*src = sig->force_link) {
|
||||
// And this is the pointer to be removed.
|
||||
vvp_net_ptr_t dst_ptr (net, 2);
|
||||
unlink_from_driver(src, dst_ptr);
|
||||
sig->force_link = 0;
|
||||
}
|
||||
assert(net->fil);
|
||||
net->fil->force_unlink();
|
||||
|
||||
// Send a command to this signal to unforce itself.
|
||||
vvp_net_ptr_t ptr (net, 3);
|
||||
vvp_send_long(ptr, 2 + type);
|
||||
|
||||
vvp_net_ptr_t ptr (net, 0);
|
||||
net->fil->release(ptr, type==0);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -4269,7 +4158,8 @@ bool of_SET_X0(vthread_t thr, vvp_code_t cp)
|
|||
// X0 register.
|
||||
long index = thr->words[0].w_int;
|
||||
|
||||
vvp_fun_signal_vec*sig = dynamic_cast<vvp_fun_signal_vec*> (net->fun);
|
||||
vvp_signal_value*sig = dynamic_cast<vvp_signal_value*> (net->fil);
|
||||
assert(sig);
|
||||
|
||||
// If the entire part is below the beginning of the vector,
|
||||
// then we are done.
|
||||
|
|
@ -4278,7 +4168,7 @@ bool of_SET_X0(vthread_t thr, vvp_code_t cp)
|
|||
|
||||
// If the entire part is above then end of the vector, then we
|
||||
// are done.
|
||||
if (index >= (long)sig->size())
|
||||
if (index >= (long)sig->value_size())
|
||||
return true;
|
||||
|
||||
// If the part starts below the vector, then skip the first
|
||||
|
|
@ -4291,8 +4181,8 @@ bool of_SET_X0(vthread_t thr, vvp_code_t cp)
|
|||
}
|
||||
|
||||
// Reduce the width to keep the part inside the vector.
|
||||
if (index+wid > sig->size())
|
||||
wid = sig->size() - index;
|
||||
if (index+wid > sig->value_size())
|
||||
wid = sig->value_size() - index;
|
||||
|
||||
vvp_vector4_t bit_vec(wid);
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
|
|
@ -4303,7 +4193,7 @@ bool of_SET_X0(vthread_t thr, vvp_code_t cp)
|
|||
}
|
||||
|
||||
vvp_net_ptr_t ptr (net, 0);
|
||||
vvp_send_vec4_pv(ptr, bit_vec, index, wid, sig->size(), thr->wt_context);
|
||||
vvp_send_vec4_pv(ptr, bit_vec, index, wid, sig->value_size(), thr->wt_context);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ void island_send_value(vvp_net_t*net, const vvp_vector8_t&val)
|
|||
return;
|
||||
|
||||
fun->outvalue = val;
|
||||
vvp_send_vec8(net->out, fun->outvalue);
|
||||
net->send_vec8(fun->outvalue);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
1011
vvp/vvp_net.cc
1011
vvp/vvp_net.cc
File diff suppressed because it is too large
Load Diff
587
vvp/vvp_net.h
587
vvp/vvp_net.h
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
# include "config.h"
|
||||
# include "vpi_user.h"
|
||||
# include "vvp_vpi_callback.h"
|
||||
# include <stddef.h>
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
|
|
@ -42,6 +43,7 @@ class vvp_scalar_t;
|
|||
/* Basic netlist types. */
|
||||
class vvp_net_t;
|
||||
class vvp_net_fun_t;
|
||||
class vvp_net_fil_t;
|
||||
|
||||
/* Core net function types. */
|
||||
class vvp_fun_concat;
|
||||
|
|
@ -195,6 +197,9 @@ class vvp_vector4_t {
|
|||
friend class vvp_vector4array_sa;
|
||||
friend class vvp_vector4array_aa;
|
||||
|
||||
public:
|
||||
static const vvp_vector4_t nil;
|
||||
|
||||
public:
|
||||
explicit vvp_vector4_t(unsigned size =0, vvp_bit4_t bits =BIT4_X);
|
||||
|
||||
|
|
@ -634,9 +639,15 @@ extern vvp_vector2_t operator % (const vvp_vector2_t&, const vvp_vector2_t&);
|
|||
|
||||
vvp_vector2_t pow(const vvp_vector2_t&, vvp_vector2_t&);
|
||||
extern vvp_vector4_t vector2_to_vector4(const vvp_vector2_t&, unsigned wid);
|
||||
|
||||
/* A c4string is of the form C4<...> where ... are bits. */
|
||||
extern bool c4string_test(const char*str);
|
||||
extern vvp_vector4_t c4string_to_vector4(const char*str);
|
||||
|
||||
/* A crstring is of the form Cr<...> where ... defines are real. */
|
||||
extern bool crstring_test(const char*str);
|
||||
extern double crstring_to_double(const char*str);
|
||||
|
||||
extern ostream& operator<< (ostream&, const vvp_vector2_t&);
|
||||
|
||||
/* Inline some of the vector2_t methods. */
|
||||
|
|
@ -777,10 +788,15 @@ class vvp_vector8_t {
|
|||
|
||||
~vvp_vector8_t();
|
||||
|
||||
static const vvp_vector8_t nil;
|
||||
|
||||
public:
|
||||
|
||||
unsigned size() const { return size_; }
|
||||
vvp_scalar_t value(unsigned idx) const;
|
||||
vvp_vector8_t subvalue(unsigned adr, unsigned width) const;
|
||||
void set_bit(unsigned idx, vvp_scalar_t val);
|
||||
void set_vec(unsigned idx, const vvp_vector8_t&that);
|
||||
|
||||
// Test that the vectors are exactly equal
|
||||
bool eeq(const vvp_vector8_t&that) const;
|
||||
|
|
@ -821,6 +837,11 @@ extern vvp_vector8_t resistive_reduction(const vvp_vector8_t&a);
|
|||
strength information in the process. */
|
||||
extern vvp_vector4_t reduce4(const vvp_vector8_t&that);
|
||||
extern vvp_vector8_t part_expand(const vvp_vector8_t&a, unsigned wid, unsigned off);
|
||||
|
||||
/* A c8string is of the form C8<...> where ... are bits. */
|
||||
extern bool c8string_test(const char*str);
|
||||
extern vvp_vector8_t c8string_to_vector8(const char*str);
|
||||
|
||||
/* Print a vector8 value to a stream. */
|
||||
extern ostream& operator<< (ostream&, const vvp_vector8_t&);
|
||||
|
||||
|
|
@ -961,15 +982,52 @@ template <class T> ostream& operator << (ostream&out, vvp_sub_pointer_t<T> val)
|
|||
* the fan-out is unlimited.
|
||||
*
|
||||
* The vvp_send_*() functions take as input a vvp_net_ptr_t and follow
|
||||
* all the fan-out chain, delivering the specified value.
|
||||
* all the fan-out chain, delivering the specified value. The send_*()
|
||||
* methods of the vvp_net_t class are similar, but they follow the
|
||||
* output, possibly filtered, from the vvp_net_t.
|
||||
*/
|
||||
struct vvp_net_t {
|
||||
class vvp_net_t {
|
||||
public:
|
||||
vvp_net_t();
|
||||
|
||||
#ifdef CHECK_WITH_VALGRIND
|
||||
vvp_net_t *pool;
|
||||
#endif
|
||||
vvp_net_ptr_t port[4];
|
||||
vvp_net_ptr_t out;
|
||||
vvp_net_fun_t*fun;
|
||||
vvp_net_fil_t*fil;
|
||||
|
||||
public:
|
||||
// Connect the port to the output from this net.
|
||||
void link(vvp_net_ptr_t port);
|
||||
// Disconnect the port from the output of this net.
|
||||
void unlink(vvp_net_ptr_t port);
|
||||
|
||||
public: // Methods to propagate output from this node.
|
||||
void send_vec4(const vvp_vector4_t&val, vvp_context_t context);
|
||||
void send_vec8(const vvp_vector8_t&val);
|
||||
void send_real(double val, vvp_context_t context);
|
||||
void send_long(long val);
|
||||
|
||||
void send_vec4_pv(const vvp_vector4_t&val,
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t context);
|
||||
void send_vec8_pv(const vvp_vector8_t&val,
|
||||
unsigned base, unsigned wid, unsigned vwid);
|
||||
|
||||
|
||||
public: // Methods to arrange for the output of this net to be forced.
|
||||
|
||||
// The intent is that all efforts at force are directed to
|
||||
// operate only on the vvp_net_t whose output is to be
|
||||
// forced. These methods then communicate the force to the
|
||||
// attached filter to set up the actual force.
|
||||
void force_vec4(const vvp_vector4_t&val, vvp_vector2_t mask);
|
||||
void force_vec8(const vvp_vector8_t&val, vvp_vector2_t mask);
|
||||
void force_real(double val, vvp_vector2_t mask);
|
||||
|
||||
private:
|
||||
vvp_net_ptr_t out_;
|
||||
|
||||
public: // Need a better new for these objects.
|
||||
static void* operator new(std::size_t size);
|
||||
|
|
@ -1044,6 +1102,86 @@ class vvp_net_fun_t {
|
|||
static void operator delete[](void*);
|
||||
};
|
||||
|
||||
/*
|
||||
* A vvp_net_fil_t is a filter object that filters an output from a
|
||||
* vvp_net_t. The send_*() methods of the vvp_net_t object call the
|
||||
* filter of the output being transmitted. The filter function will
|
||||
* decide if this value is to be propagated, and return true or
|
||||
* false. If false, then send_*() continues as usual. If false, output
|
||||
* propagation is stopped.
|
||||
*
|
||||
* The filter object also provides an implementation hooks for
|
||||
* force/release.
|
||||
*/
|
||||
class vvp_net_fil_t : public vvp_vpi_callback {
|
||||
|
||||
public:
|
||||
vvp_net_fil_t();
|
||||
virtual ~vvp_net_fil_t();
|
||||
|
||||
public:
|
||||
enum prop_t { STOP=0, PROP, REPL };
|
||||
|
||||
// Return a non-empty vector if the filter allows an
|
||||
// output. The output result may be different from the
|
||||
// input. If the output is nil, then suppress propagation.
|
||||
|
||||
// Return true if the value is to be propagated, or false if
|
||||
// propagation is suppressed. The value may be edited by the
|
||||
// filter, or overridden by the rep argument if present.
|
||||
virtual prop_t filter_vec4(const vvp_vector4_t&bit, vvp_vector4_t&rep,
|
||||
unsigned base, unsigned vwid);
|
||||
virtual prop_t filter_vec8(const vvp_vector8_t&val, vvp_vector8_t&rep,
|
||||
unsigned base, unsigned vwid);
|
||||
virtual prop_t filter_real(double&val);
|
||||
virtual prop_t filter_long(long&val);
|
||||
|
||||
virtual void release(vvp_net_ptr_t ptr, bool net_flag) =0;
|
||||
virtual void release_pv(vvp_net_ptr_t ptr, unsigned base, unsigned wid, bool net_flag) =0;
|
||||
|
||||
// The %force/link instruction needs a place to write the
|
||||
// source node of the force, so that subsequent %force and
|
||||
// %release instructions can undo the link as needed. */
|
||||
void force_link(vvp_net_t*dst, vvp_net_t*src);
|
||||
void force_unlink(void);
|
||||
|
||||
virtual unsigned filter_size() const =0;
|
||||
|
||||
public:
|
||||
// Suport for force methods
|
||||
virtual void force_fil_vec4(const vvp_vector4_t&val, vvp_vector2_t mask) =0;
|
||||
virtual void force_fil_vec8(const vvp_vector8_t&val, vvp_vector2_t mask) =0;
|
||||
virtual void force_fil_real(double val, vvp_vector2_t mask) =0;
|
||||
|
||||
protected:
|
||||
// Set bits of the filter force mask
|
||||
void force_mask(vvp_vector2_t mask);
|
||||
// Release the force on the bits set in the mask.
|
||||
void release_mask(vvp_vector2_t mask);
|
||||
// Test bits of the filter force mask;
|
||||
bool test_force_mask(unsigned bit) const;
|
||||
bool test_force_mask_is_zero() const;
|
||||
|
||||
// This template method is used by derived classes to process
|
||||
// the val through the force mask. The force value is the
|
||||
// currently forced value, and the buf is a value that this
|
||||
// method will use to hold a filtered value, if needed. This
|
||||
// method returns a pointer to val or buf.
|
||||
template <class T> prop_t filter_mask_(const T&val, const T&force, T&rep, unsigned addr);
|
||||
// This template method is similar to the above, but works for
|
||||
// native types that are not so expensive to edit in place.
|
||||
template <class T> prop_t filter_mask_(T&val, T force);
|
||||
|
||||
private:
|
||||
// Mask of forced bits
|
||||
vvp_vector2_t force_mask_;
|
||||
// True if the next filter must propagate. Need this to allow
|
||||
// the forced value to get through.
|
||||
bool force_propagate_;
|
||||
// force link back.
|
||||
struct vvp_net_t*force_link_;
|
||||
};
|
||||
|
||||
/* **** Some core net functions **** */
|
||||
|
||||
/* vvp_fun_concat
|
||||
|
|
@ -1072,6 +1210,27 @@ class vvp_fun_concat : public vvp_net_fun_t {
|
|||
vvp_vector4_t val_;
|
||||
};
|
||||
|
||||
/*
|
||||
* The vvp_fun_force class objects are net functors that use their input
|
||||
* to force the associated filter. They do not actually have an
|
||||
* output, they instead drive the force_* methods of the net filter.
|
||||
*
|
||||
* This functor is also special in that we know a priori that only
|
||||
* port-0 is used, so we can use ports 1-3 for local storage. See the
|
||||
* implementation of vvp_filter_wire_base::force_link in
|
||||
* vvp_net_sig.cc for details.
|
||||
*/
|
||||
class vvp_fun_force : public vvp_net_fun_t {
|
||||
|
||||
public:
|
||||
vvp_fun_force();
|
||||
~vvp_fun_force();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
void recv_real(vvp_net_ptr_t port, double bit, vvp_context_t);
|
||||
};
|
||||
|
||||
/* vvp_fun_repeat
|
||||
* This node function create vectors by repeating the input. The width
|
||||
* is the width of the output vector, and the repeat is the number of
|
||||
|
|
@ -1137,325 +1296,6 @@ class vvp_fun_extend_signed : public vvp_net_fun_t {
|
|||
unsigned width_;
|
||||
};
|
||||
|
||||
/* vvp_fun_signal
|
||||
* This node is the place holder in a vvp network for signals,
|
||||
* including nets of various sort. The output from a signal follows
|
||||
* the type of its port-0 input. If vvp_vector4_t values come in
|
||||
* through port-0, then vvp_vector4_t values are propagated. If
|
||||
* vvp_vector8_t values come in through port-0, then vvp_vector8_t
|
||||
* values are propagated. Thus, this node is slightly polymorphic.
|
||||
*
|
||||
* If the signal is a net (i.e. a wire or tri) then this node will
|
||||
* have an input that is the data source. The data source will connect
|
||||
* through port-0.
|
||||
*
|
||||
* If the signal is a reg, then there will be no netlist input, the
|
||||
* values will be written by behavioral statements. The %set and
|
||||
* %assign statements will write through port-0.
|
||||
*
|
||||
* In any case, behavioral code is able to read the value that this
|
||||
* node last propagated, by using the value() method. That is important
|
||||
* functionality of this node.
|
||||
*
|
||||
* Continuous assignments are made through port-1. When a value is
|
||||
* written here, continuous assign mode is activated, and input
|
||||
* through port-0 is ignored until continuous assign mode is turned
|
||||
* off again. Writing into this port can be done in behavioral code
|
||||
* using the %cassign/v instruction, or can be done by the network by
|
||||
* hooking the output of a vvp_net_t to this port.
|
||||
*
|
||||
* Force assignments are made through port-2. When a value is written
|
||||
* here, force mode is activated. In force mode, port-0 data (or
|
||||
* port-1 data if in continuous assign mode) is tracked but not
|
||||
* propagated. The force value is propagated and is what is readable
|
||||
* through the value method.
|
||||
*
|
||||
* Port-3 is a command port, intended for use by procedural
|
||||
* instructions. The client must write long values to this port to
|
||||
* invoke the command of interest. The command values are:
|
||||
*
|
||||
* 1 -- deassign
|
||||
* The deassign command takes the node out of continuous
|
||||
* assignment mode. The output value is unchanged, and force
|
||||
* mode, if active, remains in effect.
|
||||
*
|
||||
* 2 -- release/net
|
||||
* The release/net command takes the node out of force mode,
|
||||
* and propagates the tracked port-0 value to the signal
|
||||
* output. This acts like a release of a net signal.
|
||||
*
|
||||
* 3 -- release/reg
|
||||
* The release/reg command is similar to the release/net
|
||||
* command, but the port-0 value is not propagated. Changes
|
||||
* to port-0 (or port-1 if continuous assign is active) will
|
||||
* propagate starting at the next input change.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Things derived from vvp_vpi_callback may also be array'ed, so it
|
||||
* includes some members that arrays use.
|
||||
*/
|
||||
class vvp_vpi_callback {
|
||||
|
||||
public:
|
||||
vvp_vpi_callback();
|
||||
virtual ~vvp_vpi_callback();
|
||||
|
||||
virtual void run_vpi_callbacks();
|
||||
void add_vpi_callback(struct __vpiCallback*);
|
||||
#ifdef CHECK_WITH_VALGRIND
|
||||
/* This has only been tested at EOS. */
|
||||
void clear_all_callbacks(void);
|
||||
#endif
|
||||
|
||||
virtual void get_value(struct t_vpi_value*value) =0;
|
||||
|
||||
private:
|
||||
struct __vpiCallback*vpi_callbacks_;
|
||||
};
|
||||
|
||||
class vvp_vpi_callback_wordable : public vvp_vpi_callback {
|
||||
public:
|
||||
vvp_vpi_callback_wordable();
|
||||
~vvp_vpi_callback_wordable();
|
||||
|
||||
void run_vpi_callbacks();
|
||||
void attach_as_word(class __vpiArray* arr, unsigned long addr);
|
||||
|
||||
private:
|
||||
class __vpiArray* array_;
|
||||
unsigned long array_word_;
|
||||
};
|
||||
|
||||
class vvp_fun_signal_base : public vvp_net_fun_t, public vvp_vpi_callback_wordable {
|
||||
|
||||
public:
|
||||
vvp_fun_signal_base();
|
||||
void recv_long(vvp_net_ptr_t port, long bit);
|
||||
void recv_long_pv(vvp_net_ptr_t port, long bit,
|
||||
unsigned base, unsigned wid);
|
||||
|
||||
public:
|
||||
|
||||
/* The %force/link instruction needs a place to write the
|
||||
source node of the force, so that subsequent %force and
|
||||
%release instructions can undo the link as needed. */
|
||||
struct vvp_net_t*force_link;
|
||||
struct vvp_net_t*cassign_link;
|
||||
|
||||
protected:
|
||||
|
||||
// This is true until at least one propagation happens.
|
||||
bool needs_init_;
|
||||
bool continuous_assign_active_;
|
||||
vvp_vector2_t force_mask_;
|
||||
vvp_vector2_t assign_mask_;
|
||||
|
||||
void deassign();
|
||||
void deassign_pv(unsigned base, unsigned wid);
|
||||
virtual void release(vvp_net_ptr_t ptr, bool net) =0;
|
||||
virtual void release_pv(vvp_net_ptr_t ptr, bool net,
|
||||
unsigned base, unsigned wid) =0;
|
||||
};
|
||||
|
||||
/*
|
||||
* This abstract class is a little more specific than the signal_base
|
||||
* class, in that it adds vector access methods.
|
||||
*/
|
||||
class vvp_fun_signal_vec : public vvp_fun_signal_base {
|
||||
|
||||
public:
|
||||
// For vector signal types, this returns the vector count.
|
||||
virtual unsigned size() const =0;
|
||||
virtual vvp_bit4_t value(unsigned idx) const =0;
|
||||
virtual vvp_scalar_t scalar_value(unsigned idx) const =0;
|
||||
virtual vvp_vector4_t vec4_value() const =0;
|
||||
};
|
||||
|
||||
class vvp_fun_signal4 : public vvp_fun_signal_vec {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_signal4() {};
|
||||
|
||||
void get_value(struct t_vpi_value*value);
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* Statically allocated vvp_fun_signal4.
|
||||
*/
|
||||
class vvp_fun_signal4_sa : public vvp_fun_signal4 {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_signal4_sa(unsigned wid, vvp_bit4_t init=BIT4_X);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
|
||||
|
||||
// Part select variants of above
|
||||
void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t);
|
||||
void recv_vec8_pv(vvp_net_ptr_t port, const vvp_vector8_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid);
|
||||
|
||||
// Get information about the vector value.
|
||||
unsigned size() const;
|
||||
vvp_bit4_t value(unsigned idx) const;
|
||||
vvp_scalar_t scalar_value(unsigned idx) const;
|
||||
vvp_vector4_t vec4_value() const;
|
||||
|
||||
// Commands
|
||||
void release(vvp_net_ptr_t port, bool net);
|
||||
void release_pv(vvp_net_ptr_t port, bool net,
|
||||
unsigned base, unsigned wid);
|
||||
|
||||
private:
|
||||
void calculate_output_(vvp_net_ptr_t ptr);
|
||||
|
||||
vvp_vector4_t bits4_;
|
||||
vvp_vector4_t force_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Automatically allocated vvp_fun_signal4.
|
||||
*/
|
||||
class vvp_fun_signal4_aa : public vvp_fun_signal4, public automatic_hooks_s {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_signal4_aa(unsigned wid, vvp_bit4_t init=BIT4_X);
|
||||
|
||||
void alloc_instance(vvp_context_t context);
|
||||
void reset_instance(vvp_context_t context);
|
||||
#ifdef CHECK_WITH_VALGRIND
|
||||
void free_instance(vvp_context_t context);
|
||||
#endif
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
|
||||
// Part select variants of above
|
||||
void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t);
|
||||
|
||||
// Get information about the vector value.
|
||||
unsigned size() const;
|
||||
vvp_bit4_t value(unsigned idx) const;
|
||||
vvp_scalar_t scalar_value(unsigned idx) const;
|
||||
vvp_vector4_t vec4_value() const;
|
||||
|
||||
// Commands
|
||||
void release(vvp_net_ptr_t port, bool net);
|
||||
void release_pv(vvp_net_ptr_t port, bool net,
|
||||
unsigned base, unsigned wid);
|
||||
|
||||
private:
|
||||
unsigned context_idx_;
|
||||
unsigned size_;
|
||||
};
|
||||
|
||||
class vvp_fun_signal8 : public vvp_fun_signal_vec {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_signal8(unsigned wid);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
|
||||
|
||||
// Part select variants of above
|
||||
void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t context);
|
||||
void recv_vec8_pv(vvp_net_ptr_t port, const vvp_vector8_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid);
|
||||
|
||||
// Get information about the vector value.
|
||||
unsigned size() const;
|
||||
vvp_bit4_t value(unsigned idx) const;
|
||||
vvp_scalar_t scalar_value(unsigned idx) const;
|
||||
vvp_vector4_t vec4_value() const;
|
||||
|
||||
// Commands
|
||||
void release(vvp_net_ptr_t port, bool net);
|
||||
void release_pv(vvp_net_ptr_t port, bool net,
|
||||
unsigned base, unsigned wid);
|
||||
|
||||
void get_value(struct t_vpi_value*value);
|
||||
|
||||
private:
|
||||
void calculate_output_(vvp_net_ptr_t ptr);
|
||||
|
||||
vvp_vector8_t bits8_;
|
||||
vvp_vector8_t force_;
|
||||
};
|
||||
|
||||
class vvp_fun_signal_real : public vvp_fun_signal_base {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_signal_real() {};
|
||||
|
||||
// Get information about the vector value.
|
||||
virtual double real_value() const = 0;
|
||||
|
||||
void get_value(struct t_vpi_value*value);
|
||||
};
|
||||
|
||||
/*
|
||||
* Statically allocated vvp_fun_signal_real.
|
||||
*/
|
||||
class vvp_fun_signal_real_sa : public vvp_fun_signal_real {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_signal_real_sa();
|
||||
|
||||
void recv_real(vvp_net_ptr_t port, double bit,
|
||||
vvp_context_t);
|
||||
|
||||
// Get information about the vector value.
|
||||
double real_value() const;
|
||||
|
||||
// Commands
|
||||
void release(vvp_net_ptr_t port, bool net);
|
||||
void release_pv(vvp_net_ptr_t port, bool net,
|
||||
unsigned base, unsigned wid);
|
||||
|
||||
private:
|
||||
double bits_;
|
||||
double force_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Automatically allocated vvp_fun_signal_real.
|
||||
*/
|
||||
class vvp_fun_signal_real_aa : public vvp_fun_signal_real, public automatic_hooks_s {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_signal_real_aa();
|
||||
|
||||
void alloc_instance(vvp_context_t context);
|
||||
void reset_instance(vvp_context_t context);
|
||||
#ifdef CHECK_WITH_VALGRIND
|
||||
void free_instance(vvp_context_t context);
|
||||
#endif
|
||||
|
||||
void recv_real(vvp_net_ptr_t port, double bit,
|
||||
vvp_context_t context);
|
||||
|
||||
// Get information about the vector value.
|
||||
double real_value() const;
|
||||
|
||||
// Commands
|
||||
void release(vvp_net_ptr_t port, bool net);
|
||||
void release_pv(vvp_net_ptr_t port, bool net,
|
||||
unsigned base, unsigned wid);
|
||||
|
||||
private:
|
||||
unsigned context_idx_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Wide Functors:
|
||||
* Wide functors represent special devices that may have more than 4
|
||||
|
|
@ -1536,8 +1376,7 @@ class vvp_wide_fun_t : public vvp_net_fun_t {
|
|||
};
|
||||
|
||||
|
||||
inline void vvp_send_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&val,
|
||||
vvp_context_t context)
|
||||
inline void vvp_send_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&val, vvp_context_t context)
|
||||
{
|
||||
while (struct vvp_net_t*cur = ptr.ptr()) {
|
||||
vvp_net_ptr_t next = cur->port[ptr.port()];
|
||||
|
|
@ -1576,8 +1415,8 @@ extern void vvp_send_long_pv(vvp_net_ptr_t ptr, long val,
|
|||
* mirror of the destination vector.
|
||||
*/
|
||||
inline void vvp_send_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&val,
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t context)
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t context)
|
||||
{
|
||||
while (struct vvp_net_t*cur = ptr.ptr()) {
|
||||
vvp_net_ptr_t next = cur->port[ptr.port()];
|
||||
|
|
@ -1589,9 +1428,10 @@ inline void vvp_send_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&val,
|
|||
}
|
||||
}
|
||||
|
||||
inline void vvp_send_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&val,
|
||||
unsigned base, unsigned wid, unsigned vwid)
|
||||
inline void vvp_net_t::send_vec8_pv(const vvp_vector8_t&val,
|
||||
unsigned base, unsigned wid, unsigned vwid)
|
||||
{
|
||||
vvp_net_ptr_t ptr = out_;
|
||||
while (struct vvp_net_t*cur = ptr.ptr()) {
|
||||
vvp_net_ptr_t next = cur->port[ptr.port()];
|
||||
|
||||
|
|
@ -1602,4 +1442,95 @@ inline void vvp_send_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&val,
|
|||
}
|
||||
}
|
||||
|
||||
inline void vvp_net_t::send_vec4(const vvp_vector4_t&val, vvp_context_t context)
|
||||
{
|
||||
if (fil == 0) {
|
||||
vvp_send_vec4(out_, val, context);
|
||||
return;
|
||||
}
|
||||
|
||||
vvp_vector4_t rep;
|
||||
switch (fil->filter_vec4(val, rep, 0, val.size())) {
|
||||
case vvp_net_fil_t::STOP:
|
||||
break;
|
||||
case vvp_net_fil_t::PROP:
|
||||
vvp_send_vec4(out_, val, context);
|
||||
break;
|
||||
case vvp_net_fil_t::REPL:
|
||||
vvp_send_vec4(out_, rep, context);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inline void vvp_net_t::send_vec4_pv(const vvp_vector4_t&val,
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t context)
|
||||
{
|
||||
if (fil == 0) {
|
||||
vvp_send_vec4_pv(out_, val, base, wid, vwid, context);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(val.size() == wid);
|
||||
vvp_vector4_t rep;
|
||||
switch (fil->filter_vec4(val, rep, base, vwid)) {
|
||||
case vvp_net_fil_t::STOP:
|
||||
break;
|
||||
case vvp_net_fil_t::PROP:
|
||||
vvp_send_vec4_pv(out_, val, base, wid, vwid, context);
|
||||
break;
|
||||
case vvp_net_fil_t::REPL:
|
||||
vvp_send_vec4_pv(out_, rep, base, wid, vwid, context);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inline void vvp_net_t::send_vec8(const vvp_vector8_t&val)
|
||||
{
|
||||
if (fil == 0) {
|
||||
vvp_send_vec8(out_, val);
|
||||
return;
|
||||
}
|
||||
|
||||
vvp_vector8_t rep;
|
||||
switch (fil->filter_vec8(val, rep, 0, val.size())) {
|
||||
case vvp_net_fil_t::STOP:
|
||||
break;
|
||||
case vvp_net_fil_t::PROP:
|
||||
vvp_send_vec8(out_, val);
|
||||
break;
|
||||
case vvp_net_fil_t::REPL:
|
||||
vvp_send_vec8(out_, rep);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inline void vvp_net_t::send_real(double val, vvp_context_t context)
|
||||
{
|
||||
if (fil && ! fil->filter_real(val))
|
||||
return;
|
||||
|
||||
vvp_send_real(out_, val, context);
|
||||
}
|
||||
|
||||
|
||||
inline bool vvp_net_fil_t::test_force_mask(unsigned bit) const
|
||||
{
|
||||
if (bit >= force_mask_.size())
|
||||
return false;
|
||||
if (force_mask_.value(bit))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool vvp_net_fil_t::test_force_mask_is_zero(void) const
|
||||
{
|
||||
if (force_mask_.size() == 0)
|
||||
return true;
|
||||
if (force_mask_.is_zero())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,994 @@
|
|||
/*
|
||||
* Copyright (c) 2004-2009 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
# include "config.h"
|
||||
# include "vvp_net.h"
|
||||
# include "vvp_net_sig.h"
|
||||
# include "statistics.h"
|
||||
# include "vpi_priv.h"
|
||||
# include <assert.h>
|
||||
#ifdef CHECK_WITH_VALGRIND
|
||||
# include <valgrind/memcheck.h>
|
||||
# include <map>
|
||||
#endif
|
||||
|
||||
# include <iostream>
|
||||
|
||||
template <class T> vvp_net_fil_t::prop_t vvp_net_fil_t::filter_mask_(const T&val, const T&force, T&filter, unsigned base)
|
||||
{
|
||||
if (!test_force_mask_is_zero()) {
|
||||
bool propagate_flag = force_propagate_;
|
||||
force_propagate_ = false;
|
||||
assert(force_mask_.size() == force.size());
|
||||
assert((base+val.size()) <= force_mask_.size());
|
||||
|
||||
filter = val;
|
||||
for (unsigned idx = 0 ; idx < val.size() ; idx += 1) {
|
||||
if (force_mask_.value(base+idx))
|
||||
filter.set_bit(idx, force.value(base+idx));
|
||||
else
|
||||
propagate_flag = true;
|
||||
}
|
||||
|
||||
if (propagate_flag) {
|
||||
run_vpi_callbacks();
|
||||
return REPL;
|
||||
} else {
|
||||
return STOP;
|
||||
}
|
||||
|
||||
} else {
|
||||
run_vpi_callbacks();
|
||||
return PROP;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T> vvp_net_fil_t::prop_t vvp_net_fil_t::filter_mask_(T&val, T force)
|
||||
{
|
||||
|
||||
if (test_force_mask(0)) {
|
||||
val = force;
|
||||
run_vpi_callbacks();
|
||||
return REPL;
|
||||
}
|
||||
run_vpi_callbacks();
|
||||
return PROP;
|
||||
}
|
||||
|
||||
vvp_signal_value::~vvp_signal_value()
|
||||
{
|
||||
}
|
||||
|
||||
double vvp_signal_value::real_value() const
|
||||
{
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void vvp_net_t::force_vec4(const vvp_vector4_t&val, vvp_vector2_t mask)
|
||||
{
|
||||
assert(fil);
|
||||
fil->force_fil_vec4(val, mask);
|
||||
vvp_send_vec4(out_, val, 0);
|
||||
}
|
||||
|
||||
void vvp_net_t::force_vec8(const vvp_vector8_t&val, vvp_vector2_t mask)
|
||||
{
|
||||
assert(fil);
|
||||
fil->force_fil_vec8(val, mask);
|
||||
vvp_send_vec8(out_, val);
|
||||
}
|
||||
|
||||
void vvp_net_t::force_real(double val, vvp_vector2_t mask)
|
||||
{
|
||||
assert(fil);
|
||||
fil->force_fil_real(val, mask);
|
||||
vvp_send_real(out_, val, 0);
|
||||
}
|
||||
|
||||
/* **** vvp_fun_signal methods **** */
|
||||
|
||||
vvp_fun_signal_base::vvp_fun_signal_base()
|
||||
{
|
||||
continuous_assign_active_ = false;
|
||||
needs_init_ = true;
|
||||
cassign_link = 0;
|
||||
count_functors_sig += 1;
|
||||
}
|
||||
|
||||
vvp_fun_signal4_sa::vvp_fun_signal4_sa(unsigned wid, vvp_bit4_t init)
|
||||
: bits4_(wid, init)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Nets simply reflect their input to their output.
|
||||
*
|
||||
* NOTE: It is a quirk of vvp_fun_signal that it has an initial value
|
||||
* that needs to be propagated, but after that it only needs to
|
||||
* propagate if the value changes. Eliminating duplicate propagations
|
||||
* should improve performance, but has the quirk that an input that
|
||||
* matches the initial value might not be propagated. The hack used
|
||||
* herein is to keep a "needs_init_" flag that is turned false after
|
||||
* the first propagation, and forces the first propagation to happen
|
||||
* even if it matches the initial value.
|
||||
*/
|
||||
void vvp_fun_signal4_sa::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
switch (ptr.port()) {
|
||||
case 0: // Normal input (feed from net, or set from process)
|
||||
/* If we don't have a continuous assign mask then just
|
||||
copy the bits, otherwise we need to see if there are
|
||||
any holes in the mask so we can set those bits. */
|
||||
if (assign_mask_.size() == 0) {
|
||||
if (needs_init_ || !bits4_.eeq(bit)) {
|
||||
assert(bit.size() == bits4_.size());
|
||||
bits4_ = bit;
|
||||
needs_init_ = false;
|
||||
ptr.ptr()->send_vec4(bits4_, 0);
|
||||
}
|
||||
} 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;
|
||||
ptr.ptr()->send_vec4(bits4_, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: // Continuous assign value
|
||||
bits4_ = bit;
|
||||
assign_mask_ = vvp_vector2_t(vvp_vector2_t::FILL1, bits4_.size());
|
||||
ptr.ptr()->send_vec4(bits4_, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Unsupported port type %d.\n", ptr.port());
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void vvp_fun_signal4_sa::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
|
||||
{
|
||||
recv_vec4(ptr, reduce4(bit), 0);
|
||||
}
|
||||
|
||||
void vvp_fun_signal4_sa::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t)
|
||||
{
|
||||
assert(bit.size() == wid);
|
||||
assert(bits4_.size() == vwid);
|
||||
|
||||
switch (ptr.port()) {
|
||||
case 0: // Normal input
|
||||
if (assign_mask_.size() == 0) {
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
if (base+idx >= bits4_.size()) break;
|
||||
bits4_.set_bit(base+idx, bit.value(idx));
|
||||
}
|
||||
needs_init_ = false;
|
||||
ptr.ptr()->send_vec4(bits4_,0);
|
||||
} 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;
|
||||
ptr.ptr()->send_vec4(bits4_,0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: // Continuous assign value
|
||||
if (assign_mask_.size() == 0)
|
||||
assign_mask_ = vvp_vector2_t(vvp_vector2_t::FILL0, bits4_.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);
|
||||
}
|
||||
ptr.ptr()->send_vec4(bits4_,0);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Unsupported port type %d.\n", ptr.port());
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void vvp_fun_signal4_sa::recv_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid)
|
||||
{
|
||||
recv_vec4_pv(ptr, reduce4(bit), base, wid, vwid, 0);
|
||||
}
|
||||
|
||||
void vvp_fun_signal_base::deassign()
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
void automatic_signal_base::release(vvp_net_ptr_t,bool)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void automatic_signal_base::release_pv(vvp_net_ptr_t,unsigned,unsigned,bool)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
unsigned automatic_signal_base::filter_size() const
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
void automatic_signal_base::force_fil_vec4(const vvp_vector4_t&, vvp_vector2_t)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
void automatic_signal_base::force_fil_vec8(const vvp_vector8_t&, vvp_vector2_t)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
void automatic_signal_base::force_fil_real(double, vvp_vector2_t)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
void automatic_signal_base::get_value(struct t_vpi_value*)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
vvp_vector4_t vvp_fun_signal4_sa::vec4_unfiltered_value() const
|
||||
{
|
||||
return bits4_;
|
||||
}
|
||||
|
||||
vvp_fun_signal4_aa::vvp_fun_signal4_aa(unsigned wid, vvp_bit4_t init)
|
||||
{
|
||||
context_idx_ = vpip_add_item_to_context(this, vpip_peek_context_scope());
|
||||
size_ = wid;
|
||||
}
|
||||
|
||||
void vvp_fun_signal4_aa::alloc_instance(vvp_context_t context)
|
||||
{
|
||||
vvp_set_context_item(context, context_idx_, new vvp_vector4_t(size_));
|
||||
}
|
||||
|
||||
void vvp_fun_signal4_aa::reset_instance(vvp_context_t context)
|
||||
{
|
||||
vvp_vector4_t*bits = static_cast<vvp_vector4_t*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
bits->set_to_x();
|
||||
}
|
||||
|
||||
#ifdef CHECK_WITH_VALGRIND
|
||||
void vvp_fun_signal4_aa::free_instance(vvp_context_t context)
|
||||
{
|
||||
vvp_vector4_t*bits = static_cast<vvp_vector4_t*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
delete bits;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Continuous and forced assignments are not permitted on automatic
|
||||
* variables. So we only expect to receive on port 0.
|
||||
*/
|
||||
void vvp_fun_signal4_aa::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t context)
|
||||
{
|
||||
assert(ptr.port() == 0);
|
||||
assert(context);
|
||||
|
||||
vvp_vector4_t*bits4 = static_cast<vvp_vector4_t*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
if (!bits4->eeq(bit)) {
|
||||
*bits4 = bit;
|
||||
ptr.ptr()->send_vec4(*bits4, context);
|
||||
}
|
||||
}
|
||||
|
||||
void vvp_fun_signal4_aa::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t context)
|
||||
{
|
||||
assert(ptr.port() == 0);
|
||||
assert(bit.size() == wid);
|
||||
assert(size_ == vwid);
|
||||
assert(context);
|
||||
|
||||
vvp_vector4_t*bits4 = static_cast<vvp_vector4_t*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
if (base+idx >= bits4->size()) break;
|
||||
bits4->set_bit(base+idx, bit.value(idx));
|
||||
}
|
||||
ptr.ptr()->send_vec4(*bits4, context);
|
||||
}
|
||||
|
||||
unsigned vvp_fun_signal4_aa::value_size() const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
vvp_bit4_t vvp_fun_signal4_aa::value(unsigned idx) const
|
||||
{
|
||||
vvp_vector4_t*bits4 = static_cast<vvp_vector4_t*>
|
||||
(vthread_get_rd_context_item(context_idx_));
|
||||
|
||||
return bits4->value(idx);
|
||||
}
|
||||
|
||||
vvp_scalar_t vvp_fun_signal4_aa::scalar_value(unsigned idx) const
|
||||
{
|
||||
vvp_vector4_t*bits4 = static_cast<vvp_vector4_t*>
|
||||
(vthread_get_rd_context_item(context_idx_));
|
||||
|
||||
return vvp_scalar_t(bits4->value(idx), 6, 6);
|
||||
}
|
||||
|
||||
vvp_vector4_t vvp_fun_signal4_aa::vec4_value() const
|
||||
{
|
||||
vvp_vector4_t*bits4 = static_cast<vvp_vector4_t*>
|
||||
(vthread_get_rd_context_item(context_idx_));
|
||||
|
||||
return *bits4;
|
||||
}
|
||||
|
||||
vvp_vector4_t vvp_fun_signal4_aa::vec4_unfiltered_value() const
|
||||
{
|
||||
return vec4_value();
|
||||
}
|
||||
|
||||
vvp_fun_signal8::vvp_fun_signal8(unsigned wid)
|
||||
: bits8_(wid)
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_fun_signal8::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
recv_vec8(ptr, vvp_vector8_t(bit,6,6));
|
||||
}
|
||||
|
||||
void vvp_fun_signal8::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
|
||||
{
|
||||
switch (ptr.port()) {
|
||||
case 0: // Normal input (feed from net, or set from process)
|
||||
if (needs_init_ || !bits8_.eeq(bit)) {
|
||||
bits8_ = bit;
|
||||
needs_init_ = false;
|
||||
ptr.ptr()->send_vec8(bits8_);
|
||||
}
|
||||
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;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Unsupported port type %d.\n", ptr.port());
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void vvp_fun_signal8::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t)
|
||||
{
|
||||
recv_vec8_pv(ptr, vvp_vector8_t(bit,6,6), base, wid, vwid);
|
||||
}
|
||||
|
||||
void vvp_fun_signal8::recv_vec8_pv(vvp_net_ptr_t ptr, const 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;
|
||||
ptr.ptr()->send_vec8(bits8_);
|
||||
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;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Unsupported port type %d.\n", ptr.port());
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Testing for equality, we want a bitwise test instead of an
|
||||
* arithmetic test because we want to treat for example -0 different
|
||||
* from +0.
|
||||
*/
|
||||
bool bits_equal(double a, double b)
|
||||
{
|
||||
return memcmp(&a, &b, sizeof a) == 0;
|
||||
}
|
||||
|
||||
vvp_fun_signal_real_sa::vvp_fun_signal_real_sa()
|
||||
{
|
||||
bits_ = 0.0;
|
||||
}
|
||||
|
||||
double vvp_fun_signal_real_sa::real_unfiltered_value() const
|
||||
{
|
||||
return bits_;
|
||||
}
|
||||
|
||||
void vvp_fun_signal_real_sa::recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
switch (ptr.port()) {
|
||||
case 0:
|
||||
if (!continuous_assign_active_) {
|
||||
if (needs_init_ || !bits_equal(bits_, bit)) {
|
||||
bits_ = bit;
|
||||
needs_init_ = false;
|
||||
ptr.ptr()->send_real(bit, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: // Continuous assign value
|
||||
continuous_assign_active_ = true;
|
||||
bits_ = bit;
|
||||
ptr.ptr()->send_real(bit, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Unsupported port type %d.\n", ptr.port());
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
vvp_fun_signal_real_aa::vvp_fun_signal_real_aa()
|
||||
{
|
||||
context_idx_ = vpip_add_item_to_context(this, vpip_peek_context_scope());
|
||||
}
|
||||
|
||||
void vvp_fun_signal_real_aa::alloc_instance(vvp_context_t context)
|
||||
{
|
||||
double*bits = new double;
|
||||
vvp_set_context_item(context, context_idx_, bits);
|
||||
|
||||
*bits = 0.0;
|
||||
}
|
||||
|
||||
void vvp_fun_signal_real_aa::reset_instance(vvp_context_t context)
|
||||
{
|
||||
double*bits = static_cast<double*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
*bits = 0.0;
|
||||
}
|
||||
|
||||
#ifdef CHECK_WITH_VALGRIND
|
||||
void vvp_fun_signal_real_aa::free_instance(vvp_context_t context)
|
||||
{
|
||||
double*bits = static_cast<double*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
delete bits;
|
||||
}
|
||||
#endif
|
||||
|
||||
double vvp_fun_signal_real_aa::real_unfiltered_value() const
|
||||
{
|
||||
double*bits = static_cast<double*>
|
||||
(vthread_get_rd_context_item(context_idx_));
|
||||
|
||||
return *bits;
|
||||
}
|
||||
|
||||
double vvp_fun_signal_real_aa::real_value() const
|
||||
{
|
||||
return real_unfiltered_value();
|
||||
}
|
||||
|
||||
void vvp_fun_signal_real_aa::recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t context)
|
||||
{
|
||||
assert(ptr.port() == 0);
|
||||
assert(context);
|
||||
|
||||
double*bits = static_cast<double*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
if (!bits_equal(*bits,bit)) {
|
||||
*bits = bit;
|
||||
ptr.ptr()->send_real(bit, context);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned vvp_fun_signal_real_aa::value_size() const
|
||||
{
|
||||
assert(0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
vvp_bit4_t vvp_fun_signal_real_aa::value(unsigned idx) const
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
vvp_scalar_t vvp_fun_signal_real_aa::scalar_value(unsigned idx) const
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
vvp_vector4_t vvp_fun_signal_real_aa::vec4_value() const
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
vvp_fun_force::vvp_fun_force()
|
||||
{
|
||||
}
|
||||
|
||||
vvp_fun_force::~vvp_fun_force()
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_fun_force::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
assert(ptr.port() == 0);
|
||||
vvp_net_t*net = ptr.ptr();
|
||||
|
||||
vvp_net_t*dst = net->port[3].ptr();
|
||||
assert(dst->fil);
|
||||
|
||||
dst->force_vec4(coerce_to_width(bit, dst->fil->filter_size()), vvp_vector2_t(vvp_vector2_t::FILL1, dst->fil->filter_size()));
|
||||
}
|
||||
|
||||
void vvp_fun_force::recv_real(vvp_net_ptr_t ptr, double bit, vvp_context_t)
|
||||
{
|
||||
assert(ptr.port() == 0);
|
||||
vvp_net_t*net = ptr.ptr();
|
||||
vvp_net_t*dst = net->port[3].ptr();
|
||||
dst->force_real(bit, vvp_vector2_t(vvp_vector2_t::FILL1, 1));
|
||||
}
|
||||
|
||||
vvp_wire_base::vvp_wire_base()
|
||||
{
|
||||
}
|
||||
|
||||
vvp_wire_base::~vvp_wire_base()
|
||||
{
|
||||
}
|
||||
|
||||
vvp_wire_vec4::vvp_wire_vec4(unsigned wid, vvp_bit4_t init)
|
||||
: bits4_(wid, init)
|
||||
{
|
||||
needs_init_ = true;
|
||||
}
|
||||
|
||||
vvp_net_fil_t::prop_t vvp_wire_vec4::filter_vec4(const vvp_vector4_t&bit, vvp_vector4_t&rep,
|
||||
unsigned base, unsigned vwid)
|
||||
{
|
||||
// Special case! the input bit is 0 wid. Interpret this as a
|
||||
// vector of BIT4_X to match the width of the bits4_ vector.
|
||||
// FIXME! This is a hack to work around some buggy gate
|
||||
// implementations! This should be removed!
|
||||
if (base==0 && vwid==0) {
|
||||
vvp_vector4_t tmp (bits4_.size(), BIT4_X);
|
||||
if (bits4_ .eeq(tmp) && !needs_init_) return STOP;
|
||||
bits4_ = tmp;
|
||||
needs_init_ = false;
|
||||
return filter_mask_(tmp, force4_, rep, 0);
|
||||
}
|
||||
|
||||
if (vwid != bits4_.size()) {
|
||||
cerr << "Internal error: Input vector expected width="
|
||||
<< bits4_.size() << ", got "
|
||||
<< "bit=" << bit << ", base=" << base << ", vwid=" << vwid
|
||||
<< endl;
|
||||
}
|
||||
assert(bits4_.size() == vwid);
|
||||
|
||||
// Keep track of the value being driven from this net, even if
|
||||
// it is not ultimately what survives the force filter.
|
||||
if (base==0 && bit.size()==vwid) {
|
||||
if (bits4_ .eeq( bit ) && !needs_init_) return STOP;
|
||||
bits4_ = bit;
|
||||
} else {
|
||||
bits4_.set_vec(base, bit);
|
||||
}
|
||||
|
||||
needs_init_ = false;
|
||||
return filter_mask_(bit, force4_, rep, base);
|
||||
}
|
||||
|
||||
vvp_net_fil_t::prop_t vvp_wire_vec4::filter_vec8(const vvp_vector8_t&bit, vvp_vector8_t&rep, unsigned base, unsigned vwid)
|
||||
{
|
||||
assert(bits4_.size() == bit.size());
|
||||
bits4_ = reduce4(bit);
|
||||
return filter_mask_(bit, vvp_vector8_t(force4_,6,6), rep, 0);
|
||||
}
|
||||
|
||||
unsigned vvp_wire_vec4::filter_size() const
|
||||
{
|
||||
return bits4_.size();
|
||||
}
|
||||
|
||||
void vvp_wire_vec4::force_fil_vec4(const vvp_vector4_t&val, vvp_vector2_t mask)
|
||||
{
|
||||
force_mask(mask);
|
||||
|
||||
if (force4_.size() == 0) {
|
||||
force4_ = val;
|
||||
} else {
|
||||
for (unsigned idx = 0; idx < mask.size() ; idx += 1) {
|
||||
if (mask.value(idx) == 0)
|
||||
continue;
|
||||
|
||||
force4_.set_bit(idx, val.value(idx));
|
||||
}
|
||||
}
|
||||
run_vpi_callbacks();
|
||||
}
|
||||
|
||||
void vvp_wire_vec4::force_fil_vec8(const vvp_vector8_t&val, vvp_vector2_t mask)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void vvp_wire_vec4::force_fil_real(double val, vvp_vector2_t mask)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void vvp_wire_vec4::release(vvp_net_ptr_t ptr, bool net_flag)
|
||||
{
|
||||
// Wires revert to their unforced value after release.
|
||||
vvp_vector2_t mask (vvp_vector2_t::FILL1, bits4_.size());
|
||||
release_mask(mask);
|
||||
if (net_flag) {
|
||||
ptr.ptr()->send_vec4(bits4_, 0);
|
||||
run_vpi_callbacks();
|
||||
} else {
|
||||
ptr.ptr()->fun->recv_vec4(ptr, force4_, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void vvp_wire_vec4::release_pv(vvp_net_ptr_t ptr, unsigned base, unsigned wid, bool net_flag)
|
||||
{
|
||||
assert(bits4_.size() >= base + wid);
|
||||
|
||||
vvp_vector2_t mask (vvp_vector2_t::FILL0, bits4_.size());
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1)
|
||||
mask.set_bit(base+idx, 1);
|
||||
|
||||
release_mask(mask);
|
||||
|
||||
if (net_flag) {
|
||||
ptr.ptr()->send_vec4_pv(bits4_.subvalue(base,wid),
|
||||
base, wid, bits4_.size(), 0);
|
||||
run_vpi_callbacks();
|
||||
} else {
|
||||
ptr.ptr()->fun->recv_vec4_pv(ptr, force4_.subvalue(base,wid),
|
||||
base, wid, bits4_.size(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned vvp_wire_vec4::value_size() const
|
||||
{
|
||||
return bits4_.size();
|
||||
}
|
||||
|
||||
vvp_bit4_t vvp_wire_vec4::filtered_value_(unsigned idx) const
|
||||
{
|
||||
if (test_force_mask(idx))
|
||||
return force4_.value(idx);
|
||||
else
|
||||
return bits4_.value(idx);
|
||||
}
|
||||
|
||||
vvp_bit4_t vvp_wire_vec4::value(unsigned idx) const
|
||||
{
|
||||
return filtered_value_(idx);
|
||||
}
|
||||
|
||||
vvp_scalar_t vvp_wire_vec4::scalar_value(unsigned idx) const
|
||||
{
|
||||
return vvp_scalar_t(value(idx),6,6);
|
||||
}
|
||||
|
||||
vvp_vector4_t vvp_wire_vec4::vec4_value() const
|
||||
{
|
||||
vvp_vector4_t tmp = bits4_;
|
||||
for (unsigned idx = 0 ; idx < bits4_.size() ; idx += 1)
|
||||
tmp.set_bit(idx, filtered_value_(idx));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
vvp_wire_vec8::vvp_wire_vec8(unsigned wid)
|
||||
: bits8_(wid)
|
||||
{
|
||||
needs_init_ = true;
|
||||
}
|
||||
|
||||
vvp_net_fil_t::prop_t vvp_wire_vec8::filter_vec4(const vvp_vector4_t&bit, vvp_vector4_t&rep,
|
||||
unsigned base, unsigned vwid)
|
||||
{
|
||||
// QUESTION: Is it really correct to propagate a vec4 if this
|
||||
// is a vec8 node? In fact, it is really possible for a vec4
|
||||
// value to get through to a vec8 filter?
|
||||
vvp_vector8_t rep8;
|
||||
prop_t rc = filter_vec8(vvp_vector8_t(bit,6,6), rep8, 0, vwid);
|
||||
if (rc == REPL)
|
||||
rep = reduce4(rep8);
|
||||
|
||||
needs_init_ = false;
|
||||
return rc;
|
||||
}
|
||||
|
||||
vvp_net_fil_t::prop_t vvp_wire_vec8::filter_vec8(const vvp_vector8_t&bit, vvp_vector8_t&rep, unsigned base, unsigned vwid)
|
||||
{
|
||||
assert(vwid == bits8_.size());
|
||||
// Keep track of the value being driven from this net, even if
|
||||
// it is not ultimately what survives the force filter.
|
||||
if (base==0 && bit.size()==vwid) {
|
||||
bits8_ = bit;
|
||||
} else {
|
||||
if (bits8_.size() == 0)
|
||||
bits8_ = vvp_vector8_t(vwid);
|
||||
assert(bits8_.size() == vwid);
|
||||
bits8_.set_vec(base, bit);
|
||||
}
|
||||
needs_init_ = false;
|
||||
return filter_mask_(bit, force8_, rep, base);
|
||||
}
|
||||
|
||||
unsigned vvp_wire_vec8::filter_size() const
|
||||
{
|
||||
return bits8_.size();
|
||||
}
|
||||
|
||||
void vvp_wire_vec8::force_fil_vec4(const vvp_vector4_t&val, vvp_vector2_t mask)
|
||||
{
|
||||
force_fil_vec8(vvp_vector8_t(val,6,6), mask);
|
||||
}
|
||||
|
||||
void vvp_wire_vec8::force_fil_vec8(const vvp_vector8_t&val, vvp_vector2_t mask)
|
||||
{
|
||||
force_mask(mask);
|
||||
|
||||
if (force8_.size() == 0) {
|
||||
force8_ = val;
|
||||
} else {
|
||||
for (unsigned idx = 0; idx < mask.size() ; idx += 1) {
|
||||
if (mask.value(idx) == 0)
|
||||
continue;
|
||||
|
||||
force8_.set_bit(idx, val.value(idx));
|
||||
}
|
||||
}
|
||||
run_vpi_callbacks();
|
||||
}
|
||||
|
||||
void vvp_wire_vec8::force_fil_real(double val, vvp_vector2_t mask)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void vvp_wire_vec8::release(vvp_net_ptr_t ptr, bool net_flag)
|
||||
{
|
||||
// Wires revert to their unforced value after release.
|
||||
vvp_vector2_t mask (vvp_vector2_t::FILL1, bits8_.size());
|
||||
release_mask(mask);
|
||||
if (net_flag)
|
||||
ptr.ptr()->send_vec8(bits8_);
|
||||
else
|
||||
ptr.ptr()->fun->recv_vec8(ptr, force8_);
|
||||
}
|
||||
|
||||
void vvp_wire_vec8::release_pv(vvp_net_ptr_t ptr, unsigned base, unsigned wid, bool net_flag)
|
||||
{
|
||||
assert(bits8_.size() >= base + wid);
|
||||
|
||||
vvp_vector2_t mask (vvp_vector2_t::FILL0, bits8_.size());
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1)
|
||||
mask.set_bit(base+idx, 1);
|
||||
|
||||
release_mask(mask);
|
||||
|
||||
if (net_flag) {
|
||||
ptr.ptr()->send_vec8_pv(bits8_.subvalue(base,wid),
|
||||
base, wid, bits8_.size());
|
||||
run_vpi_callbacks();
|
||||
} else {
|
||||
ptr.ptr()->fun->recv_vec8_pv(ptr, force8_.subvalue(base,wid),
|
||||
base, wid, force8_.size());
|
||||
}
|
||||
}
|
||||
|
||||
unsigned vvp_wire_vec8::value_size() const
|
||||
{
|
||||
return bits8_.size();
|
||||
}
|
||||
|
||||
vvp_scalar_t vvp_wire_vec8::filtered_value_(unsigned idx) const
|
||||
{
|
||||
if (test_force_mask(idx))
|
||||
return force8_.value(idx);
|
||||
else
|
||||
return bits8_.value(idx);
|
||||
}
|
||||
|
||||
vvp_bit4_t vvp_wire_vec8::value(unsigned idx) const
|
||||
{
|
||||
return filtered_value_(idx).value();
|
||||
}
|
||||
|
||||
vvp_scalar_t vvp_wire_vec8::scalar_value(unsigned idx) const
|
||||
{
|
||||
return filtered_value_(idx);
|
||||
}
|
||||
|
||||
vvp_vector8_t vvp_wire_vec8::vec8_value() const
|
||||
{
|
||||
vvp_vector8_t tmp = bits8_;
|
||||
for (unsigned idx = 0 ; idx < bits8_.size() ; idx += 1)
|
||||
tmp.set_bit(idx, filtered_value_(idx));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
vvp_vector4_t vvp_wire_vec8::vec4_value() const
|
||||
{
|
||||
return reduce4(vec8_value());
|
||||
}
|
||||
|
||||
vvp_wire_real::vvp_wire_real()
|
||||
{
|
||||
}
|
||||
|
||||
vvp_net_fil_t::prop_t vvp_wire_real::filter_real(double&bit)
|
||||
{
|
||||
bit_ = bit;
|
||||
return filter_mask_(bit, force_);
|
||||
}
|
||||
|
||||
unsigned vvp_wire_real::filter_size() const
|
||||
{
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void vvp_wire_real::force_fil_vec4(const vvp_vector4_t&val, vvp_vector2_t mask)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void vvp_wire_real::force_fil_vec8(const vvp_vector8_t&val, vvp_vector2_t mask)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void vvp_wire_real::force_fil_real(double val, vvp_vector2_t mask)
|
||||
{
|
||||
force_mask(mask);
|
||||
if (mask.value(0))
|
||||
force_ = val;
|
||||
|
||||
run_vpi_callbacks();
|
||||
}
|
||||
|
||||
void vvp_wire_real::release(vvp_net_ptr_t ptr, bool net_flag)
|
||||
{
|
||||
// Wires revert to their unforced value after release.
|
||||
vvp_vector2_t mask (vvp_vector2_t::FILL1, 1);
|
||||
release_mask(mask);
|
||||
if (net_flag)
|
||||
ptr.ptr()->send_real(bit_, 0);
|
||||
else
|
||||
ptr.ptr()->fun->recv_real(ptr, force_, 0);
|
||||
}
|
||||
|
||||
void vvp_wire_real::release_pv(vvp_net_ptr_t ptr, unsigned base, unsigned wid, bool net_flag)
|
||||
{
|
||||
vvp_vector2_t mask (vvp_vector2_t::FILL0, 1);
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1)
|
||||
mask.set_bit(base+idx, 1);
|
||||
|
||||
release_mask(mask);
|
||||
if (net_flag)
|
||||
ptr.ptr()->send_real(bit_, 0);
|
||||
else
|
||||
ptr.ptr()->fun->recv_real(ptr, force_, 0);
|
||||
}
|
||||
|
||||
unsigned vvp_wire_real::value_size() const
|
||||
{
|
||||
assert(0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
vvp_bit4_t vvp_wire_real::value(unsigned idx) const
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
vvp_scalar_t vvp_wire_real::scalar_value(unsigned idx) const
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
vvp_vector4_t vvp_wire_real::vec4_value() const
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
double vvp_wire_real::real_value() const
|
||||
{
|
||||
if (test_force_mask(0))
|
||||
return force_;
|
||||
else
|
||||
return bit_;
|
||||
}
|
||||
|
|
@ -0,0 +1,396 @@
|
|||
#ifndef __vvp_net_sig_H
|
||||
#define __vvp_net_sig_H
|
||||
/*
|
||||
* Copyright (c) 2004-2009 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
# include "config.h"
|
||||
# include "vpi_user.h"
|
||||
# include "vvp_net.h"
|
||||
# include <stddef.h>
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
# include <new>
|
||||
# include <assert.h>
|
||||
|
||||
#ifdef HAVE_IOSFWD
|
||||
# include <iosfwd>
|
||||
#else
|
||||
class ostream;
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
/* vvp_fun_signal
|
||||
* This node is the place holder in a vvp network for signals,
|
||||
* including nets of various sort. The output from a signal follows
|
||||
* the type of its port-0 input. If vvp_vector4_t values come in
|
||||
* through port-0, then vvp_vector4_t values are propagated. If
|
||||
* vvp_vector8_t values come in through port-0, then vvp_vector8_t
|
||||
* values are propagated. Thus, this node is slightly polymorphic.
|
||||
*
|
||||
* If the signal is a net (i.e. a wire or tri) then this node will
|
||||
* have an input that is the data source. The data source will connect
|
||||
* through port-0.
|
||||
*
|
||||
* If the signal is a reg, then there will be no netlist input, the
|
||||
* values will be written by behavioral statements. The %set and
|
||||
* %assign statements will write through port-0.
|
||||
*
|
||||
* In any case, behavioral code is able to read the value that this
|
||||
* node last propagated, by using the value() method. That is important
|
||||
* functionality of this node.
|
||||
*
|
||||
* Continuous assignments are made through port-1. When a value is
|
||||
* written here, continuous assign mode is activated, and input
|
||||
* through port-0 is ignored until continuous assign mode is turned
|
||||
* off again. Writing into this port can be done in behavioral code
|
||||
* using the %cassign/v instruction, or can be done by the network by
|
||||
* hooking the output of a vvp_net_t to this port.
|
||||
*/
|
||||
|
||||
|
||||
class vvp_fun_signal_base : public vvp_net_fun_t {
|
||||
|
||||
public:
|
||||
vvp_fun_signal_base();
|
||||
|
||||
void deassign();
|
||||
void deassign_pv(unsigned base, unsigned wid);
|
||||
|
||||
public:
|
||||
|
||||
/* The %cassign/link instruction needs a place to write the
|
||||
source node of the force, so that subsequent %cassign and
|
||||
%deassign instructions can undo the link as needed. */
|
||||
struct vvp_net_t*cassign_link;
|
||||
|
||||
protected:
|
||||
bool continuous_assign_active_;
|
||||
vvp_vector2_t assign_mask_;
|
||||
|
||||
protected:
|
||||
// This is true until at least one propagation happens.
|
||||
bool needs_init_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Variables and wires can have their values accessed, so this base
|
||||
* class offers the unified concept of an acessible value.
|
||||
*/
|
||||
class vvp_signal_value {
|
||||
public:
|
||||
virtual ~vvp_signal_value() =0;
|
||||
virtual unsigned value_size() const =0;
|
||||
virtual vvp_bit4_t value(unsigned idx) const =0;
|
||||
virtual vvp_scalar_t scalar_value(unsigned idx) const =0;
|
||||
virtual vvp_vector4_t vec4_value() const =0;
|
||||
virtual double real_value() const;
|
||||
|
||||
virtual void get_signal_value(struct t_vpi_value*vp);
|
||||
};
|
||||
|
||||
/*
|
||||
* This abstract class is a little more specific than the signal_base
|
||||
* class, in that it adds vector access methods.
|
||||
*/
|
||||
class vvp_fun_signal_vec : public vvp_fun_signal_base {
|
||||
public:
|
||||
virtual vvp_vector4_t vec4_unfiltered_value() const =0;
|
||||
};
|
||||
|
||||
class automatic_signal_base : public vvp_signal_value, public vvp_net_fil_t {
|
||||
|
||||
public:
|
||||
// Automatic variables cannot be forced or released. Provide
|
||||
// stubs that assert.
|
||||
virtual void release(vvp_net_ptr_t ptr, bool net_flag);
|
||||
virtual void release_pv(vvp_net_ptr_t ptr, unsigned base, unsigned wid, bool net_flag);
|
||||
|
||||
virtual unsigned filter_size() const;
|
||||
virtual void force_fil_vec4(const vvp_vector4_t&val, vvp_vector2_t mask);
|
||||
virtual void force_fil_vec8(const vvp_vector8_t&val, vvp_vector2_t mask);
|
||||
virtual void force_fil_real(double val, vvp_vector2_t mask);
|
||||
virtual void get_value(struct t_vpi_value*value);
|
||||
};
|
||||
|
||||
/*
|
||||
* Statically allocated vvp_fun_signal4.
|
||||
*/
|
||||
class vvp_fun_signal4_sa : public vvp_fun_signal_vec {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_signal4_sa(unsigned wid, vvp_bit4_t init=BIT4_X);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
|
||||
|
||||
// Part select variants of above
|
||||
void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t);
|
||||
void recv_vec8_pv(vvp_net_ptr_t port, const vvp_vector8_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid);
|
||||
|
||||
// Get information about the vector value.
|
||||
vvp_vector4_t vec4_unfiltered_value() const;
|
||||
|
||||
private:
|
||||
vvp_vector4_t bits4_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Automatically allocated vvp_fun_signal4.
|
||||
*/
|
||||
class vvp_fun_signal4_aa : public vvp_fun_signal_vec, public automatic_signal_base, public automatic_hooks_s {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_signal4_aa(unsigned wid, vvp_bit4_t init=BIT4_X);
|
||||
|
||||
void alloc_instance(vvp_context_t context);
|
||||
void reset_instance(vvp_context_t context);
|
||||
#ifdef CHECK_WITH_VALGRIND
|
||||
void free_instance(vvp_context_t context);
|
||||
#endif
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
|
||||
// Part select variants of above
|
||||
void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t);
|
||||
|
||||
// Get information about the vector value.
|
||||
unsigned value_size() const;
|
||||
vvp_bit4_t value(unsigned idx) const;
|
||||
vvp_scalar_t scalar_value(unsigned idx) const;
|
||||
vvp_vector4_t vec4_value() const;
|
||||
vvp_vector4_t vec4_unfiltered_value() const;
|
||||
|
||||
private:
|
||||
unsigned context_idx_;
|
||||
unsigned size_;
|
||||
};
|
||||
|
||||
class vvp_fun_signal8 : public vvp_fun_signal_vec {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_signal8(unsigned wid);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
|
||||
|
||||
// Part select variants of above
|
||||
void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t context);
|
||||
void recv_vec8_pv(vvp_net_ptr_t port, const vvp_vector8_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid);
|
||||
|
||||
private:
|
||||
vvp_vector8_t bits8_;
|
||||
};
|
||||
|
||||
class vvp_fun_signal_real : public vvp_fun_signal_base {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_signal_real() {};
|
||||
|
||||
// Get information about the vector value.
|
||||
virtual double real_unfiltered_value() const = 0;
|
||||
|
||||
unsigned size() const { return 1; }
|
||||
};
|
||||
|
||||
/*
|
||||
* Statically allocated vvp_fun_signal_real.
|
||||
*/
|
||||
class vvp_fun_signal_real_sa : public vvp_fun_signal_real {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_signal_real_sa();
|
||||
|
||||
void recv_real(vvp_net_ptr_t port, double bit,
|
||||
vvp_context_t);
|
||||
|
||||
// Get information about the vector value.
|
||||
double real_unfiltered_value() const;
|
||||
|
||||
private:
|
||||
double bits_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Automatically allocated vvp_fun_signal_real.
|
||||
*/
|
||||
class vvp_fun_signal_real_aa : public vvp_fun_signal_real, public automatic_signal_base, public automatic_hooks_s {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_signal_real_aa();
|
||||
|
||||
void alloc_instance(vvp_context_t context);
|
||||
void reset_instance(vvp_context_t context);
|
||||
#ifdef CHECK_WITH_VALGRIND
|
||||
void free_instance(vvp_context_t context);
|
||||
#endif
|
||||
|
||||
void recv_real(vvp_net_ptr_t port, double bit,
|
||||
vvp_context_t context);
|
||||
|
||||
// Get information about the vector value.
|
||||
double real_unfiltered_value() const;
|
||||
|
||||
// Get information about the vector value.
|
||||
unsigned value_size() const;
|
||||
vvp_bit4_t value(unsigned idx) const;
|
||||
vvp_scalar_t scalar_value(unsigned idx) const;
|
||||
vvp_vector4_t vec4_value() const;
|
||||
double real_value() const;
|
||||
void get_signal_value(struct t_vpi_value*vp);
|
||||
|
||||
private:
|
||||
unsigned context_idx_;
|
||||
};
|
||||
|
||||
|
||||
/* vvp_wire
|
||||
* The vvp_wire is different from vvp_variable objects in that it
|
||||
* exists only as a filter. The vvp_wire class tree is for
|
||||
* implementing verilog wires/nets (as opposed to regs/variables).
|
||||
*/
|
||||
|
||||
class vvp_wire_base : public vvp_net_fil_t, public vvp_signal_value {
|
||||
|
||||
public:
|
||||
vvp_wire_base();
|
||||
~vvp_wire_base();
|
||||
};
|
||||
|
||||
class vvp_wire_vec4 : public vvp_wire_base {
|
||||
|
||||
public:
|
||||
vvp_wire_vec4(unsigned wid, vvp_bit4_t init);
|
||||
|
||||
// The main filter behavior for this class. These methods take
|
||||
// the value that the node is driven to, and applies the firce
|
||||
// filters. In wires, this also saves the driven value, so
|
||||
// that when a force is released, we can revert to the driven value.
|
||||
prop_t filter_vec4(const vvp_vector4_t&bit, vvp_vector4_t&rep,
|
||||
unsigned base, unsigned vwid);
|
||||
prop_t filter_vec8(const vvp_vector8_t&val, vvp_vector8_t&rep,
|
||||
unsigned base, unsigned vwid);
|
||||
|
||||
// Abstract methods from vvp_vpi_callback
|
||||
void get_value(struct t_vpi_value*value);
|
||||
// Abstract methods from vvp_net_fit_t
|
||||
unsigned filter_size() const;
|
||||
void force_fil_vec4(const vvp_vector4_t&val, vvp_vector2_t mask);
|
||||
void force_fil_vec8(const vvp_vector8_t&val, vvp_vector2_t mask);
|
||||
void force_fil_real(double val, vvp_vector2_t mask);
|
||||
void release(vvp_net_ptr_t ptr, bool net_flag);
|
||||
void release_pv(vvp_net_ptr_t ptr, unsigned base, unsigned wid, bool net_flag);
|
||||
|
||||
// Implementation of vvp_signal_value methods
|
||||
unsigned value_size() const;
|
||||
vvp_bit4_t value(unsigned idx) const;
|
||||
vvp_scalar_t scalar_value(unsigned idx) const;
|
||||
vvp_vector4_t vec4_value() const;
|
||||
|
||||
private:
|
||||
vvp_bit4_t filtered_value_(unsigned idx) const;
|
||||
|
||||
private:
|
||||
bool needs_init_;
|
||||
vvp_vector4_t bits4_; // The tracked driven value
|
||||
vvp_vector4_t force4_; // the value being forced
|
||||
};
|
||||
|
||||
class vvp_wire_vec8 : public vvp_wire_base {
|
||||
|
||||
public:
|
||||
vvp_wire_vec8(unsigned wid);
|
||||
|
||||
// The main filter behavior for this class
|
||||
prop_t filter_vec4(const vvp_vector4_t&bit, vvp_vector4_t&rep,
|
||||
unsigned base, unsigned vwid);
|
||||
prop_t filter_vec8(const vvp_vector8_t&val, vvp_vector8_t&rep,
|
||||
unsigned base, unsigned vwid);
|
||||
|
||||
// Abstract methods from vvp_vpi_callback
|
||||
void get_value(struct t_vpi_value*value);
|
||||
// Abstract methods from vvp_net_fit_t
|
||||
unsigned filter_size() const;
|
||||
void force_fil_vec4(const vvp_vector4_t&val, vvp_vector2_t mask);
|
||||
void force_fil_vec8(const vvp_vector8_t&val, vvp_vector2_t mask);
|
||||
void force_fil_real(double val, vvp_vector2_t mask);
|
||||
void release(vvp_net_ptr_t ptr, bool net_flag);
|
||||
void release_pv(vvp_net_ptr_t ptr, unsigned base, unsigned wid, bool net_flag);
|
||||
|
||||
// Implementation of vvp_signal_value methods
|
||||
unsigned value_size() const;
|
||||
vvp_bit4_t value(unsigned idx) const;
|
||||
vvp_scalar_t scalar_value(unsigned idx) const;
|
||||
vvp_vector4_t vec4_value() const;
|
||||
// This is new to vvp_wire_vec8
|
||||
vvp_vector8_t vec8_value() const;
|
||||
|
||||
private:
|
||||
vvp_scalar_t filtered_value_(unsigned idx) const;
|
||||
|
||||
private:
|
||||
bool needs_init_;
|
||||
vvp_vector8_t bits8_;
|
||||
vvp_vector8_t force8_; // the value being forced
|
||||
};
|
||||
|
||||
class vvp_wire_real : public vvp_wire_base {
|
||||
|
||||
public:
|
||||
explicit vvp_wire_real(void);
|
||||
|
||||
// The main filter behavior for this class
|
||||
prop_t filter_real(double&bit);
|
||||
|
||||
// Abstract methods from vvp_vpi_callback
|
||||
void get_value(struct t_vpi_value*value);
|
||||
// Abstract methods from vvp_net_fit_t
|
||||
unsigned filter_size() const;
|
||||
void force_fil_vec4(const vvp_vector4_t&val, vvp_vector2_t mask);
|
||||
void force_fil_vec8(const vvp_vector8_t&val, vvp_vector2_t mask);
|
||||
void force_fil_real(double val, vvp_vector2_t mask);
|
||||
void release(vvp_net_ptr_t ptr, bool net_flag);
|
||||
void release_pv(vvp_net_ptr_t ptr, unsigned base, unsigned wid, bool net_flag);
|
||||
|
||||
// Implementation of vvp_signal_value methods
|
||||
unsigned value_size() const;
|
||||
vvp_bit4_t value(unsigned idx) const;
|
||||
vvp_scalar_t scalar_value(unsigned idx) const;
|
||||
vvp_vector4_t vec4_value() const;
|
||||
double real_value() const;
|
||||
|
||||
void get_signal_value(struct t_vpi_value*vp);
|
||||
|
||||
private:
|
||||
double bit_;
|
||||
double force_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
#ifndef __vvp_vpi_callback_H
|
||||
#define __vvp_vpi_callback_H
|
||||
/*
|
||||
* Copyright (c) 2009 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
# include "config.h"
|
||||
# include "vpi_user.h"
|
||||
|
||||
/*
|
||||
* Things derived from vvp_vpi_callback may have callbacks
|
||||
* attached. This is how vpi callbacks are attached to the vvp
|
||||
* structure.
|
||||
*
|
||||
* Things derived from vvp_vpi_callback may also be array'ed, so it
|
||||
* includes some members that arrays use.
|
||||
*/
|
||||
class vvp_vpi_callback {
|
||||
|
||||
public:
|
||||
vvp_vpi_callback();
|
||||
virtual ~vvp_vpi_callback();
|
||||
|
||||
void attach_as_word(class __vpiArray* arr, unsigned long addr);
|
||||
|
||||
void add_vpi_callback(struct __vpiCallback*);
|
||||
#ifdef CHECK_WITH_VALGRIND
|
||||
/* This has only been tested at EOS. */
|
||||
void clear_all_callbacks(void);
|
||||
#endif
|
||||
|
||||
// Derived classes implement this method to provide a way for
|
||||
// vpi to get at the vvp value of the object.
|
||||
virtual void get_value(struct t_vpi_value*value) =0;
|
||||
|
||||
protected:
|
||||
// Derived classes call this method to indicate that it is
|
||||
// time to call the callback.
|
||||
void run_vpi_callbacks();
|
||||
|
||||
private:
|
||||
struct __vpiCallback*vpi_callbacks_;
|
||||
class __vpiArray* array_;
|
||||
unsigned long array_word_;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
368
vvp/words.cc
368
vvp/words.cc
|
|
@ -20,6 +20,8 @@
|
|||
# include "compile.h"
|
||||
# include "vpi_priv.h"
|
||||
# include "array.h"
|
||||
# include "vvp_net_sig.h"
|
||||
# include "logic.h"
|
||||
# include "schedule.h"
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
|
|
@ -34,14 +36,16 @@ static void __compile_var_real(char*label, char*name,
|
|||
vvp_array_t array, unsigned long array_addr,
|
||||
int msb, int lsb)
|
||||
{
|
||||
vvp_fun_signal_real*fun;
|
||||
if (vpip_peek_current_scope()->is_automatic) {
|
||||
fun = new vvp_fun_signal_real_aa;
|
||||
} else {
|
||||
fun = new vvp_fun_signal_real_sa;
|
||||
}
|
||||
vvp_net_t*net = new vvp_net_t;
|
||||
net->fun = fun;
|
||||
|
||||
if (vpip_peek_current_scope()->is_automatic) {
|
||||
vvp_fun_signal_real_aa*tmp = new vvp_fun_signal_real_aa;
|
||||
net->fil = tmp;
|
||||
net->fun = tmp;
|
||||
} else {
|
||||
net->fil = new vvp_wire_real;
|
||||
net->fun = new vvp_fun_signal_real_sa;
|
||||
}
|
||||
|
||||
define_functor_symbol(label, net);
|
||||
|
||||
|
|
@ -52,7 +56,7 @@ static void __compile_var_real(char*label, char*name,
|
|||
assert(!array);
|
||||
vpip_attach_to_current_scope(obj);
|
||||
if (!vpip_peek_current_scope()->is_automatic)
|
||||
schedule_init_vector(vvp_net_ptr_t(net,0), fun->real_value());
|
||||
schedule_init_vector(vvp_net_ptr_t(net,0), 0.0);
|
||||
}
|
||||
if (array) {
|
||||
assert(!name);
|
||||
|
|
@ -84,23 +88,26 @@ static void __compile_var(char*label, char*name,
|
|||
{
|
||||
unsigned wid = ((msb > lsb)? msb-lsb : lsb-msb) + 1;
|
||||
|
||||
vvp_fun_signal_vec*vsig;
|
||||
if (vpip_peek_current_scope()->is_automatic) {
|
||||
vsig = new vvp_fun_signal4_aa(wid);
|
||||
} else {
|
||||
vsig = new vvp_fun_signal4_sa(wid);
|
||||
}
|
||||
vvp_net_t*node = new vvp_net_t;
|
||||
node->fun = vsig;
|
||||
vvp_net_t*net = new vvp_net_t;
|
||||
|
||||
define_functor_symbol(label, node);
|
||||
if (vpip_peek_current_scope()->is_automatic) {
|
||||
vvp_fun_signal4_aa*tmp = new vvp_fun_signal4_aa(wid);
|
||||
net->fil = tmp;
|
||||
net->fun = tmp;
|
||||
} else {
|
||||
net->fil = new vvp_wire_vec4(wid, BIT4_X);
|
||||
net->fun = new vvp_fun_signal4_sa(wid);
|
||||
}
|
||||
vvp_signal_value*vfil = dynamic_cast<vvp_signal_value*>(net->fil);
|
||||
|
||||
define_functor_symbol(label, net);
|
||||
|
||||
vpiHandle obj = 0;
|
||||
if (! local_flag && !array) {
|
||||
/* Make the vpiHandle for the reg. */
|
||||
obj = (signed_flag > 1) ?
|
||||
vpip_make_int(name, msb, lsb, node) :
|
||||
vpip_make_reg(name, msb, lsb, signed_flag!=0, node);
|
||||
vpip_make_int(name, msb, lsb, net) :
|
||||
vpip_make_reg(name, msb, lsb, signed_flag!=0, net);
|
||||
compile_vpi_symbol(label, obj);
|
||||
}
|
||||
// If the signal has a name, then it goes into the current
|
||||
|
|
@ -109,7 +116,7 @@ static void __compile_var(char*label, char*name,
|
|||
assert(!array);
|
||||
if (obj) vpip_attach_to_current_scope(obj);
|
||||
if (!vpip_peek_current_scope()->is_automatic)
|
||||
schedule_init_vector(vvp_net_ptr_t(node,0), vsig->vec4_value());
|
||||
schedule_init_vector(vvp_net_ptr_t(net,0), vfil->vec4_value());
|
||||
}
|
||||
// If this is an array word, then it does not have a name, and
|
||||
// it is attached to the addressed array.
|
||||
|
|
@ -142,65 +149,176 @@ void compile_variablew(char*label, vvp_array_t array,
|
|||
__compile_var(label, 0, array, array_addr, msb, lsb, signed_flag, false);
|
||||
}
|
||||
|
||||
vvp_net_t* create_constant_node(const char*label, const char*val_str)
|
||||
{
|
||||
if (c4string_test(val_str)) {
|
||||
vvp_net_t*net = new vvp_net_t;
|
||||
net->fun = new vvp_fun_bufz;
|
||||
schedule_init_vector(vvp_net_ptr_t(net,0), c4string_to_vector4(val_str));
|
||||
return net;
|
||||
}
|
||||
|
||||
if (c8string_test(val_str)) {
|
||||
vvp_net_t*net = new vvp_net_t;
|
||||
net->fun = new vvp_fun_bufz;
|
||||
schedule_init_vector(vvp_net_ptr_t(net,0), c8string_to_vector8(val_str));
|
||||
return net;
|
||||
}
|
||||
|
||||
if (crstring_test(val_str)) {
|
||||
vvp_net_t*net = new vvp_net_t;
|
||||
net->fun = new vvp_fun_bufz;
|
||||
schedule_init_vector(vvp_net_ptr_t(net,0), crstring_to_double(val_str));
|
||||
return net;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
class base_net_resolv : public resolv_list_s {
|
||||
public:
|
||||
explicit base_net_resolv(char*ref_label, vvp_array_t array,
|
||||
char*my_label, char*name,
|
||||
unsigned array_addr, bool local_flag)
|
||||
: resolv_list_s(ref_label)
|
||||
{ my_label_ = my_label;
|
||||
array_ = array;
|
||||
name_ = name;
|
||||
array_addr_ = array_addr;
|
||||
local_flag_ = local_flag;
|
||||
}
|
||||
|
||||
protected:
|
||||
char*my_label_;
|
||||
vvp_array_t array_;
|
||||
char*name_;
|
||||
unsigned array_addr_;
|
||||
bool local_flag_;
|
||||
};
|
||||
|
||||
class __compile_net_resolv : public base_net_resolv {
|
||||
|
||||
public:
|
||||
explicit __compile_net_resolv(char*ref_label, vvp_array_t array,
|
||||
char*my_label, char*name,
|
||||
int msb, int lsb, unsigned array_addr,
|
||||
bool signed_flag, bool net8_flag, bool local_flag)
|
||||
: base_net_resolv(ref_label, array, my_label, name, array_addr, local_flag)
|
||||
{ msb_ = msb;
|
||||
lsb_ = lsb;
|
||||
signed_flag_ = signed_flag;
|
||||
}
|
||||
|
||||
~__compile_net_resolv() { }
|
||||
|
||||
bool resolve(bool message_flag);
|
||||
|
||||
private:
|
||||
int msb_, lsb_;
|
||||
bool signed_flag_, net8_flag_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Here we handle .net records from the vvp source:
|
||||
*
|
||||
* <label> .net <name>, <msb>, <lsb>, <input> ;
|
||||
* <label> .net/s <name>, <msb>, <lsb>, <input> ;
|
||||
* <label> .net8 <name>, <msb>, <lsb>, <input> ;
|
||||
* <label> .net8/s <name>, <msb>, <lsb>, <input> ;
|
||||
* .net <name>, <msb>, <lsb>, <input> ;
|
||||
* .net/s <name>, <msb>, <lsb>, <input> ;
|
||||
* .net8 <name>, <msb>, <lsb>, <input> ;
|
||||
* .net8/s <name>, <msb>, <lsb>, <input> ;
|
||||
*
|
||||
* Create a VPI handle to represent it, and fill that handle in with
|
||||
* references into the net.
|
||||
*/
|
||||
static void __compile_net(char*label, char*name,
|
||||
char*array_label, unsigned long array_addr,
|
||||
int msb, int lsb,
|
||||
bool signed_flag, bool net8_flag, bool local_flag,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
|
||||
static void __compile_net2(vvp_net_t*node, vvp_array_t array,
|
||||
char*my_label, char*name,
|
||||
int msb, int lsb, unsigned array_addr,
|
||||
bool signed_flag, bool net8_flag, bool local_flag)
|
||||
{
|
||||
unsigned wid = ((msb > lsb)? msb-lsb : lsb-msb) + 1;
|
||||
assert(node);
|
||||
|
||||
vvp_net_t*node = new vvp_net_t;
|
||||
vvp_wire_base*vsig = dynamic_cast<vvp_wire_base*>(node->fil);
|
||||
|
||||
vvp_array_t array = array_label ? array_find(array_label) : 0;
|
||||
assert(array_label ? array!=0 : true);
|
||||
if (vsig == 0) {
|
||||
vsig = net8_flag
|
||||
? dynamic_cast<vvp_wire_base*>(new vvp_wire_vec8(wid))
|
||||
: dynamic_cast<vvp_wire_base*>(new vvp_wire_vec4(wid,BIT4_Z));
|
||||
|
||||
vvp_fun_signal_base*vsig = net8_flag
|
||||
? dynamic_cast<vvp_fun_signal_base*>(new vvp_fun_signal8(wid))
|
||||
: dynamic_cast<vvp_fun_signal_base*>(new vvp_fun_signal4_sa(wid,BIT4_Z));
|
||||
node->fun = vsig;
|
||||
|
||||
/* Add the label into the functor symbol table. */
|
||||
define_functor_symbol(label, node);
|
||||
|
||||
assert(argc == 1);
|
||||
|
||||
/* Connect the source to my input. */
|
||||
inputs_connect(node, 1, argv);
|
||||
node->fil = vsig;
|
||||
}
|
||||
|
||||
vpiHandle obj = 0;
|
||||
if (! local_flag) {
|
||||
/* Make the vpiHandle for the reg. */
|
||||
obj = vpip_make_net(name, msb, lsb, signed_flag, node);
|
||||
/* This attaches the label to the vpiHandle */
|
||||
compile_vpi_symbol(label, obj);
|
||||
compile_vpi_symbol(my_label, obj);
|
||||
}
|
||||
/* If this is an array word, then attach it to the
|
||||
array. Otherwise, attach it to the current scope. */
|
||||
|
||||
// REMOVE ME! Giving the net a label is a legacy of the times
|
||||
// when the .net was a functor of its own. In the long run, we
|
||||
// must fix the code generator to not rely on the label of the
|
||||
// .net, then we will remove that label.
|
||||
define_functor_symbol(my_label, node);
|
||||
|
||||
if (array)
|
||||
array_attach_word(array, array_addr, obj);
|
||||
else if (obj)
|
||||
vpip_attach_to_current_scope(obj);
|
||||
|
||||
free(label);
|
||||
free(my_label);
|
||||
if (name) delete[] name;
|
||||
}
|
||||
|
||||
static void __compile_net(char*label,
|
||||
char*name, char*array_label, unsigned long array_addr,
|
||||
int msb, int lsb,
|
||||
bool signed_flag, bool net8_flag, bool local_flag,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
vvp_array_t array = array_label? array_find(array_label) : 0;
|
||||
assert(array_label ? array!=0 : true);
|
||||
|
||||
if (array_label) free(array_label);
|
||||
|
||||
assert(argc == 1);
|
||||
vvp_net_t*node = vvp_net_lookup(argv[0].text);
|
||||
if (node == 0) {
|
||||
/* No existing net, but the string value may be a
|
||||
constant. In that case, we will wind up generating a
|
||||
bufz node that can carry the constant value. */
|
||||
node = create_constant_node(label, argv[0].text);
|
||||
}
|
||||
if (node == 0) {
|
||||
__compile_net_resolv*res
|
||||
= new __compile_net_resolv(argv[0].text,
|
||||
array, label, name,
|
||||
msb, lsb, array_addr,
|
||||
signed_flag, net8_flag, local_flag);
|
||||
resolv_submit(res);
|
||||
return;
|
||||
}
|
||||
assert(node);
|
||||
|
||||
__compile_net2(node, array, label, name, msb, lsb, array_addr,
|
||||
signed_flag, net8_flag, local_flag);
|
||||
|
||||
free(argv);
|
||||
}
|
||||
|
||||
void compile_net(char*label, char*name,
|
||||
int msb, int lsb,
|
||||
bool __compile_net_resolv::resolve(bool msg_flag)
|
||||
{
|
||||
vvp_net_t*node = vvp_net_lookup(label());
|
||||
if (node == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
__compile_net2(node, array_, my_label_, name_, msb_, lsb_, array_addr_, signed_flag_, net8_flag_, local_flag_);
|
||||
return true;
|
||||
}
|
||||
|
||||
void compile_net(char*label, char*name, int msb, int lsb,
|
||||
bool signed_flag, bool net8_flag, bool local_flag,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
|
|
@ -219,44 +337,98 @@ void compile_netw(char*label, char*array_label, unsigned long array_addr,
|
|||
argc, argv);
|
||||
}
|
||||
|
||||
|
||||
class __compile_real_net_resolv : public base_net_resolv {
|
||||
|
||||
public:
|
||||
explicit __compile_real_net_resolv(char*ref_label, vvp_array_t array,
|
||||
char*my_label, char*name,
|
||||
unsigned array_addr, bool local_flag)
|
||||
: base_net_resolv(ref_label, array, my_label, name, array_addr, local_flag)
|
||||
{
|
||||
}
|
||||
|
||||
~__compile_real_net_resolv() { }
|
||||
|
||||
bool resolve(bool message_flag);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
static void __compile_real_net2(vvp_net_t*node, vvp_array_t array,
|
||||
char*my_label, char*name,
|
||||
unsigned array_addr, bool local_flag)
|
||||
{
|
||||
vvp_wire_base*fil = dynamic_cast<vvp_wire_base*> (node->fil);
|
||||
|
||||
if (fil == 0) {
|
||||
fil = new vvp_wire_real;
|
||||
node->fil = fil;
|
||||
}
|
||||
|
||||
vpiHandle obj = 0;
|
||||
if (!local_flag) {
|
||||
obj = vpip_make_real_var(name, node);
|
||||
compile_vpi_symbol(my_label, obj);
|
||||
}
|
||||
|
||||
// REMOVE ME! Giving the net a label is a legacy of the times
|
||||
// when the .net was a functor of its own. In the long run, we
|
||||
// must fix the code generator to not rely on the label of the
|
||||
// .net, then we will remove that label.
|
||||
define_functor_symbol(my_label, node);
|
||||
|
||||
if (array)
|
||||
array_attach_word(array, array_addr, obj);
|
||||
else if (obj)
|
||||
vpip_attach_to_current_scope(obj);
|
||||
|
||||
free(my_label);
|
||||
if (name) delete[]name;
|
||||
}
|
||||
|
||||
static void __compile_real(char*label, char*name,
|
||||
char*array_label, unsigned long array_addr,
|
||||
int msb, int lsb, bool local_flag,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
vvp_net_t*net = new vvp_net_t;
|
||||
|
||||
vvp_array_t array = array_label ? array_find(array_label) : 0;
|
||||
assert(array_label ? array!=0 : true);
|
||||
|
||||
vvp_fun_signal_real*fun = new vvp_fun_signal_real_sa;
|
||||
net->fun = fun;
|
||||
|
||||
/* Add the label into the functor symbol table. */
|
||||
define_functor_symbol(label, net);
|
||||
if (array_label) free(array_label);
|
||||
|
||||
assert(argc == 1);
|
||||
|
||||
/* Connect the source to my input. */
|
||||
inputs_connect(net, 1, argv);
|
||||
|
||||
vpiHandle obj = 0;
|
||||
if (! local_flag) {
|
||||
/* Make the vpiHandle for the reg. */
|
||||
obj = vpip_make_real_var(name, net);
|
||||
/* This attaches the label to the vpiHandle */
|
||||
compile_vpi_symbol(label, obj);
|
||||
vvp_net_t*node = vvp_net_lookup(argv[0].text);
|
||||
if (node == 0) {
|
||||
/* No existing net, but the string value may be a
|
||||
constant. In that case, we will wind up generating a
|
||||
bufz node that can carry the constant value. */
|
||||
node = create_constant_node(label, argv[0].text);
|
||||
}
|
||||
/* If this is an array word, then attach it to the
|
||||
array. Otherwise, attach it to the current scope. */
|
||||
if (array)
|
||||
array_attach_word(array, array_addr, obj);
|
||||
else if (obj)
|
||||
vpip_attach_to_current_scope(obj);
|
||||
free(label);
|
||||
if (name) delete[] name;
|
||||
if (array_label) free(array_label);
|
||||
free(argv);
|
||||
if (node == 0) {
|
||||
__compile_real_net_resolv*res
|
||||
= new __compile_real_net_resolv(argv[0].text, array,
|
||||
label, name,
|
||||
array_addr, local_flag);
|
||||
resolv_submit(res);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(node);
|
||||
__compile_real_net2(node, array, label, name, array_addr, local_flag);
|
||||
}
|
||||
|
||||
bool __compile_real_net_resolv::resolve(bool msg_flag)
|
||||
{
|
||||
vvp_net_t*node = vvp_net_lookup(label());
|
||||
if (node == 0) {
|
||||
if (msg_flag)
|
||||
cerr << "Unable to resolve label " << label() << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
__compile_real_net2(node, array_, my_label_, name_, array_addr_, local_flag_);
|
||||
return true;
|
||||
}
|
||||
|
||||
void compile_net_real(char*label, char*name, int msb, int lsb, bool local_flag,
|
||||
|
|
@ -284,6 +456,7 @@ void compile_aliasw(char*label, char*array_label, unsigned long array_addr,
|
|||
vvp_net_t*node = vvp_net_lookup(argv[0].text);
|
||||
|
||||
/* Add the label into the functor symbol table. */
|
||||
assert(node);
|
||||
define_functor_symbol(label, node);
|
||||
|
||||
vpiHandle obj = vvp_lookup_handle(argv[0].text);
|
||||
|
|
@ -296,46 +469,19 @@ void compile_aliasw(char*label, char*array_label, unsigned long array_addr,
|
|||
free(argv);
|
||||
}
|
||||
|
||||
/*
|
||||
* The .alias is practically identical to a .net. We create all the
|
||||
* VPI stuff for the new name (and put it in the local scope) but
|
||||
* reference the node in the net.
|
||||
*/
|
||||
void compile_alias(char*label, char*name, int msb, int lsb, bool signed_flag,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
assert(argc == 1);
|
||||
|
||||
vvp_net_t*node = vvp_net_lookup(argv[0].text);
|
||||
|
||||
/* Add the label into the functor symbol table. */
|
||||
define_functor_symbol(label, node);
|
||||
|
||||
|
||||
/* Make the vpiHandle for the reg. */
|
||||
vpiHandle obj = vpip_make_net(name, msb, lsb, signed_flag, node);
|
||||
compile_vpi_symbol(label, obj);
|
||||
vpip_attach_to_current_scope(obj);
|
||||
|
||||
free(label);
|
||||
delete[] name;
|
||||
free(argv[0].text);
|
||||
free(argv);
|
||||
__compile_net(label, name, 0, 0, msb, lsb, signed_flag, false, false, argc, argv);
|
||||
}
|
||||
|
||||
void compile_alias_real(char*label, char*name, int msb, int lsb,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
assert(argc == 1);
|
||||
|
||||
vvp_net_t*node = vvp_net_lookup(argv[0].text);
|
||||
|
||||
/* Add the label into the functor symbol table. */
|
||||
define_functor_symbol(label, node);
|
||||
|
||||
|
||||
/* Make the vpiHandle for the reg. */
|
||||
vpiHandle obj = vpip_make_real_var(name, node);
|
||||
compile_vpi_symbol(label, obj);
|
||||
vpip_attach_to_current_scope(obj);
|
||||
|
||||
free(label);
|
||||
delete[] name;
|
||||
free(argv[0].text);
|
||||
free(argv);
|
||||
__compile_real(label, name, 0, 0, msb, lsb, false, argc, argv);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue