nextpnr/gowin/main.cc
YRabbit 590b9050ff gowin: add a separate router for the clocks
A simple router that takes advantage of the fact that in each cell with
DFFs their CLK inputs can directly connect to the global clock network.

Networks with a large number of such sinks are sought and then each
network is assigned to the available independent global clock networks.

There are limited possibilities for routing mixed networks, that is,
when the sinks are not only CLKs: in this case an attempt is made to use
wires such as SN10/20 and EW10/20, that is, one short transition can be
added between the global clock network and the sink.

* At this time, networks with a source other than the I/O pin are not
  supported. This is typical for Tangnano4k and runber boards.

* Router is disabled by default, you need to specify option
  --enable-globals to activate

* No new chip bases are required. This may change in the distant future.

Signed-off-by: YRabbit <rabbit@yrabbit.cyou>
2022-06-23 11:42:58 +10:00

116 lines
4.1 KiB
C++

/*
* nextpnr -- Next Generation Place and Route
*
* Copyright (C) 2018 Claire Xenia Wolf <claire@yosyshq.com>
* Copyright (C) 2020 Pepijn de Vos <pepijn@symbioticeda.com>
*
* 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.
*
*/
#ifdef MAIN_EXECUTABLE
#include <fstream>
#include <locale>
#include <regex>
#include "command.h"
#include "design_utils.h"
#include "log.h"
#include "timing.h"
USING_NEXTPNR_NAMESPACE
class GowinCommandHandler : public CommandHandler
{
public:
GowinCommandHandler(int argc, char **argv);
virtual ~GowinCommandHandler(){};
std::unique_ptr<Context> createContext(dict<std::string, Property> &values) override;
void setupArchContext(Context *ctx) override{};
void customAfterLoad(Context *ctx) override;
protected:
po::options_description getArchOptions() override;
};
GowinCommandHandler::GowinCommandHandler(int argc, char **argv) : CommandHandler(argc, argv) {}
po::options_description GowinCommandHandler::getArchOptions()
{
po::options_description specific("Architecture specific options");
specific.add_options()("device", po::value<std::string>(), "device name");
specific.add_options()("family", po::value<std::string>(), "family name");
specific.add_options()("cst", po::value<std::string>(), "physical constraints file");
specific.add_options()("enable-globals", "separate routing of the clocks");
specific.add_options()("enable-auto-longwires", "automatic detection and routing of long wires");
return specific;
}
std::unique_ptr<Context> GowinCommandHandler::createContext(dict<std::string, Property> &values)
{
if (!vm.count("device")) {
log_error("The device must be specified\n");
}
std::regex devicere = std::regex("GW1N([SZ]?)[A-Z]*-(LV|UV|UX)([0-9])(C?).*");
std::smatch match;
std::string device = vm["device"].as<std::string>();
if (!std::regex_match(device, match, devicere)) {
log_error("Invalid device %s\n", device.c_str());
}
ArchArgs chipArgs;
chipArgs.gui = vm.count("gui") != 0;
if (vm.count("family")) {
chipArgs.family = vm["family"].as<std::string>();
} else {
char buf[36];
// GW1N and GW1NR variants share the same database.
// Most Gowin devices are a System in Package with some SDRAM wirebonded to a GPIO bank.
// However, it appears that the S series with embedded ARM core are unique silicon.
snprintf(buf, 36, "GW1N%s-%s", match[1].str().c_str(), match[3].str().c_str());
chipArgs.family = buf;
}
chipArgs.partnumber = match[0];
auto ctx = std::unique_ptr<Context>(new Context(chipArgs));
// routing options
// the default values will change in the future
ctx->settings[ctx->id("arch.enable-globals")] = 0;
ctx->settings[ctx->id("arch.enable-auto-longwires")] = 0;
if (vm.count("enable-globals")) {
ctx->settings[ctx->id("arch.enable-globals")] = 1;
}
if (vm.count("enable-auto-longwires")) {
ctx->settings[ctx->id("arch.enable-auto-longwires")] = 1;
}
return ctx;
}
void GowinCommandHandler::customAfterLoad(Context *ctx)
{
if (vm.count("cst")) {
std::string filename = vm["cst"].as<std::string>();
std::ifstream in(filename);
if (!in)
log_error("Failed to open input CST file %s.\n", filename.c_str());
ctx->read_cst(in);
}
}
int main(int argc, char *argv[])
{
GowinCommandHandler handler(argc, argv);
return handler.exec();
}
#endif