Merge pull request #184 from nathanrossi/nrossi/portable-chipdb

icetime: Add support for searching for chipdb relative to binary
diff --git a/docs/index.html b/docs/index.html
index 919122e..a8ab14b 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -301,7 +301,7 @@
 <p>
 Recommended reading:
 <a href="http://www.latticesemi.com/~/media/LatticeSemi/Documents/DataSheets/iCE/iCE40LPHXFamilyDataSheet.pdf">Lattice iCE40 LP/HX Family Datasheet</a>,
-<a href="http://www.latticesemi.com/~/media/LatticeSemi/Documents/TechnicalBriefs/SBTICETechnologyLibrary201504.pdf">Lattice iCE Technology Library</a>
+<a href="http://www.latticesemi.com/~/media/LatticeSemi/Documents/TechnicalBriefs/SBTICETechnologyLibrary201608.pdf">Lattice iCE Technology Library</a>
 (Especially the three pages on "Architecture Overview", "PLB Blocks", "Routing", and "Clock/Control Distribution Network" in
 the Lattice iCE40 LP/HX Family Datasheet. Read that first, then come back here.)
 </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 @@
         #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 @@
                     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 @@
                 continue
             add_entry(entry, bits)
 
+        self.symbols = {}
         self.buffers = []
         self.routings = []
         self.bits_set = set()
@@ -830,6 +831,12 @@
         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 @@
             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 @@
                 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/icetime.cc b/icetime/icetime.cc
index 16ad142..a5a27a0 100644
--- a/icetime/icetime.cc
+++ b/icetime/icetime.cc
@@ -1305,7 +1305,7 @@
 		} 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;
 	}