vvp support for dynamic arrays.

This words completely for single-dimension dynamic arrays of
32bit integers. These changes also act as a stub for other
target types.
This commit is contained in:
Stephen Williams 2012-07-21 17:33:10 -07:00
parent fdc92ea464
commit 94e217f02b
13 changed files with 205 additions and 27 deletions

View File

@ -3676,6 +3676,20 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
NetExpr*mux = elab_and_eval(des, scope, index_tail.msb, -1, need_const); NetExpr*mux = elab_and_eval(des, scope, index_tail.msb, -1, need_const);
if (netdarray_t*darray = net->sig()->darray_type()) {
// Special case: This is a select of a dynamic
// array. Generate a NetESelect and attach it to
// the NetESignal. This should be interpreted as
// an array word select downstream.
if (debug_elaborate) {
cerr << get_fileline() << ": debug: "
<< "Bit select of a dynamic array becomes NetESelect." << endl;
}
NetESelect*res = new NetESelect(net, mux, darray->vector_width());
res->set_line(*net);
return res;
}
// If the bit select is constant, then treat it similar // If the bit select is constant, then treat it similar
// to the part select, so that I save the effort of // to the part select, so that I save the effort of
// making a mux part in the netlist. // making a mux part in the netlist.
@ -3754,20 +3768,6 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
return res; return res;
} }
if (netdarray_t*darray = net->sig()->darray_type()) {
// Special case: This is a select of a dynamic
// array. Generate a NetESelect ant attach it to
// the NetESignal. This should be interpreted as
// an array word select downstream.
if (debug_elaborate) {
cerr << get_fileline() << ": debug: "
<< "Bit select of a dynamic array becomes NetESelect." << endl;
}
NetESelect*res = new NetESelect(net, mux, darray->vector_width());
res->set_line(*net);
return res;
}
long idx = net->sig()->sb_to_idx(prefix_indices,msv); long idx = net->sig()->sb_to_idx(prefix_indices,msv);
if (idx >= (long)net->vector_width() || idx < 0) { if (idx >= (long)net->vector_width() || idx < 0) {

View File

@ -2447,6 +2447,9 @@ long NetESignal::msi() const
ivl_variable_type_t NetESignal::expr_type() const ivl_variable_type_t NetESignal::expr_type() const
{ {
if (net_->darray_type())
return IVL_VT_DARRAY;
else
return net_->data_type(); return net_->data_type();
} }

View File

@ -209,6 +209,7 @@ static void show_signal_expression(ivl_expr_t net, unsigned ind)
ivl_expr_t word = ivl_expr_oper1(net); ivl_expr_t word = ivl_expr_oper1(net);
ivl_signal_t sig = ivl_expr_signal(net); ivl_signal_t sig = ivl_expr_signal(net);
const char*vt_sig = data_type_string(ivl_signal_data_type(sig));
unsigned dimensions = ivl_signal_dimensions(sig); unsigned dimensions = ivl_signal_dimensions(sig);
unsigned word_count = ivl_signal_array_count(sig); unsigned word_count = ivl_signal_array_count(sig);
@ -218,8 +219,8 @@ static void show_signal_expression(ivl_expr_t net, unsigned ind)
stub_errors += 1; stub_errors += 1;
} }
fprintf(out, "%*s<signal=%s, words=%u, width=%u, %s type=%s>\n", ind, "", fprintf(out, "%*s<signal=%s, words=%u, width=%u, %s type=%s (%s)>\n", ind, "",
ivl_expr_name(net), word_count, width, sign, vt); ivl_expr_name(net), word_count, width, sign, vt, vt_sig);
/* If the expression refers to a signal array, then there must /* If the expression refers to a signal array, then there must
also be a word select expression, and if the signal is not an also be a word select expression, and if the signal is not an

View File

@ -187,6 +187,12 @@ static int get_vpi_taskfunc_signal_arg(struct args_info *result,
if (ivl_expr_value(vexpr) == IVL_VT_STRING) if (ivl_expr_value(vexpr) == IVL_VT_STRING)
return 0; return 0;
/* If the sub-expression is a DARRAY, then this select
is a dynamic-array word select. Handle that
elsewhere. */
if (ivl_expr_value(vexpr) == IVL_VT_DARRAY)
return 0;
/* The signal is part of an array. */ /* The signal is part of an array. */
/* Add &APV<> code here when it is finished. */ /* Add &APV<> code here when it is finished. */
bexpr = ivl_expr_oper2(expr); bexpr = ivl_expr_oper2(expr);

