Fix dynamic array assignment to make a copy of the rvalue.
IEEE Std 1800-2017 Section 7.6 Array assignments Assignment of a dynamic array creates a duplicate of the source, so that assignments to the copy don't impact the original. Handle all sorts of dynamic array base types.
This commit is contained in:
parent
7277f4e807
commit
3c2fb6a601
|
|
@ -954,7 +954,7 @@ static int show_stmt_assign_darray_pattern(ivl_statement_t net)
|
|||
|
||||
// FIXME: At the moment we reallocate the array space.
|
||||
// This probably should be a resize to avoid values glitching
|
||||
/* Allocate at least enough space for the array patter. */
|
||||
/* Allocate at least enough space for the array pattern. */
|
||||
fprintf(vvp_out, " %%ix/load %u, %u, 0;\n", size_reg, ivl_expr_parms(rval));
|
||||
/* This can not have have a X/Z value so clear flag 4. */
|
||||
fprintf(vvp_out, " %%flag_set/imm 4, 0;\n");
|
||||
|
|
@ -1038,12 +1038,36 @@ static int show_stmt_assign_sig_darray(ivl_statement_t net)
|
|||
elements of the l-value. */
|
||||
errors += show_stmt_assign_darray_pattern(net);
|
||||
|
||||
} else {
|
||||
/* There is no l-value mux, so this must be an
|
||||
assignment to the array as a whole. Evaluate the
|
||||
"object", and store the evaluated result. */
|
||||
} else if (ivl_expr_type(rval) == IVL_EX_NEW) {
|
||||
// There is no l-value mux, and the r-value expression is
|
||||
// a "new" expression. Handle this by simply storing the
|
||||
// new object to the lval.
|
||||
errors += draw_eval_object(rval);
|
||||
fprintf(vvp_out, " %%store/obj v%p_0;\n", var);
|
||||
fprintf(vvp_out, " %%store/obj v%p_0; %s:%u: %s = new ...\n",
|
||||
var, ivl_stmt_file(net), ivl_stmt_lineno(net),
|
||||
ivl_signal_basename(var));
|
||||
|
||||
} else if (ivl_expr_type(rval) == IVL_EX_SIGNAL) {
|
||||
|
||||
// There is no l-value mux, and the r-value expression is
|
||||
// a "signal" expression. Store a duplicate into the lvalue
|
||||
// By using the %dup/obj. Remember to pop the rvalue that
|
||||
// is no longer needed.
|
||||
errors += draw_eval_object(rval);
|
||||
fprintf(vvp_out, " %%dup/obj;\n");
|
||||
fprintf(vvp_out, " %%store/obj v%p_0; %s:%u: %s = <signal>\n",
|
||||
var, ivl_stmt_file(net), ivl_stmt_lineno(net),
|
||||
ivl_signal_basename(var));
|
||||
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
||||
|
||||
} else {
|
||||
// There is no l-value mux, so this must be an
|
||||
// assignment to the array as a whole. Evaluate the
|
||||
// "object", and store the evaluated result.
|
||||
errors += draw_eval_object(rval);
|
||||
fprintf(vvp_out, " %%store/obj v%p_0; %s:%u: %s = <expr type %d>\n",
|
||||
var, ivl_stmt_file(net), ivl_stmt_lineno(net),
|
||||
ivl_signal_basename(var), ivl_expr_type(rval));
|
||||
}
|
||||
|
||||
return errors;
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ extern bool of_DISABLE_FORK(vthread_t thr, vvp_code_t code);
|
|||
extern bool of_DIV(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_DIV_S(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_DIV_WR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_DUP_OBJ(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_DUP_REAL(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_DUP_VEC4(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_END(vthread_t thr, vvp_code_t code);
|
||||
|
|
|
|||
|
|
@ -159,6 +159,7 @@ static const struct opcode_table_s opcode_table[] = {
|
|||
{ "%div", of_DIV, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%div/s", of_DIV_S, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%div/wr", of_DIV_WR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%dup/obj", of_DUP_OBJ, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%dup/real", of_DUP_REAL,0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%dup/vec4", of_DUP_VEC4,0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%end", of_END, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
|
|
|
|||
|
|
@ -491,8 +491,9 @@ This opcode divides the left operand by the right operand. If the
|
|||
right operand is 0, then the result is NaN.
|
||||
|
||||
|
||||
* dup/real
|
||||
* dup/vec4
|
||||
* %dup/real
|
||||
* %dup/vec4
|
||||
* %dup/obj
|
||||
|
||||
These opcodes duplicate the value on the top of the stack for the
|
||||
corresponding type.
|
||||
|
|
|
|||
|
|
@ -3002,6 +3002,19 @@ bool of_DIV_WR(vthread_t thr, vvp_code_t)
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* %dup/obj
|
||||
* %dup/real
|
||||
* %dup/vec4
|
||||
*
|
||||
* Push a duplicate of the object on the appropriate stack.
|
||||
*/
|
||||
bool of_DUP_OBJ(vthread_t thr, vvp_code_t)
|
||||
{
|
||||
thr->push_object(thr->peek_object().duplicate());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_DUP_REAL(vthread_t thr, vvp_code_t)
|
||||
{
|
||||
thr->push_real(thr->peek_real(0));
|
||||
|
|
@ -5596,6 +5609,17 @@ bool of_RETLOAD_VEC4(vthread_t thr, vvp_code_t cp)
|
|||
return retload<vvp_vector4_t>(thr, cp);
|
||||
}
|
||||
|
||||
/*
|
||||
* %scopy
|
||||
*
|
||||
* Pop the top item from the object stack, and shallow_copy() that item into
|
||||
* the new top of the object stack. This will copy at many items as needed
|
||||
* from the source object to fill the target object. If the target object is
|
||||
* larger then the source object, then some items will be left unchanged.
|
||||
*
|
||||
* The object may be any kind of object that supports shallow_copy(),
|
||||
* including dynamic arrays and class objects.
|
||||
*/
|
||||
bool of_SCOPY(vthread_t thr, vvp_code_t)
|
||||
{
|
||||
vvp_object_t tmp;
|
||||
|
|
|
|||
|
|
@ -67,11 +67,6 @@ void vvp_darray::get_word(unsigned, vvp_object_t&)
|
|||
cerr << "XXXX get_word(vvp_object_t) not implemented for " << typeid(*this).name() << endl;
|
||||
}
|
||||
|
||||
void vvp_darray::shallow_copy(const vvp_object*)
|
||||
{
|
||||
cerr << "XXXX shallow_copy(vvp_object_t) not implemented for " << typeid(*this).name() << endl;
|
||||
}
|
||||
|
||||
vvp_vector4_t vvp_darray::get_bitstream(bool)
|
||||
{
|
||||
cerr << "XXXX get_bitstream() not implemented for " << typeid(*this).name() << endl;
|
||||
|
|
@ -122,6 +117,15 @@ template <class TYPE> void vvp_darray_atom<TYPE>::shallow_copy(const vvp_object*
|
|||
array_[idx] = that->array_[idx];
|
||||
}
|
||||
|
||||
template <class TYPE> vvp_object* vvp_darray_atom<TYPE>::duplicate(void) const
|
||||
{
|
||||
vvp_darray_atom<TYPE>*that = new vvp_darray_atom<TYPE>(array_.size());
|
||||
for (size_t idx = 0 ; idx < array_.size() ; idx += 1)
|
||||
that->array_[idx] = array_[idx];
|
||||
|
||||
return that;
|
||||
}
|
||||
|
||||
template <class TYPE> vvp_vector4_t vvp_darray_atom<TYPE>::get_bitstream(bool)
|
||||
{
|
||||
const unsigned word_wid = sizeof(TYPE) * 8;
|
||||
|
|
@ -192,6 +196,16 @@ void vvp_darray_vec4::shallow_copy(const vvp_object*obj)
|
|||
array_[idx] = that->array_[idx];
|
||||
}
|
||||
|
||||
vvp_object* vvp_darray_vec4::duplicate(void) const
|
||||
{
|
||||
vvp_darray_vec4*that = new vvp_darray_vec4(array_.size(), word_wid_);
|
||||
|
||||
for (size_t idx = 0 ; idx < array_.size() ; idx += 1)
|
||||
that->array_[idx] = array_[idx];
|
||||
|
||||
return that;
|
||||
}
|
||||
|
||||
vvp_vector4_t vvp_darray_vec4::get_bitstream(bool as_vec4)
|
||||
{
|
||||
vvp_vector4_t vec(array_.size() * word_wid_, BIT4_0);
|
||||
|
|
@ -344,6 +358,16 @@ void vvp_darray_real::shallow_copy(const vvp_object*obj)
|
|||
array_[idx] = that->array_[idx];
|
||||
}
|
||||
|
||||
vvp_object* vvp_darray_real::duplicate(void) const
|
||||
{
|
||||
vvp_darray_real*that = new vvp_darray_real(array_.size());
|
||||
|
||||
for (size_t idx = 0 ; idx < array_.size() ; idx += 1)
|
||||
that->array_[idx] = array_[idx];
|
||||
|
||||
return that;
|
||||
}
|
||||
|
||||
vvp_vector4_t vvp_darray_real::get_bitstream(bool)
|
||||
{
|
||||
const unsigned word_wid = sizeof(double) * 8;
|
||||
|
|
@ -406,6 +430,16 @@ void vvp_darray_string::shallow_copy(const vvp_object*obj)
|
|||
array_[idx] = that->array_[idx];
|
||||
}
|
||||
|
||||
vvp_object* vvp_darray_string::duplicate(void) const
|
||||
{
|
||||
vvp_darray_string*that = new vvp_darray_string(array_.size());
|
||||
|
||||
for (size_t idx = 0 ; idx < array_.size() ; idx += 1)
|
||||
that->array_[idx] = array_[idx];
|
||||
|
||||
return that;
|
||||
}
|
||||
|
||||
vvp_queue::~vvp_queue()
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,8 +45,6 @@ class vvp_darray : public vvp_object {
|
|||
virtual void set_word(unsigned adr, const vvp_object_t&value);
|
||||
virtual void get_word(unsigned adr, vvp_object_t&value);
|
||||
|
||||
virtual void shallow_copy(const vvp_object*obj);
|
||||
|
||||
virtual vvp_vector4_t get_bitstream(bool as_vec4);
|
||||
};
|
||||
|
||||
|
|
@ -60,6 +58,7 @@ template <class TYPE> class vvp_darray_atom : public vvp_darray {
|
|||
void set_word(unsigned adr, const vvp_vector4_t&value);
|
||||
void get_word(unsigned adr, vvp_vector4_t&value);
|
||||
void shallow_copy(const vvp_object*obj);
|
||||
vvp_object* duplicate(void) const;
|
||||
vvp_vector4_t get_bitstream(bool as_vec4);
|
||||
|
||||
private:
|
||||
|
|
@ -77,6 +76,7 @@ class vvp_darray_vec4 : public vvp_darray {
|
|||
void set_word(unsigned adr, const vvp_vector4_t&value);
|
||||
void get_word(unsigned adr, vvp_vector4_t&value);
|
||||
void shallow_copy(const vvp_object*obj);
|
||||
vvp_object* duplicate(void) const;
|
||||
vvp_vector4_t get_bitstream(bool as_vec4);
|
||||
|
||||
private:
|
||||
|
|
@ -112,6 +112,7 @@ class vvp_darray_real : public vvp_darray {
|
|||
void set_word(unsigned adr, double value);
|
||||
void get_word(unsigned adr, double&value);
|
||||
void shallow_copy(const vvp_object*obj);
|
||||
vvp_object* duplicate(void) const;
|
||||
vvp_vector4_t get_bitstream(bool as_vec4);
|
||||
|
||||
private:
|
||||
|
|
@ -128,6 +129,7 @@ class vvp_darray_string : public vvp_darray {
|
|||
void set_word(unsigned adr, const std::string&value);
|
||||
void get_word(unsigned adr, std::string&value);
|
||||
void shallow_copy(const vvp_object*obj);
|
||||
vvp_object* duplicate(void) const;
|
||||
|
||||
private:
|
||||
std::vector<std::string> array_;
|
||||
|
|
@ -143,6 +145,7 @@ class vvp_darray_object : public vvp_darray {
|
|||
void set_word(unsigned adr, const vvp_object_t&value);
|
||||
void get_word(unsigned adr, vvp_object_t&value);
|
||||
void shallow_copy(const vvp_object*obj);
|
||||
//virtual vvp_object* duplicate(void) const;
|
||||
|
||||
private:
|
||||
std::vector<vvp_object_t> array_;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2012-2020 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
|
||||
|
|
@ -37,5 +37,13 @@ vvp_object::~vvp_object()
|
|||
|
||||
void vvp_object::shallow_copy(const vvp_object*)
|
||||
{
|
||||
cerr << "XXXX shallow_copy(vvp_object_t) not implemented for " << typeid(*this).name() << endl;
|
||||
assert(0);
|
||||
}
|
||||
|
||||
vvp_object* vvp_object::duplicate(void) const
|
||||
{
|
||||
cerr << "XXXX duplicate() not implemented for " << typeid(*this).name() << endl;
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef IVL_vvp_object_H
|
||||
#define IVL_vvp_object_H
|
||||
/*
|
||||
* Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2012-2020 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
|
||||
|
|
@ -33,6 +33,7 @@ class vvp_object {
|
|||
virtual ~vvp_object() =0;
|
||||
|
||||
virtual void shallow_copy(const vvp_object*that);
|
||||
virtual vvp_object* duplicate(void) const;
|
||||
|
||||
static void cleanup(void);
|
||||
|
||||
|
|
@ -63,6 +64,9 @@ class vvp_object_t {
|
|||
|
||||
inline void shallow_copy(const vvp_object_t&that)
|
||||
{ ref_->shallow_copy(that.ref_); }
|
||||
inline vvp_object_t duplicate(void) const
|
||||
{ return vvp_object_t(ref_->duplicate()); }
|
||||
|
||||
template <class T> T*peek(void) const;
|
||||
|
||||
private:
|
||||
|
|
|
|||
Loading…
Reference in New Issue