Draft run-time support for SystemVerilog class objects.

This provides the ivl_target.h interface for class definitions
and expressions, the vvp code generator support for class objects
and properties, and the vvp run time support. Trivial class objects
now seem to work.
This commit is contained in:
Stephen Williams 2012-12-09 17:59:16 -08:00
parent 70dff035a2
commit 860419a346
34 changed files with 521 additions and 71 deletions

View File

@ -1524,7 +1524,7 @@ void NetENull::dump(ostream&o) const
void NetEProperty::dump(ostream&o) const
{
o << net_->name() << "." << pname_;
o << net_->name() << ".<" << pidx_ << ">";
}
void NetEScope::dump(ostream&o) const

View File

@ -805,6 +805,22 @@ extern unsigned ivl_event_lineno(ivl_event_t net);
*
* - IVL_EX_BINARY
*
* - IVL_EX_PROPERTY
* This expression represents the property select from a class
* type, for example "foo.property" where "foo" is a class handle and
* "property" is the name of one of the properties of the class. The
* ivl_expr_signal function returns the ivl_signal_t for "foo" and the
* data_type for the signal will be IVL_VT_CLASS.
*
* The ivl_signal_net_type(sig) for the "foo" signal will be a class
* type and from there you can get access to the type information.
*
* Elaboration reduces the properties of a class to a vector numbered
* from 0 to the number of properties. The ivl_expr_property_idx()
* function gets the index of the selected property into the property
* table. That number can be passed to ivl_type_prop_*() functions to
* get details about the property.
*
* - IVL_EX_SELECT
* This expression takes two operands, oper1 is the expression to
* select from, and oper2 is the selection base. The ivl_expr_width
@ -891,6 +907,8 @@ extern unsigned ivl_expr_repeat(ivl_expr_t net);
extern ivl_select_type_t ivl_expr_sel_type(ivl_expr_t net);
/* IVL_EX_EVENT */
extern ivl_event_t ivl_expr_event(ivl_expr_t net);
/* IVL_EX_PROPERTY */
extern int ivl_expr_property_idx(ivl_expr_t net);
/* IVL_EX_SCOPE */
extern ivl_scope_t ivl_expr_scope(ivl_expr_t net);
/* IVL_EX_PROPERTY IVL_EX_SIGNAL */
@ -1431,10 +1449,10 @@ extern const char*ivl_lpm_string(ivl_lpm_t net);
* ivl_expr_t that represents the index expression. Otherwise, it
* returns 0.
*
* ivl_lval_property
* ivl_lval_property_idx
* If the l-value is a class object, this is the name of a property
* to select from the object. If this property is not present, then
* the l-value represents the class object itself.
* to select from the object. If this property is not present (<0)
* then the l-value represents the class object itself.
*
* SEMANTIC NOTES
* The ivl_lval_width is not necessarily the same as the width of the
@ -1461,7 +1479,7 @@ extern ivl_expr_t ivl_lval_mux(ivl_lval_t net); /* XXXX Obsolete? */
extern ivl_expr_t ivl_lval_idx(ivl_lval_t net);
extern ivl_expr_t ivl_lval_part_off(ivl_lval_t net);
extern ivl_select_type_t ivl_lval_sel_type(ivl_lval_t net);
extern const char* ivl_lval_property(ivl_lval_t net);
extern int ivl_lval_property_idx(ivl_lval_t net);
extern ivl_signal_t ivl_lval_sig(ivl_lval_t net);
@ -2224,9 +2242,9 @@ extern unsigned ivl_type_packed_dimensions(ivl_type_t net);
extern int ivl_type_packed_lsb(ivl_type_t net, unsigned dim);
extern int ivl_type_packed_msb(ivl_type_t net, unsigned dim);
extern const char* ivl_type_name(ivl_type_t net);
extern unsigned ivl_type_properties(ivl_type_t net);
extern const char* ivl_type_prop_name(ivl_type_t net, unsigned idx);
extern ivl_type_t ivl_type_prop_type(ivl_type_t net, unsigned idx);
extern int ivl_type_properties(ivl_type_t net);
extern const char* ivl_type_prop_name(ivl_type_t net, int idx);
extern ivl_type_t ivl_type_prop_type(ivl_type_t net, int idx);
#if defined(__MINGW32__) || defined (__CYGWIN32__)

View File

@ -349,8 +349,14 @@ NetENull::~NetENull()
}
NetEProperty::NetEProperty(NetNet*net, perm_string pnam)
: net_(net), pname_(pnam)
: net_(net)
{
const netclass_t*use_type = dynamic_cast<const netclass_t*>(net->net_type());
assert(use_type);
pidx_ = use_type->property_idx_from_name(pnam);
ivl_type_t prop_type = use_type->get_prop_type(pidx_);
expr_width(prop_type->packed_width());
}
NetEProperty::~NetEProperty()

