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")
|
set(PYBIND11_INCLUDE_DIR "3rdparty/pybind11/include")
|
||||||
endif()
|
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)
|
find_package (Eigen3 REQUIRED NO_MODULE)
|
||||||
link_libraries(Eigen3::Eigen)
|
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(json/ JSON_PARSER_FILES)
|
||||||
aux_source_directory(3rdparty/json11 EXT_JSON11_FILES)
|
aux_source_directory(3rdparty/json11 EXT_JSON11_FILES)
|
||||||
|
aux_source_directory(3rdparty/oourafft EXT_OOURAFFT_FILES)
|
||||||
aux_source_directory(frontend/ FRONTEND_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 )
|
if( NOT CMAKE_BUILD_TYPE )
|
||||||
set(CMAKE_BUILD_TYPE Release)
|
set(CMAKE_BUILD_TYPE Release)
|
||||||
endif()
|
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)
|
void rngseed(uint64_t seed)
|
||||||
{
|
{
|
||||||
rngstate = seed ? seed : 0x3141592653589793;
|
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 "nextpnr.h"
|
||||||
#include "placer1.h"
|
#include "placer1.h"
|
||||||
#include "placer_heap.h"
|
#include "placer_heap.h"
|
||||||
|
#include "placer_static.h"
|
||||||
#include "router1.h"
|
#include "router1.h"
|
||||||
#include "router2.h"
|
#include "router2.h"
|
||||||
#include "timing.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()
|
bool Arch::place()
|
||||||
{
|
{
|
||||||
std::string placer = str_or_default(settings, id_placer, defaultPlacer);
|
std::string placer = str_or_default(settings, id_placer, defaultPlacer);
|
||||||
@ -609,6 +653,11 @@ bool Arch::place()
|
|||||||
|
|
||||||
if (!placer_heap(getCtx(), cfg))
|
if (!placer_heap(getCtx(), cfg))
|
||||||
return false;
|
return false;
|
||||||
|
} else if (placer == "static") {
|
||||||
|
PlacerStaticCfg cfg(getCtx());
|
||||||
|
configure_static(this, cfg);
|
||||||
|
if (!placer_static(getCtx(), cfg))
|
||||||
|
return false;
|
||||||
} else if (placer == "sa") {
|
} else if (placer == "sa") {
|
||||||
if (!placer1(getCtx(), Placer1Cfg(getCtx())))
|
if (!placer1(getCtx(), Placer1Cfg(getCtx())))
|
||||||
return false;
|
return false;
|
||||||
@ -1226,7 +1275,7 @@ WireId Arch::get_bank_eclk(int bank, int eclk)
|
|||||||
|
|
||||||
const std::string Arch::defaultPlacer = "heap";
|
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::string Arch::defaultRouter = "router1";
|
||||||
const std::vector<std::string> Arch::availableRouters = {"router1", "router2"};
|
const std::vector<std::string> Arch::availableRouters = {"router1", "router2"};
|
||||||
|
Loading…
Reference in New Issue
Block a user