From 1527b8759577de1eed2bcbd15c6c0c6e3079f77f Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Wed, 2 Jan 2013 19:02:02 -0800 Subject: [PATCH 1/2] Remove useless vvp_realarray_t The vvp_darray_real class cal be used for static arrays as well and this is a more general solution anyhow. Kill the now useless vvp_realarray_t class. --- vvp/array.cc | 32 ++++++++++++++++++++++---------- vvp/vvp_net.cc | 30 ------------------------------ vvp/vvp_net.h | 21 +-------------------- 3 files changed, 23 insertions(+), 60 deletions(-) diff --git a/vvp/array.cc b/vvp/array.cc index 26bf2d6ff..dd3b8fd0a 100644 --- a/vvp/array.cc +++ b/vvp/array.cc @@ -18,11 +18,12 @@ */ # include "array.h" -#include "symbols.h" -#include "schedule.h" -#include "vpi_priv.h" -#include "vvp_net_sig.h" -#include "config.h" +# include "symbols.h" +# include "schedule.h" +# include "vpi_priv.h" +# include "vvp_net_sig.h" +# include "vvp_darray.h" +# include "config.h" #ifdef CHECK_WITH_VALGRIND #include "vvp_cleanup.h" #endif @@ -34,6 +35,8 @@ # include # include "ivl_alloc.h" +class vvp_darray_real; + unsigned long count_net_arrays = 0; unsigned long count_net_array_words = 0; unsigned long count_var_arrays = 0; @@ -101,7 +104,7 @@ struct __vpiArray : public __vpiHandle { vpiHandle*nets; // If this is a var array, then these are used instead of nets. vvp_vector4array_t *vals4; - vvp_realarray_t *valsr; + vvp_darray_real *valsr; struct __vpiArrayWord*vals_words; vvp_fun_arrayport*ports_; @@ -1050,7 +1053,14 @@ double array_get_word_r(vvp_array_t arr, unsigned address) if (arr->valsr) { assert(arr->vals4 == 0); assert(arr->nets == 0); - return arr->valsr->get_word(address); + // In this context, address out of bounds returns 0.0 + // instead of an error. + if (address >= arr->valsr->get_size()) + return 0.0; + + double val; + arr->valsr->get_word(address, val); + return val; } assert(arr->nets); @@ -1199,7 +1209,7 @@ void compile_real_array(char*label, char*name, int last, int first, struct __vpiArray*arr = dynamic_cast<__vpiArray*>(obj); /* Make the words. */ - arr->valsr = new vvp_realarray_t(arr->array_count); + arr->valsr = new vvp_darray_real(arr->array_count); arr->vals_width = 1; /* For a real array the MSB and LSB must be zero. */ @@ -1515,8 +1525,10 @@ void array_word_change(vvp_array_t array, unsigned long addr) if (cur->test_value_callback_ready()) { if (cur->cb_data.value) { if (vpi_array_is_real(array)) { - vpip_real_get_value(array->valsr->get_word(addr), - cur->cb_data.value); + double val = 0.0; + if (addr < array->valsr->get_size()) + array->valsr->get_word(addr, val); + vpip_real_get_value(val, cur->cb_data.value); } else { vpip_vec4_get_value(array->vals4->get_word(addr), array->vals_width, diff --git a/vvp/vvp_net.cc b/vvp/vvp_net.cc index 1281ca67c..204c2fc8e 100644 --- a/vvp/vvp_net.cc +++ b/vvp/vvp_net.cc @@ -1779,36 +1779,6 @@ bool vector2_to_value(const vvp_vector2_t&a, int32_t&val, bool is_signed) return a.size() <= 32; } -vvp_realarray_t::vvp_realarray_t(unsigned wor) -: words_(wor) -{ - array_ = new double[words_]; - // Real array words have a default value of zero. - for (unsigned idx = 0 ; idx < words_; idx += 1) { - array_[idx] = 0.0; - } -} - -vvp_realarray_t::~vvp_realarray_t() -{ - delete[]array_; -} - -void vvp_realarray_t::set_word(unsigned word, double value) -{ - if (word >= words_) - return; - array_[word] = value; -} - -double vvp_realarray_t::get_word(unsigned word) const -{ - if (word >= words_) - return 0.0; - else - return array_[word]; -} - vvp_vector4array_t::vvp_vector4array_t(unsigned width__, unsigned words__) : width_(width__), words_(words__) { diff --git a/vvp/vvp_net.h b/vvp/vvp_net.h index 92968e782..8335eb410 100644 --- a/vvp/vvp_net.h +++ b/vvp/vvp_net.h @@ -1,7 +1,7 @@ #ifndef __vvp_net_H #define __vvp_net_H /* - * Copyright (c) 2004-2012 Stephen Williams (steve@icarus.com) + * Copyright (c) 2004-2013 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 @@ -522,25 +522,6 @@ extern bool vector2_to_value(const vvp_vector2_t&a, int32_t&val, bool is_signed) extern vvp_vector4_t vector4_from_text(const char*bits, unsigned wid); -/* - * The __vpiArray handle uses instances of this to keep an array of - * real valued variables. - */ -class vvp_realarray_t { - - public: - vvp_realarray_t(unsigned words); - ~vvp_realarray_t(); - - unsigned words() const { return words_; } - - double get_word(unsigned idx) const; - void set_word(unsigned idx, double val); - - private: - unsigned words_; - double*array_; -}; /* * vvp_vector4array_t From fbd2843cad6f073c91c0eb4ce5dbbefbf5d75199 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Thu, 3 Jan 2013 11:33:47 -0800 Subject: [PATCH 2/2] Runtime support for arrays of atom2 types. This handles all of the atom integer types in unpacked arrays. --- vvp/array.cc | 108 ++++++++++++++++++++++++++++++++++++++++---------- vvp/compile.h | 3 ++ vvp/lexor.lex | 6 ++- vvp/parse.y | 7 +++- 4 files changed, 99 insertions(+), 25 deletions(-) diff --git a/vvp/array.cc b/vvp/array.cc index dd3b8fd0a..9c578c876 100644 --- a/vvp/array.cc +++ b/vvp/array.cc @@ -35,8 +35,6 @@ # include # include "ivl_alloc.h" -class vvp_darray_real; - unsigned long count_net_arrays = 0; unsigned long count_net_array_words = 0; unsigned long count_var_arrays = 0; @@ -103,8 +101,8 @@ struct __vpiArray : public __vpiHandle { // If this is a net array, nets lists the handles. vpiHandle*nets; // If this is a var array, then these are used instead of nets. - vvp_vector4array_t *vals4; - vvp_darray_real *valsr; + vvp_vector4array_t*vals4; + vvp_darray *vals; struct __vpiArrayWord*vals_words; vvp_fun_arrayport*ports_; @@ -231,13 +229,13 @@ unsigned get_array_word_size(vvp_array_t array) assert(array->array_count > 0); /* For a net array we need to get the width from the first element. */ if (array->nets) { - assert(array->vals4 == 0 && array->valsr == 0); + assert(array->vals4 == 0 && array->vals == 0); struct __vpiSignal*vsig = dynamic_cast<__vpiSignal*>(array->nets[0]); assert(vsig); width = vpip_size(vsig); /* For a variable array we can get the width from vals_width. */ } else { - assert(array->vals4 || array->valsr); + assert(array->vals4 || array->vals); width = array->vals_width; } @@ -434,7 +432,7 @@ vpiHandle __vpiArrayIterator::vpi_index(int) if (array->nets) return array->nets[use_index]; - assert(array->vals4 || array->valsr); + assert(array->vals4 || array->vals); if (array->vals_words == 0) array_make_vals_words(array); @@ -604,7 +602,7 @@ static int vpi_array_var_word_get(int code, vpiHandle ref) case vpiSize: if (parent->vals4) { - assert(parent->valsr == 0); + assert(parent->vals == 0); return (int) parent->vals4->width(); } else { assert(parent->vals4 == 0); @@ -807,9 +805,11 @@ static char*vpi_array_vthr_A_get_str(int code, vpiHandle ref) static unsigned vpi_array_is_real(vvp_array_t arr) { // Check to see if this is a variable/register array. - if (arr->valsr != 0) return 1U; // A real variable array. if (arr->vals4 != 0) return 0U; // A bit based variable/register array. + if (dynamic_cast (arr->vals)) + return 1U; + // This must be a net array so look at element 0 to find the type. assert(arr->nets != 0); assert(arr->array_count > 0); @@ -992,6 +992,16 @@ void array_set_word(vvp_array_t arr, return; } + if (arr->vals) { + assert(arr->nets == 0); + // FIXME: For now, assume no part select of word? + assert(part_off==0); + assert(val.size() == arr->vals_width); + arr->vals->set_word(address, val); + array_word_change(arr, address); + return; + } + assert(arr->nets != 0); // Select the word of the array that we affect. @@ -1005,10 +1015,13 @@ void array_set_word(vvp_array_t arr, void array_set_word(vvp_array_t arr, unsigned address, double val) { - assert(arr->valsr!= 0); + assert(arr->vals != 0); assert(arr->nets == 0); - arr->valsr->set_word(address, val); + if (address >= arr->vals->get_size()) + return; + + arr->vals->set_word(address, val); array_word_change(arr, address); } @@ -1016,12 +1029,23 @@ vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address) { if (arr->vals4) { assert(arr->nets == 0); - assert(arr->valsr == 0); + assert(arr->vals == 0); return arr->vals4->get_word(address); } + if (arr->vals) { + assert(arr->nets == 0); + assert(arr->vals4== 0); + if (address >= arr->vals->get_size()) + return vvp_vector4_t(arr->vals_width, BIT4_X); + + vvp_vector4_t val; + arr->vals->get_word(address, val); + return val; + } + assert(arr->vals4 == 0); - assert(arr->valsr == 0); + assert(arr->vals == 0); assert(arr->nets != 0); if (address >= arr->array_count) { @@ -1050,16 +1074,16 @@ vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address) double array_get_word_r(vvp_array_t arr, unsigned address) { - if (arr->valsr) { + if (arr->vals) { assert(arr->vals4 == 0); assert(arr->nets == 0); // In this context, address out of bounds returns 0.0 // instead of an error. - if (address >= arr->valsr->get_size()) + if (address >= arr->vals->get_size()) return 0.0; double val; - arr->valsr->get_word(address, val); + arr->vals->get_word(address, val); return val; } @@ -1107,7 +1131,7 @@ static vpiHandle vpip_make_array(char*label, const char*name, // Start off now knowing if we are nets or variables. obj->nets = 0; obj->vals4 = 0; - obj->valsr = 0; + obj->vals = 0; obj->vals_width = 0; obj->vals_words = 0; @@ -1201,6 +1225,46 @@ void compile_var_array(char*label, char*name, int last, int first, delete[] name; } +void compile_var2_array(char*label, char*name, int last, int first, + int msb, int lsb, bool signed_flag) +{ + vpiHandle obj = vpip_make_array(label, name, first, last, signed_flag); + + struct __vpiArray*arr = dynamic_cast<__vpiArray*>(obj); + + /* Make the words. */ + arr->msb.value = msb; + arr->lsb.value = lsb; + arr->vals_width = labs(msb-lsb) + 1; + + assert(! arr->nets); + if (lsb == 0 && msb == 7 && signed_flag) { + arr->vals = new vvp_darray_atom(arr->array_count); + } else if (lsb == 0 && msb == 7 && !signed_flag) { + arr->vals = new vvp_darray_atom(arr->array_count); + } else if (lsb == 0 && msb == 15 && signed_flag) { + arr->vals = new vvp_darray_atom(arr->array_count); + } else if (lsb == 0 && msb == 15 && !signed_flag) { + arr->vals = new vvp_darray_atom(arr->array_count); + } else if (lsb == 0 && msb == 31 && signed_flag) { + arr->vals = new vvp_darray_atom(arr->array_count); + } else if (lsb == 0 && msb == 31 && !signed_flag) { + arr->vals = new vvp_darray_atom(arr->array_count); + } else if (lsb == 0 && msb == 63 && signed_flag) { + arr->vals = new vvp_darray_atom(arr->array_count); + } else if (lsb == 0 && msb == 63 && !signed_flag) { + arr->vals = new vvp_darray_atom(arr->array_count); + } else { + // For now, only support the atom sizes. + assert(0); + } + count_var_arrays += 1; + count_var_array_words += arr->array_count; + + free(label); + delete[] name; +} + void compile_real_array(char*label, char*name, int last, int first, int msb, int lsb) { @@ -1209,7 +1273,7 @@ void compile_real_array(char*label, char*name, int last, int first, struct __vpiArray*arr = dynamic_cast<__vpiArray*>(obj); /* Make the words. */ - arr->valsr = new vvp_darray_real(arr->array_count); + arr->vals = new vvp_darray_real(arr->array_count); arr->vals_width = 1; /* For a real array the MSB and LSB must be zero. */ @@ -1480,7 +1544,7 @@ static void array_attach_port(vvp_array_t array, vvp_fun_arrayport*fun) vvp_vector4_t tmp(array->vals_width, BIT4_X); schedule_init_propagate(fun->net_, tmp); } - if (array->valsr) { + if (array->vals) { schedule_init_propagate(fun->net_, 0.0); } } @@ -1526,8 +1590,8 @@ void array_word_change(vvp_array_t array, unsigned long addr) if (cur->cb_data.value) { if (vpi_array_is_real(array)) { double val = 0.0; - if (addr < array->valsr->get_size()) - array->valsr->get_word(addr, val); + if (addr < array->vals->get_size()) + array->vals->get_word(addr, val); vpip_real_get_value(val, cur->cb_data.value); } else { vpip_vec4_get_value(array->vals4->get_word(addr), @@ -1764,7 +1828,7 @@ void compile_array_alias(char*label, char*name, char*src) // Share the words with the source array. obj->nets = mem->nets; obj->vals4 = mem->vals4; - obj->valsr = mem->valsr; + obj->vals = mem->vals; obj->vals_width = mem->vals_width; obj->vals_words = mem->vals_words; diff --git a/vvp/compile.h b/vvp/compile.h index a84fba741..6c68a17c3 100644 --- a/vvp/compile.h +++ b/vvp/compile.h @@ -344,6 +344,9 @@ extern char **compile_udp_table(char **table, char *row); extern void compile_var_array(char*label, char*name, int last, int first, int msb, int lsb, char signed_flag); +extern void compile_var2_array(char*label, char*name, + int last, int first, + int msb, int lsb, bool signed_flag); extern void compile_real_array(char*label, char*name, int last, int first, int msb, int lsb); diff --git a/vvp/lexor.lex b/vvp/lexor.lex index 710ae1edd..cb92ba987 100644 --- a/vvp/lexor.lex +++ b/vvp/lexor.lex @@ -120,8 +120,10 @@ static char* strdupnew(char const *str) ".arith/sub.r" { return K_ARITH_SUB_R; } ".arith/sum" { return K_ARITH_SUM; } ".arith/sum.r" { return K_ARITH_SUM_R; } -".array" { return K_ARRAY; } -".array/i" { return K_ARRAY_I; } +".array" { return K_ARRAY; } +".array/2s" { return K_ARRAY_2S; } +".array/2u" { return K_ARRAY_2U; } +".array/i" { return K_ARRAY_I; } ".array/real" { return K_ARRAY_R; } ".array/s" { return K_ARRAY_S; } ".array/port" { return K_ARRAY_PORT; } diff --git a/vvp/parse.y b/vvp/parse.y index b689e51ee..87e4f545c 100644 --- a/vvp/parse.y +++ b/vvp/parse.y @@ -77,7 +77,7 @@ static struct __vpiModPath*modpath_dst = 0; %token K_ARITH_MOD_R K_ARITH_MOD_S %token K_ARITH_MULT K_ARITH_MULT_R K_ARITH_SUB K_ARITH_SUB_R %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_ARRAY K_ARRAY_2U K_ARRAY_2S 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 @@ -213,6 +213,11 @@ statement | T_LABEL K_ARRAY T_STRING ',' signed_t_number signed_t_number ',' signed_t_number signed_t_number ';' { compile_var_array($1, $3, $5, $6, $8, $9, 0); } + | T_LABEL K_ARRAY_2U T_STRING ',' signed_t_number signed_t_number ',' signed_t_number signed_t_number ';' + { compile_var2_array($1, $3, $5, $6, $8, $9, false); } + | T_LABEL K_ARRAY_2S T_STRING ',' signed_t_number signed_t_number ',' signed_t_number signed_t_number ';' + { compile_var2_array($1, $3, $5, $6, $8, $9, true); } + | T_LABEL K_ARRAY_I T_STRING ',' signed_t_number signed_t_number ',' signed_t_number signed_t_number ';' { compile_var_array($1, $3, $5, $6, $8, $9, 2); }