aboutsummaryrefslogtreecommitdiffstats
path: root/ice40
diff options
context:
space:
mode:
authorSergiusz Bazanski <q3k@q3k.org>2018-06-22 14:29:28 +0100
committerSergiusz Bazanski <q3k@q3k.org>2018-06-22 14:29:28 +0100
commit858acc5c1c0ee4bbdfb8d2012b80cda656ca39db (patch)
tree7cc94b94e40c05c5a7baae61c9d0db4f23a31b60 /ice40
parent98b1f0c041b01d07f64e8e04503f8eccb05a93de (diff)
parentf86a0d6c8c8792c36c87cf345665ce7c9fbcc60f (diff)
downloadnextpnr-858acc5c1c0ee4bbdfb8d2012b80cda656ca39db.tar.gz
nextpnr-858acc5c1c0ee4bbdfb8d2012b80cda656ca39db.tar.bz2
nextpnr-858acc5c1c0ee4bbdfb8d2012b80cda656ca39db.zip
Merge branch 'master' of gitlab.com:SymbioticEDA/nextpnr into q3k/gl
Diffstat (limited to 'ice40')
-rw-r--r--ice40/arch.h10
-rw-r--r--ice40/bitstream.cc13
-rw-r--r--ice40/main.cc471
-rw-r--r--ice40/pack.cc69
-rw-r--r--ice40/pcf.cc75
-rw-r--r--ice40/pcf.h2
-rwxr-xr-xice40/picorv32_arachne.sh4
7 files changed, 354 insertions, 290 deletions
diff --git a/ice40/arch.h b/ice40/arch.h
index 85fb9fc0..f3a46f5c 100644
--- a/ice40/arch.h
+++ b/ice40/arch.h
@@ -515,6 +515,8 @@ struct Arch : BaseCtx
return id(chip_info->bel_data[bel.index].name.get());
}
+ uint32_t getBelChecksum(BelId bel) const { return bel.index; }
+
void bindBel(BelId bel, IdString cell)
{
assert(bel != BelId());
@@ -607,6 +609,8 @@ struct Arch : BaseCtx
return id(chip_info->wire_data[wire.index].name.get());
}
+ uint32_t getWireChecksum(WireId wire) const { return wire.index; }
+
void bindWire(WireId wire, IdString net)
{
assert(wire != WireId());
@@ -646,6 +650,8 @@ struct Arch : BaseCtx
PipId getPipByName(IdString name) const;
IdString getPipName(PipId pip) const;
+ uint32_t getPipChecksum(PipId pip) const { return pip.index; }
+
void bindPip(PipId pip, IdString net)
{
assert(pip != PipId());
@@ -755,8 +761,10 @@ struct Arch : BaseCtx
void estimatePosition(BelId bel, int &x, int &y, bool &gb) const;
delay_t estimateDelay(WireId src, WireId dst) const;
- delay_t getDelayEpsilon() const { return 10; }
+ delay_t getDelayEpsilon() const { return 20; }
+ delay_t getRipupDelayPenalty() const { return 200; }
float getDelayNS(delay_t v) const { return v * 0.001; }
+ uint32_t getDelayChecksum(delay_t v) const { return v; }
// -------------------------------------------------
diff --git a/ice40/bitstream.cc b/ice40/bitstream.cc
index 8754fef7..e722cea4 100644
--- a/ice40/bitstream.cc
+++ b/ice40/bitstream.cc
@@ -229,6 +229,16 @@ void write_asc(const Context *ctx, std::ostream &out)
set_config(ti, config.at(iey).at(iex),
"IoCtrl.REN_" + std::to_string(iez), !pullup);
}
+
+ if (ctx->args.type == ArchArgs::UP5K) {
+ if (iez == 0) {
+ set_config(ti, config.at(iey).at(iex), "IoCtrl.cf_bit_39",
+ !pullup);
+ } else if (iez == 1) {
+ set_config(ti, config.at(iey).at(iex), "IoCtrl.cf_bit_35",
+ !pullup);
+ }
+ }
} else if (cell.second->type == ctx->id("SB_GB")) {
// no cell config bits
} else if (cell.second->type == ctx->id("ICESTORM_RAM")) {
@@ -312,7 +322,8 @@ void write_asc(const Context *ctx, std::ostream &out)
ctx->args.type == ArchArgs::HX8K) {
setColBufCtrl = (y == 8 || y == 9 || y == 24 || y == 25);
} else if (ctx->args.type == ArchArgs::UP5K) {
- if (tile == TILE_LOGIC) {
+ if (tile == TILE_LOGIC || tile == TILE_RAMB ||
+ tile == TILE_RAMT) {
setColBufCtrl = (y == 4 || y == 5 || y == 14 || y == 15 ||
y == 26 || y == 27);
} else {
diff --git a/ice40/main.cc b/ice40/main.cc
index c82cada3..f2100d45 100644
--- a/ice40/main.cc
+++ b/ice40/main.cc
@@ -39,6 +39,8 @@
#include "timing.h"
#include "version.h"
+USING_NEXTPNR_NAMESPACE
+
void svg_dump_el(const GraphicElement &el)
{
float scale = 10.0, offset = 10.0;
@@ -61,268 +63,291 @@ void svg_dump_el(const GraphicElement &el)
int main(int argc, char *argv[])
{
- namespace po = boost::program_options;
- int rc = 0;
- std::string str;
-
- log_files.push_back(stdout);
-
- po::options_description options("Allowed options");
- options.add_options()("help,h", "show help");
- options.add_options()("verbose,v", "verbose output");
- options.add_options()("force,f", "keep running after errors");
- options.add_options()("gui", "start gui");
- options.add_options()("svg", "dump SVG file");
- options.add_options()("pack-only",
- "pack design only without placement or routing");
-
- options.add_options()("run", po::value<std::vector<std::string>>(),
- "python file to execute");
- options.add_options()("json", po::value<std::string>(),
- "JSON design file to ingest");
- options.add_options()("pcf", po::value<std::string>(),
- "PCF constraints file to ingest");
- options.add_options()("asc", po::value<std::string>(),
- "asc bitstream file to write");
- options.add_options()("seed", po::value<int>(),
- "seed value for random number generator");
- options.add_options()("version,V", "show version");
- options.add_options()("tmfuzz", "run path delay estimate fuzzer");
- options.add_options()("lp384", "set device type to iCE40LP384");
- options.add_options()("lp1k", "set device type to iCE40LP1K");
- options.add_options()("lp8k", "set device type to iCE40LP8K");
- options.add_options()("hx1k", "set device type to iCE40HX1K");
- options.add_options()("hx8k", "set device type to iCE40HX8K");
- options.add_options()("up5k", "set device type to iCE40UP5K");
- options.add_options()("package", po::value<std::string>(),
- "set device package");
- po::positional_options_description pos;
- pos.add("run", -1);
-
- po::variables_map vm;
try {
- po::parsed_options parsed = po::command_line_parser(argc, argv)
- .options(options)
- .positional(pos)
- .run();
-
- po::store(parsed, vm);
-
- po::notify(vm);
- }
+ namespace po = boost::program_options;
+ int rc = 0;
+ std::string str;
+
+ log_files.push_back(stdout);
+
+ po::options_description options("Allowed options");
+ options.add_options()("help,h", "show help");
+ options.add_options()("verbose,v", "verbose output");
+ options.add_options()("debug", "debug output");
+ options.add_options()("force,f", "keep running after errors");
+ options.add_options()("gui", "start gui");
+ options.add_options()("svg", "dump SVG file");
+ options.add_options()("pack-only",
+ "pack design only without placement or routing");
+
+ options.add_options()("run", po::value<std::vector<std::string>>(),
+ "python file to execute");
+ options.add_options()("json", po::value<std::string>(),
+ "JSON design file to ingest");
+ options.add_options()("pcf", po::value<std::string>(),
+ "PCF constraints file to ingest");
+ options.add_options()("asc", po::value<std::string>(),
+ "asc bitstream file to write");
+ options.add_options()("seed", po::value<int>(),
+ "seed value for random number generator");
+ options.add_options()("version,V", "show version");
+ options.add_options()("tmfuzz", "run path delay estimate fuzzer");
+ options.add_options()("lp384", "set device type to iCE40LP384");
+ options.add_options()("lp1k", "set device type to iCE40LP1K");
+ options.add_options()("lp8k", "set device type to iCE40LP8K");
+ options.add_options()("hx1k", "set device type to iCE40HX1K");
+ options.add_options()("hx8k", "set device type to iCE40HX8K");
+ options.add_options()("up5k", "set device type to iCE40UP5K");
+ options.add_options()("freq", po::value<double>(),
+ "set target frequency for design in MHz");
+ options.add_options()("package", po::value<std::string>(),
+ "set device package");
+ po::positional_options_description pos;
+ pos.add("run", -1);
+
+ po::variables_map vm;
+ try {
+ po::parsed_options parsed = po::command_line_parser(argc, argv)
+ .options(options)
+ .positional(pos)
+ .run();
+
+ po::store(parsed, vm);
+
+ po::notify(vm);
+ }
- catch (std::exception &e) {
- std::cout << e.what() << "\n";
- return 1;
- }
+ catch (std::exception &e) {
+ std::cout << e.what() << "\n";
+ return 1;
+ }
- if (vm.count("help") || argc == 1) {
- help:
- std::cout << boost::filesystem::basename(argv[0])
- << " -- Next Generation Place and Route (git "
- "sha1 " GIT_COMMIT_HASH_STR ")\n";
- std::cout << "\n";
- std::cout << options << "\n";
- return argc != 1;
- }
+ if (vm.count("help") || argc == 1) {
+ help:
+ std::cout << boost::filesystem::basename(argv[0])
+ << " -- Next Generation Place and Route (git "
+ "sha1 " GIT_COMMIT_HASH_STR ")\n";
+ std::cout << "\n";
+ std::cout << options << "\n";
+ return argc != 1;
+ }
- if (vm.count("version")) {
- std::cout << boost::filesystem::basename(argv[0])
- << " -- Next Generation Place and Route (git "
- "sha1 " GIT_COMMIT_HASH_STR ")\n";
- return 1;
- }
+ if (vm.count("version")) {
+ std::cout << boost::filesystem::basename(argv[0])
+ << " -- Next Generation Place and Route (git "
+ "sha1 " GIT_COMMIT_HASH_STR ")\n";
+ return 1;
+ }
- ArchArgs chipArgs;
+ ArchArgs chipArgs;
- if (vm.count("lp384")) {
- if (chipArgs.type != ArchArgs::NONE)
- goto help;
- chipArgs.type = ArchArgs::LP384;
- chipArgs.package = "qn32";
- }
+ if (vm.count("lp384")) {
+ if (chipArgs.type != ArchArgs::NONE)
+ goto help;
+ chipArgs.type = ArchArgs::LP384;
+ chipArgs.package = "qn32";
+ }
- if (vm.count("lp1k")) {
- if (chipArgs.type != ArchArgs::NONE)
- goto help;
- chipArgs.type = ArchArgs::LP1K;
- chipArgs.package = "tq144";
- }
+ if (vm.count("lp1k")) {
+ if (chipArgs.type != ArchArgs::NONE)
+ goto help;
+ chipArgs.type = ArchArgs::LP1K;
+ chipArgs.package = "tq144";
+ }
- if (vm.count("lp8k")) {
- if (chipArgs.type != ArchArgs::NONE)
- goto help;
- chipArgs.type = ArchArgs::LP8K;
- chipArgs.package = "ct256";
- }
+ if (vm.count("lp8k")) {
+ if (chipArgs.type != ArchArgs::NONE)
+ goto help;
+ chipArgs.type = ArchArgs::LP8K;
+ chipArgs.package = "ct256";
+ }
- if (vm.count("hx1k")) {
- if (chipArgs.type != ArchArgs::NONE)
- goto help;
- chipArgs.type = ArchArgs::HX1K;
- chipArgs.package = "tq144";
- }
+ if (vm.count("hx1k")) {
+ if (chipArgs.type != ArchArgs::NONE)
+ goto help;
+ chipArgs.type = ArchArgs::HX1K;
+ chipArgs.package = "tq144";
+ }
- if (vm.count("hx8k")) {
- if (chipArgs.type != ArchArgs::NONE)
- goto help;
- chipArgs.type = ArchArgs::HX8K;
- chipArgs.package = "ct256";
- }
+ if (vm.count("hx8k")) {
+ if (chipArgs.type != ArchArgs::NONE)
+ goto help;
+ chipArgs.type = ArchArgs::HX8K;
+ chipArgs.package = "ct256";
+ }
- if (vm.count("up5k")) {
- if (chipArgs.type != ArchArgs::NONE)
- goto help;
- chipArgs.type = ArchArgs::UP5K;
- chipArgs.package = "sg48";
- }
+ if (vm.count("up5k")) {
+ if (chipArgs.type != ArchArgs::NONE)
+ goto help;
+ chipArgs.type = ArchArgs::UP5K;
+ chipArgs.package = "sg48";
+ }
- if (chipArgs.type == ArchArgs::NONE) {
- chipArgs.type = ArchArgs::HX1K;
- chipArgs.package = "tq144";
- }
+ if (chipArgs.type == ArchArgs::NONE) {
+ chipArgs.type = ArchArgs::HX1K;
+ chipArgs.package = "tq144";
+ }
#ifdef ICE40_HX1K_ONLY
- if (chipArgs.type != ArchArgs::HX1K) {
- std::cout << "This version of nextpnr-ice40 is built with HX1K-support "
- "only.\n";
- return 1;
- }
+ if (chipArgs.type != ArchArgs::HX1K) {
+ std::cout << "This version of nextpnr-ice40 is built with "
+ "HX1K-support "
+ "only.\n";
+ return 1;
+ }
#endif
- if (vm.count("package"))
- chipArgs.package = vm["package"].as<std::string>();
-
- Context ctx(chipArgs);
- init_python(argv[0]);
- python_export_global("ctx", ctx);
+ if (vm.count("package"))
+ chipArgs.package = vm["package"].as<std::string>();
- if (vm.count("verbose")) {
- ctx.verbose = true;
- }
+ Context ctx(chipArgs);
+ init_python(argv[0]);
+ python_export_global("ctx", ctx);
- if (vm.count("force")) {
- ctx.force = true;
- }
+ if (vm.count("verbose")) {
+ ctx.verbose = true;
+ }
- if (vm.count("seed")) {
- ctx.rngseed(vm["seed"].as<int>());
- }
+ if (vm.count("debug")) {
+ ctx.verbose = true;
+ ctx.debug = true;
+ }
- if (vm.count("svg")) {
- std::cout << "<svg xmlns=\"http://www.w3.org/2000/svg\" "
- "xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n";
- for (auto bel : ctx.getBels()) {
- std::cout << "<!-- " << ctx.getBelName(bel).str(&ctx) << " -->\n";
- for (auto &el : ctx.getBelGraphics(bel))
- svg_dump_el(el);
+ if (vm.count("force")) {
+ ctx.force = true;
}
- std::cout << "<!-- Frame -->\n";
- for (auto &el : ctx.getFrameGraphics())
- svg_dump_el(el);
- std::cout << "</svg>\n";
- }
- if (vm.count("tmfuzz")) {
- std::vector<WireId> src_wires, dst_wires;
+ if (vm.count("seed")) {
+ ctx.rngseed(vm["seed"].as<int>());
+ }
- /*for (auto w : ctx.getWires())
- src_wires.push_back(w);*/
- for (auto b : ctx.getBels()) {
- if (ctx.getBelType(b) == TYPE_ICESTORM_LC) {
- src_wires.push_back(ctx.getWireBelPin(b, PIN_O));
- }
- if (ctx.getBelType(b) == TYPE_SB_IO) {
- src_wires.push_back(ctx.getWireBelPin(b, PIN_D_IN_0));
+ if (vm.count("svg")) {
+ std::cout << "<svg xmlns=\"http://www.w3.org/2000/svg\" "
+ "xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n";
+ for (auto bel : ctx.getBels()) {
+ std::cout << "<!-- " << ctx.getBelName(bel).str(&ctx)
+ << " -->\n";
+ for (auto &el : ctx.getBelGraphics(bel))
+ svg_dump_el(el);
}
+ std::cout << "<!-- Frame -->\n";
+ for (auto &el : ctx.getFrameGraphics())
+ svg_dump_el(el);
+ std::cout << "</svg>\n";
}
- for (auto b : ctx.getBels()) {
- if (ctx.getBelType(b) == TYPE_ICESTORM_LC) {
- dst_wires.push_back(ctx.getWireBelPin(b, PIN_I0));
- dst_wires.push_back(ctx.getWireBelPin(b, PIN_I1));
- dst_wires.push_back(ctx.getWireBelPin(b, PIN_I2));
- dst_wires.push_back(ctx.getWireBelPin(b, PIN_I3));
- dst_wires.push_back(ctx.getWireBelPin(b, PIN_CEN));
- dst_wires.push_back(ctx.getWireBelPin(b, PIN_CIN));
+ if (vm.count("tmfuzz")) {
+ std::vector<WireId> src_wires, dst_wires;
+
+ /*for (auto w : ctx.getWires())
+ src_wires.push_back(w);*/
+ for (auto b : ctx.getBels()) {
+ if (ctx.getBelType(b) == TYPE_ICESTORM_LC) {
+ src_wires.push_back(ctx.getWireBelPin(b, PIN_O));
+ }
+ if (ctx.getBelType(b) == TYPE_SB_IO) {
+ src_wires.push_back(ctx.getWireBelPin(b, PIN_D_IN_0));
+ }
}
- if (ctx.getBelType(b) == TYPE_SB_IO) {
- dst_wires.push_back(ctx.getWireBelPin(b, PIN_D_OUT_0));
- dst_wires.push_back(ctx.getWireBelPin(b, PIN_OUTPUT_ENABLE));
+
+ for (auto b : ctx.getBels()) {
+ if (ctx.getBelType(b) == TYPE_ICESTORM_LC) {
+ dst_wires.push_back(ctx.getWireBelPin(b, PIN_I0));
+ dst_wires.push_back(ctx.getWireBelPin(b, PIN_I1));
+ dst_wires.push_back(ctx.getWireBelPin(b, PIN_I2));
+ dst_wires.push_back(ctx.getWireBelPin(b, PIN_I3));
+ dst_wires.push_back(ctx.getWireBelPin(b, PIN_CEN));
+ dst_wires.push_back(ctx.getWireBelPin(b, PIN_CIN));
+ }
+ if (ctx.getBelType(b) == TYPE_SB_IO) {
+ dst_wires.push_back(ctx.getWireBelPin(b, PIN_D_OUT_0));
+ dst_wires.push_back(
+ ctx.getWireBelPin(b, PIN_OUTPUT_ENABLE));
+ }
}
- }
- ctx.shuffle(src_wires);
- ctx.shuffle(dst_wires);
-
- for (int i = 0; i < int(src_wires.size()) && i < int(dst_wires.size());
- i++) {
- delay_t actual_delay;
- WireId src = src_wires[i], dst = dst_wires[i];
- if (!get_actual_route_delay(&ctx, src, dst, actual_delay))
- continue;
- printf("%s %s %.3f %.3f %d %d %d %d %d %d\n",
- ctx.getWireName(src).c_str(&ctx),
- ctx.getWireName(dst).c_str(&ctx),
- ctx.getDelayNS(actual_delay),
- ctx.getDelayNS(ctx.estimateDelay(src, dst)),
- ctx.chip_info->wire_data[src.index].x,
- ctx.chip_info->wire_data[src.index].y,
- ctx.chip_info->wire_data[src.index].type,
- ctx.chip_info->wire_data[dst.index].x,
- ctx.chip_info->wire_data[dst.index].y,
- ctx.chip_info->wire_data[dst.index].type);
+ ctx.shuffle(src_wires);
+ ctx.shuffle(dst_wires);
+
+ for (int i = 0;
+ i < int(src_wires.size()) && i < int(dst_wires.size()); i++) {
+ delay_t actual_delay;
+ WireId src = src_wires[i], dst = dst_wires[i];
+ if (!get_actual_route_delay(&ctx, src, dst, actual_delay))
+ continue;
+ printf("%s %s %.3f %.3f %d %d %d %d %d %d\n",
+ ctx.getWireName(src).c_str(&ctx),
+ ctx.getWireName(dst).c_str(&ctx),
+ ctx.getDelayNS(actual_delay),
+ ctx.getDelayNS(ctx.estimateDelay(src, dst)),
+ ctx.chip_info->wire_data[src.index].x,
+ ctx.chip_info->wire_data[src.index].y,
+ ctx.chip_info->wire_data[src.index].type,
+ ctx.chip_info->wire_data[dst.index].x,
+ ctx.chip_info->wire_data[dst.index].y,
+ ctx.chip_info->wire_data[dst.index].type);
+ }
}
- }
- if (vm.count("json")) {
- std::string filename = vm["json"].as<std::string>();
- std::istream *f = new std::ifstream(filename);
+ if (vm.count("json")) {
+ std::string filename = vm["json"].as<std::string>();
+ std::ifstream f(filename);
+ if (!parse_json_file(f, filename, &ctx))
+ log_error("Loading design failed.\n");
- parse_json_file(f, filename, &ctx);
+ if (vm.count("pcf")) {
+ std::ifstream pcf(vm["pcf"].as<std::string>());
+ if (!apply_pcf(&ctx, pcf))
+ log_error("Loading PCF failed.\n");
+ }
- if (vm.count("pcf")) {
- std::ifstream pcf(vm["pcf"].as<std::string>());
- apply_pcf(&ctx, pcf);
+ if (!pack_design(&ctx) && !ctx.force)
+ log_error("Packing design failed.\n");
+ double freq = 50e6;
+ if (vm.count("freq"))
+ freq = vm["freq"].as<double>() * 1e6;
+ assign_budget(&ctx, freq);
+ print_utilisation(&ctx);
+
+ if (!vm.count("pack-only")) {
+ if (!place_design_sa(&ctx) && !ctx.force)
+ log_error("Placing design failed.\n");
+ if (!route_design(&ctx) && !ctx.force)
+ log_error("Routing design failed.\n");
+ }
}
- if (!pack_design(&ctx) && !ctx.force)
- log_error("Packing design failed.\n");
- assign_budget(&ctx, 50e6);
- print_utilisation(&ctx);
-
- if (!vm.count("pack-only")) {
- if (!place_design_sa(&ctx) && !ctx.force)
- log_error("Placing design failed.\n");
- if (!route_design(&ctx) && !ctx.force)
- log_error("Routing design failed.\n");
+ if (vm.count("asc")) {
+ std::string filename = vm["asc"].as<std::string>();
+ std::ofstream f(filename);
+ write_asc(&ctx, f);
}
- }
- if (vm.count("asc")) {
- std::string filename = vm["asc"].as<std::string>();
- std::ofstream f(filename);
- write_asc(&ctx, f);
- }
-
- if (vm.count("run")) {
- std::vector<std::string> files =
- vm["run"].as<std::vector<std::string>>();
- for (auto filename : files)
- execute_python_file(filename.c_str());
- }
+ if (vm.count("run")) {
+ std::vector<std::string> files =
+ vm["run"].as<std::vector<std::string>>();
+ for (auto filename : files)
+ execute_python_file(filename.c_str());
+ }
- if (vm.count("gui")) {
- QApplication a(argc, argv);
- QSurfaceFormat fmt;
- fmt.setSamples(10);
- QSurfaceFormat::setDefaultFormat(fmt);
- MainWindow w(&ctx);
- w.show();
+ if (vm.count("gui")) {
+ QApplication a(argc, argv);
+ QSurfaceFormat fmt;
+ fmt.setSamples(10);
+ QSurfaceFormat::setDefaultFormat(fmt);
+ MainWindow w(&ctx);
+ w.show();
- rc = a.exec();
+ rc = a.exec();
+ }
+ deinit_python();
+ return rc;
+ } catch (log_execution_error_exception) {
+#if defined(_MSC_VER)
+ _exit(EXIT_FAILURE);
+#else
+ _Exit(EXIT_FAILURE);
+#endif
}
- deinit_python();
- return rc;
}
#endif
diff --git a/ice40/pack.cc b/ice40/pack.cc
index 19f1e7bc..35cef8b8 100644
--- a/ice40/pack.cc
+++ b/ice40/pack.cc
@@ -24,6 +24,7 @@
#include "cells.h"
#include "design_utils.h"
#include "log.h"
+#include "util.h"
NEXTPNR_NAMESPACE_BEGIN
@@ -34,10 +35,11 @@ static void pack_lut_lutffs(Context *ctx)
std::unordered_set<IdString> packed_cells;
std::vector<CellInfo *> new_cells;
- for (auto cell : ctx->cells) {
+ for (auto cell : sorted(ctx->cells)) {
CellInfo *ci = cell.second;
- log_info("cell '%s' is of type '%s'\n", ci->name.c_str(ctx),
- ci->type.c_str(ctx));
+ if (ctx->verbose)
+ log_info("cell '%s' is of type '%s'\n", ci->name.c_str(ctx),
+ ci->type.c_str(ctx));
if (is_lut(ctx, ci)) {
CellInfo *packed = create_ice_cell(ctx, "ICESTORM_LC",
ci->name.str(ctx) + "_LC");
@@ -45,8 +47,9 @@ static void pack_lut_lutffs(Context *ctx)
std::inserter(packed->attrs, packed->attrs.begin()));
packed_cells.insert(ci->name);
new_cells.push_back(packed);
- log_info("packed cell %s into %s\n", ci->name.c_str(ctx),
- packed->name.c_str(ctx));
+ if (ctx->verbose)
+ log_info("packed cell %s into %s\n", ci->name.c_str(ctx),
+ packed->name.c_str(ctx));
// See if we can pack into a DFF
// TODO: LUT cascade
NetInfo *o = ci->ports.at(ctx->id("O")).net;
@@ -54,7 +57,8 @@ static void pack_lut_lutffs(Context *ctx)
auto lut_bel = ci->attrs.find(ctx->id("BEL"));
bool packed_dff = false;
if (dff) {
- log_info("found attached dff %s\n", dff->name.c_str(ctx));
+ if (ctx->verbose)
+ log_info("found attached dff %s\n", dff->name.c_str(ctx));
auto dff_bel = dff->attrs.find(ctx->id("BEL"));
if (lut_bel != ci->attrs.end() && dff_bel != dff->attrs.end() &&
lut_bel->second != dff_bel->second) {
@@ -66,8 +70,9 @@ static void pack_lut_lutffs(Context *ctx)
if (dff_bel != dff->attrs.end())
packed->attrs[ctx->id("BEL")] = dff_bel->second;
packed_cells.insert(dff->name);
- log_info("packed cell %s into %s\n", dff->name.c_str(ctx),
- packed->name.c_str(ctx));
+ if (ctx->verbose)
+ log_info("packed cell %s into %s\n",
+ dff->name.c_str(ctx), packed->name.c_str(ctx));
packed_dff = true;
}
}
@@ -92,15 +97,16 @@ static void pack_nonlut_ffs(Context *ctx)
std::unordered_set<IdString> packed_cells;
std::vector<CellInfo *> new_cells;
- for (auto cell : ctx->cells) {
+ for (auto cell : sorted(ctx->cells)) {
CellInfo *ci = cell.second;
if (is_ff(ctx, ci)) {
CellInfo *packed = create_ice_cell(ctx, "ICESTORM_LC",
ci->name.str(ctx) + "_DFFLC");
std::copy(ci->attrs.begin(), ci->attrs.end(),
std::inserter(packed->attrs, packed->attrs.begin()));
- log_info("packed cell %s into %s\n", ci->name.c_str(ctx),
- packed->name.c_str(ctx));
+ if (ctx->verbose)
+ log_info("packed cell %s into %s\n", ci->name.c_str(ctx),
+ packed->name.c_str(ctx));
packed_cells.insert(ci->name);
new_cells.push_back(packed);
dff_to_lc(ctx, ci, packed, true);
@@ -121,7 +127,7 @@ static void pack_carries(Context *ctx)
std::unordered_set<IdString> packed_cells;
- for (auto cell : ctx->cells) {
+ for (auto cell : sorted(ctx->cells)) {
CellInfo *ci = cell.second;
if (is_carry(ctx, ci)) {
packed_cells.insert(cell.first);
@@ -196,7 +202,7 @@ static void pack_ram(Context *ctx)
std::unordered_set<IdString> packed_cells;
std::vector<CellInfo *> new_cells;
- for (auto cell : ctx->cells) {
+ for (auto cell : sorted(ctx->cells)) {
CellInfo *ci = cell.second;
if (is_ram(ctx, ci)) {
CellInfo *packed = create_ice_cell(ctx, "ICESTORM_RAM",
@@ -242,10 +248,11 @@ static void set_net_constant(const Context *ctx, NetInfo *orig,
for (auto user : orig->users) {
if (user.cell != nullptr) {
CellInfo *uc = user.cell;
- log_info("%s user %s\n", orig->name.c_str(ctx),
- uc->name.c_str(ctx));
- if (is_lut(ctx, uc) && (user.port.str(ctx).at(0) == 'I') &&
- !constval) {
+ if (ctx->verbose)
+ log_info("%s user %s\n", orig->name.c_str(ctx),
+ uc->name.c_str(ctx));
+ if ((is_lut(ctx, uc) || is_lc(ctx, uc)) &&
+ (user.port.str(ctx).at(0) == 'I') && !constval) {
uc->ports[user.port].net = nullptr;
} else {
uc->ports[user.port].net = constnet;
@@ -279,7 +286,7 @@ static void pack_constants(Context *ctx)
bool gnd_used = false, vcc_used = false;
- for (auto net : ctx->nets) {
+ for (auto net : sorted(ctx->nets)) {
NetInfo *ni = net.second;
if (ni->driver.cell != nullptr &&
ni->driver.cell->type == ctx->id("GND")) {
@@ -323,7 +330,7 @@ static void pack_io(Context *ctx)
log_info("Packing IOs..\n");
- for (auto cell : ctx->cells) {
+ for (auto cell : sorted(ctx->cells)) {
CellInfo *ci = cell.second;
if (is_nextpnr_iob(ctx, ci)) {
CellInfo *sb = nullptr;
@@ -406,8 +413,8 @@ static void promote_globals(Context *ctx)
{
log_info("Promoting globals..\n");
- std::unordered_map<IdString, int> clock_count, reset_count, cen_count;
- for (auto net : ctx->nets) {
+ std::map<IdString, int> clock_count, reset_count, cen_count;
+ for (auto net : sorted(ctx->nets)) {
NetInfo *ni = net.second;
if (ni->driver.cell != nullptr && !is_global_net(ctx, ni)) {
clock_count[net.first] = 0;
@@ -481,13 +488,19 @@ static void promote_globals(Context *ctx)
// Main pack function
bool pack_design(Context *ctx)
{
- pack_constants(ctx);
- promote_globals(ctx);
- pack_io(ctx);
- pack_lut_lutffs(ctx);
- pack_nonlut_ffs(ctx);
- pack_ram(ctx);
- return true;
+ try {
+ log_break();
+ pack_constants(ctx);
+ promote_globals(ctx);
+ pack_io(ctx);
+ pack_lut_lutffs(ctx);
+ pack_nonlut_ffs(ctx);
+ pack_ram(ctx);
+ log_info("Checksum: 0x%08x\n", ctx->checksum());
+ return true;
+ } catch (log_execution_error_exception) {
+ return false;
+ }
}
NEXTPNR_NAMESPACE_END
diff --git a/ice40/pcf.cc b/ice40/pcf.cc
index 756aba4a..87d27ff1 100644
--- a/ice40/pcf.cc
+++ b/ice40/pcf.cc
@@ -27,44 +27,51 @@ NEXTPNR_NAMESPACE_BEGIN
// Read a w
// Apply PCF constraints to a pre-packing design
-void apply_pcf(Context *ctx, std::istream &in)
+bool apply_pcf(Context *ctx, std::istream &in)
{
- if (!in)
- log_error("failed to open PCF file");
- std::string line;
- while (std::getline(in, line)) {
- size_t cstart = line.find("#");
- if (cstart != std::string::npos)
- line = line.substr(0, cstart);
- std::stringstream ss(line);
- std::vector<std::string> words;
- std::string tmp;
- while (ss >> tmp)
- words.push_back(tmp);
- if (words.size() == 0)
- continue;
- std::string cmd = words.at(0);
- if (cmd == "set_io") {
- size_t args_end = 1;
- while (args_end < words.size() && words.at(args_end).at(0) == '-')
- args_end++;
- std::string cell = words.at(args_end);
- std::string pin = words.at(args_end + 1);
- auto fnd_cell = ctx->cells.find(cell);
- if (fnd_cell == ctx->cells.end()) {
- log_warning("unmatched pcf constraint %s\n", cell.c_str());
+ try {
+ if (!in)
+ log_error("failed to open PCF file");
+ std::string line;
+ while (std::getline(in, line)) {
+ size_t cstart = line.find("#");
+ if (cstart != std::string::npos)
+ line = line.substr(0, cstart);
+ std::stringstream ss(line);
+ std::vector<std::string> words;
+ std::string tmp;
+ while (ss >> tmp)
+ words.push_back(tmp);
+ if (words.size() == 0)
+ continue;
+ std::string cmd = words.at(0);
+ if (cmd == "set_io") {
+ size_t args_end = 1;
+ while (args_end < words.size() &&
+ words.at(args_end).at(0) == '-')
+ args_end++;
+ std::string cell = words.at(args_end);
+ std::string pin = words.at(args_end + 1);
+ auto fnd_cell = ctx->cells.find(cell);
+ if (fnd_cell == ctx->cells.end()) {
+ log_warning("unmatched pcf constraint %s\n", cell.c_str());
+ } else {
+ BelId pin_bel = ctx->getPackagePinBel(pin);
+ if (pin_bel == BelId())
+ log_error("package does not have a pin named %s\n",
+ pin.c_str());
+ fnd_cell->second->attrs["BEL"] =
+ ctx->getBelName(pin_bel).str();
+ log_info("constrained '%s' to bel '%s'\n", cell.c_str(),
+ fnd_cell->second->attrs["BEL"].c_str());
+ }
} else {
- BelId pin_bel = ctx->getPackagePinBel(pin);
- if (pin_bel == BelId())
- log_error("package does not have a pin named %s\n",
- pin.c_str());
- fnd_cell->second->attrs["BEL"] = ctx->getBelName(pin_bel).str();
- log_info("constrained '%s' to bel '%s'\n", cell.c_str(),
- fnd_cell->second->attrs["BEL"].c_str());
+ log_error("unsupported pcf command '%s'\n", cmd.c_str());
}
- } else {
- log_error("unsupported pcf command '%s'\n", cmd.c_str());
}
+ return true;
+ } catch (log_execution_error_exception) {
+ return false;
}
}
diff --git a/ice40/pcf.h b/ice40/pcf.h
index e0816075..b86a7609 100644
--- a/ice40/pcf.h
+++ b/ice40/pcf.h
@@ -27,7 +27,7 @@
NEXTPNR_NAMESPACE_BEGIN
// Apply PCF constraints to a pre-packing design
-void apply_pcf(Context *ctx, std::istream &in);
+bool apply_pcf(Context *ctx, std::istream &in);
NEXTPNR_NAMESPACE_END
diff --git a/ice40/picorv32_arachne.sh b/ice40/picorv32_arachne.sh
index 00cfe6a4..b3960fdc 100755
--- a/ice40/picorv32_arachne.sh
+++ b/ice40/picorv32_arachne.sh
@@ -3,7 +3,7 @@ set -ex
rm -f picorv32.v
wget https://raw.githubusercontent.com/cliffordwolf/picorv32/master/picorv32.v
yosys -p 'synth_ice40 -nocarry -blif picorv32.blif -top top' picorv32.v picorv32_top.v
-arachne-pnr -d 8k --post-place-blif picorv32_place.blif picorv32.blif
+arachne-pnr -d 8k --post-place-blif picorv32_place.blif picorv32.blif -o picorv32_arachne_all.asc
yosys -p "read_blif -wideports picorv32_place.blif; read_verilog -lib +/ice40/cells_sim.v; write_json picorv32_place.json"
./transform_arachne_loc.py picorv32_place.json > picorv32_place_nx.json
-../nextpnr-ice40 --hx8k --asc picorv32.asc --json picorv32_place_nx.json
+../nextpnr-ice40 --hx8k --asc picorv32_ar_placed.asc --json picorv32_place_nx.json --force