WIP
This commit is contained in:
parent
8cddc49abc
commit
2bc7ffc2ea
54
xc7/arch.cc
54
xc7/arch.cc
@ -70,6 +70,8 @@ Arch::Arch(ArchArgs args) : args(args)
|
|||||||
|
|
||||||
ddbSites = &ddb->getSites();
|
ddbSites = &ddb->getSites();
|
||||||
ddbTiles = &ddb->getTiles();
|
ddbTiles = &ddb->getTiles();
|
||||||
|
|
||||||
|
bel_to_cell.resize(ddbSites->getSiteCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
@ -171,32 +173,32 @@ WireId Arch::getBelPinWire(BelId bel, IdString pin) const
|
|||||||
{
|
{
|
||||||
WireId ret;
|
WireId ret;
|
||||||
|
|
||||||
NPNR_ASSERT(bel != BelId());
|
// NPNR_ASSERT(bel != BelId());
|
||||||
|
//
|
||||||
int num_bel_wires = chip_info->bel_data[bel.index].num_bel_wires;
|
// 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();
|
// const BelWirePOD *bel_wires = chip_info->bel_data[bel.index].bel_wires.get();
|
||||||
|
//
|
||||||
if (num_bel_wires < 7) {
|
// if (num_bel_wires < 7) {
|
||||||
for (int i = 0; i < num_bel_wires; i++) {
|
// for (int i = 0; i < num_bel_wires; i++) {
|
||||||
if (bel_wires[i].port == pin.index) {
|
// if (bel_wires[i].port == pin.index) {
|
||||||
ret.index = bel_wires[i].wire_index;
|
// ret.index = bel_wires[i].wire_index;
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
} else {
|
// } else {
|
||||||
int b = 0, e = num_bel_wires - 1;
|
// int b = 0, e = num_bel_wires - 1;
|
||||||
while (b <= e) {
|
// while (b <= e) {
|
||||||
int i = (b + e) / 2;
|
// int i = (b + e) / 2;
|
||||||
if (bel_wires[i].port == pin.index) {
|
// if (bel_wires[i].port == pin.index) {
|
||||||
ret.index = bel_wires[i].wire_index;
|
// ret.index = bel_wires[i].wire_index;
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
if (bel_wires[i].port > pin.index)
|
// if (bel_wires[i].port > pin.index)
|
||||||
e = i - 1;
|
// e = i - 1;
|
||||||
else
|
// else
|
||||||
b = i + 1;
|
// b = i + 1;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
10
xc7/arch.h
10
xc7/arch.h
@ -433,7 +433,7 @@ struct Arch : BaseCtx
|
|||||||
NPNR_ASSERT(bel_to_cell[bel.index] == nullptr);
|
NPNR_ASSERT(bel_to_cell[bel.index] == nullptr);
|
||||||
|
|
||||||
bel_to_cell[bel.index] = cell;
|
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->bel = bel;
|
||||||
cell->belStrength = strength;
|
cell->belStrength = strength;
|
||||||
refreshUiBel(bel);
|
refreshUiBel(bel);
|
||||||
@ -446,7 +446,7 @@ struct Arch : BaseCtx
|
|||||||
bel_to_cell[bel.index]->bel = BelId();
|
bel_to_cell[bel.index]->bel = BelId();
|
||||||
bel_to_cell[bel.index]->belStrength = STRENGTH_NONE;
|
bel_to_cell[bel.index]->belStrength = STRENGTH_NONE;
|
||||||
bel_to_cell[bel.index] = nullptr;
|
bel_to_cell[bel.index] = nullptr;
|
||||||
bel_carry[bel.index] = false;
|
//bel_carry[bel.index] = false;
|
||||||
refreshUiBel(bel);
|
refreshUiBel(bel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -490,14 +490,14 @@ struct Arch : BaseCtx
|
|||||||
BelId getBelByLocation(Loc loc) const;
|
BelId getBelByLocation(Loc loc) const;
|
||||||
BelRange getBelsByTile(int x, int y) 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
|
IdString getBelType(BelId bel) const
|
||||||
{
|
{
|
||||||
NPNR_ASSERT(bel != BelId());
|
NPNR_ASSERT(bel != BelId());
|
||||||
const auto& site = ddbSites->getSite(bel.index);
|
const auto& site = ddbSites->getSite(bel.index);
|
||||||
const auto& tile_info = ddbTiles->getTileInfo(site.getTileIndex());
|
auto prim_def = site.getPrimitiveDefPtr();
|
||||||
return id(ddbTiles->getTileTypeName(tile_info.getTypeIndex()));
|
return id(prim_def->getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
WireId getBelPinWire(BelId bel, IdString pin) const;
|
WireId getBelPinWire(BelId bel, IdString pin) const;
|
||||||
|
@ -29,45 +29,37 @@ NEXTPNR_NAMESPACE_BEGIN
|
|||||||
|
|
||||||
bool Arch::logicCellsCompatible(const CellInfo** it, const size_t size) const
|
bool Arch::logicCellsCompatible(const CellInfo** it, const size_t size) const
|
||||||
{
|
{
|
||||||
bool dffs_exist = false, dffs_neg = false;
|
// bool dffs_exist = false, dffs_neg = false;
|
||||||
const NetInfo *cen = nullptr, *clk = nullptr, *sr = nullptr;
|
// const NetInfo *cen = nullptr, *clk = nullptr, *sr = nullptr;
|
||||||
int locals_count = 0;
|
//
|
||||||
|
// for (auto cell : boost::make_iterator_range(it, it+size)) {
|
||||||
for (auto cell : boost::make_iterator_range(it, it+size)) {
|
// NPNR_ASSERT(cell->belType == id_ICESTORM_LC);
|
||||||
NPNR_ASSERT(cell->belType == id_ICESTORM_LC);
|
// if (cell->lcInfo.dffEnable) {
|
||||||
if (cell->lcInfo.dffEnable) {
|
// if (!dffs_exist) {
|
||||||
if (!dffs_exist) {
|
// dffs_exist = true;
|
||||||
dffs_exist = true;
|
// cen = cell->lcInfo.cen;
|
||||||
cen = cell->lcInfo.cen;
|
// clk = cell->lcInfo.clk;
|
||||||
clk = cell->lcInfo.clk;
|
// sr = cell->lcInfo.sr;
|
||||||
sr = cell->lcInfo.sr;
|
//
|
||||||
|
// if (cell->lcInfo.negClk) {
|
||||||
if (cen != nullptr && !cen->is_global)
|
// dffs_neg = true;
|
||||||
locals_count++;
|
// }
|
||||||
if (clk != nullptr && !clk->is_global)
|
// } else {
|
||||||
locals_count++;
|
// if (cen != cell->lcInfo.cen)
|
||||||
if (sr != nullptr && !sr->is_global)
|
// return false;
|
||||||
locals_count++;
|
// if (clk != cell->lcInfo.clk)
|
||||||
|
// return false;
|
||||||
if (cell->lcInfo.negClk) {
|
// if (sr != cell->lcInfo.sr)
|
||||||
dffs_neg = true;
|
// return false;
|
||||||
}
|
// if (dffs_neg != cell->lcInfo.negClk)
|
||||||
} else {
|
// return false;
|
||||||
if (cen != cell->lcInfo.cen)
|
// }
|
||||||
return false;
|
// }
|
||||||
if (clk != cell->lcInfo.clk)
|
// locals_count += cell->lcInfo.inputCount;
|
||||||
return false;
|
// }
|
||||||
if (sr != cell->lcInfo.sr)
|
//
|
||||||
return false;
|
// return locals_count <= 32;
|
||||||
if (dffs_neg != cell->lcInfo.negClk)
|
return true;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
locals_count += cell->lcInfo.inputCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
return locals_count <= 32;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Arch::isBelLocationValid(BelId bel) const
|
bool Arch::isBelLocationValid(BelId bel) const
|
||||||
|
@ -7,8 +7,8 @@ module blinky (
|
|||||||
output led5
|
output led5
|
||||||
);
|
);
|
||||||
|
|
||||||
BUFG clk_gb (
|
BUFGCTRL clk_gb (
|
||||||
.I(clki),
|
.I0(clki),
|
||||||
.O(clk)
|
.O(clk)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
429
xc7/cells.cc
429
xc7/cells.cc
@ -22,6 +22,7 @@
|
|||||||
#include "cells.h"
|
#include "cells.h"
|
||||||
#include "design_utils.h"
|
#include "design_utils.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_BEGIN
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
|
|
||||||
@ -41,7 +42,8 @@ std::unique_ptr<CellInfo> create_ice_cell(Context *ctx, IdString type, std::stri
|
|||||||
new_cell->name = ctx->id(name);
|
new_cell->name = ctx->id(name);
|
||||||
}
|
}
|
||||||
new_cell->type = type;
|
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("LUT_INIT")] = "0";
|
||||||
new_cell->params[ctx->id("NEG_CLK")] = "0";
|
new_cell->params[ctx->id("NEG_CLK")] = "0";
|
||||||
new_cell->params[ctx->id("CARRY_ENABLE")] = "0";
|
new_cell->params[ctx->id("CARRY_ENABLE")] = "0";
|
||||||
@ -55,195 +57,201 @@ std::unique_ptr<CellInfo> create_ice_cell(Context *ctx, IdString type, std::stri
|
|||||||
add_port(ctx, new_cell.get(), "I1", PORT_IN);
|
add_port(ctx, new_cell.get(), "I1", PORT_IN);
|
||||||
add_port(ctx, new_cell.get(), "I2", 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(), "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(), "CIN", PORT_IN);
|
||||||
|
|
||||||
add_port(ctx, new_cell.get(), "CLK", 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(), "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(), "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);
|
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("PIN_TYPE")] = "0";
|
||||||
new_cell->params[ctx->id("PULLUP")] = "0";
|
new_cell->params[ctx->id("PULLUP")] = "0";
|
||||||
new_cell->params[ctx->id("NEG_TRIGGER")] = "0";
|
new_cell->params[ctx->id("NEG_TRIGGER")] = "0";
|
||||||
new_cell->params[ctx->id("IOSTANDARD")] = "SB_LVCMOS";
|
new_cell->params[ctx->id("IOSTANDARD")] = "SB_LVCMOS";
|
||||||
|
|
||||||
add_port(ctx, new_cell.get(), "PACKAGE_PIN", PORT_INOUT);
|
// 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(), "LATCH_INPUT_VALUE", PORT_IN);
|
||||||
add_port(ctx, new_cell.get(), "CLOCK_ENABLE", 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(), "INPUT_CLK", PORT_IN);
|
||||||
add_port(ctx, new_cell.get(), "OUTPUT_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(), "OUTPUT_ENABLE", PORT_IN);
|
||||||
add_port(ctx, new_cell.get(), "D_OUT_0", 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_OUT_1", PORT_IN);
|
||||||
|
//
|
||||||
add_port(ctx, new_cell.get(), "D_IN_0", PORT_OUT);
|
// 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(), "D_IN_1", PORT_OUT);
|
||||||
} else if (type == ctx->id("ICESTORM_RAM")) {
|
add_port(ctx, new_cell.get(), "I", PORT_OUT);
|
||||||
new_cell->params[ctx->id("NEG_CLK_W")] = "0";
|
add_port(ctx, new_cell.get(), "O", PORT_IN);
|
||||||
new_cell->params[ctx->id("NEG_CLK_R")] = "0";
|
// } else if (type == ctx->id("ICESTORM_RAM")) {
|
||||||
new_cell->params[ctx->id("WRITE_MODE")] = "0";
|
// new_cell->params[ctx->id("NEG_CLK_W")] = "0";
|
||||||
new_cell->params[ctx->id("READ_MODE")] = "0";
|
// new_cell->params[ctx->id("NEG_CLK_R")] = "0";
|
||||||
|
// new_cell->params[ctx->id("WRITE_MODE")] = "0";
|
||||||
add_port(ctx, new_cell.get(), "RCLK", PORT_IN);
|
// new_cell->params[ctx->id("READ_MODE")] = "0";
|
||||||
add_port(ctx, new_cell.get(), "RCLKE", PORT_IN);
|
//
|
||||||
add_port(ctx, new_cell.get(), "RE", PORT_IN);
|
// add_port(ctx, new_cell.get(), "RCLK", PORT_IN);
|
||||||
|
// add_port(ctx, new_cell.get(), "RCLKE", PORT_IN);
|
||||||
add_port(ctx, new_cell.get(), "WCLK", PORT_IN);
|
// add_port(ctx, new_cell.get(), "RE", PORT_IN);
|
||||||
add_port(ctx, new_cell.get(), "WCLKE", PORT_IN);
|
//
|
||||||
add_port(ctx, new_cell.get(), "WE", PORT_IN);
|
// add_port(ctx, new_cell.get(), "WCLK", PORT_IN);
|
||||||
|
// add_port(ctx, new_cell.get(), "WCLKE", PORT_IN);
|
||||||
for (int i = 0; i < 16; i++) {
|
// add_port(ctx, new_cell.get(), "WE", PORT_IN);
|
||||||
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);
|
// for (int i = 0; i < 16; i++) {
|
||||||
add_port(ctx, new_cell.get(), "RDATA_" + std::to_string(i), PORT_OUT);
|
// 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);
|
// for (int i = 0; i < 11; i++) {
|
||||||
}
|
// add_port(ctx, new_cell.get(), "RADDR_" + std::to_string(i), PORT_IN);
|
||||||
} else if (type == ctx->id("ICESTORM_LFOSC")) {
|
// add_port(ctx, new_cell.get(), "WADDR_" + std::to_string(i), PORT_IN);
|
||||||
add_port(ctx, new_cell.get(), "CLKLFEN", PORT_IN);
|
// }
|
||||||
add_port(ctx, new_cell.get(), "CLKLFPU", PORT_IN);
|
// } else if (type == ctx->id("ICESTORM_LFOSC")) {
|
||||||
add_port(ctx, new_cell.get(), "CLKLF", PORT_OUT);
|
// add_port(ctx, new_cell.get(), "CLKLFEN", PORT_IN);
|
||||||
add_port(ctx, new_cell.get(), "CLKLF_FABRIC", PORT_OUT);
|
// add_port(ctx, new_cell.get(), "CLKLFPU", PORT_IN);
|
||||||
} else if (type == ctx->id("ICESTORM_HFOSC")) {
|
// add_port(ctx, new_cell.get(), "CLKLF", PORT_OUT);
|
||||||
new_cell->params[ctx->id("CLKHF_DIV")] = "0b00";
|
// add_port(ctx, new_cell.get(), "CLKLF_FABRIC", PORT_OUT);
|
||||||
new_cell->params[ctx->id("TRIM_EN")] = "0b0";
|
// } else if (type == ctx->id("ICESTORM_HFOSC")) {
|
||||||
|
// new_cell->params[ctx->id("CLKHF_DIV")] = "0b00";
|
||||||
add_port(ctx, new_cell.get(), "CLKHFEN", PORT_IN);
|
// new_cell->params[ctx->id("TRIM_EN")] = "0b0";
|
||||||
add_port(ctx, new_cell.get(), "CLKHFPU", PORT_IN);
|
//
|
||||||
add_port(ctx, new_cell.get(), "CLKHF", PORT_OUT);
|
// add_port(ctx, new_cell.get(), "CLKHFEN", PORT_IN);
|
||||||
add_port(ctx, new_cell.get(), "CLKHF_FABRIC", PORT_OUT);
|
// add_port(ctx, new_cell.get(), "CLKHFPU", PORT_IN);
|
||||||
for (int i = 0; i < 10; i++)
|
// add_port(ctx, new_cell.get(), "CLKHF", PORT_OUT);
|
||||||
add_port(ctx, new_cell.get(), "TRIM" + std::to_string(i), PORT_IN);
|
// add_port(ctx, new_cell.get(), "CLKHF_FABRIC", PORT_OUT);
|
||||||
} else if (type == ctx->id("SB_GB")) {
|
// for (int i = 0; i < 10; i++)
|
||||||
add_port(ctx, new_cell.get(), "USER_SIGNAL_TO_GLOBAL_BUFFER", PORT_IN);
|
// add_port(ctx, new_cell.get(), "TRIM" + std::to_string(i), PORT_IN);
|
||||||
add_port(ctx, new_cell.get(), "GLOBAL_BUFFER_OUTPUT", PORT_OUT);
|
} else if (type == ctx->id("BUFGCTRL")) {
|
||||||
} else if (type == ctx->id("ICESTORM_SPRAM")) {
|
add_port(ctx, new_cell.get(), "I0", PORT_IN);
|
||||||
add_port(ctx, new_cell.get(), "WREN", PORT_IN);
|
add_port(ctx, new_cell.get(), "O", PORT_OUT);
|
||||||
add_port(ctx, new_cell.get(), "CHIPSELECT", PORT_IN);
|
// } else if (type == ctx->id("ICESTORM_SPRAM")) {
|
||||||
add_port(ctx, new_cell.get(), "CLOCK", PORT_IN);
|
// add_port(ctx, new_cell.get(), "WREN", PORT_IN);
|
||||||
add_port(ctx, new_cell.get(), "STANDBY", PORT_IN);
|
// add_port(ctx, new_cell.get(), "CHIPSELECT", PORT_IN);
|
||||||
add_port(ctx, new_cell.get(), "SLEEP", PORT_IN);
|
// add_port(ctx, new_cell.get(), "CLOCK", PORT_IN);
|
||||||
add_port(ctx, new_cell.get(), "POWEROFF", PORT_IN);
|
// add_port(ctx, new_cell.get(), "STANDBY", PORT_IN);
|
||||||
|
// add_port(ctx, new_cell.get(), "SLEEP", PORT_IN);
|
||||||
for (int i = 0; i < 16; i++) {
|
// add_port(ctx, new_cell.get(), "POWEROFF", PORT_IN);
|
||||||
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 < 16; i++) {
|
||||||
}
|
// add_port(ctx, new_cell.get(), "DATAIN_" + std::to_string(i), PORT_IN);
|
||||||
for (int i = 0; i < 14; i++) {
|
// add_port(ctx, new_cell.get(), "DATAOUT_" + std::to_string(i), PORT_OUT);
|
||||||
add_port(ctx, new_cell.get(), "ADDRESS_" + std::to_string(i), PORT_IN);
|
// }
|
||||||
}
|
// for (int i = 0; i < 14; i++) {
|
||||||
for (int i = 0; i < 4; i++) {
|
// add_port(ctx, new_cell.get(), "ADDRESS_" + std::to_string(i), PORT_IN);
|
||||||
add_port(ctx, new_cell.get(), "MASKWREN_" + std::to_string(i), PORT_IN);
|
// }
|
||||||
}
|
// for (int i = 0; i < 4; i++) {
|
||||||
} else if (type == ctx->id("ICESTORM_DSP")) {
|
// add_port(ctx, new_cell.get(), "MASKWREN_" + std::to_string(i), PORT_IN);
|
||||||
new_cell->params[ctx->id("NEG_TRIGGER")] = "0";
|
// }
|
||||||
|
// } else if (type == ctx->id("ICESTORM_DSP")) {
|
||||||
new_cell->params[ctx->id("C_REG")] = "0";
|
// new_cell->params[ctx->id("NEG_TRIGGER")] = "0";
|
||||||
new_cell->params[ctx->id("A_REG")] = "0";
|
//
|
||||||
new_cell->params[ctx->id("B_REG")] = "0";
|
// new_cell->params[ctx->id("C_REG")] = "0";
|
||||||
new_cell->params[ctx->id("D_REG")] = "0";
|
// new_cell->params[ctx->id("A_REG")] = "0";
|
||||||
new_cell->params[ctx->id("TOP_8x8_MULT_REG")] = "0";
|
// new_cell->params[ctx->id("B_REG")] = "0";
|
||||||
new_cell->params[ctx->id("BOT_8x8_MULT_REG")] = "0";
|
// new_cell->params[ctx->id("D_REG")] = "0";
|
||||||
new_cell->params[ctx->id("PIPELINE_16x16_MULT_REG1")] = "0";
|
// new_cell->params[ctx->id("TOP_8x8_MULT_REG")] = "0";
|
||||||
new_cell->params[ctx->id("PIPELINE_16x16_MULT_REG2")] = "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("TOPOUTPUT_SELECT")] = "0";
|
// new_cell->params[ctx->id("PIPELINE_16x16_MULT_REG2")] = "0";
|
||||||
new_cell->params[ctx->id("TOPADDSUB_LOWERINPUT")] = "0";
|
//
|
||||||
new_cell->params[ctx->id("TOPADDSUB_UPPERINPUT")] = "0";
|
// new_cell->params[ctx->id("TOPOUTPUT_SELECT")] = "0";
|
||||||
new_cell->params[ctx->id("TOPADDSUB_CARRYSELECT")] = "0";
|
// new_cell->params[ctx->id("TOPADDSUB_LOWERINPUT")] = "0";
|
||||||
|
// new_cell->params[ctx->id("TOPADDSUB_UPPERINPUT")] = "0";
|
||||||
new_cell->params[ctx->id("BOTOUTPUT_SELECT")] = "0";
|
// new_cell->params[ctx->id("TOPADDSUB_CARRYSELECT")] = "0";
|
||||||
new_cell->params[ctx->id("BOTADDSUB_LOWERINPUT")] = "0";
|
//
|
||||||
new_cell->params[ctx->id("BOTADDSUB_UPPERINPUT")] = "0";
|
// new_cell->params[ctx->id("BOTOUTPUT_SELECT")] = "0";
|
||||||
new_cell->params[ctx->id("BOTADDSUB_CARRYSELECT")] = "0";
|
// new_cell->params[ctx->id("BOTADDSUB_LOWERINPUT")] = "0";
|
||||||
|
// new_cell->params[ctx->id("BOTADDSUB_UPPERINPUT")] = "0";
|
||||||
new_cell->params[ctx->id("MODE_8x8")] = "0";
|
// new_cell->params[ctx->id("BOTADDSUB_CARRYSELECT")] = "0";
|
||||||
new_cell->params[ctx->id("A_SIGNED")] = "0";
|
//
|
||||||
new_cell->params[ctx->id("B_SIGNED")] = "0";
|
// new_cell->params[ctx->id("MODE_8x8")] = "0";
|
||||||
|
// new_cell->params[ctx->id("A_SIGNED")] = "0";
|
||||||
add_port(ctx, new_cell.get(), "CLK", PORT_IN);
|
// new_cell->params[ctx->id("B_SIGNED")] = "0";
|
||||||
add_port(ctx, new_cell.get(), "CE", PORT_IN);
|
//
|
||||||
for (int i = 0; i < 16; i++) {
|
// add_port(ctx, new_cell.get(), "CLK", PORT_IN);
|
||||||
add_port(ctx, new_cell.get(), "C_" + std::to_string(i), PORT_IN);
|
// add_port(ctx, new_cell.get(), "CE", PORT_IN);
|
||||||
add_port(ctx, new_cell.get(), "A_" + std::to_string(i), PORT_IN);
|
// for (int i = 0; i < 16; i++) {
|
||||||
add_port(ctx, new_cell.get(), "B_" + std::to_string(i), PORT_IN);
|
// add_port(ctx, new_cell.get(), "C_" + 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(), "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(), "AHOLD", PORT_IN);
|
// add_port(ctx, new_cell.get(), "D_" + std::to_string(i), 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(), "AHOLD", PORT_IN);
|
||||||
add_port(ctx, new_cell.get(), "DHOLD", 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(), "IRSTTOP", PORT_IN);
|
// add_port(ctx, new_cell.get(), "DHOLD", 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(), "IRSTTOP", PORT_IN);
|
||||||
add_port(ctx, new_cell.get(), "ORSTBOT", 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(), "OLOADTOP", PORT_IN);
|
// add_port(ctx, new_cell.get(), "ORSTBOT", PORT_IN);
|
||||||
add_port(ctx, new_cell.get(), "OLOADBOT", PORT_IN);
|
//
|
||||||
|
// add_port(ctx, new_cell.get(), "OLOADTOP", PORT_IN);
|
||||||
add_port(ctx, new_cell.get(), "ADDSUBTOP", PORT_IN);
|
// add_port(ctx, new_cell.get(), "OLOADBOT", PORT_IN);
|
||||||
add_port(ctx, new_cell.get(), "ADDSUBBOT", PORT_IN);
|
//
|
||||||
|
// add_port(ctx, new_cell.get(), "ADDSUBTOP", PORT_IN);
|
||||||
add_port(ctx, new_cell.get(), "OHOLDTOP", PORT_IN);
|
// add_port(ctx, new_cell.get(), "ADDSUBBOT", PORT_IN);
|
||||||
add_port(ctx, new_cell.get(), "OHOLDBOT", PORT_IN);
|
//
|
||||||
|
// add_port(ctx, new_cell.get(), "OHOLDTOP", PORT_IN);
|
||||||
add_port(ctx, new_cell.get(), "CI", PORT_IN);
|
// add_port(ctx, new_cell.get(), "OHOLDBOT", PORT_IN);
|
||||||
add_port(ctx, new_cell.get(), "ACCUMCI", PORT_IN);
|
//
|
||||||
add_port(ctx, new_cell.get(), "SIGNEXTIN", PORT_IN);
|
// add_port(ctx, new_cell.get(), "CI", PORT_IN);
|
||||||
|
// add_port(ctx, new_cell.get(), "ACCUMCI", PORT_IN);
|
||||||
for (int i = 0; i < 32; i++) {
|
// add_port(ctx, new_cell.get(), "SIGNEXTIN", PORT_IN);
|
||||||
add_port(ctx, new_cell.get(), "O_" + std::to_string(i), PORT_OUT);
|
//
|
||||||
}
|
// 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);
|
// add_port(ctx, new_cell.get(), "CO", PORT_OUT);
|
||||||
|
// add_port(ctx, new_cell.get(), "ACCUMCO", PORT_OUT);
|
||||||
} else if (type == ctx->id("ICESTORM_PLL")) {
|
// add_port(ctx, new_cell.get(), "SIGNEXTOUT", PORT_OUT);
|
||||||
new_cell->params[ctx->id("DELAY_ADJMODE_FB")] = "0";
|
//
|
||||||
new_cell->params[ctx->id("DELAY_ADJMODE_REL")] = "0";
|
// } else if (type == ctx->id("ICESTORM_PLL")) {
|
||||||
|
// new_cell->params[ctx->id("DELAY_ADJMODE_FB")] = "0";
|
||||||
new_cell->params[ctx->id("DIVF")] = "0";
|
// new_cell->params[ctx->id("DELAY_ADJMODE_REL")] = "0";
|
||||||
new_cell->params[ctx->id("DIVQ")] = "0";
|
//
|
||||||
new_cell->params[ctx->id("DIVR")] = "0";
|
// new_cell->params[ctx->id("DIVF")] = "0";
|
||||||
|
// new_cell->params[ctx->id("DIVQ")] = "0";
|
||||||
new_cell->params[ctx->id("FDA_FEEDBACK")] = "0";
|
// new_cell->params[ctx->id("DIVR")] = "0";
|
||||||
new_cell->params[ctx->id("FDA_RELATIVE")] = "0";
|
//
|
||||||
new_cell->params[ctx->id("FEEDBACK_PATH")] = "0";
|
// new_cell->params[ctx->id("FDA_FEEDBACK")] = "0";
|
||||||
new_cell->params[ctx->id("FILTER_RANGE")] = "0";
|
// new_cell->params[ctx->id("FDA_RELATIVE")] = "0";
|
||||||
|
// new_cell->params[ctx->id("FEEDBACK_PATH")] = "0";
|
||||||
new_cell->params[ctx->id("PLLOUT_SELECT_A")] = "0";
|
// new_cell->params[ctx->id("FILTER_RANGE")] = "0";
|
||||||
new_cell->params[ctx->id("PLLOUT_SELECT_B")] = "0";
|
//
|
||||||
|
// new_cell->params[ctx->id("PLLOUT_SELECT_A")] = "0";
|
||||||
new_cell->params[ctx->id("PLLTYPE")] = "0";
|
// new_cell->params[ctx->id("PLLOUT_SELECT_B")] = "0";
|
||||||
new_cell->params[ctx->id("SHIFTREG_DIVMODE")] = "0";
|
//
|
||||||
new_cell->params[ctx->id("TEST_MODE")] = "0";
|
// new_cell->params[ctx->id("PLLTYPE")] = "0";
|
||||||
|
// new_cell->params[ctx->id("SHIFTREG_DIVMODE")] = "0";
|
||||||
add_port(ctx, new_cell.get(), "BYPASS", PORT_IN);
|
// new_cell->params[ctx->id("TEST_MODE")] = "0";
|
||||||
add_port(ctx, new_cell.get(), "DYNAMICDELAY", PORT_IN);
|
//
|
||||||
add_port(ctx, new_cell.get(), "EXTFEEDBACK", PORT_IN);
|
// add_port(ctx, new_cell.get(), "BYPASS", PORT_IN);
|
||||||
add_port(ctx, new_cell.get(), "LATCHINPUTVALUE", PORT_IN);
|
// add_port(ctx, new_cell.get(), "DYNAMICDELAY", PORT_IN);
|
||||||
add_port(ctx, new_cell.get(), "REFERENCECLK", PORT_IN);
|
// add_port(ctx, new_cell.get(), "EXTFEEDBACK", PORT_IN);
|
||||||
add_port(ctx, new_cell.get(), "RESETB", 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(), "SCLK", PORT_IN);
|
// add_port(ctx, new_cell.get(), "RESETB", 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(), "SCLK", PORT_IN);
|
||||||
|
// add_port(ctx, new_cell.get(), "SDI", PORT_IN);
|
||||||
add_port(ctx, new_cell.get(), "LOCK", PORT_OUT);
|
// add_port(ctx, new_cell.get(), "SDI", 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(), "LOCK", PORT_OUT);
|
||||||
|
// add_port(ctx, new_cell.get(), "PLLOUT_A", PORT_OUT);
|
||||||
|
// add_port(ctx, new_cell.get(), "PLLOUT_B", PORT_OUT);
|
||||||
} else {
|
} 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;
|
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")];
|
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("I0"), lc, ctx->id("I0"));
|
||||||
replace_port(lut, ctx->id("I1"), lc, ctx->id("I1"));
|
if (get_net_or_empty(lut, ctx->id("I1")))
|
||||||
replace_port(lut, ctx->id("I2"), lc, ctx->id("I2"));
|
replace_port(lut, ctx->id("I1"), lc, ctx->id("I1"));
|
||||||
replace_port(lut, ctx->id("I3"), lc, ctx->id("I3"));
|
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) {
|
if (no_dff) {
|
||||||
replace_port(lut, ctx->id("O"), lc, ctx->id("O"));
|
replace_port(lut, ctx->id("O"), lc, ctx->id("O"));
|
||||||
lc->params[ctx->id("DFF_ENABLE")] = "0";
|
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)
|
void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_lut)
|
||||||
{
|
{
|
||||||
lc->params[ctx->id("DFF_ENABLE")] = "1";
|
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();
|
auto citer = config.begin();
|
||||||
replace_port(dff, ctx->id("C"), lc, ctx->id("CLK"));
|
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 (citer != config.end()) {
|
||||||
if ((config.end() - citer) >= 2) {
|
if (*citer == 'C' || *citer == 'P')
|
||||||
char c = *(citer++);
|
|
||||||
NPNR_ASSERT(c == 'S');
|
|
||||||
lc->params[ctx->id("ASYNC_SR")] = "0";
|
|
||||||
} else {
|
|
||||||
lc->params[ctx->id("ASYNC_SR")] = "1";
|
lc->params[ctx->id("ASYNC_SR")] = "1";
|
||||||
}
|
else
|
||||||
|
lc->params[ctx->id("ASYNC_SR")] = "0";
|
||||||
|
|
||||||
if (*citer == 'S') {
|
if (*citer == 'S') {
|
||||||
citer++;
|
citer++;
|
||||||
replace_port(dff, ctx->id("S"), lc, ctx->id("SR"));
|
replace_port(dff, ctx->id("S"), lc, ctx->id("SR"));
|
||||||
lc->params[ctx->id("SET_NORESET")] = "1";
|
lc->params[ctx->id("SET_NORESET")] = "1";
|
||||||
} else {
|
} else if (*citer == 'R') {
|
||||||
NPNR_ASSERT(*citer == 'R');
|
|
||||||
citer++;
|
citer++;
|
||||||
replace_port(dff, ctx->id("R"), lc, ctx->id("SR"));
|
replace_port(dff, ctx->id("R"), lc, ctx->id("SR"));
|
||||||
lc->params[ctx->id("SET_NORESET")] = "0";
|
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());
|
NPNR_ASSERT(citer == config.end());
|
||||||
|
|
||||||
if (pass_thru_lut) {
|
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("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)
|
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"));
|
auto pu_attr = nxio->attrs.find(ctx->id("PULLUP"));
|
||||||
if (pu_attr != nxio->attrs.end())
|
if (pu_attr != nxio->attrs.end())
|
||||||
sbio->params[ctx->id("PULLUP")] = pu_attr->second;
|
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")) {
|
} else if (nxio->type == ctx->id("$nextpnr_obuf")) {
|
||||||
sbio->params[ctx->id("PIN_TYPE")] = "25";
|
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")) {
|
} else if (nxio->type == ctx->id("$nextpnr_iobuf")) {
|
||||||
// N.B. tristate will be dealt with below
|
// N.B. tristate will be dealt with below
|
||||||
sbio->params[ctx->id("PIN_TYPE")] = "25";
|
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"));
|
||||||
replace_port(nxio, ctx->id("O"), sbio, ctx->id("D_IN_0"));
|
replace_port(nxio, ctx->id("O"), sbio, ctx->id("I"));
|
||||||
} else {
|
} else {
|
||||||
NPNR_ASSERT(false);
|
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(
|
CellInfo *tbuf = net_driven_by(
|
||||||
ctx, donet, [](const Context *ctx, const CellInfo *cell) { return cell->type == ctx->id("$_TBUF_"); },
|
ctx, donet, [](const Context *ctx, const CellInfo *cell) { return cell->type == ctx->id("$_TBUF_"); },
|
||||||
ctx->id("Y"));
|
ctx->id("Y"));
|
||||||
if (tbuf) {
|
if (tbuf) {
|
||||||
sbio->params[ctx->id("PIN_TYPE")] = "41";
|
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"));
|
replace_port(tbuf, ctx->id("E"), sbio, ctx->id("OUTPUT_ENABLE"));
|
||||||
ctx->nets.erase(donet->name);
|
ctx->nets.erase(donet->name);
|
||||||
if (!donet->users.empty())
|
if (!donet->users.empty())
|
||||||
|
16
xc7/cells.h
16
xc7/cells.h
@ -30,31 +30,23 @@ NEXTPNR_NAMESPACE_BEGIN
|
|||||||
std::unique_ptr<CellInfo> create_ice_cell(Context *ctx, IdString type, std::string name = "");
|
std::unique_ptr<CellInfo> create_ice_cell(Context *ctx, IdString type, std::string name = "");
|
||||||
|
|
||||||
// Return true if a cell is a LUT
|
// 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
|
// Return true if a cell is a flipflop
|
||||||
inline bool is_ff(const BaseCtx *ctx, const CellInfo *cell)
|
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") ||
|
return cell->type == id_FDRE || cell->type == id_FDSE || cell->type == id_FDCE || cell->type == id_FDPE;
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool is_carry(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_CARRY"); }
|
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
|
// 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"); }
|
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
|
// 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
|
// Return true if a cell is a RAM
|
||||||
inline bool is_ram(const BaseCtx *ctx, const CellInfo *cell)
|
inline bool is_ram(const BaseCtx *ctx, const CellInfo *cell)
|
||||||
|
@ -435,3 +435,21 @@ X(ICESTORM_SPRAM)
|
|||||||
X(DFF_ENABLE)
|
X(DFF_ENABLE)
|
||||||
X(CARRY_ENABLE)
|
X(CARRY_ENABLE)
|
||||||
X(NEG_CLK)
|
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?
|
||||||
|
36
xc7/pack.cc
36
xc7/pack.cc
@ -42,7 +42,7 @@ static void pack_lut_lutffs(Context *ctx)
|
|||||||
if (ctx->verbose)
|
if (ctx->verbose)
|
||||||
log_info("cell '%s' is of type '%s'\n", ci->name.c_str(ctx), ci->type.c_str(ctx));
|
log_info("cell '%s' is of type '%s'\n", ci->name.c_str(ctx), ci->type.c_str(ctx));
|
||||||
if (is_lut(ctx, ci)) {
|
if (is_lut(ctx, ci)) {
|
||||||
std::unique_ptr<CellInfo> packed = create_ice_cell(ctx, ctx->id("ICESTORM_LC"), ci->name.str(ctx) + "_LC");
|
std::unique_ptr<CellInfo> 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()));
|
std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(packed->attrs, packed->attrs.begin()));
|
||||||
packed_cells.insert(ci->name);
|
packed_cells.insert(ci->name);
|
||||||
if (ctx->verbose)
|
if (ctx->verbose)
|
||||||
@ -97,7 +97,7 @@ static void pack_nonlut_ffs(Context *ctx)
|
|||||||
CellInfo *ci = cell.second;
|
CellInfo *ci = cell.second;
|
||||||
if (is_ff(ctx, ci)) {
|
if (is_ff(ctx, ci)) {
|
||||||
std::unique_ptr<CellInfo> packed =
|
std::unique_ptr<CellInfo> 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()));
|
std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(packed->attrs, packed->attrs.begin()));
|
||||||
if (ctx->verbose)
|
if (ctx->verbose)
|
||||||
log_info("packed cell %s into %s\n", ci->name.c_str(ctx), packed->name.c_str(ctx));
|
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 {
|
} else {
|
||||||
// No LC to pack into matching I0/I1, insert a new one
|
// No LC to pack into matching I0/I1, insert a new one
|
||||||
std::unique_ptr<CellInfo> created_lc =
|
std::unique_ptr<CellInfo> 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();
|
carry_lc = created_lc.get();
|
||||||
created_lc->ports.at(ctx->id("I1")).net = i0_net;
|
created_lc->ports.at(ctx->id("I1")).net = i0_net;
|
||||||
if (i0_net) {
|
if (i0_net) {
|
||||||
@ -331,7 +331,7 @@ static void pack_constants(Context *ctx)
|
|||||||
{
|
{
|
||||||
log_info("Packing constants..\n");
|
log_info("Packing constants..\n");
|
||||||
|
|
||||||
std::unique_ptr<CellInfo> gnd_cell = create_ice_cell(ctx, ctx->id("ICESTORM_LC"), "$PACKER_GND");
|
std::unique_ptr<CellInfo> gnd_cell = create_ice_cell(ctx, ctx->id("XC7_LC"), "$PACKER_GND");
|
||||||
gnd_cell->params[ctx->id("LUT_INIT")] = "0";
|
gnd_cell->params[ctx->id("LUT_INIT")] = "0";
|
||||||
std::unique_ptr<NetInfo> gnd_net = std::unique_ptr<NetInfo>(new NetInfo);
|
std::unique_ptr<NetInfo> gnd_net = std::unique_ptr<NetInfo>(new NetInfo);
|
||||||
gnd_net->name = ctx->id("$PACKER_GND_NET");
|
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_net->driver.port = ctx->id("O");
|
||||||
gnd_cell->ports.at(ctx->id("O")).net = gnd_net.get();
|
gnd_cell->ports.at(ctx->id("O")).net = gnd_net.get();
|
||||||
|
|
||||||
std::unique_ptr<CellInfo> vcc_cell = create_ice_cell(ctx, ctx->id("ICESTORM_LC"), "$PACKER_VCC");
|
std::unique_ptr<CellInfo> vcc_cell = create_ice_cell(ctx, ctx->id("XC7_LC"), "$PACKER_VCC");
|
||||||
vcc_cell->params[ctx->id("LUT_INIT")] = "1";
|
vcc_cell->params[ctx->id("LUT_INIT")] = "1";
|
||||||
std::unique_ptr<NetInfo> vcc_net = std::unique_ptr<NetInfo>(new NetInfo);
|
std::unique_ptr<NetInfo> vcc_net = std::unique_ptr<NetInfo>(new NetInfo);
|
||||||
vcc_net->name = ctx->id("$PACKER_VCC_NET");
|
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);
|
sb = net_only_drives(ctx, ci->ports.at(ctx->id("I")).net, is_sb_io, ctx->id("PACKAGE_PIN"), true, ci);
|
||||||
}
|
}
|
||||||
if (sb != nullptr) {
|
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
|
// 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));
|
ci->type.c_str(ctx), ci->name.c_str(ctx));
|
||||||
NetInfo *net = sb->ports.at(ctx->id("PACKAGE_PIN")).net;
|
NetInfo *net = sb->ports.at(ctx->id("PACKAGE_PIN")).net;
|
||||||
if (net != nullptr) {
|
if (net != nullptr) {
|
||||||
@ -421,9 +421,9 @@ static void pack_io(Context *ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Create a SB_IO buffer
|
// Create a IOBUF buffer
|
||||||
std::unique_ptr<CellInfo> ice_cell =
|
std::unique_ptr<CellInfo> 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());
|
nxio_to_sb(ctx, ci, ice_cell.get());
|
||||||
new_cells.push_back(std::move(ice_cell));
|
new_cells.push_back(std::move(ice_cell));
|
||||||
sb = new_cells.back().get();
|
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)
|
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::string glb_name = net->name.str(ctx) + std::string("_$glb_") + (is_reset ? "sr" : (is_cen ? "ce" : "clk"));
|
||||||
std::unique_ptr<CellInfo> gb = create_ice_cell(ctx, ctx->id("SB_GB"), "$gbuf_" + glb_name);
|
std::unique_ptr<CellInfo> gb = create_ice_cell(ctx, id_BUFGCTRL, "$bufg_" + glb_name);
|
||||||
gb->ports[ctx->id("USER_SIGNAL_TO_GLOBAL_BUFFER")].net = net;
|
gb->ports[ctx->id("I0")].net = net;
|
||||||
PortRef pr;
|
PortRef pr;
|
||||||
pr.cell = gb.get();
|
pr.cell = gb.get();
|
||||||
pr.port = ctx->id("USER_SIGNAL_TO_GLOBAL_BUFFER");
|
pr.port = ctx->id("I0");
|
||||||
net->users.push_back(pr);
|
net->users.push_back(pr);
|
||||||
|
|
||||||
pr.cell = gb.get();
|
pr.cell = gb.get();
|
||||||
pr.port = ctx->id("GLOBAL_BUFFER_OUTPUT");
|
pr.port = ctx->id("O");
|
||||||
std::unique_ptr<NetInfo> glbnet = std::unique_ptr<NetInfo>(new NetInfo());
|
std::unique_ptr<NetInfo> glbnet = std::unique_ptr<NetInfo>(new NetInfo());
|
||||||
glbnet->name = ctx->id(glb_name);
|
glbnet->name = ctx->id(glb_name);
|
||||||
glbnet->driver = pr;
|
glbnet->driver = pr;
|
||||||
gb->ports[ctx->id("GLOBAL_BUFFER_OUTPUT")].net = glbnet.get();
|
gb->ports[ctx->id("O")].net = glbnet.get();
|
||||||
std::vector<PortRef> keep_users;
|
std::vector<PortRef> keep_users;
|
||||||
for (auto user : net->users) {
|
for (auto user : net->users) {
|
||||||
if (is_clock_port(ctx, user) || (is_reset && is_reset_port(ctx, user)) ||
|
if (is_clock_port(ctx, user) || (is_reset && is_reset_port(ctx, user)) ||
|
||||||
@ -582,7 +582,7 @@ static std::unique_ptr<CellInfo> spliceLUT(Context *ctx, CellInfo *ci, IdString
|
|||||||
NPNR_ASSERT(port.net != nullptr);
|
NPNR_ASSERT(port.net != nullptr);
|
||||||
|
|
||||||
// Create pass-through LUT.
|
// Create pass-through LUT.
|
||||||
std::unique_ptr<CellInfo> pt = create_ice_cell(ctx, ctx->id("ICESTORM_LC"),
|
std::unique_ptr<CellInfo> pt = create_ice_cell(ctx, ctx->id("XC7_LC"),
|
||||||
ci->name.str(ctx) + "$nextpnr_" + portId.str(ctx) + "_lut_through");
|
ci->name.str(ctx) + "$nextpnr_" + portId.str(ctx) + "_lut_through");
|
||||||
pt->params[ctx->id("LUT_INIT")] = "65280"; // output is always I3
|
pt->params[ctx->id("LUT_INIT")] = "65280"; // output is always I3
|
||||||
|
|
||||||
@ -596,7 +596,7 @@ static std::unique_ptr<CellInfo> spliceLUT(Context *ctx, CellInfo *ci, IdString
|
|||||||
// New users of the original cell's port
|
// New users of the original cell's port
|
||||||
std::vector<PortRef> new_users;
|
std::vector<PortRef> new_users;
|
||||||
for (const auto &user : port.net->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);
|
new_users.push_back(user);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -823,7 +823,7 @@ static void pack_special(Context *ctx)
|
|||||||
unsigned int lut_count = 0;
|
unsigned int lut_count = 0;
|
||||||
for (const auto &user : port.net->users) {
|
for (const auto &user : port.net->users) {
|
||||||
NPNR_ASSERT(user.cell != nullptr);
|
NPNR_ASSERT(user.cell != nullptr);
|
||||||
if (user.cell->type == ctx->id("ICESTORM_LC")) {
|
if (user.cell->type == ctx->id("XC7_LC")) {
|
||||||
found_lut = true;
|
found_lut = true;
|
||||||
lut_count++;
|
lut_count++;
|
||||||
} else {
|
} else {
|
||||||
@ -856,7 +856,7 @@ static void pack_special(Context *ctx)
|
|||||||
int z = 0;
|
int z = 0;
|
||||||
for (const auto &user : port.net->users) {
|
for (const auto &user : port.net->users) {
|
||||||
NPNR_ASSERT(user.cell != nullptr);
|
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
|
// TODO(q3k): handle when the Bel might be already the
|
||||||
// target of another constraint.
|
// target of another constraint.
|
||||||
|
Loading…
Reference in New Issue
Block a user