// ソースを解析して Entity の階層関係を作成 public List <EntityHierarchyItem> Update() { Dictionary <string, string> inFile = new Dictionary <string, string>(); Dictionary <string, List <string> > duplicatedEntities = new Dictionary <string, List <string> >(); List <string> entities = new List <string>(); items = new List <EntityHierarchyItem>(); List <VHDLSource.Component> components = new List <VHDLSource.Component>(); // Entity, Component 宣言を数え上げる foreach (string FileName in project.sourceFiles) { VHDLSource src = new VHDLSource(FileName); if (!src.isValid) { continue; } foreach (string entity in src.entities) { if (entities.Contains(entity)) { if (!duplicatedEntities.ContainsKey(entity)) { duplicatedEntities[entity] = new List <string>(); duplicatedEntities[entity].Add(inFile[entity]); } duplicatedEntities[entity].Add(FileName); } else { entities.Add(entity); inFile[entity] = FileName; } } foreach (VHDLSource.Component component in src.components) { components.Add(component); } } if (entities.Count == 0) { return(InvalidHierarchy("<!> Entity が見つかりません.")); } if (duplicatedEntities.Count != 0) { return(ReportDuplicatedEntities(duplicatedEntities)); } // 他から参照されていない Entity を列挙 List <string> roots = new List <string>(entities); foreach (VHDLSource.Component component in components) { if (roots.Contains(component.Name)) { roots.Remove(component.Name); } } if (roots.Count == 0) { return(InvalidHierarchy("<!> Entity の循環参照を検出しました.")); } // 参照をたどり,木を生成 List <List <EntityHierarchyItem> > trees = new List <List <EntityHierarchyItem> >(); foreach (string root in roots) { List <EntityHierarchyItem> tree = SearchEntityTree(root, new List <string>(), entities, components); if (tree == null) { return(InvalidHierarchy("<!> Entity の循環参照を検出しました.")); } trees.Add(tree); } trees.Sort((a, b) => b.Count - a.Count); // トップモジュール・波形ファイルの設定 if (!entities.Contains(project.topModule) || project.guessTopModule) { project.topModule = trees[0][0].Name; project.guessTopModule = true; } if (entities.Contains(project.topModule)) { string file = inFile[project.topModule]; int pos = file.LastIndexOf("."); pos = (pos == -1) ? file.Length : pos; project.wavePath = Path.GetDirectoryName(file) + "\\" + Path.GetFileNameWithoutExtension(file) + ".vcd"; } // 各 Entity に対応するソースのパス名を設定 foreach (List <EntityHierarchyItem> tree in trees) { foreach (EntityHierarchyItem item in tree) { if (inFile.ContainsKey(item.Name)) { item.LongPath = inFile[item.Name]; item.ShortPath = Path.GetFileName(item.LongPath); } item.IsTop = item.Name.Equals(project.topModule); } items.AddRange(tree); } return(items); }
// GHDLを何度か実行して,VHDLのコンパイルとシミュレーションを行う public static void CompileAndSimulate() { int numSources = 0, numErrors = 0; string args; const string compileOption = "-fexplicit -fsynopsys"; string simulationOption = "--vcd=wave.vcd --ieee-asserts=disable --stop-time=" + settings.simLimit; List <VHDLSource> sources = new List <VHDLSource>(); // 入力が空でないかをチェック if (!settings.Check()) { return; } settings.Save(); if (!currentProject.Check()) { return; } // 入力のリストアップ・整形・解析 args = "-a " + compileOption; CleanWorkDir(); GHDLResult analResult = null; foreach (string FileName in currentProject.sourceFiles) { numSources += 1; VHDLSource newSource = new VHDLSource(FileName, numSources); if (newSource.isValid) { newSource.CheckDataFileReference(currentProject.hierarchy); newSource.CopyToWorkDirectory(workDir); } if (!newSource.isValid) { Warn(newSource.content); return; } sources.Add(newSource); args = "-a " + compileOption + " " + newSource.FileName.Internal; analResult = ExecToolAndGetResult(GetGHDLPath(), args, analResult); if (analResult == null) { return; } if (analResult.code != 0) { numErrors += 1; } } // 解析にエラーがなければ,再解析(Elaborate)を行う if (numErrors == 0) { args = "-e " + compileOption + " " + currentProject.topModule; analResult = ExecToolAndGetResult(GetGHDLPath(), args, analResult); if (analResult == null) { return; } if (analResult.code != 0) { numErrors = -1; } } // ソースの解析結果の整形 analResult.RestoreFileName(currentProject.sourceFiles); if (numErrors != 0) { string errorIn; if (numErrors == -1) { errorIn = "ファイル全体"; } else { errorIn = numErrors + "個のファイル"; } Warn(errorIn + "の解析中にエラーが発生しました.詳しくはログを参照してください."); analResult.code = 1; analResult.ShowMessage(); return; } else if (analResult.message != "") { analResult.ShowMessage(); if (!WarnAndConfirm("解析中に警告が発生しました.詳しくはログを参照してください.\n" + "続けてシミュレーションを行いますか?")) { return; } } // シミュレーションとその結果の整形 args = "-r " + compileOption + " " + currentProject.topModule + " " + simulationOption; GHDLResult simResult = ExecToolAndGetResult(GetGHDLPath(), args); if (simResult == null) { return; } simResult.RestoreFileName(currentProject.sourceFiles); if (simResult.violateAssertion) { String timeString = String.Format("{0:#,0.###}", simResult.simTime / 1000000.0); Info("シミュレーションは " + timeString + " ns 後に停止しました."); } else if (simResult.code != 0) { Warn("シミュレーション中にエラーが発生しました.詳しくはログを参照してください."); simResult.ShowMessage(); return; } else { Warn("シミュレーションは " + settings.simLimit + " 以内に終了しませんでした."); } // 出力ファイル(波形・テストベンチ出力)のコピー try { File.Copy(workDir + "wave.vcd", currentProject.wavePath, true); StreamWriter sw = new StreamWriter(currentProject.wavePath, true, Encoding.GetEncoding("ISO-8859-1")); sw.WriteLine("#" + simResult.simTime); sw.Close(); } catch (IOException) { Warn("波形ファイルのコピー中にエラーが発生しました."); } foreach (VHDLSource source in sources) { source.CopyFromWorkDirectory(workDir); if (!source.isValid) { Warn(source.content); } } }