/// <summary> /// Copy constructor /// </summary> /// <param name="other"></param> public TCLRoutingTree(TCLRoutingTree other) { if (other == null) { return; } if (other.Root == null) { return; } Root = new TCLRoutingTreeNode(other.Root); Queue <Tuple <TCLRoutingTreeNode, TCLRoutingTreeNode> > pairs = new Queue <Tuple <TCLRoutingTreeNode, TCLRoutingTreeNode> >(); pairs.Enqueue(new Tuple <TCLRoutingTreeNode, TCLRoutingTreeNode>(Root, other.Root)); while (pairs.Count > 0) { Tuple <TCLRoutingTreeNode, TCLRoutingTreeNode> next = pairs.Dequeue(); for (int i = 0; i < next.Item2.Children.Count; i++) { next.Item1.Children[i] = new TCLRoutingTreeNode(next.Item2.Children[i]); pairs.Enqueue(new Tuple <TCLRoutingTreeNode, TCLRoutingTreeNode>(next.Item1.Children[i], next.Item2.Children[i])); } } }
private void ToTCL(TCLRoutingTreeNode node, StringBuilder buffer) { if (node == null) { buffer.Append("{}"); return; } // the first two node do need any tabs if (node.Depth >= 2) { buffer.AppendLine(@" \"); buffer.Append(string.Concat(Enumerable.Repeat("\t", node.Depth))); } // do not insert braces on last branch bool openBranch = node.Parent == null ? false : node.Parent.Children.Count > 1 && !node.Equals(node.Parent.Children[node.Parent.Children.Count - 1]); if (openBranch) { buffer.Append("{"); } // the node itself buffer.Append(node.Port.Name + (node.Children.Count == 0 ? "" : " ")); // the node has leaves only -> dump them without recursion if (node.Children.Count > 0 && node.Children.All(n => n.Children.Count == 0)) { for (int i = 0; i < node.Children.Count - 1; i++) { buffer.Append("{" + node.Children[i].Port.Name + "}"); if (i % 5 == 0 && i > 0) { buffer.AppendLine(@"\"); buffer.Append(string.Concat(Enumerable.Repeat("\t", node.Depth + 2))); } } // last branch goes without braces buffer.Append(node.Children[node.Children.Count - 1].Port.Name); } else { // the node has children which have children in turn -> recursion foreach (TCLRoutingTreeNode child in node.Children) { ToTCL(child, buffer); } } if (openBranch) { buffer.Append("}"); } }
public void UnflattenNet() { List <TCLRoutingTreeNode> nodeQueue = new List <TCLRoutingTreeNode>(RoutingTree.Root.Children); NetOutpin outPin = (NetOutpin)NetPins.First(np => np is NetOutpin); Tile rootTile = FPGA.FPGA.Instance.GetTile(outPin.TileName); TCLRoutingTreeNode newRoot = nodeQueue.FirstOrDefault(n => n.Tile.Location.Equals(rootTile.Location) && rootTile.GetSliceByName(outPin.SliceName).PortMapping.IsSliceOutPort(outPin.SlicePort)); nodeQueue.Remove(newRoot); NodeNet = false; RoutingTree.Root = newRoot; // try to assign each node to parent while (nodeQueue.Count > 0) { foreach (TCLRoutingTreeNode node in RoutingTree.GetAllRoutingNodes()) { bool addedNodes = false; // stay on tile TCLRoutingTreeNode nodeOnThisTile = nodeQueue.Find(n => n.Tile.Location.Equals(node.Tile.Location) && n.Tile.SwitchMatrix.Contains(node.Port, n.Port)); if (nodeOnThisTile != null) { node.Children.Add(nodeOnThisTile); nodeQueue.Remove(nodeOnThisTile); addedNodes = true; break; } // leave tile foreach (Location loc in Navigator.GetDestinations(node.Tile, node.Port)) { // look for next hop on loc.Tile TCLRoutingTreeNode nodeOnOtherTile = nodeQueue.Find(n => n.Tile.Location.Equals(loc.Tile.Location) && n.Tile.SwitchMatrix.Contains(loc.Pip, n.Port)); if (nodeOnOtherTile != null) { node.Children.Add(nodeOnOtherTile); nodeQueue.Remove(nodeOnOtherTile); addedNodes = true; break; } } if (addedNodes) { break; } } } }
public override bool Equals(object obj) { if (!(obj is TCLRoutingTreeNode)) { return(false); } TCLRoutingTreeNode other = (TCLRoutingTreeNode)obj; // TODO compare more? return (other.Tile.Location.Equals(Tile.Location) && other.Port.NameKey == Port.NameKey); }
/// <summary> /// Copy constructor /// </summary> /// <param name="other"></param> public TCLRoutingTreeNode(TCLRoutingTreeNode other) { Port = other.Port; Children = new Children(other.Children); foreach (TCLRoutingTreeNode child in Children) { child.Parent = this; } Children.Parent = this; Parent = other.Parent == null? null : new TCLRoutingTreeNode((TCLRoutingTreeNode)other.Parent); Tile = other.Tile; VirtualNode = other.VirtualNode; }
private void SetTiles(TCLRoutingTreeNode node, Tile tile, Command caller) { foreach (TCLRoutingTreeNode child in node.Children) { child.Tile = tile; bool destinationsFound = false; IEnumerable <Location> locs = Navigator.GetDestinations(tile.Location, child.Port.Name); if (locs.Count() == 1) { SetTiles(child, locs.First().Tile, caller); destinationsFound = true; } else if (locs.Count() > 1) { foreach (Location l in locs) { bool pathCanContinue = true; foreach (TCLRoutingTreeNode c in node.Children) { if (!l.Tile.SwitchMatrix.GetDrivenPorts(l.Pip).Contains(c.Port)) { pathCanContinue = false; } } if (pathCanContinue) { SetTiles(child, l.Tile, caller); destinationsFound = true; break; } } /* * Wenn es mehrere loc gibt, dann nimm die, von dessen loc.Pip aus die/der child.children erreichbar sind * Wenn es davon mehrer gibt --> Fehler * if (!child.Port.Name.StartsWith("IMUX") && !child.Port.Name.StartsWith("CLK")) * { * * } * caller.OutputManager.WriteWarning("Path is not unique, branching from node " + child); * */ } if (!destinationsFound) { SetTiles(child, tile, caller); } } }
public IEnumerable <TCLRoutingTreeNode> GetAllRoutingNodes(TCLRoutingTreeNode root) { // nothing to return in case of empty routing if (root != null) { yield return(root); foreach (TCLRoutingTreeNode child in root.Children) { foreach (TCLRoutingTreeNode other in GetAllRoutingNodes(child)) { yield return(other); } } } }
public void SetTiles(Command caller) { // no routing if (m_routingTree == null) { return; } // no routing if (m_routingTree.Root == null) { return; } if (m_routingTree.Root.VirtualNode) { foreach (TCLRoutingTreeNode child in m_routingTree.Root.Children) { if (child.Tile == null) { throw new ArgumentException("Can not set tiles for virtual node with child " + child + " in " + Name); } SetTiles(child, child.Tile, caller); } } else { // no start point if (OutpinInstance == null) { throw new ArgumentException("Can not set tiles due to missing geometrical information in " + Name); } else { Tile t = FPGA.FPGA.Instance.GetTile(OutpinInstance.TileKey); TCLRoutingTreeNode n = m_routingTree.Root; n.Tile = t; SetTiles(n, t, caller); } } }
public void FlattenNet() { // we do not need to overwrite TCLRoutingTree (which is only s very flat class) TCLRoutingTreeNode newRoot = new TCLRoutingTreeNode(null, null); newRoot.VirtualNode = true; // we can ignore virtual nodes as the new root will be the virtual new node foreach (TCLRoutingTreeNode node in RoutingTree.GetAllRoutingNodes().Where(n => !n.VirtualNode)) { newRoot.Children.Add(node); node.Parent = newRoot; } // clear children after iterating over GetAllRoutingNodes, otherwise this will change the result fromGetAllRoutingNodes foreach (TCLRoutingTreeNode node in newRoot.Children) { node.Children.Clear(); } NodeNet = true; RoutingTree.Root = newRoot; }
private void ParseRoutingTree(string line, ref TCLRoutingTreeNode root) { int i = 0; int braces = 0; int start = 0; string buffer = ""; TCLRoutingTreeNode current = root; while (i < line.Length) { switch (line[i]) { case ' ': if (!string.IsNullOrEmpty(buffer)) { // buffer is either something like INT_L_X26Y7/VCC_WIRE or EE2BEG0 TCLRoutingTreeNode node; string parameter = buffer; int split = buffer.IndexOf('/'); if (split > 0) { string tileName = buffer.Substring(0, split); string portName = buffer.Substring(split + 1, buffer.Length - split - 1); node = new TCLRoutingTreeNode(FPGA.FPGA.Instance.GetTile(tileName), new Port(portName)); } else { node = new TCLRoutingTreeNode(new Port(buffer)); } node.Parent = current; // if we create the root node, current is null if (root == null) { root = node; } else { current.Children.Add(node); } current = node; buffer = ""; } break; case '(': // read everything up to closing bracket start = i; while (i < line.Length) { if (line[i] == ')') { if (root == null) { ParseRoutingTree(line.Substring(start + 1, i - start - 1), ref root); } else { ParseRoutingTree(line.Substring(start + 1, i - start - 1), ref current); } break; } else { i++; } } break; case '{': if (braces != 0) { int subtreeBraces = 0; start = i; // extract substree, e.g., { .. {}} while (i < line.Length) { switch (line[i]) { case '{': subtreeBraces++; break; case '}': subtreeBraces--; break; default: break; } if (subtreeBraces == 0) { ParseRoutingTree(line.Substring(start, i - start + 1), ref current); // i++ done in outer loop break; } else { i++; } } } else { braces++; } break; case '}': braces--; break; default: buffer += line[i]; break; } i++; } if (braces != 0) { throw new ArgumentException("Incomplete routing tree found: " + line); } }
public override void ParseDesign(NetlistContainer nlc, Command caller) { TCLContainer container = (TCLContainer)nlc; Regex commentRegexp = new Regex(@"^\s*#", RegexOptions.Compiled); StreamReader sr = new StreamReader(m_fileName); FileInfo fi = new FileInfo(m_fileName); long charCount = 0; string line = ""; while ((line = sr.ReadLine()) != null) { //Console.WriteLine(line); if (line.Equals("debug")) { } charCount += line.Length; if (caller.PrintProgress) { caller.ProgressInfo.Progress = (int)((double)charCount / (double)fi.Length * caller.ProgressShare); } if (commentRegexp.IsMatch(line)) { continue; } int length = line.IndexOf('='); string linePrefix = line.Substring(0, length); string[] atoms = line.Split(';'); caller.Watch.Start("switch"); switch (linePrefix) { case "Cell": // BEL=IOB33.INBUF_EN(0),CLASS=cell(1), TCLInstance cellInstance = new TCLInstance(); cellInstance.AddCode(line); foreach (string atom in atoms.Where(a => !string.IsNullOrEmpty(a))) { string atomPrefix; string atomData; bool readOnly; bool property; Decompose(atom, out atomPrefix, out atomData, out readOnly, out property); // store special properties (i.e. name or properties that need ot modified) switch (atomPrefix) { case "NAME": cellInstance.Name = atomData; // flatten hierarchy to ease/enable netlist relocation cellInstance.Name = cellInstance.Name.Replace('/', '_'); break; case "LOC": Slice s = FPGA.FPGA.Instance.GetSlice(atomData); cellInstance.SliceName = s.SliceName; cellInstance.SliceType = s.SliceType; cellInstance.SliceNumber = s.ContainingTile.GetSliceNumberByName(s.SliceName); cellInstance.TileKey = s.ContainingTile.TileKey; cellInstance.Location = s.ContainingTile.Location; cellInstance.LocationX = s.ContainingTile.LocationX; cellInstance.LocationY = s.ContainingTile.LocationY; // we need a name and a location to add the instance break; case "BEL": cellInstance.BELType = atomData.Substring(atomData.LastIndexOf(".") + 1); break; } // Primitive is not a Xilinx primitive property, but denotes a primitive instance in a GoAhead netlist (*.viv_rpt if (property) { cellInstance.Properties.SetProperty(atomPrefix, atomData, readOnly); } } container.Add(cellInstance); break; case "Net": // Net=I_IBUF[0],Routing={},BelPin=SLICE_X20Y6/D6LUT/A5,BelPin=SLICE_X20Y11/C6LUT/A6,BelPin=IOB_X0Y1/INBUF_EN/OUT TCLNet net = new TCLNet("replacedLater"); net.AddCode(line); foreach (string atom in atoms.Where(a => !string.IsNullOrEmpty(a))) { string atomPrefix; string atomData; bool readOnly; bool property; Decompose(atom, out atomPrefix, out atomData, out readOnly, out property); switch (atomPrefix) { case "Net": net.Name = atomData; // flatten hierarchy to ease/enable netlist relocation net.Name = net.Name.Replace('/', '_'); // we need a name to add the net container.Add(net); break; case "Nodes": net.RoutingTree = new TCLRoutingTree(); net.RoutingTree.Root = new TCLRoutingTreeNode(null, null); net.RoutingTree.Root.VirtualNode = true; net.NodeNet = true; string[] nodes = atomData.Split(' '); foreach (string node in nodes) { string nodeTileName = node.Substring(0, node.IndexOf('/')); string nodePortName = node.Substring(node.IndexOf('/') + 1); TCLRoutingTreeNode routingNode = new TCLRoutingTreeNode(FPGA.FPGA.Instance.GetTile(nodeTileName), new Port(nodePortName)); net.RoutingTree.Root.Children.Add(routingNode); } break; case "BelPin": // BelPin=IOB_X0Y1/INBUF_EN/OUT string[] hierarchy = atomData.Split('/'); string sliceName = hierarchy[0]; string belName = hierarchy[1]; string portName = hierarchy[2]; Instance instance = container.GetInstanceBySliceName(sliceName, belName); // inst ist manchmal null, kommt bei ROUTETHROUGH vor, also zb A6 und es wird durch die LUT durchgeroutet Slice slice = FPGA.FPGA.Instance.GetSlice(sliceName); NetPin netPin; if (slice.PortMapping.IsSliceInPort(portName)) { netPin = new NetInpin(); netPin.TileName = slice.ContainingTile.Location; } else if (slice.PortMapping.IsSliceOutPort(portName)) { netPin = new NetOutpin(); net.OutpinInstance = instance; netPin.TileName = slice.ContainingTile.Location; } else { throw new ArgumentException("Cannot resolve direction of bel pin " + portName + " in line " + line); } netPin.InstanceName = instance != null? instance.Name : "unknown instance"; netPin.SliceName = sliceName; netPin.SlicePort = portName; netPin.Code = atomData; net.Add(netPin); break; case "ROUTE": case "FIXED_ROUTE": // we need the property TYPE before we can pasrs the net if (net.Properties.HasProperty("TYPE")) { // parse now net.RoutingTree = new TCLRoutingTree(); if (net.Type == TCLNet.NetType.POWER || net.Type == TCLNet.NetType.GROUND) // TODO more?? { net.RoutingTree.Root = new TCLRoutingTreeNode(null, null); net.RoutingTree.Root.VirtualNode = true; } ParseRoutingTree(atomData, ref net.RoutingTree.Root); } else { // parse later net.SetCode(atomData); } // do not set property ROUTE, as the ROUTE property is generated //net.Properties.SetProperty(atomPrefix, atomData, readOnly); break; case "TYPE": net.Properties.SetProperty(atomPrefix, atomData, readOnly); net.Type = (TCLNet.NetType)Enum.Parse(typeof(TCLNet.NetType), net.Properties.GetValue("TYPE")); if (net.RoutingTree == null) { net.RoutingTree = new TCLRoutingTree(); if (net.Type == TCLNet.NetType.POWER || net.Type == TCLNet.NetType.GROUND) { net.RoutingTree.Root = new TCLRoutingTreeNode(null, null); net.RoutingTree.Root.VirtualNode = true; } ParseRoutingTree(net.GetCode(), ref net.RoutingTree.Root); } break; default: net.Properties.SetProperty(atomPrefix, atomData, readOnly); break; } } break; case "Pin": TCLPin pin = new TCLPin(); pin.AddCode(line); foreach (string atom in atoms.Where(a => !string.IsNullOrEmpty(a))) { string atomPrefix; string atomData; bool readOnly; bool property; Decompose(atom, out atomPrefix, out atomData, out readOnly, out property); switch (atomPrefix) { case "Pin": pin.Name = atomData; container.Add(pin); break; default: pin.Properties.SetProperty(atomPrefix, atomData, readOnly); break; } } break; case "Port": TCLPort port = new TCLPort(); port.AddCode(line); foreach (string atom in atoms.Where(a => !string.IsNullOrEmpty(a))) { string atomPrefix; string atomData; bool readOnly; bool property; Decompose(atom, out atomPrefix, out atomData, out readOnly, out property); switch (atomPrefix) { case "Port": port.ExternalName = atomData; container.Add(port); break; default: port.Properties.SetProperty(atomPrefix, atomData, readOnly); break; } } break; case "Hierarchy": TCLDesignHierarchy hier = new TCLDesignHierarchy(); hier.AddCode(line); foreach (string atom in atoms.Where(a => !string.IsNullOrEmpty(a))) { string atomPrefix; string atomData; bool readOnly; bool property; Decompose(atom, out atomPrefix, out atomData, out readOnly, out property); switch (atomPrefix) { case "Hierarchy": hier.Name = atomData; container.Add(hier); break; default: hier.Properties.SetProperty(atomPrefix, atomData, readOnly); break; } } break; default: throw new ArgumentException("Unexpected netlist element: " + line); } caller.Watch.Stop("switch"); } foreach (TCLNet n in container.Nets) { int pinCount = int.Parse(n.Properties.GetValue("PIN_COUNT")); int flatPinCount = int.Parse(n.Properties.GetValue("FLAT_PIN_COUNT")); if (pinCount != flatPinCount) { } if (pinCount != n.NetPinCount) { //caller.OutputManager.WriteWarning("PIN_COUNT should match the number of BelPins in " + n.Name); } } foreach (TCLNet n in container.Nets) { caller.Watch.Start("SetTiles"); n.SetTiles(caller); caller.Watch.Stop("SetTiles"); caller.Watch.Start("SetPins"); n.SetPins(); caller.Watch.Stop("SetPins"); } sr.Close(); }