diff options
author | Sergiusz Bazanski <q3k@q3k.org> | 2018-06-22 14:29:28 +0100 |
---|---|---|
committer | Sergiusz Bazanski <q3k@q3k.org> | 2018-06-22 14:29:28 +0100 |
commit | 858acc5c1c0ee4bbdfb8d2012b80cda656ca39db (patch) | |
tree | 7cc94b94e40c05c5a7baae61c9d0db4f23a31b60 /ice40 | |
parent | 98b1f0c041b01d07f64e8e04503f8eccb05a93de (diff) | |
parent | f86a0d6c8c8792c36c87cf345665ce7c9fbcc60f (diff) | |
download | nextpnr-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.h | 10 | ||||
-rw-r--r-- | ice40/bitstream.cc | 13 | ||||
-rw-r--r-- | ice40/main.cc | 471 | ||||
-rw-r--r-- | ice40/pack.cc | 69 | ||||
-rw-r--r-- | ice40/pcf.cc | 75 | ||||
-rw-r--r-- | ice40/pcf.h | 2 | ||||
-rwxr-xr-x | ice40/picorv32_arachne.sh | 4 |
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 |