From 6425032ec4def444f8538c6c92eab13660ab13e0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 11 Aug 2018 15:00:31 -0700 Subject: [PATCH] Rip out ice40 stuff, put xc7z020 in --- xc7/arch.cc | 126 +----- xc7/arch.h | 11 +- xc7/bitstream.cc | 999 ----------------------------------------------- xc7/bitstream.h | 34 -- xc7/delay.cc | 128 +----- xc7/family.cmake | 84 ---- xc7/main.cc | 125 ++---- xc7/project.cc | 19 +- 8 files changed, 59 insertions(+), 1467 deletions(-) delete mode 100644 xc7/bitstream.cc delete mode 100644 xc7/bitstream.h diff --git a/xc7/arch.cc b/xc7/arch.cc index 7e2dd7f7..9b739ba4 100644 --- a/xc7/arch.cc +++ b/xc7/arch.cc @@ -41,105 +41,42 @@ void IdString::initialize_arch(const BaseCtx *ctx) // ----------------------------------------------------------------------- -static const ChipInfoPOD *get_chip_info(const RelPtr *ptr) { return ptr->get(); } - -#if defined(_MSC_VER) -void load_chipdb(); -#endif - Arch::Arch(ArchArgs args) : args(args) { -#if defined(_MSC_VER) - load_chipdb(); -#endif - -#ifdef ICE40_HX1K_ONLY - if (args.type == ArchArgs::HX1K) { - fast_part = true; - chip_info = get_chip_info(reinterpret_cast *>(chipdb_blob_1k)); + if (args.type == ArchArgs::XC7Z020) { + //chip_info = get_chip_info(reinterpret_cast *>(chipdb_blob_1k)); } else { - log_error("Unsupported iCE40 chip type.\n"); + log_error("Unsupported XC7 chip type.\n"); } -#else - if (args.type == ArchArgs::LP384) { - fast_part = false; - chip_info = get_chip_info(reinterpret_cast *>(chipdb_blob_384)); - } else if (args.type == ArchArgs::LP1K || args.type == ArchArgs::HX1K) { - fast_part = args.type == ArchArgs::HX1K; - chip_info = get_chip_info(reinterpret_cast *>(chipdb_blob_1k)); - } else if (args.type == ArchArgs::UP5K) { - fast_part = false; - chip_info = get_chip_info(reinterpret_cast *>(chipdb_blob_5k)); - } else if (args.type == ArchArgs::LP8K || args.type == ArchArgs::HX8K) { - fast_part = args.type == ArchArgs::HX8K; - chip_info = get_chip_info(reinterpret_cast *>(chipdb_blob_8k)); - } else { - log_error("Unsupported iCE40 chip type.\n"); - } -#endif - package_info = nullptr; - for (int i = 0; i < chip_info->num_packages; i++) { - if (chip_info->packages_data[i].name.get() == args.package) { - package_info = &(chip_info->packages_data[i]); - break; - } - } - if (package_info == nullptr) - log_error("Unsupported package '%s'.\n", args.package.c_str()); - - bel_carry.resize(chip_info->num_bels); - bel_to_cell.resize(chip_info->num_bels); - wire_to_net.resize(chip_info->num_wires); - pip_to_net.resize(chip_info->num_pips); - switches_locked.resize(chip_info->num_switches); +// package_info = nullptr; +// for (int i = 0; i < chip_info->num_packages; i++) { +// if (chip_info->packages_data[i].name.get() == args.package) { +// package_info = &(chip_info->packages_data[i]); +// break; +// } +// } +// if (package_info == nullptr) +// log_error("Unsupported package '%s'.\n", args.package.c_str()); } // ----------------------------------------------------------------------- std::string Arch::getChipName() const { -#ifdef ICE40_HX1K_ONLY - if (args.type == ArchArgs::HX1K) { - return "Lattice LP1K"; + if (args.type == ArchArgs::XC7Z020) { + return "XC7Z020"; } else { - log_error("Unsupported iCE40 chip type.\n"); + log_error("Unsupported XC7 chip type.\n"); } -#else - if (args.type == ArchArgs::LP384) { - return "Lattice LP384"; - } else if (args.type == ArchArgs::LP1K) { - return "Lattice LP1K"; - } else if (args.type == ArchArgs::HX1K) { - return "Lattice HX1K"; - } else if (args.type == ArchArgs::UP5K) { - return "Lattice UP5K"; - } else if (args.type == ArchArgs::LP8K) { - return "Lattice LP8K"; - } else if (args.type == ArchArgs::HX8K) { - return "Lattice HX8K"; - } else { - log_error("Unknown chip\n"); - } -#endif } // ----------------------------------------------------------------------- IdString Arch::archArgsToId(ArchArgs args) const { - if (args.type == ArchArgs::LP384) - return id("lp384"); - if (args.type == ArchArgs::LP1K) - return id("lp1k"); - if (args.type == ArchArgs::HX1K) - return id("hx1k"); - if (args.type == ArchArgs::UP5K) - return id("up5k"); - if (args.type == ArchArgs::LP8K) - return id("lp8k"); - if (args.type == ArchArgs::HX8K) - return id("hx8k"); + if (args.type == ArchArgs::XC7Z020) + return id("xc7z020"); return IdString(); } @@ -531,35 +468,6 @@ std::vector Arch::getGroupGroups(GroupId group) const bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const { - const auto &driver = net_info->driver; - if (driver.port == id_COUT && sink.port == id_CIN) { - auto driver_loc = getBelLocation(driver.cell->bel); - auto sink_loc = getBelLocation(sink.cell->bel); - if (driver_loc.y == sink_loc.y) - budget = 0; - else - switch (args.type) { -#ifndef ICE40_HX1K_ONLY - case ArchArgs::HX8K: -#endif - case ArchArgs::HX1K: - budget = 190; - break; -#ifndef ICE40_HX1K_ONLY - case ArchArgs::LP384: - case ArchArgs::LP1K: - case ArchArgs::LP8K: - budget = 290; - break; - case ArchArgs::UP5K: - budget = 560; - break; -#endif - default: - log_error("Unsupported iCE40 chip type.\n"); - } - return true; - } return false; } diff --git a/xc7/arch.h b/xc7/arch.h index 8fd1af23..d92ff0c1 100644 --- a/xc7/arch.h +++ b/xc7/arch.h @@ -378,12 +378,7 @@ struct ArchArgs enum ArchArgsTypes { NONE, - LP384, - LP1K, - LP8K, - HX1K, - HX8K, - UP5K + XC7Z020 } type = NONE; std::string package; }; @@ -410,7 +405,7 @@ struct Arch : BaseCtx std::string getChipName() const; - IdString archId() const { return id("ice40"); } + IdString archId() const { return id("xc7"); } ArchArgs archArgs() const { return args; } IdString archArgsToId(ArchArgs args) const; @@ -836,6 +831,6 @@ struct Arch : BaseCtx float placer_constraintWeight = 10; }; -void ice40DelayFuzzerMain(Context *ctx); +//void ice40DelayFuzzerMain(Context *ctx); NEXTPNR_NAMESPACE_END diff --git a/xc7/bitstream.cc b/xc7/bitstream.cc deleted file mode 100644 index ee276e49..00000000 --- a/xc7/bitstream.cc +++ /dev/null @@ -1,999 +0,0 @@ -/* - * nextpnr -- Next Generation Place and Route - * - * Copyright (C) 2018 Clifford Wolf - * Copyright (C) 2018 David Shah - * Copyright (C) 2018 Serge Bazanski - * - * 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. - * - */ -#include "bitstream.h" -#include -#include -#include "cells.h" -#include "log.h" - -NEXTPNR_NAMESPACE_BEGIN - -inline TileType tile_at(const Context *ctx, int x, int y) -{ - return ctx->chip_info->tile_grid[y * ctx->chip_info->width + x]; -} - -const ConfigEntryPOD &find_config(const TileInfoPOD &tile, const std::string &name) -{ - for (int i = 0; i < tile.num_config_entries; i++) { - if (std::string(tile.entries[i].name.get()) == name) { - return tile.entries[i]; - } - } - NPNR_ASSERT_FALSE_STR("unable to find config bit " + name); -} - -std::tuple get_ieren(const BitstreamInfoPOD &bi, int8_t x, int8_t y, int8_t z) -{ - for (int i = 0; i < bi.num_ierens; i++) { - auto ie = bi.ierens[i]; - if (ie.iox == x && ie.ioy == y && ie.ioz == z) { - return std::make_tuple(ie.ierx, ie.iery, ie.ierz); - } - } - // No pin at this location - return std::make_tuple(-1, -1, -1); -}; - -bool get_config(const TileInfoPOD &ti, std::vector> &tile_cfg, const std::string &name, - int index = -1) -{ - const ConfigEntryPOD &cfg = find_config(ti, name); - if (index == -1) { - for (int i = 0; i < cfg.num_bits; i++) { - return tile_cfg.at(cfg.bits[i].row).at(cfg.bits[i].col); - } - } else { - return tile_cfg.at(cfg.bits[index].row).at(cfg.bits[index].col); - } - return false; -} - -void set_config(const TileInfoPOD &ti, std::vector> &tile_cfg, const std::string &name, bool value, - int index = -1) -{ - const ConfigEntryPOD &cfg = find_config(ti, name); - if (index == -1) { - for (int i = 0; i < cfg.num_bits; i++) { - int8_t &cbit = tile_cfg.at(cfg.bits[i].row).at(cfg.bits[i].col); - if (cbit && !value) - log_error("clearing already set config bit %s\n", name.c_str()); - cbit = value; - } - } else { - int8_t &cbit = tile_cfg.at(cfg.bits[index].row).at(cfg.bits[index].col); - cbit = value; - if (cbit && !value) - log_error("clearing already set config bit %s[%d]\n", name.c_str(), index); - } -} - -// Set an IE_{EN,REN} logical bit in a tile config. Logical means enabled. -// On {HX,LP}1K devices these bits are active low, so we need to invert them. -void set_ie_bit_logical(const Context *ctx, const TileInfoPOD &ti, std::vector> &tile_cfg, - const std::string &name, bool value) -{ - if (ctx->args.type == ArchArgs::LP1K || ctx->args.type == ArchArgs::HX1K) { - set_config(ti, tile_cfg, name, !value); - } else { - set_config(ti, tile_cfg, name, value); - } -} - -int get_param_or_def(const CellInfo *cell, const IdString param, int defval = 0) -{ - auto found = cell->params.find(param); - if (found != cell->params.end()) - return std::stoi(found->second); - else - return defval; -} - -std::string get_param_str_or_def(const CellInfo *cell, const IdString param, std::string defval = "") -{ - auto found = cell->params.find(param); - if (found != cell->params.end()) - return found->second; - else - return defval; -} - -char get_hexdigit(int i) { return std::string("0123456789ABCDEF").at(i); } - -static const BelConfigPOD &get_ec_config(const ChipInfoPOD *chip, BelId bel) -{ - for (int i = 0; i < chip->num_belcfgs; i++) { - if (chip->bel_config[i].bel_index == bel.index) - return chip->bel_config[i]; - } - NPNR_ASSERT_FALSE("failed to find bel config"); -} - -typedef std::vector>>> chipconfig_t; - -static void set_ec_cbit(chipconfig_t &config, const Context *ctx, const BelConfigPOD &cell_cbits, std::string name, - bool value, std::string prefix) -{ - const ChipInfoPOD *chip = ctx->chip_info; - - for (int i = 0; i < cell_cbits.num_entries; i++) { - const auto &cbit = cell_cbits.entries[i]; - if (cbit.entry_name.get() == name) { - const auto &ti = chip->bits_info->tiles_nonrouting[tile_at(ctx, cbit.x, cbit.y)]; - set_config(ti, config.at(cbit.y).at(cbit.x), prefix + cbit.cbit_name.get(), value); - return; - } - } - NPNR_ASSERT_FALSE_STR("failed to config extra cell config bit " + name); -} - -void configure_extra_cell(chipconfig_t &config, const Context *ctx, CellInfo *cell, - const std::vector> ¶ms, bool string_style, std::string prefix) -{ - const ChipInfoPOD *chip = ctx->chip_info; - const auto &bc = get_ec_config(chip, cell->bel); - for (auto p : params) { - std::vector value; - if (string_style) { - // Lattice's weird string style params, not sure if - // prefixes other than 0b should be supported, only 0b features in docs - std::string raw = get_param_str_or_def(cell, ctx->id(p.first), "0b0"); - assert(raw.substr(0, 2) == "0b"); - raw = raw.substr(2); - value.resize(raw.length()); - for (int i = 0; i < (int)raw.length(); i++) { - if (raw[i] == '1') { - value[(raw.length() - 1) - i] = 1; - } else { - assert(raw[i] == '0'); - value[(raw.length() - 1) - i] = 0; - } - } - } else { - int ival = get_param_or_def(cell, ctx->id(p.first), 0); - - for (int i = 0; i < p.second; i++) - value.push_back((ival >> i) & 0x1); - } - - value.resize(p.second); - if (p.second == 1) { - set_ec_cbit(config, ctx, bc, p.first, value.at(0), prefix); - } else { - for (int i = 0; i < p.second; i++) { - set_ec_cbit(config, ctx, bc, p.first + "_" + std::to_string(i), value.at(i), prefix); - } - } - } -} - -std::string tagTileType(TileType &tile) -{ - if (tile == TILE_NONE) - return ""; - switch (tile) { - case TILE_LOGIC: - return ".logic_tile"; - break; - case TILE_IO: - return ".io_tile"; - break; - case TILE_RAMB: - return ".ramb_tile"; - break; - case TILE_RAMT: - return ".ramt_tile"; - break; - case TILE_DSP0: - return ".dsp0_tile"; - break; - case TILE_DSP1: - return ".dsp1_tile"; - break; - case TILE_DSP2: - return ".dsp2_tile"; - break; - case TILE_DSP3: - return ".dsp3_tile"; - break; - case TILE_IPCON: - return ".ipcon_tile"; - break; - default: - NPNR_ASSERT(false); - } -} - -static BelPin get_one_bel_pin(const Context *ctx, WireId wire) -{ - auto pins = ctx->getWireBelPins(wire); - NPNR_ASSERT(pins.begin() != pins.end()); - return *pins.begin(); -} - -// Permute LUT init value given map (LUT input -> ext input) -unsigned permute_lut(unsigned orig_init, const std::unordered_map &input_permute) -{ - unsigned new_init = 0; - - for (int i = 0; i < 16; i++) { - int permute_address = 0; - for (int j = 0; j < 4; j++) { - if ((i >> j) & 0x1) - permute_address |= (1 << input_permute.at(j)); - } - if ((orig_init >> i) & 0x1) { - new_init |= (1 << permute_address); - } - } - - return new_init; -} - -void write_asc(const Context *ctx, std::ostream &out) -{ - - static const std::vector lut_perm = { - 4, 14, 15, 5, 6, 16, 17, 7, 3, 13, 12, 2, 1, 11, 10, 0, - }; - - // [y][x][row][col] - const ChipInfoPOD &ci = *ctx->chip_info; - const BitstreamInfoPOD &bi = *ci.bits_info; - chipconfig_t config; - config.resize(ci.height); - for (int y = 0; y < ci.height; y++) { - config.at(y).resize(ci.width); - for (int x = 0; x < ci.width; x++) { - TileType tile = tile_at(ctx, x, y); - int rows = bi.tiles_nonrouting[tile].rows; - int cols = bi.tiles_nonrouting[tile].cols; - config.at(y).at(x).resize(rows, std::vector(cols)); - } - } - out << ".comment from next-pnr" << std::endl; - - switch (ctx->args.type) { - case ArchArgs::LP384: - out << ".device 384" << std::endl; - break; - case ArchArgs::HX1K: - case ArchArgs::LP1K: - out << ".device 1k" << std::endl; - break; - case ArchArgs::HX8K: - case ArchArgs::LP8K: - out << ".device 8k" << std::endl; - break; - case ArchArgs::UP5K: - out << ".device 5k" << std::endl; - break; - default: - NPNR_ASSERT_FALSE("unsupported device type\n"); - } - // Set pips - for (auto pip : ctx->getPips()) { - if (ctx->pip_to_net[pip.index] != nullptr) { - const PipInfoPOD &pi = ci.pip_data[pip.index]; - const SwitchInfoPOD &swi = bi.switches[pi.switch_index]; - int sw_bel_idx = swi.bel; - if (sw_bel_idx >= 0) { - const BelInfoPOD &beli = ci.bel_data[sw_bel_idx]; - const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_LOGIC]; - BelId sw_bel; - sw_bel.index = sw_bel_idx; - NPNR_ASSERT(ctx->getBelType(sw_bel) == id_ICESTORM_LC); - - if (ci.wire_data[ctx->getPipDstWire(pip).index].type == WireInfoPOD::WIRE_TYPE_LUTFF_IN_LUT) - continue; // Permutation pips - BelPin output = get_one_bel_pin(ctx, ctx->getPipDstWire(pip)); - NPNR_ASSERT(output.bel == sw_bel && output.pin == id_O); - unsigned lut_init; - - WireId permWire; - for (auto permPip : ctx->getPipsUphill(ctx->getPipSrcWire(pip))) { - if (ctx->getBoundPipNet(permPip) != nullptr) { - permWire = ctx->getPipSrcWire(permPip); - } - } - NPNR_ASSERT(permWire != WireId()); - std::string dName = ci.wire_data[permWire.index].name.get(); - - switch (dName.back()) { - case '0': - lut_init = 2; - break; - case '1': - lut_init = 4; - break; - case '2': - lut_init = 16; - break; - case '3': - lut_init = 256; - break; - default: - NPNR_ASSERT_FALSE("bad feedthru LUT input"); - } - std::vector lc(20, false); - for (int i = 0; i < 16; i++) { - if ((lut_init >> i) & 0x1) - lc.at(lut_perm.at(i)) = true; - } - - for (int i = 0; i < 20; i++) - set_config(ti, config.at(beli.y).at(beli.x), "LC_" + std::to_string(beli.z), lc.at(i), i); - } else { - for (int i = 0; i < swi.num_bits; i++) { - bool val = (pi.switch_mask & (1 << ((swi.num_bits - 1) - i))) != 0; - int8_t &cbit = config.at(swi.y).at(swi.x).at(swi.cbits[i].row).at(swi.cbits[i].col); - if (bool(cbit) != 0) - NPNR_ASSERT(false); - cbit = val; - } - } - } - } - - std::unordered_set sb_io_used_by_pll; - std::unordered_set sb_io_used_by_io; - - // Set logic cell config - for (auto &cell : ctx->cells) { - - BelId bel = cell.second.get()->bel; - if (bel == BelId()) { - std::cout << "Found unplaced cell " << cell.first.str(ctx) << " while generating bitstream!" << std::endl; - continue; - } - if (cell.second->type == ctx->id("ICESTORM_LC")) { - const BelInfoPOD &beli = ci.bel_data[bel.index]; - int x = beli.x, y = beli.y, z = beli.z; - const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_LOGIC]; - unsigned lut_init = get_param_or_def(cell.second.get(), ctx->id("LUT_INIT")); - bool neg_clk = get_param_or_def(cell.second.get(), ctx->id("NEG_CLK")); - bool dff_enable = get_param_or_def(cell.second.get(), ctx->id("DFF_ENABLE")); - bool async_sr = get_param_or_def(cell.second.get(), ctx->id("ASYNC_SR")); - bool set_noreset = get_param_or_def(cell.second.get(), ctx->id("SET_NORESET")); - bool carry_enable = get_param_or_def(cell.second.get(), ctx->id("CARRY_ENABLE")); - std::vector lc(20, false); - - // Discover permutation - std::unordered_map input_perm; - std::set unused; - for (int i = 0; i < 4; i++) - unused.insert(i); - for (int i = 0; i < 4; i++) { - WireId lut_wire = ctx->getBelPinWire(bel, IdString(ID_I0 + i)); - for (auto pip : ctx->getPipsUphill(lut_wire)) { - if (ctx->getBoundPipNet(pip) != nullptr) { - std::string name = ci.wire_data[ctx->getPipSrcWire(pip).index].name.get(); - switch (name.back()) { - case '0': - input_perm[i] = 0; - unused.erase(0); - break; - case '1': - input_perm[i] = 1; - unused.erase(1); - break; - case '2': - input_perm[i] = 2; - unused.erase(2); - break; - case '3': - input_perm[i] = 3; - unused.erase(3); - break; - default: - NPNR_ASSERT_FALSE("failed to determine LUT permutation"); - } - break; - } - } - } - for (int i = 0; i < 4; i++) { - if (!input_perm.count(i)) { - NPNR_ASSERT(!unused.empty()); - input_perm[i] = *(unused.begin()); - unused.erase(input_perm[i]); - } - } - lut_init = permute_lut(lut_init, input_perm); - for (int i = 0; i < 16; i++) { - if ((lut_init >> i) & 0x1) - lc.at(lut_perm.at(i)) = true; - } - lc.at(8) = carry_enable; - lc.at(9) = dff_enable; - lc.at(18) = set_noreset; - lc.at(19) = async_sr; - - for (int i = 0; i < 20; i++) - set_config(ti, config.at(y).at(x), "LC_" + std::to_string(z), lc.at(i), i); - if (dff_enable) - set_config(ti, config.at(y).at(x), "NegClk", neg_clk); - - bool carry_const = get_param_or_def(cell.second.get(), ctx->id("CIN_CONST")); - bool carry_set = get_param_or_def(cell.second.get(), ctx->id("CIN_SET")); - if (carry_const) { - if (!ctx->force) - NPNR_ASSERT(z == 0); - set_config(ti, config.at(y).at(x), "CarryInSet", carry_set); - } - } else if (cell.second->type == ctx->id("SB_IO")) { - const BelInfoPOD &beli = ci.bel_data[bel.index]; - int x = beli.x, y = beli.y, z = beli.z; - sb_io_used_by_io.insert(Loc(x, y, z)); - const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_IO]; - unsigned pin_type = get_param_or_def(cell.second.get(), ctx->id("PIN_TYPE")); - bool neg_trigger = get_param_or_def(cell.second.get(), ctx->id("NEG_TRIGGER")); - bool pullup = get_param_or_def(cell.second.get(), ctx->id("PULLUP")); - for (int i = 0; i < 6; i++) { - bool val = (pin_type >> i) & 0x01; - set_config(ti, config.at(y).at(x), "IOB_" + std::to_string(z) + ".PINTYPE_" + std::to_string(i), val); - } - set_config(ti, config.at(y).at(x), "NegClk", neg_trigger); - auto ieren = get_ieren(bi, x, y, z); - int iex, iey, iez; - std::tie(iex, iey, iez) = ieren; - NPNR_ASSERT(iez != -1); - - bool input_en = false; - if ((ctx->wire_to_net[ctx->getBelPinWire(bel, id_D_IN_0).index] != nullptr) || - (ctx->wire_to_net[ctx->getBelPinWire(bel, id_D_IN_1).index] != nullptr)) { - input_en = true; - } - - if (ctx->args.type == ArchArgs::LP1K || ctx->args.type == ArchArgs::HX1K) { - set_config(ti, config.at(iey).at(iex), "IoCtrl.IE_" + std::to_string(iez), !input_en); - set_config(ti, config.at(iey).at(iex), "IoCtrl.REN_" + std::to_string(iez), !pullup); - } else { - set_config(ti, config.at(iey).at(iex), "IoCtrl.IE_" + std::to_string(iez), input_en); - 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")) { - const BelInfoPOD &beli = ci.bel_data[bel.index]; - int x = beli.x, y = beli.y; - const TileInfoPOD &ti_ramt = bi.tiles_nonrouting[TILE_RAMT]; - const TileInfoPOD &ti_ramb = bi.tiles_nonrouting[TILE_RAMB]; - if (!(ctx->args.type == ArchArgs::LP1K || ctx->args.type == ArchArgs::HX1K)) { - set_config(ti_ramb, config.at(y).at(x), "RamConfig.PowerUp", true); - } - bool negclk_r = get_param_or_def(cell.second.get(), ctx->id("NEG_CLK_R")); - bool negclk_w = get_param_or_def(cell.second.get(), ctx->id("NEG_CLK_W")); - int write_mode = get_param_or_def(cell.second.get(), ctx->id("WRITE_MODE")); - int read_mode = get_param_or_def(cell.second.get(), ctx->id("READ_MODE")); - set_config(ti_ramb, config.at(y).at(x), "NegClk", negclk_w); - set_config(ti_ramt, config.at(y + 1).at(x), "NegClk", negclk_r); - - set_config(ti_ramt, config.at(y + 1).at(x), "RamConfig.CBIT_0", write_mode & 0x1); - set_config(ti_ramt, config.at(y + 1).at(x), "RamConfig.CBIT_1", write_mode & 0x2); - set_config(ti_ramt, config.at(y + 1).at(x), "RamConfig.CBIT_2", read_mode & 0x1); - set_config(ti_ramt, config.at(y + 1).at(x), "RamConfig.CBIT_3", read_mode & 0x2); - } else if (cell.second->type == ctx->id("SB_WARMBOOT") || cell.second->type == ctx->id("ICESTORM_LFOSC")) { - // No config needed - } else if (cell.second->type == ctx->id("ICESTORM_SPRAM")) { - const BelInfoPOD &beli = ci.bel_data[bel.index]; - int x = beli.x, y = beli.y, z = beli.z; - NPNR_ASSERT(ctx->args.type == ArchArgs::UP5K); - if (x == 0 && y == 0) { - const TileInfoPOD &ti_ipcon = bi.tiles_nonrouting[TILE_IPCON]; - if (z == 1) { - set_config(ti_ipcon, config.at(1).at(0), "IpConfig.CBIT_0", true); - } else if (z == 2) { - set_config(ti_ipcon, config.at(1).at(0), "IpConfig.CBIT_1", true); - } else { - NPNR_ASSERT(false); - } - } else if (x == 25 && y == 0) { - const TileInfoPOD &ti_ipcon = bi.tiles_nonrouting[TILE_IPCON]; - if (z == 3) { - set_config(ti_ipcon, config.at(1).at(25), "IpConfig.CBIT_0", true); - } else if (z == 4) { - set_config(ti_ipcon, config.at(1).at(25), "IpConfig.CBIT_1", true); - } else { - NPNR_ASSERT(false); - } - } - } else if (cell.second->type == ctx->id("ICESTORM_DSP")) { - const std::vector> mac16_params = {{"C_REG", 1}, - {"A_REG", 1}, - {"B_REG", 1}, - {"D_REG", 1}, - {"TOP_8x8_MULT_REG", 1}, - {"BOT_8x8_MULT_REG", 1}, - {"PIPELINE_16x16_MULT_REG1", 1}, - {"PIPELINE_16x16_MULT_REG2", 1}, - {"TOPOUTPUT_SELECT", 2}, - {"TOPADDSUB_LOWERINPUT", 2}, - {"TOPADDSUB_UPPERINPUT", 1}, - {"TOPADDSUB_CARRYSELECT", 2}, - {"BOTOUTPUT_SELECT", 2}, - {"BOTADDSUB_LOWERINPUT", 2}, - {"BOTADDSUB_UPPERINPUT", 1}, - {"BOTADDSUB_CARRYSELECT", 2}, - {"MODE_8x8", 1}, - {"A_SIGNED", 1}, - {"B_SIGNED", 1}}; - configure_extra_cell(config, ctx, cell.second.get(), mac16_params, false, std::string("IpConfig.")); - } else if (cell.second->type == ctx->id("ICESTORM_HFOSC")) { - const std::vector> hfosc_params = {{"CLKHF_DIV", 2}, {"TRIM_EN", 1}}; - configure_extra_cell(config, ctx, cell.second.get(), hfosc_params, true, std::string("IpConfig.")); - - } else if (cell.second->type == ctx->id("ICESTORM_PLL")) { - const std::vector> pll_params = {{"DELAY_ADJMODE_FB", 1}, - {"DELAY_ADJMODE_REL", 1}, - {"DIVF", 7}, - {"DIVQ", 3}, - {"DIVR", 4}, - {"FDA_FEEDBACK", 4}, - {"FDA_RELATIVE", 4}, - {"FEEDBACK_PATH", 3}, - {"FILTER_RANGE", 3}, - {"PLLOUT_SELECT_A", 2}, - {"PLLOUT_SELECT_B", 2}, - {"PLLTYPE", 3}, - {"SHIFTREG_DIV_MODE", 1}, - {"TEST_MODE", 1}}; - configure_extra_cell(config, ctx, cell.second.get(), pll_params, false, std::string("PLL.")); - - // Configure the SB_IOs that the clock outputs are going through. - for (auto &port : cell.second->ports) { - // If this port is not a PLLOUT port, ignore it. - if (port.second.name != ctx->id("PLLOUT_A") && port.second.name != ctx->id("PLLOUT_B")) - continue; - - // If the output is not driving any net, ignore it. - if (port.second.net == nullptr) - continue; - - // Get IO Bel that this PLL port goes through by finding sibling - // Bel driving the same wire via PIN_D_IN_0. - auto wire = ctx->getBelPinWire(cell.second->bel, port.second.name); - BelId io_bel; - for (auto pin : ctx->getWireBelPins(wire)) { - if (pin.pin == id_D_IN_0) { - io_bel = pin.bel; - break; - } - } - NPNR_ASSERT(io_bel.index != -1); - auto io_bel_loc = ctx->getBelLocation(io_bel); - - // Check that this SB_IO is either unused or just used as an output. - if (sb_io_used_by_io.count(io_bel_loc)) { - log_error("SB_IO '%s' already in use, cannot route PLL through\n", ctx->getBelName(bel).c_str(ctx)); - } - sb_io_used_by_pll.insert(io_bel_loc); - - // Get IE/REN config location (cf. http://www.clifford.at/icestorm/io_tile.html) - auto ieren = get_ieren(bi, io_bel_loc.x, io_bel_loc.y, io_bel_loc.z); - int iex, iey, iez; - std::tie(iex, iey, iez) = ieren; - NPNR_ASSERT(iez != -1); - - // Write config. - const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_IO]; - // Enable input buffer and disable pull-up resistor in block - // (this is used by the PLL). - set_ie_bit_logical(ctx, ti, config.at(iey).at(iex), "IoCtrl.IE_" + std::to_string(iez), true); - set_ie_bit_logical(ctx, ti, config.at(iey).at(iex), "IoCtrl.REN_" + std::to_string(iez), false); - // PINTYPE[0] passes the PLL through to the fabric. - set_config(ti, config.at(io_bel_loc.y).at(io_bel_loc.x), - "IOB_" + std::to_string(io_bel_loc.z) + ".PINTYPE_0", true); - } - - } else { - NPNR_ASSERT(false); - } - } - // Set config bits in unused IO and RAM - for (auto bel : ctx->getBels()) { - if (ctx->bel_to_cell[bel.index] == nullptr && ctx->getBelType(bel) == id_SB_IO) { - const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_IO]; - const BelInfoPOD &beli = ci.bel_data[bel.index]; - int x = beli.x, y = beli.y, z = beli.z; - if (sb_io_used_by_pll.count(Loc(x, y, z))) { - continue; - } - - auto ieren = get_ieren(bi, x, y, z); - int iex, iey, iez; - std::tie(iex, iey, iez) = ieren; - if (iez != -1) { - set_ie_bit_logical(ctx, ti, config.at(iey).at(iex), "IoCtrl.IE_" + std::to_string(iez), true); - set_ie_bit_logical(ctx, ti, config.at(iey).at(iex), "IoCtrl.REN_" + std::to_string(iez), false); - } - } else if (ctx->bel_to_cell[bel.index] == nullptr && ctx->getBelType(bel) == id_ICESTORM_RAM) { - const BelInfoPOD &beli = ci.bel_data[bel.index]; - int x = beli.x, y = beli.y; - const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_RAMB]; - if ((ctx->args.type == ArchArgs::LP1K || ctx->args.type == ArchArgs::HX1K)) { - set_config(ti, config.at(y).at(x), "RamConfig.PowerUp", true); - } - } - } - - // Set other config bits - for (int y = 0; y < ci.height; y++) { - for (int x = 0; x < ci.width; x++) { - TileType tile = tile_at(ctx, x, y); - const TileInfoPOD &ti = bi.tiles_nonrouting[tile]; - - // set all ColBufCtrl bits (FIXME) - bool setColBufCtrl = true; - if (ctx->args.type == ArchArgs::LP1K || ctx->args.type == ArchArgs::HX1K) { - if (tile == TILE_RAMB || tile == TILE_RAMT) { - setColBufCtrl = (y == 3 || y == 5 || y == 11 || y == 13); - } else { - setColBufCtrl = (y == 4 || y == 5 || y == 12 || y == 13); - } - } else if (ctx->args.type == ArchArgs::LP8K || ctx->args.type == ArchArgs::HX8K) { - setColBufCtrl = (y == 8 || y == 9 || y == 24 || y == 25); - } else if (ctx->args.type == ArchArgs::UP5K) { - setColBufCtrl = (y == 4 || y == 5 || y == 14 || y == 15 || y == 26 || y == 27); - } - if (setColBufCtrl) { - set_config(ti, config.at(y).at(x), "ColBufCtrl.glb_netwk_0", true); - set_config(ti, config.at(y).at(x), "ColBufCtrl.glb_netwk_1", true); - set_config(ti, config.at(y).at(x), "ColBufCtrl.glb_netwk_2", true); - set_config(ti, config.at(y).at(x), "ColBufCtrl.glb_netwk_3", true); - set_config(ti, config.at(y).at(x), "ColBufCtrl.glb_netwk_4", true); - set_config(ti, config.at(y).at(x), "ColBufCtrl.glb_netwk_5", true); - set_config(ti, config.at(y).at(x), "ColBufCtrl.glb_netwk_6", true); - set_config(ti, config.at(y).at(x), "ColBufCtrl.glb_netwk_7", true); - } - - // Weird UltraPlus bits - if (tile == TILE_DSP0 || tile == TILE_DSP1 || tile == TILE_DSP2 || tile == TILE_DSP3 || - tile == TILE_IPCON) { - if (ctx->args.type == ArchArgs::UP5K && x == 25 && y == 14) { - // Mystery bits not set in this one tile - } else { - for (int lc_idx = 0; lc_idx < 8; lc_idx++) { - static const std::vector ip_dsp_lut_perm = { - 4, 14, 15, 5, 6, 16, 17, 7, 3, 13, 12, 2, 1, 11, 10, 0, - }; - for (int i = 0; i < 16; i++) - set_config(ti, config.at(y).at(x), "LC_" + std::to_string(lc_idx), ((i % 8) >= 4), - ip_dsp_lut_perm.at(i)); - if (tile == TILE_IPCON) - set_config(ti, config.at(y).at(x), - "Cascade.IPCON_LC0" + std::to_string(lc_idx) + "_inmux02_5", true); - else - set_config(ti, config.at(y).at(x), - "Cascade.MULT" + std::to_string(int(tile - TILE_DSP0)) + "_LC0" + - std::to_string(lc_idx) + "_inmux02_5", - true); - } - } - } - } - } - - // Write config out - for (int y = 0; y < ci.height; y++) { - for (int x = 0; x < ci.width; x++) { - TileType tile = tile_at(ctx, x, y); - if (tile == TILE_NONE) - continue; - out << tagTileType(tile); - out << " " << x << " " << y << std::endl; - for (auto row : config.at(y).at(x)) { - for (auto col : row) { - if (col == 1) - out << "1"; - else - out << "0"; - } - out << std::endl; - } - out << std::endl; - } - } - - // Write RAM init data - for (auto &cell : ctx->cells) { - if (cell.second->bel != BelId()) { - if (cell.second->type == ctx->id("ICESTORM_RAM")) { - const BelInfoPOD &beli = ci.bel_data[cell.second->bel.index]; - int x = beli.x, y = beli.y; - out << ".ram_data " << x << " " << y << std::endl; - for (int w = 0; w < 16; w++) { - std::vector bits(256); - std::string init = - get_param_str_or_def(cell.second.get(), ctx->id(std::string("INIT_") + get_hexdigit(w))); - NPNR_ASSERT(init != ""); - for (size_t i = 0; i < init.size(); i++) { - bool val = (init.at((init.size() - 1) - i) == '1'); - bits.at(i) = val; - } - for (int i = bits.size() - 4; i >= 0; i -= 4) { - int c = bits.at(i) + (bits.at(i + 1) << 1) + (bits.at(i + 2) << 2) + (bits.at(i + 3) << 3); - out << char(std::tolower(get_hexdigit(c))); - } - out << std::endl; - } - out << std::endl; - } - } - } - - // Write symbols - // const bool write_symbols = 1; - for (auto wire : ctx->getWires()) { - NetInfo *net = ctx->getBoundWireNet(wire); - if (net != nullptr) - out << ".sym " << wire.index << " " << net->name.str(ctx) << std::endl; - } -} - -void read_config(Context *ctx, std::istream &in, chipconfig_t &config) -{ - constexpr size_t line_buf_size = 65536; - char buffer[line_buf_size]; - int tile_x = -1, tile_y = -1, line_nr = -1; - - while (1) { - in.getline(buffer, line_buf_size); - if (buffer[0] == '.') { - line_nr = -1; - const char *tok = strtok(buffer, " \t\r\n"); - - if (!strcmp(tok, ".device")) { - std::string config_device = strtok(nullptr, " \t\r\n"); - std::string expected; - switch (ctx->args.type) { - case ArchArgs::LP384: - expected = "384"; - break; - case ArchArgs::HX1K: - case ArchArgs::LP1K: - expected = "1k"; - break; - case ArchArgs::HX8K: - case ArchArgs::LP8K: - expected = "8k"; - break; - case ArchArgs::UP5K: - expected = "5k"; - break; - default: - log_error("unsupported device type\n"); - } - if (expected != config_device) - log_error("device type does not match\n"); - } else if (!strcmp(tok, ".io_tile") || !strcmp(tok, ".logic_tile") || !strcmp(tok, ".ramb_tile") || - !strcmp(tok, ".ramt_tile") || !strcmp(tok, ".ipcon_tile") || !strcmp(tok, ".dsp0_tile") || - !strcmp(tok, ".dsp1_tile") || !strcmp(tok, ".dsp2_tile") || !strcmp(tok, ".dsp3_tile")) { - line_nr = 0; - tile_x = atoi(strtok(nullptr, " \t\r\n")); - tile_y = atoi(strtok(nullptr, " \t\r\n")); - - TileType tile = tile_at(ctx, tile_x, tile_y); - if (tok != tagTileType(tile)) - log_error("Wrong tile type for specified position\n"); - - } else if (!strcmp(tok, ".extra_bit")) { - /* - int b = atoi(strtok(nullptr, " \t\r\n")); - int x = atoi(strtok(nullptr, " \t\r\n")); - int y = atoi(strtok(nullptr, " \t\r\n")); - std::tuple key(b, x, y); - extra_bits.insert(key); - */ - } else if (!strcmp(tok, ".sym")) { - int wireIndex = atoi(strtok(nullptr, " \t\r\n")); - const char *name = strtok(nullptr, " \t\r\n"); - - IdString netName = ctx->id(name); - - if (ctx->nets.find(netName) == ctx->nets.end()) { - std::unique_ptr created_net = std::unique_ptr(new NetInfo); - created_net->name = netName; - ctx->nets[netName] = std::move(created_net); - } - - WireId wire; - wire.index = wireIndex; - ctx->bindWire(wire, ctx->nets.at(netName).get(), STRENGTH_WEAK); - } - } else if (line_nr >= 0 && strlen(buffer) > 0) { - if (line_nr > int(config.at(tile_y).at(tile_x).size() - 1)) - log_error("Invalid data in input asc file"); - for (int i = 0; buffer[i] == '0' || buffer[i] == '1'; i++) - config.at(tile_y).at(tile_x).at(line_nr).at(i) = (buffer[i] == '1') ? 1 : 0; - line_nr++; - } - if (in.eof()) - break; - } -} - -bool read_asc(Context *ctx, std::istream &in) -{ - try { - // [y][x][row][col] - const ChipInfoPOD &ci = *ctx->chip_info; - const BitstreamInfoPOD &bi = *ci.bits_info; - chipconfig_t config; - config.resize(ci.height); - for (int y = 0; y < ci.height; y++) { - config.at(y).resize(ci.width); - for (int x = 0; x < ci.width; x++) { - TileType tile = tile_at(ctx, x, y); - int rows = bi.tiles_nonrouting[tile].rows; - int cols = bi.tiles_nonrouting[tile].cols; - config.at(y).at(x).resize(rows, std::vector(cols)); - } - } - read_config(ctx, in, config); - - // Set pips - for (auto pip : ctx->getPips()) { - const PipInfoPOD &pi = ci.pip_data[pip.index]; - const SwitchInfoPOD &swi = bi.switches[pi.switch_index]; - bool isUsed = true; - for (int i = 0; i < swi.num_bits; i++) { - bool val = (pi.switch_mask & (1 << ((swi.num_bits - 1) - i))) != 0; - int8_t cbit = config.at(swi.y).at(swi.x).at(swi.cbits[i].row).at(swi.cbits[i].col); - isUsed &= !(bool(cbit) ^ val); - } - if (isUsed) { - NetInfo *net = ctx->wire_to_net[pi.dst]; - WireId wire; - wire.index = pi.dst; - ctx->unbindWire(wire); - ctx->bindPip(pip, net, STRENGTH_WEAK); - } - } - for (auto bel : ctx->getBels()) { - if (ctx->getBelType(bel) == id_ICESTORM_LC) { - const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_LOGIC]; - const BelInfoPOD &beli = ci.bel_data[bel.index]; - int x = beli.x, y = beli.y, z = beli.z; - std::vector lc(20, false); - bool isUsed = false; - for (int i = 0; i < 20; i++) { - lc.at(i) = get_config(ti, config.at(y).at(x), "LC_" + std::to_string(z), i); - isUsed |= lc.at(i); - } - bool neg_clk = get_config(ti, config.at(y).at(x), "NegClk"); - isUsed |= neg_clk; - bool carry_set = get_config(ti, config.at(y).at(x), "CarryInSet"); - isUsed |= carry_set; - - if (isUsed) { - std::unique_ptr created = create_ice_cell(ctx, ctx->id("ICESTORM_LC")); - IdString name = created->name; - ctx->cells[name] = std::move(created); - ctx->bindBel(bel, ctx->cells[name].get(), STRENGTH_WEAK); - // TODO: Add port mapping to nets and assign values of properties - } - } - if (ctx->getBelType(bel) == id_SB_IO) { - const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_IO]; - const BelInfoPOD &beli = ci.bel_data[bel.index]; - int x = beli.x, y = beli.y, z = beli.z; - bool isUsed = false; - for (int i = 0; i < 6; i++) { - isUsed |= get_config(ti, config.at(y).at(x), - "IOB_" + std::to_string(z) + ".PINTYPE_" + std::to_string(i)); - } - bool neg_trigger = get_config(ti, config.at(y).at(x), "NegClk"); - isUsed |= neg_trigger; - - if (isUsed) { - std::unique_ptr created = create_ice_cell(ctx, ctx->id("SB_IO")); - IdString name = created->name; - ctx->cells[name] = std::move(created); - ctx->bindBel(bel, ctx->cells[name].get(), STRENGTH_WEAK); - // TODO: Add port mapping to nets and assign values of properties - } - } - } - // Add cells that are without change in initial state of configuration - for (auto &net : ctx->nets) { - for (auto w : net.second->wires) { - if (w.second.pip == PipId()) { - WireId wire = w.first; - for (auto belpin : ctx->getWireBelPins(wire)) { - - if (ctx->checkBelAvail(belpin.bel)) { - if (ctx->getBelType(belpin.bel) == id_ICESTORM_LC) { - std::unique_ptr created = create_ice_cell(ctx, ctx->id("ICESTORM_LC")); - IdString name = created->name; - ctx->cells[name] = std::move(created); - ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK); - // TODO: Add port mapping to nets - } - if (ctx->getBelType(belpin.bel) == id_SB_IO) { - std::unique_ptr created = create_ice_cell(ctx, ctx->id("SB_IO")); - IdString name = created->name; - ctx->cells[name] = std::move(created); - ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK); - // TODO: Add port mapping to nets - } - if (ctx->getBelType(belpin.bel) == id_SB_GB) { - std::unique_ptr created = create_ice_cell(ctx, ctx->id("SB_GB")); - IdString name = created->name; - ctx->cells[name] = std::move(created); - ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK); - // TODO: Add port mapping to nets - } - if (ctx->getBelType(belpin.bel) == id_SB_WARMBOOT) { - std::unique_ptr created = create_ice_cell(ctx, ctx->id("SB_WARMBOOT")); - IdString name = created->name; - ctx->cells[name] = std::move(created); - ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK); - // TODO: Add port mapping to nets - } - if (ctx->getBelType(belpin.bel) == id_ICESTORM_LFOSC) { - std::unique_ptr created = create_ice_cell(ctx, ctx->id("ICESTORM_LFOSC")); - IdString name = created->name; - ctx->cells[name] = std::move(created); - ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK); - // TODO: Add port mapping to nets - } - } - } - } - } - } - for (auto &cell : ctx->cells) { - if (cell.second->bel != BelId()) { - for (auto &port : cell.second->ports) { - IdString pin = port.first; - WireId wire = ctx->getBelPinWire(cell.second->bel, pin); - if (wire != WireId()) { - NetInfo *net = ctx->getBoundWireNet(wire); - if (net != nullptr) { - port.second.net = net; - PortRef ref; - ref.cell = cell.second.get(); - ref.port = port.second.name; - - if (port.second.type == PORT_OUT) - net->driver = ref; - else - net->users.push_back(ref); - } - } - } - } - } - return true; - } catch (log_execution_error_exception) { - return false; - } -} -NEXTPNR_NAMESPACE_END diff --git a/xc7/bitstream.h b/xc7/bitstream.h deleted file mode 100644 index 41a2ae68..00000000 --- a/xc7/bitstream.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * nextpnr -- Next Generation Place and Route - * - * Copyright (C) 2018 Clifford Wolf - * Copyright (C) 2018 David Shah - * - * 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 ICE40_BITSTREAM_H -#define ICE40_BITSTREAM_H - -#include -#include "nextpnr.h" - -NEXTPNR_NAMESPACE_BEGIN - -void write_asc(const Context *ctx, std::ostream &out); -bool read_asc(Context *ctx, std::istream &in); - -NEXTPNR_NAMESPACE_END - -#endif diff --git a/xc7/delay.cc b/xc7/delay.cc index d76aaefb..98c3c655 100644 --- a/xc7/delay.cc +++ b/xc7/delay.cc @@ -98,92 +98,10 @@ void ice40DelayFuzzerMain(Context *ctx) } } -namespace { - -struct model_params_t -{ - int neighbourhood; - - int model0_offset; - int model0_norm1; - - int model1_offset; - int model1_norm1; - int model1_norm2; - int model1_norm3; - - int model2_offset; - int model2_linear; - int model2_sqrt; - - int delta_local; - int delta_lutffin; - int delta_sp4; - int delta_sp12; - - static const model_params_t &get(const ArchArgs& args) - { - static const model_params_t model_hx8k = {588, 129253, 8658, 118333, 23915, -73105, 57696, - -86797, 89, 3706, -316, -575, -158, -296}; - - static const model_params_t model_lp8k = {867, 206236, 11043, 191910, 31074, -95972, 75739, - -309793, 30, 11056, -474, -856, -363, -536}; - - static const model_params_t model_up5k = {1761, 305798, 16705, 296830, 24430, -40369, 33038, - -162662, 94, 4705, -1099, -1761, -418, -838}; - - if (args.type == ArchArgs::HX1K || args.type == ArchArgs::HX8K) - return model_hx8k; - - if (args.type == ArchArgs::LP384 || args.type == ArchArgs::LP1K || args.type == ArchArgs::LP8K) - return model_lp8k; - - if (args.type == ArchArgs::UP5K) - return model_up5k; - - NPNR_ASSERT(0); - } -}; - -} // namespace - delay_t Arch::estimateDelay(WireId src, WireId dst) const { - NPNR_ASSERT(src != WireId()); - int x1 = chip_info->wire_data[src.index].x; - int y1 = chip_info->wire_data[src.index].y; - int z1 = chip_info->wire_data[src.index].z; - int type = chip_info->wire_data[src.index].type; - - NPNR_ASSERT(dst != WireId()); - int x2 = chip_info->wire_data[dst.index].x; - int y2 = chip_info->wire_data[dst.index].y; - int z2 = chip_info->wire_data[dst.index].z; - - int dx = abs(x2 - x1); - int dy = abs(y2 - y1); - - const model_params_t &p = model_params_t::get(args); - delay_t v = p.neighbourhood; - - if (dx > 1 || dy > 1) - v = (p.model0_offset + p.model0_norm1 * (dx + dy)) / 128; - - if (dx == 0 && dy == 0) { - if (type == WireInfoPOD::WIRE_TYPE_LOCAL) - v += p.delta_local; - - if (type == WireInfoPOD::WIRE_TYPE_LUTFF_IN || type == WireInfoPOD::WIRE_TYPE_LUTFF_IN_LUT) - v += (z1 == z2) ? p.delta_lutffin : 0; - } - - if (type == WireInfoPOD::WIRE_TYPE_SP4_V || type == WireInfoPOD::WIRE_TYPE_SP4_H) - v += p.delta_sp4; - - if (type == WireInfoPOD::WIRE_TYPE_SP12_V || type == WireInfoPOD::WIRE_TYPE_SP12_H) - v += p.delta_sp12; - - return v; + //return 200 * (abs(src.location.x - dst.location.x) + abs(src.location.y - dst.location.y)); + return 0; } delay_t Arch::predictDelay(const NetInfo *net_info, const PortRef &sink) const @@ -192,47 +110,7 @@ delay_t Arch::predictDelay(const NetInfo *net_info, const PortRef &sink) const auto driver_loc = getBelLocation(driver.cell->bel); auto sink_loc = getBelLocation(sink.cell->bel); - if (driver.port == id_COUT) { - if (driver_loc.y == sink_loc.y) - return 0; - return 250; - } - - int dx = abs(sink_loc.x - driver_loc.x); - int dy = abs(sink_loc.y - driver_loc.y); - - const model_params_t &p = model_params_t::get(args); - - if (dx <= 1 && dy <= 1) - return p.neighbourhood; - -#if 1 - // Model #0 - return (p.model0_offset + p.model0_norm1 * (dx + dy)) / 128; -#else - float norm1 = dx + dy; - - float dx2 = dx * dx; - float dy2 = dy * dy; - float norm2 = sqrtf(dx2 + dy2); - - float dx3 = dx2 * dx; - float dy3 = dy2 * dy; - float norm3 = powf(dx3 + dy3, 1.0 / 3.0); - - // Model #1 - float v = p.model1_offset; - v += p.model1_norm1 * norm1; - v += p.model1_norm2 * norm2; - v += p.model1_norm3 * norm3; - v /= 128; - - // Model #2 - v = p.model2_offset + p.model2_linear * v + p.model2_sqrt * sqrtf(v); - v /= 128; - - return v; -#endif + return 200 * (abs(driver_loc.x - sink_loc.x) + abs(driver_loc.y - sink_loc.y)); } NEXTPNR_NAMESPACE_END diff --git a/xc7/family.cmake b/xc7/family.cmake index f558a14d..e69de29b 100644 --- a/xc7/family.cmake +++ b/xc7/family.cmake @@ -1,84 +0,0 @@ -if(ICE40_HX1K_ONLY) - set(devices 1k) - foreach (target ${family_targets}) - target_compile_definitions(${target} PRIVATE ICE40_HX1K_ONLY=1) - endforeach (target) -else() - set(devices 384 1k 5k 8k) -endif() - -set(DB_PY ${CMAKE_CURRENT_SOURCE_DIR}/ice40/chipdb.py) - -set(ICEBOX_ROOT "/usr/local/share/icebox" CACHE STRING "icebox location root") -file(MAKE_DIRECTORY ice40/chipdbs/) -add_library(ice40_chipdb OBJECT ice40/chipdbs/) -target_compile_definitions(ice40_chipdb PRIVATE NEXTPNR_NAMESPACE=nextpnr_${family}) -target_include_directories(ice40_chipdb PRIVATE ${family}/) - -if (MSVC) - target_sources(ice40_chipdb PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/ice40/resource/embed.cc) - set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/ice40/resources/chipdb.rc PROPERTIES LANGUAGE RC) - foreach (dev ${devices}) - if (dev EQUAL "5k") - set(OPT_FAST "") - set(OPT_SLOW --slow ${ICEBOX_ROOT}/timings_up5k.txt) - elseif(dev EQUAL "384") - set(OPT_FAST "") - set(OPT_SLOW --slow ${ICEBOX_ROOT}/timings_lp384.txt) - else() - set(OPT_FAST --fast ${ICEBOX_ROOT}/timings_hx${dev}.txt) - set(OPT_SLOW --slow ${ICEBOX_ROOT}/timings_lp${dev}.txt) - endif() - set(DEV_TXT_DB ${ICEBOX_ROOT}/chipdb-${dev}.txt) - set(DEV_CC_BBA_DB ${CMAKE_CURRENT_SOURCE_DIR}/ice40/chipdbs/chipdb-${dev}.bba) - set(DEV_CC_DB ${CMAKE_CURRENT_SOURCE_DIR}/ice40/chipdbs/chipdb-${dev}.bin) - set(DEV_CONSTIDS_INC ${CMAKE_CURRENT_SOURCE_DIR}/ice40/constids.inc) - set(DEV_GFXH ${CMAKE_CURRENT_SOURCE_DIR}/ice40/gfx.h) - add_custom_command(OUTPUT ${DEV_CC_BBA_DB} - COMMAND ${PYTHON_EXECUTABLE} ${DB_PY} -p ${DEV_CONSTIDS_INC} -g ${DEV_GFXH} ${OPT_FAST} ${OPT_SLOW} ${DEV_TXT_DB} > ${DEV_CC_BBA_DB} - DEPENDS ${DEV_TXT_DB} ${DB_PY} - ) - add_custom_command(OUTPUT ${DEV_CC_DB} - COMMAND bbasm ${DEV_CC_BBA_DB} ${DEV_CC_DB} - DEPENDS bbasm ${DEV_CC_BBA_DB} - ) - target_sources(ice40_chipdb PRIVATE ${DEV_CC_DB}) - set_source_files_properties(${DEV_CC_DB} PROPERTIES HEADER_FILE_ONLY TRUE) - foreach (target ${family_targets}) - target_sources(${target} PRIVATE $ ${CMAKE_CURRENT_SOURCE_DIR}/ice40/resource/chipdb.rc) - endforeach (target) - endforeach (dev) -else() - target_compile_options(ice40_chipdb PRIVATE -g0 -O0 -w) - foreach (dev ${devices}) - if (dev EQUAL "5k") - set(OPT_FAST "") - set(OPT_SLOW --slow ${ICEBOX_ROOT}/timings_up5k.txt) - elseif(dev EQUAL "384") - set(OPT_FAST "") - set(OPT_SLOW --slow ${ICEBOX_ROOT}/timings_lp384.txt) - else() - set(OPT_FAST --fast ${ICEBOX_ROOT}/timings_hx${dev}.txt) - set(OPT_SLOW --slow ${ICEBOX_ROOT}/timings_lp${dev}.txt) - endif() - set(DEV_TXT_DB ${ICEBOX_ROOT}/chipdb-${dev}.txt) - set(DEV_CC_BBA_DB ${CMAKE_CURRENT_SOURCE_DIR}/ice40/chipdbs/chipdb-${dev}.bba) - set(DEV_CC_DB ${CMAKE_CURRENT_SOURCE_DIR}/ice40/chipdbs/chipdb-${dev}.cc) - set(DEV_CONSTIDS_INC ${CMAKE_CURRENT_SOURCE_DIR}/ice40/constids.inc) - set(DEV_GFXH ${CMAKE_CURRENT_SOURCE_DIR}/ice40/gfx.h) - add_custom_command(OUTPUT ${DEV_CC_BBA_DB} - COMMAND ${PYTHON_EXECUTABLE} ${DB_PY} -p ${DEV_CONSTIDS_INC} -g ${DEV_GFXH} ${OPT_FAST} ${OPT_SLOW} ${DEV_TXT_DB} > ${DEV_CC_BBA_DB}.new - COMMAND mv ${DEV_CC_BBA_DB}.new ${DEV_CC_BBA_DB} - DEPENDS ${DEV_TXT_DB} ${DB_PY} - ) - add_custom_command(OUTPUT ${DEV_CC_DB} - COMMAND bbasm --c ${DEV_CC_BBA_DB} ${DEV_CC_DB}.new - COMMAND mv ${DEV_CC_DB}.new ${DEV_CC_DB} - DEPENDS bbasm ${DEV_CC_BBA_DB} - ) - target_sources(ice40_chipdb PRIVATE ${DEV_CC_DB}) - foreach (target ${family_targets}) - target_sources(${target} PRIVATE $) - endforeach (target) - endforeach (dev) -endif() diff --git a/xc7/main.cc b/xc7/main.cc index 8bab360d..440a26d0 100644 --- a/xc7/main.cc +++ b/xc7/main.cc @@ -21,7 +21,6 @@ #ifdef MAIN_EXECUTABLE #include -#include "bitstream.h" #include "command.h" #include "design_utils.h" #include "jsonparse.h" @@ -31,133 +30,77 @@ USING_NEXTPNR_NAMESPACE -class Ice40CommandHandler : public CommandHandler +class Xc7CommandHandler : public CommandHandler { public: - Ice40CommandHandler(int argc, char **argv); - virtual ~Ice40CommandHandler(){}; + Xc7CommandHandler(int argc, char **argv); + virtual ~Xc7CommandHandler(){}; std::unique_ptr createContext() override; void setupArchContext(Context *ctx) override; void validate() override; void customAfterLoad(Context *ctx) override; - void customBitstream(Context *ctx) override; protected: po::options_description getArchOptions(); }; -Ice40CommandHandler::Ice40CommandHandler(int argc, char **argv) : CommandHandler(argc, argv) {} +Xc7CommandHandler::Xc7CommandHandler(int argc, char **argv) : CommandHandler(argc, argv) {} -po::options_description Ice40CommandHandler::getArchOptions() +po::options_description Xc7CommandHandler::getArchOptions() { po::options_description specific("Architecture specific options"); -#ifdef ICE40_HX1K_ONLY - specific.add_options()("hx1k", "set device type to iCE40HX1K"); -#else - specific.add_options()("lp384", "set device type to iCE40LP384"); - specific.add_options()("lp1k", "set device type to iCE40LP1K"); - specific.add_options()("lp8k", "set device type to iCE40LP8K"); - specific.add_options()("hx1k", "set device type to iCE40HX1K"); - specific.add_options()("hx8k", "set device type to iCE40HX8K"); - specific.add_options()("up5k", "set device type to iCE40UP5K"); -#endif - specific.add_options()("package", po::value(), "set device package"); - specific.add_options()("pcf", po::value(), "PCF constraints file to ingest"); - specific.add_options()("asc", po::value(), "asc bitstream file to write"); - specific.add_options()("read", po::value(), "asc bitstream file to read"); - specific.add_options()("tmfuzz", "run path delay estimate fuzzer"); + specific.add_options()("xc7z020", "set device type to xc7z020"); +// specific.add_options()("package", po::value(), "set device package"); +// specific.add_options()("pcf", po::value(), "PCF constraints file to ingest"); + specific.add_options()("xdl", po::value(), "XDL file to write"); +// specific.add_options()("read", po::value(), "asc bitstream file to read"); +// specific.add_options()("tmfuzz", "run path delay estimate fuzzer"); return specific; } -void Ice40CommandHandler::validate() +void Xc7CommandHandler::validate() { conflicting_options(vm, "read", "json"); - if ((vm.count("lp384") + vm.count("lp1k") + vm.count("lp8k") + vm.count("hx1k") + vm.count("hx8k") + - vm.count("up5k")) > 1) - log_error("Only one device type can be set\n"); +// if ((vm.count("lp384") + vm.count("lp1k") + vm.count("lp8k") + vm.count("hx1k") + vm.count("hx8k") + +// vm.count("up5k")) > 1) +// log_error("Only one device type can be set\n"); } -void Ice40CommandHandler::customAfterLoad(Context *ctx) +void Xc7CommandHandler::customAfterLoad(Context *ctx) { - if (vm.count("pcf")) { - std::string filename = vm["pcf"].as(); - std::ifstream pcf(filename); - if (!apply_pcf(ctx, filename, pcf)) - log_error("Loading PCF failed.\n"); - } +// if (vm.count("pcf")) { +// std::string filename = vm["pcf"].as(); +// std::ifstream pcf(filename); +// if (!apply_pcf(ctx, filename, pcf)) +// log_error("Loading PCF failed.\n"); +// } } -void Ice40CommandHandler::customBitstream(Context *ctx) +void Xc7CommandHandler::setupArchContext(Context *ctx) { - if (vm.count("asc")) { - std::string filename = vm["asc"].as(); - std::ofstream f(filename); - write_asc(ctx, f); - } +// if (vm.count("tmfuzz")) +// ice40DelayFuzzerMain(ctx); } -void Ice40CommandHandler::setupArchContext(Context *ctx) +std::unique_ptr Xc7CommandHandler::createContext() { - if (vm.count("tmfuzz")) - ice40DelayFuzzerMain(ctx); - - if (vm.count("read")) { - std::string filename = vm["read"].as(); - std::ifstream f(filename); - if (!read_asc(ctx, f)) - log_error("Loading ASC failed.\n"); - } -} - -std::unique_ptr Ice40CommandHandler::createContext() -{ - if (vm.count("lp384")) { - chipArgs.type = ArchArgs::LP384; - chipArgs.package = "qn32"; - } - - if (vm.count("lp1k")) { - chipArgs.type = ArchArgs::LP1K; - chipArgs.package = "tq144"; - } - - if (vm.count("lp8k")) { - chipArgs.type = ArchArgs::LP8K; - chipArgs.package = "ct256"; - } - - if (vm.count("hx1k")) { - chipArgs.type = ArchArgs::HX1K; - chipArgs.package = "tq144"; - } - - if (vm.count("hx8k")) { - chipArgs.type = ArchArgs::HX8K; - chipArgs.package = "ct256"; - } - - if (vm.count("up5k")) { - chipArgs.type = ArchArgs::UP5K; - chipArgs.package = "sg48"; + if (vm.count("xc7z020")) { + chipArgs.type = ArchArgs::XC7Z020; + chipArgs.package = "clg484"; } if (chipArgs.type == ArchArgs::NONE) { - chipArgs.type = ArchArgs::HX1K; - chipArgs.package = "tq144"; + chipArgs.type = ArchArgs::XC7Z020; + chipArgs.package = "clg484"; } -#ifdef ICE40_HX1K_ONLY - if (chipArgs.type != ArchArgs::HX1K) { - log_error("This version of nextpnr-ice40 is built with HX1K-support only.\n"); - } -#endif - if (vm.count("package")) - chipArgs.package = vm["package"].as(); +// if (vm.count("package")) +// chipArgs.package = vm["package"].as(); return std::unique_ptr(new Context(chipArgs)); } int main(int argc, char *argv[]) { - Ice40CommandHandler handler(argc, argv); + Xc7CommandHandler handler(argc, argv); return handler.exec(); } diff --git a/xc7/project.cc b/xc7/project.cc index 8ca10e36..af0a775b 100644 --- a/xc7/project.cc +++ b/xc7/project.cc @@ -38,23 +38,8 @@ std::unique_ptr ProjectHandler::createContext(pt::ptree &root) { ArchArgs chipArgs; std::string arch_type = root.get("project.arch.type"); - if (arch_type == "lp384") { - chipArgs.type = ArchArgs::LP384; - } - if (arch_type == "lp1k") { - chipArgs.type = ArchArgs::LP1K; - } - if (arch_type == "lp8k") { - chipArgs.type = ArchArgs::LP8K; - } - if (arch_type == "hx1k") { - chipArgs.type = ArchArgs::HX1K; - } - if (arch_type == "hx8k") { - chipArgs.type = ArchArgs::HX8K; - } - if (arch_type == "up5k") { - chipArgs.type = ArchArgs::UP5K; + if (arch_type == "xc7z020") { + chipArgs.type = ArchArgs::XC7Z020; } chipArgs.package = root.get("project.arch.package");