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 + * + * 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 + * + * 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 + { + std::size_t operator()(const BelId &bel) const noexcept + { + return bel.index; + } + }; + + template<> struct hash + { + 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 getBelGuiLines(BelId bel) const; + vector 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 + * + * 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))