aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2018-05-26 14:27:21 +0200
committerClifford Wolf <clifford@clifford.at>2018-05-26 14:27:28 +0200
commit1899833b4db65e506746926831c323a8a8923fc4 (patch)
tree715a3133e699323da2476aa3ba0980fd745e6289
parent1338f0f9ebc1748d93ac331d277f2fd0c2cb30b4 (diff)
downloadnextpnr-1899833b4db65e506746926831c323a8a8923fc4.tar.gz
nextpnr-1899833b4db65e506746926831c323a8a8923fc4.tar.bz2
nextpnr-1899833b4db65e506746926831c323a8a8923fc4.zip
Start work on iCE40 chipdb
Signed-off-by: Clifford Wolf <clifford@clifford.at>
-rw-r--r--.gitignore3
-rw-r--r--Makefile21
-rw-r--r--ice40/.gitignore4
-rw-r--r--ice40/chip.cc34
-rw-r--r--ice40/chip.h224
-rw-r--r--ice40/chipdb.py114
-rw-r--r--ice40/main.cc30
-rw-r--r--ice40/makefile.inc17
8 files changed, 438 insertions, 9 deletions
diff --git a/.gitignore b/.gitignore
index f422c7f0..1ce0c108 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
-/build/
+/objs/
/nextpnr-dummy
+/nextpnr-ice40
diff --git a/Makefile b/Makefile
index 2ddcb724..fd669ba7 100644
--- a/Makefile
+++ b/Makefile
@@ -2,6 +2,11 @@ archs = dummy
common_objs = design.o
dummy_objs = chip.o main.o
+all::
+clean::
+
+include ice40/makefile.inc
+
CXX = clang
CXXFLAGS = -ggdb -MD -std=c++11 -O2 -Icommon
LDFLAGS = -ggdb
@@ -10,21 +15,21 @@ LDLIBS = -lstdc++
define binaries
all:: nextpnr-$(1)
-nextpnr-$(1): $$(addprefix build/$(1)-common-,$$(common_objs)) $$(addprefix build/$(1)-arch-,$$($(1)_objs))
+nextpnr-$(1): $$(addprefix objs/$(1)-common-,$$(common_objs)) $$(addprefix objs/$(1)-arch-,$$($(1)_objs))
$$(CXX) -o $$@ $$(LDFLAGS) -I$(1) $$^ $$(LDLIBS)
-build/$(1)-common-%.o: common/%.cc
- @mkdir -p build
+objs/$(1)-common-%.o: common/%.cc
+ @mkdir -p objs
$$(CXX) -c -o $$@ -D$$(shell echo arch_$(1) | tr a-z A-Z) $$(CXXFLAGS) -I$(1) $$<
-build/$(1)-arch-%.o: $(1)/%.cc
- @mkdir -p build
+objs/$(1)-arch-%.o: $(1)/%.cc
+ @mkdir -p objs
$$(CXX) -c -o $$@ -D$$(shell echo arch_$(1) | tr a-z A-Z) $$(CXXFLAGS) -I$(1) $$<
endef
$(foreach arch,$(archs),$(eval $(call binaries,$(arch))))
-clean:
- rm -rf $(addprefix nextpnr-,$(archs)) build
+clean::
+ rm -rf $(addprefix nextpnr-,$(archs)) objs
--include build/*.d
+-include objs/*.d
diff --git a/ice40/.gitignore b/ice40/.gitignore
new file mode 100644
index 00000000..e0813c20
--- /dev/null
+++ b/ice40/.gitignore
@@ -0,0 +1,4 @@
+/chipdb-1k.cc
+/chipdb-384.cc
+/chipdb-5k.cc
+/chipdb-8k.cc
diff --git a/ice40/chip.cc b/ice40/chip.cc
new file mode 100644
index 00000000..df7590ee
--- /dev/null
+++ b/ice40/chip.cc
@@ -0,0 +1,34 @@
+/*
+ * nextpnr -- Next Generation Place and Route
+ *
+ * Copyright (C) 2018 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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 "chip.h"
+
+Chip::Chip(ChipArgs)
+{
+}
+
+BelRange Chip::getBels() const
+{
+ return BelRange();
+}
+
+IdString Chip::getBelName(BelId bel) const
+{
+ return "*unknown*";
+}
diff --git a/ice40/chip.h b/ice40/chip.h
new file mode 100644
index 00000000..7dd39b63
--- /dev/null
+++ b/ice40/chip.h
@@ -0,0 +1,224 @@
+/*
+ * nextpnr -- Next Generation Place and Route
+ *
+ * Copyright (C) 2018 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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 "design.h"
+
+#ifndef CHIP_H
+#define CHIP_H
+
+struct BelId
+{
+ int32_t index = -1;
+
+ bool nil() const {
+ return index < 0;
+ }
+};
+
+struct WireId
+{
+ int32_t index = -1;
+
+ bool nil() const {
+ return index < 0;
+ }
+};
+
+namespace std
+{
+ template<> struct hash<BelId>
+ {
+ std::size_t operator()(const BelId &bel) const noexcept
+ {
+ return bel.index;
+ }
+ };
+
+ template<> struct hash<WireId>
+ {
+ std::size_t operator()(const WireId &wire) const noexcept
+ {
+ return wire.index;
+ }
+ };
+}
+
+struct BelIterator
+{
+ BelId *ptr = nullptr;
+
+ void operator++() { ptr++; }
+ bool operator!=(const BelIterator &other) const { return ptr != other.ptr; }
+ BelId operator*() const { return *ptr; }
+};
+
+struct BelRange
+{
+ BelIterator b, e;
+ BelIterator begin() const { return b; }
+ BelIterator end() const { return e; }
+};
+
+struct WireIterator
+{
+ WireId *ptr = nullptr;
+
+ void operator++() { ptr++; }
+ bool operator!=(const WireIterator &other) const { return ptr != other.ptr; }
+ WireId operator*() const { return *ptr; }
+};
+
+struct WireRange
+{
+ WireIterator b, e;
+ WireIterator begin() const { return b; }
+ WireIterator end() const { return e; }
+};
+
+struct WireDelay
+{
+ WireId wire;
+ float delay;
+};
+
+struct WireDelayIterator
+{
+ WireDelay *ptr = nullptr;
+
+ void operator++() { ptr++; }
+ bool operator!=(const WireDelayIterator &other) const { return ptr != other.ptr; }
+ WireDelay operator*() const { return *ptr; }
+};
+
+struct WireDelayRange
+{
+ WireDelayIterator b, e;
+ WireDelayIterator begin() const { return b; }
+ WireDelayIterator end() const { return e; }
+};
+
+struct BelPin
+{
+ BelId bel;
+ IdString pin;
+};
+
+struct BelPinIterator
+{
+ BelPin *ptr = nullptr;
+
+ void operator++() { ptr++; }
+ bool operator!=(const BelPinIterator &other) const { return ptr != other.ptr; }
+ BelPin operator*() const { return *ptr; }
+};
+
+struct BelPinRange
+{
+ BelPinIterator b, e;
+ BelPinIterator begin() const { return b; }
+ BelPinIterator end() const { return e; }
+};
+
+struct GuiLine
+{
+ float x1, y1, x2, y2;
+};
+
+struct ChipArgs
+{
+ enum {
+ NONE,
+ LP384,
+ LP1K,
+ LP8K,
+ HX1K,
+ HX8K,
+ UP5K
+ } type = NONE;
+};
+
+struct BelInfo
+{
+ const char *name;
+};
+
+struct WireDelayPOD
+{
+ int32_t wire_index;
+ float delay;
+};
+
+struct BelPortPOD
+{
+ int32_t bel_index;
+ int port_index;
+};
+
+struct WireInfo
+{
+ const char *name;
+ int num_uphill, num_downhill, num_bidir;
+ WireDelayPOD *wires_uphill, *wires_downhill, *wires_bidir;
+
+ int num_bels_downhill;
+ BelPortPOD bel_uphill;
+ BelPortPOD *bels_downhill;
+};
+
+struct Chip
+{
+ int num_bels, num_wires;
+ BelInfo *bel_data;
+ WireInfo *wire_data;
+
+ // ...
+
+ Chip(ChipArgs args);
+
+ void setBelActive(BelId bel, bool active);
+ bool getBelActive(BelId bel);
+
+ BelId getBelByName(IdString name) const;
+ WireId getWireByName(IdString name) const;
+ IdString getBelName(BelId bel) const;
+ IdString getWireName(WireId wire) const;
+
+ BelRange getBels() const;
+ BelRange getBelsByType(IdString type) const;
+ IdString getBelType(BelId bel) const;
+
+ void getBelPosition(BelId bel, float &x, float &y) const;
+ void getWirePosition(WireId wire, float &x, float &y) const;
+ vector<GuiLine> getBelGuiLines(BelId bel) const;
+ vector<GuiLine> getWireGuiLines(WireId wire) const;
+
+ WireRange getWires() const;
+ WireDelayRange getWiresUphill(WireId wire) const;
+ WireDelayRange getWiresDownhill(WireId wire) const;
+ WireDelayRange getWiresBidir(WireId wire) const;
+ WireDelayRange getWireAliases(WireId wire) const;
+
+ // the following will only operate on / return "active" BELs
+ // multiple active uphill BELs for a wire will cause a runtime error
+ WireId getWireBelPin(BelId bel, IdString pin) const;
+ BelPin getBelPinUphill(WireId wire) const;
+ BelPinRange getBelPinsDownhill(WireId wire) const;
+};
+
+#endif
diff --git a/ice40/chipdb.py b/ice40/chipdb.py
new file mode 100644
index 00000000..eec7aad0
--- /dev/null
+++ b/ice40/chipdb.py
@@ -0,0 +1,114 @@
+#!/usr/bin/env python3
+
+import sys
+
+dev_name = None
+dev_width = None
+dev_height = None
+num_wires = None
+
+wire_uphill = dict()
+wire_downhill = dict()
+wire_bidir = dict()
+
+with open(sys.argv[1], "r") as f:
+ mode = None
+
+ for line in f:
+ line = line.split()
+
+ if len(line) == 0 or line[0] == "#":
+ continue
+
+ if line[0] == ".device":
+ dev_name = line[1]
+ dev_width = int(line[2])
+ dev_height = int(line[3])
+ num_wires = int(line[4])
+ continue
+
+ if line[0] == ".net":
+ mode = ("net", int(line[1]))
+ continue
+
+ if line[0] == ".buffer":
+ mode = ("buffer", int(line[3]))
+ continue
+
+ if line[0] == ".routing":
+ mode = ("routing", int(line[3]))
+ continue
+
+ if (line[0][0] == ".") or (mode is None):
+ mode = None
+ continue
+
+ if mode[0] == "net":
+ continue
+
+ if mode[0] == "buffer":
+ wire_a = int(line[1])
+ wire_b = mode[1]
+ if wire_a not in wire_downhill:
+ wire_downhill[wire_a] = set()
+ if wire_b not in wire_uphill:
+ wire_uphill[wire_b] = set()
+ wire_downhill[wire_a].add(wire_b)
+ wire_uphill[wire_b].add(wire_a)
+ continue
+
+ if mode[0] == "routing":
+ wire_a = int(line[1])
+ wire_b = mode[1]
+ if wire_a not in wire_bidir:
+ wire_bidir[wire_a] = set()
+ if wire_b not in wire_bidir:
+ wire_bidir[wire_b] = set()
+ wire_bidir[wire_a].add(wire_b)
+ wire_bidir[wire_b].add(wire_b)
+ continue
+
+print('#include "chip.h"')
+
+wireinfo = list()
+
+for wire in range(num_wires):
+ num_uphill = 0
+ num_downhill = 0
+ num_bidir = 0
+
+ has_bel_uphill = False
+ num_bels_downhill = 0
+
+ if wire in wire_uphill:
+ num_uphill = len(wire_uphill[wire])
+ print("static WireDelayPOD wire%d_uphill[] = {" % wire)
+ print(",\n".join([" {%d, 1.0}" % other_wire for other_wire in wire_uphill[wire]]))
+ print("};")
+
+ if wire in wire_downhill:
+ num_downhill = len(wire_downhill[wire])
+ print("static WireDelayPOD wire%d_downhill[] = {" % wire)
+ print(",\n".join([" {%d, 1.0}" % other_wire for other_wire in wire_downhill[wire]]))
+ print("};")
+
+ if wire in wire_bidir:
+ num_bidir = len(wire_bidir[wire])
+ print("static WireDelayPOD wire%d_bidir[] = {" % wire)
+ print(",\n".join([" {%d, 1.0}" % other_wire for other_wire in wire_bidir[wire]]))
+ print("};")
+
+ info = " {"
+ info += "\"wire%d\", " % wire
+ info += "%d, %d, %d, " % (num_uphill, num_downhill, num_bidir)
+ info += ("wire%d_uphill, " % wire) if num_uphill > 0 else "nullptr, "
+ info += ("wire%d_downhill, " % wire) if num_downhill > 0 else "nullptr, "
+ info += ("wire%d_bidir, " % wire) if num_bidir > 0 else "nullptr, "
+ info += "}"
+
+ wireinfo.append(info)
+
+print("extern WireInfo wire_data_%s[%d];" % (dev_name, num_wires))
+print("WireInfo wire_data_%s[%d] = {" % (dev_name, num_wires))
+print(",\n".join(wireinfo))
+print("};")
diff --git a/ice40/main.cc b/ice40/main.cc
new file mode 100644
index 00000000..e3a784ca
--- /dev/null
+++ b/ice40/main.cc
@@ -0,0 +1,30 @@
+/*
+ * nextpnr -- Next Generation Place and Route
+ *
+ * Copyright (C) 2018 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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 "design.h"
+
+int main()
+{
+ Design design(ChipArgs{});
+
+ for (auto bel : design.chip.getBels())
+ printf("%s\n", design.chip.getBelName(bel).c_str());
+
+ return 0;
+}
diff --git a/ice40/makefile.inc b/ice40/makefile.inc
new file mode 100644
index 00000000..0dac3444
--- /dev/null
+++ b/ice40/makefile.inc
@@ -0,0 +1,17 @@
+archs += ice40
+ice40_objs = chip.o main.o
+
+define ice40_chipdb
+ice40_objs += chipdb-$(1).o
+ice40/chipdb-$(1).cc: ice40/chipdb.py /usr/local/share/icebox/chipdb-$(1).txt
+ python3 ice40/chipdb.py /usr/local/share/icebox/chipdb-$(1).txt > ice40/chipdb-$(1).cc.new
+ mv ice40/chipdb-$(1).cc.new ice40/chipdb-$(1).cc
+
+clean::
+ rm -f ice40/chipdb-$(1).cc
+endef
+
+$(eval $(call ice40_chipdb,384))
+$(eval $(call ice40_chipdb,1k))
+$(eval $(call ice40_chipdb,5k))
+$(eval $(call ice40_chipdb,8k))