Merge branch 'master' of github.com:steveicarus/iverilog
This commit is contained in:
commit
502a0708ea
112
vvp/array.cc
112
vvp/array.cc
|
|
@ -22,6 +22,7 @@
|
||||||
# include "schedule.h"
|
# include "schedule.h"
|
||||||
# include "vpi_priv.h"
|
# include "vpi_priv.h"
|
||||||
# include "vvp_net_sig.h"
|
# include "vvp_net_sig.h"
|
||||||
|
# include "vvp_darray.h"
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
#ifdef CHECK_WITH_VALGRIND
|
#ifdef CHECK_WITH_VALGRIND
|
||||||
#include "vvp_cleanup.h"
|
#include "vvp_cleanup.h"
|
||||||
|
|
@ -101,7 +102,7 @@ struct __vpiArray : public __vpiHandle {
|
||||||
vpiHandle*nets;
|
vpiHandle*nets;
|
||||||
// If this is a var array, then these are used instead of nets.
|
// If this is a var array, then these are used instead of nets.
|
||||||
vvp_vector4array_t*vals4;
|
vvp_vector4array_t*vals4;
|
||||||
vvp_realarray_t *valsr;
|
vvp_darray *vals;
|
||||||
struct __vpiArrayWord*vals_words;
|
struct __vpiArrayWord*vals_words;
|
||||||
|
|
||||||
vvp_fun_arrayport*ports_;
|
vvp_fun_arrayport*ports_;
|
||||||
|
|
@ -228,13 +229,13 @@ unsigned get_array_word_size(vvp_array_t array)
|
||||||
assert(array->array_count > 0);
|
assert(array->array_count > 0);
|
||||||
/* For a net array we need to get the width from the first element. */
|
/* For a net array we need to get the width from the first element. */
|
||||||
if (array->nets) {
|
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]);
|
struct __vpiSignal*vsig = dynamic_cast<__vpiSignal*>(array->nets[0]);
|
||||||
assert(vsig);
|
assert(vsig);
|
||||||
width = vpip_size(vsig);
|
width = vpip_size(vsig);
|
||||||
/* For a variable array we can get the width from vals_width. */
|
/* For a variable array we can get the width from vals_width. */
|
||||||
} else {
|
} else {
|
||||||
assert(array->vals4 || array->valsr);
|
assert(array->vals4 || array->vals);
|
||||||
width = array->vals_width;
|
width = array->vals_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -431,7 +432,7 @@ vpiHandle __vpiArrayIterator::vpi_index(int)
|
||||||
|
|
||||||
if (array->nets) return array->nets[use_index];
|
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);
|
if (array->vals_words == 0) array_make_vals_words(array);
|
||||||
|
|
||||||
|
|
@ -601,7 +602,7 @@ static int vpi_array_var_word_get(int code, vpiHandle ref)
|
||||||
|
|
||||||
case vpiSize:
|
case vpiSize:
|
||||||
if (parent->vals4) {
|
if (parent->vals4) {
|
||||||
assert(parent->valsr == 0);
|
assert(parent->vals == 0);
|
||||||
return (int) parent->vals4->width();
|
return (int) parent->vals4->width();
|
||||||
} else {
|
} else {
|
||||||
assert(parent->vals4 == 0);
|
assert(parent->vals4 == 0);
|
||||||
|
|
@ -804,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)
|
static unsigned vpi_array_is_real(vvp_array_t arr)
|
||||||
{
|
{
|
||||||
// Check to see if this is a variable/register array.
|
// 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 (arr->vals4 != 0) return 0U; // A bit based variable/register array.
|
||||||
|
|
||||||
|
if (dynamic_cast<vvp_darray_real*> (arr->vals))
|
||||||
|
return 1U;
|
||||||
|
|
||||||
// This must be a net array so look at element 0 to find the type.
|
// This must be a net array so look at element 0 to find the type.
|
||||||
assert(arr->nets != 0);
|
assert(arr->nets != 0);
|
||||||
assert(arr->array_count > 0);
|
assert(arr->array_count > 0);
|
||||||
|
|
@ -989,6 +992,16 @@ void array_set_word(vvp_array_t arr,
|
||||||
return;
|
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);
|
assert(arr->nets != 0);
|
||||||
|
|
||||||
// Select the word of the array that we affect.
|
// Select the word of the array that we affect.
|
||||||
|
|
@ -1002,10 +1015,13 @@ void array_set_word(vvp_array_t arr,
|
||||||
|
|
||||||
void array_set_word(vvp_array_t arr, unsigned address, double val)
|
void array_set_word(vvp_array_t arr, unsigned address, double val)
|
||||||
{
|
{
|
||||||
assert(arr->valsr!= 0);
|
assert(arr->vals != 0);
|
||||||
assert(arr->nets == 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);
|
array_word_change(arr, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1013,12 +1029,23 @@ vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address)
|
||||||
{
|
{
|
||||||
if (arr->vals4) {
|
if (arr->vals4) {
|
||||||
assert(arr->nets == 0);
|
assert(arr->nets == 0);
|
||||||
assert(arr->valsr == 0);
|
assert(arr->vals == 0);
|
||||||
return arr->vals4->get_word(address);
|
return arr->vals4->get_word(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (arr->vals) {
|
||||||
|
assert(arr->nets == 0);
|
||||||
assert(arr->vals4== 0);
|
assert(arr->vals4== 0);
|
||||||
assert(arr->valsr == 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->vals == 0);
|
||||||
assert(arr->nets != 0);
|
assert(arr->nets != 0);
|
||||||
|
|
||||||
if (address >= arr->array_count) {
|
if (address >= arr->array_count) {
|
||||||
|
|
@ -1047,10 +1074,17 @@ vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address)
|
||||||
|
|
||||||
double array_get_word_r(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->vals4 == 0);
|
||||||
assert(arr->nets == 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->vals->get_size())
|
||||||
|
return 0.0;
|
||||||
|
|
||||||
|
double val;
|
||||||
|
arr->vals->get_word(address, val);
|
||||||
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(arr->nets);
|
assert(arr->nets);
|
||||||
|
|
@ -1097,7 +1131,7 @@ static vpiHandle vpip_make_array(char*label, const char*name,
|
||||||
// Start off now knowing if we are nets or variables.
|
// Start off now knowing if we are nets or variables.
|
||||||
obj->nets = 0;
|
obj->nets = 0;
|
||||||
obj->vals4 = 0;
|
obj->vals4 = 0;
|
||||||
obj->valsr = 0;
|
obj->vals = 0;
|
||||||
obj->vals_width = 0;
|
obj->vals_width = 0;
|
||||||
obj->vals_words = 0;
|
obj->vals_words = 0;
|
||||||
|
|
||||||
|
|
@ -1191,6 +1225,46 @@ void compile_var_array(char*label, char*name, int last, int first,
|
||||||
delete[] name;
|
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<int8_t>(arr->array_count);
|
||||||
|
} else if (lsb == 0 && msb == 7 && !signed_flag) {
|
||||||
|
arr->vals = new vvp_darray_atom<uint8_t>(arr->array_count);
|
||||||
|
} else if (lsb == 0 && msb == 15 && signed_flag) {
|
||||||
|
arr->vals = new vvp_darray_atom<int16_t>(arr->array_count);
|
||||||
|
} else if (lsb == 0 && msb == 15 && !signed_flag) {
|
||||||
|
arr->vals = new vvp_darray_atom<uint16_t>(arr->array_count);
|
||||||
|
} else if (lsb == 0 && msb == 31 && signed_flag) {
|
||||||
|
arr->vals = new vvp_darray_atom<int32_t>(arr->array_count);
|
||||||
|
} else if (lsb == 0 && msb == 31 && !signed_flag) {
|
||||||
|
arr->vals = new vvp_darray_atom<uint32_t>(arr->array_count);
|
||||||
|
} else if (lsb == 0 && msb == 63 && signed_flag) {
|
||||||
|
arr->vals = new vvp_darray_atom<int64_t>(arr->array_count);
|
||||||
|
} else if (lsb == 0 && msb == 63 && !signed_flag) {
|
||||||
|
arr->vals = new vvp_darray_atom<uint64_t>(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,
|
void compile_real_array(char*label, char*name, int last, int first,
|
||||||
int msb, int lsb)
|
int msb, int lsb)
|
||||||
{
|
{
|
||||||
|
|
@ -1199,7 +1273,7 @@ void compile_real_array(char*label, char*name, int last, int first,
|
||||||
struct __vpiArray*arr = dynamic_cast<__vpiArray*>(obj);
|
struct __vpiArray*arr = dynamic_cast<__vpiArray*>(obj);
|
||||||
|
|
||||||
/* Make the words. */
|
/* Make the words. */
|
||||||
arr->valsr = new vvp_realarray_t(arr->array_count);
|
arr->vals = new vvp_darray_real(arr->array_count);
|
||||||
arr->vals_width = 1;
|
arr->vals_width = 1;
|
||||||
|
|
||||||
/* For a real array the MSB and LSB must be zero. */
|
/* For a real array the MSB and LSB must be zero. */
|
||||||
|
|
@ -1470,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);
|
vvp_vector4_t tmp(array->vals_width, BIT4_X);
|
||||||
schedule_init_propagate(fun->net_, tmp);
|
schedule_init_propagate(fun->net_, tmp);
|
||||||
}
|
}
|
||||||
if (array->valsr) {
|
if (array->vals) {
|
||||||
schedule_init_propagate(fun->net_, 0.0);
|
schedule_init_propagate(fun->net_, 0.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1515,8 +1589,10 @@ void array_word_change(vvp_array_t array, unsigned long addr)
|
||||||
if (cur->test_value_callback_ready()) {
|
if (cur->test_value_callback_ready()) {
|
||||||
if (cur->cb_data.value) {
|
if (cur->cb_data.value) {
|
||||||
if (vpi_array_is_real(array)) {
|
if (vpi_array_is_real(array)) {
|
||||||
vpip_real_get_value(array->valsr->get_word(addr),
|
double val = 0.0;
|
||||||
cur->cb_data.value);
|
if (addr < array->vals->get_size())
|
||||||
|
array->vals->get_word(addr, val);
|
||||||
|
vpip_real_get_value(val, cur->cb_data.value);
|
||||||
} else {
|
} else {
|
||||||
vpip_vec4_get_value(array->vals4->get_word(addr),
|
vpip_vec4_get_value(array->vals4->get_word(addr),
|
||||||
array->vals_width,
|
array->vals_width,
|
||||||
|
|
@ -1752,7 +1828,7 @@ void compile_array_alias(char*label, char*name, char*src)
|
||||||
// Share the words with the source array.
|
// Share the words with the source array.
|
||||||
obj->nets = mem->nets;
|
obj->nets = mem->nets;
|
||||||
obj->vals4 = mem->vals4;
|
obj->vals4 = mem->vals4;
|
||||||
obj->valsr = mem->valsr;
|
obj->vals = mem->vals;
|
||||||
obj->vals_width = mem->vals_width;
|
obj->vals_width = mem->vals_width;
|
||||||
obj->vals_words = mem->vals_words;
|
obj->vals_words = mem->vals_words;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -344,6 +344,9 @@ extern char **compile_udp_table(char **table, char *row);
|
||||||
extern void compile_var_array(char*label, char*name,
|
extern void compile_var_array(char*label, char*name,
|
||||||
int last, int first,
|
int last, int first,
|
||||||
int msb, int lsb, char signed_flag);
|
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,
|
extern void compile_real_array(char*label, char*name,
|
||||||
int last, int first,
|
int last, int first,
|
||||||
int msb, int lsb);
|
int msb, int lsb);
|
||||||
|
|
|
||||||
|
|
@ -121,6 +121,8 @@ static char* strdupnew(char const *str)
|
||||||
".arith/sum" { return K_ARITH_SUM; }
|
".arith/sum" { return K_ARITH_SUM; }
|
||||||
".arith/sum.r" { return K_ARITH_SUM_R; }
|
".arith/sum.r" { return K_ARITH_SUM_R; }
|
||||||
".array" { return K_ARRAY; }
|
".array" { return K_ARRAY; }
|
||||||
|
".array/2s" { return K_ARRAY_2S; }
|
||||||
|
".array/2u" { return K_ARRAY_2U; }
|
||||||
".array/i" { return K_ARRAY_I; }
|
".array/i" { return K_ARRAY_I; }
|
||||||
".array/real" { return K_ARRAY_R; }
|
".array/real" { return K_ARRAY_R; }
|
||||||
".array/s" { return K_ARRAY_S; }
|
".array/s" { return K_ARRAY_S; }
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ static struct __vpiModPath*modpath_dst = 0;
|
||||||
%token K_ARITH_MOD_R K_ARITH_MOD_S
|
%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_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_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_CAST_INT K_CAST_REAL K_CAST_REAL_S K_CAST_2
|
||||||
%token K_CLASS
|
%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_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 ';'
|
| 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); }
|
{ 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 ';'
|
| 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); }
|
{ compile_var_array($1, $3, $5, $6, $8, $9, 2); }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1779,36 +1779,6 @@ bool vector2_to_value(const vvp_vector2_t&a, int32_t&val, bool is_signed)
|
||||||
return a.size() <= 32;
|
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__)
|
vvp_vector4array_t::vvp_vector4array_t(unsigned width__, unsigned words__)
|
||||||
: width_(width__), words_(words__)
|
: width_(width__), words_(words__)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __vvp_net_H
|
#ifndef __vvp_net_H
|
||||||
#define __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
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* 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);
|
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
|
* vvp_vector4array_t
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue