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
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

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 (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);
}
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())) {
cerr << get_fileline() << ": error: "
<< "Enumeration type mismatch in assignment." << endl;

View File

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

View File

@ -348,6 +348,25 @@ ivl_select_type_t NetESelect::select_type() const
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
{
return true;

View File

@ -3807,6 +3807,10 @@ class NetESelect : public NetExpr {
const NetExpr*select() 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 bool has_width() const;
virtual void expr_scan(struct expr_scan_t*) const;

View File

@ -152,6 +152,16 @@ NetExpr* cast_to_int2(NetExpr*expr)
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
* 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 NetExpr*cast_to_int2(NetExpr*expr);
extern NetExpr*cast_to_real(NetExpr*expr);
/*
* 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_->type_ = IVL_EX_SELECT;
expr_->value_= IVL_VT_VECTOR;
expr_->value_= net->expr_type();
expr_->net_type=0;
expr_->width_= net->expr_width();
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);
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);
}

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);
assert(element_type);
assert(ivl_type_packed_dimensions(element_type) == 1);
int msb = ivl_type_packed_msb(element_type, 0);
int lsb = ivl_type_packed_lsb(element_type, 0);
int wid = msb>=lsb? msb - lsb : lsb - msb;
wid += 1;
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);
int msb = ivl_type_packed_msb(element_type, 0);
int lsb = ivl_type_packed_lsb(element_type, 0);
int wid = msb>=lsb? msb - lsb : lsb - msb;
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;
}

View File

@ -306,6 +306,26 @@ static int draw_real_logic_expr(ivl_expr_t expr, int stuff_ok_flag)
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)
{
int res;
@ -619,6 +639,10 @@ int draw_eval_real(ivl_expr_t expr)
res = draw_realnum_real(expr);
break;
case IVL_EX_SELECT:
res = draw_select_real(expr);
break;
case IVL_EX_SFUNC:
res = draw_sfunc_real(expr);
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 part = ivl_lval_part_off(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);
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(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),
STUFF_OK_XZ);
/* 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_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_R(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_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_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_R(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_X0(vthread_t thr, vvp_code_t code);

View File

@ -170,14 +170,15 @@ static const struct opcode_table_s opcode_table[] = {
{ "%join/detach",of_JOIN_DETACH,1,{OA_NUMBER,OA_NONE, OA_NONE} },
{ "%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/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",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/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/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/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/s",of_LOAD_VP0_S,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
{ "%load/vp0/s",of_LOAD_VP0_S,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
{ "%load/wr",of_LOAD_WR,2, {OA_BIT1, OA_VPI_PTR, OA_BIT2} },
{ "%load/x1p",of_LOAD_X1P,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
{ "%loadi/wr",of_LOADI_WR,3,{OA_BIT1, OA_NUMBER, 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/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/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/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} },

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).
* %load/dar <bit>, <functor-label>, <wid>
* %load/dar/r <bit>, <functor-label>
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.
The dar/r variant reads a real-value into a real-valued register.
(See also %set/dar)
* %load/v <bit>, <functor-label>, <wid>
@ -739,7 +742,9 @@ the array. See also %delete/obj
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>

View File

@ -3124,6 +3124,29 @@ bool of_LOAD_DAR(vthread_t thr, vvp_code_t cp)
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.
*/
@ -3973,6 +3996,8 @@ bool of_NEW_DARRAY(vthread_t thr, vvp_code_t cp)
obj = new vvp_darray_atom<int32_t>(size);
} else if (strcmp(text,"sb64") == 0) {
obj = new vvp_darray_atom<int64_t>(size);
} else if (strcmp(text,"r") == 0) {
obj = new vvp_darray_real(size);
} else {
obj = new vvp_darray (size);
}
@ -4526,6 +4551,28 @@ bool of_SET_DAR(vthread_t thr, vvp_code_t cp)
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.
*

View File

@ -34,12 +34,22 @@ vvp_darray::~vvp_darray()
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&)
{
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()
@ -79,3 +89,24 @@ template class vvp_darray_atom<int8_t>;
template class vvp_darray_atom<int16_t>;
template class vvp_darray_atom<int32_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_; }
virtual void set_word(unsigned adr, const 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:
size_t size_;
};
@ -54,11 +56,23 @@ template <class TYPE> class vvp_darray_atom : public vvp_darray {
~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_;
};
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