Initial implementation of $ivl_method$next/prev

Create the v2009.vpi module to include SystemVerilog core
functions, and start out with some of the enum methods.

Add to vvp support for creating enum types, including some
vpi access methods.
This commit is contained in:
Stephen Williams 2010-11-17 20:00:23 -08:00
parent 00c1176a5d
commit 0c72dfe60f
15 changed files with 487 additions and 6 deletions

4
.gitignore vendored
View File

@ -7,6 +7,9 @@
# Object files and libraries
*.[oa]
gmon*.out
gmon*.txt
# From autoconf
configure
config.log
@ -54,6 +57,7 @@ dep
/vpi/sdf_parse.output
/vpi/sys_readmem_lex.c
/vvp/dump.*
/vvp/lexor.cc
/vvp/parse.cc
/vvp/parse.h

View File

@ -49,6 +49,13 @@ EXTERN_C_START
#define vpiByteVar 614
#define vpiLogicVar vpiReg
/********* TYPESPECS *************/
#define vpiEnumTypespec 633
#define vpiEnumConst 634
/********* Many-to-One ***********/
#define vpiMember 742
EXTERN_C_END
#endif

View File

@ -73,7 +73,9 @@ M = sys_clog2.o v2005_math.o
# Object files for va_math.vpi
V = va_math.o
all: dep system.vpi va_math.vpi v2005_math.vpi $(ALL32)
V2009 = v2009_table.o v2009_enum.o
all: dep system.vpi va_math.vpi v2005_math.vpi v2009.vpi $(ALL32)
check: all
@ -128,6 +130,9 @@ sdf_parse.c sdf_parse.h: $(srcdir)/sdf_parse.y
v2005_math.vpi: $M ../vvp/libvpi.a
$(CC) @shared@ -o $@ $M -L../vvp $(LDFLAGS) -lvpi $(VA_MATH_VPI_LDFLAGS)
v2009.vpi: $(V2009) ../vvp/libvpi.a
$(CC) @shared@ -o $@ $(V2009) -L../vvp $(LDFLAGS) -lvpi $(SYSTEM_VPI_LDFLAGS)
va_math.vpi: $V ../vvp/libvpi.a
$(CC) @shared@ -o $@ $V -L../vvp $(LDFLAGS) -lvpi $(VA_MATH_VPI_LDFLAGS)
@ -139,7 +144,8 @@ vpi_config.h: stamp-vpi_config-h
install: all installdirs \
$(vpidir)/system.vpi $(vpidir)/system.sft \
$(vpidir)/va_math.vpi $(vpidir)/va_math.sft \
$(vpidir)/v2005_math.vpi $(vpidir)/v2005_math.sft
$(vpidir)/v2005_math.vpi $(vpidir)/v2005_math.sft \
$(vpidir)/v2009.vpi $(vpidir)/v2009.sft \
$(vpidir)/system.vpi: ./system.vpi
$(INSTALL_PROGRAM) ./system.vpi "$(DESTDIR)$(vpidir)/system.vpi"
@ -159,6 +165,12 @@ $(vpidir)/v2005_math.vpi: ./v2005_math.vpi
$(vpidir)/v2005_math.sft: v2005_math.sft
$(INSTALL_DATA) $< "$(DESTDIR)$@"
$(vpidir)/v2009_math.vpi: ./v2009.vpi
$(INSTALL_PROGRAM) ./v2009.vpi "$(DESTDIR)$(vpidir)/v2009.vpi"
$(vpidir)/v2009.sft: v2009.sft
$(INSTALL_DATA) $< "$(DESTDIR)$@"
installdirs: $(srcdir)/../mkinstalldirs
$(srcdir)/../mkinstalldirs "$(DESTDIR)$(libdir)" "$(DESTDIR)$(vpidir)"
@ -169,6 +181,8 @@ uninstall:
rm -f "$(DESTDIR)$(vpidir)/va_math.sft"
rm -f "$(DESTDIR)$(vpidir)/v2005_math.vpi"
rm -f "$(DESTDIR)$(vpidir)/v2005_math.sft"
rm -f "$(DESTDIR)$(vpidir)/v2009.vpi"
rm -f "$(DESTDIR)$(vpidir)/v2009.sft"
-include $(patsubst %.o, dep/%.d, $O)
-include $(patsubst %.o, dep/%.d, $(OPP))

5
vpi/v2009.sft Normal file
View File

@ -0,0 +1,5 @@
#
# This is the system function descriptor table for the
# builtin (system) functions.
#

187
vpi/v2009_enum.c Normal file
View File