View File

@ -2812,6 +2812,19 @@ static struct vector_info draw_select_expr(ivl_expr_t expr, unsigned wid,
return res; return res;
} }
/* Special case: The sub-expression is a DARRAY variable, so
do a dynamic array word load. */
if (ivl_expr_value(sube) == IVL_VT_DARRAY) {
ivl_signal_t sig = ivl_expr_signal(sube);
assert(sig);
res.base = allocate_vector(wid);
res.wid = wid;
draw_eval_expr_into_integer(shift, 3);
fprintf(vvp_out, " %%load/dar %u, v%p_0, %u;\n",
res.base, sig, res.wid);
return res;
}
if (ivl_expr_type(sube) == IVL_EX_SIGNAL) { if (ivl_expr_type(sube) == IVL_EX_SIGNAL) {
res = draw_select_signal(expr, sube, shift, ivl_expr_width(expr), res = draw_select_signal(expr, sube, shift, ivl_expr_width(expr),
wid); wid);

View File

@ -28,7 +28,8 @@ static int eval_darray_new(ivl_expr_t ex)
draw_eval_expr_into_integer(size_expr, size_reg); draw_eval_expr_into_integer(size_expr, size_reg);
clr_word(size_reg); clr_word(size_reg);
fprintf(vvp_out, " %%new/darray %u;\n", size_reg); // XXXX: Assume elements are 32bit integers.
fprintf(vvp_out, " %%new/darray %u, \"sb32\";\n", size_reg);
return 0; return 0;
} }

View File

@ -773,14 +773,30 @@ static int show_stmt_assign_sig_darray(ivl_statement_t net)
ivl_expr_t rval = ivl_stmt_rval(net); ivl_expr_t rval = ivl_stmt_rval(net);
ivl_expr_t part = ivl_lval_part_off(lval); ivl_expr_t part = ivl_lval_part_off(lval);
ivl_signal_t var= ivl_lval_sig(lval); ivl_signal_t var= ivl_lval_sig(lval);
ivl_expr_t mux = ivl_lval_idx(lval);
assert(ivl_stmt_lvals(net) == 1); assert(ivl_stmt_lvals(net) == 1);
assert(ivl_stmt_opcode(net) == 0); assert(ivl_stmt_opcode(net) == 0);
assert(ivl_lval_mux(lval) == 0); assert(ivl_lval_mux(lval) == 0);
assert(part == 0); assert(part == 0);
if (mux) {
struct vector_info rvec = draw_eval_expr_wid(rval, ivl_lval_width(lval),
STUFF_OK_XZ);
/* The %set/dar expects the array index to be in index
register 3. Calculate the index in place. */
draw_eval_expr_into_integer(mux, 3);
fprintf(vvp_out, " %%set/dar v%p_0, %u, %u;\n",
var, rvec.base, rvec.wid);
if (rvec.base >= 4) clr_vector(rvec);
} else {
errors += draw_eval_object(rval); errors += draw_eval_object(rval);
fprintf(vvp_out, " %%store/obj v%p_0;\n", var); fprintf(vvp_out, " %%store/obj v%p_0;\n", var);
}
return errors; return errors;
} }

View File

