aboutsummaryrefslogtreecommitdiffstats
path: root/ice40
diff options
context:
space:
mode:
authorEddie Hung <eddie.hung+gitlab@gmail.com>2018-07-15 19:22:57 +0000
committerEddie Hung <eddie.hung+gitlab@gmail.com>2018-07-15 19:22:57 +0000
commit0bae7f5606b15591a23fb63da1c5ff6f93b40747 (patch)
tree7b0760fa1e5c837f9b43cf1c97fa9f55973a169b /ice40
parent1457a6453c11af34a73460868833a9462e987854 (diff)
parent21bf78dae9ef95e65b549c60061bce9790b1b611 (diff)
downloadnextpnr-0bae7f5606b15591a23fb63da1c5ff6f93b40747.tar.gz
nextpnr-0bae7f5606b15591a23fb63da1c5ff6f93b40747.tar.bz2
nextpnr-0bae7f5606b15591a23fb63da1c5ff6f93b40747.zip
Merge branch 'master' into 'master'
Master See merge request eddiehung/nextpnr!1
Diffstat (limited to 'ice40')
-rw-r--r--ice40/arch.cc293
-rw-r--r--ice40/arch.h46
-rw-r--r--ice40/arch_pybindings.cc13
-rw-r--r--ice40/archdefs.h67
-rw-r--r--ice40/bitstream.cc5
-rw-r--r--ice40/chipdb.py41
-rw-r--r--ice40/family.cmake6
-rw-r--r--ice40/gfx.cc488
-rw-r--r--ice40/gfx.h474
-rw-r--r--ice40/main.cc166
-rw-r--r--ice40/pack.cc4
-rw-r--r--ice40/pack.h32
12 files changed, 1427 insertions, 208 deletions
diff --git a/ice40/arch.cc b/ice40/arch.cc
index 72f9c1f3..adc37dbd 100644
--- a/ice40/arch.cc
+++ b/ice40/arch.cc
@@ -19,9 +19,13 @@
#include <algorithm>
#include <cmath>
+#include "gfx.h"
#include "log.h"
#include "nextpnr.h"
+#include "placer1.h"
+#include "router1.h"
#include "util.h"
+
NEXTPNR_NAMESPACE_BEGIN
// -----------------------------------------------------------------------
@@ -365,6 +369,49 @@ std::string Arch::getBelPackagePin(BelId bel) const
}
return "";
}
+
+// -----------------------------------------------------------------------
+
+GroupId Arch::getGroupByName(IdString name) const
+{
+ for (auto g : getGroups())
+ if (getGroupName(g) == name)
+ return g;
+ return GroupId();
+}
+
+IdString Arch::getGroupName(GroupId group) const { return IdString(); }
+
+std::vector<GroupId> Arch::getGroups() const
+{
+ std::vector<GroupId> ret;
+ return ret;
+}
+
+std::vector<BelId> Arch::getGroupBels(GroupId group) const
+{
+ std::vector<BelId> ret;
+ return ret;
+}
+
+std::vector<WireId> Arch::getGroupWires(GroupId group) const
+{
+ std::vector<WireId> ret;
+ return ret;
+}
+
+std::vector<PipId> Arch::getGroupPips(GroupId group) const
+{
+ std::vector<PipId> ret;
+ return ret;
+}
+
+std::vector<GroupId> Arch::getGroupGroups(GroupId group) const
+{
+ std::vector<GroupId> ret;
+ return ret;
+}
+
// -----------------------------------------------------------------------
void Arch::estimatePosition(BelId bel, int &x, int &y, bool &gb) const
@@ -398,100 +445,206 @@ delay_t Arch::estimateDelay(WireId src, WireId dst) const
// -----------------------------------------------------------------------
-std::vector<GraphicElement> Arch::getFrameGraphics() const
+bool Arch::place() { return placer1(getCtx()); }
+
+bool Arch::route() { return router1(getCtx()); }
+
+// -----------------------------------------------------------------------
+
+DecalXY Arch::getFrameDecal() const
{
- std::vector<GraphicElement> ret;
+ DecalXY decalxy;
+ decalxy.decal.type = DecalId::TYPE_FRAME;
+ decalxy.decal.active = true;
+ return decalxy;
+}
- for (int x = 0; x <= chip_info->width; x++)
- for (int y = 0; y <= chip_info->height; y++) {
- GraphicElement el;
- el.type = GraphicElement::G_LINE;
- el.x1 = x - 0.05, el.x2 = x + 0.05, el.y1 = y, el.y2 = y, el.z = 0;
- ret.push_back(el);
- el.x1 = x, el.x2 = x, el.y1 = y - 0.05, el.y2 = y + 0.05, el.z = 0;
- ret.push_back(el);
- }
+DecalXY Arch::getBelDecal(BelId bel) const
+{
+ DecalXY decalxy;
+ decalxy.decal.type = DecalId::TYPE_BEL;
+ decalxy.decal.index = bel.index;
+ decalxy.decal.active = bel_to_cell.at(bel.index) != IdString();
+ return decalxy;
+}
- return ret;
+DecalXY Arch::getWireDecal(WireId wire) const
+{
+ DecalXY decalxy;
+ decalxy.decal.type = DecalId::TYPE_WIRE;
+ decalxy.decal.index = wire.index;
+ decalxy.decal.active = wire_to_net.at(wire.index) != IdString();
+ return decalxy;
}
-std::vector<GraphicElement> Arch::getBelGraphics(BelId bel) const
+DecalXY Arch::getPipDecal(PipId pip) const
+{
+ DecalXY decalxy;
+ decalxy.decal.type = DecalId::TYPE_PIP;
+ decalxy.decal.index = pip.index;
+ decalxy.decal.active = pip_to_net.at(pip.index) != IdString();
+ return decalxy;
+};
+
+DecalXY Arch::getGroupDecal(GroupId group) const
+{
+ DecalXY decalxy;
+ decalxy.decal.type = DecalId::TYPE_GROUP;
+ decalxy.decal.index = (group.type << 16) | (group.x << 8) | (group.y);
+ decalxy.decal.active = true;
+ return decalxy;
+};
+
+std::vector<GraphicElement> Arch::getDecalGraphics(DecalId decal) const
{
std::vector<GraphicElement> ret;
- auto bel_type = getBelType(bel);
-
- if (bel_type == TYPE_ICESTORM_LC) {
- GraphicElement el;
- el.type = GraphicElement::G_BOX;
- el.x1 = chip_info->bel_data[bel.index].x + 0.1;
- el.x2 = chip_info->bel_data[bel.index].x + 0.9;
- el.y1 = chip_info->bel_data[bel.index].y + 0.10 + (chip_info->bel_data[bel.index].z) * (0.8 / 8);
- el.y2 = chip_info->bel_data[bel.index].y + 0.18 + (chip_info->bel_data[bel.index].z) * (0.8 / 8);
- el.z = 0;
- ret.push_back(el);
+ if (decal.type == DecalId::TYPE_FRAME) {
+ for (int x = 0; x <= chip_info->width; x++)
+ for (int y = 0; y <= chip_info->height; y++) {
+ GraphicElement el;
+ el.type = GraphicElement::G_LINE;
+ el.x1 = x - 0.05, el.x2 = x + 0.05, el.y1 = y, el.y2 = y, el.z = 0;
+ ret.push_back(el);
+ el.x1 = x, el.x2 = x, el.y1 = y - 0.05, el.y2 = y + 0.05, el.z = 0;
+ ret.push_back(el);
+ }
+ }
+
+ if (decal.type == DecalId::TYPE_WIRE) {
+ WireId wire;
+ wire.index = decal.index;
+
+ int n = chip_info->wire_data[wire.index].num_segments;
+ const WireSegmentPOD *p = chip_info->wire_data[wire.index].segments.get();
+
+ GraphicElement::style_t style = decal.active ? GraphicElement::G_ACTIVE : GraphicElement::G_INACTIVE;
+
+ for (int i = 0; i < n; i++)
+ gfxTileWire(ret, p[i].x, p[i].y, GfxTileWireId(p[i].index), style);
}
- if (bel_type == TYPE_SB_IO) {
- if (chip_info->bel_data[bel.index].x == 0 || chip_info->bel_data[bel.index].x == chip_info->width - 1) {
+ if (decal.type == DecalId::TYPE_BEL) {
+ BelId bel;
+ bel.index = decal.index;
+
+ auto bel_type = getBelType(bel);
+
+ if (bel_type == TYPE_ICESTORM_LC) {
GraphicElement el;
el.type = GraphicElement::G_BOX;
- el.x1 = chip_info->bel_data[bel.index].x + 0.1;
- el.x2 = chip_info->bel_data[bel.index].x + 0.9;
- if (chip_info->bel_data[bel.index].z == 0) {
- el.y1 = chip_info->bel_data[bel.index].y + 0.10;
- el.y2 = chip_info->bel_data[bel.index].y + 0.45;
- } else {
- el.y1 = chip_info->bel_data[bel.index].y + 0.55;
- el.y2 = chip_info->bel_data[bel.index].y + 0.90;
- }
+ el.style = decal.active ? GraphicElement::G_ACTIVE : GraphicElement::G_INACTIVE;
+ el.x1 = chip_info->bel_data[bel.index].x + logic_cell_x1;
+ el.x2 = chip_info->bel_data[bel.index].x + logic_cell_x2;
+ el.y1 = chip_info->bel_data[bel.index].y + logic_cell_y1 +
+ (chip_info->bel_data[bel.index].z) * logic_cell_pitch;
+ el.y2 = chip_info->bel_data[bel.index].y + logic_cell_y2 +
+ (chip_info->bel_data[bel.index].z) * logic_cell_pitch;
el.z = 0;
ret.push_back(el);
- } else {
- GraphicElement el;
- el.type = GraphicElement::G_BOX;
+
if (chip_info->bel_data[bel.index].z == 0) {
- el.x1 = chip_info->bel_data[bel.index].x + 0.10;
- el.x2 = chip_info->bel_data[bel.index].x + 0.45;
+ int tx = chip_info->bel_data[bel.index].x;
+ int ty = chip_info->bel_data[bel.index].y;
+
+ // Main switchbox
+ GraphicElement main_sw;
+ main_sw.type = GraphicElement::G_BOX;
+ main_sw.style = GraphicElement::G_FRAME;
+ main_sw.x1 = tx + main_swbox_x1;
+ main_sw.x2 = tx + main_swbox_x2;
+ main_sw.y1 = ty + main_swbox_y1;
+ main_sw.y2 = ty + main_swbox_y2;
+ ret.push_back(main_sw);
+
+ // Local tracks to LUT input switchbox
+ GraphicElement local_sw;
+ local_sw.type = GraphicElement::G_BOX;
+ local_sw.style = GraphicElement::G_FRAME;
+ local_sw.x1 = tx + local_swbox_x1;
+ local_sw.x2 = tx + local_swbox_x2;
+ local_sw.y1 = ty + local_swbox_y1;
+ local_sw.y2 = ty + local_swbox_y2;
+ local_sw.z = 0;
+ ret.push_back(local_sw);
+ }
+ }
+
+ if (bel_type == TYPE_SB_IO) {
+ if (chip_info->bel_data[bel.index].x == 0 || chip_info->bel_data[bel.index].x == chip_info->width - 1) {
+ GraphicElement el;
+ el.type = GraphicElement::G_BOX;
+ el.x1 = chip_info->bel_data[bel.index].x + 0.1;
+ el.x2 = chip_info->bel_data[bel.index].x + 0.9;
+ if (chip_info->bel_data[bel.index].z == 0) {
+ el.y1 = chip_info->bel_data[bel.index].y + 0.10;
+ el.y2 = chip_info->bel_data[bel.index].y + 0.45;
+ } else {
+ el.y1 = chip_info->bel_data[bel.index].y + 0.55;
+ el.y2 = chip_info->bel_data[bel.index].y + 0.90;
+ }
+ el.z = 0;
+ ret.push_back(el);
} else {
- el.x1 = chip_info->bel_data[bel.index].x + 0.55;
- el.x2 = chip_info->bel_data[bel.index].x + 0.90;
+ GraphicElement el;
+ el.type = GraphicElement::G_BOX;
+ if (chip_info->bel_data[bel.index].z == 0) {
+ el.x1 = chip_info->bel_data[bel.index].x + 0.10;
+ el.x2 = chip_info->bel_data[bel.index].x + 0.45;
+ } else {
+ el.x1 = chip_info->bel_data[bel.index].x + 0.55;
+ el.x2 = chip_info->bel_data[bel.index].x + 0.90;
+ }
+ el.y1 = chip_info->bel_data[bel.index].y + 0.1;
+ el.y2 = chip_info->bel_data[bel.index].y + 0.9;
+ el.z = 0;
+ ret.push_back(el);
}
- el.y1 = chip_info->bel_data[bel.index].y + 0.1;
- el.y2 = chip_info->bel_data[bel.index].y + 0.9;
- el.z = 0;
- ret.push_back(el);
}
- }
- if (bel_type == TYPE_ICESTORM_RAM) {
- GraphicElement el;
- el.type = GraphicElement::G_BOX;
- el.x1 = chip_info->bel_data[bel.index].x + 0.1;
- el.x2 = chip_info->bel_data[bel.index].x + 0.9;
- el.y1 = chip_info->bel_data[bel.index].y + 0.1;
- el.y2 = chip_info->bel_data[bel.index].y + 1.9;
- el.z = 0;
- ret.push_back(el);
+ if (bel_type == TYPE_ICESTORM_RAM) {
+ for (int i = 0; i < 2; i++)
+ {
+ int tx = chip_info->bel_data[bel.index].x;
+ int ty = chip_info->bel_data[bel.index].y + i;
+
+ GraphicElement el;
+ el.type = GraphicElement::G_BOX;
+ el.style = decal.active ? GraphicElement::G_ACTIVE : GraphicElement::G_INACTIVE;
+ el.x1 = chip_info->bel_data[bel.index].x + logic_cell_x1;
+ el.x2 = chip_info->bel_data[bel.index].x + logic_cell_x2;
+ el.y1 = chip_info->bel_data[bel.index].y + logic_cell_y1;
+ el.y2 = chip_info->bel_data[bel.index].y + logic_cell_y2 + 7*logic_cell_pitch;
+ el.z = 0;
+ ret.push_back(el);
+
+ // Main switchbox
+ GraphicElement main_sw;
+ main_sw.type = GraphicElement::G_BOX;
+ main_sw.style = GraphicElement::G_FRAME;
+ main_sw.x1 = tx + main_swbox_x1;
+ main_sw.x2 = tx + main_swbox_x2;
+ main_sw.y1 = ty + main_swbox_y1;
+ main_sw.y2 = ty + main_swbox_y2;
+ ret.push_back(main_sw);
+
+ // Local tracks to LUT input switchbox
+ GraphicElement local_sw;
+ local_sw.type = GraphicElement::G_BOX;
+ local_sw.style = GraphicElement::G_FRAME;
+ local_sw.x1 = tx + local_swbox_x1;
+ local_sw.x2 = tx + local_swbox_x2;
+ local_sw.y1 = ty + local_swbox_y1;
+ local_sw.y2 = ty + local_swbox_y2;
+ local_sw.z = 0;
+ ret.push_back(local_sw);
+ }
+ }
}
return ret;
}
-std::vector<GraphicElement> Arch::getWireGraphics(WireId wire) const
-{
- std::vector<GraphicElement> ret;
- // FIXME
- return ret;
-}
-
-std::vector<GraphicElement> Arch::getPipGraphics(PipId pip) const
-{
- std::vector<GraphicElement> ret;
- // FIXME
- return ret;
-};
-
// -----------------------------------------------------------------------
bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, delay_t &delay) const
diff --git a/ice40/arch.h b/ice40/arch.h
index 43aa0829..a02e0ced 100644
--- a/ice40/arch.h
+++ b/ice40/arch.h
@@ -70,6 +70,11 @@ NPNR_PACKED_STRUCT(struct PipInfoPOD {
int32_t switch_index;
});
+NPNR_PACKED_STRUCT(struct WireSegmentPOD {
+ int8_t x, y;
+ int16_t index;
+});
+
NPNR_PACKED_STRUCT(struct WireInfoPOD {
RelPtr<char> name;
int32_t num_uphill, num_downhill;
@@ -79,6 +84,9 @@ NPNR_PACKED_STRUCT(struct WireInfoPOD {
BelPortPOD bel_uphill;
RelPtr<BelPortPOD> bels_downhill;
+ int32_t num_segments;
+ RelPtr<WireSegmentPOD> segments;
+
int8_t x, y;
WireType type;
int8_t padding_0;
@@ -515,9 +523,6 @@ struct Arch : BaseCtx
// -------------------------------------------------
PipId getPipByName(IdString name) const;
- IdString getPipName(PipId pip) const;
-
- uint32_t getPipChecksum(PipId pip) const { return pip.index; }
void bindPip(PipId pip, IdString net, PlaceStrength strength)
{
@@ -577,6 +582,10 @@ struct Arch : BaseCtx
range.e.cursor = chip_info->num_pips;
return range;
}
+
+ IdString getPipName(PipId pip) const;
+
+ uint32_t getPipChecksum(PipId pip) const { return pip.index; }
WireId getPipSrcWire(PipId pip) const
{
@@ -634,6 +643,16 @@ struct Arch : BaseCtx
// -------------------------------------------------
+ GroupId getGroupByName(IdString name) const;
+ IdString getGroupName(GroupId group) const;
+ std::vector<GroupId> getGroups() const;
+ std::vector<BelId> getGroupBels(GroupId group) const;
+ std::vector<WireId> getGroupWires(GroupId group) const;
+ std::vector<PipId> getGroupPips(GroupId group) const;
+ std::vector<GroupId> getGroupGroups(GroupId group) const;
+
+ // -------------------------------------------------
+
void estimatePosition(BelId bel, int &x, int &y, bool &gb) const;
delay_t estimateDelay(WireId src, WireId dst) const;
delay_t getDelayEpsilon() const { return 20; }
@@ -643,16 +662,19 @@ struct Arch : BaseCtx
// -------------------------------------------------
- std::vector<GraphicElement> getFrameGraphics() const;
- std::vector<GraphicElement> getBelGraphics(BelId bel) const;
- std::vector<GraphicElement> getWireGraphics(WireId wire) const;
- std::vector<GraphicElement> getPipGraphics(PipId pip) const;
+ bool pack();
+ bool place();
+ bool route();
+
+ // -------------------------------------------------
+
+ std::vector<GraphicElement> getDecalGraphics(DecalId decal) const;
- bool allGraphicsReload = false;
- bool frameGraphicsReload = false;
- std::unordered_set<BelId> belGraphicsReload;
- std::unordered_set<WireId> wireGraphicsReload;
- std::unordered_set<PipId> pipGraphicsReload;
+ DecalXY getFrameDecal() const;
+ DecalXY getBelDecal(BelId bel) const;
+ DecalXY getWireDecal(WireId wire) const;
+ DecalXY getPipDecal(PipId pip) const;
+ DecalXY getGroupDecal(GroupId group) const;
// -------------------------------------------------
diff --git a/ice40/arch_pybindings.cc b/ice40/arch_pybindings.cc
index 67a37983..fd5109b4 100644
--- a/ice40/arch_pybindings.cc
+++ b/ice40/arch_pybindings.cc
@@ -58,7 +58,10 @@ void arch_wrap_python()
auto arch_cls = class_<Arch, Arch *, bases<BaseCtx>, boost::noncopyable>("Arch", init<ArchArgs>());
auto ctx_cls = class_<Context, Context *, bases<Arch>, boost::noncopyable>("Context", no_init)
- .def("checksum", &Context::checksum);
+ .def("checksum", &Context::checksum)
+ .def("pack", &Context::pack)
+ .def("place", &Context::place)
+ .def("route", &Context::route);
fn_wrapper_1a<Context, decltype(&Context::getBelType), &Context::getBelType, conv_to_str<BelType>,
conv_from_str<BelId>>::def_wrap(ctx_cls, "getBelType");
@@ -75,7 +78,7 @@ void arch_wrap_python()
fn_wrapper_1a<Context, decltype(&Context::getConflictingBelCell), &Context::getConflictingBelCell,
conv_to_str<IdString>, conv_from_str<BelId>>::def_wrap(ctx_cls, "getConflictingBelCell");
fn_wrapper_0a<Context, decltype(&Context::getBels), &Context::getBels, wrap_context<BelRange>>::def_wrap(ctx_cls,
- "getBels");
+ "getBels");
fn_wrapper_1a<Context, decltype(&Context::getBelsAtSameTile), &Context::getBelsAtSameTile, wrap_context<BelRange>,
conv_from_str<BelId>>::def_wrap(ctx_cls, "getBelsAtSameTile");
@@ -139,15 +142,15 @@ void arch_wrap_python()
fn_wrapper_0a<Context, decltype(&Context::getChipName), &Context::getChipName, pass_through<std::string>>::def_wrap(
ctx_cls, "getChipName");
fn_wrapper_0a<Context, decltype(&Context::archId), &Context::archId, conv_to_str<IdString>>::def_wrap(ctx_cls,
- "archId");
+ "archId");
typedef std::unordered_map<IdString, std::unique_ptr<CellInfo>> CellMap;
typedef std::unordered_map<IdString, std::unique_ptr<NetInfo>> NetMap;
readonly_wrapper<Context, decltype(&Context::cells), &Context::cells, wrap_context<CellMap &>>::def_wrap(ctx_cls,
- "cells");
+ "cells");
readonly_wrapper<Context, decltype(&Context::nets), &Context::nets, wrap_context<NetMap &>>::def_wrap(ctx_cls,
- "nets");
+ "nets");
WRAP_RANGE(Bel, conv_to_str<BelId>);
WRAP_RANGE(Wire, conv_to_str<WireId>);
WRAP_RANGE(AllPip, conv_to_str<PipId>);
diff --git a/ice40/archdefs.h b/ice40/archdefs.h
index be2e406d..75df678a 100644
--- a/ice40/archdefs.h
+++ b/ice40/archdefs.h
@@ -21,6 +21,8 @@
#error Include "archdefs.h" via "nextpnr.h" only.
#endif
+#include <boost/functional/hash.hpp>
+
NEXTPNR_NAMESPACE_BEGIN
typedef int delay_t;
@@ -107,6 +109,47 @@ struct PipId
bool operator!=(const PipId &other) const { return index != other.index; }
};
+struct GroupId
+{
+ enum : int8_t
+ {
+ TYPE_NONE,
+ TYPE_FRAME,
+ TYPE_MAIN_SW,
+ TYPE_LOCAL_SW,
+ TYPE_LC0_SW,
+ TYPE_LC1_SW,
+ TYPE_LC2_SW,
+ TYPE_LC3_SW,
+ TYPE_LC4_SW,
+ TYPE_LC5_SW,
+ TYPE_LC6_SW,
+ TYPE_LC7_SW
+ } type = TYPE_NONE;
+ int8_t x = 0, y = 0;
+
+ bool operator==(const GroupId &other) const { return (type == other.type) && (x == other.x) && (y == other.y); }
+ bool operator!=(const GroupId &other) const { return (type != other.type) || (x != other.x) || (y == other.y); }
+};
+
+struct DecalId
+{
+ enum : int8_t
+ {
+ TYPE_NONE,
+ TYPE_FRAME,
+ TYPE_BEL,
+ TYPE_WIRE,
+ TYPE_PIP,
+ TYPE_GROUP
+ } type = TYPE_NONE;
+ int32_t index = -1;
+ bool active = false;
+
+ bool operator==(const DecalId &other) const { return (type == other.type) && (index == other.index); }
+ bool operator!=(const DecalId &other) const { return (type != other.type) || (index != other.index); }
+};
+
NEXTPNR_NAMESPACE_END
namespace std {
@@ -135,4 +178,28 @@ template <> struct hash<NEXTPNR_NAMESPACE_PREFIX BelType> : hash<int>
template <> struct hash<NEXTPNR_NAMESPACE_PREFIX PortPin> : hash<int>
{
};
+
+template <> struct hash<NEXTPNR_NAMESPACE_PREFIX GroupId>
+{
+ std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX GroupId &group) const noexcept
+ {
+ std::size_t seed = 0;
+ boost::hash_combine(seed, hash<int>()(group.type));
+ boost::hash_combine(seed, hash<int>()(group.x));
+ boost::hash_combine(seed, hash<int>()(group.y));
+ return seed;
+ }
+};
+
+template <> struct hash<NEXTPNR_NAMESPACE_PREFIX DecalId>
+{
+ std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX DecalId &decal) const noexcept
+ {
+ std::size_t seed = 0;
+ boost::hash_combine(seed, hash<int>()(decal.type));
+ boost::hash_combine(seed, hash<int>()(decal.index));
+ return seed;
+ }
+};
+
} // namespace std
diff --git a/ice40/bitstream.cc b/ice40/bitstream.cc
index 98a7a0e4..a62c6c09 100644
--- a/ice40/bitstream.cc
+++ b/ice40/bitstream.cc
@@ -341,9 +341,8 @@ void write_asc(const Context *ctx, std::ostream &out)
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",
+ 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);
}
}
diff --git a/ice40/chipdb.py b/ice40/chipdb.py
index 931c73d1..51fe169c 100644
--- a/ice40/chipdb.py
+++ b/ice40/chipdb.py
@@ -11,6 +11,7 @@ group.add_argument("-b", "--binary", action="store_true")
group.add_argument("-c", "--c_file", action="store_true")
parser.add_argument("filename", type=str, help="chipdb input filename")
parser.add_argument("-p", "--portspins", type=str, help="path to portpins.inc")
+parser.add_argument("-g", "--gfxh", type=str, help="path to gfx.h")
args = parser.parse_args()
endianness = "le"
@@ -54,6 +55,9 @@ beltypes = dict()
tiletypes = dict()
wiretypes = dict()
+gfx_wire_ids = dict()
+wire_segments = dict()
+
with open(args.portspins) as f:
for line in f:
line = line.replace("(", " ")
@@ -66,6 +70,20 @@ with open(args.portspins) as f:
idx = len(portpins) + 1
portpins[line[1]] = idx
+with open(args.gfxh) as f:
+ state = 0
+ for line in f:
+ if state == 0 and line.startswith("enum GfxTileWireId"):
+ state = 1
+ elif state == 1 and line.startswith("};"):
+ state = 0
+ elif state == 1 and (line.startswith("{") or line.strip() == ""):
+ pass
+ elif state == 1:
+ idx = len(gfx_wire_ids)
+ name = line.strip().rstrip(",")
+ gfx_wire_ids[name] = idx
+
beltypes["ICESTORM_LC"] = 1
beltypes["ICESTORM_RAM"] = 2
beltypes["SB_IO"] = 3
@@ -371,6 +389,10 @@ with open(args.filename, "r") as f:
if mode[1] not in wire_xy:
wire_xy[mode[1]] = list()
wire_xy[mode[1]].append((int(line[0]), int(line[1])))
+ if mode[1] not in wire_segments:
+ wire_segments[mode[1]] = set()
+ if ("TILE_WIRE_" + wname[2].upper().replace("/", "_")) in gfx_wire_ids:
+ wire_segments[mode[1]].add((wname[0], wname[1], gfx_wire_ids["TILE_WIRE_" + wname[2].upper().replace("/", "_")]))
continue
if mode[0] in ("buffer", "routing"):
@@ -712,7 +734,7 @@ class BinaryBlobAssembler:
def finalize(self):
assert not self.finalized
- for s, index in self.strings.items():
+ for s, index in sorted(self.strings.items()):
self.l("str%d" % index, "char")
for c in s:
self.data.append(ord(c))
@@ -947,7 +969,7 @@ for wire in range(num_wires):
if wire in wire_downhill_belports:
num_bels_downhill = len(wire_downhill_belports[wire])
bba.l("wire%d_downbels" % wire, "BelPortPOD")
- for belport in wire_downhill_belports[wire]:
+ for belport in sorted(wire_downhill_belports[wire]):
bba.u32(belport[0], "bel_index")
bba.u32(portpins[belport[1]], "port")
else:
@@ -1040,7 +1062,7 @@ for t in range(num_tile_types):
tileinfo.append(ti)
bba.l("wire_data_%s" % dev_name, "WireInfoPOD")
-for info in wireinfo:
+for wire, info in enumerate(wireinfo):
bba.s(info["name"], "name")
bba.u32(info["num_uphill"], "num_uphill")
bba.u32(info["num_downhill"], "num_downhill")
@@ -1050,11 +1072,24 @@ for info in wireinfo:
bba.u32(info["uphill_bel"], "bel_uphill.bel_index")
bba.u32(info["uphill_pin"], "bel_uphill.port")
bba.r(info["list_bels_downhill"], "bels_downhill")
+ bba.u32(len(wire_segments[wire]), "num_segments")
+ if len(wire_segments[wire]):
+ bba.r("wire_segments_%d" % wire, "segments")
+ else:
+ bba.u32(0, "segments")
bba.u8(info["x"], "x")
bba.u8(info["y"], "y")
bba.u8(wiretypes[wire_type(info["name"])], "type")
bba.u8(0, "padding")
+for wire in range(num_wires):
+ if len(wire_segments[wire]):
+ bba.l("wire_segments_%d" % wire, "WireSegmentPOD")
+ for seg in sorted(wire_segments[wire]):
+ bba.u8(seg[0], "x")
+ bba.u8(seg[1], "y")
+ bba.u16(seg[2], "index")
+
bba.l("pip_data_%s" % dev_name, "PipInfoPOD")
for info in pipinfo:
bba.u32(info["src"], "src")
diff --git a/ice40/family.cmake b/ice40/family.cmake
index e6cefecb..9af06f82 100644
--- a/ice40/family.cmake
+++ b/ice40/family.cmake
@@ -21,8 +21,9 @@ if (MSVC)
set(DEV_TXT_DB ${ICEBOX_ROOT}/chipdb-${dev}.txt)
set(DEV_CC_DB ${CMAKE_CURRENT_SOURCE_DIR}/ice40/chipdbs/chipdb-${dev}.bin)
set(DEV_PORTS_INC ${CMAKE_CURRENT_SOURCE_DIR}/ice40/portpins.inc)
+ set(DEV_GFXH ${CMAKE_CURRENT_SOURCE_DIR}/ice40/gfx.h)
add_custom_command(OUTPUT ${DEV_CC_DB}
- COMMAND ${PYTHON_EXECUTABLE} ${DB_PY} -b -p ${DEV_PORTS_INC} ${DEV_TXT_DB} > ${DEV_CC_DB}
+ COMMAND ${PYTHON_EXECUTABLE} ${DB_PY} -b -p ${DEV_PORTS_INC} -g ${DEV_GFXH} ${DEV_TXT_DB} > ${DEV_CC_DB}
DEPENDS ${DEV_TXT_DB} ${DB_PY}
)
target_sources(ice40_chipdb PRIVATE ${DEV_CC_DB})
@@ -37,8 +38,9 @@ else()
set(DEV_TXT_DB ${ICEBOX_ROOT}/chipdb-${dev}.txt)
set(DEV_CC_DB ${CMAKE_CURRENT_SOURCE_DIR}/ice40/chipdbs/chipdb-${dev}.cc)
set(DEV_PORTS_INC ${CMAKE_CURRENT_SOURCE_DIR}/ice40/portpins.inc)
+ set(DEV_GFXH ${CMAKE_CURRENT_SOURCE_DIR}/ice40/gfx.h)
add_custom_command(OUTPUT ${DEV_CC_DB}
- COMMAND ${PYTHON_EXECUTABLE} ${DB_PY} -c -p ${DEV_PORTS_INC} ${DEV_TXT_DB} > ${DEV_CC_DB}.new
+ COMMAND ${PYTHON_EXECUTABLE} ${DB_PY} -c -p ${DEV_PORTS_INC} -g ${DEV_GFXH} ${DEV_TXT_DB} > ${DEV_CC_DB}.new
COMMAND mv ${DEV_CC_DB}.new ${DEV_CC_DB}
DEPENDS ${DEV_TXT_DB} ${DB_PY}
)
diff --git a/ice40/gfx.cc b/ice40/gfx.cc
new file mode 100644
index 00000000..19aaed13
--- /dev/null
+++ b/ice40/gfx.cc
@@ -0,0 +1,488 @@
+/*
+ * nextpnr -- Next Generation Place and Route
+ *
+ * Copyright (C) 2018 Clifford Wolf <clifford@symbioticeda.com>
+ *
+ * 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 "gfx.h"
+
+NEXTPNR_NAMESPACE_BEGIN
+
+void gfxTileWire(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId id, GraphicElement::style_t style)
+{
+ GraphicElement el;
+ el.type = GraphicElement::G_LINE;
+ el.style = style;
+
+ // Horizontal Span-4 Wires
+
+ if (id >= TILE_WIRE_SP4_H_L_36 && id <= TILE_WIRE_SP4_H_L_47) {
+ int idx = (id - TILE_WIRE_SP4_H_L_36) + 48;
+
+ float y1 = y + 1.0 - (0.03 + 0.0025 * (60 - (idx ^ 1)));
+ float y2 = y + 1.0 - (0.03 + 0.0025 * (60 - idx));
+
+ el.x1 = x;
+ el.x2 = x + 0.01;
+ el.y1 = y1;
+ el.y2 = y1;
+ g.push_back(el);
+
+ el.x1 = x + 0.01;
+ el.x2 = x + 0.02;
+ el.y1 = y1;
+ el.y2 = y2;
+ g.push_back(el);
+
+ el.x1 = x + 0.02;
+ el.x2 = x + 0.9;
+ el.y1 = y2;
+ el.y2 = y2;
+ g.push_back(el);
+
+ el.x1 = x + main_swbox_x1 + 0.0025 * (idx + 35);
+ el.x2 = el.x1;
+ el.y1 = y2;
+ el.y2 = y + main_swbox_y2;
+ g.push_back(el);
+ }
+
+ if (id >= TILE_WIRE_SP4_H_R_0 && id <= TILE_WIRE_SP4_H_R_47) {
+ int idx = id - TILE_WIRE_SP4_H_R_0;
+
+ float y1 = y + 1.0 - (0.03 + 0.0025 * (60 - idx));
+ float y2 = y + 1.0 - (0.03 + 0.0025 * (60 - (idx ^ 1)));
+ float y3 = y + 1.0 - (0.03 + 0.0025 * (60 - (idx ^ 1) - 12));
+
+ if (idx >= 12) {
+ el.x1 = x;
+ el.x2 = x + 0.01;
+ el.y1 = y1;
+ el.y2 = y1;
+ g.push_back(el);
+
+ el.x1 = x + 0.01;
+ el.x2 = x + 0.02;
+ el.y1 = y1;
+ el.y2 = y2;
+ g.push_back(el);
+ }
+
+ el.x1 = x + 0.02;
+ el.x2 = x + 0.9;
+ el.y1 = y2;
+ el.y2 = y2;
+ g.push_back(el);
+
+ el.x1 = x + 0.9;
+ el.x2 = x + 1.0;
+ el.y1 = y2;
+ el.y2 = y3;
+ g.push_back(el);
+
+ el.x1 = x + main_swbox_x1 + 0.0025 * ((idx ^ 1) + 35);
+ el.x2 = el.x1;
+ el.y1 = y2;
+ el.y2 = y + main_swbox_y2;
+ g.push_back(el);
+ }
+
+ // Vertical Span-4 Wires
+
+ if (id >= TILE_WIRE_SP4_V_T_36 && id <= TILE_WIRE_SP4_V_T_47) {
+ int idx = (id - TILE_WIRE_SP4_V_T_36) + 48;
+
+ float x1 = x + 0.03 + 0.0025 * (60 - (idx ^ 1));
+ float x2 = x + 0.03 + 0.0025 * (60 - idx);
+
+ el.y1 = y + 1.00;
+ el.y2 = y + 0.99;
+ el.x1 = x1;
+ el.x2 = x1;
+ g.push_back(el);
+
+ el.y1 = y + 0.99;
+ el.y2 = y + 0.98;
+ el.x1 = x1;
+ el.x2 = x2;
+ g.push_back(el);
+
+ el.y1 = y + 0.98;
+ el.y2 = y + 0.10;
+ el.x1 = x2;
+ el.x2 = x2;
+ g.push_back(el);
+
+ el.y1 = y + 1.0 - (0.03 + 0.0025 * (270 - idx));
+ el.y2 = el.y1;
+ el.x1 = x2;
+ el.x2 = x + main_swbox_x1;
+ g.push_back(el);
+ }
+
+ if (id >= TILE_WIRE_SP4_V_B_0 && id <= TILE_WIRE_SP4_V_B_47) {
+ int idx = id - TILE_WIRE_SP4_V_B_0;
+
+ float x1 = x + 0.03 + 0.0025 * (60 - idx);
+ float x2 = x + 0.03 + 0.0025 * (60 - (idx ^ 1));
+ float x3 = x + 0.03 + 0.0025 * (60 - (idx ^ 1) - 12);
+
+ if (idx >= 12) {
+ el.y1 = y + 1.00;
+ el.y2 = y + 0.99;
+ el.x1 = x1;
+ el.x2 = x1;
+ g.push_back(el);
+
+ el.y1 = y + 0.99;
+ el.y2 = y + 0.98;
+ el.x1 = x1;
+ el.x2 = x2;
+ g.push_back(el);
+ }
+
+ el.y1 = y + 0.98;
+ el.y2 = y + 0.10;
+ el.x1 = x2;
+ el.x2 = x2;
+ g.push_back(el);
+
+ el.y1 = y + 0.10;
+ el.y2 = y;
+ el.x1 = x2;
+ el.x2 = x3;
+ g.push_back(el);
+
+ el.y1 = y + 1.0 - (0.03 + 0.0025 * (145 - (idx ^ 1)));
+ el.y2 = el.y1;
+ el.x1 = x;
+ el.x2 = x2;
+ g.push_back(el);
+
+ el.y1 = y + 1.0 - (0.03 + 0.0025 * (270 - (idx ^ 1)));
+ el.y2 = el.y1;
+ el.x1 = x2;
+ el.x2 = x + main_swbox_x1;
+ g.push_back(el);
+ }
+
+ // Horizontal Span-12 Wires
+
+ if (id >= TILE_WIRE_SP12_H_L_22 && id <= TILE_WIRE_SP12_H_L_23) {
+ int idx = (id - TILE_WIRE_SP12_H_L_22) + 24;
+
+ float y1 = y + 1.0 - (0.03 + 0.0025 * (90 - (idx ^ 1)));
+ float y2 = y + 1.0 - (0.03 + 0.0025 * (90 - idx));
+
+ el.x1 = x;
+ el.x2 = x + 0.01;
+ el.y1 = y1;
+ el.y2 = y1;
+ g.push_back(el);
+
+ el.x1 = x + 0.01;
+ el.x2 = x + 0.02;
+ el.y1 = y1;
+ el.y2 = y2;
+ g.push_back(el);
+
+ el.x1 = x + 0.02;
+ el.x2 = x + 0.98333;
+ el.y1 = y2;
+ el.y2 = y2;
+ g.push_back(el);
+
+ el.x1 = x + main_swbox_x1 + 0.0025 * (idx + 5);
+ el.x2 = el.x1;
+ el.y1 = y2;
+ el.y2 = y + main_swbox_y2;
+ g.push_back(el);
+ }
+
+ if (id >= TILE_WIRE_SP12_H_R_0 && id <= TILE_WIRE_SP12_H_R_23) {
+ int idx = id - TILE_WIRE_SP12_H_R_0;
+
+ float y1 = y + 1.0 - (0.03 + 0.0025 * (90 - idx));
+ float y2 = y + 1.0 - (0.03 + 0.0025 * (90 - (idx ^ 1)));
+ float y3 = y + 1.0 - (0.03 + 0.0025 * (90 - (idx ^ 1) - 2));
+
+ if (idx >= 2) {
+ el.x1 = x;
+ el.x2 = x + 0.01;
+ el.y1 = y1;
+ el.y2 = y1;
+ g.push_back(el);
+
+ el.x1 = x + 0.01;
+ el.x2 = x + 0.02;
+ el.y1 = y1;
+ el.y2 = y2;
+ g.push_back(el);
+ }
+
+ el.x1 = x + 0.02;
+ el.x2 = x + 0.98333;
+ el.y1 = y2;
+ el.y2 = y2;
+ g.push_back(el);
+
+ el.x1 = x + 0.98333;
+ el.x2 = x + 1.0;
+ el.y1 = y2;
+ el.y2 = y3;
+ g.push_back(el);
+
+ el.x1 = x + main_swbox_x1 + 0.0025 * ((idx ^ 1) + 5);
+ el.x2 = el.x1;
+ el.y1 = y2;
+ el.y2 = y + main_swbox_y2;
+ g.push_back(el);
+ }
+
+ // Vertical Right Span-4
+
+ if (id >= TILE_WIRE_SP4_R_V_B_0 && id <= TILE_WIRE_SP4_R_V_B_47) {
+ int idx = id - TILE_WIRE_SP4_R_V_B_0;
+
+ float y1 = y + 1.0 - (0.03 + 0.0025 * (145 - (idx ^ 1)));
+
+ el.y1 = y1;
+ el.y2 = y1;
+ el.x1 = x + main_swbox_x2;
+ el.x2 = x + 1.0;
+ g.push_back(el);
+ }
+
+ // Vertical Span-12 Wires
+
+ if (id >= TILE_WIRE_SP12_V_T_22 && id <= TILE_WIRE_SP12_V_T_23) {
+ int idx = (id - TILE_WIRE_SP12_V_T_22) + 24;
+
+ float x1 = x + 0.03 + 0.0025 * (90 - (idx ^ 1));
+ float x2 = x + 0.03 + 0.0025 * (90 - idx);
+
+ el.y1 = y + 1.00;
+ el.y2 = y + 0.99;
+ el.x1 = x1;
+ el.x2 = x1;
+ g.push_back(el);
+
+ el.y1 = y + 0.99;
+ el.y2 = y + 0.98;
+ el.x1 = x1;
+ el.x2 = x2;
+ g.push_back(el);
+
+ el.y1 = y + 0.98;
+ el.y2 = y + 0.01667;
+ el.x1 = x2;
+ el.x2 = x2;
+ g.push_back(el);
+
+ el.y1 = y + 1.0 - (0.03 + 0.0025 * (300 - idx));
+ el.y2 = el.y1;
+ el.x1 = x2;
+ el.x2 = x + main_swbox_x1;
+ g.push_back(el);
+ }
+
+ if (id >= TILE_WIRE_SP12_V_B_0 && id <= TILE_WIRE_SP12_V_B_23) {
+ int idx = id - TILE_WIRE_SP12_V_B_0;
+
+ float x1 = x + 0.03 + 0.0025 * (90 - idx);
+ float x2 = x + 0.03 + 0.0025 * (90 - (idx ^ 1));
+ float x3 = x + 0.03 + 0.0025 * (90 - (idx ^ 1) - 2);
+
+ if (idx >= 2) {
+ el.y1 = y + 1.00;
+ el.y2 = y + 0.99;
+ el.x1 = x1;
+ el.x2 = x1;
+ g.push_back(el);
+
+ el.y1 = y + 0.99;
+ el.y2 = y + 0.98;
+ el.x1 = x1;
+ el.x2 = x2;
+ g.push_back(el);
+ }
+
+ el.y1 = y + 0.98;
+ el.y2 = y + 0.01667;
+ el.x1 = x2;
+ el.x2 = x2;
+ g.push_back(el);
+
+ el.y1 = y + 0.01667;
+ el.y2 = y;
+ el.x1 = x2;
+ el.x2 = x3;
+ g.push_back(el);
+
+ el.y1 = y + 1.0 - (0.03 + 0.0025 * (300 - (idx ^ 1)));
+ el.y2 = el.y1;
+ el.x1 = x2;
+ el.x2 = x + main_swbox_x1;
+ g.push_back(el);
+ }
+
+ // Global2Local
+
+ if (id >= TILE_WIRE_GLB2LOCAL_0 && id <= TILE_WIRE_GLB2LOCAL_3) {
+ int idx = id - TILE_WIRE_GLB2LOCAL_0;
+ el.x1 = x + main_swbox_x1 + 0.005 * (idx + 5);
+ el.x2 = el.x1;
+ el.y1 = y + main_swbox_y1;
+ el.y2 = el.y1 - 0.02;
+ g.push_back(el);
+ }
+
+ // GlobalNets
+
+ if (id >= TILE_WIRE_GLB_NETWK_0 && id <= TILE_WIRE_GLB_NETWK_7) {
+ int idx = id - TILE_WIRE_GLB_NETWK_0;
+ el.x1 = x + main_swbox_x1 - 0.05;
+ el.x2 = x + main_swbox_x1;
+ el.y1 = y + main_swbox_y1 + 0.005 * (13 - idx);
+ el.y2 = el.y1;
+ g.push_back(el);
+ }
+
+ // Neighbours
+
+ if (id >= TILE_WIRE_NEIGH_OP_BNL_0 && id <= TILE_WIRE_NEIGH_OP_TOP_7) {
+ int idx = id - TILE_WIRE_NEIGH_OP_BNL_0;
+ el.y1 = y + main_swbox_y2 - (0.0025 * (idx + 10) + 0.01 * (idx / 8));
+ el.y2 = el.y1;
+ el.x1 = x + main_swbox_x1 - 0.05;
+ el.x2 = x + main_swbox_x1;
+ g.push_back(el);
+ }
+
+ // Local Tracks
+
+ if (id >= TILE_WIRE_LOCAL_G0_0 && id <= TILE_WIRE_LOCAL_G3_7) {
+ int idx = id - TILE_WIRE_LOCAL_G0_0;
+ el.x1 = x + main_swbox_x2;
+ el.x2 = x + local_swbox_x1;
+ float yoff = y + (local_swbox_y1 + local_swbox_y2) / 2 - 0.005 * 16 - 0.075;
+ el.y1 = yoff + 0.005 * idx + 0.05 * (idx / 8);
+ el.y2 = el.y1;
+ g.push_back(el);
+ }
+
+ // LC Inputs
+
+ if (id >= TILE_WIRE_LUTFF_0_IN_0 && id <= TILE_WIRE_LUTFF_7_IN_3) {
+ int idx = id - TILE_WIRE_LUTFF_0_IN_0;
+ int z = idx / 4;
+ int input = idx % 4;
+ el.x1 = x + local_swbox_x2;
+ el.x2 = x + logic_cell_x1;
+ el.y1 = y + (logic_cell_y1 + logic_cell_y2) / 2 - 0.0075 + (0.005 * input) + z * logic_cell_pitch;
+ el.y2 = el.y1;
+ g.push_back(el);
+ }
+
+ // LC Outputs
+
+ if (id >= TILE_WIRE_LUTFF_0_OUT && id <= TILE_WIRE_LUTFF_7_OUT) {
+ int idx = id - TILE_WIRE_LUTFF_0_OUT;
+
+ float y1 = y + 1.0 - (0.03 + 0.0025 * (152 + idx));
+
+ el.y1 = y1;
+ el.y2 = y1;
+ el.x1 = x + main_swbox_x2;
+ el.x2 = x + 0.97 + 0.0025 * (7 - idx);
+ g.push_back(el);
+
+ el.y1 = y1;
+ el.y2 = y + (logic_cell_y1 + logic_cell_y2) / 2 + idx * logic_cell_pitch;
+ el.x1 = el.x2;
+ g.push_back(el);
+
+ el.y1 = el.y2;
+ el.x1 = x + logic_cell_x2;
+ g.push_back(el);
+ }
+
+ // LC Control
+
+ if (id >= TILE_WIRE_LUTFF_GLOBAL_CEN && id <= TILE_WIRE_LUTFF_GLOBAL_S_R) {
+ int idx = id - TILE_WIRE_LUTFF_GLOBAL_CEN;
+
+ el.x1 = x + main_swbox_x2 - 0.005 * (idx + 5);
+ el.x2 = el.x1;
+ el.y1 = y + main_swbox_y1;
+ el.y2 = el.y1 - 0.005 * (idx + 2);
+ g.push_back(el);
+
+ el.y1 = el.y2;
+ el.x2 = x + logic_cell_x2 - 0.005 * (2 - idx + 5);
+ g.push_back(el);
+
+ el.y2 = y + logic_cell_y1;
+ el.x1 = el.x2;
+ g.push_back(el);
+
+ for (int i = 0; i < 7; i++) {
+ el.y1 = y + logic_cell_y2 + i * logic_cell_pitch;
+ el.y2 = y + logic_cell_y1 + (i + 1) * logic_cell_pitch;
+ g.push_back(el);
+ }
+ }
+
+ // LC Cascade
+
+ if (id >= TILE_WIRE_LUTFF_0_LOUT && id <= TILE_WIRE_LUTFF_6_LOUT) {
+ int idx = id - TILE_WIRE_LUTFF_0_LOUT;
+ el.x1 = x + logic_cell_x1 + 0.005 * 5;
+ el.x2 = el.x1;
+ el.y1 = y + logic_cell_y2 + idx * logic_cell_pitch;
+ el.y2 = y + logic_cell_y1 + (idx + 1) * logic_cell_pitch;
+ g.push_back(el);
+ }
+
+ // Carry Chain
+
+ if (id >= TILE_WIRE_LUTFF_0_COUT && id <= TILE_WIRE_LUTFF_7_COUT) {
+ int idx = id - TILE_WIRE_LUTFF_0_COUT;
+ el.x1 = x + logic_cell_x1 + 0.005 * 3;
+ el.x2 = el.x1;
+ el.y1 = y + logic_cell_y2 + idx * logic_cell_pitch;
+ el.y2 = y + (idx < 7 ? logic_cell_y1 + (idx + 1) * logic_cell_pitch : 1.0);
+ g.push_back(el);
+ }
+
+ if (id == TILE_WIRE_CARRY_IN) {
+ el.x1 = x + logic_cell_x1 + 0.005 * 3;
+ el.x2 = el.x1;
+ el.y1 = y;
+ el.y2 = y + 0.01;
+ g.push_back(el);
+ }
+
+ if (id == TILE_WIRE_CARRY_IN_MUX) {
+ el.x1 = x + logic_cell_x1 + 0.005 * 3;
+ el.x2 = el.x1;
+ el.y1 = y + 0.02;
+ el.y2 = y + logic_cell_y1;
+ g.push_back(el);
+ }
+}
+
+NEXTPNR_NAMESPACE_END
diff --git a/ice40/gfx.h b/ice40/gfx.h
new file mode 100644
index 00000000..a65f7683
--- /dev/null
+++ b/ice40/gfx.h
@@ -0,0 +1,474 @@
+/*
+ * nextpnr -- Next Generation Place and Route
+ *
+ * Copyright (C) 2018 Clifford Wolf <clifford@symbioticeda.com>
+ *
+ * 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 GFX_H
+#define GFX_H
+
+#include "nextpnr.h"
+
+NEXTPNR_NAMESPACE_BEGIN
+
+const float main_swbox_x1 = 0.35;
+const float main_swbox_x2 = 0.60;
+const float main_swbox_y1 = 0.05;
+const float main_swbox_y2 = 0.73;
+
+const float local_swbox_x1 = 0.63;
+const float local_swbox_x2 = 0.73;
+const float local_swbox_y1 = 0.05;
+const float local_swbox_y2 = 0.55;
+
+const float logic_cell_x1 = 0.76;
+const float logic_cell_x2 = 0.95;
+const float logic_cell_y1 = 0.05;
+const float logic_cell_y2 = 0.10;
+const float logic_cell_pitch = 0.0625;
+
+enum GfxTileWireId
+{
+ TILE_WIRE_GLB2LOCAL_0,
+ TILE_WIRE_GLB2LOCAL_1,
+ TILE_WIRE_GLB2LOCAL_2,
+ TILE_WIRE_GLB2LOCAL_3,
+
+ TILE_WIRE_GLB_NETWK_0,
+ TILE_WIRE_GLB_NETWK_1,
+ TILE_WIRE_GLB_NETWK_2,
+ TILE_WIRE_GLB_NETWK_3,
+ TILE_WIRE_GLB_NETWK_4,
+ TILE_WIRE_GLB_NETWK_5,
+ TILE_WIRE_GLB_NETWK_6,
+ TILE_WIRE_GLB_NETWK_7,
+
+ TILE_WIRE_LOCAL_G0_0,
+ TILE_WIRE_LOCAL_G0_1,
+ TILE_WIRE_LOCAL_G0_2,
+ TILE_WIRE_LOCAL_G0_3,
+ TILE_WIRE_LOCAL_G0_4,
+ TILE_WIRE_LOCAL_G0_5,
+ TILE_WIRE_LOCAL_G0_6,
+ TILE_WIRE_LOCAL_G0_7,
+
+ TILE_WIRE_LOCAL_G1_0,
+ TILE_WIRE_LOCAL_G1_1,
+ TILE_WIRE_LOCAL_G1_2,
+ TILE_WIRE_LOCAL_G1_3,
+ TILE_WIRE_LOCAL_G1_4,
+ TILE_WIRE_LOCAL_G1_5,
+ TILE_WIRE_LOCAL_G1_6,
+ TILE_WIRE_LOCAL_G1_7,
+
+ TILE_WIRE_LOCAL_G2_0,
+ TILE_WIRE_LOCAL_G2_1,
+ TILE_WIRE_LOCAL_G2_2,
+ TILE_WIRE_LOCAL_G2_3,
+ TILE_WIRE_LOCAL_G2_4,
+ TILE_WIRE_LOCAL_G2_5,
+ TILE_WIRE_LOCAL_G2_6,
+ TILE_WIRE_LOCAL_G2_7,
+
+ TILE_WIRE_LOCAL_G3_0,
+ TILE_WIRE_LOCAL_G3_1,
+ TILE_WIRE_LOCAL_G3_2,
+ TILE_WIRE_LOCAL_G3_3,
+ TILE_WIRE_LOCAL_G3_4,
+ TILE_WIRE_LOCAL_G3_5,
+ TILE_WIRE_LOCAL_G3_6,
+ TILE_WIRE_LOCAL_G3_7,
+
+ TILE_WIRE_CARRY_IN,
+ TILE_WIRE_CARRY_IN_MUX,
+
+ TILE_WIRE_LUTFF_0_IN_0,
+ TILE_WIRE_LUTFF_0_IN_1,
+ TILE_WIRE_LUTFF_0_IN_2,
+ TILE_WIRE_LUTFF_0_IN_3,
+
+ TILE_WIRE_LUTFF_1_IN_0,
+ TILE_WIRE_LUTFF_1_IN_1,
+ TILE_WIRE_LUTFF_1_IN_2,
+ TILE_WIRE_LUTFF_1_IN_3,
+
+ TILE_WIRE_LUTFF_2_IN_0,
+ TILE_WIRE_LUTFF_2_IN_1,
+ TILE_WIRE_LUTFF_2_IN_2,
+ TILE_WIRE_LUTFF_2_IN_3,
+
+ TILE_WIRE_LUTFF_3_IN_0,
+ TILE_WIRE_LUTFF_3_IN_1,
+ TILE_WIRE_LUTFF_3_IN_2,
+ TILE_WIRE_LUTFF_3_IN_3,
+
+ TILE_WIRE_LUTFF_4_IN_0,
+ TILE_WIRE_LUTFF_4_IN_1,
+ TILE_WIRE_LUTFF_4_IN_2,
+ TILE_WIRE_LUTFF_4_IN_3,
+
+ TILE_WIRE_LUTFF_5_IN_0,
+ TILE_WIRE_LUTFF_5_IN_1,
+ TILE_WIRE_LUTFF_5_IN_2,
+ TILE_WIRE_LUTFF_5_IN_3,
+
+ TILE_WIRE_LUTFF_6_IN_0,
+ TILE_WIRE_LUTFF_6_IN_1,
+ TILE_WIRE_LUTFF_6_IN_2,
+ TILE_WIRE_LUTFF_6_IN_3,
+
+ TILE_WIRE_LUTFF_7_IN_0,
+ TILE_WIRE_LUTFF_7_IN_1,
+ TILE_WIRE_LUTFF_7_IN_2,
+ TILE_WIRE_LUTFF_7_IN_3,
+
+ TILE_WIRE_LUTFF_0_LOUT,
+ TILE_WIRE_LUTFF_1_LOUT,
+ TILE_WIRE_LUTFF_2_LOUT,
+ TILE_WIRE_LUTFF_3_LOUT,
+ TILE_WIRE_LUTFF_4_LOUT,
+ TILE_WIRE_LUTFF_5_LOUT,
+ TILE_WIRE_LUTFF_6_LOUT,
+
+ TILE_WIRE_LUTFF_0_OUT,
+ TILE_WIRE_LUTFF_1_OUT,
+ TILE_WIRE_LUTFF_2_OUT,
+ TILE_WIRE_LUTFF_3_OUT,
+ TILE_WIRE_LUTFF_4_OUT,
+ TILE_WIRE_LUTFF_5_OUT,
+ TILE_WIRE_LUTFF_6_OUT,
+ TILE_WIRE_LUTFF_7_OUT,
+
+ TILE_WIRE_LUTFF_0_COUT,
+ TILE_WIRE_LUTFF_1_COUT,
+ TILE_WIRE_LUTFF_2_COUT,
+ TILE_WIRE_LUTFF_3_COUT,
+ TILE_WIRE_LUTFF_4_COUT,
+ TILE_WIRE_LUTFF_5_COUT,
+ TILE_WIRE_LUTFF_6_COUT,
+ TILE_WIRE_LUTFF_7_COUT,
+
+ TILE_WIRE_LUTFF_GLOBAL_CEN,
+ TILE_WIRE_LUTFF_GLOBAL_CLK,
+ TILE_WIRE_LUTFF_GLOBAL_S_R,
+
+ TILE_WIRE_NEIGH_OP_BNL_0,
+ TILE_WIRE_NEIGH_OP_BNL_1,
+ TILE_WIRE_NEIGH_OP_BNL_2,
+ TILE_WIRE_NEIGH_OP_BNL_3,
+ TILE_WIRE_NEIGH_OP_BNL_4,
+ TILE_WIRE_NEIGH_OP_BNL_5,
+ TILE_WIRE_NEIGH_OP_BNL_6,
+ TILE_WIRE_NEIGH_OP_BNL_7,
+
+ TILE_WIRE_NEIGH_OP_BNR_0,
+ TILE_WIRE_NEIGH_OP_BNR_1,
+ TILE_WIRE_NEIGH_OP_BNR_2,
+ TILE_WIRE_NEIGH_OP_BNR_3,
+ TILE_WIRE_NEIGH_OP_BNR_4,
+ TILE_WIRE_NEIGH_OP_BNR_5,
+ TILE_WIRE_NEIGH_OP_BNR_6,
+ TILE_WIRE_NEIGH_OP_BNR_7,
+
+ TILE_WIRE_NEIGH_OP_BOT_0,
+ TILE_WIRE_NEIGH_OP_BOT_1,
+ TILE_WIRE_NEIGH_OP_BOT_2,
+ TILE_WIRE_NEIGH_OP_BOT_3,
+ TILE_WIRE_NEIGH_OP_BOT_4,
+ TILE_WIRE_NEIGH_OP_BOT_5,
+ TILE_WIRE_NEIGH_OP_BOT_6,
+ TILE_WIRE_NEIGH_OP_BOT_7,
+
+ TILE_WIRE_NEIGH_OP_LFT_0,
+ TILE_WIRE_NEIGH_OP_LFT_1,
+ TILE_WIRE_NEIGH_OP_LFT_2,
+ TILE_WIRE_NEIGH_OP_LFT_3,
+ TILE_WIRE_NEIGH_OP_LFT_4,
+ TILE_WIRE_NEIGH_OP_LFT_5,
+ TILE_WIRE_NEIGH_OP_LFT_6,
+ TILE_WIRE_NEIGH_OP_LFT_7,
+
+ TILE_WIRE_NEIGH_OP_RGT_0,
+ TILE_WIRE_NEIGH_OP_RGT_1,
+ TILE_WIRE_NEIGH_OP_RGT_2,
+ TILE_WIRE_NEIGH_OP_RGT_3,
+ TILE_WIRE_NEIGH_OP_RGT_4,
+ TILE_WIRE_NEIGH_OP_RGT_5,
+ TILE_WIRE_NEIGH_OP_RGT_6,
+ TILE_WIRE_NEIGH_OP_RGT_7,
+
+ TILE_WIRE_NEIGH_OP_TNL_0,
+ TILE_WIRE_NEIGH_OP_TNL_1,
+ TILE_WIRE_NEIGH_OP_TNL_2,
+ TILE_WIRE_NEIGH_OP_TNL_3,
+ TILE_WIRE_NEIGH_OP_TNL_4,
+ TILE_WIRE_NEIGH_OP_TNL_5,
+ TILE_WIRE_NEIGH_OP_TNL_6,
+ TILE_WIRE_NEIGH_OP_TNL_7,
+
+ TILE_WIRE_NEIGH_OP_TNR_0,
+ TILE_WIRE_NEIGH_OP_TNR_1,
+ TILE_WIRE_NEIGH_OP_TNR_2,
+ TILE_WIRE_NEIGH_OP_TNR_3,
+ TILE_WIRE_NEIGH_OP_TNR_4,
+ TILE_WIRE_NEIGH_OP_TNR_5,
+ TILE_WIRE_NEIGH_OP_TNR_6,
+ TILE_WIRE_NEIGH_OP_TNR_7,
+
+ TILE_WIRE_NEIGH_OP_TOP_0,
+ TILE_WIRE_NEIGH_OP_TOP_1,
+ TILE_WIRE_NEIGH_OP_TOP_2,
+ TILE_WIRE_NEIGH_OP_TOP_3,
+ TILE_WIRE_NEIGH_OP_TOP_4,
+ TILE_WIRE_NEIGH_OP_TOP_5,
+ TILE_WIRE_NEIGH_OP_TOP_6,
+ TILE_WIRE_NEIGH_OP_TOP_7,
+
+ TILE_WIRE_SP4_V_B_0,
+ TILE_WIRE_SP4_V_B_1,
+ TILE_WIRE_SP4_V_B_2,
+ TILE_WIRE_SP4_V_B_3,
+ TILE_WIRE_SP4_V_B_4,
+ TILE_WIRE_SP4_V_B_5,
+ TILE_WIRE_SP4_V_B_6,
+ TILE_WIRE_SP4_V_B_7,
+ TILE_WIRE_SP4_V_B_8,
+ TILE_WIRE_SP4_V_B_9,
+ TILE_WIRE_SP4_V_B_10,
+ TILE_WIRE_SP4_V_B_11,
+ TILE_WIRE_SP4_V_B_12,
+ TILE_WIRE_SP4_V_B_13,
+ TILE_WIRE_SP4_V_B_14,
+ TILE_WIRE_SP4_V_B_15,
+ TILE_WIRE_SP4_V_B_16,
+ TILE_WIRE_SP4_V_B_17,
+ TILE_WIRE_SP4_V_B_18,
+ TILE_WIRE_SP4_V_B_19,
+ TILE_WIRE_SP4_V_B_20,
+ TILE_WIRE_SP4_V_B_21,
+ TILE_WIRE_SP4_V_B_22,
+ TILE_WIRE_SP4_V_B_23,
+ TILE_WIRE_SP4_V_B_24,
+ TILE_WIRE_SP4_V_B_25,
+ TILE_WIRE_SP4_V_B_26,
+ TILE_WIRE_SP4_V_B_27,
+ TILE_WIRE_SP4_V_B_28,
+ TILE_WIRE_SP4_V_B_29,
+ TILE_WIRE_SP4_V_B_30,
+ TILE_WIRE_SP4_V_B_31,
+ TILE_WIRE_SP4_V_B_32,
+ TILE_WIRE_SP4_V_B_33,
+ TILE_WIRE_SP4_V_B_34,
+ TILE_WIRE_SP4_V_B_35,
+ TILE_WIRE_SP4_V_B_36,
+ TILE_WIRE_SP4_V_B_37,
+ TILE_WIRE_SP4_V_B_38,
+ TILE_WIRE_SP4_V_B_39,
+ TILE_WIRE_SP4_V_B_40,
+ TILE_WIRE_SP4_V_B_41,
+ TILE_WIRE_SP4_V_B_42,
+ TILE_WIRE_SP4_V_B_43,
+ TILE_WIRE_SP4_V_B_44,
+ TILE_WIRE_SP4_V_B_45,
+ TILE_WIRE_SP4_V_B_46,
+ TILE_WIRE_SP4_V_B_47,
+
+ TILE_WIRE_SP4_V_T_36,
+ TILE_WIRE_SP4_V_T_37,
+ TILE_WIRE_SP4_V_T_38,
+ TILE_WIRE_SP4_V_T_39,
+ TILE_WIRE_SP4_V_T_40,
+ TILE_WIRE_SP4_V_T_41,
+ TILE_WIRE_SP4_V_T_42,
+ TILE_WIRE_SP4_V_T_43,
+ TILE_WIRE_SP4_V_T_44,
+ TILE_WIRE_SP4_V_T_45,
+ TILE_WIRE_SP4_V_T_46,
+ TILE_WIRE_SP4_V_T_47,
+
+ TILE_WIRE_SP4_R_V_B_0,
+ TILE_WIRE_SP4_R_V_B_1,
+ TILE_WIRE_SP4_R_V_B_2,
+ TILE_WIRE_SP4_R_V_B_3,
+ TILE_WIRE_SP4_R_V_B_4,
+ TILE_WIRE_SP4_R_V_B_5,
+ TILE_WIRE_SP4_R_V_B_6,
+ TILE_WIRE_SP4_R_V_B_7,
+ TILE_WIRE_SP4_R_V_B_8,
+ TILE_WIRE_SP4_R_V_B_9,
+ TILE_WIRE_SP4_R_V_B_10,
+ TILE_WIRE_SP4_R_V_B_11,
+ TILE_WIRE_SP4_R_V_B_12,
+ TILE_WIRE_SP4_R_V_B_13,
+ TILE_WIRE_SP4_R_V_B_14,
+ TILE_WIRE_SP4_R_V_B_15,
+ TILE_WIRE_SP4_R_V_B_16,
+ TILE_WIRE_SP4_R_V_B_17,
+ TILE_WIRE_SP4_R_V_B_18,
+ TILE_WIRE_SP4_R_V_B_19,
+ TILE_WIRE_SP4_R_V_B_20,
+ TILE_WIRE_SP4_R_V_B_21,
+ TILE_WIRE_SP4_R_V_B_22,
+ TILE_WIRE_SP4_R_V_B_23,
+ TILE_WIRE_SP4_R_V_B_24,
+ TILE_WIRE_SP4_R_V_B_25,
+ TILE_WIRE_SP4_R_V_B_26,
+ TILE_WIRE_SP4_R_V_B_27,
+ TILE_WIRE_SP4_R_V_B_28,
+ TILE_WIRE_SP4_R_V_B_29,
+ TILE_WIRE_SP4_R_V_B_30,
+ TILE_WIRE_SP4_R_V_B_31,
+ TILE_WIRE_SP4_R_V_B_32,
+ TILE_WIRE_SP4_R_V_B_33,
+ TILE_WIRE_SP4_R_V_B_34,
+ TILE_WIRE_SP4_R_V_B_35,
+ TILE_WIRE_SP4_R_V_B_36,
+ TILE_WIRE_SP4_R_V_B_37,
+ TILE_WIRE_SP4_R_V_B_38,
+ TILE_WIRE_SP4_R_V_B_39,
+ TILE_WIRE_SP4_R_V_B_40,
+ TILE_WIRE_SP4_R_V_B_41,
+ TILE_WIRE_SP4_R_V_B_42,
+ TILE_WIRE_SP4_R_V_B_43,
+ TILE_WIRE_SP4_R_V_B_44,
+ TILE_WIRE_SP4_R_V_B_45,
+ TILE_WIRE_SP4_R_V_B_46,
+ TILE_WIRE_SP4_R_V_B_47,
+
+ TILE_WIRE_SP4_H_L_36,
+ TILE_WIRE_SP4_H_L_37,
+ TILE_WIRE_SP4_H_L_38,
+ TILE_WIRE_SP4_H_L_39,
+ TILE_WIRE_SP4_H_L_40,
+ TILE_WIRE_SP4_H_L_41,
+ TILE_WIRE_SP4_H_L_42,
+ TILE_WIRE_SP4_H_L_43,
+ TILE_WIRE_SP4_H_L_44,
+ TILE_WIRE_SP4_H_L_45,
+ TILE_WIRE_SP4_H_L_46,
+ TILE_WIRE_SP4_H_L_47,
+
+ TILE_WIRE_SP4_H_R_0,
+ TILE_WIRE_SP4_H_R_1,
+ TILE_WIRE_SP4_H_R_2,
+ TILE_WIRE_SP4_H_R_3,
+ TILE_WIRE_SP4_H_R_4,
+ TILE_WIRE_SP4_H_R_5,
+ TILE_WIRE_SP4_H_R_6,
+ TILE_WIRE_SP4_H_R_7,
+ TILE_WIRE_SP4_H_R_8,
+ TILE_WIRE_SP4_H_R_9,
+ TILE_WIRE_SP4_H_R_10,
+ TILE_WIRE_SP4_H_R_11,
+ TILE_WIRE_SP4_H_R_12,
+ TILE_WIRE_SP4_H_R_13,
+ TILE_WIRE_SP4_H_R_14,
+ TILE_WIRE_SP4_H_R_15,
+ TILE_WIRE_SP4_H_R_16,
+ TILE_WIRE_SP4_H_R_17,
+ TILE_WIRE_SP4_H_R_18,
+ TILE_WIRE_SP4_H_R_19,
+ TILE_WIRE_SP4_H_R_20,
+ TILE_WIRE_SP4_H_R_21,
+ TILE_WIRE_SP4_H_R_22,
+ TILE_WIRE_SP4_H_R_23,
+ TILE_WIRE_SP4_H_R_24,
+ TILE_WIRE_SP4_H_R_25,
+ TILE_WIRE_SP4_H_R_26,
+ TILE_WIRE_SP4_H_R_27,
+ TILE_WIRE_SP4_H_R_28,
+ TILE_WIRE_SP4_H_R_29,
+ TILE_WIRE_SP4_H_R_30,
+ TILE_WIRE_SP4_H_R_31,
+ TILE_WIRE_SP4_H_R_32,
+ TILE_WIRE_SP4_H_R_33,
+ TILE_WIRE_SP4_H_R_34,
+ TILE_WIRE_SP4_H_R_35,
+ TILE_WIRE_SP4_H_R_36,
+ TILE_WIRE_SP4_H_R_37,
+ TILE_WIRE_SP4_H_R_38,
+ TILE_WIRE_SP4_H_R_39,
+ TILE_WIRE_SP4_H_R_40,
+ TILE_WIRE_SP4_H_R_41,
+ TILE_WIRE_SP4_H_R_42,
+ TILE_WIRE_SP4_H_R_43,
+ TILE_WIRE_SP4_H_R_44,
+ TILE_WIRE_SP4_H_R_45,
+ TILE_WIRE_SP4_H_R_46,
+ TILE_WIRE_SP4_H_R_47,
+
+ TILE_WIRE_SP12_V_B_0,
+ TILE_WIRE_SP12_V_B_1,
+ TILE_WIRE_SP12_V_B_2,
+ TILE_WIRE_SP12_V_B_3,
+ TILE_WIRE_SP12_V_B_4,
+ TILE_WIRE_SP12_V_B_5,
+ TILE_WIRE_SP12_V_B_6,
+ TILE_WIRE_SP12_V_B_7,
+ TILE_WIRE_SP12_V_B_8,
+ TILE_WIRE_SP12_V_B_9,
+ TILE_WIRE_SP12_V_B_10,
+ TILE_WIRE_SP12_V_B_11,
+ TILE_WIRE_SP12_V_B_12,
+ TILE_WIRE_SP12_V_B_13,
+ TILE_WIRE_SP12_V_B_14,
+ TILE_WIRE_SP12_V_B_15,
+ TILE_WIRE_SP12_V_B_16,
+ TILE_WIRE_SP12_V_B_17,
+ TILE_WIRE_SP12_V_B_18,
+ TILE_WIRE_SP12_V_B_19,
+ TILE_WIRE_SP12_V_B_20,
+ TILE_WIRE_SP12_V_B_21,
+ TILE_WIRE_SP12_V_B_22,
+ TILE_WIRE_SP12_V_B_23,
+
+ TILE_WIRE_SP12_V_T_22,
+ TILE_WIRE_SP12_V_T_23,
+
+ TILE_WIRE_SP12_H_R_0,
+ TILE_WIRE_SP12_H_R_1,
+ TILE_WIRE_SP12_H_R_2,
+ TILE_WIRE_SP12_H_R_3,
+ TILE_WIRE_SP12_H_R_4,
+ TILE_WIRE_SP12_H_R_5,
+ TILE_WIRE_SP12_H_R_6,
+ TILE_WIRE_SP12_H_R_7,
+ TILE_WIRE_SP12_H_R_8,
+ TILE_WIRE_SP12_H_R_9,
+ TILE_WIRE_SP12_H_R_10,
+ TILE_WIRE_SP12_H_R_11,
+ TILE_WIRE_SP12_H_R_12,
+ TILE_WIRE_SP12_H_R_13,
+ TILE_WIRE_SP12_H_R_14,
+ TILE_WIRE_SP12_H_R_15,
+ TILE_WIRE_SP12_H_R_16,
+ TILE_WIRE_SP12_H_R_17,
+ TILE_WIRE_SP12_H_R_18,
+ TILE_WIRE_SP12_H_R_19,
+ TILE_WIRE_SP12_H_R_20,
+ TILE_WIRE_SP12_H_R_21,
+ TILE_WIRE_SP12_H_R_22,
+ TILE_WIRE_SP12_H_R_23,
+
+ TILE_WIRE_SP12_H_L_22,
+ TILE_WIRE_SP12_H_L_23
+};
+
+void gfxTileWire(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId id, GraphicElement::style_t style);
+
+NEXTPNR_NAMESPACE_END
+
+#endif // GFX_H
diff --git a/ice40/main.cc b/ice40/main.cc
index 87a32ded..e77bdd34 100644
--- a/ice40/main.cc
+++ b/ice40/main.cc
@@ -39,30 +39,30 @@
#include "jsonparse.h"
#include "log.h"
#include "nextpnr.h"
-#include "pack.h"
#include "pcf.h"
#include "place_legaliser.h"
-#include "place_sa.h"
-#include "route.h"
#include "timing.h"
#include "version.h"
USING_NEXTPNR_NAMESPACE
-void svg_dump_el(const GraphicElement &el)
+void svg_dump_decal(const Context *ctx, const DecalXY &decal)
{
- float scale = 10.0, offset = 10.0;
- std::string style = "stroke=\"black\" stroke-width=\"0.1\" fill=\"none\"";
-
- if (el.type == GraphicElement::G_BOX) {
- std::cout << "<rect x=\"" << (offset + scale * el.x1) << "\" y=\"" << (offset + scale * el.y1) << "\" height=\""
- << (scale * (el.y2 - el.y1)) << "\" width=\"" << (scale * (el.x2 - el.x1)) << "\" " << style
- << "/>\n";
- }
+ const float scale = 10.0, offset = 10.0;
+ const std::string style = "stroke=\"black\" stroke-width=\"0.1\" fill=\"none\"";
+
+ for (auto &el : ctx->getDecalGraphics(decal.decal)) {
+ if (el.type == GraphicElement::G_BOX) {
+ std::cout << "<rect x=\"" << (offset + scale * (decal.x + el.x1)) << "\" y=\""
+ << (offset + scale * (decal.y + el.y1)) << "\" height=\"" << (scale * (el.y2 - el.y1))
+ << "\" width=\"" << (scale * (el.x2 - el.x1)) << "\" " << style << "/>\n";
+ }
- if (el.type == GraphicElement::G_LINE) {
- std::cout << "<line x1=\"" << (offset + scale * el.x1) << "\" y1=\"" << (offset + scale * el.y1) << "\" x2=\""
- << (offset + scale * el.x2) << "\" y2=\"" << (offset + scale * el.y2) << "\" " << style << "/>\n";
+ if (el.type == GraphicElement::G_LINE) {
+ std::cout << "<line x1=\"" << (offset + scale * (decal.x + el.x1)) << "\" y1=\""
+ << (offset + scale * (decal.y + el.y1)) << "\" x2=\"" << (offset + scale * (decal.x + el.x2))
+ << "\" y2=\"" << (offset + scale * (decal.y + el.y2)) << "\" " << style << "/>\n";
+ }
}
}
@@ -98,12 +98,16 @@ int main(int argc, char *argv[])
options.add_options()("seed", po::value<int>(), "seed value for random number generator");
options.add_options()("version,V", "show version");
options.add_options()("tmfuzz", "run path delay estimate fuzzer");
+#ifdef ICE40_HX1K_ONLY
+ options.add_options()("hx1k", "set device type to iCE40HX1K");
+#else
options.add_options()("lp384", "set device type to iCE40LP384");
options.add_options()("lp1k", "set device type to iCE40LP1K");
options.add_options()("lp8k", "set device type to iCE40LP8K");
options.add_options()("hx1k", "set device type to iCE40HX1K");
options.add_options()("hx8k", "set device type to iCE40HX8K");
options.add_options()("up5k", "set device type to iCE40UP5K");
+#endif
options.add_options()("freq", po::value<double>(), "set target frequency for design in MHz");
options.add_options()("no-tmdriv", "disable timing-driven placement");
options.add_options()("package", po::value<std::string>(), "set device package");
@@ -267,112 +271,126 @@ int main(int argc, char *argv[])
return 1;
}
- Context ctx(chipArgs);
+ std::unique_ptr<Context> ctx = std::unique_ptr<Context>(new Context(chipArgs));
if (vm.count("verbose")) {
- ctx.verbose = true;
+ ctx->verbose = true;
}
if (vm.count("debug")) {
- ctx.verbose = true;
- ctx.debug = true;
+ ctx->verbose = true;
+ ctx->debug = true;
}
if (vm.count("force")) {
- ctx.force = true;
+ ctx->force = true;
}
if (vm.count("seed")) {
- ctx.rngseed(vm["seed"].as<int>());
+ ctx->rngseed(vm["seed"].as<int>());
}
if (vm.count("svg")) {
std::cout << "<svg xmlns=\"http://www.w3.org/2000/svg\" "
"xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n";
- for (auto bel : ctx.getBels()) {
- std::cout << "<!-- " << ctx.getBelName(bel).str(&ctx) << " -->\n";
- for (auto &el : ctx.getBelGraphics(bel))
- svg_dump_el(el);
+ for (auto bel : ctx->getBels()) {
+ std::cout << "<!-- " << ctx->getBelName(bel).str(ctx.get()) << " -->\n";
+ svg_dump_decal(ctx.get(), ctx->getBelDecal(bel));
}
std::cout << "<!-- Frame -->\n";
- for (auto &el : ctx.getFrameGraphics())
- svg_dump_el(el);
+ svg_dump_decal(ctx.get(), ctx->getFrameDecal());
std::cout << "</svg>\n";
}
if (vm.count("tmfuzz")) {
std::vector<WireId> src_wires, dst_wires;
- /*for (auto w : ctx.getWires())
+ /*for (auto w : ctx->getWires())
src_wires.push_back(w);*/
- for (auto b : ctx.getBels()) {
- if (ctx.getBelType(b) == TYPE_ICESTORM_LC) {
- src_wires.push_back(ctx.getWireBelPin(b, PIN_O));
+ for (auto b : ctx->getBels()) {
+ if (ctx->getBelType(b) == TYPE_ICESTORM_LC) {
+ src_wires.push_back(ctx->getWireBelPin(b, PIN_O));
}
- if (ctx.getBelType(b) == TYPE_SB_IO) {
- src_wires.push_back(ctx.getWireBelPin(b, PIN_D_IN_0));
+ if (ctx->getBelType(b) == TYPE_SB_IO) {
+ src_wires.push_back(ctx->getWireBelPin(b, PIN_D_IN_0));
}
}
- for (auto b : ctx.getBels()) {
- if (ctx.getBelType(b) == TYPE_ICESTORM_LC) {
- dst_wires.push_back(ctx.getWireBelPin(b, PIN_I0));
- dst_wires.push_back(ctx.getWireBelPin(b, PIN_I1));
- dst_wires.push_back(ctx.getWireBelPin(b, PIN_I2));
- dst_wires.push_back(ctx.getWireBelPin(b, PIN_I3));
- dst_wires.push_back(ctx.getWireBelPin(b, PIN_CEN));
- dst_wires.push_back(ctx.getWireBelPin(b, PIN_CIN));
+ for (auto b : ctx->getBels()) {
+ if (ctx->getBelType(b) == TYPE_ICESTORM_LC) {
+ dst_wires.push_back(ctx->getWireBelPin(b, PIN_I0));
+ dst_wires.push_back(ctx->getWireBelPin(b, PIN_I1));
+ dst_wires.push_back(ctx->getWireBelPin(b, PIN_I2));
+ dst_wires.push_back(ctx->getWireBelPin(b, PIN_I3));
+ dst_wires.push_back(ctx->getWireBelPin(b, PIN_CEN));
+ dst_wires.push_back(ctx->getWireBelPin(b, PIN_CIN));
}
- if (ctx.getBelType(b) == TYPE_SB_IO) {
- dst_wires.push_back(ctx.getWireBelPin(b, PIN_D_OUT_0));
- dst_wires.push_back(ctx.getWireBelPin(b, PIN_OUTPUT_ENABLE));
+ if (ctx->getBelType(b) == TYPE_SB_IO) {
+ dst_wires.push_back(ctx->getWireBelPin(b, PIN_D_OUT_0));
+ dst_wires.push_back(ctx->getWireBelPin(b, PIN_OUTPUT_ENABLE));
}
}
- ctx.shuffle(src_wires);
- ctx.shuffle(dst_wires);
+ ctx->shuffle(src_wires);
+ ctx->shuffle(dst_wires);
for (int i = 0; i < int(src_wires.size()) && i < int(dst_wires.size()); i++) {
delay_t actual_delay;
WireId src = src_wires[i], dst = dst_wires[i];
- if (!get_actual_route_delay(&ctx, src, dst, actual_delay))
+ if (!ctx->getActualRouteDelay(src, dst, actual_delay))
continue;
- printf("%s %s %.3f %.3f %d %d %d %d %d %d\n", ctx.getWireName(src).c_str(&ctx),
- ctx.getWireName(dst).c_str(&ctx), ctx.getDelayNS(actual_delay),
- ctx.getDelayNS(ctx.estimateDelay(src, dst)), ctx.chip_info->wire_data[src.index].x,
- ctx.chip_info->wire_data[src.index].y, ctx.chip_info->wire_data[src.index].type,
- ctx.chip_info->wire_data[dst.index].x, ctx.chip_info->wire_data[dst.index].y,
- ctx.chip_info->wire_data[dst.index].type);
+ printf("%s %s %.3f %.3f %d %d %d %d %d %d\n", ctx->getWireName(src).c_str(ctx.get()),
+ ctx->getWireName(dst).c_str(ctx.get()), ctx->getDelayNS(actual_delay),
+ ctx->getDelayNS(ctx->estimateDelay(src, dst)), ctx->chip_info->wire_data[src.index].x,
+ ctx->chip_info->wire_data[src.index].y, ctx->chip_info->wire_data[src.index].type,
+ ctx->chip_info->wire_data[dst.index].x, ctx->chip_info->wire_data[dst.index].y,
+ ctx->chip_info->wire_data[dst.index].type);
}
}
+ if (vm.count("freq"))
+ ctx->target_freq = vm["freq"].as<double>() * 1e6;
+ ctx->timing_driven = true;
+ if (vm.count("no-tmdriv"))
+ ctx->timing_driven = false;
+#ifndef NO_GUI
+ if (vm.count("gui")) {
+ Application a(argc, argv);
+ MainWindow w(std::move(ctx), chipArgs);
+ if (vm.count("json")) {
+ std::string filename = vm["json"].as<std::string>();
+ std::string pcf = "";
+ if (vm.count("pcf"))
+ pcf = vm["pcf"].as<std::string>();
+ w.load_json(filename, pcf);
+ }
+ w.show();
+
+ return a.exec();
+ }
+#endif
if (vm.count("json")) {
std::string filename = vm["json"].as<std::string>();
std::ifstream f(filename);
- if (!parse_json_file(f, filename, &ctx))
+ if (!parse_json_file(f, filename, ctx.get()))
log_error("Loading design failed.\n");
if (vm.count("pcf")) {
std::ifstream pcf(vm["pcf"].as<std::string>());
- if (!apply_pcf(&ctx, pcf))
+ if (!apply_pcf(ctx.get(), pcf))
log_error("Loading PCF failed.\n");
}
- if (!pack_design(&ctx) && !ctx.force)
+ if (!ctx->pack() && !ctx->force)
log_error("Packing design failed.\n");
- if (vm.count("freq"))
- ctx.target_freq = vm["freq"].as<double>() * 1e6;
- assign_budget(&ctx);
- ctx.check();
- print_utilisation(&ctx);
- ctx.timing_driven = true;
- if (vm.count("no-tmdriv"))
- ctx.timing_driven = false;
+ assign_budget(ctx.get());
+ ctx->check();
+ print_utilisation(ctx.get());
if (!vm.count("pack-only")) {
- if (!place_design_sa(&ctx) && !ctx.force)
+ if (!ctx->place() && !ctx->force)
log_error("Placing design failed.\n");
- ctx.check();
- if (!route_design(&ctx) && !ctx.force)
+ ctx->check();
+ if (!ctx->route() && !ctx->force)
log_error("Routing design failed.\n");
}
}
@@ -380,13 +398,13 @@ int main(int argc, char *argv[])
if (vm.count("asc")) {
std::string filename = vm["asc"].as<std::string>();
std::ofstream f(filename);
- write_asc(&ctx, f);
+ write_asc(ctx.get(), f);
}
#ifndef NO_PYTHON
if (vm.count("run")) {
init_python(argv[0], true);
- python_export_global("ctx", ctx);
+ python_export_global("ctx", *ctx.get());
std::vector<std::string> files = vm["run"].as<std::vector<std::string>>();
for (auto filename : files)
@@ -395,16 +413,6 @@ int main(int argc, char *argv[])
deinit_python();
}
#endif
-
-#ifndef NO_GUI
- if (vm.count("gui")) {
- Application a(argc, argv);
- MainWindow w;
- w.show();
-
- rc = a.exec();
- }
-#endif
return rc;
} catch (log_execution_error_exception) {
#if defined(_MSC_VER)
diff --git a/ice40/pack.cc b/ice40/pack.cc
index d1be4a29..76a52be0 100644
--- a/ice40/pack.cc
+++ b/ice40/pack.cc
@@ -18,7 +18,6 @@
*
*/
-#include "pack.h"
#include <algorithm>
#include <iterator>
#include <unordered_set>
@@ -577,8 +576,9 @@ static void pack_special(Context *ctx)
}
// Main pack function
-bool pack_design(Context *ctx)
+bool Arch::pack()
{
+ Context *ctx = getCtx();
try {
log_break();
pack_constants(ctx);
diff --git a/ice40/pack.h b/ice40/pack.h
deleted file mode 100644
index cdebdd79..00000000
--- a/ice40/pack.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * nextpnr -- Next Generation Place and Route
- *
- * Copyright (C) 2018 Clifford Wolf <clifford@symbioticeda.com>
- * Copyright (C) 2018 David Shah <david@symbioticeda.com>
- *
- * 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 PACK_H
-#define PACK_H
-
-#include "nextpnr.h"
-
-NEXTPNR_NAMESPACE_BEGIN
-
-bool pack_design(Context *ctx);
-
-NEXTPNR_NAMESPACE_END
-
-#endif // ROUTE_H