diff --git a/.gitignore b/.gitignore index 538236514..21e8b33cb 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/sv_vpi_user.h b/sv_vpi_user.h index d06c16689..d613f1185 100644 --- a/sv_vpi_user.h +++ b/sv_vpi_user.h @@ -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 diff --git a/vpi/Makefile.in b/vpi/Makefile.in index a9720dbd7..d57f6c1ef 100644 --- a/vpi/Makefile.in +++ b/vpi/Makefile.in @@ -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)) diff --git a/vpi/v2009.sft b/vpi/v2009.sft new file mode 100644 index 000000000..a606d187d --- /dev/null +++ b/vpi/v2009.sft @@ -0,0 +1,5 @@ +# +# This is the system function descriptor table for the +# builtin (system) functions. +# + diff --git a/vpi/v2009_enum.c b/vpi/v2009_enum.c new file mode 100644 index 000000000..bcb8e80df --- /dev/null +++ b/vpi/v2009_enum.c @@ -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 + +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); +} diff --git a/vpi/v2009_table.c b/vpi/v2009_table.c new file mode 100644 index 000000000..be21785d3 --- /dev/null +++ b/vpi/v2009_table.c @@ -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 +# include +# include + +extern void v2009_enum_register(void); + +void (*vlog_startup_routines[])() = { + v2009_enum_register, + 0 +}; diff --git a/vvp/Makefile.in b/vvp/Makefile.in index b5be44e01..d959f14c3 100644 --- a/vvp/Makefile.in +++ b/vvp/Makefile.in @@ -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 diff --git a/vvp/compile.h b/vvp/compile.h index 4eaa051a5..43edf40fb 100644 --- a/vvp/compile.h +++ b/vvp/compile.h @@ -21,6 +21,7 @@ # include # include +# include # include # 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*names); + class __vpiModPath; extern __vpiModPath* compile_modpath(char*label, unsigned width, diff --git a/vvp/enum_type.cc b/vvp/enum_type.cc new file mode 100644 index 000000000..06aefca48 --- /dev/null +++ b/vvp/enum_type.cc @@ -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 +# include + +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 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 (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*names) +{ + struct __vpiEnumTypespec*spec = new struct __vpiEnumTypespec; + spec->base.vpi_type = &enum_type_rt; + spec->names = std::vector (names->size()); + + size_t idx = 0; + for (list::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; +} diff --git a/vvp/enum_type.h b/vvp/enum_type.h new file mode 100644 index 000000000..78464aab3 --- /dev/null +++ b/vvp/enum_type.h @@ -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 diff --git a/vvp/lexor.lex b/vvp/lexor.lex index 6dfee86a1..2736cb765 100644 --- a/vvp/lexor.lex +++ b/vvp/lexor.lex @@ -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; } diff --git a/vvp/parse.y b/vvp/parse.y index a77ead1ee..c9936c97d 100644 --- a/vvp/parse.y +++ b/vvp/parse.y @@ -23,6 +23,7 @@ # include "compile.h" # include "delay.h" # include "ivl_alloc.h" +# include # include # include # include @@ -58,6 +59,9 @@ static struct __vpiModPath*modpath_dst = 0; struct numbv_s numbv; + struct enum_name_s enum_name; + std::list*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 argument symbol_access %type delay +%type enum_type_name +%type 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*tmp = new list; + tmp->push_back($1); + $$ = tmp; + } + | enum_type_names ',' enum_type_name + { list*tmp = $1; + tmp->push_back($3); + $$ = tmp; + } + ; + +enum_type_name + : T_STRING T_NUMBER + { $$.text = $1; $$.val2 = $2; } + ; local_flag : '*' { $$ = true; } diff --git a/vvp/parse_misc.h b/vvp/parse_misc.h index 85c01240b..81c8d00fe 100644 --- a/vvp/parse_misc.h +++ b/vvp/parse_misc.h @@ -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); diff --git a/vvp/vvp_net.cc b/vvp/vvp_net.cc index a1a5acc75..27788c3c4 100644 --- a/vvp/vvp_net.cc +++ b/vvp/vvp_net.cc @@ -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) { diff --git a/vvp/vvp_net.h b/vvp/vvp_net.h index aa531b8af..1e58d6df5 100644 --- a/vvp/vvp_net.h +++ b/vvp/vvp_net.h @@ -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.