@ -125,6 +125,7 @@ extern bool of_LOAD_AV(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_AVP0(vthread_t thr, vvp_code_t code); extern bool of_LOAD_AVP0(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_AVP0_S(vthread_t thr, vvp_code_t code); extern bool of_LOAD_AVP0_S(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_AVX_P(vthread_t thr, vvp_code_t code); extern bool of_LOAD_AVX_P(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_DAR(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_STR(vthread_t thr, vvp_code_t code); extern bool of_LOAD_STR(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_VEC(vthread_t thr, vvp_code_t code); extern bool of_LOAD_VEC(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_VP0(vthread_t thr, vvp_code_t code); extern bool of_LOAD_VP0(vthread_t thr, vvp_code_t code);
@ -163,6 +164,7 @@ extern bool of_RELEASE_REG(vthread_t thr, vvp_code_t code);
extern bool of_RELEASE_WR(vthread_t thr, vvp_code_t code); extern bool of_RELEASE_WR(vthread_t thr, vvp_code_t code);
extern bool of_SET_AR(vthread_t thr, vvp_code_t code); extern bool of_SET_AR(vthread_t thr, vvp_code_t code);
extern bool of_SET_AV(vthread_t thr, vvp_code_t code); extern bool of_SET_AV(vthread_t thr, vvp_code_t code);
extern bool of_SET_DAR(vthread_t thr, vvp_code_t code);
extern bool of_SET_VEC(vthread_t thr, vvp_code_t code); extern bool of_SET_VEC(vthread_t thr, vvp_code_t code);
extern bool of_SET_WORDR(vthread_t thr, vvp_code_t code); extern bool of_SET_WORDR(vthread_t thr, vvp_code_t code);
extern bool of_SET_X0(vthread_t thr, vvp_code_t code); extern bool of_SET_X0(vthread_t thr, vvp_code_t code);

View File

@ -173,6 +173,7 @@ static const struct opcode_table_s opcode_table[] = {
{ "%load/avp0",of_LOAD_AVP0,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} }, { "%load/avp0",of_LOAD_AVP0,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} },
{ "%load/avp0/s",of_LOAD_AVP0_S,3,{OA_BIT1, OA_ARR_PTR, OA_BIT2} }, { "%load/avp0/s",of_LOAD_AVP0_S,3,{OA_BIT1, OA_ARR_PTR, OA_BIT2} },
{ "%load/avx.p",of_LOAD_AVX_P,3,{OA_BIT1, OA_ARR_PTR, OA_BIT2} }, { "%load/avx.p",of_LOAD_AVX_P,3,{OA_BIT1, OA_ARR_PTR, OA_BIT2} },
{ "%load/dar",of_LOAD_DAR,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
{ "%load/str",of_LOAD_STR,1,{OA_FUNC_PTR, OA_NONE, OA_NONE} }, { "%load/str",of_LOAD_STR,1,{OA_FUNC_PTR, OA_NONE, OA_NONE} },
{ "%load/v", of_LOAD_VEC,3, {OA_BIT1, OA_FUNC_PTR, OA_BIT2} }, { "%load/v", of_LOAD_VEC,3, {OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
{ "%load/vp0",of_LOAD_VP0,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} }, { "%load/vp0",of_LOAD_VP0,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
@ -192,7 +193,7 @@ static const struct opcode_table_s opcode_table[] = {
{ "%muli", of_MULI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%muli", of_MULI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%nand", of_NAND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%nand", of_NAND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%nand/r", of_NANDR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%nand/r", of_NANDR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%new/darray",of_NEW_DARRAY,1,{OA_NUMBER,OA_NONE, OA_NONE} }, { "%new/darray",of_NEW_DARRAY,2,{OA_BIT1, OA_STRING, OA_NONE} },
{ "%noop", of_NOOP, 0, {OA_NONE, OA_NONE, OA_NONE} }, { "%noop", of_NOOP, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%nor", of_NOR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%nor", of_NOR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%nor/r", of_NORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%nor/r", of_NORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
@ -211,6 +212,7 @@ static const struct opcode_table_s opcode_table[] = {
{ "%release/wr",of_RELEASE_WR,2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} }, { "%release/wr",of_RELEASE_WR,2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} },
{ "%set/ar", of_SET_AR, 3, {OA_ARR_PTR, OA_BIT1, OA_BIT2} }, { "%set/ar", of_SET_AR, 3, {OA_ARR_PTR, OA_BIT1, OA_BIT2} },
{ "%set/av", of_SET_AV, 3, {OA_ARR_PTR, OA_BIT1, OA_BIT2} }, { "%set/av", of_SET_AV, 3, {OA_ARR_PTR, OA_BIT1, OA_BIT2} },
{ "%set/dar",of_SET_DAR,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
{ "%set/v", of_SET_VEC,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} }, { "%set/v", of_SET_VEC,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
{ "%set/wr", of_SET_WORDR,2,{OA_FUNC_PTR, OA_BIT1, OA_NONE} }, { "%set/wr", of_SET_WORDR,2,{OA_FUNC_PTR, OA_BIT1, OA_NONE} },
{ "%set/x0", of_SET_X0, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} }, { "%set/x0", of_SET_X0, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },

View File

@ -597,6 +597,15 @@ bit, and the <index> is the selector for the bit to use. If <index> is
out of range, then x is loaded. The index value is incremented by one out of range, then x is loaded. The index value is incremented by one
if it is defined (bit 4 is not 1). if it is defined (bit 4 is not 1).
* %load/dar <bit>, <functor-label>, <wid>
This instruction loads an array word from a dynamic array. The
<label> refers to the variable object, and the <bit>/<wid> are the
location in local vector space where the extracted word goes. The
index is implicitly extracted from index register 3.
(See also %set/dar)
* %load/v <bit>, <functor-label>, <wid> * %load/v <bit>, <functor-label>, <wid>
This instruction loads a vector value from the given functor node into This instruction loads a vector value from the given functor node into
@ -721,13 +730,16 @@ means the following:
otherwise x otherwise x
* %new/darray <idx> * %new/darray <idx>, "<type>"
Create a new array (of int objects) with a size. the <idx> is the Create a new array (of int objects) with a size. the <idx> is the
address of an index variable that contains the computed array size to address of an index variable that contains the computed array size to
use. See also %delete/obj use. The <type> is a string that expresses the type of the elements of
the array. See also %delete/obj
NOTE: For now, assume this is an array of int values. The supported types are:
"sb32" - signed bool 32bits
* %nor <dst>, <src>, <wid> * %nor <dst>, <src>, <wid>
@ -832,6 +844,12 @@ Release the force on the real signal that is represented by the functor
statement. The <type> is 0 for nets and 1 for registers. See the other statement. The <type> is 0 for nets and 1 for registers. See the other
%release commands above. %release commands above.
* %set/dar <var-label>, <bit>, <wid>
This sets a vector to a word of the dynamic array. Index register 3
contains the word address within the dynamic array, and <bit>,<wid>
specifies the thread vector to be written.
* %set/v <var-label>, <bit>, <wid> * %set/v <var-label>, <bit>, <wid>
This sets a vector to a variable, and is used to implement blocking This sets a vector to a variable, and is used to implement blocking

View File

@ -3098,6 +3098,32 @@ bool of_LOAD_AV(vthread_t thr, vvp_code_t cp)
return true; return true;
} }
/*
* %load/dar <bit>, <array-label>, <index>;
*/
bool of_LOAD_DAR(vthread_t thr, vvp_code_t cp)
{
unsigned bit = cp->bit_idx[0];
unsigned wid = cp->bit_idx[1];
unsigned adr = thr->words[3].w_int;
vvp_net_t*net = cp->net;
assert(net);
vvp_fun_signal_object*obj = dynamic_cast<vvp_fun_signal_object*> (net->fun);
assert(obj);
vvp_darray*darray = dynamic_cast<vvp_darray*>(obj->get_object());
assert(darray);
vvp_vector4_t word;
darray->get_word(adr, word);
assert(word.size() == wid);
thr->bits4.set_vec(bit, word);
return true;
}
/* /*
* %load/vp0, %load/vp0/s, %load/avp0 and %load/avp0/s share this function. * %load/vp0, %load/vp0/s, %load/avp0 and %load/avp0/s share this function.
*/ */
@ -3927,9 +3953,15 @@ bool of_NAND(vthread_t thr, vvp_code_t cp)
bool of_NEW_DARRAY(vthread_t thr, vvp_code_t cp) bool of_NEW_DARRAY(vthread_t thr, vvp_code_t cp)
{ {
size_t size = thr->words[cp->number].w_int; const char*text = cp->text;
size_t size = thr->words[cp->bit_idx[0]].w_int;
vvp_object_t obj = new vvp_darray (size); vvp_object_t obj;
if (strcmp(text,"sb32") == 0) {
obj = new vvp_darray_atom<int32_t>(size);
} else {
obj = new vvp_darray (size);
}
thr->stack_obj.push_back(obj); thr->stack_obj.push_back(obj);
@ -4457,6 +4489,28 @@ bool of_SET_AV(vthread_t thr, vvp_code_t cp)
return true; return true;
} }
/*
* %set/dar <label>, <bit>, <wid>
*/
bool of_SET_DAR(vthread_t thr, vvp_code_t cp)
{
unsigned bit = cp->bit_idx[0];
unsigned wid = cp->bit_idx[1];
unsigned adr = thr->words[3].w_int;
/* Make a vector of the desired width. */
vvp_vector4_t value = vthread_bits_to_vector(thr, bit, wid);
vvp_net_t*net = cp->net;
vvp_fun_signal_object*obj = dynamic_cast<vvp_fun_signal_object*> (net->fun);
assert(obj);
vvp_darray*darray = dynamic_cast<vvp_darray*>(obj->get_object());
assert(darray);
darray->set_word(adr, value);
return true;
}
/* /*
* This implements the "%set/v <label>, <bit>, <wid>" instruction. * This implements the "%set/v <label>, <bit>, <wid>" instruction.

View File

@ -18,6 +18,11 @@
*/ */
# include "vvp_object.h" # include "vvp_object.h"
# include "vvp_net.h"
# include <iostream>
# include <typeinfo>
using namespace std;
vvp_object::~vvp_object() vvp_object::~vvp_object()
{ {
@ -26,3 +31,40 @@ vvp_object::~vvp_object()
vvp_darray::~vvp_darray() vvp_darray::~vvp_darray()
{ {
} }
void vvp_darray::set_word(unsigned adr, const vvp_vector4_t&)
{
cerr << "XXXX set_word not implemented for " << typeid(*this).name() << endl;
}
void vvp_darray::get_word(unsigned, vvp_vector4_t&)
{
cerr << "XXXX get_word not implemented for " << typeid(*this).name() << endl;
}
template <> vvp_darray_atom<int32_t>::~vvp_darray_atom()
{
}
template <> void vvp_darray_atom<int32_t>::set_word(unsigned adr, const vvp_vector4_t&value)
{
if (adr >= array_.size())
return;
vector4_to_value(value, array_[adr], true, false);
}
template <> void vvp_darray_atom<int32_t>::get_word(unsigned adr, vvp_vector4_t&value)
{
if (adr >= array_.size()) {
value = vvp_vector4_t(32, BIT4_X);
return;
}
uint32_t word = array_[adr];
vvp_vector4_t tmp (32, BIT4_0);
for (unsigned idx = 0 ; idx < 32 ; idx += 1) {
if (word&1) tmp.set_bit(idx, BIT4_1);
word >>= 1;
}
value = tmp;
}

View File

@ -20,8 +20,10 @@
*/ */
# include <stdlib.h> # include <stdlib.h>
# include <vector>
typedef class vvp_object*vvp_object_t; typedef class vvp_object*vvp_object_t;
class vvp_vector4_t;
class vvp_object { class vvp_object {
public: public:
@ -33,12 +35,30 @@ class vvp_darray : public vvp_object {
public: public:
inline vvp_darray(size_t siz) : size_(siz) { } inline vvp_darray(size_t siz) : size_(siz) { }
~vvp_darray(); virtual ~vvp_darray();
inline size_t get_size(void) const { return size_; } inline size_t get_size(void) const { return size_; }
virtual void set_word(unsigned adr, const vvp_vector4_t&value);
virtual void get_word(unsigned adr, vvp_vector4_t&value);
private: private:
size_t size_; size_t size_;
}; };
template <class TYPE> class vvp_darray_atom : public vvp_darray {
public:
inline vvp_darray_atom(size_t siz) : vvp_darray(siz), array_(siz) { }
~vvp_darray_atom();
void set_word(unsigned adr, const vvp_vector4_t&value);
void get_word(unsigned adr, vvp_vector4_t&value);
private:
std::vector<TYPE> array_;
};
#endif #endif