View File

@ -33,13 +33,17 @@ netclass_t::~netclass_t()
bool netclass_t::set_property(perm_string pname, ivl_type_s*ptype)
{
map<perm_string,ivl_type_s*>::const_iterator cur;
map<perm_string,size_t>::const_iterator cur;
cur = properties_.find(pname);
if (cur != properties_.end())
return false;
properties_[pname] = ptype;
property_table_.push_back(pname);
prop_t tmp;
tmp.name = pname;
tmp.type = ptype;
property_table_.push_back(tmp);
properties_[pname] = property_table_.size()-1;
return true;
}
@ -50,22 +54,33 @@ ivl_variable_type_t netclass_t::base_type() const
const ivl_type_s* netclass_t::get_property(perm_string pname) const
{
map<perm_string,ivl_type_s*>::const_iterator cur;
map<perm_string,size_t>::const_iterator cur;
cur = properties_.find(pname);
if (cur == properties_.end())
return 0;
else
return cur->second;
assert(property_table_.size() > cur->second);
return property_table_[cur->second].type;
}
int netclass_t::property_idx_from_name(perm_string pname) const
{
map<perm_string,size_t>::const_iterator cur;
cur = properties_.find(pname);
if (cur == properties_.end())
return -1;
return cur->second;
}
const char*netclass_t::get_prop_name(size_t idx) const
{
assert(idx < property_table_.size());
return property_table_[idx];
return property_table_[idx].name;
}
ivl_type_t netclass_t::get_prop_type(size_t idx) const
{
assert(idx < property_table_.size());
return get_property(property_table_[idx]);
return property_table_[idx].type;
}

View File

@ -47,12 +47,18 @@ class netclass_t : public ivl_type_s {
const char*get_prop_name(size_t idx) const;
ivl_type_t get_prop_type(size_t idx) const;
int property_idx_from_name(perm_string pname) const;
private:
perm_string name_;
// Bind properties to their types.
std::map<perm_string,ivl_type_s*> properties_;
// This is to help the get_prop_name() method work.
std::vector<perm_string> property_table_;
// Map properrty names to property table index.
std::map<perm_string,size_t> properties_;
// Vector of properties.
struct prop_t {
perm_string name;
ivl_type_s* type;
};
std::vector<prop_t> property_table_;
};
#endif

View File

@ -3941,7 +3941,7 @@ class NetEProperty : public NetExpr {
~NetEProperty();
inline const NetNet* get_sig() const { return net_; }
inline const char* get_pname() const { return pname_.str(); }
inline size_t property_idx() const { return pidx_; }
virtual void expr_scan(struct expr_scan_t*) const;
virtual NetEProperty* dup_expr() const;
@ -3951,7 +3951,7 @@ class NetEProperty : public NetExpr {
private:
NetNet*net_;
perm_string pname_;
size_t pidx_;
};
/*

View File

@ -57,6 +57,8 @@ EXTERN_C_START
#define vpiEnumTypespec 633
#define vpiEnumConst 634
#define vpiClassDefn 652
/********* One-to-One ***********/
#define vpiBaseTypespec 703

View File

@ -430,7 +430,11 @@ extern "C" const char* ivl_expr_name(ivl_expr_t net)
return net->u_.signal_.sig->name_;
case IVL_EX_PROPERTY:
return net->u_.property_.pname;
{ ivl_signal_t sig = ivl_expr_signal(net);
ivl_type_t use_type = ivl_signal_net_type(sig);
unsigned idx = ivl_expr_property_idx(net);
return ivl_type_prop_name(use_type, idx);
}
default:
assert(0);
@ -598,6 +602,13 @@ extern "C" ivl_event_t ivl_expr_event(ivl_expr_t net)
return net->u_.event_.event;
}
extern "C" int ivl_expr_property_idx(ivl_expr_t net)
{
assert(net);
assert(net->type_ == IVL_EX_PROPERTY);
return net->u_.property_.prop_idx;
}
extern "C" ivl_scope_t ivl_expr_scope(ivl_expr_t net)
{
assert(net);
@ -1561,13 +1572,10 @@ extern "C" unsigned ivl_lval_width(ivl_lval_t net)
return net->width_;
}
extern "C" const char* ivl_lval_property(ivl_lval_t net)
extern "C" int ivl_lval_property_idx(ivl_lval_t net)
{
assert(net);
if (net->property.nil())
return 0;
else
return net->property.str();
return net->property_idx;
}
extern "C" ivl_signal_t ivl_lval_sig(ivl_lval_t net)
@ -2864,7 +2872,7 @@ extern "C" const char* ivl_type_name(ivl_type_t net)
return 0;
}
extern "C" unsigned ivl_type_properties(ivl_type_t net)
extern "C" int ivl_type_properties(ivl_type_t net)
{
const netclass_t*class_type = dynamic_cast<const netclass_t*>(net);
assert(class_type);
@ -2872,15 +2880,16 @@ extern "C" unsigned ivl_type_properties(ivl_type_t net)
return class_type->get_properties();
}
extern "C" const char* ivl_type_prop_name(ivl_type_t net, unsigned idx)
extern "C" const char* ivl_type_prop_name(ivl_type_t net, int idx)
{
if (idx < 0) return 0;
const netclass_t*class_type = dynamic_cast<const netclass_t*>(net);
assert(class_type);
return class_type->get_prop_name(idx);
}
extern "C" ivl_type_t ivl_type_prop_type(ivl_type_t net, unsigned idx)
extern "C" ivl_type_t ivl_type_prop_type(ivl_type_t net, int idx)
{
const netclass_t*class_type = dynamic_cast<const netclass_t*>(net);
assert(class_type);

View File

@ -24,6 +24,7 @@
# include <cstring>
# include "t-dll.h"
# include "netlist.h"
# include "netclass.h"
# include <cassert>
# include <cstdlib>
# include "ivl_alloc.h"
@ -362,7 +363,7 @@ void dll_target::expr_property(const NetEProperty*net)
expr_->value_ = net->expr_type();
expr_->net_type= net->net_type();
expr_->u_.property_.sig = find_signal(des_, net->get_sig());
expr_->u_.property_.pname = net->get_pname();
expr_->u_.property_.prop_idx = net->property_idx();
}
void dll_target::expr_event(const NetEEvent*net)

