placer_static: Initial prototype

Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
gatecat 2023-01-25 11:03:06 +01:00 committed by myrtle
parent 95e7598cc6
commit 0eb9a9ad02
12 changed files with 6703 additions and 3 deletions

3305
3rdparty/oourafft/fftsg.cc vendored Normal file

File diff suppressed because it is too large Load Diff

24
3rdparty/oourafft/fftsg.h vendored Normal file
View File

@ -0,0 +1,24 @@
#ifndef FFTSG_H
#define FFTSG_H
#include "nextpnr_namespaces.h"
NEXTPNR_NAMESPACE_BEGIN
//
// The following FFT library came from
// http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html
//
//
/// 1D FFT ////////////////////////////////////////////////////////////////
void ddct(int n, int isgn, float *a, int *ip, float *w);
void ddst(int n, int isgn, float *a, int *ip, float *w);
/// 2D FFT ////////////////////////////////////////////////////////////////
void ddct2d(int n1, int n2, int isgn, float **a, float *t, int *ip, float *w);
void ddsct2d(int n1, int n2, int isgn, float **a, float *t, int *ip, float *w);
void ddcst2d(int n1, int n2, int isgn, float **a, float *t, int *ip, float *w);
NEXTPNR_NAMESPACE_END
#endif

1419
3rdparty/oourafft/fftsg2d.cc vendored Normal file

File diff suppressed because it is too large Load Diff

167
3rdparty/oourafft/readme.txt vendored Normal file
View File

