HeAP: Make HeAP placer optional
A CMake option 'BUILD_HEAP' (default on) configures building of the HeAP placer and the associated Eigen3 dependency. Default for the iCE40 is SA placer, with --heap-placer to use HeAP Default for the ECP5 is HeAP placer, as SA placer can take 1hr+ for large ECP5 designs and HeAP tends to give better QoR. --sa-placer can be used to use SA instead, and auto-fallback to SA if HeAP not built. Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
parent
1c824709e2
commit
7142db28a8
@ -5,6 +5,8 @@ project(nextpnr)
|
|||||||
option(BUILD_GUI "Build GUI" ON)
|
option(BUILD_GUI "Build GUI" ON)
|
||||||
option(BUILD_PYTHON "Build Python Integration" ON)
|
option(BUILD_PYTHON "Build Python Integration" ON)
|
||||||
option(BUILD_TESTS "Build GUI" OFF)
|
option(BUILD_TESTS "Build GUI" OFF)
|
||||||
|
option(BUILD_HEAP "Build HeAP analytic placer" ON)
|
||||||
|
option(USE_OPENMP "Use OpenMP to accelerate analytic placer" OFF)
|
||||||
option(COVERAGE "Add code coverage info" OFF)
|
option(COVERAGE "Add code coverage info" OFF)
|
||||||
option(STATIC_BUILD "Create static build" OFF)
|
option(STATIC_BUILD "Create static build" OFF)
|
||||||
option(EXTERNAL_CHIPDB "Create build with pre-built chipdb binaries" OFF)
|
option(EXTERNAL_CHIPDB "Create build with pre-built chipdb binaries" OFF)
|
||||||
@ -58,7 +60,11 @@ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D_DEBUG /W4 /wd4100 /wd4244
|
|||||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /W4 /wd4100 /wd4244 /wd4125 /wd4800 /wd4456 /wd4458 /wd4305 /wd4459 /wd4121 /wd4996 /wd4127")
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /W4 /wd4100 /wd4244 /wd4125 /wd4800 /wd4456 /wd4458 /wd4305 /wd4459 /wd4121 /wd4996 /wd4127")
|
||||||
else()
|
else()
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "-Wall -fPIC -ggdb -pipe")
|
set(CMAKE_CXX_FLAGS_DEBUG "-Wall -fPIC -ggdb -pipe")
|
||||||
|
if (USE_OPENMP)
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "-Wall -fPIC -O3 -g -pipe -fopenmp")
|
set(CMAKE_CXX_FLAGS_RELEASE "-Wall -fPIC -O3 -g -pipe -fopenmp")
|
||||||
|
else()
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "-Wall -fPIC -O3 -g -pipe")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
set(CMAKE_DEFIN)
|
set(CMAKE_DEFIN)
|
||||||
|
|
||||||
@ -180,10 +186,15 @@ if (BUILD_PYTHON)
|
|||||||
endif ()
|
endif ()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package (Eigen3 REQUIRED NO_MODULE)
|
include_directories(common/ json/ ${Boost_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIRS})
|
||||||
|
|
||||||
include_directories(common/ json/ ${Boost_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIRS} ${EIGEN3_INCLUDE_DIRS})
|
if(BUILD_HEAP)
|
||||||
|
find_package (Eigen3 REQUIRED NO_MODULE)
|
||||||
|
include_directories(${EIGEN3_INCLUDE_DIRS})
|
||||||
add_definitions(${EIGEN3_DEFINITIONS})
|
add_definitions(${EIGEN3_DEFINITIONS})
|
||||||
|
add_definitions(-DWITH_HEAP)
|
||||||
|
endif()
|
||||||
|
|
||||||
aux_source_directory(common/ COMMON_SRC_FILES)
|
aux_source_directory(common/ COMMON_SRC_FILES)
|
||||||
aux_source_directory(json/ JSON_PARSER_FILES)
|
aux_source_directory(json/ JSON_PARSER_FILES)
|
||||||
set(COMMON_FILES ${COMMON_SRC_FILES} ${JSON_PARSER_FILES})
|
set(COMMON_FILES ${COMMON_SRC_FILES} ${JSON_PARSER_FILES})
|
||||||
|
@ -31,6 +31,8 @@
|
|||||||
* - To make the placer timing-driven, the bound2bound weights are multiplied by (1 + 10 * crit^2)
|
* - To make the placer timing-driven, the bound2bound weights are multiplied by (1 + 10 * crit^2)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef WITH_HEAP
|
||||||
|
|
||||||
#include <Eigen/Core>
|
#include <Eigen/Core>
|
||||||
#include <Eigen/IterativeLinearSolvers>
|
#include <Eigen/IterativeLinearSolvers>
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
@ -1509,5 +1511,19 @@ class HeAPPlacer
|
|||||||
int HeAPPlacer::CutSpreader::seq = 0;
|
int HeAPPlacer::CutSpreader::seq = 0;
|
||||||
|
|
||||||
bool placer_heap(Context *ctx) { return HeAPPlacer(ctx).place(); }
|
bool placer_heap(Context *ctx) { return HeAPPlacer(ctx).place(); }
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
#include "nextpnr.h"
|
||||||
|
|
||||||
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
|
bool placer_heap(Context *ctx)
|
||||||
|
{
|
||||||
|
log_error("nextpnr was built without the HeAP placer\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
NEXTPNR_NAMESPACE_END
|
||||||
|
|
||||||
|
#endif
|
||||||
|
19
ecp5/arch.cc
19
ecp5/arch.cc
@ -457,6 +457,7 @@ delay_t Arch::estimateDelay(WireId src, WireId dst) const
|
|||||||
auto src_loc = est_location(src), dst_loc = est_location(dst);
|
auto src_loc = est_location(src), dst_loc = est_location(dst);
|
||||||
|
|
||||||
int dx = abs(src_loc.first - dst_loc.first), dy = abs(src_loc.second - dst_loc.second);
|
int dx = abs(src_loc.first - dst_loc.first), dy = abs(src_loc.second - dst_loc.second);
|
||||||
|
|
||||||
return (130 - 25 * args.speed) *
|
return (130 - 25 * args.speed) *
|
||||||
(6 + std::max(dx - 5, 0) + std::max(dy - 5, 0) + 2 * (std::min(dx, 5) + std::min(dy, 5)));
|
(6 + std::max(dx - 5, 0) + std::max(dy - 5, 0) + 2 * (std::min(dx, 5) + std::min(dy, 5)));
|
||||||
|
|
||||||
@ -486,6 +487,7 @@ delay_t Arch::predictDelay(const NetInfo *net_info, const PortRef &sink) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
int dx = abs(driver_loc.x - sink_loc.x), dy = abs(driver_loc.y - sink_loc.y);
|
int dx = abs(driver_loc.x - sink_loc.x), dy = abs(driver_loc.y - sink_loc.y);
|
||||||
|
|
||||||
return (130 - 25 * args.speed) *
|
return (130 - 25 * args.speed) *
|
||||||
(6 + std::max(dx - 5, 0) + std::max(dy - 5, 0) + 2 * (std::min(dx, 5) + std::min(dy, 5)));
|
(6 + std::max(dx - 5, 0) + std::max(dy - 5, 0) + 2 * (std::min(dx, 5) + std::min(dy, 5)));
|
||||||
}
|
}
|
||||||
@ -505,7 +507,22 @@ bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
|
|
||||||
bool Arch::place() { return placer_heap(getCtx()); }
|
bool Arch::place()
|
||||||
|
{
|
||||||
|
// HeAP is the default unless overriden or not built
|
||||||
|
#ifdef WITH_HEAP
|
||||||
|
if (bool_or_default(settings, id("sa_placer"), false)) {
|
||||||
|
#endif
|
||||||
|
if (!placer1(getCtx(), Placer1Cfg(getCtx())))
|
||||||
|
return false;
|
||||||
|
#ifdef WITH_HEAP
|
||||||
|
} else {
|
||||||
|
if (!placer_heap(getCtx()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool Arch::route()
|
bool Arch::route()
|
||||||
{
|
{
|
||||||
|
@ -59,6 +59,8 @@ po::options_description ECP5CommandHandler::getArchOptions()
|
|||||||
specific.add_options()("um5g-45k", "set device type to LFE5UM5G-45F");
|
specific.add_options()("um5g-45k", "set device type to LFE5UM5G-45F");
|
||||||
specific.add_options()("um5g-85k", "set device type to LFE5UM5G-85F");
|
specific.add_options()("um5g-85k", "set device type to LFE5UM5G-85F");
|
||||||
|
|
||||||
|
specific.add_options()("sa-placer", "use pure simulated annealing placer instead of HeAP analytic placer");
|
||||||
|
|
||||||
specific.add_options()("package", po::value<std::string>(), "select device package (defaults to CABGA381)");
|
specific.add_options()("package", po::value<std::string>(), "select device package (defaults to CABGA381)");
|
||||||
specific.add_options()("speed", po::value<int>(), "select device speedgrade (6, 7 or 8)");
|
specific.add_options()("speed", po::value<int>(), "select device speedgrade (6, 7 or 8)");
|
||||||
|
|
||||||
@ -149,8 +151,12 @@ std::unique_ptr<Context> ECP5CommandHandler::createContext()
|
|||||||
chipArgs.speed = ArchArgs::SPEED_6;
|
chipArgs.speed = ArchArgs::SPEED_6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
auto ctx = std::unique_ptr<Context>(new Context(chipArgs));
|
||||||
|
|
||||||
return std::unique_ptr<Context>(new Context(chipArgs));
|
if (vm.count("sa-placer"))
|
||||||
|
ctx->settings[ctx->id("sa_placer")] = "1";
|
||||||
|
|
||||||
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ECP5CommandHandler::customAfterLoad(Context *ctx)
|
void ECP5CommandHandler::customAfterLoad(Context *ctx)
|
||||||
|
@ -671,10 +671,13 @@ bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay
|
|||||||
|
|
||||||
bool Arch::place()
|
bool Arch::place()
|
||||||
{
|
{
|
||||||
// if (!placer1(getCtx(), Placer1Cfg(getCtx())))
|
if (bool_or_default(settings, id("heap_placer"), false)) {
|
||||||
// return false;
|
|
||||||
if (!placer_heap(getCtx()))
|
if (!placer_heap(getCtx()))
|
||||||
return false;
|
return false;
|
||||||
|
} else {
|
||||||
|
if (!placer1(getCtx(), Placer1Cfg(getCtx())))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (bool_or_default(settings, id("opt_timing"), false)) {
|
if (bool_or_default(settings, id("opt_timing"), false)) {
|
||||||
TimingOptCfg tocfg(getCtx());
|
TimingOptCfg tocfg(getCtx());
|
||||||
tocfg.cellTypes.insert(id_ICESTORM_LC);
|
tocfg.cellTypes.insert(id_ICESTORM_LC);
|
||||||
|
@ -69,6 +69,8 @@ po::options_description Ice40CommandHandler::getArchOptions()
|
|||||||
specific.add_options()("promote-logic",
|
specific.add_options()("promote-logic",
|
||||||
"enable promotion of 'logic' globals (in addition to clk/ce/sr by default)");
|
"enable promotion of 'logic' globals (in addition to clk/ce/sr by default)");
|
||||||
specific.add_options()("no-promote-globals", "disable all global promotion");
|
specific.add_options()("no-promote-globals", "disable all global promotion");
|
||||||
|
specific.add_options()("heap-placer",
|
||||||
|
"use HeAP analytic placer instead of simulated annealing (faster, experimental)");
|
||||||
specific.add_options()("opt-timing", "run post-placement timing optimisation pass (experimental)");
|
specific.add_options()("opt-timing", "run post-placement timing optimisation pass (experimental)");
|
||||||
specific.add_options()("tmfuzz", "run path delay estimate fuzzer");
|
specific.add_options()("tmfuzz", "run path delay estimate fuzzer");
|
||||||
specific.add_options()("pcf-allow-unconstrained", "don't require PCF to constrain all IO");
|
specific.add_options()("pcf-allow-unconstrained", "don't require PCF to constrain all IO");
|
||||||
@ -176,7 +178,8 @@ std::unique_ptr<Context> Ice40CommandHandler::createContext()
|
|||||||
ctx->settings[ctx->id("opt_timing")] = "1";
|
ctx->settings[ctx->id("opt_timing")] = "1";
|
||||||
if (vm.count("pcf-allow-unconstrained"))
|
if (vm.count("pcf-allow-unconstrained"))
|
||||||
ctx->settings[ctx->id("pcf_allow_unconstrained")] = "1";
|
ctx->settings[ctx->id("pcf_allow_unconstrained")] = "1";
|
||||||
|
if (vm.count("heap-placer"))
|
||||||
|
ctx->settings[ctx->id("heap_placer")] = "1";
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user