placer_static: Initial prototype
Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
parent
95e7598cc6
commit
0eb9a9ad02
3305
3rdparty/oourafft/fftsg.cc
vendored
Normal file
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
24
3rdparty/oourafft/fftsg.h
vendored
Normal 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
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
167
3rdparty/oourafft/readme.txt
vendored
Normal 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
77
3rdparty/oourafft/readme2d.txt
vendored
Normal 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"
|
||||
|
@ -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
148
common/kernel/array2d.h
Normal 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
|
@ -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;
|
||||
|
1296
common/place/placer_static.cc
Normal file
1296
common/place/placer_static.cc
Normal file
File diff suppressed because it is too large
Load Diff
70
common/place/placer_static.h
Normal file
70
common/place/placer_static.h
Normal 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
142
common/place/static_util.h
Normal 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
|
51
ecp5/arch.cc
51
ecp5/arch.cc
@ -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"};
|
||||
|
Loading…
Reference in New Issue
Block a user