@ -0,0 +1,187 @@
/*
* Copyright (c) 2010 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 "vpi_config.h"
# include "sv_vpi_user.h"
# include <assert.h>
static void missing_arguments(vpiHandle sys)
{
vpi_printf("%s:%d: error: Invalid/missing arguments next/prev method\n",
vpi_get_str(vpiFile, sys), vpi_get(vpiLineNo,sys));
vpi_control(vpiFinish, 1);
}
static PLI_INT32 ivl_method_next_prev_compiletf(ICARUS_VPI_CONST PLI_BYTE8*data)
{
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, sys);
vpiHandle arg_enum, arg_item, arg_extra;
if (argv == 0) {
missing_arguments(sys);
return 0;
}
arg_enum = vpi_scan(argv);
if (arg_enum == 0) {
missing_arguments(sys);
return 0;
}
arg_item = vpi_scan(argv);
if (arg_item == 0) {
missing_arguments(sys);
return 0;
}
/* Make sure there are no excess arguments */
arg_extra = vpi_scan(argv);
if (arg_extra != 0) {
missing_arguments(sys);
vpi_free_object(argv);
return 0;
}
/* The first argument must be an enum typespec */
if (vpi_get(vpiType, arg_enum) != vpiEnumTypespec) {
missing_arguments(sys);
return 0;
}
/* The return value and input value must be the same size */
if (vpi_get(vpiSize,sys) != vpi_get(vpiSize,arg_item)) {
missing_arguments(sys);
return 0;
}
return 0;
}
static PLI_INT32 ivl_method_next2_calltf(PLI_BYTE8*data)
{
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, sys);
vpiHandle arg_enum = vpi_scan(argv);
vpiHandle arg_item = vpi_scan(argv);
vpiHandle arg_extra = vpi_scan(argv);
vpiHandle enum_list = 0;
vpiHandle memb = 0, first_memb = 0;
s_vpi_value memb_value, item_value;
assert(arg_extra == 0);
item_value.format = vpiIntVal;
vpi_get_value(arg_item, &item_value);
enum_list = vpi_iterate(vpiMember, arg_enum);
assert(enum_list);
/* Search for the current value in the member list. */
do {
memb = vpi_scan(enum_list);
if (first_memb == 0) first_memb = memb;
if (memb == 0) break;
memb_value.format = vpiIntVal;
vpi_get_value(memb, &memb_value);
} while (memb_value.value.integer != item_value.value.integer);
if (memb != 0);
memb = vpi_scan(enum_list);
if (memb != 0)
vpi_free_object(enum_list);
if (memb == 0) {
memb = first_memb;
memb_value.format = vpiIntVal;
}
vpi_get_value(memb, &memb_value);
vpi_put_value(sys, &memb_value, 0, vpiNoDelay);
return 0;
}
static PLI_INT32 ivl_method_prev2_calltf(PLI_BYTE8*data)
{
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, sys);
vpiHandle arg_enum = vpi_scan(argv);
vpiHandle arg_item = vpi_scan(argv);
vpiHandle arg_extra = vpi_scan(argv);
vpiHandle enum_list = 0;
vpiHandle memb = 0, prev = 0, last_memb = 0;
s_vpi_value memb_value, item_value;
assert(arg_extra == 0);
item_value.format = vpiIntVal;
vpi_get_value(arg_item, &item_value);
enum_list = vpi_iterate(vpiMember, arg_enum);
assert(enum_list);
/* Search for the current value in the member list. */
do {
prev = memb;
memb = vpi_scan(enum_list);
if (memb == 0) break;
last_memb = memb;
memb_value.format = vpiIntVal;
vpi_get_value(memb, &memb_value);
} while (memb_value.value.integer != item_value.value.integer);
while (memb) {
last_memb = memb;
memb = vpi_scan(enum_list);
}
if (prev == 0)
prev = last_memb;
vpi_get_value(prev, &memb_value);
vpi_put_value(sys, &memb_value, 0, vpiNoDelay);
return 0;
}
void v2009_enum_register(void)
{
s_vpi_systf_data tf_data;
tf_data.type = vpiSysFunc;
tf_data.calltf = ivl_method_next2_calltf;
tf_data.compiletf = ivl_method_next_prev_compiletf;
tf_data.sizetf = 0;
tf_data.tfname = "$ivl_method$next";
tf_data.user_data = "$ivl_method$next";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysFunc;
tf_data.calltf = ivl_method_prev2_calltf;
tf_data.compiletf = 0;
tf_data.sizetf = 0;
tf_data.tfname = "$ivl_method$prev";
tf_data.user_data = "$ivl_method$prev";
vpi_register_systf(&tf_data);
}

