protected override void DoCommandAction() { FPGATypes.AssertBackendType(FPGATypes.BackendType.ISE); StringBuilder buffer = new StringBuilder(); buffer.AppendLine("################ GoAhead ################ GoAhead ################"); foreach (string netlistContainerName in NetlistContainerNames) { string anchor; List <XDLContainer> nlcs = new List <XDLContainer>(); nlcs.Add((XDLContainer)NetlistContainerManager.Instance.Get(netlistContainerName)); bool anchorFound = XDLContainer.GetAnchor(nlcs, out anchor); buffer.AppendLine("INST \"*inst_" + netlistContainerName + "\" LOC = \"" + anchor + "\"; # generated_by_GoAhead"); } // write to file if (File.Exists(FileName)) { TextWriter tw = new StreamWriter(FileName); tw.Write(buffer.ToString()); tw.Close(); } // write to gui OutputManager.WriteUCFOutput(buffer.ToString()); }
protected override void DoCommandAction() { FPGATypes.AssertBackendType(FPGATypes.BackendType.ISE); if (TileSelectionManager.Instance.NumberOfSelectedTiles == 0) { OutputManager.WriteOutput("Warning: No tiles selected"); } // read file DesignParser parser = DesignParser.CreateDesignParser(XDLInFile); // into design NetlistContainer inContainer = new XDLContainer(); parser.ParseDesign(inContainer, this); // store selected parts in outDesign XDLContainer outContainer = (XDLContainer)inContainer.GetSelectedDesignElements(); // write design to file StreamWriter sw = new StreamWriter(XDLOutFile, false); outContainer.WriteCodeToFile(sw); sw.Close(); if (!string.IsNullOrEmpty(BinaryNetlist)) { SaveXDLLibraryElementAsBinaryLibraryElement saveCmd = new SaveXDLLibraryElementAsBinaryLibraryElement(); saveCmd.FileName = BinaryNetlist; saveCmd.XDLFileName = XDLOutFile; CommandExecuter.Instance.Execute(saveCmd); } }
private void CutOffISE() { XDLContainer nlc = (XDLContainer)GetNetlistContainer(); int netsDone = 0; foreach (XDLNet n in nlc.Nets) { ProgressInfo.Progress = (int)((double)netsDone++ / (double)nlc.NetCount * 100); int pipCount = n.PipCount; //List<XDLPip> removedPips = n.Remove(p => Remove(p)); n.RemoveAllPinStatements(np => Remove(np, nlc)); // pip count changed -> probably a PRLink that may be decomposed if (pipCount != n.PipCount) { n.PRLink = true; } } nlc.Remove(inst => Remove(inst)); // remove all nets that are now empty nlc.Remove(n => n.PipCount == 0 && n.InpinCount == 0 && n.OutpinCount == 0); }
protected override void DoCommandAction() { FPGATypes.AssertBackendType(FPGATypes.BackendType.ISE); XDLContainer nlc = (XDLContainer)GetNetlistContainer(); AddTemplate(nlc, Template, Location, PrimitiveIndex); }
protected override void DoCommandAction() { FPGATypes.AssertBackendType(FPGATypes.BackendType.ISE); Slice where = FPGA.FPGA.Instance.Current.Slices[SliceNumber]; XDLMacroPort addedPort = new XDLMacroPort(PortName, new Port(PortString), where); XDLContainer netlistContainer = (XDLContainer)GetNetlistContainer(); netlistContainer.Add(addedPort); }
private void RemovePipsFromNet(XDLContainer netlistContainer, Dictionary <string, bool> targetLocations, XDLNet net) { int pipCount = net.PipCount; net.Remove(p => targetLocations.ContainsKey(p.Location)); net.RemoveAllPinStatements(np => targetLocations.ContainsKey(netlistContainer.GetInstance(np).Location)); // pip count changed -> probably a PRLink that may be decomposed if (pipCount != net.PipCount) { net.PRLink = true; } }
protected override void DoCommandAction() { FPGATypes.AssertBackendType(FPGATypes.BackendType.ISE); // read file DesignParser parser = DesignParser.CreateDesignParser(FileName); XDLContainer container = new XDLContainer(); // into design parser.ParseDesign(container, this); // derive name from file string elementName = Path.GetFileNameWithoutExtension(FileName); if (container.ModuleCount != 0) { // find ports to block and assign them to slices // as we want to either // connect these ports (if used) or // drive a '1' to (if unused) foreach (XDLModule module in container.Modules) { // new library element to be added to library LibraryElement libElement = new LibraryElement(); libElement.Containter = module; libElement.Name = elementName; libElement.PrimitiveName = elementName; libElement.LoadCommand = ToString(); // add lib element to library, BEFORE deriving block data as command SaveXDLLibraryElementAsBinaryLibraryElement access the element in the library Objects.Library.Instance.Add(libElement); DeriveBlockingData(libElement); } } else { // new library element to be added to library LibraryElement libElement = new LibraryElement(); libElement.Containter = container; libElement.Name = elementName; libElement.PrimitiveName = elementName; libElement.LoadCommand = ToString(); // add lib element to library, BEFORE deriving block data as command SaveXDLLibraryElementAsBinaryLibraryElement access the element in the library Objects.Library.Instance.Add(libElement); DeriveBlockingData(libElement); } }
protected override void DoCommandAction() { FPGATypes.AssertBackendType(FPGATypes.BackendType.ISE); XDLContainer netlistContainer = (XDLContainer)GetNetlistContainer(); Port from = new Port(From); Port to = new Port(To); if (!FPGA.FPGA.Instance.Current.SwitchMatrix.Contains(from, to)) { throw new ArgumentException("Tile " + FPGA.FPGA.Instance.Current + " does not contain arc " + from + " -> " + to); } if (FPGA.FPGA.Instance.Current.IsPortBlocked(from) && !((XDLNet)netlistContainer.LastNetAdded).Contains(FPGA.FPGA.Instance.Current, from)) { throw new ArgumentException("Port " + from + " on slice " + FPGA.FPGA.Instance.Current + " is blocked by another net"); } if (FPGA.FPGA.Instance.Current.IsPortBlocked(to) && !((XDLNet)netlistContainer.LastNetAdded).Contains(FPGA.FPGA.Instance.Current, to)) { throw new ArgumentException("Port " + to + " on slice " + FPGA.FPGA.Instance.Current + " is blocked by another net"); } if (netlistContainer == null) { throw new ArgumentException("No current macro"); } if (netlistContainer.LastNetAdded == null) { throw new ArgumentException("No current net"); } ((XDLNet)netlistContainer.LastNetAdded).Add(FPGA.FPGA.Instance.Current, from, to); if (!FPGA.FPGA.Instance.Current.IsPortBlocked(from)) { FPGA.FPGA.Instance.Current.BlockPort(from, Tile.BlockReason.Blocked); } if (!FPGA.FPGA.Instance.Current.IsPortBlocked(to)) { FPGA.FPGA.Instance.Current.BlockPort(to, Tile.BlockReason.Blocked); } }
protected override void DoCommandAction() { FPGATypes.AssertBackendType(FPGATypes.BackendType.ISE); XDLContainer design = (XDLContainer)GetNetlistContainer(); XDLContainer blocker = new XDLContainer(); // read file DesignParser parser = DesignParser.CreateDesignParser(Blocker); // into design parser.ParseDesign(blocker, this); /* * only the blocker net is deleted, the blocker instance remains part of the static design * foreach (XDLInstance inst in blocker.Instances) * { * if (design.HasInstanceBySliceName(inst.SliceName)) * { * this.OutputManager.WriteOutput("Resource conflict on instance " + inst.Name); * } * }*/ foreach (XDLNet net in blocker.Nets) { foreach (XDLPip pip in net.Pips) { Tile t = FPGA.FPGA.Instance.GetTile(pip.Location); if (t.IsPortBlocked(pip.From)) { OutputManager.WriteOutput("In net " + net.Name + ": resource conflict on FROM port " + pip); } if (t.IsPortBlocked(pip.To)) { OutputManager.WriteOutput("In net " + net.Name + ": resource conflict on TO port " + pip); } } } }
public static void AddTemplate(XDLContainer netlistContainer, string template, string location, int primitiveIndex) { StreamReader sr = new StreamReader(template); string wholeFile = sr.ReadToEnd(); sr.Close(); Tile t = FPGA.FPGA.Instance.GetTile(location); MatchCollection instanceMatches = m_regExpInstance.Matches(wholeFile); foreach (Match match in instanceMatches) { string instanceCode = match.Groups[1].Value; instanceCode = instanceCode.Replace("_LOCATION_", t.Location); instanceCode = instanceCode.Replace("_SLICENAME_", t.Slices[primitiveIndex].SliceName); instanceCode = instanceCode.Replace("_SLICETYPE_", t.Slices[primitiveIndex].SliceType); // attach usage t.Slices[primitiveIndex].Usage = FPGATypes.SliceUsage.Blocker; netlistContainer.AddSliceCodeBlock(instanceCode); } MatchCollection netMatches = m_regExpNets.Matches(wholeFile); foreach (Match netMatch in netMatches) { string netCode = netMatch.Groups[1].Value; // DSP and BRAM templates only use _LOCATION_ netCode = netCode.Replace("_LOCATION_", t.Location); // SLICEX templates only use _SLICENAME_ netCode = netCode.Replace("_SLICENAME_", t.Slices[primitiveIndex].SliceName); netlistContainer.AddNetCodeBlock(netCode); } }
protected override void DoCommandAction() { FPGATypes.AssertBackendType(FPGATypes.BackendType.ISE); DesignParser parser = DesignParser.CreateDesignParser(XDLFile); XDLContainer container = new XDLContainer(); parser.ParseDesign(container, this); VHDLParser moduleParser = new VHDLParser(VHDLModule); VHDLParserEntity ent = moduleParser.GetEntity(0); Dictionary <int, List <Signal> > east = new Dictionary <int, List <Signal> >(); Dictionary <int, List <Signal> > west = new Dictionary <int, List <Signal> >(); double xCenter, yCenter; TileSelectionManager.Instance.GetCenterOfSelection(t => TileSelectionManager.Instance.IsSelected(t.TileKey), out xCenter, out yCenter); foreach (HDLEntitySignal signal in ent.InterfaceSignals) { foreach (XDLNet net in container.Nets.Where(n => n.Name.StartsWith(signal.SignalName) && ((XDLNet)n).HasIndex()).OrderBy(n => ((XDLNet)n).GetIndex())) { Tile fromTile; Tile toTile; GetSourceAndSink(container, net, out fromTile, out toTile); GetSourceAndSink(container, net, out fromTile, out toTile); Tile innerTile = null; Tile outerTile = null; string signalMode = ""; if (!TileSelectionManager.Instance.IsSelected(fromTile.TileKey) && TileSelectionManager.Instance.IsSelected(toTile.TileKey)) { innerTile = toTile; outerTile = fromTile; signalMode = "in"; } else if (TileSelectionManager.Instance.IsSelected(fromTile.TileKey) && !TileSelectionManager.Instance.IsSelected(toTile.TileKey)) { outerTile = toTile; innerTile = fromTile; signalMode = "out"; } else { throw new ArgumentException("Expecting an instance inside the current selection"); } FPGATypes.InterfaceDirection dir = outerTile.TileKey.X < (int)xCenter ? FPGATypes.InterfaceDirection.East : FPGATypes.InterfaceDirection.West; Dictionary <int, List <Signal> > signalCollection = dir.Equals(FPGATypes.InterfaceDirection.East) ? east : west; if (!signalCollection.ContainsKey(innerTile.TileKey.Y)) { signalCollection.Add(innerTile.TileKey.Y, new List <Signal>()); } Signal s = new Signal(); s.Column = -1; s.SignalDirection = dir; s.SignalMode = signalMode; s.SignalName = net.Name; signalCollection[innerTile.TileKey.Y].Add(s); // weiter: vor verlaesst das gummiband die partielle flaeche? // vektoren nach osten oder westen? } } bool interleaveEast = east.Any(t => t.Value.Count > 4); bool interleaveWest = west.Any(t => t.Value.Count > 4); Dictionary <FPGA.FPGATypes.Direction, Dictionary <int, List <Signal> > > interfaces = new Dictionary <FPGATypes.Direction, Dictionary <int, List <Signal> > >(); interfaces.Add(FPGATypes.Direction.East, new Dictionary <int, List <Signal> >()); interfaces[FPGATypes.Direction.East][0] = new List <Signal>(); interfaces[FPGATypes.Direction.East][1] = new List <Signal>(); interfaces.Add(FPGATypes.Direction.West, new Dictionary <int, List <Signal> >()); interfaces[FPGATypes.Direction.West][0] = new List <Signal>(); interfaces[FPGATypes.Direction.West][1] = new List <Signal>(); if (interleaveEast) { int columnIndex = 0; foreach (KeyValuePair <int, List <Signal> > tupel in east) { foreach (Signal s in tupel.Value) { Signal copy = new Signal(s.SignalName, s.SignalMode, s.SignalDirection, "", columnIndex); interfaces[FPGATypes.Direction.East][columnIndex].Add(copy); columnIndex++; columnIndex %= 2; } } } //ent.InterfaceSignals }
private void RelocateInstancesForXDL(LibraryElement libElement, Tile anchorCLB, XDLContainer netlistContainer) { // reli foreach (Tuple <Instance, Tile> tileSliceTupel in libElement.GetInstanceTiles(anchorCLB, libElement)) { int sliceNumber = tileSliceTupel.Item1.SliceNumber; Slice slice = tileSliceTupel.Item2.Slices[sliceNumber]; string xdlCode = tileSliceTupel.Item1.ToString(); /* in TODO init.goa auslagern * @"placed.*SLICE_X\d+Y\d+"; * @"placed.*TIEOFF_X\d+Y\d+"; * @"placed.*RAMB16_X\d+Y\d+" * */ if (IdentifierManager.Instance.IsMatch(tileSliceTupel.Item1.Location, IdentifierManager.RegexTypes.CLB)) { // replace placement information in: inst "right" "SLICEX", placed CLEXL_X9Y33 SLICE_X13Y33 string newPlacement = "placed " + tileSliceTupel.Item2.Location + " " + slice.SliceName; string oldPlacement = @"placed.*SLICE_X\d+Y\d+"; xdlCode = Regex.Replace(xdlCode, oldPlacement, newPlacement); } else if (IdentifierManager.Instance.IsMatch(tileSliceTupel.Item1.Location, IdentifierManager.RegexTypes.Interconnect)) { string newPlacement = "placed " + tileSliceTupel.Item2.Location + " " + slice.SliceName; string oldPlacement = @"placed.*TIEOFF_X\d+Y\d+"; xdlCode = Regex.Replace(xdlCode, oldPlacement, newPlacement); } else if (IdentifierManager.Instance.IsMatch(tileSliceTupel.Item1.Location, IdentifierManager.RegexTypes.DSP)) { int underScoreLocation = tileSliceTupel.Item2.Location.IndexOf("_"); string locationPrefix = tileSliceTupel.Item2.Location.Substring(0, underScoreLocation); string newPlacement = "placed " + tileSliceTupel.Item2.Location + " " + slice.SliceName; string oldPlacement = "placed.*" + locationPrefix + @"_X\d+Y\d+.*" + tileSliceTupel.Item1.SliceName; xdlCode = Regex.Replace(xdlCode, oldPlacement, newPlacement); } else if (IdentifierManager.Instance.IsMatch(tileSliceTupel.Item1.Location, IdentifierManager.RegexTypes.BRAM)) { int underScoreLocation = tileSliceTupel.Item2.Location.IndexOf("_"); string locationPrefix = tileSliceTupel.Item2.Location.Substring(0, underScoreLocation); string newPlacement = "placed " + tileSliceTupel.Item2.Location + " " + slice.SliceName; string oldPlacement = "placed.*" + locationPrefix + @"_X\d+Y\d+.*" + tileSliceTupel.Item1.SliceName; //String oldPlacement = @"placed.*RAMB16_X\d+Y\d+"; xdlCode = Regex.Replace(xdlCode, oldPlacement, newPlacement); } if (InsertPrefix) { // insert instance prefix // remove greedy between double quotes MatchCollection matches = Regex.Matches(xdlCode, "(\".*?\")"); string oldInstanceName = matches[0].ToString(); oldInstanceName = Regex.Replace(oldInstanceName, "\"", ""); string newInstanceName = InstanceName + Regex.Replace(oldInstanceName, "\"", ""); // replace both the instance name AND slice configuration xdlCode = xdlCode.Replace("\"" + oldInstanceName, "\"" + newInstanceName); if (IdentifierManager.Instance.IsMatch(tileSliceTupel.Item1.Location, IdentifierManager.RegexTypes.BRAM)) { xdlCode = xdlCode.Replace("RAMB16BWER:" + oldInstanceName, "RAMB16BWER:" + newInstanceName); } // XDL Shape?? xdlCode = xdlCode.Replace("Shape_", InstanceName + "Shape_"); } netlistContainer.AddSliceCodeBlock(xdlCode); } }
private void RelocateNetsForXDL(LibraryElement libElement, Tile anchorCLB, XDLContainer netlistContainer) { foreach (XDLNet net in libElement.Containter.Nets) { // insert instance prefix XDLNet relocatedNet = new XDLNet(InstanceName + net.Name); relocatedNet.HeaderExtension = net.HeaderExtension; foreach (NetPin pin in net.NetPins) { NetPin copy = NetPin.Copy(pin); if (InsertPrefix) { // insert instance prefix // remove greedy between double quotes string oldInstanceName = pin.InstanceName; string newInstanceName = "\"" + InstanceName + Regex.Replace(oldInstanceName, "\"", "") + "\""; //xdlCode = Regex.Replace(xdlCode, oldInstanceName, newInstanceName); copy.InstanceName = newInstanceName; copy.InstanceName = copy.InstanceName.Replace("\"", ""); } relocatedNet.Add(copy); } //foreach (NetSegment seg in originalNet.GetAllSegments()) foreach (XDLPip pip in net.Pips) { string targetLocation; bool success = libElement.GetTargetLocation(pip.Location, anchorCLB, out targetLocation); Tile targetTile = null; if (FPGA.FPGA.Instance.Contains(targetLocation)) { targetTile = FPGA.FPGA.Instance.GetTile(targetLocation); } else { throw new ArgumentException("Error during relocation of pip " + pip + " to " + targetLocation); } XDLPip relocatedSegment = null; if (targetTile.SwitchMatrix.Contains(pip.From, pip.To)) { // we do not need to transform identifiers relocatedSegment = new XDLPip(targetTile.Location, pip.From, pip.Operator, pip.To); } else { // naming fun relocatedSegment = FPGATypes.RelocatePip(targetTile, pip, relocatedNet); } if (relocatedSegment == null) { throw new ArgumentException("Could not relocate " + pip.ToString() + " to tile " + targetLocation); } if (!targetTile.SwitchMatrix.Contains(relocatedSegment.From, relocatedSegment.To)) { throw new ArgumentException("Could not relocate " + pip.ToString() + " to tile " + targetLocation); } relocatedNet.Add(relocatedSegment); } if (netlistContainer.Nets.Any(n => n.Name.Equals(relocatedNet.Name))) { throw new ArgumentException("A net named " + relocatedNet.Name + " is alredy inserted to netlist " + netlistContainer.Name + ". Did you try to join two instances of the same macro in one?"); } netlistContainer.Add(relocatedNet); } }
private bool Remove(NetPin np, XDLContainer netlistContainer) { return(TileSelectionManager.Instance.IsSelected(FPGA.FPGA.Instance.GetTile(netlistContainer.GetInstance(np).Location).TileKey)); }
protected override void DoCommandAction() { FPGATypes.AssertBackendType(FPGATypes.BackendType.ISE); XDLContainer nlc = (XDLContainer)GetNetlistContainer(); List <string> fixedSliceConfigurations = new List <string>(); foreach (XDLInstance inst in nlc.Instances) { // A5LUT:Inst_PE/Mmult_OPA[31]_OPB[31]_MuLt_17_OUT_Madd10_cy<6>:#LUT -> A5LUT::#LUT string originalCode = inst.ToString(); string fixedCode = originalCode; if (!fixedCode.Contains("A5LUT::#OFF")) { fixedCode = Regex.Replace(fixedCode, " A5LUT:(.+?):#LUT:", " A5LUT::#LUT:"); } if (!fixedCode.Contains("B5LUT::#OFF")) { fixedCode = Regex.Replace(fixedCode, " B5LUT:(.+?):#LUT:", " B5LUT::#LUT:"); } if (!fixedCode.Contains("C5LUT::#OFF")) { fixedCode = Regex.Replace(fixedCode, " C5LUT:(.+?):#LUT:", " C5LUT::#LUT:"); } if (!fixedCode.Contains("D5LUT::#OFF")) { fixedCode = Regex.Replace(fixedCode, " D5LUT:(.+?):#LUT:", " D5LUT::#LUT:"); } if (!fixedCode.Contains("A6LUT::#OFF")) { fixedCode = Regex.Replace(fixedCode, " A6LUT:(.+?):#LUT:", " A6LUT::#LUT:"); } if (!fixedCode.Contains("B6LUT::#OFF")) { fixedCode = Regex.Replace(fixedCode, " B6LUT:(.+?):#LUT:", " B6LUT::#LUT:"); } if (!fixedCode.Contains("C6LUT::#OFF")) { fixedCode = Regex.Replace(fixedCode, " C6LUT:(.+?):#LUT:", " C6LUT::#LUT:"); } if (!fixedCode.Contains("D6LUT::#OFF")) { fixedCode = Regex.Replace(fixedCode, " D6LUT:(.+?):#LUT:", " D6LUT::#LUT:"); } // neu // A5FF:Inst_PE/Mmult_OPA[31]_OPB[31]_MuLt_18_OUT_OPA,OPB<20>_x_OPA,OPB<62>_mand1_FRB: -> A5FF:: if (!fixedCode.Contains("A5FF::")) { fixedCode = Regex.Replace(fixedCode, "A5FF:(.+?):", "A5FF::"); } if (!fixedCode.Contains("B5FF::")) { fixedCode = Regex.Replace(fixedCode, "B5FF:(.+?):", "B5FF::"); } if (!fixedCode.Contains("C5FF::")) { fixedCode = Regex.Replace(fixedCode, "C5FF:(.+?):", "C5FF::"); } if (!fixedCode.Contains("D5FF::")) { fixedCode = Regex.Replace(fixedCode, "D5FF:(.+?):", "D5FF::"); } // BFF:Inst_PE/config_data_en_0:#FF --> BFF::#FF if (!fixedCode.Contains("AFF::#OFF") && !fixedCode.Contains("AFF::#FF")) { fixedCode = Regex.Replace(fixedCode, "AFF:(.+?):", "AFF::"); } if (!fixedCode.Contains("BFF::#OFF") && !fixedCode.Contains("BFF::#FF")) { fixedCode = Regex.Replace(fixedCode, "BFF:(.+?):", "BFF::"); } if (!fixedCode.Contains("CFF::#OFF") && !fixedCode.Contains("CFF::#FF")) { fixedCode = Regex.Replace(fixedCode, "CFF:(.+?):", "CFF::"); } if (!fixedCode.Contains("DFF::#OFF") && !fixedCode.Contains("DFF::#FF")) { fixedCode = Regex.Replace(fixedCode, "DFF:(.+?):", "DFF::"); } fixedSliceConfigurations.Add(fixedCode); } nlc.Remove(delegate(Instance i) { return(true); }); foreach (string xdlCode in fixedSliceConfigurations) { nlc.AddSliceCodeBlock(xdlCode); } }
protected override void DoCommandAction() { FPGATypes.AssertBackendType(FPGATypes.BackendType.ISE); // read file DesignParser parser = DesignParser.CreateDesignParser(XDLInFile); // into design XDLContainer container = new XDLContainer(); parser.ParseDesign(container, this); XDLNet netWithOutPin = (XDLNet)container.Nets.FirstOrDefault(n => n.OutpinCount == 1 && string.IsNullOrEmpty(((XDLNet)n).HeaderExtension)); if (netWithOutPin == null) { throw new ArgumentException("No net with outpin found"); } List <string> namesOfNetsWithoutOutpin = new List <string>(); foreach (Net net in container.Nets.Where(n => n.OutpinCount == 0)) { namesOfNetsWithoutOutpin.Add(net.Name); } foreach (string netName in namesOfNetsWithoutOutpin) { XDLNet net = (XDLNet)container.Nets.FirstOrDefault(n => n.Name.Equals(netName)); if (net == null) { throw new ArgumentException("Net " + netName + " not found"); } foreach (XDLPip pip in net.Pips) { netWithOutPin.Add(pip); } net.ClearPips(); } System.IO.TextWriter tw = new System.IO.StreamWriter(XDLOutFile, false); tw.WriteLine(container.GetDesignConfig().ToString()); foreach (XDLModule mod in container.Modules) { tw.WriteLine(mod.ToString()); } foreach (XDLPort p in container.Ports) { tw.WriteLine(p.ToString()); } foreach (XDLInstance inst in container.Instances) { tw.WriteLine(inst.ToString()); } foreach (XDLNet net in container.Nets) { tw.WriteLine(net.ToString()); } tw.Close(); }