nextpnr/common/kernel/array2d.h
gatecat 0eb9a9ad02 placer_static: Initial prototype
Signed-off-by: gatecat <gatecat@ds0.me>
2023-10-02 14:56:40 +02:00

149 lines
4.4 KiB
C++

/*
* nextpnr -- Next Generation Place and Route
*
* Copyright (C) 2021-22 gatecat <gatecat@ds0.me>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#ifndef ARRAY2D_H
#define ARRAY2D_H
#include <algorithm>
#include <fstream>
#include <limits>
#include <string>
#include <type_traits>
#include <vector>
#include "nextpnr_assertions.h"
#include "nextpnr_namespaces.h"
NEXTPNR_NAMESPACE_BEGIN
template <typename T> class array2d
{
public:
array2d() : m_width(0), m_height(0), m_size(0), data(nullptr){};
array2d(int width, int height) : m_width(width), m_height(height), m_size(width * height)
{
data = new T[m_width * m_height]();
}
array2d(int width, int height, const T &init) : m_width(width), m_height(height), m_size(width * height)
{
data = new T[m_width * m_height];
std::fill(data, data + (m_width * m_height), init);
}
array2d(const array2d &other) : m_width(other.m_width), m_height(other.m_height), m_size(other.m_size)
{
data = new T[m_size]();
if (m_size > 0)
std::copy(other.data, other.data + (m_width * m_height), data);
}
array2d(array2d &&other) noexcept : m_width(other.m_width), m_height(other.m_height), m_size(other.m_size)
{
data = other.data;
other.data = nullptr;
other.m_size = 0;
}
void reset(int new_width, int new_height, const T &init = {})
{
if ((new_width * new_height) > m_size) {
delete[] data;
m_size = new_width * new_height;
data = new T[m_size];
}
m_width = new_width;
m_height = new_height;
std::fill(data, data + (m_width * m_height), init);
}
int width() const { return m_width; }
int height() const { return m_height; }
T &at(int x, int y)
{
NPNR_ASSERT(x >= 0 && x < m_width);
NPNR_ASSERT(y >= 0 && y < m_height);
return data[y * m_width + x];
}
T &at(const Loc &l) { return at(l.x, l.y); }
const T &at(int x, int y) const
{
NPNR_ASSERT(x >= 0 && x < m_width);
NPNR_ASSERT(y >= 0 && y < m_height);
return data[y * m_width + x];
}
const T &at(const Loc &l) const { return at(l.x, l.y); }
~array2d() { delete[] data; }
struct entry
{
entry(int x, int y, T &value) : x(x), y(y), value(value){};
int x, y;
T &value;
};
struct iterator
{
public:
entry operator*() { return {x, y, base->at(x, y)}; }
inline iterator operator++()
{
++x;
if (x >= base->width()) {
x = 0;
++y;
}
return *this;
}
inline iterator operator++(int)
{
iterator prior(x, y, base);
++x;
if (x >= base->width()) {
x = 0;
++y;
}
return prior;
}
inline bool operator!=(const iterator &other) const { return other.x != x || other.y != y; }
inline bool operator==(const iterator &other) const { return other.x == x && other.y == y; }
private:
iterator(int x, int y, array2d<T> &base) : x(x), y(y), base(&base){};
int x, y;
array2d<T> *base;
friend class array2d;
};
iterator begin() { return {0, 0, *this}; }
iterator end() { return {0, m_height, *this}; }
void write_csv(const std::string &filename) const
{
std::ofstream out(filename);
NPNR_ASSERT(out);
for (int y = 0; y < m_height; y++) {
for (int x = 0; x < m_width; x++) {
out << at(x, y) << ",";
}
out << std::endl;
}
}
private:
int m_width, m_height, m_size;
T *data;
};
NEXTPNR_NAMESPACE_END
#endif