/* * Copyright (c) 2012-2016 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 * General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ # include "nettypes.h" # include # include using namespace std; ivl_type_s::~ivl_type_s() { } /* * The derived class may override this to provide a more accurate * response. */ bool ivl_type_s::packed(void) const { return false; } long ivl_type_s::packed_width(void) const { return 1; } vector ivl_type_s::slice_dimensions() const { return vector(); } ivl_variable_type_t ivl_type_s::base_type() const { return IVL_VT_NO_TYPE; } bool ivl_type_s::get_signed() const { return false; } bool ivl_type_s::type_compatible(ivl_type_t that) const { if (this == that) return true; return test_compatibility(that); } bool ivl_type_s::test_compatibility(const ivl_type_s* /*that*/) const { return false; } netarray_t::~netarray_t() { } ivl_variable_type_t netarray_t::base_type() const { return element_type_->base_type(); } unsigned long netrange_width(const vector&packed) { unsigned wid = 1; for (vector::const_iterator cur = packed.begin() ; cur != packed.end() ; ++cur) { unsigned use_wid = cur->width(); wid *= use_wid; } return wid; } /* * Given a netrange_t list (which represent packed dimensions) and a * prefix of calculated index values, calculate the canonical offset * and width of the resulting slice. In this case, the "sb" argument * is an extra index of the prefix. */ bool prefix_to_slice(const std::vector&dims, const std::list&prefix, long sb, long&loff, unsigned long&lwid) { assert(prefix.size() < dims.size()); // Figure out the width of the slice, given the number of // prefix numbers there are. We don't need to look at the // actual values yet, but we do need to know how many there // are compared to the actual dimensions of the target. So do // this by multiplying the widths of the dims that are NOT // accounted for by the prefix or sb indices. size_t acc_wid = 1; vector::const_iterator pcur = dims.end(); for (size_t idx = prefix.size()+1 ; idx < dims.size() ; idx += 1) { -- pcur; acc_wid *= pcur->width(); } lwid = acc_wid; // lwid is now the final slice width. // pcur is pointing to the dimension AFTER the dimension that // we have an index for, so step back one, then this will be // used with the sb index. Start accumulating in the acc_off // the offset into the n-dimensional vector. -- pcur; if (sb < pcur->get_msb() && sb < pcur->get_lsb()) return false; if (sb > pcur->get_msb() && sb > pcur->get_lsb()) return false; long acc_off = 0; if (pcur->get_msb() >= pcur->get_lsb()) acc_off += (sb - pcur->get_lsb()) * acc_wid; else acc_off += (pcur->get_lsb() - sb) * acc_wid; // If there are no more prefix items, we are done. if (prefix.empty()) { loff = acc_off; return true; } // Now similarly go through the prefix numbers, working // through the dimensions until we run out. Accumulate a // growing slice width (acc_wid) that is used to calculate the // growing offset (acc_off). list::const_iterator icur = prefix.end(); do { -- icur; acc_wid *= pcur->width(); -- pcur; if (pcur->get_msb() >= pcur->get_lsb()) acc_off += (*icur - pcur->get_lsb()) * acc_wid; else acc_off += (pcur->get_lsb() - *icur) * acc_wid; } while (icur != prefix.begin()); // Got our final offset. loff = acc_off; return true; }