Support the new[] operator for arrays

Implement through the ivl core to the ivl_target.h API.
Also draft implementation of creating and storing arrays
in the vvp runtime and code generator.
This commit is contained in:
Stephen Williams 2012-07-15 20:44:07 -07:00
parent 14f229de30
commit d0e6b24ca2
18 changed files with 249 additions and 113 deletions

View File

@ -446,6 +446,11 @@ class PENew : public PExpr {
~PENew();
virtual void dump(ostream&) const;
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid,
unsigned flags) const;
private:
PExpr*size_;

View File

@ -107,6 +107,9 @@ class PAssign_ : public Statement {
NetExpr* elaborate_rval_(Design*, NetScope*, unsigned lv_width,
ivl_variable_type_t type) const;
NetExpr* elaborate_rval_obj_(Design*, NetScope*,
ivl_variable_type_t type) const;
PExpr* delay_;
PEventStatement*event_;
PExpr* count_;

View File

@ -89,6 +89,7 @@ NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
switch (lv_type) {
case IVL_VT_REAL:
case IVL_VT_STRING:
case IVL_VT_DARRAY:
break;
case IVL_VT_BOOL:
case IVL_VT_LOGIC:
@ -96,7 +97,6 @@ NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
break;
case IVL_VT_VOID:
case IVL_VT_NO_TYPE:
case IVL_VT_DARRAY:
ivl_assert(*expr, 0);
break;
}
@ -1638,23 +1638,7 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
NetExpr*tmp = elaborate_expr_method_(des, scope, expr_wid);
if (tmp) return tmp;
}
#if 0
// Maybe this is a method attached to an enumeration name? If
// this is system verilog, then test to see if the name is
// really a method attached to an object.
if (gn_system_verilog() && path_.size() >= 2) {
NetExpr*tmp = elaborate_expr_enum_method_(des, scope, expr_wid);
if (tmp) return tmp;
}
// Maybe this is a method attached to a string variable?
// If this is System Verilog, then test to see if the
// name is really a method attached to a string object.
if (gn_system_verilog() && path_.size() >= 2) {
NetExpr*tmp = elaborate_expr_string_method_(des, scope);
if (tmp) return tmp;
}
#endif
// Nothing was found so report this as an error.
cerr << get_fileline() << ": error: No function named `" << path_
<< "' found in this context (" << scope_path(scope) << ")."
@ -1850,81 +1834,6 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
return 0;
}
#if 0
NetExpr* PECallFunction::elaborate_expr_enum_method_(Design*des, NetScope*scope,
unsigned expr_wid) const
{
pform_name_t use_path = path_;
perm_string method_name = peek_tail_name(use_path);
use_path.pop_back();
NetNet *net;
const NetExpr *par;
NetEvent *eve;
const NetExpr *ex1, *ex2;
symbol_search(this, des, scope, use_path,
net, par, eve, ex1, ex2);
// Check to see if we have a net and if so is it an
// enumeration? If so then check to see if this is an
// enumeration method call.
if (net != 0) {
if (netenum_t*netenum = net->enumeration()) {
// We may need the net expression for the
// enumeration variable so get it.
NetESignal*expr = new NetESignal(net);
expr->set_line(*this);
// This expression cannot be a select!
assert(use_path.back().index.empty());
PExpr*tmp = parms_.size() ? parms_[0] : 0;
return check_for_enum_methods(this, des, scope,
netenum, use_path,
method_name, expr,
expr_wid, tmp,
parms_.size());
}
}
return 0;
}
#endif
#if 0
NetExpr* PECallFunction::elaborate_expr_string_method_(Design*des, NetScope*scope) const
{
pform_name_t use_path = path_;
perm_string method_name = peek_tail_name(use_path);
use_path.pop_back();
NetNet *net;
const NetExpr *par;
NetEvent *eve;
const NetExpr *ex1, *ex2;
symbol_search(this, des, scope, use_path,
net, par, eve, ex1, ex2);
// Check to see if we have a net and if so is it an
// enumeration? If so then check to see if this is an
// enumeration method call.
if (net == 0)
return 0;
if (net->data_type() != IVL_VT_STRING)
return 0;
if (method_name == "len") {
NetESFunc*sys_expr = new NetESFunc("$ivl_string_method$len",
IVL_VT_BOOL, 32, 1);
sys_expr->parm(0, new NetESignal(net));
return sys_expr;
}
return 0;
}
#endif
unsigned PECastSize::test_width(Design*des, NetScope*scope, width_mode_t&)
{
@ -3968,6 +3877,28 @@ NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope,
return node;
}
unsigned PENew::test_width(Design*des, NetScope*, width_mode_t&)
{
expr_type_ = IVL_VT_DARRAY;
expr_width_ = 1;
min_width_ = 1;
signed_flag_= false;
return 1;
}
NetExpr* PENew::elaborate_expr(Design*des, NetScope*scope,
unsigned, unsigned flags) const
{
width_mode_t mode = LOSSLESS;
unsigned use_wid = size_->test_width(des, scope, mode);
NetExpr*size = size_->elaborate_expr(des, scope, use_wid, flags);
NetESFunc*tmp = new NetESFunc("$ivl_darray_method$new",
IVL_VT_DARRAY, 1, 1);
tmp->set_line(*this);
tmp->parm(0, size);
return tmp;
}
unsigned PENumber::test_width(Design*, NetScope*, width_mode_t&mode)
{
expr_type_ = IVL_VT_LOGIC;

View File

@ -89,6 +89,8 @@ unsigned NetAssign_::lwidth() const
ivl_variable_type_t NetAssign_::expr_type() const
{
if (sig_->darray_type())
return IVL_VT_DARRAY;
return sig_->data_type();
}

View File

@ -938,13 +938,14 @@ endnew_opt : ':' K_new | ;
dynamic_array_new /* IEEE1800-2005: A.2.4 */
: K_new '[' expression ']'
{ //yyerror(@1, "sorry: Dynamic array new expression not supported.");
$$ = new PENew($3);
{ $$ = new PENew($3);
FILE_NAME($$, @1);
}
| K_new '[' expression ']' '(' expression ')'
{ yyerror(@1, "sorry: Dynamic array new expression with initializer not supported.");
delete $6;
$$ = new PENew($3);
FILE_NAME($$, @1);
}
;

View File

@ -49,7 +49,8 @@ CFLAGS = @WARNING_FLAGS@ @CFLAGS@
LDFLAGS = @LDFLAGS@
O = vvp.o draw_enum.o draw_mux.o draw_net_input.o draw_switch.o draw_ufunc.o draw_vpi.o \
eval_bool.o eval_expr.o eval_real.o eval_string.o modpath.o stmt_assign.o vector.o \
eval_bool.o eval_expr.o eval_object.o eval_real.o eval_string.o \
modpath.o stmt_assign.o vector.o \
vvp_process.o vvp_scope.o
all: dep vvp.tgt vvp.conf vvp-s.conf

58
tgt-vvp/eval_object.c Normal file
View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 2012 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
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "vvp_priv.h"
# include <string.h>
# include <assert.h>
static int eval_darray_new(ivl_expr_t ex)
{
unsigned size_reg = allocate_word();
ivl_expr_t size_expr = ivl_expr_parm(ex, 0);
draw_eval_expr_into_integer(size_expr, size_reg);
clr_word(size_reg);
fprintf(vvp_out, " %%new/darray %u;\n", size_reg);
return 0;
}
static int draw_eval_object_sfunc(ivl_expr_t ex)
{
const char*name = ivl_expr_name(ex);
if (strcmp(name, "$ivl_darray_method$new") == 0)
return eval_darray_new(ex);
fprintf(vvp_out, "; ERROR: Invalid system function %s for darray\n", name);
return 1;
}
int draw_eval_object(ivl_expr_t ex)
{
switch (ivl_expr_type(ex)) {
case IVL_EX_SFUNC:
return draw_eval_object_sfunc(ex);
default:
fprintf(vvp_out, "; ERROR: Invalid expression type %u\n", ivl_expr_type(ex));
return 1;
}
}

View File

@ -766,6 +766,24 @@ static int show_stmt_assign_sig_string(ivl_statement_t net)
return 0;
}
static int show_stmt_assign_sig_darray(ivl_statement_t net)
{
int errors = 0;
ivl_lval_t lval = ivl_stmt_lval(net, 0);
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);
assert(ivl_stmt_lvals(net) == 1);
assert(ivl_stmt_opcode(net) == 0);
assert(ivl_lval_mux(lval) == 0);
assert(part == 0);
errors += draw_eval_object(rval);
fprintf(vvp_out, " %%store/obj v%p_0;\n", var);
return errors;
}
int show_stmt_assign(ivl_statement_t net)
{
ivl_lval_t lval;
@ -784,5 +802,9 @@ int show_stmt_assign(ivl_statement_t net)
return show_stmt_assign_sig_string(net);
}
if (sig && (ivl_signal_data_type(sig) == IVL_VT_DARRAY)) {
return show_stmt_assign_sig_darray(net);
}
return show_stmt_assign_vector(net);
}