View File

@ -27,6 +27,7 @@
# include "ivl_target.h"
# include "compiler.h"
# include "t-dll.h"
# include "netclass.h"
# include <cstdlib>
# include "ivl_alloc.h"
@ -162,7 +163,6 @@ void dll_target::make_assign_lvals_(const NetAssignBase*net)
}
cur->width_ = asn->lwidth();
cur->property = asn->get_property();
if (asn->sig()) {
cur->type_ = IVL_LVAL_REG;
@ -180,6 +180,14 @@ void dll_target::make_assign_lvals_(const NetAssignBase*net)
cur->idx = expr_;
expr_ = 0;
}
cur->property_idx = -1;
perm_string pname = asn->get_property();
if (!pname.nil()) {
const netclass_t*use_type = dynamic_cast<const netclass_t*> (cur->n.sig->net_type);
cur->property_idx = use_type->property_idx_from_name(pname);
}
} else {
assert(0);
}

View File

@ -328,7 +328,7 @@ struct ivl_expr_s {
struct {
ivl_signal_t sig;
const char*pname;
unsigned prop_idx;
} property_;
} u_;
};
@ -451,7 +451,7 @@ struct ivl_lval_s {
ivl_expr_t idx;
unsigned width_;
unsigned type_ : 8;
perm_string property;
int property_idx;
union {
ivl_signal_t sig;
ivl_memory_t mem;

View File

@ -210,8 +210,8 @@ static void show_property_expression(ivl_expr_t net, unsigned ind)
ivl_signal_t sig = ivl_expr_signal(net);
const char* pnam = ivl_expr_name(net);
fprintf(out, "%*s%s<property>%s\n", ind, "",
ivl_signal_basename(sig), pnam);
fprintf(out, "%*s<property base=%s, prop=%s, width=%u>\n", ind, "",
ivl_signal_basename(sig), pnam, ivl_expr_width(net));
if (ivl_signal_data_type(sig) != IVL_VT_CLASS) {
fprintf(out, "%*sERROR: Property signal must be IVL_VT_CLASS, got %s.\n",
ind+3, "", data_type_string(ivl_signal_data_type(sig)));

View File

@ -60,12 +60,12 @@ static unsigned show_assign_lval_darray(ivl_lval_t lval, unsigned ind)
static unsigned show_assign_lval_class(ivl_lval_t lval, unsigned ind)
{
ivl_signal_t sig = ivl_lval_sig(lval);
const char*sig_prop = ivl_lval_property(lval);
int sig_prop = ivl_lval_property_idx(lval);
assert(sig);
/* If there is no property select, then this l-value is for
the class handle itself. */
if (sig_prop == 0) {
if (sig_prop < 0) {
fprintf(out, "%*s{name=%s class object}\n", ind, "", ivl_signal_name(sig));
if (ivl_lval_width(lval) != 1) {
fprintf(out, "%*sERROR: ivl_lval_width should be 1 for class objects\n",
@ -75,7 +75,7 @@ static unsigned show_assign_lval_class(ivl_lval_t lval, unsigned ind)
return ivl_lval_width(lval);
}
fprintf(out, "%*s{name=%s<property>%s l-value width=%u}\n",
fprintf(out, "%*s{name=%s.<property-%d> l-value width=%u}\n",
ind, "", ivl_signal_name(sig), sig_prop, ivl_lval_width(lval));
return ivl_lval_width(lval);

View File

@ -47,7 +47,8 @@ CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ @PICFLAG@
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 \
O = vvp.o draw_class.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_object.o eval_real.o eval_string.o \
modpath.o stmt_assign.o vector.o \
vvp_process.o vvp_scope.o

46
tgt-vvp/draw_class.c Normal file
View File

@ -0,0 +1,46 @@
/*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "vvp_priv.h"
# include <stdlib.h>
# include <string.h>
# include <assert.h>
# include <inttypes.h>
static void show_prop_type(ivl_type_t ptype)
{
// XXXX: For now, assume all properties are 32bit integers.
fprintf(vvp_out, "\"b32\"");
}
void draw_class_in_scope(ivl_type_t classtype)
{
int idx;
fprintf(vvp_out, "C%p .class \"%s\" [%d]\n",
classtype, ivl_type_name(classtype), ivl_type_properties(classtype));
for (idx = 0 ; idx < ivl_type_properties(classtype) ; idx += 1) {
fprintf(vvp_out, " %3d: \"%s\", ", idx, ivl_type_prop_name(classtype,idx));
show_prop_type(ivl_type_prop_type(classtype,idx));
fprintf(vvp_out, "\n");
}
fprintf(vvp_out, " ;\n");
}

View File

@ -2108,6 +2108,23 @@ static struct vector_info draw_number_expr(ivl_expr_t expr, unsigned wid)
return res;
}
static struct vector_info draw_property_expr(ivl_expr_t expr, unsigned wid)
{
ivl_signal_t sig = ivl_expr_signal(expr);
unsigned pidx = ivl_expr_property_idx(expr);
struct vector_info res;
res.base = allocate_vector(wid);
res.wid = wid;
assert(res.base != 0);
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
fprintf(vvp_out, " %%prop/v %u, %u, %u;\n", pidx, res.base, wid);
return res;
}
/*
* This little helper function generates the instructions to pad a
* vector in place. It is assumed that the calling function has set up
@ -3641,6 +3658,10 @@ struct vector_info draw_eval_expr_wid(ivl_expr_t expr, unsigned wid,
res = draw_number_expr(expr, wid);
break;
case IVL_EX_PROPERTY:
res = draw_property_expr(expr, wid);
break;
case IVL_EX_REALNUM:
res = draw_realnum_expr(expr, wid);
break;

View File

@ -69,7 +69,8 @@ static int eval_darray_new(ivl_expr_t ex)
static int eval_class_new(ivl_expr_t ex)
{
fprintf(vvp_out, " %%new/cobj ; XXXX Need to specify the type?\n");
ivl_type_t class_type = ivl_expr_net_type(ex);
fprintf(vvp_out, " %%new/cobj C%p;\n", class_type);
return 0;
}

View File

@ -826,10 +826,32 @@ static int show_stmt_assign_sig_cobject(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_signal_t var= ivl_lval_sig(lval);
ivl_signal_t sig= ivl_lval_sig(lval);
int prop_idx = ivl_lval_property_idx(lval);
if (prop_idx >= 0) {
ivl_type_t sig_type = ivl_signal_net_type(sig);
ivl_type_t prop_type = ivl_type_prop_type(sig_type, prop_idx);
assert(ivl_type_base(prop_type) == IVL_VT_BOOL);
assert(ivl_type_packed_dimensions(prop_type) == 1);
assert(ivl_type_packed_msb(prop_type,0) >= ivl_type_packed_lsb(prop_type, 0));
int wid = ivl_type_packed_msb(prop_type,0) - ivl_type_packed_lsb(prop_type,0) + 1;
struct vector_info val = draw_eval_expr_wid(rval, wid, STUFF_OK_XZ);
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
fprintf(vvp_out, " %%store/prop/v %d, %u, %u;\n", prop_idx, val.base, val.wid);
clr_vector(val);
} else {
/* There is no property select, so evaluate the r-value
as an object and assign the entire object to the
variable. */
errors += draw_eval_object(rval);
fprintf(vvp_out, " %%store/obj v%p_0;\n", sig);
}
errors += draw_eval_object(rval);
fprintf(vvp_out, " %%store/obj v%p_0;\n", var);
return errors;
}

View File

@ -131,6 +131,8 @@ extern struct vector_info draw_vpi_func_call(ivl_expr_t expr,
unsigned wid);
extern void draw_vpi_rfunc_call(ivl_expr_t expr);
extern void draw_class_in_scope(ivl_type_t classtype);
/*
* Enumeration draw routine.
*/

View File

@ -2228,6 +2228,11 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
}
}
for (idx = 0 ; idx < ivl_scope_classes(net) ; idx += 1) {
ivl_type_t class_type = ivl_scope_class(net,idx);
draw_class_in_scope(class_type);
}
/* Scan the scope for enumeration types, and write out
enumeration typespecs. */

View File

@ -72,7 +72,7 @@ V = vpi_modules.o vpi_callback.o vpi_cobject.o vpi_const.o vpi_darray.o \
vpip_to_dec.o vpip_format.o vvp_vpi.o
O = main.o parse.o parse_misc.o lexor.o arith.o array.o bufif.o compile.o \
concat.o dff.o enum_type.o extend.o file_line.o npmos.o part.o \
concat.o dff.o class_type.o enum_type.o extend.o file_line.o npmos.o part.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 \

67
vvp/class_type.cc Normal file
View File

@ -0,0 +1,67 @@
/*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "class_type.h"
# include "compile.h"
# include "vpi_priv.h"
# include <cassert>
using namespace std;
class_type::class_type(const string&nam, size_t nprop)
: class_name_(nam), properties_(nprop)
{
}
void class_type::set_property(size_t idx, const string&name)
{
assert(idx < properties_.size());
properties_[idx].name = name;
}
int class_type::get_type_code(void) const
{
return vpiClassDefn;
}
static class_type*compile_class = 0;
void compile_class_start(char*lab, char*nam, unsigned ntype)
{
assert(compile_class == 0);
compile_class = new class_type(nam, ntype);
compile_vpi_symbol(lab, compile_class);
delete[]lab;
delete[]nam;
}
void compile_class_property(unsigned idx, char*nam, char*typ)
{
assert(compile_class);
compile_class->set_property(idx, nam);
}
void compile_class_done(void)
{
struct __vpiScope*scope = vpip_peek_current_scope();
assert(scope);
scope->classes[compile_class->class_name()] = compile_class;
compile_class = 0;
}

57
vvp/class_type.h Normal file
View File

@ -0,0 +1,57 @@
#ifndef __class_type_H
#define __class_type_H
/*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include <string>
# include <vector>
# include "vpi_priv.h"
/*
* This represents the TYPE information for a class. A %new operator
* uses this information to figure out how to construct an actual
* instance.
*/
class class_type : public __vpiHandle {
public:
explicit class_type(const std::string&nam, size_t nprop);
// This is the name of the class type.
inline const std::string&class_name(void) const { return class_name_; }
// Number of properties in the class definition.
inline size_t property_count(void) const { return properties_.size(); }
// Set the details about the property. This is used during
// parse of the .vvp file to fill in the details of the
// property for the class definition.
void set_property(size_t idx, const std::string&name);
int get_type_code(void) const;
private:
std::string class_name_;
struct prop_t {
std::string name;
};
std::vector<prop_t> properties_;
};
#endif

View File

@ -163,6 +163,7 @@ extern bool of_POP_STR(vthread_t thr, vvp_code_t code);
extern bool of_POW(vthread_t thr, vvp_code_t code);
extern bool of_POW_S(vthread_t thr, vvp_code_t code);
extern bool of_POW_WR(vthread_t thr, vvp_code_t code);
extern bool of_PROP_V(vthread_t thr, vvp_code_t code);
extern bool of_PUSHI_STR(vthread_t thr, vvp_code_t code);
extern bool of_PUSHI_REAL(vthread_t thr, vvp_code_t code);
extern bool of_PUSHV_STR(vthread_t thr, vvp_code_t code);
@ -181,6 +182,7 @@ extern bool of_SHIFTR_S_I0(vthread_t thr, vvp_code_t code);
extern bool of_STORE_DAR_R(vthread_t thr, vvp_code_t code);
extern bool of_STORE_DAR_STR(vthread_t thr, vvp_code_t code);
extern bool of_STORE_OBJ(vthread_t thr, vvp_code_t code);
extern bool of_STORE_PROP_V(vthread_t thr, vvp_code_t code);
extern bool of_STORE_REAL(vthread_t thr, vvp_code_t code);
extern bool of_STORE_REALA(vthread_t thr, vvp_code_t code);
extern bool of_STORE_STR(vthread_t thr, vvp_code_t code);

View File

@ -197,8 +197,8 @@ 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/cobj", of_NEW_COBJ, 0, {OA_NONE,OA_NONE, OA_NONE} },
{ "%new/darray",of_NEW_DARRAY,2, {OA_BIT1,OA_STRING, OA_NONE} },
{ "%new/cobj", of_NEW_COBJ, 1, {OA_VPI_PTR,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} },
{ "%nor", of_NOR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%nor/r", of_NORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
@ -211,6 +211,7 @@ static const struct opcode_table_s opcode_table[] = {
{ "%pow", of_POW, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%pow/s", of_POW_S, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%pow/wr", of_POW_WR, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%prop/v", of_PROP_V, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%pushi/real",of_PUSHI_REAL,2,{OA_BIT1, OA_BIT2, OA_NONE} },
{ "%pushi/str", of_PUSHI_STR, 1,{OA_STRING, OA_NONE, OA_NONE} },
{ "%pushv/str", of_PUSHV_STR, 2, {OA_BIT1,OA_BIT2, OA_NONE} },
@ -227,10 +228,11 @@ static const struct opcode_table_s opcode_table[] = {
{ "%shiftr/s/i0", of_SHIFTR_S_I0,2,{OA_BIT1,OA_NUMBER, OA_NONE} },
{ "%store/dar/r", of_STORE_DAR_R, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
{ "%store/dar/str",of_STORE_DAR_STR, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
{ "%store/obj", of_STORE_OBJ, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
{ "%store/real", of_STORE_REAL, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
{ "%store/reala",of_STORE_REALA,2,{OA_ARR_PTR, OA_BIT1, OA_NONE} },
{ "%store/str", of_STORE_STR, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
{ "%store/obj", of_STORE_OBJ, 1, {OA_FUNC_PTR,OA_NONE, OA_NONE} },
{ "%store/prop/v",of_STORE_PROP_V,3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%store/real", of_STORE_REAL, 1, {OA_FUNC_PTR,OA_NONE, OA_NONE} },
{ "%store/reala", of_STORE_REALA, 2, {OA_ARR_PTR, OA_BIT1, 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, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%subi", of_SUBI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },

View File

@ -522,4 +522,8 @@ extern void compile_island_tranvp(char*island, char*ba, char*bb,
extern void delete_udp_symbols(void);
extern void compile_class_start(char*lab, char*nam, unsigned nprop);
extern void compile_class_property(unsigned idx, char*nam, char*typ);
extern void compile_class_done(void);
#endif

View File

@ -129,6 +129,7 @@ static char* strdupnew(char const *str)
".cast/int" { return K_CAST_INT; }
".cast/real" { return K_CAST_REAL; }
".cast/real.s" { return K_CAST_REAL_S; }
".class" { return K_CLASS; }
".cmp/eeq" { return K_CMP_EEQ; }
".cmp/eq" { return K_CMP_EQ; }
".cmp/eq.r" { return K_CMP_EQ_R; }

View File

@ -638,6 +638,15 @@ the object handle stack.
See also %store/obj.
* %load/prop/v <pid>, <bit>, <wid>
This instruction loads from a class object property into the specified
thread register bit. The <pid> is the number of the property and the
<bit> is the location where the loaded value goes.
The handle for the class object is found on the top of the object
stack, and the stack is NOT popped.
* %load/real <vpi-label>
The %load/real instruction reads a real value from the vpi-like object
@ -779,6 +788,11 @@ means the following:
otherwise x
* %new/cobj <label>
Create a new class object. The <label> is the VPI label for a class
type definition.
* %new/darray <idx>, "<type>"
Create a new array (of int objects) with a size. the <idx> is the
@ -871,6 +885,11 @@ replaces the left operand.
This opcode raises the left operand by the right operand, and pushes
the result.
* %prop/v <pid>, <base>, <wid>
Write the vector into property number <pid> of the class object on the
top of the object stack. The stack is NOT popped.
* %pushi/real <mant>, <exp>
This opcode loads an immediate value, floating point, into the real

View File

@ -79,6 +79,7 @@ static struct __vpiModPath*modpath_dst = 0;
%token K_ARITH_SUM K_ARITH_SUM_R K_ARITH_POW K_ARITH_POW_R K_ARITH_POW_S
%token K_ARRAY K_ARRAY_I K_ARRAY_R K_ARRAY_S K_ARRAY_PORT
%token K_CAST_INT K_CAST_REAL K_CAST_REAL_S K_CAST_2
%token K_CLASS
%token K_CMP_EEQ K_CMP_EQ K_CMP_EQ_R K_CMP_NEE K_CMP_NE K_CMP_NE_R
%token K_CMP_GE K_CMP_GE_R K_CMP_GE_S K_CMP_GT K_CMP_GT_R K_CMP_GT_S
%token K_CONCAT K_DEBUG K_DELAY K_DFF
@ -821,6 +822,11 @@ statement
/* Other statemehts */
| T_LABEL K_CLASS T_STRING '[' T_NUMBER ']'
{ compile_class_start($1, $3, $5); }
class_properties ';'
{ compile_class_done(); }
| enum_type
{ ; }
@ -829,6 +835,16 @@ statement
| ';'
;
class_properties
: class_properties class_property
| class_property
;
class_property
: T_NUMBER ':' T_STRING ',' T_STRING
{ compile_class_property($1, $3, $5); }
;
/* Enumeration types */
enum_type
: T_LABEL K_ENUM2 '(' T_NUMBER ')' enum_type_names ';'

View File

@ -23,6 +23,7 @@
# include "vvp_net.h"
# include "config.h"
# include <map>
# include <set>
# include <string>
@ -33,6 +34,8 @@
#include "delay.h"
class class_type;
/*
* This header file contains the internal definitions that the vvp
* program uses to implement the public interface in the vpi_user.h
@ -234,6 +237,8 @@ struct __vpiScope : public __vpiHandle {
/* Keep an array of internal scope items. */
class __vpiHandle**intern;
unsigned nintern;
/* Set of types */
std::map<std::string,class_type*> classes;
/* Keep an array of items to be automatically allocated */
struct automatic_hooks_s**item;
unsigned nitem;

View File

@ -27,6 +27,7 @@
# include "vvp_net_sig.h"
# include "vvp_cobject.h"
# include "vvp_darray.h"
# include "class_type.h"
#ifdef CHECK_WITH_VALGRIND
# include "vvp_cleanup.h"
#endif
@ -89,6 +90,8 @@ using namespace std;
*/
struct vthread_s {
vthread_s();
/* This is the program counter. */
vvp_code_t pc;
/* These hold the private thread bits. */
@ -163,19 +166,27 @@ struct vthread_s {
/* Objects are also operated on in a stack. */
private:
vector<vvp_object_t> stack_obj_;
enum { STACK_OBJ_MAX_SIZE = 32 };
vvp_object_t stack_obj_[STACK_OBJ_MAX_SIZE];
int stack_obj_size_;
public:
inline vvp_object_t pop_object(void)
inline vvp_object_t& peek_object(void)
{
assert(stack_obj_.size() > 0);
vvp_object_t val = stack_obj_.back();
stack_obj_.back().reset();
stack_obj_.pop_back();
return val;
assert(stack_obj_size_ > 0);
return stack_obj_[stack_obj_size_-1];
}
inline void push_object(vvp_object_t obj)
inline void pop_object(vvp_object_t&obj)
{
stack_obj_.push_back(obj);
assert(stack_obj_size_ > 0);
stack_obj_size_ -= 1;
obj = stack_obj_[stack_obj_size_];
stack_obj_[stack_obj_size_].reset(0);
}
inline void push_object(const vvp_object_t&obj)
{
assert(stack_obj_size_ < STACK_OBJ_MAX_SIZE);
stack_obj_[stack_obj_size_] = obj;
stack_obj_size_ += 1;
}
/* My parent sets this when it wants me to wake it up. */
@ -201,6 +212,11 @@ struct vthread_s {
uint64_t ecount;
};
inline vthread_s::vthread_s()
{
stack_obj_size_ = 0;
}
static bool test_joinable(vthread_t thr, vthread_t child);
static void do_join(vthread_t thr, vthread_t child);
@ -4085,14 +4101,17 @@ bool of_NAND(vthread_t thr, vvp_code_t cp)
}
/*
* %new/cobj
* %new/cobj <vpi_object>
* This creates a new cobject (SystemVerilog class object) and pushes
* it to the stack.
* it to the stack. The <vpi-object> is a __vpiHandle that is a
* vpiClassDefn object that defines the item to be created.
*/
bool of_NEW_COBJ(vthread_t thr, vvp_code_t cp)
{
vvp_object_t tmp;
tmp = new vvp_cobject;
const class_type*defn = dynamic_cast<const class_type*> (cp->handle);
assert(defn);
vvp_object_t tmp (new vvp_cobject(defn));
thr->push_object(tmp);
return true;
}
@ -4164,7 +4183,7 @@ bool of_NORR(vthread_t thr, vvp_code_t cp)
/*
* Push a null to the object stack.
*/
bool of_NULL(vthread_t thr, vvp_code_t cp)
bool of_NULL(vthread_t thr, vvp_code_t)
{
vvp_object_t tmp;
thr->push_object(tmp);
@ -4480,6 +4499,38 @@ bool of_POW_WR(vthread_t thr, vvp_code_t)
return true;
}
/*
* %prop/v <pid> <base> <wid>
*
* Load a property <id> from the cobject on the top of the stack into
* the vector space at <base>.
*/
bool of_PROP_V(vthread_t thr, vvp_code_t cp)
{
unsigned pid = cp->bit_idx[0];
unsigned dst = cp->bit_idx[1];
unsigned wid = cp->number;
thr_check_addr(thr, dst+wid-1);
vvp_object_t&obj = thr->peek_object();
vvp_cobject*cobj = obj.peek<vvp_cobject>();
vvp_vector4_t val;
cobj->get_vec4(pid, val);
if (val.size() > wid)
val.resize(wid);
thr->bits4.set_vec(dst, val);
if (val.size() < wid) {
for (unsigned idx = val.size() ; idx < wid ; idx += 1)
thr->bits4.set_bit(dst+idx, BIT4_X);
}
return true;
}
bool of_PUSHI_REAL(vthread_t thr, vvp_code_t cp)
{
double mant = cp->bit_idx[0];
@ -4981,13 +5032,35 @@ 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);
vvp_object_t val = thr->pop_object();
vvp_object_t val;
thr->pop_object(val);
vvp_send_object(ptr, val, thr->wt_context);
return true;
}
/*
* %store/prop/v <id> <base> <wid>
*
* Store vector value into property <id> of cobject in the top of the stack.
*/
bool of_STORE_PROP_V(vthread_t thr, vvp_code_t cp)
{
size_t pid = cp->bit_idx[0];
unsigned src = cp->bit_idx[1];
unsigned wid = cp->number;
vvp_vector4_t val = vthread_bits_to_vector(thr, src, wid);
vvp_object_t&obj = thr->peek_object();
vvp_cobject*cobj = obj.peek<vvp_cobject>();
assert(cobj);
cobj->set_vec4(pid, val);
return true;
}
bool of_STORE_REAL(vthread_t thr, vvp_code_t cp)
{
double val = thr->pop_real();

View File

@ -18,13 +18,40 @@
*/
# include "vvp_cobject.h"
# include "class_type.h"
# include <iostream>
# include <cassert>
using namespace std;
vvp_cobject::vvp_cobject(void)
vvp_cobject::vvp_cobject(const class_type*defn)
: defn_(defn), properties_(new int32_t[defn->property_count()])
{
}
vvp_cobject::~vvp_cobject()
{
delete[]properties_;
properties_ = 0;
}
void vvp_cobject::set_vec4(size_t pid, const vvp_vector4_t&val)
{
assert(pid < defn_->property_count());
int32_t tmp;
bool flag = vector4_to_value(val, tmp, true, false);
assert(flag);
properties_[pid] = tmp;
}
void vvp_cobject::get_vec4(size_t pid, vvp_vector4_t&val)
{
assert(pid < defn_->property_count());
unsigned long tmp[1];
tmp[0] = properties_[pid];
val.resize(32);
val.setarray(0, 32, tmp);
}

View File

@ -21,15 +21,22 @@
# include "vvp_object.h"
class class_type;
class vvp_vector4_t;
class vvp_cobject : public vvp_object {
public:
vvp_cobject();
explicit vvp_cobject(const class_type*defn);
~vvp_cobject();
void set_vec4(size_t pid, const vvp_vector4_t&val);
void get_vec4(size_t pid, vvp_vector4_t&val);
private:
int stub_;
const class_type* defn_;
// For now, only support 32bit bool signed properties.
int32_t*properties_;
};
#endif

View File

@ -45,6 +45,7 @@ class vvp_object_t {
public:
inline vvp_object_t() : ref_(0) { }
vvp_object_t(const vvp_object_t&that);
explicit vvp_object_t(class vvp_object*that);
~vvp_object_t();
vvp_object_t& operator = (const vvp_object_t&that);
@ -70,6 +71,12 @@ inline vvp_object_t::vvp_object_t(const vvp_object_t&that)
if (ref_) ref_->ref_cnt_ += 1;
}
inline vvp_object_t::vvp_object_t(class vvp_object*tgt)
{
if (tgt) tgt->ref_cnt_ += 1;
ref_ = tgt;
}
inline vvp_object_t::~vvp_object_t()
{
reset(0);