diff options
author | Ruben Undheim <ruben.undheim@gmail.com> | 2018-12-05 08:24:49 +0100 |
---|---|---|
committer | Ruben Undheim <ruben.undheim@gmail.com> | 2018-12-05 08:24:49 +0100 |
commit | 8cdaf84defddf5a7bd1c4551ece81b9d832e4595 (patch) | |
tree | 633fb613368bc4d1f26a63fc5142b4de3a9b6cc5 | |
parent | e515d7ff6e4e71b3e5fe6b264427029f2e3c9e72 (diff) | |
parent | 8cbb9960214d27e06e6e69c57e77f4178dcfe36b (diff) |
Merge tag 'upstream/0_20181109git9671b76'
Upstream version 0~20181109git9671b76
-rw-r--r-- | config.mk | 9 | ||||
-rw-r--r-- | docs/index.html | 27 | ||||
-rw-r--r-- | icebox/icebox.py | 24 | ||||
-rwxr-xr-x | icebox/icebox_hlc2asc.py | 20 | ||||
-rw-r--r-- | icetime/Makefile | 3 | ||||
-rw-r--r-- | icetime/icetime.cc | 35 | ||||
-rw-r--r-- | icetime/iceutil.cc | 179 |
7 files changed, 261 insertions, 36 deletions
@@ -1,4 +1,5 @@ PREFIX ?= /usr/local +DEBUG ?= 0 CXX ?= clang++ CC ?= clang @@ -6,12 +7,12 @@ PKG_CONFIG ?= pkg-config C_STD ?= c99 CXX_STD ?= c++11 -ifeq ($(EMCC),1) -OPT_LEVEL ?= 2 -DBG_LEVEL ?= -else +ifeq ($(DEBUG),1) OPT_LEVEL ?= 0 DBG_LEVEL ?= -ggdb +else +OPT_LEVEL ?= 2 +DBG_LEVEL ?= endif WARN_LEVEL ?= all diff --git a/docs/index.html b/docs/index.html index a8ab14b..efda996 100644 --- a/docs/index.html +++ b/docs/index.html @@ -142,7 +142,8 @@ Installing prerequisites (this command is for Ubuntu 14.04): <pre style="padding-left: 3em"> sudo apt-get install build-essential clang bison flex libreadline-dev \ gawk tcl-dev libffi-dev git mercurial graphviz \ - xdot pkg-config python python3 libftdi-dev + xdot pkg-config python python3 libftdi-dev \ + qt5-default python3-dev libboost-dev </pre> <p> @@ -152,10 +153,15 @@ On Fedora 24 the following command installs all prerequisites: <pre style="padding-left: 3em"> sudo dnf install make automake gcc gcc-c++ kernel-devel clang bison \ flex readline-devel gawk tcl-devel libffi-devel git mercurial \ - graphviz python-xdot pkgconfig python python3 libftdi-devel + graphviz python-xdot pkgconfig python python3 libftdi-devel \ + qt5-devel python3-devel boost-devel </pre> <p> +Note: All tools will be installed relative to /usr/local +</p> + +<p> Installing the <a href="https://github.com/cliffordwolf/icestorm">IceStorm Tools</a> (icepack, icebox, iceprog, icetime, chip databases): </p> @@ -165,7 +171,7 @@ make -j$(nproc) sudo make install</pre> <p> -Installing <a href="https://github.com/cseed/arachne-pnr">Arachne-PNR</a> (the place&route tool): +Installing <a href="https://github.com/cseed/arachne-pnr">Arachne-PNR</a> (place&route tool, predecessor to NextPNR): </p> <pre style="padding-left: 3em">git clone https://github.com/cseed/arachne-pnr.git arachne-pnr @@ -174,6 +180,16 @@ make -j$(nproc) sudo make install</pre> <p> +Installing <a href="https://github.com/YosysHQ/nextpnr">NextPNR</a> (place&route tool, Arachne-PNR replacement): +</p> + +<pre style="padding-left: 3em">git clone https://github.com/YosysHQ/nextpnr nextpnr +cd nextpnr +cmake -DARCH=ice40 -DCMAKE_INSTALL_PREFIX=/usr/local . +make -j$(nproc) +sudo make install</pre> + +<p> Installing <a href="http://www.clifford.at/yosys/">Yosys</a> (Verilog synthesis): </p> @@ -183,8 +199,9 @@ make -j$(nproc) sudo make install</pre> <p> -The Arachne-PNR build converts the IceStorm text chip databases into the arachne-pnr binary chip databases. Always rebuild Arachne-PNR -after updating your IceStorm installation. +Both place and route tools (Arachne-PNR & NextPNR) convert the IceStorm +text chip databases into the respective PNR binary chip databases during build. +Always rebuild the PNR tools after updating your IceStorm installation. </p> <p> diff --git a/icebox/icebox.py b/icebox/icebox.py index 41d6bac..f49d7ed 100644 --- a/icebox/icebox.py +++ b/icebox/icebox.py @@ -704,6 +704,26 @@ class iceconfig: #print('\tafter directions', neighbours) return neighbours + def get_net_number(self, segment): + if not hasattr(self, 'net_map') or self.net_map is None: + self.net_map = {} + for netidx, group in enumerate(sorted(self.all_group_segments())): + for seg in group: + self.net_map[seg] = netidx + + return self.net_map[segment] + + def all_group_segments(self): + if not hasattr(self, 'all_groups') or self.all_groups is None: + all_tiles = set() + for x in range(self.max_x + 1): + for y in range(self.max_y + 1): + if self.tile(x, y) is not None: + all_tiles.add((x, y)) + + self.all_groups = self.group_segments(all_tiles, connect_gb=False) + return self.all_groups + def group_segments(self, all_from_tiles=set(), extra_connections=list(), extra_segments=list(), connect_gb=True): seed_segments = set() seen_segments = set() @@ -957,7 +977,9 @@ class iceconfig: print(line, file=f) for extra_bit in sorted(self.extra_bits): print(".extra_bit %d %d %d" % extra_bit, file=f) - + for net in sorted(self.symbols.keys()): + for sym_key in self.symbols[net]: + print(".sym %s %s" % (net, sym_key), file=f) class tileconfig: def __init__(self, tile): self.bits = set() diff --git a/icebox/icebox_hlc2asc.py b/icebox/icebox_hlc2asc.py index 6fe9d1c..8b82132 100755 --- a/icebox/icebox_hlc2asc.py +++ b/icebox/icebox_hlc2asc.py @@ -742,6 +742,7 @@ class Tile: continue add_entry(entry, bits) + self.symbols = {} self.buffers = [] self.routings = [] self.bits_set = set() @@ -830,6 +831,12 @@ clearing:{:<30} - current set :{}""".format( elif len(fields) >= 5 and (fields[1] == '->' or fields[1] == '~>'): self.read(fields[:3]) self.read(fields[2:]) + elif len(fields) == 3 and fields[1] == '.sym>': + nn = untranslate_netname(self.x, self.y, + self.ic.max_x - 1, + self.ic.max_y - 1, fields[0]) + net = self.ic.get_net_number( (self.x, self.y, nn) ) + self.ic.symbols.setdefault(net, set()).add(fields[2]) else: raise ParseError("Unknown Tile specification format") @@ -907,6 +914,13 @@ class LogicCell: else: self.tile.read(fields) return + elif len(fields) == 3 and fields[1] == '.sym>': + nn = untranslate_netname(self.tile.x, self.tile.y, + self.tile.ic.max_x - 1, + self.tile.ic.max_y - 1, fields[0]) + net = self.tile.ic.get_net_number( (self.tile.x, self.tile.y, nn) ) + self.tile.ic.symbols.setdefault(net, set()).add(fields[2]) + bits = ''.join([ self.lut_bits[15], self.lut_bits[12], @@ -1081,6 +1095,12 @@ Should be at io_tile {},{} io{} self.tile.read(fields[:-1] + [prefix + fields[-1]]) else: self.tile.read(fields) + elif len(fields) == 3 and fields[1] == '.sym>': + nn = untranslate_netname(self.tile.x, self.tile.y, + self.tile.ic.max_x - 1, + self.tile.ic.max_y - 1, fields[0]) + net = self.tile.ic.get_net_number( (self.tile.x, self.tile.y, nn) ) + self.tile.ic.symbols.setdefault(net, set()).add(fields[2]) else: raise ParseError("Unknown IOBlock specification format: {}".format(fields)) diff --git a/icetime/Makefile b/icetime/Makefile index d260681..b1cd18d 100644 --- a/icetime/Makefile +++ b/icetime/Makefile @@ -26,10 +26,11 @@ share/$(CHIPDB_SUBDIR)/chipdb-5k.txt: ../icebox/chipdb-5k.txt override LDFLAGS += --embed-file share endif -icetime$(EXE): icetime.o +icetime$(EXE): icetime.o iceutil.o $(CXX) -o $@ $(LDFLAGS) $^ $(LDLIBS) icetime.o: icetime.cc timings.inc +iceutil.o: iceutil.cc timings.inc: timings.py ../icefuzz/timings_*.txt python3 timings.py > timings.inc.new diff --git a/icetime/icetime.cc b/icetime/icetime.cc index 35ce99a..a5a27a0 100644 --- a/icetime/icetime.cc +++ b/icetime/icetime.cc @@ -38,6 +38,8 @@ #include <emscripten.h> #endif +std::string find_chipdb(std::string config_device); + // add this number of ns as estimate for clock distribution mismatch #define GLOBAL_CLK_DIST_JITTER 0.1 @@ -322,35 +324,18 @@ void read_config() void read_chipdb() { char buffer[1024]; + std::string filepath = chipdbfile; - if (!chipdbfile.empty()) { - snprintf(buffer, 1024, "%s", chipdbfile.c_str()); - } else - if (PREFIX[0] == '~' && PREFIX[1] == '/') { - std::string homedir; -#ifdef _WIN32 - if (getenv("USERPROFILE") != nullptr) { - homedir += getenv("USERPROFILE"); - } - else { - if (getenv("HOMEDRIVE") != nullptr && - getenv("HOMEPATH") != nullptr) { - homedir += getenv("HOMEDRIVE"); - homedir += getenv("HOMEPATH"); - } - } -#else - homedir += getenv("HOME"); -#endif - snprintf(buffer, 1024, "%s%s/share/" CHIPDB_SUBDIR "/chipdb-%s.txt", homedir.c_str(), PREFIX+1, config_device.c_str()); - } else { - snprintf(buffer, 1024, PREFIX "/share/" CHIPDB_SUBDIR "/chipdb-%s.txt", config_device.c_str()); + if (filepath.empty()) + filepath = find_chipdb(config_device); + if (filepath.empty()) { + fprintf(stderr, "Can't find chipdb file for device %s\n", config_device.c_str()); + exit(1); } - FILE *fdb = fopen(buffer, "r"); + FILE *fdb = fopen(filepath.c_str(), "r"); if (fdb == nullptr) { perror("Can't open chipdb file"); - fprintf(stderr, " %s\n", buffer); exit(1); } @@ -1320,7 +1305,7 @@ std::string ecnetname_to_vlog(std::string ec_name) } else { return ec_name; } - } catch(std::invalid_argument e) { // Not numeric and stoi throws exception + } catch(std::invalid_argument &e) { // Not numeric and stoi throws exception return ec_name; } diff --git a/icetime/iceutil.cc b/icetime/iceutil.cc new file mode 100644 index 0000000..ad8d662 --- /dev/null +++ b/icetime/iceutil.cc @@ -0,0 +1,179 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 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 <errno.h> +#include <string> +#include <sstream> +#include <cstring> + +#ifdef _WIN32 +# include <windows.h> +# include <io.h> +#elif defined(__APPLE__) +# include <mach-o/dyld.h> +# include <unistd.h> +#else +# include <unistd.h> +#endif + +#ifdef __FreeBSD__ +# include <sys/sysctl.h> +#endif + +#include <limits.h> + +#if defined(__linux__) || defined(__CYGWIN__) +std::string proc_self_dirname() +{ + char path[PATH_MAX]; + ssize_t buflen = readlink("/proc/self/exe", path, sizeof(path)); + if (buflen < 0) { + fprintf(stderr, "fatal error: readlink(\"/proc/self/exe\") failed: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + while (buflen > 0 && path[buflen-1] != '/') + buflen--; + return std::string(path, buflen); +} +#elif defined(__FreeBSD__) +std::string proc_self_dirname() +{ + int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1}; + size_t buflen; + char *buffer; + std::string path; + if (sysctl(mib, 4, NULL, &buflen, NULL, 0) != 0) { + fprintf(stderr, "fatal error: sysctl failed: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + buffer = (char*)malloc(buflen); + if (buffer == NULL) { + fprintf(stderr, "fatal error: malloc failed: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + if (sysctl(mib, 4, buffer, &buflen, NULL, 0) != 0) { + fprintf(stderr, "fatal error: sysctl failed: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + while (buflen > 0 && buffer[buflen-1] != '/') + buflen--; + path.assign(buffer, buflen); + free(buffer); + return path; +} +#elif defined(__APPLE__) +std::string proc_self_dirname() +{ + char *path = NULL; + uint32_t buflen = 0; + while (_NSGetExecutablePath(path, &buflen) != 0) + path = (char *) realloc((void *) path, buflen); + while (buflen > 0 && path[buflen-1] != '/') + buflen--; + return std::string(path, buflen); +} +#elif defined(_WIN32) +std::string proc_self_dirname() +{ + int i = 0; +# ifdef __MINGW32__ + char longpath[MAX_PATH + 1]; + char shortpath[MAX_PATH + 1]; +# else + WCHAR longpath[MAX_PATH + 1]; + TCHAR shortpath[MAX_PATH + 1]; +# endif + if (!GetModuleFileName(0, longpath, MAX_PATH+1)) { + fprintf(stderr, "fatal error: GetModuleFileName() failed.\n"); + exit(EXIT_FAILURE); + } + if (!GetShortPathName(longpath, shortpath, MAX_PATH+1)) { + fprintf(stderr, "fatal error: GetShortPathName() failed.\n"); + exit(EXIT_FAILURE); + } + while (shortpath[i] != 0) + i++; + while (i > 0 && shortpath[i-1] != '/' && shortpath[i-1] != '\\') + shortpath[--i] = 0; + std::string path; + for (i = 0; shortpath[i]; i++) + path += char(shortpath[i]); + return path; +} +#elif defined(EMSCRIPTEN) +std::string proc_self_dirname() +{ + return "/"; +} +#else + #error Dont know how to determine process executable base path! +#endif + +bool file_test_open(std::string path) +{ + FILE *fdb = fopen(path.c_str(), "r"); + if (fdb == nullptr) { + return false; + } + fclose(fdb); + return true; +} + +extern bool verbose; + +std::string find_chipdb(std::string config_device) +{ + if (PREFIX[0] == '~' && PREFIX[1] == '/') { + std::string homepath; +#ifdef _WIN32 + if (getenv("USERPROFILE") != nullptr) { + homepath += getenv("USERPROFILE"); + } + else { + if (getenv("HOMEDRIVE") != nullptr && + getenv("HOMEPATH") != nullptr) { + homepath += getenv("HOMEDRIVE"); + homepath += getenv("HOMEPATH"); + } + } +#else + homepath += getenv("HOME"); +#endif + homepath += std::string(PREFIX + 1) + "/" CHIPDB_SUBDIR "/chipdb-" + config_device + ".txt"; + if (verbose) + fprintf(stderr, "Looking for chipdb '%s' at %s\n", config_device.c_str(), homepath.c_str()); + if (file_test_open(homepath)) + return homepath; + } + + std::string prefixpath = PREFIX "/share/" CHIPDB_SUBDIR "/chipdb-" + config_device + ".txt"; + if (verbose) + fprintf(stderr, "Looking for chipdb '%s' at %s\n", config_device.c_str(), prefixpath.c_str()); + if (file_test_open(prefixpath)) + return prefixpath; + + std::string relbinarypath = proc_self_dirname() + "../share/" CHIPDB_SUBDIR "/chipdb-" + config_device + ".txt"; + if (verbose) + fprintf(stderr, "Looking for chipdb '%s' at %s\n", config_device.c_str(), relbinarypath.c_str()); + if (file_test_open(relbinarypath)) + return relbinarypath; + + return ""; +} + |