diff --git a/xc7/arch.cc b/xc7/arch.cc index 31b02a9e..fd0eb6bd 100644 --- a/xc7/arch.cc +++ b/xc7/arch.cc @@ -70,6 +70,8 @@ Arch::Arch(ArchArgs args) : args(args) ddbSites = &ddb->getSites(); ddbTiles = &ddb->getTiles(); + + bel_to_cell.resize(ddbSites->getSiteCount()); } // ----------------------------------------------------------------------- @@ -171,32 +173,32 @@ WireId Arch::getBelPinWire(BelId bel, IdString pin) const { WireId ret; - NPNR_ASSERT(bel != BelId()); - - int num_bel_wires = chip_info->bel_data[bel.index].num_bel_wires; - const BelWirePOD *bel_wires = chip_info->bel_data[bel.index].bel_wires.get(); - - if (num_bel_wires < 7) { - for (int i = 0; i < num_bel_wires; i++) { - if (bel_wires[i].port == pin.index) { - ret.index = bel_wires[i].wire_index; - break; - } - } - } else { - int b = 0, e = num_bel_wires - 1; - while (b <= e) { - int i = (b + e) / 2; - if (bel_wires[i].port == pin.index) { - ret.index = bel_wires[i].wire_index; - break; - } - if (bel_wires[i].port > pin.index) - e = i - 1; - else - b = i + 1; - } - } +// NPNR_ASSERT(bel != BelId()); +// +// int num_bel_wires = chip_info->bel_data[bel.index].num_bel_wires; +// const BelWirePOD *bel_wires = chip_info->bel_data[bel.index].bel_wires.get(); +// +// if (num_bel_wires < 7) { +// for (int i = 0; i < num_bel_wires; i++) { +// if (bel_wires[i].port == pin.index) { +// ret.index = bel_wires[i].wire_index; +// break; +// } +// } +// } else { +// int b = 0, e = num_bel_wires - 1; +// while (b <= e) { +// int i = (b + e) / 2; +// if (bel_wires[i].port == pin.index) { +// ret.index = bel_wires[i].wire_index; +// break; +// } +// if (bel_wires[i].port > pin.index) +// e = i - 1; +// else +// b = i + 1; +// } +// } return ret; } diff --git a/xc7/arch.h b/xc7/arch.h index 810ff4d5..c16040f5 100644 --- a/xc7/arch.h +++ b/xc7/arch.h @@ -433,7 +433,7 @@ struct Arch : BaseCtx NPNR_ASSERT(bel_to_cell[bel.index] == nullptr); bel_to_cell[bel.index] = cell; - bel_carry[bel.index] = (cell->type == id_ICESTORM_LC && cell->lcInfo.carryEnable); + //bel_carry[bel.index] = (cell->type == id_ICESTORM_LC && cell->lcInfo.carryEnable); cell->bel = bel; cell->belStrength = strength; refreshUiBel(bel); @@ -446,7 +446,7 @@ struct Arch : BaseCtx bel_to_cell[bel.index]->bel = BelId(); bel_to_cell[bel.index]->belStrength = STRENGTH_NONE; bel_to_cell[bel.index] = nullptr; - bel_carry[bel.index] = false; + //bel_carry[bel.index] = false; refreshUiBel(bel); } @@ -490,14 +490,14 @@ struct Arch : BaseCtx BelId getBelByLocation(Loc loc) const; BelRange getBelsByTile(int x, int y) const; - bool getBelGlobalBuf(BelId bel) const { return chip_info->bel_data[bel.index].type == ID_SB_GB; } + bool getBelGlobalBuf(BelId bel) const { return getBelType(bel) == id_BUFGCTRL; } IdString getBelType(BelId bel) const { NPNR_ASSERT(bel != BelId()); const auto& site = ddbSites->getSite(bel.index); - const auto& tile_info = ddbTiles->getTileInfo(site.getTileIndex()); - return id(ddbTiles->getTileTypeName(tile_info.getTypeIndex())); + auto prim_def = site.getPrimitiveDefPtr(); + return id(prim_def->getName()); } WireId getBelPinWire(BelId bel, IdString pin) const; diff --git a/xc7/arch_place.cc b/xc7/arch_place.cc index ca98fa18..463e8312 100644 --- a/xc7/arch_place.cc +++ b/xc7/arch_place.cc @@ -29,45 +29,37 @@ NEXTPNR_NAMESPACE_BEGIN bool Arch::logicCellsCompatible(const CellInfo** it, const size_t size) const { - bool dffs_exist = false, dffs_neg = false; - const NetInfo *cen = nullptr, *clk = nullptr, *sr = nullptr; - int locals_count = 0; - - for (auto cell : boost::make_iterator_range(it, it+size)) { - NPNR_ASSERT(cell->belType == id_ICESTORM_LC); - if (cell->lcInfo.dffEnable) { - if (!dffs_exist) { - dffs_exist = true; - cen = cell->lcInfo.cen; - clk = cell->lcInfo.clk; - sr = cell->lcInfo.sr; - - if (cen != nullptr && !cen->is_global) - locals_count++; - if (clk != nullptr && !clk->is_global) - locals_count++; - if (sr != nullptr && !sr->is_global) - locals_count++; - - if (cell->lcInfo.negClk) { - dffs_neg = true; - } - } else { - if (cen != cell->lcInfo.cen) - return false; - if (clk != cell->lcInfo.clk) - return false; - if (sr != cell->lcInfo.sr) - return false; - if (dffs_neg != cell->lcInfo.negClk) - return false; - } - } - - locals_count += cell->lcInfo.inputCount; - } - - return locals_count <= 32; +// bool dffs_exist = false, dffs_neg = false; +// const NetInfo *cen = nullptr, *clk = nullptr, *sr = nullptr; +// +// for (auto cell : boost::make_iterator_range(it, it+size)) { +// NPNR_ASSERT(cell->belType == id_ICESTORM_LC); +// if (cell->lcInfo.dffEnable) { +// if (!dffs_exist) { +// dffs_exist = true; +// cen = cell->lcInfo.cen; +// clk = cell->lcInfo.clk; +// sr = cell->lcInfo.sr; +// +// if (cell->lcInfo.negClk) { +// dffs_neg = true; +// } +// } else { +// if (cen != cell->lcInfo.cen) +// return false; +// if (clk != cell->lcInfo.clk) +// return false; +// if (sr != cell->lcInfo.sr) +// return false; +// if (dffs_neg != cell->lcInfo.negClk) +// return false; +// } +// } +// locals_count += cell->lcInfo.inputCount; +// } +// +// return locals_count <= 32; + return true; } bool Arch::isBelLocationValid(BelId bel) const diff --git a/xc7/blinky.v b/xc7/blinky.v index daaac373..f636bfcb 100644 --- a/xc7/blinky.v +++ b/xc7/blinky.v @@ -7,8 +7,8 @@ module blinky ( output led5 ); - BUFG clk_gb ( - .I(clki), + BUFGCTRL clk_gb ( + .I0(clki), .O(clk) ); diff --git a/xc7/cells.cc b/xc7/cells.cc index 5bdc7990..07f33f0c 100644 --- a/xc7/cells.cc +++ b/xc7/cells.cc @@ -22,6 +22,7 @@ #include "cells.h" #include "design_utils.h" #include "log.h" +#include "util.h" NEXTPNR_NAMESPACE_BEGIN @@ -41,7 +42,8 @@ std::unique_ptr create_ice_cell(Context *ctx, IdString type, std::stri new_cell->name = ctx->id(name); } new_cell->type = type; - if (type == ctx->id("ICESTORM_LC")) { + if (type == ctx->id("XC7_LC")) { + new_cell->type = id_SLICEL; // HACK HACK HACK: Place one LC into each slice new_cell->params[ctx->id("LUT_INIT")] = "0"; new_cell->params[ctx->id("NEG_CLK")] = "0"; new_cell->params[ctx->id("CARRY_ENABLE")] = "0"; @@ -55,195 +57,201 @@ std::unique_ptr create_ice_cell(Context *ctx, IdString type, std::stri add_port(ctx, new_cell.get(), "I1", PORT_IN); add_port(ctx, new_cell.get(), "I2", PORT_IN); add_port(ctx, new_cell.get(), "I3", PORT_IN); + add_port(ctx, new_cell.get(), "I4", PORT_IN); + add_port(ctx, new_cell.get(), "I5", PORT_IN); add_port(ctx, new_cell.get(), "CIN", PORT_IN); add_port(ctx, new_cell.get(), "CLK", PORT_IN); - add_port(ctx, new_cell.get(), "CEN", PORT_IN); + add_port(ctx, new_cell.get(), "CE", PORT_IN); add_port(ctx, new_cell.get(), "SR", PORT_IN); - add_port(ctx, new_cell.get(), "LO", PORT_OUT); add_port(ctx, new_cell.get(), "O", PORT_OUT); + add_port(ctx, new_cell.get(), "OMUX", PORT_OUT); + add_port(ctx, new_cell.get(), "OQ", PORT_OUT); add_port(ctx, new_cell.get(), "COUT", PORT_OUT); - } else if (type == ctx->id("SB_IO")) { + } else if (type == ctx->id("IOBUF")) { + new_cell->type = id_IOB33S; new_cell->params[ctx->id("PIN_TYPE")] = "0"; new_cell->params[ctx->id("PULLUP")] = "0"; new_cell->params[ctx->id("NEG_TRIGGER")] = "0"; new_cell->params[ctx->id("IOSTANDARD")] = "SB_LVCMOS"; - add_port(ctx, new_cell.get(), "PACKAGE_PIN", PORT_INOUT); - - add_port(ctx, new_cell.get(), "LATCH_INPUT_VALUE", PORT_IN); - add_port(ctx, new_cell.get(), "CLOCK_ENABLE", PORT_IN); - add_port(ctx, new_cell.get(), "INPUT_CLK", PORT_IN); - add_port(ctx, new_cell.get(), "OUTPUT_CLK", PORT_IN); - - add_port(ctx, new_cell.get(), "OUTPUT_ENABLE", PORT_IN); - add_port(ctx, new_cell.get(), "D_OUT_0", PORT_IN); - add_port(ctx, new_cell.get(), "D_OUT_1", PORT_IN); - - add_port(ctx, new_cell.get(), "D_IN_0", PORT_OUT); - add_port(ctx, new_cell.get(), "D_IN_1", PORT_OUT); - } else if (type == ctx->id("ICESTORM_RAM")) { - new_cell->params[ctx->id("NEG_CLK_W")] = "0"; - new_cell->params[ctx->id("NEG_CLK_R")] = "0"; - new_cell->params[ctx->id("WRITE_MODE")] = "0"; - new_cell->params[ctx->id("READ_MODE")] = "0"; - - add_port(ctx, new_cell.get(), "RCLK", PORT_IN); - add_port(ctx, new_cell.get(), "RCLKE", PORT_IN); - add_port(ctx, new_cell.get(), "RE", PORT_IN); - - add_port(ctx, new_cell.get(), "WCLK", PORT_IN); - add_port(ctx, new_cell.get(), "WCLKE", PORT_IN); - add_port(ctx, new_cell.get(), "WE", PORT_IN); - - for (int i = 0; i < 16; i++) { - add_port(ctx, new_cell.get(), "WDATA_" + std::to_string(i), PORT_IN); - add_port(ctx, new_cell.get(), "MASK_" + std::to_string(i), PORT_IN); - add_port(ctx, new_cell.get(), "RDATA_" + std::to_string(i), PORT_OUT); - } - - for (int i = 0; i < 11; i++) { - add_port(ctx, new_cell.get(), "RADDR_" + std::to_string(i), PORT_IN); - add_port(ctx, new_cell.get(), "WADDR_" + std::to_string(i), PORT_IN); - } - } else if (type == ctx->id("ICESTORM_LFOSC")) { - add_port(ctx, new_cell.get(), "CLKLFEN", PORT_IN); - add_port(ctx, new_cell.get(), "CLKLFPU", PORT_IN); - add_port(ctx, new_cell.get(), "CLKLF", PORT_OUT); - add_port(ctx, new_cell.get(), "CLKLF_FABRIC", PORT_OUT); - } else if (type == ctx->id("ICESTORM_HFOSC")) { - new_cell->params[ctx->id("CLKHF_DIV")] = "0b00"; - new_cell->params[ctx->id("TRIM_EN")] = "0b0"; - - add_port(ctx, new_cell.get(), "CLKHFEN", PORT_IN); - add_port(ctx, new_cell.get(), "CLKHFPU", PORT_IN); - add_port(ctx, new_cell.get(), "CLKHF", PORT_OUT); - add_port(ctx, new_cell.get(), "CLKHF_FABRIC", PORT_OUT); - for (int i = 0; i < 10; i++) - add_port(ctx, new_cell.get(), "TRIM" + std::to_string(i), PORT_IN); - } else if (type == ctx->id("SB_GB")) { - add_port(ctx, new_cell.get(), "USER_SIGNAL_TO_GLOBAL_BUFFER", PORT_IN); - add_port(ctx, new_cell.get(), "GLOBAL_BUFFER_OUTPUT", PORT_OUT); - } else if (type == ctx->id("ICESTORM_SPRAM")) { - add_port(ctx, new_cell.get(), "WREN", PORT_IN); - add_port(ctx, new_cell.get(), "CHIPSELECT", PORT_IN); - add_port(ctx, new_cell.get(), "CLOCK", PORT_IN); - add_port(ctx, new_cell.get(), "STANDBY", PORT_IN); - add_port(ctx, new_cell.get(), "SLEEP", PORT_IN); - add_port(ctx, new_cell.get(), "POWEROFF", PORT_IN); - - for (int i = 0; i < 16; i++) { - add_port(ctx, new_cell.get(), "DATAIN_" + std::to_string(i), PORT_IN); - add_port(ctx, new_cell.get(), "DATAOUT_" + std::to_string(i), PORT_OUT); - } - for (int i = 0; i < 14; i++) { - add_port(ctx, new_cell.get(), "ADDRESS_" + std::to_string(i), PORT_IN); - } - for (int i = 0; i < 4; i++) { - add_port(ctx, new_cell.get(), "MASKWREN_" + std::to_string(i), PORT_IN); - } - } else if (type == ctx->id("ICESTORM_DSP")) { - new_cell->params[ctx->id("NEG_TRIGGER")] = "0"; - - new_cell->params[ctx->id("C_REG")] = "0"; - new_cell->params[ctx->id("A_REG")] = "0"; - new_cell->params[ctx->id("B_REG")] = "0"; - new_cell->params[ctx->id("D_REG")] = "0"; - new_cell->params[ctx->id("TOP_8x8_MULT_REG")] = "0"; - new_cell->params[ctx->id("BOT_8x8_MULT_REG")] = "0"; - new_cell->params[ctx->id("PIPELINE_16x16_MULT_REG1")] = "0"; - new_cell->params[ctx->id("PIPELINE_16x16_MULT_REG2")] = "0"; - - new_cell->params[ctx->id("TOPOUTPUT_SELECT")] = "0"; - new_cell->params[ctx->id("TOPADDSUB_LOWERINPUT")] = "0"; - new_cell->params[ctx->id("TOPADDSUB_UPPERINPUT")] = "0"; - new_cell->params[ctx->id("TOPADDSUB_CARRYSELECT")] = "0"; - - new_cell->params[ctx->id("BOTOUTPUT_SELECT")] = "0"; - new_cell->params[ctx->id("BOTADDSUB_LOWERINPUT")] = "0"; - new_cell->params[ctx->id("BOTADDSUB_UPPERINPUT")] = "0"; - new_cell->params[ctx->id("BOTADDSUB_CARRYSELECT")] = "0"; - - new_cell->params[ctx->id("MODE_8x8")] = "0"; - new_cell->params[ctx->id("A_SIGNED")] = "0"; - new_cell->params[ctx->id("B_SIGNED")] = "0"; - - add_port(ctx, new_cell.get(), "CLK", PORT_IN); - add_port(ctx, new_cell.get(), "CE", PORT_IN); - for (int i = 0; i < 16; i++) { - add_port(ctx, new_cell.get(), "C_" + std::to_string(i), PORT_IN); - add_port(ctx, new_cell.get(), "A_" + std::to_string(i), PORT_IN); - add_port(ctx, new_cell.get(), "B_" + std::to_string(i), PORT_IN); - add_port(ctx, new_cell.get(), "D_" + std::to_string(i), PORT_IN); - } - add_port(ctx, new_cell.get(), "AHOLD", PORT_IN); - add_port(ctx, new_cell.get(), "BHOLD", PORT_IN); - add_port(ctx, new_cell.get(), "CHOLD", PORT_IN); - add_port(ctx, new_cell.get(), "DHOLD", PORT_IN); - - add_port(ctx, new_cell.get(), "IRSTTOP", PORT_IN); - add_port(ctx, new_cell.get(), "IRSTBOT", PORT_IN); - add_port(ctx, new_cell.get(), "ORSTTOP", PORT_IN); - add_port(ctx, new_cell.get(), "ORSTBOT", PORT_IN); - - add_port(ctx, new_cell.get(), "OLOADTOP", PORT_IN); - add_port(ctx, new_cell.get(), "OLOADBOT", PORT_IN); - - add_port(ctx, new_cell.get(), "ADDSUBTOP", PORT_IN); - add_port(ctx, new_cell.get(), "ADDSUBBOT", PORT_IN); - - add_port(ctx, new_cell.get(), "OHOLDTOP", PORT_IN); - add_port(ctx, new_cell.get(), "OHOLDBOT", PORT_IN); - - add_port(ctx, new_cell.get(), "CI", PORT_IN); - add_port(ctx, new_cell.get(), "ACCUMCI", PORT_IN); - add_port(ctx, new_cell.get(), "SIGNEXTIN", PORT_IN); - - for (int i = 0; i < 32; i++) { - add_port(ctx, new_cell.get(), "O_" + std::to_string(i), PORT_OUT); - } - - add_port(ctx, new_cell.get(), "CO", PORT_OUT); - add_port(ctx, new_cell.get(), "ACCUMCO", PORT_OUT); - add_port(ctx, new_cell.get(), "SIGNEXTOUT", PORT_OUT); - - } else if (type == ctx->id("ICESTORM_PLL")) { - new_cell->params[ctx->id("DELAY_ADJMODE_FB")] = "0"; - new_cell->params[ctx->id("DELAY_ADJMODE_REL")] = "0"; - - new_cell->params[ctx->id("DIVF")] = "0"; - new_cell->params[ctx->id("DIVQ")] = "0"; - new_cell->params[ctx->id("DIVR")] = "0"; - - new_cell->params[ctx->id("FDA_FEEDBACK")] = "0"; - new_cell->params[ctx->id("FDA_RELATIVE")] = "0"; - new_cell->params[ctx->id("FEEDBACK_PATH")] = "0"; - new_cell->params[ctx->id("FILTER_RANGE")] = "0"; - - new_cell->params[ctx->id("PLLOUT_SELECT_A")] = "0"; - new_cell->params[ctx->id("PLLOUT_SELECT_B")] = "0"; - - new_cell->params[ctx->id("PLLTYPE")] = "0"; - new_cell->params[ctx->id("SHIFTREG_DIVMODE")] = "0"; - new_cell->params[ctx->id("TEST_MODE")] = "0"; - - add_port(ctx, new_cell.get(), "BYPASS", PORT_IN); - add_port(ctx, new_cell.get(), "DYNAMICDELAY", PORT_IN); - add_port(ctx, new_cell.get(), "EXTFEEDBACK", PORT_IN); - add_port(ctx, new_cell.get(), "LATCHINPUTVALUE", PORT_IN); - add_port(ctx, new_cell.get(), "REFERENCECLK", PORT_IN); - add_port(ctx, new_cell.get(), "RESETB", PORT_IN); - - add_port(ctx, new_cell.get(), "SCLK", PORT_IN); - add_port(ctx, new_cell.get(), "SDI", PORT_IN); - add_port(ctx, new_cell.get(), "SDI", PORT_OUT); - - add_port(ctx, new_cell.get(), "LOCK", PORT_OUT); - add_port(ctx, new_cell.get(), "PLLOUT_A", PORT_OUT); - add_port(ctx, new_cell.get(), "PLLOUT_B", PORT_OUT); +// add_port(ctx, new_cell.get(), "PACKAGE_PIN", PORT_INOUT); +// +// add_port(ctx, new_cell.get(), "LATCH_INPUT_VALUE", PORT_IN); +// add_port(ctx, new_cell.get(), "CLOCK_ENABLE", PORT_IN); +// add_port(ctx, new_cell.get(), "INPUT_CLK", PORT_IN); +// add_port(ctx, new_cell.get(), "OUTPUT_CLK", PORT_IN); +// +// add_port(ctx, new_cell.get(), "OUTPUT_ENABLE", PORT_IN); +// add_port(ctx, new_cell.get(), "D_OUT_0", PORT_IN); +// add_port(ctx, new_cell.get(), "D_OUT_1", PORT_IN); +// +// add_port(ctx, new_cell.get(), "D_IN_0", PORT_OUT); +// add_port(ctx, new_cell.get(), "D_IN_1", PORT_OUT); + add_port(ctx, new_cell.get(), "I", PORT_OUT); + add_port(ctx, new_cell.get(), "O", PORT_IN); +// } else if (type == ctx->id("ICESTORM_RAM")) { +// new_cell->params[ctx->id("NEG_CLK_W")] = "0"; +// new_cell->params[ctx->id("NEG_CLK_R")] = "0"; +// new_cell->params[ctx->id("WRITE_MODE")] = "0"; +// new_cell->params[ctx->id("READ_MODE")] = "0"; +// +// add_port(ctx, new_cell.get(), "RCLK", PORT_IN); +// add_port(ctx, new_cell.get(), "RCLKE", PORT_IN); +// add_port(ctx, new_cell.get(), "RE", PORT_IN); +// +// add_port(ctx, new_cell.get(), "WCLK", PORT_IN); +// add_port(ctx, new_cell.get(), "WCLKE", PORT_IN); +// add_port(ctx, new_cell.get(), "WE", PORT_IN); +// +// for (int i = 0; i < 16; i++) { +// add_port(ctx, new_cell.get(), "WDATA_" + std::to_string(i), PORT_IN); +// add_port(ctx, new_cell.get(), "MASK_" + std::to_string(i), PORT_IN); +// add_port(ctx, new_cell.get(), "RDATA_" + std::to_string(i), PORT_OUT); +// } +// +// for (int i = 0; i < 11; i++) { +// add_port(ctx, new_cell.get(), "RADDR_" + std::to_string(i), PORT_IN); +// add_port(ctx, new_cell.get(), "WADDR_" + std::to_string(i), PORT_IN); +// } +// } else if (type == ctx->id("ICESTORM_LFOSC")) { +// add_port(ctx, new_cell.get(), "CLKLFEN", PORT_IN); +// add_port(ctx, new_cell.get(), "CLKLFPU", PORT_IN); +// add_port(ctx, new_cell.get(), "CLKLF", PORT_OUT); +// add_port(ctx, new_cell.get(), "CLKLF_FABRIC", PORT_OUT); +// } else if (type == ctx->id("ICESTORM_HFOSC")) { +// new_cell->params[ctx->id("CLKHF_DIV")] = "0b00"; +// new_cell->params[ctx->id("TRIM_EN")] = "0b0"; +// +// add_port(ctx, new_cell.get(), "CLKHFEN", PORT_IN); +// add_port(ctx, new_cell.get(), "CLKHFPU", PORT_IN); +// add_port(ctx, new_cell.get(), "CLKHF", PORT_OUT); +// add_port(ctx, new_cell.get(), "CLKHF_FABRIC", PORT_OUT); +// for (int i = 0; i < 10; i++) +// add_port(ctx, new_cell.get(), "TRIM" + std::to_string(i), PORT_IN); + } else if (type == ctx->id("BUFGCTRL")) { + add_port(ctx, new_cell.get(), "I0", PORT_IN); + add_port(ctx, new_cell.get(), "O", PORT_OUT); +// } else if (type == ctx->id("ICESTORM_SPRAM")) { +// add_port(ctx, new_cell.get(), "WREN", PORT_IN); +// add_port(ctx, new_cell.get(), "CHIPSELECT", PORT_IN); +// add_port(ctx, new_cell.get(), "CLOCK", PORT_IN); +// add_port(ctx, new_cell.get(), "STANDBY", PORT_IN); +// add_port(ctx, new_cell.get(), "SLEEP", PORT_IN); +// add_port(ctx, new_cell.get(), "POWEROFF", PORT_IN); +// +// for (int i = 0; i < 16; i++) { +// add_port(ctx, new_cell.get(), "DATAIN_" + std::to_string(i), PORT_IN); +// add_port(ctx, new_cell.get(), "DATAOUT_" + std::to_string(i), PORT_OUT); +// } +// for (int i = 0; i < 14; i++) { +// add_port(ctx, new_cell.get(), "ADDRESS_" + std::to_string(i), PORT_IN); +// } +// for (int i = 0; i < 4; i++) { +// add_port(ctx, new_cell.get(), "MASKWREN_" + std::to_string(i), PORT_IN); +// } +// } else if (type == ctx->id("ICESTORM_DSP")) { +// new_cell->params[ctx->id("NEG_TRIGGER")] = "0"; +// +// new_cell->params[ctx->id("C_REG")] = "0"; +// new_cell->params[ctx->id("A_REG")] = "0"; +// new_cell->params[ctx->id("B_REG")] = "0"; +// new_cell->params[ctx->id("D_REG")] = "0"; +// new_cell->params[ctx->id("TOP_8x8_MULT_REG")] = "0"; +// new_cell->params[ctx->id("BOT_8x8_MULT_REG")] = "0"; +// new_cell->params[ctx->id("PIPELINE_16x16_MULT_REG1")] = "0"; +// new_cell->params[ctx->id("PIPELINE_16x16_MULT_REG2")] = "0"; +// +// new_cell->params[ctx->id("TOPOUTPUT_SELECT")] = "0"; +// new_cell->params[ctx->id("TOPADDSUB_LOWERINPUT")] = "0"; +// new_cell->params[ctx->id("TOPADDSUB_UPPERINPUT")] = "0"; +// new_cell->params[ctx->id("TOPADDSUB_CARRYSELECT")] = "0"; +// +// new_cell->params[ctx->id("BOTOUTPUT_SELECT")] = "0"; +// new_cell->params[ctx->id("BOTADDSUB_LOWERINPUT")] = "0"; +// new_cell->params[ctx->id("BOTADDSUB_UPPERINPUT")] = "0"; +// new_cell->params[ctx->id("BOTADDSUB_CARRYSELECT")] = "0"; +// +// new_cell->params[ctx->id("MODE_8x8")] = "0"; +// new_cell->params[ctx->id("A_SIGNED")] = "0"; +// new_cell->params[ctx->id("B_SIGNED")] = "0"; +// +// add_port(ctx, new_cell.get(), "CLK", PORT_IN); +// add_port(ctx, new_cell.get(), "CE", PORT_IN); +// for (int i = 0; i < 16; i++) { +// add_port(ctx, new_cell.get(), "C_" + std::to_string(i), PORT_IN); +// add_port(ctx, new_cell.get(), "A_" + std::to_string(i), PORT_IN); +// add_port(ctx, new_cell.get(), "B_" + std::to_string(i), PORT_IN); +// add_port(ctx, new_cell.get(), "D_" + std::to_string(i), PORT_IN); +// } +// add_port(ctx, new_cell.get(), "AHOLD", PORT_IN); +// add_port(ctx, new_cell.get(), "BHOLD", PORT_IN); +// add_port(ctx, new_cell.get(), "CHOLD", PORT_IN); +// add_port(ctx, new_cell.get(), "DHOLD", PORT_IN); +// +// add_port(ctx, new_cell.get(), "IRSTTOP", PORT_IN); +// add_port(ctx, new_cell.get(), "IRSTBOT", PORT_IN); +// add_port(ctx, new_cell.get(), "ORSTTOP", PORT_IN); +// add_port(ctx, new_cell.get(), "ORSTBOT", PORT_IN); +// +// add_port(ctx, new_cell.get(), "OLOADTOP", PORT_IN); +// add_port(ctx, new_cell.get(), "OLOADBOT", PORT_IN); +// +// add_port(ctx, new_cell.get(), "ADDSUBTOP", PORT_IN); +// add_port(ctx, new_cell.get(), "ADDSUBBOT", PORT_IN); +// +// add_port(ctx, new_cell.get(), "OHOLDTOP", PORT_IN); +// add_port(ctx, new_cell.get(), "OHOLDBOT", PORT_IN); +// +// add_port(ctx, new_cell.get(), "CI", PORT_IN); +// add_port(ctx, new_cell.get(), "ACCUMCI", PORT_IN); +// add_port(ctx, new_cell.get(), "SIGNEXTIN", PORT_IN); +// +// for (int i = 0; i < 32; i++) { +// add_port(ctx, new_cell.get(), "O_" + std::to_string(i), PORT_OUT); +// } +// +// add_port(ctx, new_cell.get(), "CO", PORT_OUT); +// add_port(ctx, new_cell.get(), "ACCUMCO", PORT_OUT); +// add_port(ctx, new_cell.get(), "SIGNEXTOUT", PORT_OUT); +// +// } else if (type == ctx->id("ICESTORM_PLL")) { +// new_cell->params[ctx->id("DELAY_ADJMODE_FB")] = "0"; +// new_cell->params[ctx->id("DELAY_ADJMODE_REL")] = "0"; +// +// new_cell->params[ctx->id("DIVF")] = "0"; +// new_cell->params[ctx->id("DIVQ")] = "0"; +// new_cell->params[ctx->id("DIVR")] = "0"; +// +// new_cell->params[ctx->id("FDA_FEEDBACK")] = "0"; +// new_cell->params[ctx->id("FDA_RELATIVE")] = "0"; +// new_cell->params[ctx->id("FEEDBACK_PATH")] = "0"; +// new_cell->params[ctx->id("FILTER_RANGE")] = "0"; +// +// new_cell->params[ctx->id("PLLOUT_SELECT_A")] = "0"; +// new_cell->params[ctx->id("PLLOUT_SELECT_B")] = "0"; +// +// new_cell->params[ctx->id("PLLTYPE")] = "0"; +// new_cell->params[ctx->id("SHIFTREG_DIVMODE")] = "0"; +// new_cell->params[ctx->id("TEST_MODE")] = "0"; +// +// add_port(ctx, new_cell.get(), "BYPASS", PORT_IN); +// add_port(ctx, new_cell.get(), "DYNAMICDELAY", PORT_IN); +// add_port(ctx, new_cell.get(), "EXTFEEDBACK", PORT_IN); +// add_port(ctx, new_cell.get(), "LATCHINPUTVALUE", PORT_IN); +// add_port(ctx, new_cell.get(), "REFERENCECLK", PORT_IN); +// add_port(ctx, new_cell.get(), "RESETB", PORT_IN); +// +// add_port(ctx, new_cell.get(), "SCLK", PORT_IN); +// add_port(ctx, new_cell.get(), "SDI", PORT_IN); +// add_port(ctx, new_cell.get(), "SDI", PORT_OUT); +// +// add_port(ctx, new_cell.get(), "LOCK", PORT_OUT); +// add_port(ctx, new_cell.get(), "PLLOUT_A", PORT_OUT); +// add_port(ctx, new_cell.get(), "PLLOUT_B", PORT_OUT); } else { - log_error("unable to create iCE40 cell of type %s", type.c_str(ctx)); + log_error("unable to create XC7 cell of type %s\n", type.c_str(ctx)); } return new_cell; } @@ -252,9 +260,16 @@ void lut_to_lc(const Context *ctx, CellInfo *lut, CellInfo *lc, bool no_dff) { lc->params[ctx->id("LUT_INIT")] = lut->params[ctx->id("LUT_INIT")]; replace_port(lut, ctx->id("I0"), lc, ctx->id("I0")); - replace_port(lut, ctx->id("I1"), lc, ctx->id("I1")); - replace_port(lut, ctx->id("I2"), lc, ctx->id("I2")); - replace_port(lut, ctx->id("I3"), lc, ctx->id("I3")); + if (get_net_or_empty(lut, ctx->id("I1"))) + replace_port(lut, ctx->id("I1"), lc, ctx->id("I1")); + if (get_net_or_empty(lut, ctx->id("I2"))) + replace_port(lut, ctx->id("I2"), lc, ctx->id("I2")); + if (get_net_or_empty(lut, ctx->id("I3"))) + replace_port(lut, ctx->id("I3"), lc, ctx->id("I3")); + if (get_net_or_empty(lut, ctx->id("I4"))) + replace_port(lut, ctx->id("I4"), lc, ctx->id("I3")); + if (get_net_or_empty(lut, ctx->id("I5"))) + replace_port(lut, ctx->id("I5"), lc, ctx->id("I3")); if (no_dff) { replace_port(lut, ctx->id("O"), lc, ctx->id("O")); lc->params[ctx->id("DFF_ENABLE")] = "0"; @@ -264,43 +279,41 @@ void lut_to_lc(const Context *ctx, CellInfo *lut, CellInfo *lc, bool no_dff) void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_lut) { lc->params[ctx->id("DFF_ENABLE")] = "1"; - std::string config = dff->type.str(ctx).substr(6); + std::string config = dff->type.str(ctx).substr(2); auto citer = config.begin(); replace_port(dff, ctx->id("C"), lc, ctx->id("CLK")); - if (citer != config.end() && *citer == 'N') { - lc->params[ctx->id("NEG_CLK")] = "1"; - ++citer; - } else { - lc->params[ctx->id("NEG_CLK")] = "0"; - } - - if (citer != config.end() && *citer == 'E') { - replace_port(dff, ctx->id("E"), lc, ctx->id("CEN")); - ++citer; - } - if (citer != config.end()) { - if ((config.end() - citer) >= 2) { - char c = *(citer++); - NPNR_ASSERT(c == 'S'); - lc->params[ctx->id("ASYNC_SR")] = "0"; - } else { + if (*citer == 'C' || *citer == 'P') lc->params[ctx->id("ASYNC_SR")] = "1"; - } + else + lc->params[ctx->id("ASYNC_SR")] = "0"; if (*citer == 'S') { citer++; replace_port(dff, ctx->id("S"), lc, ctx->id("SR")); lc->params[ctx->id("SET_NORESET")] = "1"; - } else { - NPNR_ASSERT(*citer == 'R'); + } else if (*citer == 'R') { citer++; replace_port(dff, ctx->id("R"), lc, ctx->id("SR")); lc->params[ctx->id("SET_NORESET")] = "0"; + } else if (*citer == 'C') { + citer++; + replace_port(dff, ctx->id("CLR"), lc, ctx->id("SR")); + lc->params[ctx->id("SET_NORESET")] = "0"; + } else { + NPNR_ASSERT(*citer == 'P'); + citer++; + replace_port(dff, ctx->id("PRE"), lc, ctx->id("SR")); + lc->params[ctx->id("SET_NORESET")] = "1"; } } + if (citer != config.end() && *citer == 'E') { + replace_port(dff, ctx->id("CE"), lc, ctx->id("CE")); + ++citer; + } + NPNR_ASSERT(citer == config.end()); if (pass_thru_lut) { @@ -308,7 +321,7 @@ void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_l replace_port(dff, ctx->id("D"), lc, ctx->id("I0")); } - replace_port(dff, ctx->id("Q"), lc, ctx->id("O")); + replace_port(dff, ctx->id("Q"), lc, ctx->id("OQ")); } void nxio_to_sb(Context *ctx, CellInfo *nxio, CellInfo *sbio) @@ -318,25 +331,25 @@ void nxio_to_sb(Context *ctx, CellInfo *nxio, CellInfo *sbio) auto pu_attr = nxio->attrs.find(ctx->id("PULLUP")); if (pu_attr != nxio->attrs.end()) sbio->params[ctx->id("PULLUP")] = pu_attr->second; - replace_port(nxio, ctx->id("O"), sbio, ctx->id("D_IN_0")); + replace_port(nxio, ctx->id("O"), sbio, ctx->id("I")); } else if (nxio->type == ctx->id("$nextpnr_obuf")) { sbio->params[ctx->id("PIN_TYPE")] = "25"; - replace_port(nxio, ctx->id("I"), sbio, ctx->id("D_OUT_0")); + replace_port(nxio, ctx->id("I"), sbio, ctx->id("O")); } else if (nxio->type == ctx->id("$nextpnr_iobuf")) { // N.B. tristate will be dealt with below sbio->params[ctx->id("PIN_TYPE")] = "25"; - replace_port(nxio, ctx->id("I"), sbio, ctx->id("D_OUT_0")); - replace_port(nxio, ctx->id("O"), sbio, ctx->id("D_IN_0")); + replace_port(nxio, ctx->id("I"), sbio, ctx->id("O")); + replace_port(nxio, ctx->id("O"), sbio, ctx->id("I")); } else { NPNR_ASSERT(false); } - NetInfo *donet = sbio->ports.at(ctx->id("D_OUT_0")).net; + NetInfo *donet = sbio->ports.at(ctx->id("O")).net; CellInfo *tbuf = net_driven_by( ctx, donet, [](const Context *ctx, const CellInfo *cell) { return cell->type == ctx->id("$_TBUF_"); }, ctx->id("Y")); if (tbuf) { sbio->params[ctx->id("PIN_TYPE")] = "41"; - replace_port(tbuf, ctx->id("A"), sbio, ctx->id("D_OUT_0")); + replace_port(tbuf, ctx->id("A"), sbio, ctx->id("O")); replace_port(tbuf, ctx->id("E"), sbio, ctx->id("OUTPUT_ENABLE")); ctx->nets.erase(donet->name); if (!donet->users.empty()) diff --git a/xc7/cells.h b/xc7/cells.h index 16135448..2a1d8f90 100644 --- a/xc7/cells.h +++ b/xc7/cells.h @@ -30,31 +30,23 @@ NEXTPNR_NAMESPACE_BEGIN std::unique_ptr create_ice_cell(Context *ctx, IdString type, std::string name = ""); // Return true if a cell is a LUT -inline bool is_lut(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_LUT4"); } +inline bool is_lut(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_LUT1 || cell->type == id_LUT2 || cell->type == id_LUT3 || cell->type == id_LUT4 || cell->type == id_LUT5 || cell->type == id_LUT6; } // Return true if a cell is a flipflop inline bool is_ff(const BaseCtx *ctx, const CellInfo *cell) { - return cell->type == ctx->id("SB_DFF") || cell->type == ctx->id("SB_DFFE") || cell->type == ctx->id("SB_DFFSR") || - cell->type == ctx->id("SB_DFFR") || cell->type == ctx->id("SB_DFFSS") || cell->type == ctx->id("SB_DFFS") || - cell->type == ctx->id("SB_DFFESR") || cell->type == ctx->id("SB_DFFER") || - cell->type == ctx->id("SB_DFFESS") || cell->type == ctx->id("SB_DFFES") || - cell->type == ctx->id("SB_DFFN") || cell->type == ctx->id("SB_DFFNE") || - cell->type == ctx->id("SB_DFFNSR") || cell->type == ctx->id("SB_DFFNR") || - cell->type == ctx->id("SB_DFFNSS") || cell->type == ctx->id("SB_DFFNS") || - cell->type == ctx->id("SB_DFFNESR") || cell->type == ctx->id("SB_DFFNER") || - cell->type == ctx->id("SB_DFFNESS") || cell->type == ctx->id("SB_DFFNES"); + return cell->type == id_FDRE || cell->type == id_FDSE || cell->type == id_FDCE || cell->type == id_FDPE; } inline bool is_carry(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_CARRY"); } -inline bool is_lc(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("ICESTORM_LC"); } +inline bool is_lc(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("XC7_LC"); } // Return true if a cell is a SB_IO inline bool is_sb_io(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_IO"); } // Return true if a cell is a global buffer -inline bool is_gbuf(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_GB"); } +inline bool is_gbuf(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("BUFGCTRL"); } // Return true if a cell is a RAM inline bool is_ram(const BaseCtx *ctx, const CellInfo *cell) diff --git a/xc7/constids.inc b/xc7/constids.inc index adcea7ad..10543fb3 100644 --- a/xc7/constids.inc +++ b/xc7/constids.inc @@ -435,3 +435,21 @@ X(ICESTORM_SPRAM) X(DFF_ENABLE) X(CARRY_ENABLE) X(NEG_CLK) + +X(LUT1) +X(LUT2) +X(LUT3) +X(LUT4) +X(LUT5) +X(LUT6) + +X(FDRE) +X(FDSE) +X(FDCE) +X(FDPE) + +X(BUFGCTRL) +X(SLICEL) +X(IOBUF) +X(IOB33S) +X(IOB33M) // What is the difference between IOB33S and IOB33M? diff --git a/xc7/pack.cc b/xc7/pack.cc index 05338713..e8207210 100644 --- a/xc7/pack.cc +++ b/xc7/pack.cc @@ -42,7 +42,7 @@ static void pack_lut_lutffs(Context *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)) { - std::unique_ptr packed = create_ice_cell(ctx, ctx->id("ICESTORM_LC"), ci->name.str(ctx) + "_LC"); + std::unique_ptr packed = create_ice_cell(ctx, ctx->id("XC7_LC"), ci->name.str(ctx) + "_LC"); std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(packed->attrs, packed->attrs.begin())); packed_cells.insert(ci->name); if (ctx->verbose) @@ -97,7 +97,7 @@ static void pack_nonlut_ffs(Context *ctx) CellInfo *ci = cell.second; if (is_ff(ctx, ci)) { std::unique_ptr packed = - create_ice_cell(ctx, ctx->id("ICESTORM_LC"), ci->name.str(ctx) + "_DFFLC"); + create_ice_cell(ctx, ctx->id("XC7_LC"), ci->name.str(ctx) + "_DFFLC"); std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(packed->attrs, packed->attrs.begin())); if (ctx->verbose) log_info("packed cell %s into %s\n", ci->name.c_str(ctx), packed->name.c_str(ctx)); @@ -192,7 +192,7 @@ static void pack_carries(Context *ctx) } else { // No LC to pack into matching I0/I1, insert a new one std::unique_ptr created_lc = - create_ice_cell(ctx, ctx->id("ICESTORM_LC"), cell.first.str(ctx) + "$CARRY"); + create_ice_cell(ctx, ctx->id("XC7_LC"), cell.first.str(ctx) + "$CARRY"); carry_lc = created_lc.get(); created_lc->ports.at(ctx->id("I1")).net = i0_net; if (i0_net) { @@ -331,7 +331,7 @@ static void pack_constants(Context *ctx) { log_info("Packing constants..\n"); - std::unique_ptr gnd_cell = create_ice_cell(ctx, ctx->id("ICESTORM_LC"), "$PACKER_GND"); + std::unique_ptr gnd_cell = create_ice_cell(ctx, ctx->id("XC7_LC"), "$PACKER_GND"); gnd_cell->params[ctx->id("LUT_INIT")] = "0"; std::unique_ptr gnd_net = std::unique_ptr(new NetInfo); gnd_net->name = ctx->id("$PACKER_GND_NET"); @@ -339,7 +339,7 @@ static void pack_constants(Context *ctx) gnd_net->driver.port = ctx->id("O"); gnd_cell->ports.at(ctx->id("O")).net = gnd_net.get(); - std::unique_ptr vcc_cell = create_ice_cell(ctx, ctx->id("ICESTORM_LC"), "$PACKER_VCC"); + std::unique_ptr vcc_cell = create_ice_cell(ctx, ctx->id("XC7_LC"), "$PACKER_VCC"); vcc_cell->params[ctx->id("LUT_INIT")] = "1"; std::unique_ptr vcc_net = std::unique_ptr(new NetInfo); vcc_net->name = ctx->id("$PACKER_VCC_NET"); @@ -405,9 +405,9 @@ static void pack_io(Context *ctx) sb = net_only_drives(ctx, ci->ports.at(ctx->id("I")).net, is_sb_io, ctx->id("PACKAGE_PIN"), true, ci); } if (sb != nullptr) { - // Trivial case, SB_IO used. Just destroy the net and the + // Trivial case, IOBUF used. Just destroy the net and the // iobuf - log_info("%s feeds SB_IO %s, removing %s %s.\n", ci->name.c_str(ctx), sb->name.c_str(ctx), + log_info("%s feeds IOBUF %s, removing %s %s.\n", ci->name.c_str(ctx), sb->name.c_str(ctx), ci->type.c_str(ctx), ci->name.c_str(ctx)); NetInfo *net = sb->ports.at(ctx->id("PACKAGE_PIN")).net; if (net != nullptr) { @@ -421,9 +421,9 @@ static void pack_io(Context *ctx) } } } else { - // Create a SB_IO buffer + // Create a IOBUF buffer std::unique_ptr ice_cell = - create_ice_cell(ctx, ctx->id("SB_IO"), ci->name.str(ctx) + "$sb_io"); + create_ice_cell(ctx, ctx->id("IOBUF"), ci->name.str(ctx) + "$iob"); nxio_to_sb(ctx, ci, ice_cell.get()); new_cells.push_back(std::move(ice_cell)); sb = new_cells.back().get(); @@ -452,19 +452,19 @@ static bool is_logic_port(BaseCtx *ctx, const PortRef &port) static void insert_global(Context *ctx, NetInfo *net, bool is_reset, bool is_cen, bool is_logic) { std::string glb_name = net->name.str(ctx) + std::string("_$glb_") + (is_reset ? "sr" : (is_cen ? "ce" : "clk")); - std::unique_ptr gb = create_ice_cell(ctx, ctx->id("SB_GB"), "$gbuf_" + glb_name); - gb->ports[ctx->id("USER_SIGNAL_TO_GLOBAL_BUFFER")].net = net; + std::unique_ptr gb = create_ice_cell(ctx, id_BUFGCTRL, "$bufg_" + glb_name); + gb->ports[ctx->id("I0")].net = net; PortRef pr; pr.cell = gb.get(); - pr.port = ctx->id("USER_SIGNAL_TO_GLOBAL_BUFFER"); + pr.port = ctx->id("I0"); net->users.push_back(pr); pr.cell = gb.get(); - pr.port = ctx->id("GLOBAL_BUFFER_OUTPUT"); + pr.port = ctx->id("O"); std::unique_ptr glbnet = std::unique_ptr(new NetInfo()); glbnet->name = ctx->id(glb_name); glbnet->driver = pr; - gb->ports[ctx->id("GLOBAL_BUFFER_OUTPUT")].net = glbnet.get(); + gb->ports[ctx->id("O")].net = glbnet.get(); std::vector keep_users; for (auto user : net->users) { if (is_clock_port(ctx, user) || (is_reset && is_reset_port(ctx, user)) || @@ -582,7 +582,7 @@ static std::unique_ptr spliceLUT(Context *ctx, CellInfo *ci, IdString NPNR_ASSERT(port.net != nullptr); // Create pass-through LUT. - std::unique_ptr pt = create_ice_cell(ctx, ctx->id("ICESTORM_LC"), + std::unique_ptr pt = create_ice_cell(ctx, ctx->id("XC7_LC"), ci->name.str(ctx) + "$nextpnr_" + portId.str(ctx) + "_lut_through"); pt->params[ctx->id("LUT_INIT")] = "65280"; // output is always I3 @@ -596,7 +596,7 @@ static std::unique_ptr spliceLUT(Context *ctx, CellInfo *ci, IdString // New users of the original cell's port std::vector new_users; for (const auto &user : port.net->users) { - if (onlyNonLUTs && user.cell->type == ctx->id("ICESTORM_LC")) { + if (onlyNonLUTs && user.cell->type == ctx->id("XC7_LC")) { new_users.push_back(user); continue; } @@ -823,7 +823,7 @@ static void pack_special(Context *ctx) unsigned int lut_count = 0; for (const auto &user : port.net->users) { NPNR_ASSERT(user.cell != nullptr); - if (user.cell->type == ctx->id("ICESTORM_LC")) { + if (user.cell->type == ctx->id("XC7_LC")) { found_lut = true; lut_count++; } else { @@ -856,7 +856,7 @@ static void pack_special(Context *ctx) int z = 0; for (const auto &user : port.net->users) { NPNR_ASSERT(user.cell != nullptr); - NPNR_ASSERT(user.cell->type == ctx->id("ICESTORM_LC")); + NPNR_ASSERT(user.cell->type == ctx->id("XC7_LC")); // TODO(q3k): handle when the Bel might be already the // target of another constraint.