@ -0,0 +1,167 @@
General Purpose FFT (Fast Fourier/Cosine/Sine Transform) Package
Description:
A package to calculate Discrete Fourier/Cosine/Sine Transforms of
1-dimensional sequences of length 2^N.
Files:
fft4g.c : FFT Package in C - Fast Version I (radix 4,2)
fft4g.f : FFT Package in Fortran - Fast Version I (radix 4,2)
fft4g_h.c : FFT Package in C - Simple Version I (radix 4,2)
fft8g.c : FFT Package in C - Fast Version II (radix 8,4,2)
fft8g.f : FFT Package in Fortran - Fast Version II (radix 8,4,2)
fft8g_h.c : FFT Package in C - Simple Version II (radix 8,4,2)
fftsg.c : FFT Package in C - Fast Version III (Split-Radix)
fftsg.f : FFT Package in Fortran - Fast Version III (Split-Radix)
fftsg_h.c : FFT Package in C - Simple Version III (Split-Radix)
readme.txt : Readme File
sample1/ : Test Directory
Makefile : for gcc, cc
Makefile.f77: for Fortran
testxg.c : Test Program for "fft*g.c"
testxg.f : Test Program for "fft*g.f"
testxg_h.c : Test Program for "fft*g_h.c"
sample2/ : Benchmark Directory
Makefile : for gcc, cc
Makefile.pth: POSIX Thread version
pi_fft.c : PI(= 3.1415926535897932384626...) Calculation Program
for a Benchmark Test for "fft*g.c"
Difference of the Files:
C and Fortran versions are equal and
the same routines are in each version.
"fft4g*.*" are optimized for most machines.
"fft8g*.*" are fast on the UltraSPARC.
"fftsg*.*" are optimized for the machines that
have the multi-level (L1,L2,etc) cache.
The simple versions "fft*g_h.c" use no work area, but
the fast versions "fft*g.*" use work areas.
The fast versions "fft*g.*" have the same specification.
Routines in the Package:
cdft: Complex Discrete Fourier Transform
rdft: Real Discrete Fourier Transform
ddct: Discrete Cosine Transform
ddst: Discrete Sine Transform
dfct: Cosine Transform of RDFT (Real Symmetric DFT)
dfst: Sine Transform of RDFT (Real Anti-symmetric DFT)
Usage:
Please refer to the comments in the "fft**.*" file which
you want to use. Brief explanations are in the block
comments of each package. The examples are also given in
the test programs.
Method:
-------- cdft --------
fft4g*.*, fft8g*.*:
A method of in-place, radix 2^M, Sande-Tukey (decimation in
frequency). Index of the butterfly loop is in bit
reverse order to keep continuous memory access.
fftsg*.*:
A method of in-place, Split-Radix, recursive fast
algorithm.
-------- rdft --------
A method with a following butterfly operation appended to "cdft".
In forward transform :
A[k] = sum_j=0^n-1 a[j]*W(n)^(j*k), 0<=k<=n/2,
W(n) = exp(2*pi*i/n),
this routine makes an array x[] :
x[j] = a[2*j] + i*a[2*j+1], 0<=j<n/2
and calls "cdft" of length n/2 :
X[k] = sum_j=0^n/2-1 x[j] * W(n/2)^(j*k), 0<=k<n.
The result A[k] are :
A[k] = X[k] - (1+i*W(n)^k)/2 * (X[k]-conjg(X[n/2-k])),
A[n/2-k] = X[n/2-k] +
conjg((1+i*W(n)^k)/2 * (X[k]-conjg(X[n/2-k]))),
0<=k<=n/2
(notes: conjg() is a complex conjugate, X[n/2]=X[0]).
-------- ddct --------
A method with a following butterfly operation appended to "rdft".
In backward transform :
C[k] = sum_j=0^n-1 a[j]*cos(pi*j*(k+1/2)/n), 0<=k<n,
this routine makes an array r[] :
r[0] = a[0],
r[j] = Re((a[j] - i*a[n-j]) * W(4*n)^j*(1+i)/2),
r[n-j] = Im((a[j] - i*a[n-j]) * W(4*n)^j*(1+i)/2),
0<j<=n/2
and calls "rdft" of length n :
A[k] = sum_j=0^n-1 r[j]*W(n)^(j*k), 0<=k<=n/2,
W(n) = exp(2*pi*i/n).
The result C[k] are :
C[2*k] = Re(A[k] * (1-i)),
C[2*k-1] = -Im(A[k] * (1-i)).
-------- ddst --------
A method with a following butterfly operation appended to "rdft".
In backward transform :
S[k] = sum_j=1^n A[j]*sin(pi*j*(k+1/2)/n), 0<=k<n,
this routine makes an array r[] :
r[0] = a[0],
r[j] = Im((a[n-j] - i*a[j]) * W(4*n)^j*(1+i)/2),
r[n-j] = Re((a[n-j] - i*a[j]) * W(4*n)^j*(1+i)/2),
0<j<=n/2
and calls "rdft" of length n :
A[k] = sum_j=0^n-1 r[j]*W(n)^(j*k), 0<=k<=n/2,
W(n) = exp(2*pi*i/n).
The result S[k] are :
S[2*k] = Re(A[k] * (1+i)),
S[2*k-1] = -Im(A[k] * (1+i)).
-------- dfct --------
A method to split into "dfct" and "ddct" of half length.
The transform :
C[k] = sum_j=0^n a[j]*cos(pi*j*k/n), 0<=k<=n
is divided into :
C[2*k] = sum'_j=0^n/2 (a[j]+a[n-j])*cos(pi*j*k/(n/2)),
C[2*k+1] = sum_j=0^n/2-1 (a[j]-a[n-j])*cos(pi*j*(k+1/2)/(n/2))
(sum' is a summation whose last term multiplies 1/2).
This routine uses "ddct" recursively.
To keep the in-place operation, the data in fft*g_h.*
are sorted in bit reversal order.
-------- dfst --------
A method to split into "dfst" and "ddst" of half length.
The transform :
S[k] = sum_j=1^n-1 a[j]*sin(pi*j*k/n), 0<k<n
is divided into :
S[2*k] = sum_j=1^n/2-1 (a[j]-a[n-j])*sin(pi*j*k/(n/2)),
S[2*k+1] = sum'_j=1^n/2 (a[j]+a[n-j])*sin(pi*j*(k+1/2)/(n/2))
(sum' is a summation whose last term multiplies 1/2).
This routine uses "ddst" recursively.
To keep the in-place operation, the data in fft*g_h.*
are sorted in bit reversal order.
Reference:
* Masatake MORI, Makoto NATORI, Tatuo TORII: Suchikeisan,
Iwanamikouzajyouhoukagaku18, Iwanami, 1982 (Japanese)
* Henri J. Nussbaumer: Fast Fourier Transform and Convolution
Algorithms, Springer Verlag, 1982
* C. S. Burrus, Notes on the FFT (with large FFT paper list)
http://www-dsp.rice.edu/research/fft/fftnote.asc
Copyright:
Copyright(C) 1996-2001 Takuya OOURA
email: ooura@mmm.t.u-tokyo.ac.jp
download: http://momonga.t.u-tokyo.ac.jp/~ooura/fft.html
You may use, copy, modify this code for any purpose and
without fee. You may distribute this ORIGINAL package.
History:
...
Dec. 1995 : Edit the General Purpose FFT
Mar. 1996 : Change the specification
Jun. 1996 : Change the method of trigonometric function table
Sep. 1996 : Modify the documents
Feb. 1997 : Change the butterfly loops
Dec. 1997 : Modify the documents
Dec. 1997 : Add "fft4g.*"
Jul. 1998 : Fix some bugs in the documents
Jul. 1998 : Add "fft8g.*" and delete "fft4f.*"
Jul. 1998 : Add a benchmark program "pi_fft.c"
Jul. 1999 : Add a simple version "fft*g_h.c"
Jul. 1999 : Add a Split-Radix FFT package "fftsg*.c"
Sep. 1999 : Reduce the memory operation (minor optimization)
Oct. 1999 : Change the butterfly structure of "fftsg*.c"
Oct. 1999 : Save the code size
Sep. 2001 : Add "fftsg.f"
Sep. 2001 : Add Pthread & Win32thread routines to "fftsg*.c"
Dec. 2006 : Fix a minor bug in "fftsg.f"

77
3rdparty/oourafft/readme2d.txt vendored Normal file
View File

@ -0,0 +1,77 @@
General Purpose 2D,3D FFT (Fast Fourier Transform) Package
Files
alloc.c : 2D-array Allocation
alloc.h : 2D-array Allocation
fft4f2d.c : 2D FFT Package in C - Version I (radix 4, 2)
fft4f2d.f : 2D FFT Package in Fortran - Version I (radix 4, 2)
fftsg.c : 1D FFT Package in C - Fast Version (Split-Radix)
fftsg.f : 1D FFT Package in Fortran - Fast Version (Split-Radix)
fftsg2d.c : 2D FFT Package in C - Version II (Split-Radix)
fftsg2d.f : 2D FFT Package in Fortran - Version II (Split-Radix)
fftsg3d.c : 3D FFT Package in C - Version II (Split-Radix)
fftsg3d.f : 3D FFT Package in Fortran - Version II (Split-Radix)
shrtdct.c : 8x8, 16x16 DCT Package
sample2d/
Makefile : for gcc, cc
Makefile.f77: for Fortran
Makefile.pth: Pthread version
fft4f2dt.c : Test Program for "fft4f2d.c"
fft4f2dt.f : Test Program for "fft4f2d.f"
fftsg2dt.c : Test Program for "fftsg2d.c"
fftsg2dt.f : Test Program for "fftsg2d.f"
fftsg3dt.c : Test Program for "fftsg3d.c"
fftsg3dt.f : Test Program for "fftsg3d.f"
shrtdctt.c : Test Program for "shrtdct.c"
Difference of Files
C and Fortran versions are equal and
the same routines are in each version.
---- Difference between "fft4f2d.*" and "fftsg2d.*" ----
"fft4f2d.*" are optimized for the old machines that
don't have the large size CPU cache.
"fftsg2d.*", "fftsg3d.*" use 1D FFT routines in "fftsg.*".
"fftsg2d.*", "fftsg3d.*" are optimized for the machines that
have the multi-level (L1,L2,etc) cache.
Routines in the Package
in fft4f2d.*, fftsg2d.*
cdft2d: 2-dim Complex Discrete Fourier Transform
rdft2d: 2-dim Real Discrete Fourier Transform
ddct2d: 2-dim Discrete Cosine Transform
ddst2d: 2-dim Discrete Sine Transform
rdft2dsort: rdft2d input/output ordering (fftsg2d.*)
in fftsg3d.*
cdft3d: 3-dim Complex Discrete Fourier Transform
rdft3d: 3-dim Real Discrete Fourier Transform
ddct3d: 3-dim Discrete Cosine Transform
ddst3d: 3-dim Discrete Sine Transform
rdft3dsort: rdft3d input/output ordering
in fftsg.*
cdft: 1-dim Complex Discrete Fourier Transform
rdft: 1-dim Real Discrete Fourier Transform
ddct: 1-dim Discrete Cosine Transform
ddst: 1-dim Discrete Sine Transform
dfct: 1-dim Real Symmetric DFT
dfst: 1-dim Real Anti-symmetric DFT
(these routines are called by fftsg2d.*, fftsg3d.*)
in shrtdct.c
ddct8x8s : Normalized 8x8 DCT
ddct16x16s: Normalized 16x16 DCT
(faster than ddct2d())
Usage
Brief explanations are in block comments of each packages.
The examples are given in the test programs.
Copyright
Copyright(C) 1997,2001 Takuya OOURA (email: ooura@kurims.kyoto-u.ac.jp).
You may use, copy, modify this code for any purpose and
without fee. You may distribute this ORIGINAL package.
History
...
Nov. 2001 : Add 3D-FFT routines
Dec. 2006 : Fix a documentation bug in "fftsg3d.*"
Dec. 2006 : Fix a minor bug in "fftsg.f"

View File

@ -235,7 +235,7 @@ if (NOT DEFINED PYBIND11_INCLUDE_DIR)
set(PYBIND11_INCLUDE_DIR "3rdparty/pybind11/include")
endif()
include_directories(common/kernel/ common/place/ common/route/ json/ frontend/ 3rdparty/json11/ ${PYBIND11_INCLUDE_DIR} ${Boost_INCLUDE_DIRS} ${Python3_INCLUDE_DIRS})
include_directories(common/kernel/ common/place/ common/route/ json/ frontend/ 3rdparty/json11/ 3rdparty/oourafft ${PYBIND11_INCLUDE_DIR} ${Boost_INCLUDE_DIRS} ${Python3_INCLUDE_DIRS})
find_package (Eigen3 REQUIRED NO_MODULE)
link_libraries(Eigen3::Eigen)
@ -246,9 +246,10 @@ aux_source_directory(common/route/ ROUTE_SRC_FILES)
aux_source_directory(json/ JSON_PARSER_FILES)
aux_source_directory(3rdparty/json11 EXT_JSON11_FILES)
aux_source_directory(3rdparty/oourafft EXT_OOURAFFT_FILES)
aux_source_directory(frontend/ FRONTEND_FILES)
set(COMMON_FILES ${KERNEL_SRC_FILES} ${PLACE_SRC_FILES} ${ROUTE_SRC_FILES} ${EXT_JSON11_FILES} ${JSON_PARSER_FILES} ${FRONTEND_FILES})
set(COMMON_FILES ${KERNEL_SRC_FILES} ${PLACE_SRC_FILES} ${ROUTE_SRC_FILES} ${EXT_JSON11_FILES} ${EXT_OOURAFFT_FILES} ${JSON_PARSER_FILES} ${FRONTEND_FILES})
if( NOT CMAKE_BUILD_TYPE )
set(CMAKE_BUILD_TYPE Release)
endif()

148
common/kernel/array2d.h Normal file
View File

@ -0,0 +1,148 @@
/*
* 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

View File

@ -72,6 +72,8 @@ struct DeterministicRNG
}
}
float rngf(float n) { return float(rng64() & 0x3fffffff) * (n / float(0x3fffffff)); }
void rngseed(uint64_t seed)
{
rngstate = seed ? seed : 0x3141592653589793;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,70 @@
/*
* nextpnr -- Next Generation Place and Route
*
* Copyright (C) 2022-23 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 PLACER_STATIC_H
#define PLACER_STATIC_H
#include "log.h"
#include "nextpnr.h"
NEXTPNR_NAMESPACE_BEGIN
struct StaticRect
{
StaticRect() : w(0), h(0){};
StaticRect(float w, float h) : w(w), h(h){};
float w, h;
float area() const { return w * h; }
};
struct StaticCellGroupCfg
{
// name of the group for debugging purposes
IdString name;
// bel buckets in this group
pool<BelBucketId> bel_buckets;
// cell & bel types in this group and the (normalised) area of that cell/bel type
dict<IdString, StaticRect> cell_area, bel_area;
// these cells (generally auxilliary CLB cells like RAMW; carry; MUX) are considered to have zero area when part of
// a macro with other non-zero-area cells
pool<IdString> zero_area_cells;
// size of spacers to insert
StaticRect spacer_rect{0.5, 0.5};
};
struct PlacerStaticCfg
{
PlacerStaticCfg(Context *ctx);
// These cell types will be randomly locked to prevent singular matrices
pool<IdString> ioBufTypes;
int hpwl_scale_x = 1;
int hpwl_scale_y = 1;
bool timing_driven = false;
// for calculating timing estimates based on distance
// estimate = c + mx*dx + my * dy
delay_t timing_c = 100, timing_mx = 100, timing_my = 100;
// groups of cells that should be placed together.
// group 0 must be LUTs and group 1 must be FFs, further groups for BRAM/DSP/misc
std::vector<StaticCellGroupCfg> cell_groups;
};
extern bool placer_static(Context *ctx, PlacerStaticCfg cfg);
NEXTPNR_NAMESPACE_END
#endif

142
common/place/static_util.h Normal file
View File

@ -0,0 +1,142 @@
/*
* nextpnr -- Next Generation Place and Route
*
* Copyright (C) 2023 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 STATIC_UTIL_H
#define STATIC_UTIL_H
#include <fstream>
#include "nextpnr_assertions.h"
#include "nextpnr_namespaces.h"
NEXTPNR_NAMESPACE_BEGIN
namespace StaticUtil {
enum class Axis
{
X,
Y
};
struct RealPair
{
RealPair() : x(0), y(0){};
RealPair(float x, float y) : x(x), y(y){};
explicit RealPair(Loc l, float bias = 0.0f) : x(l.x + bias), y(l.y + bias){};
float x, y;
RealPair &operator+=(const RealPair &other)
{
x += other.x;
y += other.y;
return *this;
}
RealPair &operator/=(float factor)
{
x /= factor;
y /= factor;
return *this;
}
friend RealPair operator+(RealPair a, RealPair b);
friend RealPair operator-(RealPair a, RealPair b);
RealPair operator*(float factor) const { return RealPair(x * factor, y * factor); }
RealPair operator/(float factor) const { return RealPair(x / factor, y / factor); }
// to simplify axis-generic code
inline float &at(Axis axis) { return (axis == Axis::Y) ? y : x; }
inline const float &at(Axis axis) const { return (axis == Axis::Y) ? y : x; }
};
inline RealPair operator+(RealPair a, RealPair b) { return RealPair(a.x + b.x, a.y + b.y); }
inline RealPair operator-(RealPair a, RealPair b) { return RealPair(a.x - b.x, a.y - b.y); }
// array2d; but as ourafft wants it
struct FFTArray
{
FFTArray(int width = 0, int height = 0) : m_width(width), m_height(height)
{
alloc();
fill(0);
}
void fill(float value)
{
for (int x = 0; x < m_width; x++)
for (int y = 0; y < m_height; y++)
m_data[x][y] = value;
}
void reset(int width, int height, float value = 0)
{
if (width != m_height || height != m_height) {
destroy();
m_width = width;
m_height = height;
alloc();
}
fill(value);
}
float &at(int x, int y)
{
NPNR_ASSERT(x >= 0 && x < m_width && y >= 0 && y < m_height);
return m_data[x][y];
}
float at(int x, int y) const
{
NPNR_ASSERT(x >= 0 && x < m_width && y >= 0 && y < m_height);
return m_data[x][y];
}
float **data() { return m_data; }
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;
}
}
~FFTArray() { destroy(); }
private:
int m_width, m_height;
float **m_data = nullptr;
void alloc()
{
if (m_width == 0)
return;
m_data = new float *[m_width];
for (int x = 0; x < m_width; x++)
m_data[x] = (m_height > 0) ? (new float[m_height]) : nullptr;
}
void destroy()
{
for (int x = 0; x < m_width; x++)
delete[] m_data[x];
delete[] m_data;
}
};
}; // namespace StaticUtil
NEXTPNR_NAMESPACE_END
#endif

View File

@ -30,6 +30,7 @@
#include "nextpnr.h"
#include "placer1.h"
#include "placer_heap.h"
#include "placer_static.h"
#include "router1.h"
#include "router2.h"
#include "timing.h"
@ -586,6 +587,49 @@ delay_t Arch::getRipupDelayPenalty() const { return 400; }
// -----------------------------------------------------------------------
namespace {
void configure_static(Arch *arch, PlacerStaticCfg &cfg)
{
{
cfg.cell_groups.emplace_back();
auto &comb = cfg.cell_groups.back();
comb.name = arch->id("COMB");
comb.bel_area[id_TRELLIS_COMB] = StaticRect(1.0f, 0.125f);
comb.bel_area[id_TRELLIS_RAMW] = StaticRect(1.0f, 0.125f);
comb.cell_area[id_TRELLIS_COMB] = StaticRect(1.0f, 0.125f);
comb.cell_area[id_TRELLIS_RAMW] = StaticRect(1.0f, 0.125f);
comb.zero_area_cells.insert(id_TRELLIS_RAMW);
comb.spacer_rect = StaticRect(1.0f, 0.125f);
}
{
cfg.cell_groups.emplace_back();
auto &comb = cfg.cell_groups.back();
comb.name = arch->id("FF");
comb.cell_area[id_TRELLIS_FF] = StaticRect(1.0f, 0.125f);
comb.bel_area[id_TRELLIS_FF] = StaticRect(1.0f, 0.125f);
comb.spacer_rect = StaticRect(1.0f, 0.125f);
}
{
cfg.cell_groups.emplace_back();
auto &comb = cfg.cell_groups.back();
comb.name = arch->id("RAM");
comb.cell_area[id_DP16KD] = StaticRect(2.0f, 1.0f);
comb.bel_area[id_DP16KD] = StaticRect(2.0f, 1.0f);
comb.spacer_rect = StaticRect(2.0f, 1.0f);
}
{
cfg.cell_groups.emplace_back();
auto &comb = cfg.cell_groups.back();
comb.name = arch->id("MUL");
comb.cell_area[id_MULT18X18D] = StaticRect(2.0f, 1.0f);
comb.bel_area[id_MULT18X18D] = StaticRect(2.0f, 1.0f);
comb.spacer_rect = StaticRect(2.0f, 1.0f);
}
}
} // namespace
bool Arch::place()
{
std::string placer = str_or_default(settings, id_placer, defaultPlacer);
@ -609,6 +653,11 @@ bool Arch::place()
if (!placer_heap(getCtx(), cfg))
return false;
} else if (placer == "static") {
PlacerStaticCfg cfg(getCtx());
configure_static(this, cfg);
if (!placer_static(getCtx(), cfg))
return false;
} else if (placer == "sa") {
if (!placer1(getCtx(), Placer1Cfg(getCtx())))
return false;
@ -1226,7 +1275,7 @@ WireId Arch::get_bank_eclk(int bank, int eclk)
const std::string Arch::defaultPlacer = "heap";
const std::vector<std::string> Arch::availablePlacers = {"sa", "heap"};
const std::vector<std::string> Arch::availablePlacers = {"sa", "heap", "static"};
const std::string Arch::defaultRouter = "router1";
const std::vector<std::string> Arch::availableRouters = {"router1", "router2"};