31
vpi/v2009_table.c Normal file
View File

@ -0,0 +1,31 @@
/*
* Copyright (c) 2010 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 "vpi_config.h"
# include "vpi_user.h"
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
extern void v2009_enum_register(void);
void (*vlog_startup_routines[])() = {
v2009_enum_register,
0
};

View File

@ -67,7 +67,8 @@ V = vpi_modules.o vpi_callback.o vpi_const.o vpi_event.o vpi_iter.o vpi_mcd.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 extend.o npmos.o part.o permaheap.o reduce.o resolv.o \
concat.o dff.o enum_type.o extend.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 \
event.o logic.o delay.o words.o island_tran.o $V

View File

@ -21,6 +21,7 @@
# include <cstdio>
# include <fstream>
# include <list>
# include <vector>
# include "parse_misc.h"
# include "sv_vpi_user.h"
@ -201,6 +202,8 @@ extern void compile_dff(char*label,
struct symb_s arg_e,
struct symb_s arg_a);
extern void compile_enum_type(char*label, std::list<struct enum_name_s>*names);
class __vpiModPath;
extern __vpiModPath* compile_modpath(char*label,
unsigned width,

145
vvp/enum_type.cc Normal file
View File

@ -0,0 +1,145 @@
/*
* Copyright (c) 2010 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 "compile.h"
# include "enum_type.h"
# include <iostream>
# include <cassert>
struct enumconst_s {
struct __vpiHandle base;
const char*name;
vvp_vector2_t val2;
};
static struct enumconst_s* enumconst_from_handle(vpiHandle obj)
{
if (obj->vpi_type->type_code == vpiEnumConst)
return (struct enumconst_s*) obj;
else
return 0;
}
struct __vpiEnumTypespec {
struct __vpiHandle base;
std::vector<enumconst_s> names;
};
static struct __vpiEnumTypespec* vpip_enum_typespec_from_handle(vpiHandle obj)
{
if (obj->vpi_type->type_code == vpiEnumTypespec)
return (struct __vpiEnumTypespec*) obj;
return 0;
}
static vpiHandle enum_type_iterate(int code, vpiHandle obj)
{
struct __vpiEnumTypespec*ref = vpip_enum_typespec_from_handle(obj);
assert(ref);
if (code == vpiMember) {
vpiHandle*args = (vpiHandle*)
calloc(ref->names.size(), sizeof(vpiHandle*));
for (int idx = 0 ; idx < ref->names.size() ; idx += 1)
args[idx] = vpi_handle(&ref->names[idx]);
return vpip_make_iterator(ref->names.size(), args, true);
}
return 0;
}
static const struct __vpirt enum_type_rt = {
vpiEnumTypespec,
0, //enum_type_get,
0, //enum_type_get_str,
0, //enum_type_get_value,
0, //enum_type_put_value,
0, //enum_type_handle,
enum_type_iterate,
0, //enum_type_index,
0, //enum_type_free_object,
0, //enum_type_get_delays,
0, //enum_type_put_delays
};
static char* enum_name_get_str(int code, vpiHandle obj)
{
struct enumconst_s*ref = enumconst_from_handle(obj);
assert(ref);
switch (code) {
case vpiName:
return const_cast<char*> (ref->name);
default:
return 0;
}
}
static void enum_name_get_value(vpiHandle obj, p_vpi_value value)
{
struct enumconst_s*ref = enumconst_from_handle(obj);
assert(ref);
switch (value->format) {
case vpiObjTypeVal:
value->format = vpiIntVal;
case vpiIntVal:
vector2_to_value(ref->val2, value->value.integer, true);
break;
default:
break;
}
}
static const struct __vpirt enum_name_rt = {
vpiEnumConst,
0, //enum_name_get,
enum_name_get_str,
enum_name_get_value,
0, //enum_name_put_value,
0, //enum_name_handle,
0, //enum_name_iterate,
0, //enum_name_index,
0, //enum_name_free_object,
0, //enum_name_get_delays,
0, //enum_name_put_delays
};
void compile_enum_type(char*label, std::list<struct enum_name_s>*names)
{
struct __vpiEnumTypespec*spec = new struct __vpiEnumTypespec;
spec->base.vpi_type = &enum_type_rt;
spec->names = std::vector<enumconst_s> (names->size());
size_t idx = 0;
for (list<struct enum_name_s>::iterator cur = names->begin()
; cur != names->end() ; ++cur, ++idx) {
spec->names[idx].base.vpi_type = &enum_name_rt;
spec->names[idx].name = cur->text;
spec->names[idx].val2 = vvp_vector2_t(cur->val2, 32);
}
assert(idx == spec->names.size());
compile_vpi_symbol(label, vpi_handle(spec));
free(label);
delete names;
}

22
vvp/enum_type.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef __enum_type_H
#define __enum_type_H
/*
* Copyright (c) 2010 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
*/
#endif

