diff --git a/vhdlpp/std_funcs.cc b/vhdlpp/std_funcs.cc index 93da71b82..7dab67cc7 100644 --- a/vhdlpp/std_funcs.cc +++ b/vhdlpp/std_funcs.cc @@ -199,6 +199,28 @@ void preload_std_funcs(void) fn_std_logic_vector_args, &primitive_STDLOGIC_VECTOR); register_std_subprogram(fn_std_logic_vector); + /* numeric_std library + * function shift_left (arg: unsigned; count: natural) return unsigned; + */ + std::list*fn_shift_left_args = new std::list(); + fn_shift_left_args->push_back(new InterfacePort(&primitive_UNSIGNED)); + fn_shift_left_args->push_back(new InterfacePort(&primitive_UNSIGNED)); + SubprogramBuiltin*fn_shift_left = new SubprogramBuiltin(perm_string::literal("shift_left"), + perm_string::literal("$ivlh_shift_left"), + fn_shift_left_args, &primitive_UNSIGNED); + register_std_subprogram(fn_shift_left); + + /* numeric_std library + * function shift_right (arg: unsigned; count: natural) return unsigned; + */ + std::list*fn_shift_right_args = new std::list(); + fn_shift_right_args->push_back(new InterfacePort(&primitive_UNSIGNED)); + fn_shift_right_args->push_back(new InterfacePort(&primitive_UNSIGNED)); + SubprogramBuiltin*fn_shift_right = new SubprogramBuiltin(perm_string::literal("shift_right"), + perm_string::literal("$ivlh_shift_right"), + fn_shift_right_args, &primitive_UNSIGNED); + register_std_subprogram(fn_shift_right); + /* function resize */ fn_resize = new SubprogramSizeCast(perm_string::literal("resize")); diff --git a/vpi/Makefile.in b/vpi/Makefile.in index 4a5502902..aebdb70b2 100644 --- a/vpi/Makefile.in +++ b/vpi/Makefile.in @@ -75,7 +75,7 @@ V = va_math.o V2009 = v2009_table.o v2009_array.o v2009_enum.o v2009_string.o -VHDL_SYS = vhdl_table.o +VHDL_SYS = vhdl_table.o sys_priv.o VHDL_TEXTIO = vhdl_textio.o sys_priv.o diff --git a/vpi/vhdl_sys.sft b/vpi/vhdl_sys.sft index d0d452212..86903476f 100644 --- a/vpi/vhdl_sys.sft +++ b/vpi/vhdl_sys.sft @@ -1,3 +1,6 @@ $ivlh_attribute_event vpiSysFuncSized 1 unsigned $ivlh_rising_edge vpiSysFuncSized 1 unsigned $ivlh_falling_edge vpiSysFuncSized 1 unsigned + +$ivlh_shift_left vpiSysFuncSized 32 unsigned +$ivlh_shift_right vpiSysFuncSized 32 unsigned diff --git a/vpi/vhdl_table.c b/vpi/vhdl_table.c index a6db9c717..64cfe0386 100644 --- a/vpi/vhdl_table.c +++ b/vpi/vhdl_table.c @@ -21,6 +21,7 @@ # include "vpi_user.h" # include # include "ivl_alloc.h" +# include "sys_priv.h" /* * The $ivlh_attribute_event implements the VHDL 'event @@ -50,6 +51,14 @@ static const char* attr_func_names[] = { "$ivlh_rising_edge", "$ivlh_falling_edge" }; + +typedef enum { + SHIFT_LEFT = 0, + SHIFT_RIGHT = 1, +} shift_type_t; +static const char* shift_func_names[] = { + "$ivlh_shift_left", + "$ivlh_shift_right", }; /* To keep valgrind happy free the allocated memory. */ @@ -185,6 +194,43 @@ static PLI_INT32 ivlh_attribute_event_sizetf(ICARUS_VPI_CONST PLI_BYTE8*type) return 1; } +static PLI_INT32 ivlh_shift_calltf(ICARUS_VPI_CONST PLI_BYTE8*data) +{ + shift_type_t shift_type = (shift_type_t) data; + vpiHandle callh = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, callh); + vpiHandle argh = vpi_scan(argv); + vpiHandle counth = vpi_scan(argv); + s_vpi_value val; + PLI_INT32 count; + + vpi_free_object(argv); + + val.format = vpiIntVal; + vpi_get_value(counth, &val); + count = val.value.integer; + + val.format = vpiIntVal; + vpi_get_value(argh, &val); + + if(shift_type == SHIFT_LEFT) + val.value.integer <<= count; + else if(shift_type == SHIFT_RIGHT) + val.value.integer >>= count; + else + assert(0); + + vpi_put_value(callh, &val, 0, vpiNoDelay); + + return 0; +} + +static PLI_INT32 ivlh_shift_sizetf(ICARUS_VPI_CONST PLI_BYTE8*type) +{ + (void) type; /* Parameter is not used. */ + return 32; +} + static void vhdl_register(void) { s_vpi_systf_data tf_data; @@ -210,6 +256,22 @@ static void vhdl_register(void) tf_data.tfname = attr_func_names[FALLING_EDGE]; tf_data.user_data = (PLI_BYTE8*) FALLING_EDGE; res = vpi_register_systf(&tf_data); + vpip_make_systf_system_defined(res); + + /* Shift functions */ + tf_data.type = vpiSysFunc; + tf_data.sysfunctype = vpiSizedFunc; + tf_data.calltf = ivlh_shift_calltf; + tf_data.compiletf = sys_two_numeric_args_compiletf; + tf_data.sizetf = ivlh_shift_sizetf; + tf_data.tfname = shift_func_names[SHIFT_LEFT]; + tf_data.user_data = (PLI_BYTE8*) SHIFT_LEFT; + res = vpi_register_systf(&tf_data); + vpip_make_systf_system_defined(res); + + tf_data.tfname = shift_func_names[SHIFT_RIGHT]; + tf_data.user_data = (PLI_BYTE8*) SHIFT_RIGHT; + res = vpi_register_systf(&tf_data); vpip_make_systf_system_defined(res); /* Create a callback to clear the monitor data memory when the