View File

@ -319,6 +319,12 @@ extern int draw_eval_bool64(ivl_expr_t ex);
*/
extern void draw_eval_string(ivl_expr_t ex);
/*
* The draw_eval_string functio evaluates the expression as an object,
* and pushes the object onto the object stack.
*/
extern int draw_eval_object(ivl_expr_t ex);
extern int show_stmt_assign(ivl_statement_t net);
extern void show_stmt_file_line(ivl_statement_t net, const char*desc);

View File

@ -76,7 +76,7 @@ O = main.o parse.o parse_misc.o lexor.o arith.o array.o bufif.o compile.o \
permaheap.o reduce.o resolv.o \
sfunc.o stop.o symbols.o ufunc.o codes.o vthread.o schedule.o \
statistics.o tables.o udp.o vvp_island.o vvp_net.o vvp_net_sig.o \
event.o logic.o delay.o words.o island_tran.o $V
vvp_object.o event.o logic.o delay.o words.o island_tran.o $V
all: dep vvp@EXEEXT@ libvpi.a vvp.man

View File

@ -143,6 +143,7 @@ extern bool of_MUL_WR(vthread_t thr, vvp_code_t code);
extern bool of_MULI(vthread_t thr, vvp_code_t code);
extern bool of_NAND(vthread_t thr, vvp_code_t code);
extern bool of_NANDR(vthread_t thr, vvp_code_t code);
extern bool of_NEW_DARRAY(vthread_t thr, vvp_code_t code);
extern bool of_NOOP(vthread_t thr, vvp_code_t code);
extern bool of_NOR(vthread_t thr, vvp_code_t code);
extern bool of_NORR(vthread_t thr, vvp_code_t code);
@ -168,6 +169,7 @@ extern bool of_SET_X0_X(vthread_t thr, vvp_code_t code);
extern bool of_SHIFTL_I0(vthread_t thr, vvp_code_t code);
extern bool of_SHIFTR_I0(vthread_t thr, vvp_code_t code);
extern bool of_SHIFTR_S_I0(vthread_t thr, vvp_code_t code);
extern bool of_STORE_OBJ(vthread_t thr, vvp_code_t code);
extern bool of_STORE_STR(vthread_t thr, vvp_code_t code);
extern bool of_SUB(vthread_t thr, vvp_code_t code);
extern bool of_SUB_WR(vthread_t thr, vvp_code_t code);