View File

@ -142,6 +142,7 @@ static char* strdupnew(char const *str)
".concat" { return K_CONCAT; }
".delay" { return K_DELAY; }
".dff" { return K_DFF; }
".enum" { return K_ENUM; }
".event" { return K_EVENT; }
".event/or" { return K_EVENT_OR; }
".export" { return K_EXPORT; }

View File

@ -23,6 +23,7 @@
# include "compile.h"
# include "delay.h"
# include "ivl_alloc.h"
# include <list>
# include <cstdio>
# include <cstdlib>
# include <cassert>
@ -58,6 +59,9 @@ static struct __vpiModPath*modpath_dst = 0;
struct numbv_s numbv;
struct enum_name_s enum_name;
std::list<struct enum_name_s>*enum_namev;
struct symb_s vect;
struct argv_s argv;
@ -76,7 +80,7 @@ static struct __vpiModPath*modpath_dst = 0;
%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
%token K_EVENT K_EVENT_OR K_EXPORT K_EXTEND_S K_FUNCTOR K_IMPORT K_ISLAND
%token K_ENUM K_EVENT K_EVENT_OR K_EXPORT K_EXTEND_S K_FUNCTOR K_IMPORT K_ISLAND
%token K_MODPATH
%token K_NET K_NET_S K_NET_R K_NET_2S K_NET_2U K_NET8 K_NET8_S
%token K_PARAM_STR K_PARAM_L K_PARAM_REAL K_PART K_PART_PV
@ -112,6 +116,9 @@ static struct __vpiModPath*modpath_dst = 0;
%type <vpi> argument symbol_access
%type <cdelay> delay
%type <enum_name> enum_type_name
%type <enum_namev> enum_type_names
%%
source_file : header_lines_opt program footer_lines;
@ -780,10 +787,39 @@ statement
| K_TRANVP T_NUMBER T_NUMBER T_NUMBER ',' T_SYMBOL ',' T_SYMBOL T_SYMBOL ';'
{ compile_island_tranvp($6, $8, $9, $2, $3, $4); }
/* Other statemehts */
| enum_type
{ ; }
/* Oh and by the way, empty statements are OK as well. */
| ';'
;
| ';'
;
/* Enumeration types */
enum_type
: T_LABEL K_ENUM enum_type_names ';'
{ compile_enum_type($1, $3); }
;
enum_type_names
: enum_type_name
{ list<struct enum_name_s>*tmp = new list<struct enum_name_s>;
tmp->push_back($1);
$$ = tmp;
}
| enum_type_names ',' enum_type_name
{ list<struct enum_name_s>*tmp = $1;
tmp->push_back($3);
$$ = tmp;
}
;
enum_type_name
: T_STRING T_NUMBER
{ $$.text = $1; $$.val2 = $2; }
;
local_flag
: '*' { $$ = true; }

View File

@ -70,6 +70,11 @@ struct numbv_s {
long*nvec;
};
struct enum_name_s {
char*text;
uint64_t val2;
};
extern void numbv_init(struct numbv_s*obj);
extern void numbv_add(struct numbv_s*obj, long item);
extern void numbv_clear(struct numbv_s*obj);

View File

@ -1697,6 +1697,24 @@ bool vector4_to_value(const vvp_vector4_t&vec, double&val, bool signed_flag)
return flag;
}
bool vector2_to_value(const vvp_vector2_t&a, int32_t&val, bool is_signed)
{
val = 0;
int idx;
int32_t mask;
for (idx = 0, mask = 1 ; idx < a.size() && idx < 32 ; idx += 1, mask <<= 1) {
if (a.value(idx)) val |= mask;
}
if (is_signed && a.size() < 32 && a.value(a.size()-1)) {
mask = -1;
mask <<= a.size();
val |= mask;
}
return a.size() <= 32;
}
vvp_realarray_t::vvp_realarray_t(unsigned wor)
: words_(wor)
{

View File

@ -496,6 +496,8 @@ extern bool vector4_to_value(const vvp_vector4_t&a, vvp_time64_t&val);
#endif
extern bool vector4_to_value(const vvp_vector4_t&a, double&val, bool is_signed);
extern bool vector2_to_value(const vvp_vector2_t&a, int32_t&val, bool is_signed);
/*
* The __vpiArray handle uses instances of this to keep an array of
* real valued variables.