Force instruction that can be indexed.

This commit is contained in:
steve 2005-11-26 17:16:05 +00:00
parent 0e044d6684
commit 2b8fd28a95
6 changed files with 173 additions and 34 deletions

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: codes.h,v 1.76 2005/09/17 04:01:01 steve Exp $"
#ident "$Id: codes.h,v 1.77 2005/11/26 17:16:05 steve Exp $"
#endif
@ -73,6 +73,7 @@ extern bool of_DIV_WR(vthread_t thr, vvp_code_t code);
extern bool of_END(vthread_t thr, vvp_code_t code);
extern bool of_FORCE_LINK(vthread_t thr, vvp_code_t code);
extern bool of_FORCE_V(vthread_t thr, vvp_code_t code);
extern bool of_FORCE_X0(vthread_t thr, vvp_code_t code);
extern bool of_FORK(vthread_t thr, vvp_code_t code);
extern bool of_INV(vthread_t thr, vvp_code_t code);
extern bool of_IX_ADD(vthread_t thr, vvp_code_t code);
@ -178,6 +179,9 @@ extern vvp_code_t codespace_null(void);
/*
* $Log: codes.h,v $
* Revision 1.77 2005/11/26 17:16:05 steve
* Force instruction that can be indexed.
*
* Revision 1.76 2005/09/17 04:01:01 steve
* Add the load/v.p instruction.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: compile.cc,v 1.214 2005/10/12 17:23:15 steve Exp $"
#ident "$Id: compile.cc,v 1.215 2005/11/26 17:16:05 steve Exp $"
#endif
# include "arith.h"
@ -118,6 +118,7 @@ const static struct opcode_table_s opcode_table[] = {
{ "%end", of_END, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%force/link",of_FORCE_LINK,2,{OA_FUNC_PTR,OA_FUNC_PTR2,OA_NONE} },
{ "%force/v",of_FORCE_V,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
{ "%force/x0",of_FORCE_X0,3,{OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
{ "%inv", of_INV, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%ix/add", of_IX_ADD, 2, {OA_BIT1, OA_NUMBER, OA_NONE} },
{ "%ix/get", of_IX_GET, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
@ -1481,6 +1482,9 @@ void compile_param_string(char*label, char*name, char*str, char*value)
/*
* $Log: compile.cc,v $
* Revision 1.215 2005/11/26 17:16:05 steve
* Force instruction that can be indexed.
*
* Revision 1.214 2005/10/12 17:23:15 steve
* Add alias nodes.
*

View File

@ -1,7 +1,7 @@
/*
* Copyright (c) 2001-2003 Stephen Williams (steve@icarus.com)
*
* $Id: opcodes.txt,v 1.68 2005/09/19 21:45:37 steve Exp $
* $Id: opcodes.txt,v 1.69 2005/11/26 17:16:05 steve Exp $
*/
@ -263,6 +263,14 @@ functor instead of the normal assign port (port-0), so the signal
responds differently. See "VARIABLE STATEMENTS" and "NET STATEMENTS"
in the README.txt file.
* %force/x0 <label>, <bit>, <wid>
Force a constant value to part target variable. This is similar to
%set/x instruction, but it uses the force port (port-2) of the signal
functor instead of the normal assign port (port-0), so the signal
responds differently. See "VARIABLE STATEMENTS" and "NET STATEMENTS"
in the README.txt file.
* %fork <code-label>, <scope-label>
This instruction is similar to %jmp, except that it creates a new

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vthread.cc,v 1.149 2005/11/25 17:55:26 steve Exp $"
#ident "$Id: vthread.cc,v 1.150 2005/11/26 17:16:05 steve Exp $"
#endif
# include "config.h"
@ -1566,6 +1566,45 @@ bool of_FORCE_V(vthread_t thr, vvp_code_t cp)
return true;
}
bool of_FORCE_X0(vthread_t thr, vvp_code_t cp)
{
vvp_net_t*net = cp->net;
unsigned bit = cp->bit_idx[0];
unsigned wid = cp->bit_idx[1];
// Implicitly, we get the base into the target vector from the
// X0 register.
long index = thr->words[0].w_int;
vvp_fun_signal_vec*sig = dynamic_cast<vvp_fun_signal_vec*> (net->fun);
if (index < 0 && (wid <= (unsigned)-index))
return true;
if (index >= (long)sig->size())
return true;
if (index < 0) {
wid -= (unsigned) -index;
index = 0;
}
if (index+wid > sig->size())
wid = sig->size() - index;
vvp_vector4_t bit_vec(wid);
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
vvp_bit4_t bit_val = thr_get_bit(thr, bit);
bit_vec.set_bit(idx, bit_val);
if (bit >= 4)
bit += 1;
}
vvp_net_ptr_t ptr (net, 2);
vvp_send_vec4_pv(ptr, bit_vec, index, wid, sig->size());
return true;
}
/*
* The %fork instruction causes a new child to be created and pushed
* in front of any existing child. This causes the new child to be the
@ -2827,7 +2866,7 @@ bool of_SET_X0(vthread_t thr, vvp_code_t cp)
// X0 register.
long index = thr->words[0].w_int;
vvp_fun_signal*sig = dynamic_cast<vvp_fun_signal*> (net->fun);
vvp_fun_signal_vec*sig = dynamic_cast<vvp_fun_signal_vec*> (net->fun);
if (index < 0 && (wid <= (unsigned)-index))
return true;
@ -3189,6 +3228,9 @@ bool of_JOIN_UFUNC(vthread_t thr, vvp_code_t cp)
/*
* $Log: vthread.cc,v $
* Revision 1.150 2005/11/26 17:16:05 steve
* Force instruction that can be indexed.
*
* Revision 1.149 2005/11/25 17:55:26 steve
* Put vec8 and vec4 nets into seperate net classes.
*

View File

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ident "$Id: vvp_net.cc,v 1.48 2005/11/25 17:55:26 steve Exp $"
#ident "$Id: vvp_net.cc,v 1.49 2005/11/26 17:16:05 steve Exp $"
# include "config.h"
# include "vvp_net.h"
@ -632,6 +632,17 @@ vvp_vector2_t::vvp_vector2_t(unsigned long v, unsigned wid)
vec_[idx] = 0;
}
vvp_vector2_t::vvp_vector2_t(vvp_vector2_t::fill_t fill, unsigned wid)
{
wid_ = wid;
const unsigned bits_per_word = 8 * sizeof(vec_[0]);
const unsigned words = (wid_ + bits_per_word-1) / bits_per_word;
vec_ = new unsigned long[words];
for (unsigned idx = 0 ; idx < words ; idx += 1)
vec_[idx] = fill? -1 : 0;
}
vvp_vector2_t::vvp_vector2_t(const vvp_vector4_t&that)
{
wid_ = that.size();
@ -892,6 +903,20 @@ int vvp_vector2_t::value(unsigned idx) const
return 0;
}
void vvp_vector2_t::set_bit(unsigned idx, int bit)
{
assert(idx < wid_);
const unsigned bits_per_word = 8 * sizeof(vec_[0]);
unsigned addr = idx/bits_per_word;
unsigned long mask = idx%bits_per_word;
if (bit)
vec_[addr] |= 1UL << mask;
else
vec_[addr] &= ~(1UL << mask);
}
bool vvp_vector2_t::is_NaN() const
{
return wid_ == 0;
@ -1290,7 +1315,6 @@ vvp_fun_signal_base::vvp_fun_signal_base()
{
needs_init_ = true;
continuous_assign_active_ = false;
force_active_ = false;
force_link = 0;
}
@ -1350,12 +1374,15 @@ void vvp_fun_signal::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
{
switch (ptr.port()) {
case 0: // Normal input (feed from net, or set from process)
/* If continuous assign is active, then this is a var
and the continuous assigned values overrides any
normal input. So process input only if continuous
assignment is not active. */
if (!continuous_assign_active_) {
if (needs_init_ || !bits4_.eeq(bit)) {
bits4_ = bit;
needs_init_ = false;
vvp_send_vec4(ptr.ptr()->out, bit);
run_vpi_callbacks();
calculate_output_(ptr);
}
}
break;
@ -1363,8 +1390,7 @@ void vvp_fun_signal::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
case 1: // Continuous assign value
continuous_assign_active_ = true;
bits4_ = bit;
vvp_send_vec4(ptr.ptr()->out, bits4_);
run_vpi_callbacks();
calculate_output_(ptr);
break;
case 2: // Force value
@ -1376,9 +1402,8 @@ void vvp_fun_signal::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
else
force_ = bit;
force_active_ = true;
vvp_send_vec4(ptr.ptr()->out, force_);
run_vpi_callbacks();
force_mask_ = vvp_vector2_t(vvp_vector2_t::FILL1, size());
calculate_output_(ptr);
break;
default:
@ -1402,17 +1427,50 @@ void vvp_fun_signal::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
bits4_.set_bit(base+idx, bit.value(idx));
}
needs_init_ = false;
vvp_send_vec4(ptr.ptr()->out, bits4_);
run_vpi_callbacks();
calculate_output_(ptr);
}
break;
case 2: // Force value
if (force_mask_.size() == 0)
force_mask_ = vvp_vector2_t(vvp_vector2_t::FILL0, size());
if (force_.size() == 0)
force_ = vvp_vector4_t(vwid, BIT4_Z);
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
force_mask_.set_bit(base+idx, 1);
force_.set_bit(base+idx, bit.value(idx));
}
calculate_output_(ptr);
break;
default:
assert(0);
break;
}
}
void vvp_fun_signal::calculate_output_(vvp_net_ptr_t ptr)
{
if (force_mask_.size()) {
assert(bits4_.size() == force_mask_.size());
assert(bits4_.size() == force_.size());
vvp_vector4_t bits (bits4_);
for (unsigned idx = 0 ; idx < bits.size() ; idx += 1) {
if (force_mask_.value(idx))
bits.set_bit(idx, force_.value(idx));
}
vvp_send_vec4(ptr.ptr()->out, bits);
} else {
vvp_send_vec4(ptr.ptr()->out, bits4_);
}
run_vpi_callbacks();
}
void vvp_fun_signal::recv_vec8(vvp_net_ptr_t ptr, vvp_vector8_t bit)
{
recv_vec4(ptr, reduce4(bit));
@ -1421,7 +1479,7 @@ void vvp_fun_signal::recv_vec8(vvp_net_ptr_t ptr, vvp_vector8_t bit)
void vvp_fun_signal::release(vvp_net_ptr_t ptr, bool net)
{
force_active_ = false;
force_mask_ = vvp_vector2_t();
if (net) {
vvp_send_vec4(ptr.ptr()->out, bits4_);
run_vpi_callbacks();
@ -1432,7 +1490,7 @@ void vvp_fun_signal::release(vvp_net_ptr_t ptr, bool net)
unsigned vvp_fun_signal::size() const
{
if (force_active_)
if (force_mask_.size())
return force_.size();
else
return bits4_.size();
@ -1440,7 +1498,7 @@ unsigned vvp_fun_signal::size() const
vvp_bit4_t vvp_fun_signal::value(unsigned idx) const
{
if (force_active_)
if (force_mask_.size() && force_mask_.value(idx))
return force_.value(idx);
else
return bits4_.value(idx);
@ -1448,7 +1506,7 @@ vvp_bit4_t vvp_fun_signal::value(unsigned idx) const
vvp_scalar_t vvp_fun_signal::scalar_value(unsigned idx) const
{
if (force_active_)
if (force_mask_.size() && force_mask_.value(idx))
return vvp_scalar_t(force_.value(idx), 6, 6);
else
return vvp_scalar_t(bits4_.value(idx), 6, 6);
@ -1456,10 +1514,19 @@ vvp_scalar_t vvp_fun_signal::scalar_value(unsigned idx) const
vvp_vector4_t vvp_fun_signal::vec4_value() const
{
if (force_active_)
return force_;
else
if (force_mask_.size()) {
assert(bits4_.size() == force_mask_.size());
assert(bits4_.size() == force_.size());
vvp_vector4_t bits (bits4_);
for (unsigned idx = 0 ; idx < bits.size() ; idx += 1) {
if (force_mask_.value(idx))
bits.set_bit(idx, force_.value(idx));
}
return bits;
} else {
return bits4_;
}
}
vvp_fun_signal8::vvp_fun_signal8(unsigned wid)
@ -1502,7 +1569,7 @@ void vvp_fun_signal8::recv_vec8(vvp_net_ptr_t ptr, vvp_vector8_t bit)
else
force_ = bit;
force_active_ = true;
force_mask_ = vvp_vector2_t(vvp_vector2_t::FILL1, size());
vvp_send_vec8(ptr.ptr()->out, force_);
run_vpi_callbacks();
break;
@ -1515,7 +1582,7 @@ void vvp_fun_signal8::recv_vec8(vvp_net_ptr_t ptr, vvp_vector8_t bit)
void vvp_fun_signal8::release(vvp_net_ptr_t ptr, bool net)
{
force_active_ = false;
force_mask_ = vvp_vector2_t();
if (net) {
vvp_send_vec8(ptr.ptr()->out, bits8_);
run_vpi_callbacks();
@ -1526,7 +1593,7 @@ void vvp_fun_signal8::release(vvp_net_ptr_t ptr, bool net)
unsigned vvp_fun_signal8::size() const
{
if (force_active_)
if (force_mask_.size())
return force_.size();
else
return bits8_.size();
@ -1534,7 +1601,7 @@ unsigned vvp_fun_signal8::size() const
vvp_bit4_t vvp_fun_signal8::value(unsigned idx) const
{
if (force_active_)
if (force_mask_.size() && force_mask_.value(idx))
return force_.value(idx).value();
else
return bits8_.value(idx).value();
@ -1542,7 +1609,7 @@ vvp_bit4_t vvp_fun_signal8::value(unsigned idx) const
vvp_vector4_t vvp_fun_signal8::vec4_value() const
{
if (force_active_)
if (force_mask_.size())
return reduce4(force_);
else
return reduce4(bits8_);
@ -1550,7 +1617,7 @@ vvp_vector4_t vvp_fun_signal8::vec4_value() const
vvp_scalar_t vvp_fun_signal8::scalar_value(unsigned idx) const
{
if (force_active_)
if (force_mask_.size() && force_mask_.value(idx))
return force_.value(idx);
else
return bits8_.value(idx);
@ -1562,7 +1629,7 @@ vvp_fun_signal_real::vvp_fun_signal_real()
double vvp_fun_signal_real::real_value() const
{
if (force_active_)
if (force_mask_.size())
return force_;
else
return bits_;
@ -1590,7 +1657,7 @@ void vvp_fun_signal_real::recv_real(vvp_net_ptr_t ptr, double bit)
break;
case 2: // Force value
force_active_ = true;
force_mask_ = vvp_vector2_t(1, 1);
force_ = bit;
vvp_send_real(ptr.ptr()->out, bit);
run_vpi_callbacks();
@ -1604,7 +1671,7 @@ void vvp_fun_signal_real::recv_real(vvp_net_ptr_t ptr, double bit)
void vvp_fun_signal_real::release(vvp_net_ptr_t ptr, bool net)
{
force_active_ = false;
force_mask_ = vvp_vector2_t();
if (net) {
vvp_send_real(ptr.ptr()->out, bits_);
run_vpi_callbacks();
@ -2073,6 +2140,9 @@ vvp_bit4_t compare_gtge_signed(const vvp_vector4_t&a,
/*
* $Log: vvp_net.cc,v $
* Revision 1.49 2005/11/26 17:16:05 steve
* Force instruction that can be indexed.
*
* Revision 1.48 2005/11/25 17:55:26 steve
* Put vec8 and vec4 nets into seperate net classes.
*

View File

@ -18,7 +18,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ident "$Id: vvp_net.h,v 1.48 2005/11/25 17:55:26 steve Exp $"
#ident "$Id: vvp_net.h,v 1.49 2005/11/26 17:16:05 steve Exp $"
# include "config.h"
# include <stddef.h>
@ -276,6 +276,9 @@ class vvp_vector2_t {
explicit vvp_vector2_t(const vvp_vector4_t&that);
// Make from a native long and a specified width.
vvp_vector2_t(unsigned long val, unsigned wid);
// Make with the width, and filled with 1 or 0 bits.
enum fill_t {FILL0, FILL1};
vvp_vector2_t(fill_t fill, unsigned wid);
~vvp_vector2_t();
vvp_vector2_t&operator += (const vvp_vector2_t&that);
@ -287,6 +290,7 @@ class vvp_vector2_t {
bool is_NaN() const;
unsigned size() const;
int value(unsigned idx) const;
void set_bit(unsigned idx, int bit);
private:
enum { BITS_PER_WORD = 8 * sizeof(unsigned long) };
@ -777,7 +781,7 @@ class vvp_fun_signal_base : public vvp_net_fun_t, public vvp_vpi_callback {
// This is true until at least one propagation happens.
bool needs_init_;
bool continuous_assign_active_;
bool force_active_;
vvp_vector2_t force_mask_;
void deassign();
virtual void release(vvp_net_ptr_t ptr, bool net) =0;
@ -821,6 +825,8 @@ class vvp_fun_signal : public vvp_fun_signal_vec {
void get_value(struct t_vpi_value*value);
private:
void calculate_output_(vvp_net_ptr_t ptr);
vvp_vector4_t bits4_;
vvp_vector4_t force_;
};
@ -849,6 +855,8 @@ class vvp_fun_signal8 : public vvp_fun_signal_vec {
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_;
};
@ -997,6 +1005,9 @@ inline void vvp_send_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&val,
/*
* $Log: vvp_net.h,v $
* Revision 1.49 2005/11/26 17:16:05 steve
* Force instruction that can be indexed.
*
* Revision 1.48 2005/11/25 17:55:26 steve
* Put vec8 and vec4 nets into seperate net classes.
*