View File

@ -191,6 +191,7 @@ static const struct opcode_table_s opcode_table[] = {
{ "%muli", of_MULI, 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} },
{ "%new/darray",of_NEW_DARRAY,1,{OA_NUMBER,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/r", of_NORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
@ -215,6 +216,7 @@ static const struct opcode_table_s opcode_table[] = {
{ "%shiftl/i0", of_SHIFTL_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} },
{ "%shiftr/i0", of_SHIFTR_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} },
{ "%shiftr/s/i0", of_SHIFTR_S_I0,2,{OA_BIT1,OA_NUMBER, OA_NONE} },
{ "%store/obj",of_STORE_OBJ,1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
{ "%store/str",of_STORE_STR,1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
{ "%sub", of_SUB, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%sub/wr", of_SUB_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
@ -332,6 +334,11 @@ vvp_net_t* vvp_net_lookup(const char*label)
return tmp->funct;
}
case vpiArrayVar: {
__vpiDarrayVar*tmp = dynamic_cast<__vpiDarrayVar*>(vpi);
return tmp->get_net();
}
default:
fprintf(stderr, "Unsupported type %d.\n",
vpi->get_type_code());

View File

@ -716,6 +716,14 @@ means the following:
otherwise x
* %new/darray <idx>
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
use.
NOTE: For now, assume this is an array of int values.
* %nor <dst>, <src>, <wid>
Perform the bitwise nor of the vectors. Each bit in the <dst> is
@ -894,6 +902,11 @@ top bits. %shiftr/s/i0 is a signed shift, so the value is sign-extended.
For a negative shift %shiftr/i0 will pad the value with 'bx.
* %store/obj <var-label>
This pops the top of the object stack and writes it to the object
variable given by the label.
* %store/str <var-label>
This pops the top of the string stack and writes it to the string

View File

@ -33,23 +33,6 @@
using namespace std;
class __vpiDarrayVar : public __vpiHandle {
public:
__vpiDarrayVar(__vpiScope*scope, const char*name, vvp_net_t*net);
int get_type_code(void) const;
int vpi_get(int code);
void vpi_get_value(p_vpi_value val);
inline vvp_net_t* get_net() const { return net_; }
private:
struct __vpiScope* scope_;
const char*name_;
vvp_net_t*net_;
};
__vpiDarrayVar::__vpiDarrayVar(__vpiScope*sc, const char*na, vvp_net_t*ne)
: scope_(sc), name_(na), net_(ne)
{
@ -64,8 +47,15 @@ int __vpiDarrayVar::vpi_get(int code)
vvp_fun_signal_object*fun = dynamic_cast<vvp_fun_signal_object*> (net_->fun);
assert(fun);
vvp_object_t val = fun->get_object();
vvp_darray*aval = dynamic_cast<vvp_darray*> (val);
switch (code) {
case vpiSize:
if (aval == 0)
return 0;
else
return aval->get_size();
default:
return 0;
}

View File

@ -497,6 +497,23 @@ class __vpiStringVar : public __vpiHandle {
extern vpiHandle vpip_make_string_var(const char*name, vvp_net_t*net);
class __vpiDarrayVar : public __vpiHandle {
public:
__vpiDarrayVar(__vpiScope*scope, const char*name, vvp_net_t*net);
int get_type_code(void) const;
int vpi_get(int code);
void vpi_get_value(p_vpi_value val);
inline vvp_net_t* get_net() const { return net_; }
private:
struct __vpiScope* scope_;
const char*name_;
vvp_net_t*net_;
};
extern vpiHandle vpip_make_darray_var(const char*name, vvp_net_t*net);
/*

View File

@ -106,6 +106,9 @@ struct vthread_s {
(back()) only. */
vector<string> stack_str;
/* Objects are also operated on in a stack. */
vector<vvp_object_t> stack_obj;
/* My parent sets this when it wants me to wake it up. */
unsigned i_am_joining :1;
unsigned i_have_ended :1;
@ -3907,6 +3910,17 @@ bool of_NAND(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;
vvp_object_t obj = new vvp_darray (size);
thr->stack_obj.push_back(obj);
return true;
}
bool of_NOOP(vthread_t, vvp_code_t)
{
return true;
@ -4665,6 +4679,22 @@ bool of_SHIFTR_S_I0(vthread_t thr, vvp_code_t cp)
return true;
}
bool of_STORE_OBJ(vthread_t thr, vvp_code_t cp)
{
/* set the value into port 0 of the destination. */
vvp_net_ptr_t ptr (cp->net, 0);
assert(!thr->stack_obj.empty());
vvp_object_t val= thr->stack_obj.back();
thr->stack_obj.pop_back();
vvp_send_object(ptr, val, thr->wt_context);
return true;
}
bool of_STORE_STR(vthread_t thr, vvp_code_t cp)
{
/* set the value into port 0 of the destination. */

28
vvp/vvp_object.cc Normal file
View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2012 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
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "vvp_object.h"
vvp_object::~vvp_object()
{
}
vvp_darray::~vvp_darray()
{
}

View File

@ -19,6 +19,26 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include <stdlib.h>
typedef class vvp_object*vvp_object_t;
class vvp_object {
public:
inline vvp_object() { }
virtual ~vvp_object() =0;
};
class vvp_darray : public vvp_object {
public:
inline vvp_darray(size_t siz) : size_(siz) { }
~vvp_darray();
inline size_t get_size(void) const { return size_; }
private:
size_t size_;
};
#endif