diff --git a/ivl.def b/ivl.def index 197671305..d57d9ad0d 100644 --- a/ivl.def +++ b/ivl.def @@ -181,6 +181,7 @@ ivl_scope_time_units ivl_scope_type ivl_scope_tname +ivl_signal_array_addr_swapped ivl_signal_array_base ivl_signal_array_count ivl_signal_attr diff --git a/ivl_target.h b/ivl_target.h index 7811a9f45..78723d155 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -1654,10 +1654,12 @@ extern int ivl_scope_time_units(ivl_scope_t net); * * ivl_signal_array_base * ivl_signal_array_count + * ivl_signal_array_addr_swapped * 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 - * address is the Verilog source for the canonical zero word. This - * may be negative, positive or zero. + * address in the Verilog source for the canonical zero word. This + * 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 * 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 int ivl_signal_array_base(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 ivl_discipline_t ivl_signal_discipline(ivl_signal_t net); extern int ivl_signal_msb(ivl_signal_t net); diff --git a/netlist.cc b/netlist.cc index c9ad7bafc..7b3309898 100644 --- a/netlist.cc +++ b/netlist.cc @@ -716,12 +716,20 @@ unsigned NetNet::array_dimensions() const long NetNet::array_first() const { - if (s0_ < e0_) + if (s0_ <= e0_) return s0_; else return e0_; } +bool NetNet::array_addr_swapped() const +{ + if (s0_ <= e0_) + return false; + else + return true; +} + unsigned NetNet::array_count() const { return calculate_count(s0_, e0_); diff --git a/netlist.h b/netlist.h index fc98cb0f9..ad071c6c2 100644 --- a/netlist.h +++ b/netlist.h @@ -602,6 +602,7 @@ class NetNet : public NetObj { indices. (Currently only one array index is supported.) */ unsigned array_dimensions() const; long array_first() const; + bool array_addr_swapped() const; // This is the number of array elements. unsigned array_count() const; diff --git a/t-dll-api.cc b/t-dll-api.cc index e7b544e2b..fbce632eb 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -1824,6 +1824,11 @@ extern "C" unsigned ivl_signal_array_count(ivl_signal_t net) 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) { return net->array_dimensions_; diff --git a/t-dll.cc b/t-dll.cc index c9fda2b64..f602e45cb 100644 --- a/t-dll.cc +++ b/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 * 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_words = net->array_count(); + obj->array_addr_swapped = net->array_addr_swapped() ? 1 : 0; if (obj->array_words > 1) obj->pins = new ivl_nexus_t[obj->array_words]; diff --git a/t-dll.h b/t-dll.h index 7af3cd1d8..e6c7bd6bc 100644 --- a/t-dll.h +++ b/t-dll.h @@ -639,6 +639,7 @@ struct ivl_signal_s { /* For now, support only 0 or 1 array dimensions. */ unsigned array_dimensions_ : 1; + unsigned array_addr_swapped : 1; /* These encode the run-time index for the least significant bit, and the distance to the second bit. */ diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index c2520671a..441a3479f 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -400,12 +400,13 @@ static void draw_reg_in_scope(ivl_signal_t sig) write out the .array record to declare the array indices. */ if (ivl_signal_dimensions(sig) > 0) { 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 first = ivl_signal_array_base(sig); fprintf(vvp_out, "v%p .array%s \"%s\", %d %d, %d %d;\n", sig, datatype_flag, vvp_mangle_name(ivl_signal_basename(sig)), - last, first, msb, lsb); + swapped ? first: last, swapped ? last : first, msb, lsb); } else { @@ -462,11 +463,12 @@ static void draw_net_in_scope(ivl_signal_t sig) vec8 = "8"; if (iword == 0 && dimensions > 0) { + unsigned swapped = ivl_signal_array_addr_swapped(sig); int last = ivl_signal_array_base(sig) + word_count-1; int first = ivl_signal_array_base(sig); fprintf(vvp_out, "v%p .array \"%s\", %d %d;\n", sig, vvp_mangle_name(ivl_signal_basename(sig)), - last, first); + swapped ? first : last, swapped ? last : first); } if (dimensions > 0) { /* 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. */ } else { if (iword == 0) { + unsigned swapped = ivl_signal_array_addr_swapped(sig); int first = ivl_signal_array_base(sig); int last = first + word_count-1; fprintf(vvp_out, "v%p .array \"%s\", %d %d;\n", 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, " diff --git a/vvp/array.cc b/vvp/array.cc index f29bc2d39..79468a401 100644 --- a/vvp/array.cc +++ b/vvp/array.cc @@ -102,6 +102,7 @@ struct __vpiArray { class vvp_fun_arrayport*ports_; struct __vpiCallback *vpi_callbacks; bool signed_flag; + bool swap_addr; }; struct __vpiArrayIterator { @@ -384,10 +385,12 @@ static vpiHandle vpi_array_get_handle(int code, vpiHandle ref) switch (code) { case vpiLeftRange: - return &(obj->first_addr.base); + if (obj->swap_addr) return &(obj->last_addr.base); + else return &(obj->first_addr.base); case vpiRightRange: - return &(obj->last_addr.base); + if (obj->swap_addr) return &(obj->first_addr.base); + else return &(obj->last_addr.base); case vpiScope: return &obj->scope->base; @@ -861,6 +864,14 @@ static vpiHandle vpip_make_array(char*label, const char*name, obj->signed_flag = signed_flag; // 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); unsigned array_count = last_addr+1-first_addr;