public void Add(TCLPin pin) { if (m_pins.ContainsKey(pin.Name)) { return; throw new ArgumentException("A pin named " + pin.Name + " has already been added"); } m_pins.Add(pin.Name, pin); }
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(); }