Keep the left and right array range value order information.
Previously Icarus normalized the results so array [7:0] would be the same as array [0:7]. This works just fine for simulation, but the VPI calls can select the left or right value and this was incorrect for the [7:0] case since it was being normalized to [0:7]. This patch swaps the two values in the a.out file and from this creates the previous first/last values and a new flag that can be used to get the correct left and right values for the VPI interface.
This commit is contained in:
parent
f1e702bdd5
commit
158e9fd2be
1
ivl.def
1
ivl.def
|
|
@ -181,6 +181,7 @@ ivl_scope_time_units
|
||||||
ivl_scope_type
|
ivl_scope_type
|
||||||
ivl_scope_tname
|
ivl_scope_tname
|
||||||
|
|
||||||
|
ivl_signal_array_addr_swapped
|
||||||
ivl_signal_array_base
|
ivl_signal_array_base
|
||||||
ivl_signal_array_count
|
ivl_signal_array_count
|
||||||
ivl_signal_attr
|
ivl_signal_attr
|
||||||
|
|
|
||||||
|
|
@ -1654,10 +1654,12 @@ extern int ivl_scope_time_units(ivl_scope_t net);
|
||||||
*
|
*
|
||||||
* ivl_signal_array_base
|
* ivl_signal_array_base
|
||||||
* ivl_signal_array_count
|
* ivl_signal_array_count
|
||||||
|
* ivl_signal_array_addr_swapped
|
||||||
* The signal may be arrayed. If so, the array_count is >1. Each
|
* The signal may be arrayed. If so, the array_count is >1. Each
|
||||||
* word of the array has its own nexus. The array_base is the
|
* word of the array has its own nexus. The array_base is the
|
||||||
* address is the Verilog source for the canonical zero word. This
|
* address in the Verilog source for the canonical zero word. This
|
||||||
* may be negative, positive or zero.
|
* may be negative, positive or zero. The array addresses may be
|
||||||
|
* reversed/swapped.
|
||||||
*
|
*
|
||||||
* Note that arraying of the signal into words is distinct from the
|
* Note that arraying of the signal into words is distinct from the
|
||||||
* vectors. The width of a signal is the width of a WORD.
|
* vectors. The width of a signal is the width of a WORD.
|
||||||
|
|
@ -1736,6 +1738,7 @@ extern int ivl_scope_time_units(ivl_scope_t net);
|
||||||
extern ivl_nexus_t ivl_signal_nex(ivl_signal_t net, unsigned word);
|
extern ivl_nexus_t ivl_signal_nex(ivl_signal_t net, unsigned word);
|
||||||
extern int ivl_signal_array_base(ivl_signal_t net);
|
extern int ivl_signal_array_base(ivl_signal_t net);
|
||||||
extern unsigned ivl_signal_array_count(ivl_signal_t net);
|
extern unsigned ivl_signal_array_count(ivl_signal_t net);
|
||||||
|
extern unsigned ivl_signal_array_addr_swapped(ivl_signal_t net);
|
||||||
extern unsigned ivl_signal_dimensions(ivl_signal_t net);
|
extern unsigned ivl_signal_dimensions(ivl_signal_t net);
|
||||||
extern ivl_discipline_t ivl_signal_discipline(ivl_signal_t net);
|
extern ivl_discipline_t ivl_signal_discipline(ivl_signal_t net);
|
||||||
extern int ivl_signal_msb(ivl_signal_t net);
|
extern int ivl_signal_msb(ivl_signal_t net);
|
||||||
|
|
|
||||||
10
netlist.cc
10
netlist.cc
|
|
@ -716,12 +716,20 @@ unsigned NetNet::array_dimensions() const
|
||||||
|
|
||||||
long NetNet::array_first() const
|
long NetNet::array_first() const
|
||||||
{
|
{
|
||||||
if (s0_ < e0_)
|
if (s0_ <= e0_)
|
||||||
return s0_;
|
return s0_;
|
||||||
else
|
else
|
||||||
return e0_;
|
return e0_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NetNet::array_addr_swapped() const
|
||||||
|
{
|
||||||
|
if (s0_ <= e0_)
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned NetNet::array_count() const
|
unsigned NetNet::array_count() const
|
||||||
{
|
{
|
||||||
return calculate_count(s0_, e0_);
|
return calculate_count(s0_, e0_);
|
||||||
|
|
|
||||||
|
|
@ -602,6 +602,7 @@ class NetNet : public NetObj {
|
||||||
indices. (Currently only one array index is supported.) */
|
indices. (Currently only one array index is supported.) */
|
||||||
unsigned array_dimensions() const;
|
unsigned array_dimensions() const;
|
||||||
long array_first() const;
|
long array_first() const;
|
||||||
|
bool array_addr_swapped() const;
|
||||||
|
|
||||||
// This is the number of array elements.
|
// This is the number of array elements.
|
||||||
unsigned array_count() const;
|
unsigned array_count() const;
|
||||||
|
|
|
||||||
|
|
@ -1824,6 +1824,11 @@ extern "C" unsigned ivl_signal_array_count(ivl_signal_t net)
|
||||||
return net->array_words;
|
return net->array_words;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" unsigned ivl_signal_array_addr_swapped(ivl_signal_t net)
|
||||||
|
{
|
||||||
|
return net->array_addr_swapped;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" unsigned ivl_signal_dimensions(ivl_signal_t net)
|
extern "C" unsigned ivl_signal_dimensions(ivl_signal_t net)
|
||||||
{
|
{
|
||||||
return net->array_dimensions_;
|
return net->array_dimensions_;
|
||||||
|
|
|
||||||
3
t-dll.cc
3
t-dll.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000-2008 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2000-2009 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
|
||||||
|
|
@ -2559,6 +2559,7 @@ void dll_target::signal(const NetNet*net)
|
||||||
|
|
||||||
obj->array_base = net->array_first();
|
obj->array_base = net->array_first();
|
||||||
obj->array_words = net->array_count();
|
obj->array_words = net->array_count();
|
||||||
|
obj->array_addr_swapped = net->array_addr_swapped() ? 1 : 0;
|
||||||
if (obj->array_words > 1)
|
if (obj->array_words > 1)
|
||||||
obj->pins = new ivl_nexus_t[obj->array_words];
|
obj->pins = new ivl_nexus_t[obj->array_words];
|
||||||
|
|
||||||
|
|
|
||||||
1
t-dll.h
1
t-dll.h
|
|
@ -639,6 +639,7 @@ struct ivl_signal_s {
|
||||||
|
|
||||||
/* For now, support only 0 or 1 array dimensions. */
|
/* For now, support only 0 or 1 array dimensions. */
|
||||||
unsigned array_dimensions_ : 1;
|
unsigned array_dimensions_ : 1;
|
||||||
|
unsigned array_addr_swapped : 1;
|
||||||
|
|
||||||
/* These encode the run-time index for the least significant
|
/* These encode the run-time index for the least significant
|
||||||
bit, and the distance to the second bit. */
|
bit, and the distance to the second bit. */
|
||||||
|
|
|
||||||
|
|
@ -400,12 +400,13 @@ static void draw_reg_in_scope(ivl_signal_t sig)
|
||||||
write out the .array record to declare the array indices. */
|
write out the .array record to declare the array indices. */
|
||||||
if (ivl_signal_dimensions(sig) > 0) {
|
if (ivl_signal_dimensions(sig) > 0) {
|
||||||
unsigned word_count = ivl_signal_array_count(sig);
|
unsigned word_count = ivl_signal_array_count(sig);
|
||||||
|
unsigned swapped = ivl_signal_array_addr_swapped(sig);
|
||||||
int last = ivl_signal_array_base(sig)+word_count-1;
|
int last = ivl_signal_array_base(sig)+word_count-1;
|
||||||
int first = ivl_signal_array_base(sig);
|
int first = ivl_signal_array_base(sig);
|
||||||
fprintf(vvp_out, "v%p .array%s \"%s\", %d %d, %d %d;\n",
|
fprintf(vvp_out, "v%p .array%s \"%s\", %d %d, %d %d;\n",
|
||||||
sig, datatype_flag,
|
sig, datatype_flag,
|
||||||
vvp_mangle_name(ivl_signal_basename(sig)),
|
vvp_mangle_name(ivl_signal_basename(sig)),
|
||||||
last, first, msb, lsb);
|
swapped ? first: last, swapped ? last : first, msb, lsb);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
|
@ -462,11 +463,12 @@ static void draw_net_in_scope(ivl_signal_t sig)
|
||||||
vec8 = "8";
|
vec8 = "8";
|
||||||
|
|
||||||
if (iword == 0 && dimensions > 0) {
|
if (iword == 0 && dimensions > 0) {
|
||||||
|
unsigned swapped = ivl_signal_array_addr_swapped(sig);
|
||||||
int last = ivl_signal_array_base(sig) + word_count-1;
|
int last = ivl_signal_array_base(sig) + word_count-1;
|
||||||
int first = ivl_signal_array_base(sig);
|
int first = ivl_signal_array_base(sig);
|
||||||
fprintf(vvp_out, "v%p .array \"%s\", %d %d;\n",
|
fprintf(vvp_out, "v%p .array \"%s\", %d %d;\n",
|
||||||
sig, vvp_mangle_name(ivl_signal_basename(sig)),
|
sig, vvp_mangle_name(ivl_signal_basename(sig)),
|
||||||
last, first);
|
swapped ? first : last, swapped ? last : first);
|
||||||
}
|
}
|
||||||
if (dimensions > 0) {
|
if (dimensions > 0) {
|
||||||
/* If this is a word of an array, then use an
|
/* If this is a word of an array, then use an
|
||||||
|
|
@ -511,12 +513,14 @@ static void draw_net_in_scope(ivl_signal_t sig)
|
||||||
/* An alias for an individual word. */
|
/* An alias for an individual word. */
|
||||||
} else {
|
} else {
|
||||||
if (iword == 0) {
|
if (iword == 0) {
|
||||||
|
unsigned swapped = ivl_signal_array_addr_swapped(sig);
|
||||||
int first = ivl_signal_array_base(sig);
|
int first = ivl_signal_array_base(sig);
|
||||||
int last = first + word_count-1;
|
int last = first + word_count-1;
|
||||||
fprintf(vvp_out, "v%p .array \"%s\", %d %d;\n",
|
fprintf(vvp_out, "v%p .array \"%s\", %d %d;\n",
|
||||||
sig,
|
sig,
|
||||||
vvp_mangle_name(ivl_signal_basename(sig)),
|
vvp_mangle_name(ivl_signal_basename(sig)),
|
||||||
last, first);
|
swapped ? first : last,
|
||||||
|
swapped ? last : first);
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(vvp_out, "v%p_%u .alias%s v%p %u, %d %d, "
|
fprintf(vvp_out, "v%p_%u .alias%s v%p %u, %d %d, "
|
||||||
|
|
|
||||||
15
vvp/array.cc
15
vvp/array.cc
|
|
@ -102,6 +102,7 @@ struct __vpiArray {
|
||||||
class vvp_fun_arrayport*ports_;
|
class vvp_fun_arrayport*ports_;
|
||||||
struct __vpiCallback *vpi_callbacks;
|
struct __vpiCallback *vpi_callbacks;
|
||||||
bool signed_flag;
|
bool signed_flag;
|
||||||
|
bool swap_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct __vpiArrayIterator {
|
struct __vpiArrayIterator {
|
||||||
|
|
@ -384,10 +385,12 @@ static vpiHandle vpi_array_get_handle(int code, vpiHandle ref)
|
||||||
switch (code) {
|
switch (code) {
|
||||||
|
|
||||||
case vpiLeftRange:
|
case vpiLeftRange:
|
||||||
return &(obj->first_addr.base);
|
if (obj->swap_addr) return &(obj->last_addr.base);
|
||||||
|
else return &(obj->first_addr.base);
|
||||||
|
|
||||||
case vpiRightRange:
|
case vpiRightRange:
|
||||||
return &(obj->last_addr.base);
|
if (obj->swap_addr) return &(obj->first_addr.base);
|
||||||
|
else return &(obj->last_addr.base);
|
||||||
|
|
||||||
case vpiScope:
|
case vpiScope:
|
||||||
return &obj->scope->base;
|
return &obj->scope->base;
|
||||||
|
|
@ -861,6 +864,14 @@ static vpiHandle vpip_make_array(char*label, const char*name,
|
||||||
obj->signed_flag = signed_flag;
|
obj->signed_flag = signed_flag;
|
||||||
|
|
||||||
// Assume increasing addresses.
|
// Assume increasing addresses.
|
||||||
|
if (last_addr >= first_addr) {
|
||||||
|
obj->swap_addr = false;
|
||||||
|
} else {
|
||||||
|
obj->swap_addr = true;
|
||||||
|
int tmp = last_addr;
|
||||||
|
last_addr = first_addr;
|
||||||
|
first_addr = tmp;
|
||||||
|
}
|
||||||
assert(last_addr >= first_addr);
|
assert(last_addr >= first_addr);
|
||||||
unsigned array_count = last_addr+1-first_addr;
|
unsigned array_count = last_addr+1-first_addr;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue