Handle DARRAYs of real variables

This involves working out the code to get the base type of a select
expression of a darray. Also added the runtime support for darrays
with real value elements.
This commit is contained in:
Stephen Williams 2012-10-07 20:29:24 -07:00
parent 1326f9aef1
commit d6efece5dd
18 changed files with 226 additions and 20 deletions

View File

@ -1527,7 +1527,14 @@ void NetESelect::dump(ostream&o) const
else else
o << "(0)"; o << "(0)";
o << "+:" << expr_width() << "]>"; o << "+:" << expr_width() << "]";
if (ivl_type_t nt = net_type()) {
o << " net_type=(" << *nt << ")";
} else {
o << " expr_type=" << expr_type();
}
o << ">";
} }
void NetESFunc::dump(ostream&o) const void NetESFunc::dump(ostream&o) const

View File

@ -2509,10 +2509,17 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
if (lv->expr_type() == IVL_VT_BOOL && rv->expr_type() != IVL_VT_BOOL) { if (lv->expr_type() == IVL_VT_BOOL && rv->expr_type() != IVL_VT_BOOL) {
if (debug_elaborate) if (debug_elaborate)
cerr << get_fileline() << ": debug: Cast expression to int2" << endl; cerr << get_fileline() << ": debug: "
<< "Cast expression to int2" << endl;
rv = cast_to_int2(rv); rv = cast_to_int2(rv);
} }
if (lv->expr_type() == IVL_VT_REAL && rv->expr_type() != IVL_VT_REAL) {
if (debug_elaborate)
cerr << get_fileline() << ": debug: "
<< "Cast expression to real." << endl;
rv = cast_to_real(rv);
}
if (lv->enumeration() && (lv->enumeration() != rv->enumeration())) { if (lv->enumeration() && (lv->enumeration() != rv->enumeration())) {
cerr << get_fileline() << ": error: " cerr << get_fileline() << ": error: "
<< "Enumeration type mismatch in assignment." << endl; << "Enumeration type mismatch in assignment." << endl;

View File

@ -53,6 +53,9 @@ static bool get_real_arg_(const NetExpr*expr, verireal&val)
break; break;
} }
case IVL_VT_DARRAY:
return false;
default: default:
assert(0); assert(0);
} }

View File

@ -348,6 +348,25 @@ ivl_select_type_t NetESelect::select_type() const
return sel_type_; return sel_type_;
} }
ivl_variable_type_t NetESelect::expr_type() const
{
ivl_variable_type_t type = expr_->expr_type();
if (type != IVL_VT_DARRAY)
return type;
ivl_assert(*this, type == IVL_VT_DARRAY);
// Special case: If the expression is a DARRAY, then the
// sub-expression must be a NetESignal and the type of the
// NetESelect expression is the element type of the arrayed signal.
NetESignal*sig = dynamic_cast<NetESignal*>(expr_);
ivl_assert(*this, sig);
const netarray_t*array_type = dynamic_cast<const netarray_t*> (sig->sig()->net_type());
ivl_assert(*this, array_type);
return array_type->element_type()->base_type();
}
bool NetESelect::has_width() const bool NetESelect::has_width() const
{ {
return true; return true;

View File

@ -3807,6 +3807,10 @@ class NetESelect : public NetExpr {
const NetExpr*select() const; const NetExpr*select() const;
ivl_select_type_t select_type() const; ivl_select_type_t select_type() const;
// The type of a NetESelect is the base type of the
// sub-expression.
virtual ivl_variable_type_t expr_type() const;
virtual NexusSet* nex_input(bool rem_out = true); virtual NexusSet* nex_input(bool rem_out = true);
virtual bool has_width() const; virtual bool has_width() const;
virtual void expr_scan(struct expr_scan_t*) const; virtual void expr_scan(struct expr_scan_t*) const;

View File

@ -152,6 +152,16 @@ NetExpr* cast_to_int2(NetExpr*expr)
return cast; return cast;
} }
NetExpr* cast_to_real(NetExpr*expr)
{
if (expr->expr_type() == IVL_VT_REAL)
return expr;
NetECast*cast = new NetECast('r', expr, 1, true);
cast->set_line(*expr);
return cast;
}
/* /*
* Add a signed constant to an existing expression. Generate a new * Add a signed constant to an existing expression. Generate a new
* NetEBAdd node that has the input expression and an expression made * NetEBAdd node that has the input expression and an expression made

View File

@ -79,6 +79,7 @@ extern NetNet*cast_to_int2(Design*des, NetScope*scope, NetNet*src, unsigned wid)
extern NetNet*cast_to_real(Design*des, NetScope*scope, NetNet*src); extern NetNet*cast_to_real(Design*des, NetScope*scope, NetNet*src);
extern NetExpr*cast_to_int2(NetExpr*expr); extern NetExpr*cast_to_int2(NetExpr*expr);
extern NetExpr*cast_to_real(NetExpr*expr);
/* /*
* Take the input expression and return a variation that assures that * Take the input expression and return a variation that assures that

View File

@ -383,7 +383,7 @@ void dll_target::expr_select(const NetESelect*net)
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s)); expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
expr_->type_ = IVL_EX_SELECT; expr_->type_ = IVL_EX_SELECT;
expr_->value_= IVL_VT_VECTOR; expr_->value_= net->expr_type();
expr_->net_type=0; expr_->net_type=0;
expr_->width_= net->expr_width(); expr_->width_= net->expr_width();
expr_->signed_ = net->has_sign()? 1 : 0; expr_->signed_ = net->has_sign()? 1 : 0;

View File

@ -31,7 +31,9 @@ static unsigned show_assign_lval_darray(ivl_lval_t lval, unsigned ind)
assert(sig); assert(sig);
if (ivl_lval_idx(lval)) { if (ivl_lval_idx(lval)) {
fprintf(out, "%*sAddress-0 select of dynamic array:\n", ind+4, ""); fprintf(out, "%*sAddress-0 select of ", ind+4, "");
show_type_of_signal(sig);
fprintf(out, ":\n");
show_expression(ivl_lval_idx(lval), ind+6); show_expression(ivl_lval_idx(lval), ind+6);
} }

View File

@ -36,14 +36,28 @@ static int eval_darray_new(ivl_expr_t ex)
ivl_type_t element_type = ivl_type_element(net_type); ivl_type_t element_type = ivl_type_element(net_type);
assert(element_type); assert(element_type);
switch (ivl_type_base(element_type)) {
case IVL_VT_REAL:
// REAL objects are not packable.
assert(ivl_type_packed_dimensions(element_type) == 0);
fprintf(vvp_out, " %%new/darray %u, \"r\";\n", size_reg);
break;
case IVL_VT_BOOL:
// bool objects are vectorable, but for now only support
// a single dimensions.
assert(ivl_type_packed_dimensions(element_type) == 1); assert(ivl_type_packed_dimensions(element_type) == 1);
int msb = ivl_type_packed_msb(element_type, 0); int msb = ivl_type_packed_msb(element_type, 0);
int lsb = ivl_type_packed_lsb(element_type, 0); int lsb = ivl_type_packed_lsb(element_type, 0);
int wid = msb>=lsb? msb - lsb : lsb - msb; int wid = msb>=lsb? msb - lsb : lsb - msb;
wid += 1; wid += 1;
// XXXX: Assume elements are signed integers.
fprintf(vvp_out, " %%new/darray %u, \"sb%d\";\n", size_reg, wid); fprintf(vvp_out, " %%new/darray %u, \"sb%d\";\n", size_reg, wid);
break;
default:
assert(0);
break;
}
return 0; return 0;
} }

View File

@ -306,6 +306,26 @@ static int draw_real_logic_expr(ivl_expr_t expr, int stuff_ok_flag)
return res; return res;
} }
static int draw_select_real(ivl_expr_t expr)
{
int res;
/* The sube references the expression to be selected from. */
ivl_expr_t sube = ivl_expr_oper1(expr);
/* This is the select expression */
ivl_expr_t shift= ivl_expr_oper2(expr);
/* Assume the sub-expression is a signal */
ivl_signal_t sig = ivl_expr_signal(sube);
assert(ivl_signal_data_type(sig) == IVL_VT_DARRAY);
res = allocate_word();
draw_eval_expr_into_integer(shift, 3);
fprintf(vvp_out, " %%load/dar/r %u, v%p_0;\n", res, sig);
return res;
}
static int draw_sfunc_real(ivl_expr_t expr) static int draw_sfunc_real(ivl_expr_t expr)
{ {
int res; int res;
@ -619,6 +639,10 @@ int draw_eval_real(ivl_expr_t expr)
res = draw_realnum_real(expr); res = draw_realnum_real(expr);
break; break;
case IVL_EX_SELECT:
res = draw_select_real(expr);
break;
case IVL_EX_SFUNC: case IVL_EX_SFUNC:
res = draw_sfunc_real(expr); res = draw_sfunc_real(expr);
break; break;

View File

@ -773,6 +773,10 @@ 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_type_t var_type= ivl_signal_net_type(var);
assert(ivl_type_base(var_type) == IVL_VT_DARRAY);
ivl_type_t element_type = ivl_type_element(var_type);
ivl_expr_t mux = ivl_lval_idx(lval); ivl_expr_t mux = ivl_lval_idx(lval);
assert(ivl_stmt_lvals(net) == 1); assert(ivl_stmt_lvals(net) == 1);
@ -780,7 +784,17 @@ static int show_stmt_assign_sig_darray(ivl_statement_t net)
assert(ivl_lval_mux(lval) == 0); assert(ivl_lval_mux(lval) == 0);
assert(part == 0); assert(part == 0);
if (mux) { if (mux && (ivl_type_base(element_type)==IVL_VT_REAL)) {
int dst = draw_eval_real(rval);
/* 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/r v%p_0, %u;\n", var, dst);
clr_word(dst);
} else if (mux) {
struct vector_info rvec = draw_eval_expr_wid(rval, ivl_lval_width(lval), struct vector_info rvec = draw_eval_expr_wid(rval, ivl_lval_width(lval),
STUFF_OK_XZ); STUFF_OK_XZ);
/* The %set/dar expects the array index to be in index /* The %set/dar expects the array index to be in index

View File

@ -126,6 +126,7 @@ 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_DAR(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_DAR_R(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);
@ -165,6 +166,7 @@ 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_DAR(vthread_t thr, vvp_code_t code);
extern bool of_SET_DAR_R(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

@ -171,9 +171,10 @@ static const struct opcode_table_s opcode_table[] = {
{ "%load/ar",of_LOAD_AR,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} }, { "%load/ar",of_LOAD_AR,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} },
{ "%load/av",of_LOAD_AV,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} }, { "%load/av",of_LOAD_AV,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} },
{ "%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/dar",of_LOAD_DAR,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
{ "%load/dar/r",of_LOAD_DAR_R,2,{OA_BIT1, OA_FUNC_PTR, OA_NONE} },
{ "%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} },
@ -213,6 +214,7 @@ static const struct opcode_table_s opcode_table[] = {
{ "%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/dar",of_SET_DAR,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
{ "%set/dar/r",of_SET_DAR_R,2,{OA_FUNC_PTR,OA_BIT1, OA_NONE} },
{ "%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

@ -598,12 +598,15 @@ 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> * %load/dar <bit>, <functor-label>, <wid>
* %load/dar/r <bit>, <functor-label>
This instruction loads an array word from a dynamic array. The This instruction loads an array word from a dynamic array. The
<label> refers to the variable object, and the <bit>/<wid> are the <label> refers to the variable object, and the <bit>/<wid> are the
location in local vector space where the extracted word goes. The location in local vector space where the extracted word goes. The
index is implicitly extracted from index register 3. index is implicitly extracted from index register 3.
The dar/r variant reads a real-value into a real-valued register.
(See also %set/dar) (See also %set/dar)
* %load/v <bit>, <functor-label>, <wid> * %load/v <bit>, <functor-label>, <wid>
@ -739,7 +742,9 @@ the array. See also %delete/obj
The supported types are: The supported types are:
"sb32" - signed bool 32bits "b<N>" - unsigned bool <N>-bits
"sb<N>" - signed bool <N>-bits
"r" - real
* %nor <dst>, <src>, <wid> * %nor <dst>, <src>, <wid>

View File

@ -3124,6 +3124,29 @@ bool of_LOAD_DAR(vthread_t thr, vvp_code_t cp)
return true; return true;
} }
/*
* %load/dar/r <dst>, <array-label>;
*/
bool of_LOAD_DAR_R(vthread_t thr, vvp_code_t cp)
{
unsigned dst = cp->bit_idx[0];
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);
double word;
darray->get_word(adr, word);
thr->words[dst].w_real = 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.
*/ */
@ -3973,6 +3996,8 @@ bool of_NEW_DARRAY(vthread_t thr, vvp_code_t cp)
obj = new vvp_darray_atom<int32_t>(size); obj = new vvp_darray_atom<int32_t>(size);
} else if (strcmp(text,"sb64") == 0) { } else if (strcmp(text,"sb64") == 0) {
obj = new vvp_darray_atom<int64_t>(size); obj = new vvp_darray_atom<int64_t>(size);
} else if (strcmp(text,"r") == 0) {
obj = new vvp_darray_real(size);
} else { } else {
obj = new vvp_darray (size); obj = new vvp_darray (size);
} }
@ -4526,6 +4551,28 @@ bool of_SET_DAR(vthread_t thr, vvp_code_t cp)
return true; return true;
} }
/*
* %set/dar/r <label>, <bit>
*/
bool of_SET_DAR_R(vthread_t thr, vvp_code_t cp)
{
unsigned bit = cp->bit_idx[0];
unsigned adr = thr->words[3].w_int;
/* Make a vector of the desired width. */
double value = thr->words[bit].w_real;
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

@ -34,12 +34,22 @@ vvp_darray::~vvp_darray()
void vvp_darray::set_word(unsigned, const vvp_vector4_t&) void vvp_darray::set_word(unsigned, const vvp_vector4_t&)
{ {
cerr << "XXXX set_word not implemented for " << typeid(*this).name() << endl; cerr << "XXXX set_word(vvp_vector4_t) not implemented for " << typeid(*this).name() << endl;
}
void vvp_darray::set_word(unsigned, double)
{
cerr << "XXXX set_word(double) not implemented for " << typeid(*this).name() << endl;
} }
void vvp_darray::get_word(unsigned, vvp_vector4_t&) void vvp_darray::get_word(unsigned, vvp_vector4_t&)
{ {
cerr << "XXXX get_word not implemented for " << typeid(*this).name() << endl; cerr << "XXXX get_word(vvp_vector4_t) not implemented for " << typeid(*this).name() << endl;
}
void vvp_darray::get_word(unsigned, double&)
{
cerr << "XXXX get_word(double) not implemented for " << typeid(*this).name() << endl;
} }
template <class TYPE> vvp_darray_atom<TYPE>::~vvp_darray_atom() template <class TYPE> vvp_darray_atom<TYPE>::~vvp_darray_atom()
@ -79,3 +89,24 @@ template class vvp_darray_atom<int8_t>;
template class vvp_darray_atom<int16_t>; template class vvp_darray_atom<int16_t>;
template class vvp_darray_atom<int32_t>; template class vvp_darray_atom<int32_t>;
template class vvp_darray_atom<int64_t>; template class vvp_darray_atom<int64_t>;
vvp_darray_real::~vvp_darray_real()
{
}
void vvp_darray_real::set_word(unsigned adr, double value)
{
if (adr >= array_.size())
return;
array_[adr] = value;
}
void vvp_darray_real::get_word(unsigned adr, double&value)
{
if (adr >= array_.size()) {
value = 0.0;
return;
}
value = array_[adr];
}

View File

@ -40,9 +40,11 @@ class vvp_darray : public vvp_object {
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 set_word(unsigned adr, const vvp_vector4_t&value);
virtual void get_word(unsigned adr, vvp_vector4_t&value); virtual void get_word(unsigned adr, vvp_vector4_t&value);
virtual void set_word(unsigned adr, double value);
virtual void get_word(unsigned adr, double&value);
private: private:
size_t size_; size_t size_;
}; };
@ -54,11 +56,23 @@ template <class TYPE> class vvp_darray_atom : public vvp_darray {
~vvp_darray_atom(); ~vvp_darray_atom();
void set_word(unsigned adr, const vvp_vector4_t&value); void set_word(unsigned adr, const vvp_vector4_t&value);
void get_word(unsigned adr, vvp_vector4_t&value); void get_word(unsigned adr, vvp_vector4_t&value);
private: private:
std::vector<TYPE> array_; std::vector<TYPE> array_;
}; };
class vvp_darray_real : public vvp_darray {
public:
inline vvp_darray_real(size_t siz) : vvp_darray(siz), array_(siz) { }
~vvp_darray_real();
void set_word(unsigned adr, double value);
void get_word(unsigned adr, double&value);
private:
std::vector<double> array_;
};
#endif #endif