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:
Cary R 2009-02-23 17:04:14 -08:00 committed by Stephen Williams
parent f1e702bdd5
commit 158e9fd2be
9 changed files with 44 additions and 9 deletions

View File

@ -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

View File

@ -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);

View File

@ -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_);

View File

@ -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;

View File

@ -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_;

View File

@ -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];

View File

@ -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. */

View File

@ -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, "

View File

@ -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;