// 外部プログラムを実行(出力を必要とする場合) public static GHDLResult ExecToolAndGetResult(string FileName, string args, GHDLResult result = null) { string outMessage = ""; string errMessage = ""; if (result == null) { result = new GHDLResult(); } Process p = ExecTool(FileName, args, true); if (p == null) { return(null); } p.OutputDataReceived += new DataReceivedEventHandler((sender, e) => { if (e.Data != null) { outMessage += e.Data + "\n"; } }); p.ErrorDataReceived += new DataReceivedEventHandler((sender, e) => { if (e.Data != null) { errMessage += e.Data + "\n"; } }); p.BeginOutputReadLine(); p.BeginErrorReadLine(); if (!p.WaitForExit(settings.procLimit)) { p.Kill(); Warn("GHDLが指定した時間内に終了しなかったため,強制停止しました.\n再度試すか,無限ループとなる記述がないか確認してください."); p.Close(); return(null); } result.code = p.ExitCode; if (!string.IsNullOrEmpty(result.message) && (outMessage != "" || errMessage != "")) { result.message += "\n"; } result.message += outMessage + errMessage; p.Close(); return(result); }
// 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); } } }