diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..5ead9861eaffe06b692e32c92783c1d91c854890 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.vs/ +bin +obj \ No newline at end of file diff --git a/Broker/Broker.sln b/Broker/Broker.sln new file mode 100644 index 0000000000000000000000000000000000000000..99fe4d92681942463c0c14d2cd7d1d9b09d3ad91 --- /dev/null +++ b/Broker/Broker.sln @@ -0,0 +1,25 @@ +п»ї +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.9.34728.123 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Broker", "Broker\Broker.csproj", "{878FA1BC-E0B7-4E44-8A96-BBC8A39B78EA}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {878FA1BC-E0B7-4E44-8A96-BBC8A39B78EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {878FA1BC-E0B7-4E44-8A96-BBC8A39B78EA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {878FA1BC-E0B7-4E44-8A96-BBC8A39B78EA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {878FA1BC-E0B7-4E44-8A96-BBC8A39B78EA}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {93E8500E-DF4F-40CA-856C-CB9D77B21DF9} + EndGlobalSection +EndGlobal diff --git a/Broker/Broker/Broker.csproj b/Broker/Broker/Broker.csproj new file mode 100644 index 0000000000000000000000000000000000000000..dba7e8ab4633ee16cc72333ec645872af3b7ff1b --- /dev/null +++ b/Broker/Broker/Broker.csproj @@ -0,0 +1,18 @@ +п»ї<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <OutputType>Exe</OutputType> + <TargetFramework>net8.0</TargetFramework> + <ImplicitUsings>enable</ImplicitUsings> + <Nullable>enable</Nullable> + </PropertyGroup> + + <ItemGroup> + <Compile Include="..\..\Shared\ProjectSettings.cs" Link="ProjectSettings.cs" /> + </ItemGroup> + + <ItemGroup> + <PackageReference Include="System.Security.Cryptography.ProtectedData" Version="9.0.2" /> + </ItemGroup> + +</Project> diff --git a/Broker/Broker/Program.cs b/Broker/Broker/Program.cs new file mode 100644 index 0000000000000000000000000000000000000000..093384206d5f449b007fe9e7eb7aa1ad84ea93a6 --- /dev/null +++ b/Broker/Broker/Program.cs @@ -0,0 +1,386 @@ +п»їusing System; +using System.Diagnostics; +using System.Text.Json; +using System.Text.Json.Nodes; +using System.Text.Json.Serialization; + +namespace HDLNoCGen +{ + static class Program + { + + static void uncheckMetadata (string json_path, int stage) + { + string json = File.ReadAllText(json_path); + ProjectSettings projectSettings = JsonSerializer.Deserialize<ProjectSettings>(json); + + if (stage <= 3) + { + projectSettings.databaseMetadata.writtenToDB = false; + } + if (stage <= 2) + { + projectSettings.quartusMetadata.quartusCompiled = false; + } + if (stage <= 1) + { + projectSettings.graphVerilogMetadata.verilogGenerated = false; + } + if (stage == 0) + { + projectSettings.graphVerilogMetadata.graphSerialized = false; + } + + json = JsonSerializer.Serialize<ProjectSettings>(projectSettings, new JsonSerializerOptions { WriteIndented = true }); + File.WriteAllText(json_path, json); + } + + static void Main(string[] args) + { + + bool launch_manager = false; + string project_name = ""; + string project_location = ""; + string project_new_name = ""; + string project_action = "o"; + + bool launch_graph = false; + string topology = ""; + List<int> generators = new List<int>(); + string queue_type = ""; + string queue_position = ""; + string arbiter_type = ""; + string algorithm = ""; + int info_width = 0; + int queue_length = 0; + bool create_verilog = false; + + bool launch_quartus = false; + string device_name = "5CGXFC9E7F35C8"; + + bool launch_db = false; + string db_ip = ""; + string db_username = ""; + string db_password = ""; + string db_name = ""; + int db_port = 5432; + + bool launch_settings = false; + string quartus_path = ""; + + try + { + for (int i = 0; i < args.Length; i++) + { + switch (args[i]) + { + case "--project": + launch_manager = true; + + bool project_breaker = false; + while (!project_breaker) + { + if (i + 1 < args.Length) + { + switch (args[++i]) + { + case "-n": + case "--name": + project_name = args[++i]; + break; + case "-l": + case "--location": + project_location = args[++i]; + break; + case "-o": + case "--open": + project_action = "o"; + break; + case "-c": + case "--create": + project_action = "c"; + break; + case "-e": + case "--erase": + project_action = "e"; + break; + case "-r": + case "--rename": + project_action = "r"; + project_new_name = args[++i]; + break; + default: + i--; + project_breaker = true; + break; + } + } + else + { + project_breaker = true; + } + } + break; + case "--graph": + launch_graph = true; + + bool graph_breaker = false; + + while (!graph_breaker) + { + if (i + 1 < args.Length) + { + switch (args[++i]) + { + case "c": + topology = "c"; + break; + case "m": + topology = "m"; + break; + case "t": + topology = "t"; + break; + case "--queue_type": + queue_type = args[++i]; + break; + case "--queue_position": + queue_position = args[++i]; + break; + case "--arbiter_type": + arbiter_type = args[++i]; + break; + case "--algorithm": + algorithm = args[++i]; + break; + case "--info_width": + try + { + info_width = Convert.ToInt32(args[++i]); + } + catch (Exception e) + { + Console.WriteLine("--info_width must be a number"); + Environment.Exit(1); + } + break; + case "--queue_length": + try + { + queue_length = Convert.ToInt32(args[++i]); + } + catch (Exception e) + { + Console.WriteLine("--queue_lenght must be a number"); + Environment.Exit(1); + } + break; + case "-v": + case "--verilog": + create_verilog = true; + break; + default: + try + { + generators.Add(Convert.ToInt32(args[i])); + } + catch (Exception e) + { + i--; + graph_breaker = true; + } + break; + } + } + else + { + graph_breaker = true; + } + } + break; + case "--quartus": + launch_quartus = true; + + if (i + 1 < args.Length) + { + switch (args[++i]) + { + case "-d": + case "--device": + device_name = args[++i]; + break; + default: + i--; + break; + } + } + break; + case "--database": + launch_db = true; + + bool db_breaker = false; + + while (!db_breaker) + { + if (i + 1 < args.Length) + { + switch (args[++i]) + { + case "-i": + case "--ip": + db_ip = args[++i]; + break; + case "-u": + case "--username": + db_username = args[++i]; + break; + case "--pass": + case "--password": + db_password = args[++i]; + break; + case "-n": + case "--name": + db_name = args[++i]; + break; + case "--port": + try + { + db_port = Convert.ToInt32(args[++i]); + } + catch (FormatException e) + { + Console.WriteLine("--port must be a number"); + Environment.Exit(1); + } + break; + default: + i--; + db_breaker = true; + break; + } + } + else + { + db_breaker = true; + } + } + break; + case "--settings": + launch_settings = true; + + bool settings_breaker = false; + while (!settings_breaker) + { + if (i + 1 < args.Length) + { + switch (args[++i]) + { + case "--qp": + case "--quartus_path": + quartus_path = args[++i]; + break; + default: + i--; + settings_breaker = true; + break; + } + } + else + { + settings_breaker = true; + } + } + break; + default: + Console.WriteLine($"Argument {args[i]} does not exist. Check the spelling or check graph generator numbers"); + Environment.Exit(1); + break; + } + } + } + catch (IndexOutOfRangeException e) + { + Console.WriteLine("No argument after an option that requires an argument"); + Environment.Exit(1); + } + + if (launch_manager) + { + using (Process manager = new Process()) + { + string manager_location = "../../../../../Project_manager/Project_manager/bin/Debug/net8.0"; + string manager_arguments = $"-l {project_location} -n {project_name} -{project_action} {(project_action == "r" ? project_new_name : "")}"; + string output_data = ""; + + manager.StartInfo.FileName = $"{manager_location}/Project_manager.exe"; + manager.StartInfo.Arguments = manager_arguments; + manager.StartInfo.RedirectStandardOutput = true; + manager.StartInfo.WorkingDirectory = manager_location; + + manager.OutputDataReceived += new DataReceivedEventHandler((sender, e) => + { + if (!String.IsNullOrEmpty(e.Data)) + { + output_data = $"{e.Data}\n"; + } + }); + + manager.Start(); + manager.BeginOutputReadLine(); + manager.WaitForExit(); + manager.Kill(); + + if (manager.ExitCode != 0) + { + Console.WriteLine("Project_manager failure:"); + Console.Write(output_data); + Environment.Exit(1); + } + } + } + + if (launch_graph) + { + uncheckMetadata($"{project_location}/{project_name}_metadata.json", 0); + using (Process veriloger = new Process()) + { + string veriloger_location = "../../../../../Graph_verilog_generator/Graph_verilog_generator/bin/Debug/net8.0"; + string veriloger_arguments = $"-l {project_location} -n {project_name} {topology} {String.Join(" ", generators)} " + + $"--queue_type {queue_type} " + + $"--queue_position {queue_position} " + + $"--arbiter_type {arbiter_type} " + + $"--algorithm {algorithm} " + + $"--info_width {info_width} " + + $"--queue_length {queue_length} " + + $"{(create_verilog ? "-v" : " ")}"; + string output_data = ""; + + veriloger.StartInfo.FileName = $"{veriloger_location}/Graph_verilog_generator.exe"; + veriloger.StartInfo.Arguments = veriloger_arguments; + veriloger.StartInfo.RedirectStandardOutput = true; + veriloger.StartInfo.WorkingDirectory = veriloger_location; + + veriloger.OutputDataReceived += new DataReceivedEventHandler((sender, e) => + { + if (!String.IsNullOrEmpty(e.Data)) + { + output_data = $"{e.Data}\n"; + } + }); + + veriloger.Start(); + veriloger.BeginOutputReadLine(); + veriloger.WaitForExit(); + veriloger.Kill(); + + if (veriloger.ExitCode != 0) + { + Console.WriteLine("Graph_verilog_generator failure:"); + Console.Write(output_data); + Environment.Exit(1); + } + } + } + } + } +} \ No newline at end of file diff --git a/Broker/Broker/Properties/launchSettings.json b/Broker/Broker/Properties/launchSettings.json new file mode 100644 index 0000000000000000000000000000000000000000..373fa251df3c2d55d5c7da66cf02be4c33f0d55a --- /dev/null +++ b/Broker/Broker/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "Broker": { + "commandName": "Project", + "commandLineArgs": "--project -l D:/kal -n ultrakal -r superkal" + } + } +} \ No newline at end of file diff --git a/Graph_verilog_generator/Graph_verilog_generator.sln b/Graph_verilog_generator/Graph_verilog_generator.sln new file mode 100644 index 0000000000000000000000000000000000000000..7248b379f51c80fae7febc7832a819dd71f7b9df --- /dev/null +++ b/Graph_verilog_generator/Graph_verilog_generator.sln @@ -0,0 +1,25 @@ +п»ї +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.9.34728.123 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Graph_verilog_generator", "Graph_verilog_generator\Graph_verilog_generator.csproj", "{68AA1BBD-6B31-40D4-BC74-5371E2242388}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {68AA1BBD-6B31-40D4-BC74-5371E2242388}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {68AA1BBD-6B31-40D4-BC74-5371E2242388}.Debug|Any CPU.Build.0 = Debug|Any CPU + {68AA1BBD-6B31-40D4-BC74-5371E2242388}.Release|Any CPU.ActiveCfg = Release|Any CPU + {68AA1BBD-6B31-40D4-BC74-5371E2242388}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {21362C82-333C-4D3F-82C0-6662721FD81D} + EndGlobalSection +EndGlobal diff --git a/Graph_verilog_generator/Graph_verilog_generator/Graph_verilog_generator.csproj b/Graph_verilog_generator/Graph_verilog_generator/Graph_verilog_generator.csproj new file mode 100644 index 0000000000000000000000000000000000000000..9a1da2087ba3db8276d4d94bf0e13ff501b8e0e9 --- /dev/null +++ b/Graph_verilog_generator/Graph_verilog_generator/Graph_verilog_generator.csproj @@ -0,0 +1,28 @@ +п»ї<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <OutputType>Exe</OutputType> + <TargetFramework>net8.0</TargetFramework> + <ImplicitUsings>enable</ImplicitUsings> + <Nullable>enable</Nullable> + </PropertyGroup> + + <ItemGroup> + <Compile Include="..\..\Shared\Graph.cs" Link="Graph.cs" /> + <Compile Include="..\..\Shared\GraphCirculant.cs" Link="GraphCirculant.cs" /> + <Compile Include="..\..\Shared\GraphMesh.cs" Link="GraphMesh.cs" /> + <Compile Include="..\..\Shared\GraphTorus.cs" Link="GraphTorus.cs" /> + <Compile Include="..\..\Shared\IRectangleLike.cs" Link="IRectangleLike.cs" /> + <Compile Include="..\..\Shared\IRoundLike.cs" Link="IRoundLike.cs" /> + <Compile Include="..\..\Shared\ProjectGenerator.cs" Link="ProjectGenerator.cs" /> + <Compile Include="..\..\Shared\ProjectSettings.cs" Link="ProjectSettings.cs" /> + <Compile Include="..\..\Shared\Settings.cs" Link="Settings.cs" /> + </ItemGroup> + + <ItemGroup> + <PackageReference Include="Npgsql" Version="9.0.3" /> + <PackageReference Include="System.Management" Version="9.0.2" /> + <PackageReference Include="System.Security.Cryptography.ProtectedData" Version="9.0.2" /> + </ItemGroup> + +</Project> diff --git a/Graph_verilog_generator/Graph_verilog_generator/Program.cs b/Graph_verilog_generator/Graph_verilog_generator/Program.cs new file mode 100644 index 0000000000000000000000000000000000000000..b9989a1699a16019c8f6eaf9ad4851bbb8422611 --- /dev/null +++ b/Graph_verilog_generator/Graph_verilog_generator/Program.cs @@ -0,0 +1,297 @@ +п»їusing System; +using System.Diagnostics; +using System.Reflection.Metadata; +using System.Text.Json; +using System.Xml.Linq; + +namespace HDLNoCGen +{ + static class Program + { + + static void finish_job (string json_location, ProjectSettings project_settings) + { + string json = JsonSerializer.Serialize<ProjectSettings>(project_settings, new JsonSerializerOptions { WriteIndented = true }); + File.WriteAllText(json_location, json); + Environment.Exit(0); + } + + static void Main(string[] args) + { + string location = "C:/Users/Serha/Desktop/kal"; + string name = "kal"; + + string topology = ""; + List<int> generators = new List<int>(); + string queue_type = "pointer"; + string queue_position = "front"; + string arbiter_type = "round_robin"; + string algorithm = "xy"; + int info_width = 8; + int queue_length = 4; + bool create_verilog = false; + Graph graph = null; + + router_options parameters = new router_options(); + string graph_filename = ""; + + CancellationTokenSource GeneralPurposeCancellationTokenSource = new CancellationTokenSource(); + CancellationToken GeneralPurposeCancellationToken = GeneralPurposeCancellationTokenSource.Token; + + try + { + for (int i = 0; i < args.Length; i++) + { + switch (args[i]) + { + case "-l": + case "--location": + location = args[++i]; + break; + case "-n": + case "--name": + name = args[++i]; + break; + case "c": + topology = "c"; + break; + case "m": + topology = "m"; + break; + case "t": + topology = "t"; + break; + case "--queue_type": + queue_type = args[++i]; + break; + case "--queue_position": + queue_position = args[++i]; + break; + case "--arbiter_type": + arbiter_type = args[++i]; + break; + case "--algorithm": + algorithm = args[++i]; + break; + case "--info_width": + try + { + info_width = Convert.ToInt32(args[++i]); + } + catch (Exception e) + { + Console.WriteLine("--info_width must be a number"); + Environment.Exit(1); + } + break; + case "--queue_length": + try + { + queue_length = Convert.ToInt32(args[++i]); + } + catch (Exception e) + { + Console.WriteLine("--queue_lenght must be a number"); + Environment.Exit(1); + } + break; + case "-v": + case "--verilog": + create_verilog = true; + break; + default: + try + { + generators.Add(Convert.ToInt32(args[i])); + } + catch (Exception e) + { + Console.WriteLine($"Argument {args[i]} is invalid"); + } + break; + + } + } + } + catch (IndexOutOfRangeException e) + { + Console.WriteLine("No argument after an option that requires an argument"); + Environment.Exit(1); + } + + string metadata_location = $"{location}/{name}_metadata.json"; + string project_settings_json = File.ReadAllText(metadata_location); + ProjectSettings projectSettings = JsonSerializer.Deserialize<ProjectSettings>(project_settings_json); + + switch (topology) + { + case "c": + graph = new GraphCirculant(); + break; + case "m": + graph = new GraphMesh(); + break; + case "t": + graph = new GraphTorus(); + break; + default: + Console.WriteLine($"Topology {topology} does not exit"); + Environment.Exit(1); + break; + } + + graph.InstallGenerators(generators, GeneralPurposeCancellationToken); + + graph_filename += $"{info_width}_bit"; + + switch (graph.graphId) + { + case GraphType.Circulant: + graph_filename += "__circulant"; + graph_filename += $"_{graph.node_count}_" + String.Join("_", graph.generators.Slice(0, graph.generators.Count - 1).Select(s => $"{s}")); + break; + case GraphType.Mesh: + graph_filename += "__mesh"; + graph_filename += $"_{graph.node_count}_" + String.Join("_", graph.generators.Select(s => $"{s}")); + break; + case GraphType.Torus: + graph_filename += "__torus"; + graph_filename += $"_{graph.node_count}_" + String.Join("_", graph.generators.Select(s => $"{s}")); + break; + default: + Console.WriteLine($"Graph type {graph.graphId} was not implemented into this switch statement."); + Environment.Exit(1); + break; + } + + switch (queue_type) + { + case "index": + parameters.queue_type = RouterOptions.Queue_types.Index; + graph_filename += $"__indexQueue_{queue_length}_long"; + break; + case "pointer": + parameters.queue_type = RouterOptions.Queue_types.Pointer; + graph_filename += $"__pointerQueue_{queue_length}_long"; + break; + case "line": + parameters.queue_type = RouterOptions.Queue_types.Line; + graph_filename += $"__lineQueue_{queue_length}_long"; + break; + default: + Console.WriteLine($"Queue type '{queue_length}' does not exist. It should be either 'index', 'pointer' or 'line'."); + Environment.Exit(1); + break; + } + + switch (queue_position) + { + case "front": + parameters.queue_position = RouterOptions.Queue_position.Front; + graph_filename += "_front"; + break; + case "rear": + parameters.queue_position = RouterOptions.Queue_position.Rear; + graph_filename += "_rear"; + break; + default: + Console.WriteLine($"Queue position '{queue_position}' does not exist. It should be either 'front' or 'rear'."); + Environment.Exit(1); + break; + } + + switch (arbiter_type) + { + case "round_robin": + parameters.arbiter_type = RouterOptions.Arbiter_types.Round_Robin; + graph_filename += "__arbRoundRobin"; + break; + default: + Console.WriteLine($"Arbiter type '{queue_position}' does not exist. It should be either 'front' or 'rear'."); + Environment.Exit(1); + break; + } + + switch (algorithm) + { + case "xy": + graph_filename += "__xy"; + + switch (graph.graphId) + { + case GraphType.Mesh: + parameters.algorithm = RouterOptions.Algorithm.XY; + break; + case GraphType.Torus: + parameters.algorithm = RouterOptions.Algorithm.XY; + break; + default: + Console.WriteLine($"Graph type {graph.graphId} was not implemented into this switch statement."); + Environment.Exit(1); + break; + } + + break; + case "ga": + parameters.algorithm = RouterOptions.Algorithm.GA; + graph_filename += "__ga"; + break; + default: + Console.WriteLine($"Algorithm '{algorithm}' does not exist. It should be either 'xy' or 'ga'."); + Environment.Exit(1); + break; + } + + switch (graph.graphId) + { + case GraphType.Circulant: + parameters.packet_width = 1 + graph.get_bits(graph.node_count) + info_width; + break; + case GraphType.Mesh: + case GraphType.Torus: + parameters.packet_width = 1 + 2 * graph.get_bits(generators[1]) + info_width; + break; + } + parameters.queue_length = queue_length; + parameters.info_width = info_width; + + graph.parameters = parameters; + string graph_json = ""; + + switch (graph.graphId) + { + case GraphType.Circulant: + graph_json = JsonSerializer.Serialize<GraphCirculant>(graph as GraphCirculant, new JsonSerializerOptions { WriteIndented = true }); + break; + case GraphType.Mesh: + graph_json = JsonSerializer.Serialize<GraphMesh>(graph as GraphMesh, new JsonSerializerOptions { WriteIndented = true }); + break; + case GraphType.Torus: + graph_json = JsonSerializer.Serialize<GraphTorus>(graph as GraphTorus, new JsonSerializerOptions { WriteIndented = true }); + break; + } + + using (StreamWriter sw = new StreamWriter($"{location}/{name}_graph_object_serialized.json")) + { + sw.Write(graph_json); + } + + projectSettings.graphVerilogMetadata.graphSerialized = true; + if (!create_verilog) + { + finish_job(metadata_location, projectSettings); + } + + Tuple<string, Process, Process> preparation_result = ProjectGenerator.routerPreparation(graph, $"{name}_NoC_description", location, parameters); + string verilog_path = preparation_result.Item1; + Process compile_process = preparation_result.Item2; + Process simulate_process = preparation_result.Item3; + + graph.createNoC(verilog_path, parameters); + + projectSettings.graphVerilogMetadata.verilogGenerated = true; + finish_job(metadata_location, projectSettings); + + } + } +} \ No newline at end of file diff --git a/Graph_verilog_generator/Graph_verilog_generator/Properties/launchSettings.json b/Graph_verilog_generator/Graph_verilog_generator/Properties/launchSettings.json new file mode 100644 index 0000000000000000000000000000000000000000..e2eb19bf2f4bac526fa72109a139b5291d201903 --- /dev/null +++ b/Graph_verilog_generator/Graph_verilog_generator/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "Graph_verilog_generator": { + "commandName": "Project", + "commandLineArgs": "-l D:/kal -n kal m 3 3 --queue_type pointer --queue_position front --arbiter_type round_robin --algorithm xy --info_width 8 --queue_length 16 -v" + } + } +} \ No newline at end of file diff --git a/Graph_verilog_generator/Graph_verilog_generator/router_variants.json b/Graph_verilog_generator/Graph_verilog_generator/router_variants.json new file mode 100644 index 0000000000000000000000000000000000000000..74c7ac7d2f0d978fea4e726cb8c9eb2c7adac017 --- /dev/null +++ b/Graph_verilog_generator/Graph_verilog_generator/router_variants.json @@ -0,0 +1,92 @@ +{ + "mesh": { + "xy": { + "front": [ + "input clk,", + "input[0:`PL-1] inputs[0:`REN-1], output[0:`PL-1] outputs[0:`REN-1],", + "input signals_in[0:`REN-1], output signals_out[0:`REN-1],", + "input[`CS-1:0] router_X, input[`CS-1:0] router_Y", + + "c#_splitter", + + "algorithm XY(", + ".from_arbiter(arbiter_to_algorithm), .shift(shift), .outputs(outputs),", + ".router_X(router_X), .router_Y(router_Y),", + ".availability_signals_in(signals_in), .shift_signals(shift_signals));" + ], + "rear": [ + "input clk,", + "input[0:`PL-1] inputs[0:`REN-1], output[0:`PL-1] outputs[0:`REN-1],", + "input signals_in[0:`REN-1], output signals_out[0:`REN-1],", + "input[`CS-1:0] router_X, input[`CS-1:0] router_Y", + + "c#_splitter", + + "algorithm XY(", + ".from_arbiter(arbiter_to_algorithm), .shift(shift), .outputs(algotihm_to_queue),", + ".router_X(router_X), .router_Y(router_Y),", + ".availability_signals_in(availability_signals), .shift_signals(signals_out));" + ] + } + }, + "torus": { + "xy": { + "front": [ + "input clk,", + "input[0:`PL-1] inputs[0:`REN-1], output[0:`PL-1] outputs[0:`REN-1],", + "input signals_in[0:`REN-1], output signals_out[0:`REN-1],", + "input[`CS-1:0] router_X, input[`CS-1:0] router_Y", + + "c#_splitter", + + "algorithm XY(", + ".from_arbiter(arbiter_to_algorithm), .shift(shift), .outputs(outputs),", + ".router_X(router_X), .router_Y(router_Y),", + ".availability_signals_in(signals_in), .shift_signals(shift_signals));" + ], + "rear": [ + "input clk,", + "input[0:`PL-1] inputs[0:`REN-1], output[0:`PL-1] outputs[0:`REN-1],", + "input signals_in[0:`REN-1], output signals_out[0:`REN-1],", + "input[`CS-1:0] router_X, input[`CS-1:0] router_Y", + + "c#_splitter", + + "algorithm XY(", + ".from_arbiter(arbiter_to_algorithm), .shift(shift), .outputs(algotihm_to_queue),", + ".router_X(router_X), .router_Y(router_Y),", + ".availability_signals_in(availability_signals), .shift_signals(signals_out));" + ] + } + }, + "circulant": { + "ga": { + "front": [ + "input clk,", + "input[0:`PL-1] inputs[0:`REN-1], output[0:`PL-1] outputs[0:`REN-1],", + "input signals_in[0:`REN-1], output signals_out[0:`REN-1],", + "input[`CS-1:0] router_no", + + "c#_splitter", + + "algorithm GA(", + ".from_arbiter(arbiter_to_algorithm), .shift(shift), .outputs(outputs),", + ".router_no(router_no),", + ".availability_signals_in(signals_in), .shift_signals(shift_signals));" + ], + "rear": [ + "input clk,", + "input[0:`PL-1] inputs[0:`REN-1], output[0:`PL-1] outputs[0:`REN-1],", + "input signals_in[0:`REN-1], output signals_out[0:`REN-1],", + "input[`CS-1:0] router_no", + + "c#_splitter", + + "algorithm GA(", + ".from_arbiter(arbiter_to_algorithm), .shift(shift), .outputs(algotihm_to_queue),", + ".router_no(router_no),", + ".availability_signals_in(availability_signals), .shift_signals(signals_out));" + ] + } + } +} \ No newline at end of file diff --git a/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/inc/noc.svh b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/inc/noc.svh new file mode 100644 index 0000000000000000000000000000000000000000..41308892f9a7c2ec2274d49f16fb1fa500b80730 --- /dev/null +++ b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/inc/noc.svh @@ -0,0 +1,8 @@ +`ifndef _noc_parameters_svh_ +`define _noc_parameters_svh_ + +`define PL {0}// length of datapack +`define CS {1} // size of single coordinate part +`define RN {2} // number of routers in network + +`endif diff --git a/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/inc/noc_CIRCULANT.svh b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/inc/noc_CIRCULANT.svh new file mode 100644 index 0000000000000000000000000000000000000000..257926e836f7a22bed6a9ca64406bf3ad486d2ef --- /dev/null +++ b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/inc/noc_CIRCULANT.svh @@ -0,0 +1,9 @@ +`ifndef _noc_CIRCULANT_parameters_svh_ +`define _noc_CIRCULANT_parameters_svh_ + +`define GENERATICS {0} // generatics + +// GA +`define LT {1} // LT - long throw - length of the long edge + +`endif \ No newline at end of file diff --git a/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/inc/noc_XY.svh b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/inc/noc_XY.svh new file mode 100644 index 0000000000000000000000000000000000000000..35d14c4bd5e79e71743f91ebef3023889674dbf9 --- /dev/null +++ b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/inc/noc_XY.svh @@ -0,0 +1,7 @@ +`ifndef _noc_XY_parameters_svh_ +`define _noc_XY_parameters_svh_ + +`define X {0} // number of routers in network on X axis +`define Y {1} // number of routers in network on Y axis + +`endif diff --git a/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/inc/queue.svh b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/inc/queue.svh new file mode 100644 index 0000000000000000000000000000000000000000..4391efd2147633ceab4cb4f104d353a78bd909a9 --- /dev/null +++ b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/inc/queue.svh @@ -0,0 +1,9 @@ +`ifndef _queue_parameters_svh_ +`define _queue_parameters_svh_ + +`include "inc/noc.svh" + +`define EN {0} // number of queue entries +`define EN_B {1} // number of bits required to encode queue entries + +`endif diff --git a/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/inc/router.svh b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/inc/router.svh new file mode 100644 index 0000000000000000000000000000000000000000..497ff11fea982cc386617183f61e0636b04f8194 --- /dev/null +++ b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/inc/router.svh @@ -0,0 +1,9 @@ +`ifndef _router_parameters_svh_ +`define _router_parameters_svh_ + +`include "inc/noc.svh" + +`define REN {0} // number of router entries +`define REN_B {1} // number bits required to eoncode router entries + +`endif diff --git a/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/noc/circulant.sv b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/noc/circulant.sv new file mode 100644 index 0000000000000000000000000000000000000000..0f18212b9998bb8a585c34cbd271c97763a74fd0 --- /dev/null +++ b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/noc/circulant.sv @@ -0,0 +1,68 @@ +`include "inc/noc.svh" +`include "inc/noc_CIRCULANT.svh" +`include "src/router.sv" + +module noc( + input clk, + output[0:`PL-1] core_inputs[0:`RN-1], + input[0:`PL-1] core_outputs[0:`RN-1], + input core_availability_signals_out[0:`RN-1], + output core_availability_signals_in[0:`RN-1] +); + +localparam[0:`CS*(`REN-1)-1] generatics = `GENERATICS; + +wire [0:`PL-1] inputs[0:`RN-1][0:`REN-1]; + +wire availability_signals[0:`RN-1][0:`REN-1]; + + +generate + genvar router_iterator; + for (router_iterator = 0; router_iterator < `RN; router_iterator = router_iterator + 1) + begin : routers + wire [0:`PL-1] outputs [0:`REN-1]; + wire availability_signals_in [0:`REN-1]; + + assign core_inputs[router_iterator] = outputs[0]; + assign inputs[router_iterator][0] = core_outputs[router_iterator]; + + assign availability_signals_in[0] = core_availability_signals_out[router_iterator]; + assign core_availability_signals_in[router_iterator] = availability_signals[router_iterator][0]; + + genvar generatic_iterator; + + for (generatic_iterator = 0; generatic_iterator < `REN-1; generatic_iterator = generatic_iterator + 1) begin : generatics_gen + + if (generatics[generatic_iterator * `CS : (generatic_iterator+1) * `CS - 1] + router_iterator >= `RN) begin + localparam int next = generatics[generatic_iterator * `CS : (generatic_iterator+1) * `CS - 1] + router_iterator - `RN; + assign inputs[next][`REN-generatic_iterator-1] = outputs[generatic_iterator+1]; + assign availability_signals_in[generatic_iterator+1] = availability_signals[next][`REN-generatic_iterator-1]; + end else begin + localparam int next = generatics[generatic_iterator * `CS : (generatic_iterator+1) * `CS - 1] + router_iterator; + assign inputs[next][`REN-generatic_iterator-1] = outputs[generatic_iterator+1]; + assign availability_signals_in[generatic_iterator+1] = availability_signals[next][`REN-generatic_iterator-1]; + end + + end + + wire [0:`PL-1] input_router[0:`REN-1]; + wire avail_router[0:`REN-1]; + wire [`CS-1:0] router_no = router_iterator; + genvar i; + for (i = 0; i < `REN; i = i + 1) + begin : wire_crutch_entries + assign input_router[i] = inputs[router_iterator][i]; + assign availability_signals[router_iterator][i] = avail_router[i]; + end + + router router( + .clk(clk), + .inputs(input_router), .outputs(outputs), + .signals_out(avail_router), .signals_in(availability_signals_in), + .router_no(router_no) + ); + end +endgenerate + +endmodule diff --git a/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/noc/mesh.sv b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/noc/mesh.sv new file mode 100644 index 0000000000000000000000000000000000000000..ba96029a7972a738ea1f695f5227b5f1ea7e9128 --- /dev/null +++ b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/noc/mesh.sv @@ -0,0 +1,93 @@ +`include "inc/noc.svh" +`include "inc/noc_XY.svh" +`include "src/router.sv" + +module noc( + input clk, + output[0:`PL-1] core_inputs[0:`Y-1][0:`X-1], + input[0:`PL-1] core_outputs[0:`Y-1][0:`X-1], + input core_availability_signals_out[0:`Y-1][0:`X-1], + output core_availability_signals_in[0:`Y-1][0:`X-1] +); + +wire [0:`PL-1] inputs[0:`Y + 1][0:`X + 1][0:`REN-1]; + +wire availability_signals[0:`Y + 1][0:`X + 1][0:`REN-1]; + +generate + + genvar i, j; + for (i = 0; i <= `Y; i = i + 1) + begin : init_avail_Y + for (j = 0; j < `REN; j = j + 1) + begin : init_avail_REN_1 + assign availability_signals[i][0][j] = 1; + assign availability_signals[i][`X + 1][j] = 1; + end + end + + + for (i = 0; i <= `X; i = i + 1) + begin : init_avail_X + for (j = 0; j < `REN; j = j + 1) + begin : init_avail_REN_2 + assign availability_signals[0][i][j] = 1; + assign availability_signals[`Y + 1][i][j] = 1; + end + end + + for (i = 1; i <= `X; i = i + 1) + begin : init_packet_X + assign inputs[1][i][1] = 0; + assign inputs[`Y][i][3] = 0; + end + + for (i = 1; i <= `Y; i = i + 1) + begin : init_packet_Y + assign inputs[i][1][4] = 0; + assign inputs[i][`X][2] = 0; + end + +endgenerate + +generate + genvar router_Y_iterator, router_X_iterator; + for (router_Y_iterator = 1; router_Y_iterator <= `Y; router_Y_iterator = router_Y_iterator + 1) + begin : routers_Y + for (router_X_iterator = 1; router_X_iterator <= `X; router_X_iterator = router_X_iterator + 1) + begin : routers_X + + assign core_availability_signals_in[router_Y_iterator-1][router_X_iterator-1] = availability_signals[router_Y_iterator][router_X_iterator][0]; + + localparam lower = router_Y_iterator + 1; + localparam right = router_X_iterator + 1; + localparam upper = router_Y_iterator - 1; + localparam left = router_X_iterator - 1; + + wire[0:`PL-1] outputs[0:`REN-1]; + assign core_inputs[router_Y_iterator-1][router_X_iterator-1] = outputs[0]; + assign inputs[upper][router_X_iterator][3] = outputs[1]; + assign inputs[router_Y_iterator][right][4] = outputs[2]; + assign inputs[lower][router_X_iterator][1] = outputs[3]; + assign inputs[router_Y_iterator][left][2] = outputs[4]; + + wire signals_in[0:`REN-1]; + assign signals_in[0] = core_availability_signals_out[router_Y_iterator-1][router_X_iterator-1]; + assign signals_in[1] = availability_signals[upper][router_X_iterator][3]; + assign signals_in[2] = availability_signals[router_Y_iterator][right][4]; + assign signals_in[3] = availability_signals[lower][router_X_iterator][1]; + assign signals_in[4] = availability_signals[router_Y_iterator][left][2]; + + router router( + .clk(clk), + .inputs(inputs[router_Y_iterator][router_X_iterator]), .outputs(outputs), + .signals_out(availability_signals[router_Y_iterator][router_X_iterator]), .signals_in(signals_in), + .router_Y(router_Y_iterator - 1), .router_X(router_X_iterator - 1) + ); + + assign inputs[router_Y_iterator][router_X_iterator][0] = core_outputs[router_Y_iterator-1][router_X_iterator-1]; + end + end +endgenerate + +endmodule \ No newline at end of file diff --git a/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/noc/torus.sv b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/noc/torus.sv new file mode 100644 index 0000000000000000000000000000000000000000..6f8f8474dd1d59bb809ad3aeed69ae13d2bf8078 --- /dev/null +++ b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/noc/torus.sv @@ -0,0 +1,61 @@ +`include "inc/noc.svh" +`include "inc/noc_XY.svh" +`include "src/router.sv" + +module noc( + input clk, + output[0:`PL-1] core_inputs[0:`Y-1][0:`X-1], + input[0:`PL-1] core_outputs[0:`Y-1][0:`X-1], + input core_availability_signals_out[0:`Y-1][0:`X-1], + output core_availability_signals_in[0:`Y-1][0:`X-1] +); + +wire [0:`PL-1] inputs[0:`Y-1][0:`X-1][0:`REN-1]; + +wire availability_signals[0:`Y-1][0:`X-1][0:`REN-1]; + +generate + genvar router_Y_iterator, router_X_iterator; + for (router_Y_iterator = 0; router_Y_iterator < `Y; router_Y_iterator = router_Y_iterator + 1) + begin : routers_Y + for (router_X_iterator = 0; router_X_iterator < `X; router_X_iterator = router_X_iterator + 1) + begin : routers_X + + assign core_availability_signals_in[router_Y_iterator][router_X_iterator] = availability_signals[router_Y_iterator][router_X_iterator][0]; + + localparam lower = router_Y_iterator == `Y-1 ? 0 : router_Y_iterator + 1; + localparam right = router_X_iterator == `X-1 ? 0 : router_X_iterator + 1; + localparam upper = router_Y_iterator == 0 ? `Y-1 : router_Y_iterator - 1; + localparam left = router_X_iterator == 0 ? `X-1 : router_X_iterator - 1; + + wire[0:`PL-1] outputs[0:`REN-1]; + assign core_inputs[router_Y_iterator][router_X_iterator] = outputs[0]; + assign inputs[upper][router_X_iterator][3] = outputs[1]; + assign inputs[router_Y_iterator][right][4] = outputs[2]; + assign inputs[lower][router_X_iterator][1] = outputs[3]; + assign inputs[router_Y_iterator][left][2] = outputs[4]; + + wire signals_in[0:`REN-1]; + assign signals_in[0] = core_availability_signals_out[router_Y_iterator][router_X_iterator]; + assign signals_in[1] = availability_signals[upper][router_X_iterator][3]; + assign signals_in[2] = availability_signals[router_Y_iterator][right][4]; + assign signals_in[3] = availability_signals[lower][router_X_iterator][1]; + assign signals_in[4] = availability_signals[router_Y_iterator][left][2]; + + router router( + .clk(clk), + .inputs(inputs[router_Y_iterator][router_X_iterator]), .outputs(outputs), + .signals_out(availability_signals[router_Y_iterator][router_X_iterator]), .signals_in(signals_in), + .router_Y(router_Y_iterator), .router_X(router_X_iterator) + ); + + assign inputs[router_Y_iterator][router_X_iterator][0] = core_outputs[router_Y_iterator][router_X_iterator]; + end + end +endgenerate + +always @(posedge clk) + begin + end + +endmodule diff --git a/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/sel/circle.sv b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/sel/circle.sv new file mode 100644 index 0000000000000000000000000000000000000000..1d182f2b04d4f72095e260ad68067970b9fae63c --- /dev/null +++ b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/sel/circle.sv @@ -0,0 +1,60 @@ +`include "inc/noc.svh" +`include "inc/noc_CIRCULANT.svh" +`include "noc/noc.sv" + + +module toplevel ( + input clk, + input[0:`PL-1] packet, + input[`CS-1:0] core_NO, + input core_availability_signals_out[0:`RN-1], + output core_availability_signals_in[0:`RN-1], + output wire[0:1] core_inputs_2_bits[0:`RN-1] +); + + wire[0:`PL-1] core_inputs[0:`RN-1]; + wire[0:`PL-1] core_outputs[0:`RN-1]; + + generate + genvar i; + + for (i = 0; i < `RN; i = i + 1) + begin : bool_grid + assign core_inputs_2_bits[i] = {core_inputs[i][0], ^core_inputs[i]}; + end + + endgenerate + + dataSelector selector(.clk(clk), .packet(packet), .core_NO(core_NO), .core_outputs(core_outputs)); + + noc noc( + .clk(clk), + .core_inputs(core_inputs), + .core_outputs(core_outputs), + .core_availability_signals_out(core_availability_signals_out), + .core_availability_signals_in(core_availability_signals_in) + ); + +endmodule + + +module dataSelector ( + input clk, + input[0:`PL-1] packet, + input[`CS-1:0] core_NO, + output reg[0:`PL-1] core_outputs[0:`RN-1] +); + + initial begin + int i; + for (i = 0; i < `RN; i = i + 1) + begin + core_outputs[i] = 0; + end + end + + always @(posedge clk) begin + core_outputs[core_NO] <= packet; + end + +endmodule \ No newline at end of file diff --git a/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/sel/rectangle.sv b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/sel/rectangle.sv new file mode 100644 index 0000000000000000000000000000000000000000..0b8fa9cc57e641b0504ffd26d386ba3fef95b5b5 --- /dev/null +++ b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/sel/rectangle.sv @@ -0,0 +1,68 @@ +`include "inc/noc.svh" +`include "inc/noc_XY.svh" +`include "noc/noc.sv" + + +module toplevel ( + input clk, + input[0:`PL-1] packet, + input[`CS-1:0] core_X, + input[`CS-1:0] core_Y, + input core_availability_signals_out[0:`Y-1][0:`X-1], + output core_availability_signals_in[0:`Y-1][0:`X-1], + output wire[0:1] core_inputs_2_bits[0:`Y-1][0:`X-1] +); + + wire[0:`PL-1] core_inputs[0:`Y-1][0:`X-1]; + wire[0:`PL-1] core_outputs[0:`Y-1][0:`X-1]; + + generate + genvar i, j; + + for (i = 0; i < `Y; i = i + 1) + begin : bool_grid_Y + for (j = 0; j < `X; j = j + 1) + begin : bool_grid_X + assign core_inputs_2_bits[i][j] = {core_inputs[i][j][0], ^core_inputs[i][j]}; + end + end + + endgenerate + + dataSelector selector(.clk(clk), .packet(packet), .core_X(core_X), .core_Y(core_Y), .core_outputs(core_outputs)); + + noc noc( + .clk(clk), + .core_inputs(core_inputs), + .core_outputs(core_outputs), + .core_availability_signals_out(core_availability_signals_out), + .core_availability_signals_in(core_availability_signals_in) + ); + +endmodule + + +module dataSelector ( + input clk, + input[0:`PL-1] packet, + input[`CS-1:0] core_X, + input[`CS-1:0] core_Y, + output reg[0:`PL-1] core_outputs[0:`Y-1][0:`X-1] +); + + initial begin + int i, j; + for (i = 0; i < `Y; i = i + 1) + begin + for (j = 0; j < `X; j = j + 1) + begin + core_outputs[i][j] = 0; + end + end + end + + always @(posedge clk) begin + core_outputs[core_Y][core_X] <= packet; + end + +endmodule \ No newline at end of file diff --git a/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/src/alg/circulant/GA.sv b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/src/alg/circulant/GA.sv new file mode 100644 index 0000000000000000000000000000000000000000..7603095150643032239e18a86b8c707803507753 --- /dev/null +++ b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/src/alg/circulant/GA.sv @@ -0,0 +1,90 @@ +// This is an XY example +`include "inc/router.svh" +`include "inc/noc_CIRCULANT.svh" + +module algorithm +( + input[0:`PL-1] from_arbiter, + input[`CS-1:0] router_no, + input[`REN_B-1:0] shift, + output shift_signals[0:`REN-1], + input availability_signals_in[0:`REN-1], + output wire[0:`PL-1] outputs[0:`REN-1] +); + + wire [`CS:0] router_quantity = `RN; + wire [`CS:0] long_length = `LT; + wire signed[`CS:0] destination = {1'b0, from_arbiter[1:`CS]}; + wire signed[`CS:0] long_length_s = {1'b0, long_length}; + wire signed[`CS:0] relative_destination; + + wire[0:1] drc_1; // destination_router_comparator_1 + assign drc_1[0] = destination > router_no; + assign drc_1[1] = destination < router_no; + + wire[0:4] drc_2; // destination_router_comparator_2 + assign drc_2[0] = (drc_1 == 2'b00); + assign drc_2[1] = drc_1[0] & (destination - router_no <= (router_no + router_quantity) - destination); + assign drc_2[2] = drc_1[0] & !drc_2[1]; + assign drc_2[3] = drc_1[1] & (router_no - destination <= (destination + router_quantity) - router_no); + assign drc_2[4] = drc_1[1] & !drc_2[3]; + + assign relative_destination = drc_2[0] ? 0 : + drc_2[1] ? destination - router_no : + drc_2[2] ? destination - (router_no + router_quantity) : + drc_2[3] ? destination - router_no : + drc_2[4] ? (destination + router_quantity) - router_no : + 0; + + wire[0:1] selector_step1 = {relative_destination < 0, relative_destination > 0}; + + wire[0:2] selector_step2; + assign selector_step2[0] = (relative_destination > long_length_s) | + (-relative_destination > long_length_s); + assign selector_step2[1] = (long_length_s - relative_destination < relative_destination) | + (long_length_s + relative_destination < -relative_destination); + assign selector_step2[2] = (selector_step2[0] == 0) & (selector_step2[1] == 0); + + + wire[0:4] selector; + assign selector[0] = (selector_step1 == 2'b00) & availability_signals_in[0] & from_arbiter[0]; + assign selector[1] = selector_step1[0] & (selector_step2[0] | selector_step2[1]) & availability_signals_in[1] & from_arbiter[0]; + assign selector[2] = selector_step1[0] & selector_step2[2] & availability_signals_in[2] & from_arbiter[0]; + assign selector[3] = selector_step1[1] & selector_step2[2] & availability_signals_in[3] & from_arbiter[0]; + assign selector[4] = selector_step1[1] & (selector_step2[0] | selector_step2[1]) & availability_signals_in[4] & from_arbiter[0]; + + + wire shift_required = selector[0] | selector[1] | selector[2] | selector[3] | selector[4]; + + assign shift_signals[0] = shift_required & (shift == 0); + assign shift_signals[1] = shift_required & (shift == 1); + assign shift_signals[2] = shift_required & (shift == 2); + assign shift_signals[3] = shift_required & (shift == 3); + assign shift_signals[4] = shift_required & (shift == 4); + + + generate + genvar i, j; + for (i = 0; i < `PL; i = i + 1 ) begin : generate_outputs_bits_core + assign outputs[0][i] = from_arbiter[i] & selector[0]; + end + + for (i = 0; i < `PL; i = i + 1 ) begin : generate_outputs_bits_left_long + assign outputs[1][i] = from_arbiter[i] & selector[1]; + end + + for (i = 0; i < `PL; i = i + 1 ) begin : generate_outputs_bits_left_short + assign outputs[2][i] = from_arbiter[i] & selector[2] & !selector[1] & !selector[3]; + end + + for (i = 0; i < `PL; i = i + 1 ) begin : generate_outputs_bits_right_short + assign outputs[3][i] = from_arbiter[i] & selector[3]; + end + + for (i = 0; i < `PL; i = i + 1 ) begin : generate_outputs_bits_right_long + assign outputs[4][i] = from_arbiter[i] & selector[4] & !selector[1] & !selector[3]; + end + + endgenerate + +endmodule \ No newline at end of file diff --git a/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/src/alg/mesh/XY.sv b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/src/alg/mesh/XY.sv new file mode 100644 index 0000000000000000000000000000000000000000..8a7ce59facebfba72b7178836fee76481bc6f42a --- /dev/null +++ b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/src/alg/mesh/XY.sv @@ -0,0 +1,60 @@ +// This is an XY example +`include "inc/router.svh" + +module algorithm +( + input[0:`PL-1] from_arbiter, + input[`CS-1:0] router_X, + input[`CS-1:0] router_Y, + input[`REN_B-1:0] shift, + output shift_signals[0:`REN-1], + input availability_signals_in[0:`REN-1], + output wire[0:`PL-1] outputs[0:`REN-1] +); + + wire[`CS-1:0] destination_X = from_arbiter[1:`CS]; + wire[`CS-1:0] destination_Y = from_arbiter[`CS+1:2*`CS]; + + wire[0:4] selector; + assign selector[0] = ((destination_X == router_X) & (destination_Y == router_Y)) & availability_signals_in[0] & from_arbiter[0]; + assign selector[1] = (destination_Y < router_Y) & availability_signals_in[1] & from_arbiter[0]; + assign selector[2] = (destination_X > router_X) & availability_signals_in[2] & from_arbiter[0]; + assign selector[3] = (destination_Y > router_Y) & availability_signals_in[3] & from_arbiter[0]; + assign selector[4] = (destination_X < router_X) & availability_signals_in[4] & from_arbiter[0]; + + wire shift_required = selector[0] | selector[1] | selector[2] | selector[3] | selector[4]; + + + assign shift_signals[0] = shift_required & (shift == 0); + assign shift_signals[1] = shift_required & (shift == 1); + assign shift_signals[2] = shift_required & (shift == 2); + assign shift_signals[3] = shift_required & (shift == 3); + assign shift_signals[4] = shift_required & (shift == 4); + + wire[0:`PL-1] check_selector[0:`REN-1]; + + generate + genvar i, j; + for (i = 0; i < `PL; i = i + 1 ) begin : generate_outputs_bits_core + assign outputs[0][i] = from_arbiter[i] & selector[0]; + end + + for (i = 0; i < `PL; i = i + 1 ) begin : generate_outputs_bits_north + assign outputs[1][i] = from_arbiter[i] & selector[1]; + end + + for (i = 0; i < `PL; i = i + 1 ) begin : generate_outputs_bits_east + assign outputs[2][i] = from_arbiter[i] & selector[2] & !selector[1] & !selector[3]; + end + + for (i = 0; i < `PL; i = i + 1 ) begin : generate_outputs_bits_south + assign outputs[3][i] = from_arbiter[i] & selector[3]; + end + + for (i = 0; i < `PL; i = i + 1 ) begin : generate_outputs_bits_west + assign outputs[4][i] = from_arbiter[i] & selector[4] & !selector[1] & !selector[3]; + end + + endgenerate + +endmodule \ No newline at end of file diff --git a/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/src/alg/torus/XY.sv b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/src/alg/torus/XY.sv new file mode 100644 index 0000000000000000000000000000000000000000..40d1dc80b76f9a84f4cf8eca30eb734b1a9329cd --- /dev/null +++ b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/src/alg/torus/XY.sv @@ -0,0 +1,80 @@ +// This is an XY example +`include "inc/router.svh" +`include "inc/noc_XY.svh" + +module algorithm +( + input[0:`PL-1] from_arbiter, + input[`CS-1:0] router_X, + input[`CS-1:0] router_Y, + input[`REN_B-1:0] shift, + output shift_signals[0:`REN-1], + input availability_signals_in[0:`REN-1], + output wire[0:`PL-1] outputs[0:`REN-1] +); + + wire[`CS-1:0] len_X = `X; + wire[`CS-1:0] len_Y = `Y; + + wire[`CS-1:0] destination_X = from_arbiter[1:`CS]; + wire[`CS-1:0] destination_Y = from_arbiter[`CS+1:2*`CS]; + + wire[0:4] selector_step1; + assign selector_step1[0] = ((destination_X == router_X) & (destination_Y == router_Y)); + assign selector_step1[1] = (destination_Y > router_Y); + assign selector_step1[2] = (destination_X > router_X); + assign selector_step1[3] = (destination_Y < router_Y); + assign selector_step1[4] = (destination_X < router_X); + + + wire [0:4] selector; + + assign selector[0] = selector_step1[0] & availability_signals_in[0] & from_arbiter[0]; + + assign selector[1] = ((selector_step1[1] & (len_Y - destination_Y + router_Y <= destination_Y - router_Y)) | + (selector_step1[3] & (len_Y - router_Y + destination_Y > router_Y - destination_Y))) & availability_signals_in[1] & from_arbiter[0]; + + assign selector[2] = ((selector_step1[2] & (len_X - destination_X + router_X > destination_X - router_X)) | + (selector_step1[4] & (len_X - router_X + destination_X <= router_X - destination_X))) & availability_signals_in[2] & from_arbiter[0]; + + assign selector[3] = ((selector_step1[1] & (len_Y - destination_Y + router_Y > destination_Y - router_Y)) | + (selector_step1[3] & (len_Y - router_Y + destination_Y <= router_Y - destination_Y))) & availability_signals_in[3] & from_arbiter[0]; + + assign selector[4] = ((selector_step1[2] & (len_X - destination_X + router_X <= destination_X - router_X)) | + (selector_step1[4] & (len_X - router_X + destination_X > router_X - destination_X))) & availability_signals_in[4] & from_arbiter[0]; + + + wire shift_required = selector[0] | selector[1] | selector[2] | selector[3] | selector[4]; + + + assign shift_signals[0] = shift_required & (shift == 0); + assign shift_signals[1] = shift_required & (shift == 1); + assign shift_signals[2] = shift_required & (shift == 2); + assign shift_signals[3] = shift_required & (shift == 3); + assign shift_signals[4] = shift_required & (shift == 4); + + generate + genvar i, j; + for (i = 0; i < `PL; i = i + 1 ) begin : generate_outputs_bits_core + assign outputs[0][i] = from_arbiter[i] & selector[0]; + end + + for (i = 0; i < `PL; i = i + 1 ) begin : generate_outputs_bits_north + assign outputs[1][i] = from_arbiter[i] & selector[1]; + end + + for (i = 0; i < `PL; i = i + 1 ) begin : generate_outputs_bits_east + assign outputs[2][i] = from_arbiter[i] & selector[2] & !selector[1] & !selector[3]; + end + + for (i = 0; i < `PL; i = i + 1 ) begin : generate_outputs_bits_south + assign outputs[3][i] = from_arbiter[i] & selector[3]; + end + + for (i = 0; i < `PL; i = i + 1 ) begin : generate_outputs_bits_west + assign outputs[4][i] = from_arbiter[i] & selector[4] & !selector[1] & !selector[3]; + end + + endgenerate + +endmodule \ No newline at end of file diff --git a/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/src/arb/RR_arbiter.sv b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/src/arb/RR_arbiter.sv new file mode 100644 index 0000000000000000000000000000000000000000..eb262d0800c62771b7c7fea71a2e8974166e765a --- /dev/null +++ b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/src/arb/RR_arbiter.sv @@ -0,0 +1,60 @@ +`include "inc/router.svh" + + +module arbiter ( + + input clk, + + input[0:`PL-1] input_[0:`REN-1], + + output wire[0:`PL-1] output_data, + + output reg[`REN_B-1:0] shift = 0 +); + wire[0:`REN-1] selector; + wire[0:2*`REN-1] shifted_selector; + wire[0:`REN-1] shifted_selector_sector; + + assign shifted_selector = {selector, selector} << shift; + assign shifted_selector_sector = shifted_selector[0:`REN-1]; + + genvar i; + generate + for (i = 0; i < `REN; i = i + 1) + begin : arbiter_selector_generator + assign selector[i] = input_[i][0]; + end + endgenerate + + always @(posedge clk) + begin + casex (shifted_selector_sector) + 5'b10000: + begin + end + 5'bx1xxx: + begin + shift <= (shift + 1 >= `REN) ? shift + 1 - `REN : shift + 1; + end + 5'bx01xx: + begin + shift <= (shift + 2 >= `REN) ? shift + 2 - `REN : shift + 2; + end + 5'bx001x: + begin + shift <= (shift + 3 >= `REN) ? shift + 3 - `REN : shift + 3; + end + 5'bx0001: + begin + shift <= (shift + 4 >= `REN) ? shift + 4 - `REN : shift + 4; + end + default: + begin + shift <= 0; + end + endcase + end + + assign output_data = input_[shift]; + +endmodule \ No newline at end of file diff --git a/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/src/bfr/index_queue.sv b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/src/bfr/index_queue.sv new file mode 100644 index 0000000000000000000000000000000000000000..9ef5eb59eb33a150663c86a728fb8c7b09f640f7 --- /dev/null +++ b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/src/bfr/index_queue.sv @@ -0,0 +1,77 @@ +`include "inc/queue.svh" + +module buffer ( + input clk, + input[0:`PL-1] data_in, + output reg[0:`PL-1] data_out = 0, + input shift_signal + ); + + always @(posedge clk) begin + if (shift_signal | !data_out[0]) begin + data_out <= data_in; + end else begin end + end + +endmodule + +module queue ( + input clk, + input[0:`PL-1] data_in, + output[0:`PL-1] data_out, + input shift_signal, + output availability_signal +); + +wire[0:`PL-1] inner_data_wires[0:`EN]; +wire[0:`PL-1] inner_data_wires_insertion[0:`EN]; + +generate + genvar i; + for (i = 0; i<`EN; i=i+1) begin : buffer_initialiser + if (i == 0) + begin + buffer buffer_i( + .clk(clk), + .data_in(inner_data_wires_insertion[i]), + .data_out(inner_data_wires[i+1]), + .shift_signal(shift_signal) + ); + end + else + begin + buffer buffer_i( + .clk(clk), + .data_in(inner_data_wires[i]|inner_data_wires_insertion[i]), + .data_out(inner_data_wires[i+1]), + .shift_signal(shift_signal) + ); + end + end +endgenerate + +assign availability_signal = ~inner_data_wires[1][0]; +assign data_out = inner_data_wires[`EN]; + +reg[`EN_B+1:0] available_buffer_pointer = `EN-1; + +wire[`EN_B:0] insert_index = $signed(available_buffer_pointer+shift_signal) < `EN ? available_buffer_pointer+shift_signal : `EN-1; + +generate + for (i = 0; i<`EN; i=i+1) begin : insertion_initialiser + assign inner_data_wires_insertion[i] = i == insert_index & availability_signal ? data_in: 0; + end +endgenerate + +always @(posedge clk) begin + if(inner_data_wires_insertion[insert_index][0]) + begin + available_buffer_pointer <= available_buffer_pointer - (!shift_signal | available_buffer_pointer == (`EN - 1)); + end + else + begin + available_buffer_pointer <= insert_index; + end +end + +endmodule diff --git a/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/src/bfr/line_queue.sv b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/src/bfr/line_queue.sv new file mode 100644 index 0000000000000000000000000000000000000000..2d64d05a3e009a0402b1c72bb75c8a4dc1e5a114 --- /dev/null +++ b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/src/bfr/line_queue.sv @@ -0,0 +1,50 @@ +`include "inc/queue.svh" + +module queue ( + input clk, + input[0:`PL-1] data_in, + input shift_signal, + output wire[0:`PL-1] data_out, + output wire availability_signal +); + + reg[0:`PL-1] queue_buffers[0:`EN-1]; + + wire[0:`EN+1] selector; + assign selector[`EN] = shift_signal; + assign selector[`EN+1] = data_in[0]; + + assign availability_signal = !queue_buffers[`EN-1][0]; + + assign data_out = queue_buffers[0]; + + genvar j; + generate + for (j = 0; j < `EN; j = j + 1) + begin : queue_selector_generator + assign selector[j] = queue_buffers[j][0]; + end + endgenerate + + initial + begin + int i; + for (i = 0; i < `EN; i = i + 1) // initialize queue at 0 + begin + queue_buffers[i] = 0; + end + end + + always @(posedge clk) + begin + + + casez (selector) // find queue entry + +{0} + + endcase + + end + +endmodule \ No newline at end of file diff --git a/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/src/bfr/pointer_queue.sv b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/src/bfr/pointer_queue.sv new file mode 100644 index 0000000000000000000000000000000000000000..f7ee8f88b66dcc425f8acd0851aa0e3a1acbcf1b --- /dev/null +++ b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/src/bfr/pointer_queue.sv @@ -0,0 +1,58 @@ +`include "inc/queue.svh" + +module queue ( + input clk, + input[0:`PL-1] data_in, + input shift_signal, + output wire[0:`PL-1] data_out, + output reg availability_signal = 1 + +); + + reg[0:`PL-1] queue_buffers[0:`EN-1] /* synthesis ramstyle = "logic" */; + reg[`EN_B:0] ptr_write = 0; + reg[`EN_B:0] ptr_read = 0; + reg empty_flag = 1; + + initial + begin + int i; + for (i = 0; i < `EN; i = i + 1) // initialize queue at 0 + begin + queue_buffers[i] = 0; + end + end + + assign data_out = empty_flag ? 0 : queue_buffers[ptr_read]; + + always @(posedge clk) + begin + casez({data_in[0], availability_signal, shift_signal, empty_flag}) + 4'b110? : begin + queue_buffers[ptr_write] <= data_in; + ptr_write <= (ptr_write + 1) % `EN; + availability_signal <= ((ptr_write + 1) % `EN) != ptr_read; + empty_flag <= 0; + end + 4'b1110 : begin + queue_buffers[ptr_write] <= data_in; + ptr_write <= (ptr_write + 1) % `EN; + ptr_read <= (ptr_read + 1) % `EN; + end + 4'b1111 : begin + queue_buffers[ptr_write] <= data_in; + ptr_write <= (ptr_write + 1) % `EN; + empty_flag <= 0; + end + 4'b0?10 : begin + ptr_read <= (ptr_read + 1) % `EN; + availability_signal <= 1; + empty_flag <= ptr_write == ((ptr_read + 1) % `EN); + end + default: begin + end + endcase + + end + +endmodule \ No newline at end of file diff --git a/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/src/rtr/f_router.sv b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/src/rtr/f_router.sv new file mode 100644 index 0000000000000000000000000000000000000000..ce7d24c4f9f3fd7340e763f24da7c2d9719a144a --- /dev/null +++ b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/src/rtr/f_router.sv @@ -0,0 +1,35 @@ +`include "inc/router.svh" +`include "src/queue.sv" +`include "src/arbiter.sv" +`include "src/algorithm.sv" + +module router ( + {0} +); + + wire[0:`PL-1] queue_to_arbiter[0:`REN-1]; + wire[0:`PL-1] arbiter_to_algorithm; + wire shift_signals[0:`REN-1]; + wire[`REN_B-1:0] shift; + wire send_data_flag; + + + generate + genvar i; + for (i=0; i<`REN; i=i+1) begin : queues_initialiser + queue queue_i (.clk(clk), + .data_in(inputs[i]), .data_out(queue_to_arbiter[i]), + .availability_signal(signals_out[i]), .shift_signal(shift_signals[i])); + end + endgenerate + + + arbiter round_robin(.clk(clk), + .input_(queue_to_arbiter), .output_data(arbiter_to_algorithm), + .shift(shift) + ); + + {1} + + +endmodule diff --git a/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/src/rtr/r_router.sv b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/src/rtr/r_router.sv new file mode 100644 index 0000000000000000000000000000000000000000..584af96e38908c44d569097dbb3f168ea6e50771 --- /dev/null +++ b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/src/rtr/r_router.sv @@ -0,0 +1,35 @@ +`include "inc/router.svh" +`include "src/queue.sv" +`include "src/arbiter.sv" +`include "src/algorithm.sv" + +module router ( + {0} +); + + wire[0:`PL-1] arbiter_to_algorithm; + wire[0:`PL-1] algotihm_to_queue[0:`REN-1]; + wire availability_signals[0:`REN-1]; + wire[`REN_B-1:0] shift; + wire send_data_flag; + + + generate + genvar i; + for (i=0; i<`REN; i=i+1) begin : queues_initialiser + queue queue_i (.clk(clk), + .data_in(algotihm_to_queue[i]), .data_out(outputs[i]), + .availability_signal(availability_signals[i]), .shift_signal(signals_in[i])); + end + endgenerate + + + arbiter round_robin(.clk(clk), + .input_(inputs), .output_data(arbiter_to_algorithm), + .shift(shift) + ); + + {1} + + +endmodule diff --git a/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/tb/queueing/front/circle.sv b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/tb/queueing/front/circle.sv new file mode 100644 index 0000000000000000000000000000000000000000..3c028b9b6d3ed1752022ecdf8ecabc09bc22f83f --- /dev/null +++ b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/tb/queueing/front/circle.sv @@ -0,0 +1,103 @@ +`include "src/router.sv" +`include "inc/queue.svh" +`include "inc/noc.svh" +`include "inc/router.svh" +`timescale 1ns/1ns + + +module tb_queueing; + + +reg clk = 0; +reg[0:`PL-1] inputs[0:`REN-1]; +wire[0:`PL-1] outputs[0:`REN-1]; +reg signals_in[0:`REN-1]; +wire signals_out[0:`REN-1]; +reg[`CS-1:0] router_NO = `RN / 2; + +integer i; +integer j; +integer k; +reg[0:`PL-1] packet; +reg[`PL - `CS - 2:0] info; +wire[3:0] arb_shift = DUT.round_robin.shift; + +router DUT ( + clk, + inputs, outputs, + signals_in, signals_out, + router_NO +); + +localparam CLK_PERIOD = 10; +always #(CLK_PERIOD/2) clk=~clk; + + +initial begin + + + for (k = 1; k < `REN; k = k + 2) + begin + + for (i = 0; i < `REN; i = i + 1) + begin + signals_in[i] = 0; + inputs[i] = 0; + end + + for (i = 1; i < `REN + 1; i = i + k) + begin + + for (j = 0; j < `EN * 2; j = j + 1) // testing with overflow + begin + info = ((i % `REN)+1) * (j+1); + packet = {1'b1, router_NO, info}; + @(posedge clk) + begin + inputs[(i % `REN)] <= packet; + end + end + @(posedge clk) + begin + inputs[(i % `REN)] <= 0; + end + + end + + @(posedge clk) + begin + inputs[0] <= 0; + end + + + if (k == 1) + while (arb_shift != 0) @(posedge clk); + else + while (arb_shift != 1 + k) @(posedge clk); + + for (i = 0; i < `REN; i = i + 1) + begin + signals_in[i] = 1; + end + + for (j = 0; j < `EN; j = j + 1) + begin + + for (i = 1; i < `REN + 1; i = i + k) + begin + info = ((i % `REN)+1) * (j+1); + packet = {1'b1, router_NO, info}; + @(posedge clk) + begin + assert (outputs[0] == packet) else $error("Packet %b not to be seen", packet); + end + end + + end + + end + + $finish; +end + +endmodule \ No newline at end of file diff --git a/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/tb/queueing/front/rectangle.sv b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/tb/queueing/front/rectangle.sv new file mode 100644 index 0000000000000000000000000000000000000000..83202dd9fcb5fe713a3104ad03d3e30491458847 --- /dev/null +++ b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/tb/queueing/front/rectangle.sv @@ -0,0 +1,105 @@ +`include "src/router.sv" +`include "inc/queue.svh" +`include "inc/noc.svh" +`include "inc/noc_XY.svh" +`include "inc/router.svh" +`timescale 1ns/1ns + + +module tb_queueing; + + +reg clk = 0; +reg[0:`PL-1] inputs[0:`REN-1]; +wire[0:`PL-1] outputs[0:`REN-1]; +reg signals_in[0:`REN-1]; +wire signals_out[0:`REN-1]; +reg[`CS-1:0] router_X = `X / 2; +reg[`CS-1:0] router_Y = `Y / 2; + +integer i; +integer j; +integer k; +reg[0:`PL-1] packet; +reg[`PL - `CS*2 - 2:0] info; +wire[3:0] arb_shift = DUT.round_robin.shift; + +router DUT ( + clk, + inputs, outputs, + signals_in, signals_out, + router_X, router_Y +); + +localparam CLK_PERIOD = 10; +always #(CLK_PERIOD/2) clk=~clk; + + +initial begin + + + for (k = 1; k < `REN; k = k + 2) + begin + + for (i = 0; i < `REN; i = i + 1) + begin + signals_in[i] = 0; + inputs[i] = 0; + end + + for (i = 1; i < `REN + 1; i = i + k) + begin + + for (j = 0; j < `EN * 2; j = j + 1) // testing with overflow + begin + info = ((i % `REN)+1) * (j+1); + packet = {1'b1, router_X, router_Y, info}; + @(posedge clk) + begin + inputs[(i % `REN)] <= packet; + end + end + @(posedge clk) + begin + inputs[(i % `REN)] <= 0; + end + + end + + @(posedge clk) + begin + inputs[0] <= 0; + end + + + if (k == 1) + while (arb_shift != 0) @(posedge clk); + else + while (arb_shift != 1 + k) @(posedge clk); + + for (i = 0; i < `REN; i = i + 1) + begin + signals_in[i] = 1; + end + + for (j = 0; j < `EN; j = j + 1) + begin + + for (i = 1; i < `REN + 1; i = i + k) + begin + info = ((i % `REN)+1) * (j+1); + packet = {1'b1, router_X, router_Y, info}; + @(posedge clk) + begin + assert (outputs[0] == packet) else $error("Packet %b not to be seen", packet); + end + end + + end + + end + + $finish; +end + +endmodule \ No newline at end of file diff --git a/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/tb/queueing/rear/circle.sv b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/tb/queueing/rear/circle.sv new file mode 100644 index 0000000000000000000000000000000000000000..056708bb62b78d651b1ef08e38ed2d6cecdb1dc8 --- /dev/null +++ b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/tb/queueing/rear/circle.sv @@ -0,0 +1,84 @@ +`include "src/router.sv" +`include "inc/queue.svh" +`include "inc/noc.svh" +`include "inc/router.svh" +`timescale 1ns/1ns + + +module tb_queueing; + + +reg clk = 0; +reg[0:`PL-1] inputs[0:`REN-1]; +wire[0:`PL-1] outputs[0:`REN-1]; +reg signals_in[0:`REN-1]; +wire signals_out[0:`REN-1]; +reg[`CS-1:0] router_NO = `RN / 2; + +reg[`CS-1:0] destination_NO[0:4] = {router_NO, router_NO - `LT, router_NO - 1, router_NO + 1, router_NO + `LT}; + +integer i; +integer j; +reg[0:`PL-1] packet; +reg[`PL - `CS - 2:0] info; + +router DUT ( + clk, + inputs, outputs, + signals_in, signals_out, + router_NO +); + +localparam CLK_PERIOD = 10; +always #(CLK_PERIOD/2) clk=~clk; + + +initial begin + + for (i = 0; i < `REN; i = i + 1) + begin + signals_in[i] = 0; + inputs[i] = 0; + end + + for (i = 0; i < `REN; i = i + 1) + begin + + for (j = 0; j < `EN * 2; j = j + 1) // testing with overflow + begin + info = (i+1) * (j+1); + packet = {1'b1, destination_NO[i], info}; + @(posedge clk) + begin + inputs[0] <= packet; + end + end + + end + + @(posedge clk) + begin + inputs[0] <= 0; + end + + for (i = 0; i < `REN; i = i + 1) + begin + signals_in[i] = 1; + end + + for (j = 0; j < `EN; j = j + 1) + begin + @(posedge clk) + begin + for (i = 0; i < `REN; i = i + 1) + begin + info = (i+1) * (j+1); + packet = {1'b1, destination_NO[i], info}; + assert (outputs[i] == packet) else $error("Packet %b not to be seen", packet); + end + end + end + $finish; +end + +endmodule \ No newline at end of file diff --git a/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/tb/queueing/rear/rectangle.sv b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/tb/queueing/rear/rectangle.sv new file mode 100644 index 0000000000000000000000000000000000000000..50e71b0c5e2c45e0e70884a0568b4534e1b9fc29 --- /dev/null +++ b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/tb/queueing/rear/rectangle.sv @@ -0,0 +1,87 @@ +`include "src/router.sv" +`include "inc/queue.svh" +`include "inc/noc.svh" +`include "inc/noc_XY.svh" +`include "inc/router.svh" +`timescale 1ns/1ns + + +module tb_queueing; + + +reg clk = 0; +reg[0:`PL-1] inputs[0:`REN-1]; +wire[0:`PL-1] outputs[0:`REN-1]; +reg signals_in[0:`REN-1]; +wire signals_out[0:`REN-1]; +reg[`CS-1:0] router_X = `X / 2; +reg[`CS-1:0] router_Y = `Y / 2; + +reg[`CS-1:0] destination_X[0:4] = {`X / 2, `X / 2, `X / 2 + 1, `X / 2, `X / 2 - 1}; +reg[`CS-1:0] destination_Y[0:4] = {`Y / 2, `Y / 2 - 1, `Y / 2, `Y / 2 + 1, `Y / 2}; + +integer i; +integer j; +reg[0:`PL-1] packet; +reg[`PL - `CS*2 - 2:0] info; + +router DUT ( + clk, + inputs, outputs, + signals_in, signals_out, + router_X, router_Y +); + +localparam CLK_PERIOD = 10; +always #(CLK_PERIOD/2) clk=~clk; + + +initial begin + + for (i = 0; i < `REN; i = i + 1) + begin + signals_in[i] = 0; + inputs[i] = 0; + end + + for (i = 0; i < `REN; i = i + 1) + begin + + for (j = 0; j < `EN * 2; j = j + 1) // testing with overflow + begin + info = (i+1) * (j+1); + packet = {1'b1, destination_X[i], destination_Y[i], info}; + @(posedge clk) + begin + inputs[0] <= packet; + end + end + + end + + @(posedge clk) + begin + inputs[0] <= 0; + end + + for (i = 0; i < `REN; i = i + 1) + begin + signals_in[i] = 1; + end + + for (j = 0; j < `EN; j = j + 1) + begin + @(posedge clk) + begin + for (i = 0; i < `REN; i = i + 1) + begin + info = (i+1) * (j+1); + packet = {1'b1, destination_X[i], destination_Y[i], info}; + assert (outputs[i] == packet) else $error("Packet %b not to be seen", packet); + end + end + end + $finish; +end + +endmodule \ No newline at end of file diff --git a/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/tb/routing/circle.sv b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/tb/routing/circle.sv new file mode 100644 index 0000000000000000000000000000000000000000..7a6671de2088996b35de8e7789b7d1244bd3c7cf --- /dev/null +++ b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/tb/routing/circle.sv @@ -0,0 +1,85 @@ +`include "noc/toplevel.sv" +`include "inc/noc.svh" +`timescale 1ns/1ns + +module tb_routing; + +reg clk = 0; +reg[0:`PL-1] packet = 0; +reg[`CS-1:0] core_NO = 0; +reg core_availability_signals_out[0:`RN-1]; +wire core_availability_signals_in[0:`RN-1]; +wire[0:1] core_inputs_2_bits[0:`RN-1]; + +reg[0:`PL-1] memory[0:`RN-1][0:1]; + +reg[31:0] i = 0; +reg[31:0] j = 0; +reg[31:0] t = 0; + +toplevel DUT (clk, packet, core_NO, core_availability_signals_out, core_availability_signals_in, core_inputs_2_bits); + +localparam CLK_PERIOD = 10; +always #(CLK_PERIOD/2) clk=~clk; + +initial begin + $dumpfile("tb/tb.vcd"); + + for (i = 0; i < `RN; i = i + 1) + begin + memory[i][0] = 0; + memory[i][1] = 0; + end + + for (i = 0; i < `RN; i = i + 1) + begin + core_availability_signals_out[i] = 1; + end + + for (i = 0; i < `RN; i = i + 1) + begin + for (j = 0; j < `RN; j = j + 1) + begin + @(posedge clk) + begin + core_NO <= i; + packet <= {1'b1, j[`CS-1:0], {(`PL-1-`CS){1'b0}}}; + end + @(posedge clk) + begin + packet <= {1'b1, j[`CS-1:0], {(`PL-1-`CS){1'b1}}}; + end + @(posedge clk) + begin + packet <= 0; + end + end + #1000; + for (j = 0; j < `RN; j = j + 1) + begin + assert (memory[j][0] == {1'b1, j[`CS-1:0], {(`PL-1-`CS){1'b0}}}) else $error("Packet %b not to be seen", {1'b1, j[`CS-1:0], {(`PL-1-`CS){1'b0}}}); + assert (memory[j][1] == {1'b1, j[`CS-1:0], {(`PL-1-`CS){1'b1}}}) else $error("Packet %b not to be seen", {1'b1, j[`CS-1:0], {(`PL-1-`CS){1'b1}}}); + memory[j][0] = 0; + memory[j][1] = 0; + end + end + #200; + $finish; + +end + +always @(*) +begin + + for (t = 0; t < `RN; t = t + 1) + begin + if (DUT.core_inputs[t] != 0) + if (DUT.core_inputs[t][`PL-1] == 0) + memory[t][0] = DUT.core_inputs[t]; + else + memory[t][1] = DUT.core_inputs[t]; + end + +end + +endmodule diff --git a/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/tb/routing/rectangle.sv b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/tb/routing/rectangle.sv new file mode 100644 index 0000000000000000000000000000000000000000..67a8cb3ffb392d85a6db47c86cac0366492cd639 --- /dev/null +++ b/Graph_verilog_generator/Graph_verilog_generator/verilog-primitives/tb/routing/rectangle.sv @@ -0,0 +1,109 @@ +`include "noc/toplevel.sv" +`include "inc/noc.svh" +`include "inc/noc_XY.svh" +`timescale 1ns/1ns + +module tb_routing; + +reg clk = 0; +reg[0:`PL-1] packet = 0; +reg[`CS-1:0] core_X = 0; +reg[`CS-1:0] core_Y = 0; +reg core_availability_signals_out[0:`Y-1][0:`X-1]; +wire core_availability_signals_in[0:`Y-1][0:`X-1]; +wire[0:1] core_inputs_2_bits[0:`Y-1][0:`X-1]; + +reg[0:`PL-1] memory[0:`Y-1][0:`X-1][0:1]; + +reg[31:0] i = 0; +reg[31:0] j = 0; +reg[31:0] k = 0; +reg[31:0] p = 0; +reg[31:0] t = 0; +reg[31:0] m = 0; + +toplevel DUT (clk, packet, core_X, core_Y, core_availability_signals_out, core_availability_signals_in, core_inputs_2_bits); + +localparam CLK_PERIOD = 10; +always #(CLK_PERIOD/2) clk=~clk; + +initial begin + $dumpfile("tb/tb.vcd"); + + for (k = 0; k < `Y; k = k + 1) + begin + for (p = 0; p < `X; p = p + 1) + begin + memory[k][p][0] = 0; + memory[k][p][1] = 0; + end + end + + for (k = 0; k < `Y; k = k + 1) + begin + for (p = 0; p < `X; p = p + 1) + begin + core_availability_signals_out[k][p] = 1; + end + end + + for (i = 0; i < `Y; i = i + 1) + begin + for (j = 0; j < `X; j = j + 1) + begin + for (k = 0; k < `Y; k = k + 1) + begin + for (p = 0; p < `X; p = p + 1) + begin + @(posedge clk) + begin + core_Y <= i; + core_X <= j; + packet <= {1'b1, p[`CS-1:0], k[`CS-1:0], {(`PL-1-`CS-`CS){1'b0}}}; + end + @(posedge clk) + begin + packet <= {1'b1, p[`CS-1:0], k[`CS-1:0], {(`PL-1-`CS-`CS){1'b1}}}; + end + @(posedge clk) + begin + packet <= 0; + end + end + end + #1000; + for (k = 0; k < `Y; k = k + 1) + begin + for (p = 0; p < `X; p = p + 1) + begin + assert (memory[k][p][0] == {1'b1, p[`CS-1:0], k[`CS-1:0], {(`PL-1-`CS-`CS){1'b0}}}) else $error("Packet %b not to be seen", {1'b1, p[`CS-1:0], k[`CS-1:0], {(`PL-1-`CS-`CS){1'b0}}}); + assert (memory[k][p][1] == {1'b1, p[`CS-1:0], k[`CS-1:0], {(`PL-1-`CS-`CS){1'b1}}}) else $error("Packet %b not to be seen", {1'b1, p[`CS-1:0], k[`CS-1:0], {(`PL-1-`CS-`CS){1'b1}}}); + memory[k][p][0] = 0; + memory[k][p][1] = 0; + end + end + end + end + #200; + $finish; + +end + +always @(*) +begin + + for (t = 0; t < `Y; t = t + 1) + begin + for (m = 0; m < `X; m = m + 1) + begin + if (DUT.core_inputs[t][m] != 0) + if (DUT.core_inputs[t][m][`PL-1] == 0) + memory[t][m][0] = DUT.core_inputs[t][m]; + else + memory[t][m][1] = DUT.core_inputs[t][m]; + end + end + +end + +endmodule diff --git a/Project_manager/Project_manager.sln b/Project_manager/Project_manager.sln new file mode 100644 index 0000000000000000000000000000000000000000..da7d2a4c36ce2555c11fa6ad9b4440c2480ebdc4 --- /dev/null +++ b/Project_manager/Project_manager.sln @@ -0,0 +1,25 @@ +п»ї +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.9.34728.123 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Project_manager", "Project_manager\Project_manager.csproj", "{9F9B386D-F8AE-4769-B354-8CFA35604F1B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9F9B386D-F8AE-4769-B354-8CFA35604F1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9F9B386D-F8AE-4769-B354-8CFA35604F1B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9F9B386D-F8AE-4769-B354-8CFA35604F1B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9F9B386D-F8AE-4769-B354-8CFA35604F1B}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {0B379225-DB49-4567-A034-C88F889CE0B0} + EndGlobalSection +EndGlobal diff --git a/Project_manager/Project_manager/Program.cs b/Project_manager/Project_manager/Program.cs new file mode 100644 index 0000000000000000000000000000000000000000..fa1b512c9972d22bfb7e7d32d6177a05955dbc88 --- /dev/null +++ b/Project_manager/Project_manager/Program.cs @@ -0,0 +1,213 @@ +п»їusing System.Text.Json; + +namespace HDLNoCGen +{ + static class Program + { + static void Main(string[] args) + { + string location = ""; + string name = ""; + string action = "o"; + string new_name = ""; + + try + { + for (int i = 0; i < args.Length; i++) + { + switch (args[i]) + { + case "-l": + case "--location": + location = args[++i]; + break; + case "-n": + case "--name": + name = args[++i]; + break; + case "-o": + case "--open": + action = "o"; + break; + case "-c": + case "--create": + action = "c"; + break; + case "-e": + case "--erase": + action = "e"; + break; + case "-r": + case "--rename": + action = "r"; + new_name = args[++i]; + break; + default: + Console.WriteLine($"Argument {args[i]} is invalid"); + Environment.Exit(1); + break; + } + } + } + catch (IndexOutOfRangeException e) + { + Console.WriteLine("No argument after an option that requires an argument"); + Environment.Exit(1); + } + + string metadata_location = $"{location}/{name}_metadata.json"; + string new_metadata_location = $"{location}/{new_name}_metadata.json"; + + string graph_location = $"{location}/{name}_graph_object_serialized.json"; + string new_graph_location = $"{location}/{new_name}_graph_object_serialized.json"; + + string verilog_location = $"{location}/{name}_NoC_description"; + string new_verilog_location = $"{location}/{new_name}_NoC_description"; + + switch (action) + { + case "o": + case "r": + + if (!Directory.Exists(location)) + { + Console.WriteLine("Failed to find project directory"); + Environment.Exit(1); + } + + if (!File.Exists(metadata_location)) + { + Console.WriteLine("Failed to find project metadata"); + Environment.Exit(1); + } + + StreamReader sr = new StreamReader(metadata_location); + string json = sr.ReadToEnd(); + sr.Close(); + ProjectSettings projectSettings = new ProjectSettings(); + + try + { + projectSettings = JsonSerializer.Deserialize<ProjectSettings>(json); + if (projectSettings.projectMetadata.name != name) + { + Console.WriteLine("Wrong project name in the metadata"); + Environment.Exit(1); + } + } + catch (Exception e) + { + Console.WriteLine("Failed to parse project metadata"); + Environment.Exit(1); + } + + if (action == "r") + { + projectSettings.projectMetadata.name = new_name; + json = JsonSerializer.Serialize<ProjectSettings>(projectSettings, new JsonSerializerOptions { WriteIndented = true }); + + try + { + File.Delete(metadata_location); + StreamWriter sw = new StreamWriter(new_metadata_location); + sw.Write(json); + sw.Close(); + + if (File.Exists(graph_location)) + { + File.Move(graph_location, new_graph_location); + } + if (File.Exists(metadata_location)) + { + File.Move(metadata_location, new_metadata_location); + } + if (Directory.Exists(verilog_location)) + { + Directory.Move(verilog_location, new_verilog_location); + } + } + catch (Exception e) + { + Console.WriteLine("Failed to rename the project"); + Environment.Exit(1); + } + } + + break; + case "c": + + if (!Directory.Exists(location)) + { + try + { + Directory.CreateDirectory(location); + } + catch (Exception e) + { + Console.WriteLine("Failed to create a project directory"); + } + } + + if (File.Exists(metadata_location)) + { + Console.WriteLine("This project already exists"); + Environment.Exit(1); + } + + ProjectSettings project_settings = new ProjectSettings(); + project_settings.projectMetadata.name = name; + string serialized = JsonSerializer.Serialize(project_settings, new JsonSerializerOptions { WriteIndented = true }); + + try + { + StreamWriter sw = new StreamWriter(metadata_location); + sw.Write(serialized); + sw.Close(); + } + catch (Exception e) + { + Console.WriteLine("Failed to create the project metadata"); + Environment.Exit(1); + } + + break; + case "e": + + if (!Directory.Exists(location)) + { + Console.WriteLine("Non-existent directory"); + Environment.Exit(0); + } + + if (!File.Exists(metadata_location)) + { + Console.WriteLine("Non-existent project"); + Environment.Exit(0); + } + + try + { + if (File.Exists(graph_location)) + { + File.Delete(graph_location); + } + if (File.Exists(metadata_location)) + { + File.Delete(metadata_location); + } + if (Directory.Exists(verilog_location)) + { + Directory.Delete(verilog_location, true); + } + } + catch (Exception e) + { + Console.WriteLine("Failed to delete the project"); + Environment.Exit(1); + } + + break; + } + } + } +} \ No newline at end of file diff --git a/Project_manager/Project_manager/Project_manager.csproj b/Project_manager/Project_manager/Project_manager.csproj new file mode 100644 index 0000000000000000000000000000000000000000..0a28e401c868ecb95c4b48f773009554b2f3fab4 --- /dev/null +++ b/Project_manager/Project_manager/Project_manager.csproj @@ -0,0 +1,14 @@ +п»ї<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <OutputType>Exe</OutputType> + <TargetFramework>net8.0</TargetFramework> + <ImplicitUsings>enable</ImplicitUsings> + <Nullable>enable</Nullable> + </PropertyGroup> + + <ItemGroup> + <Compile Include="..\..\Shared\ProjectSettings.cs" Link="ProjectSettings.cs" /> + </ItemGroup> + +</Project> diff --git a/Project_manager/Project_manager/Properties/launchSettings.json b/Project_manager/Project_manager/Properties/launchSettings.json new file mode 100644 index 0000000000000000000000000000000000000000..928db9c6fb75284c8d942db910962225ea3e01d8 --- /dev/null +++ b/Project_manager/Project_manager/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "Project_manager": { + "commandName": "Project", + "commandLineArgs": "-l C:/Users/Serha/Desktop/kal -n megakal -e" + } + } +} \ No newline at end of file diff --git a/Project_manager/Project_manager/project_metadata_template.json b/Project_manager/Project_manager/project_metadata_template.json new file mode 100644 index 0000000000000000000000000000000000000000..ee29641ec55ae6adf6b3cc62bd0738aa9d988290 --- /dev/null +++ b/Project_manager/Project_manager/project_metadata_template.json @@ -0,0 +1,20 @@ +{ + "project_metadata": { + "project_name": "MyProject" + }, + "graph_verilog_metadata": { + "graph_serialized": false, + "verilog_generated": false + }, + "quartus_metadata": { + "quartus_compiled": false, + "device_name": "5CGXFC9E7F35C8" + }, + "database_metadata": { + "database_ip": "localhost", + "database_username": "postgres", + "database_password": "password", + "database_name": "MyDatabase", + "database_port": 5432 + } +} \ No newline at end of file diff --git a/Shared/Graph.cs b/Shared/Graph.cs new file mode 100644 index 0000000000000000000000000000000000000000..652221fd2aef8d3e7bd8ab55eab2958f2d8cba0f --- /dev/null +++ b/Shared/Graph.cs @@ -0,0 +1,655 @@ +п»їnamespace HDLNoCGen +{ + /// <summary> + /// Перечисление типов графов. + /// </summary> + public enum GraphType + { + /// <summary> + /// Циркулянт. + /// </summary> + Circulant, + /// <summary> + /// Сетевой граф. + /// </summary> + Mesh, + /// <summary> + /// РўРѕСЂ. + /// </summary> + Torus + } + + /// <summary> + /// Набор опций для роутера. + /// </summary> + public struct RouterOptions + { + /// <summary> + /// Перечисление типов арбитров. + /// </summary> + public enum Arbiter_types + { + Round_Robin + }; + + /// <summary> + /// Перечисление типов очередей. + /// </summary> + public enum Queue_types + { + Index, + Pointer, + Line + }; + + /// <summary> + /// Выбор позиции очереди. + /// </summary> + public enum Queue_position + { + Front, + Rear + }; + + /// <summary> + /// Выбор позиции очереди. + /// </summary> + public enum Algorithm + { + XY, + GA + }; + } + + /// <summary> + /// Структура типа текущего роутера. + /// </summary> + public struct router_options + { + public RouterOptions.Arbiter_types arbiter_type { get; set; } + public RouterOptions.Queue_types queue_type { get; set; } + public RouterOptions.Queue_position queue_position { get; set; } + public RouterOptions.Algorithm algorithm { get; set; } + + public int packet_width { get; set; } + public int info_width { get; set; } + public int queue_length { get; set; } + } + + public class GraphDeserializer + { + public int node_count { get; set; } + + public List<int> generators { get; set; } + + public router_options parameters { get; set; } + + public GraphType graphId { get; set; } + } + + + /// <summary> + /// Класс, представляющий граф. + /// </summary> + public abstract class Graph + { + + /// <summary> + /// Сообщение РѕР± ошибке. + /// </summary> + protected string error_message { get; set; } + + /// <summary> + /// Даиметр графа. + /// </summary> + protected int diameter { get; set; } + + /// <summary> + /// Матрица смежности графа. + /// </summary> + protected int[,] matr_smej { get; set; } + + /// <summary> + /// Среднее расстояние между узлами графа. + /// </summary> + protected double average_distance { get; set; } + + /// <summary> + /// Минимальные пути РїРѕ алгоритму Дейкстры. + /// </summary> + protected List<List<int>> min_ways_routing_deikstra { get; set; } + + /// <summary> + /// Рффективность алгоритма Дейкстры. + /// </summary> + protected double efficiency_deikstra { get; set; } + + /// <summary> + /// Указывает, был ли создан граф. + /// </summary> + protected bool is_created { get; set; } + + /// <summary> + /// Количество узлов РІ графе. + /// </summary> + public int node_count { get; set; } + + /// <summary> + /// РЎРїРёСЃРѕРє генераторов графа. + /// </summary> + public List<int> generators { get; set; } + + public router_options parameters { get; set; } + + public GraphType graphId { get; set; } + + /// <summary> + /// Конструктор графа. + /// </summary> + public Graph() + { + this.error_message = ""; + + this.is_created = false; + this.generators = null; + this.node_count = 0; + this.efficiency_deikstra = 1; + } + + public Graph(GraphDeserializer graph_des) + { + this.parameters = graph_des.parameters; + this.generators = graph_des.generators; + this.node_count = graph_des.node_count; + this.graphId = graph_des.graphId; + } + + public abstract string getSignature(); + + protected abstract void SetNodeCountFromGenerators(List<int> generators); + + public void InstallGenerators(List<int> generators, CancellationToken token) + { + SetNodeCountFromGenerators(generators); + generators.Sort(); + for (int i = 0; i < generators.Count - Convert.ToInt32(this.graphId == GraphType.Circulant); i++) + { + if (token.IsCancellationRequested) + { + token.ThrowIfCancellationRequested(); + } + generators[i] = generators[i] % this.node_count; + } + + generators.Remove(0); + this.generators = generators; + + this.is_created = true; + + this.Calculate_diameter(token); + this.Generate_deikstra_routing(token); + + GC.Collect(); + } + + /// <summary> + /// Создает матрицу смежности (абстрактный метод). + /// </summary> + protected abstract void Create_matr_smej(); + + /// <summary> + /// Вычисляет эффективность алгоритма Дейкстры. + /// </summary> + /// <returns>Рффективность алгоритма Дейкстры.</returns> + public double Calculate_efficiency_deikstra() + { + this.efficiency_deikstra = 1.0; + + return this.efficiency_deikstra; + } + + /// <summary> + /// Вычисляет диаметр графа РЅР° РѕСЃРЅРѕРІРµ маршрутов, найденных алгоритмом Дейкстры. + /// </summary> + /// <param name="token">Токен для отмены операции.</param> + /// <returns>Диаметр графа или -1, если маршруты РЅРµ найдены.</returns> + public int Calculate_diameter(CancellationToken token) + { + if (this.min_ways_routing_deikstra == null) + return -1; + this.diameter = 0; + for (int i = 0; i < this.min_ways_routing_deikstra.Count; i++) + { + if (token.IsCancellationRequested) + { + token.ThrowIfCancellationRequested(); + } + if (this.min_ways_routing_deikstra[i].Count > this.diameter) + { + this.diameter = this.min_ways_routing_deikstra[i].Count; + } + } + --this.diameter; // Уменьшаем диаметр РЅР° 1, так как считаем количество рёбер + + return this.diameter; + } + + /// <summary> + /// Генерирует маршруты СЃ использованием алгоритма Дейкстры. + /// </summary> + /// <param name="token">Токен отмены для управления отменой операции.</param> + /// <returns>РЎРїРёСЃРѕРє кратчайших маршрутов между узлами графа.</returns> + /// <exception cref="OperationCanceledException">Выход, если операция была отменена.</exception> + public List<List<int>> Generate_deikstra_routing(CancellationToken token) + { + // Создаем матрицу смежности графа + Create_matr_smej(); + + // Рнициализируем СЃРїРёСЃРѕРє для хранения минимальных маршрутов + min_ways_routing_deikstra = new List<List<int>>(); + + // РџСЂРѕС…РѕРґРёРј РїРѕ каждому узлу графа + for (int m = 0; m < node_count; m++) + { + // Массивы для хранения расстояний Рё посещенных узлов + int[] d = new int[node_count]; // Расстояния РѕС‚ начального узла + int[] v = new int[node_count]; // Статус посещения узлов + int minindex; // Рндекс узла СЃ минимальным расстоянием + int min; // Минимальное расстояние + int temp; // Временная переменная для вычислений + List<int[]> ways; // РЎРїРёСЃРѕРє для хранения путей + + // Рнициализация массивов + for (int i = 0; i < node_count; i++) + { + if (token.IsCancellationRequested) + { + token.ThrowIfCancellationRequested(); + } + d[i] = 10000; // Устанавливаем максимальное значение расстояния + v[i] = 1; // Устанавливаем, что узел еще РЅРµ посещен + } + d[m] = 0; // Расстояние РґРѕ начального узла равно 0 + + // Шаг алгоритма + do + { + minindex = 10000; + min = 10000; + for (int i = 0; i < node_count; i++) + { // Если вершину ещё РЅРµ обошли Рё вес меньше min + if (token.IsCancellationRequested) + { + token.ThrowIfCancellationRequested(); + } + if ((v[i] == 1) && (d[i] < min)) + { // Переприсваиваем значения + min = d[i]; + minindex = i; + } + } + + // Добавляем найденный минимальный вес Рє текущему весу вершины + // Рё сравниваем СЃ текущим минимальным весом вершины + if (minindex != 10000) + { + for (int i = 0; i < node_count; i++) + { + if (matr_smej[minindex, i] > 0) + { + temp = min + matr_smej[minindex, i]; + if (temp < d[i]) + { + d[i] = temp; + } + } + } + v[minindex] = 0; + } + } while (minindex < 10000); + //конец алгоритма Дейкстра + + + //восстанавливаем пути + ways = new List<int[]>(); + for (int i = 0; i < node_count; i++) + { + int[] ver; + ver = new int[node_count]; + for (int j = 0; j < node_count; j++) + { + if (token.IsCancellationRequested) + { + token.ThrowIfCancellationRequested(); + } + ver[j] = -1; + } + int end = i; + ver[0] = end; + int k = 1; + int weight = d[end]; + + while (end != m)//РџРѕРєР° РЅРµ окажимся РІ начальной вершине + { + for (int j = 0; j < node_count; j++) + { + if (token.IsCancellationRequested) + { + token.ThrowIfCancellationRequested(); + } + if (matr_smej[end, j] > 0)//Если вершины смежны + { + temp = weight - matr_smej[end, j];//Предсказываем вес вершины + if (temp == d[j])//Если вес вершины совпал СЃ предсказанным + { + weight = temp; + end = j;//переходим РІ вершину + ver[k] = j;//записваем переход + k++; + break; + } + } + } + } + ways.Add(ver);//Записываем путь + } + + for (int i = 0; i < ways.Count; i++)//Расшифровываем пути + { + List<int> buff = new List<int>(); // Временный СЃРїРёСЃРѕРє для хранения маршрута + for (int j = node_count - 1; j > -1; j--) + { + if (token.IsCancellationRequested) + { + token.ThrowIfCancellationRequested(); + } + if (token.IsCancellationRequested) + { + token.ThrowIfCancellationRequested(); + } + if (ways[i][j] != -1)//Если переход РЅРµ пустой + { + buff.Add(ways[i][j]); // Добавляем вершину РІ маршрут + } + } + min_ways_routing_deikstra.Add(buff); // Добавляем маршрут РІ общий СЃРїРёСЃРѕРє маршрутов + } + } + + return this.min_ways_routing_deikstra; // Возвращаем СЃРїРёСЃРѕРє минимальных маршрутов + } + + /// <summary> + /// Создает экземпляр графа РІ зависимости РѕС‚ указанного типа графа. + /// </summary> + /// <param name="graphType">РўРёРї графа.</param> + /// <param name="buffer">Строка СЃ параметрами для создания графа.</param> + /// <param name="token">Токен отмены.</param> + /// <returns>Созданный экземпляр графа.</returns> + /// <exception cref="Exception">Выход, если тип графа РЅРµ поддерживается.</exception> + public Graph CreateGraphInstance(GraphType graphType, string buffer, CancellationToken token) + { + switch (graphType) + { + case GraphType.Circulant: + return new GraphCirculant(buffer, token); + case GraphType.Mesh: + return new GraphMesh(buffer, token); + case GraphType.Torus: + return new GraphTorus(buffer, token); + default: + throw new Exception("Unsupported graph type"); + } + } + + /// <summary> + /// Создает граф РЅР° РѕСЃРЅРѕРІРµ РІС…РѕРґРЅРѕРіРѕ буфера Рё возвращает его. + /// </summary> + /// <param name="buffer">Строка, содержащая информацию Рѕ графе.</param> + /// <param name="token">Токен для отмены операции.</param> + /// <returns>Созданный экземпляр графа.</returns> + /// <exception cref="Exception">Выход, если тип топологии графа некорректен.</exception> + public Graph CreateGraphFromBuffer(string buffer, CancellationToken token) + { + GraphType graphType; + + // Определение типа графа РЅР° РѕСЃРЅРѕРІРµ РІРІРѕРґР° + switch (buffer.Split(' ')[0]) + { + case "c": + case "C": + case "СЃ": + case "РЎ": + graphType = GraphType.Circulant; + break; + case "m": + case "M": + graphType = GraphType.Mesh; + break; + case "t": + case "T": + graphType = GraphType.Torus; + break; + default: + throw new Exception("Incorrect topology"); + } + + return CreateGraphInstance(graphType, buffer, token); + } + + /// <summary> + /// Виртуальная функция для генерации части проекта, отвечающей Р·Р° функционирование роутера. + /// </summary> + /// <param name="project_path">Путь Рє корневой папке проекта.</param> + /// <param name="parametrs">Параметры роутера.</param> + public virtual void createRouter(string project_path, router_options parametrs) + { + if (Directory.Exists(project_path)) + { + FileSystemWatcher watcher = new FileSystemWatcher(); + AutoResetEvent waitDeleteHandle = new AutoResetEvent(false); + + watcher.Path = project_path; + watcher.EnableRaisingEvents = true; + watcher.Deleted += new FileSystemEventHandler((sender, e) => + { + Directory.CreateDirectory(project_path); + Directory.CreateDirectory(project_path + "\\src"); + Directory.CreateDirectory(project_path + "\\inc"); + waitDeleteHandle.Set(); + }); + + Directory.Delete(project_path, true); + waitDeleteHandle.WaitOne(); + } + else + { + Directory.CreateDirectory(project_path); + Directory.CreateDirectory(project_path + "\\src"); + Directory.CreateDirectory(project_path + "\\inc"); + } + + File.Copy(descipher_router(parametrs.arbiter_type), project_path + "\\src\\arbiter.sv"); + File.Copy(descipher_router(parametrs.algorithm), project_path + "\\src\\algorithm.sv"); + + + string queue_path = descipher_router(parametrs.queue_type); + int queue_length = (int)parametrs.queue_length; + + switch (parametrs.queue_type) + { + case RouterOptions.Queue_types.Line: + string queue_text = File.ReadAllText(queue_path); + string casez_text = ""; + + #region casegenerator + + casez_text += " " + "'b0" + new string('?', queue_length) + "1:\n"; + casez_text += " " + "begin\n"; + casez_text += " " + " queue_buffers[0] <= data_in;\n"; + casez_text += " " + "end\n"; + + for (int i = 2; i < queue_length * 2; i++) + { + casez_text += " " + "'b" + new string('1', i / 2) + "0" + new string('?', queue_length - (i / 2) - 1) + $"{Convert.ToInt16(i % 2 == 0)}" + "1:\n"; + casez_text += " " + "begin\n"; + + for (int j = 1; (i % 2 == 0) && (j < i / 2); j++) + { + casez_text += " " + $" queue_buffers[{j - 1}] <= queue_buffers[{j}];\n"; + } + casez_text += " " + $" queue_buffers[{i / 2 - Convert.ToInt16(i % 2 == 0)}] <= data_in;\n"; + + casez_text += " " + "end\n"; + } + + casez_text += " " + "'b" + new string('1', queue_length + 2) + ":\n"; + casez_text += " " + "begin\n"; + for (int i = 1; i < queue_length; i++) + { + casez_text += " " + $" queue_buffers[{i - 1}] <= queue_buffers[{i}];\n"; + } + casez_text += " " + $" queue_buffers[{queue_length - 1}] <= 0;\n"; + casez_text += " " + "end\n"; + + casez_text += " " + "\n"; + + + for (int i = 1; i <= queue_length; i++) + { + casez_text += " " + "'b" + new string('1', i) + new string('0', Convert.ToInt32(i != queue_length)) + new string('?', Int32.Max(queue_length - i - 1, 0)) + "10:\n"; + casez_text += " " + "begin\n"; + + for (int j = 1; j < i; j++) + { + casez_text += " " + $" queue_buffers[{j - 1}] <= queue_buffers[{j}];\n"; + } + + casez_text += " " + $" queue_buffers[{i - 1}] <= 0;\n"; + casez_text += " " + "end\n\n"; + } + + casez_text += " " + "default:\n"; + casez_text += " " + "begin\n"; + casez_text += " " + "end"; + + #endregion + + queue_text = String.Format(queue_text, casez_text); + File.WriteAllText(project_path + "\\src\\queue.sv", queue_text); + + break; + case RouterOptions.Queue_types.Index: + case RouterOptions.Queue_types.Pointer: + File.Copy(queue_path, project_path + "\\src\\queue.sv"); + break; + default: + throw new NotImplementedException($"Queue type {parametrs.queue_type} was not implemented into this switch statement."); + } + + } + + /// <summary> + /// Виртуальная функция для генерации части проекта, отвечающей Р·Р° файл топологии. + /// </summary> + /// <param name="project_path">Путь Рє корневой папке проекта.</param> + public virtual void createNoC(string project_path, router_options parameters) + { + Directory.CreateDirectory(project_path + "\\noc"); + Directory.CreateDirectory(project_path + "\\tb"); + } + + /// <summary> + /// Получает минимальную длину числа РІ битах. + /// </summary> + /// <returns>Размер координат.</returns> + protected abstract int GetCordinatesSize(); //Returns how many bits are required to store coordinates + + public int get_bits(int num) + { + int bits = 1; + int counter = 2; + while (counter < num) + { + ++bits; + counter *= 2; + } + + return bits; + } + + /// <summary> + /// Возвращает относительный путь РґРѕ запрошенного файла. + /// </summary> + /// <param name="obj">Enum запрашиваемого объекта.</param> + protected string descipher_router(RouterOptions.Arbiter_types obj) + { + string response = "..\\..\\..\\verilog-primitives\\src\\arb\\"; + switch (obj) + { + case RouterOptions.Arbiter_types.Round_Robin: + response += "RR_"; + break; + default: + throw new NotImplementedException($"Arbiter {obj} was not implemented into this switch statement."); + } + return response + "arbiter.sv"; + } + + /// <summary> + /// Возвращает относительный путь РґРѕ запрошенного файла. + /// </summary> + /// <param name="obj">Enum запрашиваемого объекта.</param> + protected string descipher_router(RouterOptions.Queue_types obj) + { + string response = "..\\..\\..\\verilog-primitives\\src\\bfr\\"; + switch (obj) + { + case RouterOptions.Queue_types.Index: + response += "index_"; + break; + case RouterOptions.Queue_types.Pointer: + response += "pointer_"; + break; + case RouterOptions.Queue_types.Line: + response += "line_"; + break; + default: + throw new NotImplementedException($"Queue type {obj} was not implemented into this switch statement."); + } + return response + "queue.sv"; + } + /// <summary> + /// Возвращает относительный путь РґРѕ запрошенного файла. + /// </summary> + /// <param name="obj">Enum запрашиваемого объекта.</param> + protected abstract string descipher_router(RouterOptions.Algorithm obj); + + /// <summary> + /// Возвращает относительный путь РґРѕ запрошенного файла. + /// </summary> + /// <param name="obj">Enum запрашиваемого объекта.</param> + protected string descipher_router(RouterOptions.Queue_position obj) + { + string response = "..\\..\\..\\verilog-primitives\\src\\rtr\\"; + switch (obj) + { + case RouterOptions.Queue_position.Front: + response += "f_"; + break; + case RouterOptions.Queue_position.Rear: + response += "r_"; + break; + default: + throw new NotImplementedException($"Queue position {obj} was not implemented into this switch statement."); + } + string path = response + "router.sv"; + return File.ReadAllText(path); + } + + + } + + + +} diff --git a/Shared/GraphCirculant.cs b/Shared/GraphCirculant.cs new file mode 100644 index 0000000000000000000000000000000000000000..a19e564981847e14da9a3408e8feca0630a53273 --- /dev/null +++ b/Shared/GraphCirculant.cs @@ -0,0 +1,1734 @@ +п»їusing System.Text; +using System.Text.Json; + +namespace HDLNoCGen +{ + class GraphCirculant : Graph, IRoundLike + { + public override string getSignature() + { + return "Circulant"; + } + + protected int p { get; set; } // для алгоритма парной маршрутизации + protected List<List<int>> min_ways_routing_ROU { get; set; } // минимальные пути РїРѕ адаптивному алгоритму маршрутизации + protected List<List<int>> min_ways_routing_APM { get; set; } // минимальные пути РїРѕ алгоритму парной маршрутизации + protected List<List<int>> min_ways_routing_APO { get; set; } + protected List<List<int>> min_ways_routing_AAO { get; set; } + protected List<List<int>> min_ways_routing_AAO_orig { get; set; } // маинимальные пути РїРѕ алгоритму относительной маршрутизации + protected List<List<int>> min_ways_routing_gl { get; set; }// минимальные пути РїРѕ алгоритму парного обмена + protected List<List<int>> min_ways_routing_GA { get; set; } + protected List<List<int>> min_ways_routing_simple { get; set; } // минимальные пути РїРѕ простому алгоритму маршрутизации РЅР° 2 образующие + + protected double efficiency_simple { get; set; } + protected double efficiency_ROU { get; set; } + protected double efficiency_APM { get; set; } + protected double efficiency_APO { get; set; } + //private double efficiency_AAO; + //private double efficiency_AAO_orig; + protected double efficiency_GA { get; set; } + + protected double average_distance_GA { get; set; } + + public double Get_average_distance() + { + return this.average_distance; + } + + public int Get_p() + { + return this.p; + } + + public List<List<int>> Get_min_ways_routing_deikstra() + { + return this.min_ways_routing_deikstra; + } + + public List<List<int>> Get_min_ways_routing_simple() + { + return this.min_ways_routing_simple; + } + + public List<List<int>> Get_min_ways_routing_ROU() + { + return this.min_ways_routing_ROU; + } + + public List<List<int>> Get_min_ways_routing_APM() + { + return this.min_ways_routing_APM; + } + + public List<List<int>> Get_min_ways_routing_APO() + { + return this.min_ways_routing_APO; + } + + public double Get_efficiency_simple() + { + return this.efficiency_simple; + } + + public double Get_efficiency_ROU() + { + return this.efficiency_ROU; + } + + public double Get_efficiency_APM() + { + return this.efficiency_APM; + } + + public double Get_efficiency_APO() + { + return this.efficiency_APO; + } + + public List<List<int>> Get_min_ways_routing_GA() + { + return this.min_ways_routing_GA; + } + + public double Get_efficiency_GA() + { + return this.efficiency_GA; + } + + public GraphCirculant() : base() + { + this.diameter = 0; + this.p = 0; + this.graphId = GraphType.Circulant; + + } + + public GraphCirculant(GraphDeserializer graph_des) : base(graph_des) + { + + } + + public GraphCirculant(string parameters, CancellationToken token) + { + + this.graphId = GraphType.Circulant; + string[] buffer = parameters.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries); + string[] buffer_topology = buffer[0].Trim().Split(new string[] { "РЎ", "c", "C" , "СЃ" , ";", ":", ", ", ")", " " }, StringSplitOptions.RemoveEmptyEntries); + this.node_count = Convert.ToInt32(buffer_topology[0]); + generators = new List<int>(); + for (int i = 1; i < buffer_topology.Length; i++) + { + generators.Add(Convert.ToInt32(buffer_topology[i])); + } + + generators.Sort(); + for (int i = 0; i < generators.Count; i++) + { + if (token.IsCancellationRequested) + { + token.ThrowIfCancellationRequested(); + } + generators[i] = generators[i] % node_count; + if (this.node_count - generators[i] < generators[i]) + { + generators[i] = this.node_count - generators[i]; + } + } + generators.Add(node_count); + + string[] buffer_parameters; + if (buffer.Length > 1) + { + buffer_parameters = buffer[1].Trim().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); + buffer_parameters[0].Trim(); + string[] sub_buffer_parameters = buffer_parameters[0].Trim().Split(new string[] { "=" }, StringSplitOptions.RemoveEmptyEntries); + this.p = Convert.ToInt32(sub_buffer_parameters[1]); + } + + //string[] buffer = parameters.Split(new string[] { "РЎ(", "C(", ";", ":", ", ", ")", " " }, StringSplitOptions.RemoveEmptyEntries); + //this.node_count = Convert.ToInt32(buffer[0]); + //this.p = Convert.ToInt32(param_2); + + + + this.is_created = true; + } + + protected override void SetNodeCountFromGenerators(List<int> generators) + { + this.node_count = generators[0]; + } + + protected override void Create_matr_smej() + { + this.matr_smej = new int[this.node_count, this.node_count]; + + for (int i = 0; i < this.generators.Count; i++) + { + for (int j = 1; j < (this.node_count + 1); j++) + { + int k = this.generators[i] + j; + if (k > this.node_count) + { + k = k - this.node_count; + } + this.matr_smej[j - 1, k - 1] = 1; + this.matr_smej[k - 1, j - 1] = 1; + } + } + } + + public double Calculate_Average_distance() + { + this.average_distance = 0.0; + int hops = 0; + for (int i = 0; i < this.min_ways_routing_deikstra.Count; i++) + { + hops = hops + this.min_ways_routing_deikstra[i].Count - 1; + } + this.average_distance = Math.Round((double)hops / (double)this.min_ways_routing_deikstra.Count, 6); + + + return this.average_distance; + } + + public List<List<int>> Generate_Simple_routing() + { + this.min_ways_routing_simple = new List<List<int>>(); + + for (int m = 0; m < node_count; m++) + { + int iterations_count; // для того чтобы программа РЅРµ зависала, если РЅРµ может посчитать маршрут + + int start_node; + int end_node; + List<int> route; + + try + { + if (!this.is_created) + { + throw new Exception("Описание топологии РЅРµ было задано или задано РЅРµ полностью"); + } + + for (int i = 0; i < this.node_count; i++) + { + iterations_count = 0; + + start_node = m + 1; + end_node = i + 1; + route = new List<int>(); + route.Add(start_node - 1 + Settings.Get_node_naming_start_index()); + while (end_node != start_node) + { + iterations_count++; + + start_node = Simple_routing(start_node, end_node); + route.Add(start_node - 1 + Settings.Get_node_naming_start_index()); + + if (iterations_count > Settings.Get_error_iterations_count()) + { + throw new Exception("Превышено количество итераций моделирования маршрута для алгоритма Simple"); + } + } + this.min_ways_routing_simple.Add(route); + } + } + catch (Exception ex) + { + this.error_message = ex.Message; + return null; + } + } + + return this.min_ways_routing_simple; + } // проверка РЅР° ошибки добавлена + + private int Simple_routing(int start_node, int end_node) + { + int S = end_node - start_node; + if (S == 0) + { + return (start_node); + } + if (S < 0) + { + S = S + this.node_count; + } + if (S <= (this.node_count / 2)) + { + int i; + for (i = this.generators.Count() - 1; i > 0; i--) + { + if (S >= this.generators[i]) + { + start_node = (this.generators[i] + start_node) % this.node_count; + i = -1; + } + } + if (i == 0) + start_node = (this.generators[0] + start_node) % this.node_count; + } + else + { + S = this.node_count - S; + + int i; + for (i = this.generators.Count() - 1; i > 0; i--) + { + if (S >= this.generators[i]) + { + start_node = (this.generators[i] + start_node) % this.node_count; + i = -1; + } + } + if (i == 0) + start_node = (this.generators[0] + start_node) % this.node_count; + } + if (start_node == 0) start_node = this.node_count; + return (start_node); + } + + public List<List<int>> Generate_GL_routing() + { + int iterations_count; // для того чтобы программа РЅРµ зависала, если РЅРµ может посчитать маршрут + + int start_node; + int end_node; + List<int> route; + + this.min_ways_routing_gl = new List<List<int>>(); + + try + { + if (!this.is_created) + { + throw new Exception("Описание топологии РЅРµ было задано или задано РЅРµ полностью"); + } + + for (int i = 0; i < this.node_count; i++) + { + iterations_count = 0; + + start_node = 1; + end_node = i + 1; + route = new List<int>(); + route.Add(start_node - 1 + Settings.Get_node_naming_start_index()); + while (end_node != start_node) + { + iterations_count++; + start_node = GL_routing(this.node_count, this.generators, start_node, end_node); + route.Add(start_node - 1 + Settings.Get_node_naming_start_index()); + + if (iterations_count > Settings.Get_error_iterations_count()) + { + throw new Exception("Превышено количество итераций моделирования маршрута для алгоритма GL"); + } + } + this.min_ways_routing_gl.Add(route); + } + } + catch (Exception ex) + { + this.error_message = ex.Message; + return null; + } + + return this.min_ways_routing_gl; + } + + private int GL_routing(int nodesCount, List<int> generatrixes, int startNode, int endNode) + { + if (nodesCount <= 0) + { + throw new ArgumentOutOfRangeException(nameof(nodesCount), nodesCount, "Должно быть больше 0."); + } + + // Рщем точное расстояние Рё направление (РїРѕ часовой или против часовой стрелки) + int halfLength = nodesCount / 2; + int length = endNode - startNode; + + if (length == 0) + { + return endNode; + } + + // Рдем РїРѕ часовой, если разница индексов конечного узла Рё предыдущего РЅРµ меньше 0, иначе РІ противоположную. + bool isClockwise = length > 0; + + // флаг игнорирования условий. Обозначает, что была найдена образующая, дальнейший РїРѕРёСЃРє РЅРµ требуется + bool isQuit = false; + int value = -1; + + // Если текущее расстояние РїРѕ выбранному расстоянию будет больше половины пути, идем РІ противоположную сторону РѕС‚ выбранной + if (Math.Abs(length) > halfLength) + { + isClockwise = !isClockwise; + + if (endNode > startNode) + { + length = nodesCount - endNode + startNode; + } + else + { + length = nodesCount - startNode + endNode; + } + } + else + { + // Р’ противном случае, оставляем модуль "расстояния" + // это можно вынести перед if, избегая вызова для Math.Abs(length) дважды. + length = Math.Abs(length); + } + + // Расстояние Рё направление найдено + + var g1 = generatrixes[0]; + var g2 = generatrixes[1]; + + if (length >= g2) + { + var intG2 = length / g2; + var modG2 = length % g2; + + // Если нет остатка РѕС‚ большей образующей, идем только РїРѕ ней. + if (modG2 == 0) + { + value = isClockwise ? startNode + g2 : startNode - g2; + isQuit = true; + } + + if (!isQuit) + { + // РљРѕРіРґР° есть остаток, РЅРѕ есть возможность РЅРµ делать РґРѕРї. шаги, засчет выбора РїРѕ меньшей образующей. Р’ конечном результате, останется длина, кратная большей образующей, + // либо меньшей образующей + if (modG2 + intG2 >= g1) + { + isQuit = true; + value = isClockwise ? startNode + g1 : startNode - g1; + } + + // Находим расстояние, если Р±С‹ РїРѕРёСЃРє ввелся РїРѕ РѕРґРЅРѕР№ РёР· образующих, СЃ учетом РґРѕРї. шага для сокращения единичных шагов Рё единичные шаги + if (!isQuit) + { + // рассчет РїРѕ меньшей образующей + var lengthG1 = length / g1; + // оставшееся расстояние после движения + var cl1 = length - lengthG1 * g1; + + // требование для дополнительного шага + // cl1 > Math.Abs(cl1 - g1) -> 2 * cl1 > g1 + + if (cl1 > Math.Abs(cl1 - g1)) + { + // если потребовалось + lengthG1++; + // оставшийся путь СЃ учетом РґРѕРї.шага * 2 (РєРѕР»-РІРѕ единичных шагов) + // Math.Abs(cl1 - g1) -> g1 - cl1 + lengthG1 += Math.Abs(cl1 - g1) * 2; + } + else + { + // РЅРµ потребовалось, то оставшееся расстояние * 2 (оставшееся расстояние - это РєРѕР»-РІРѕ "единичных" шагов + lengthG1 += cl1 * 2; + } + + // рассчет РїРѕ большей образующей. Поймете. + var lengthG2 = length / g2; + cl1 = length - lengthG2 * g2; + + // РњС‹ всегда делаем РїРѕ меньшей образующей РґРѕРї. шаг, С‚.Рє. РІ любом случае Сѓ нас "отдалится" РѕС‚ конечного шага. + // P.S. возможно, есть ситуация, РєРѕРіРґР° нужно делать РїРѕ g2. РќРѕ это еще более усложнит алгоритм, Рё требуется только для альтернативных путей. + if (cl1 > Math.Abs(cl1 - g1)) + { + lengthG2++; + lengthG2 += Math.Abs(cl1 - g1) * 2; + } + else + { + lengthG2 += cl1 * 2; + } + + // выбор следующей образующей + var nextGeneratrix = lengthG1 < lengthG2 ? g1 : g2; + value = isClockwise ? startNode + nextGeneratrix : startNode - nextGeneratrix; + isQuit = true; + } + } + } + + // Выбрана меньшая образующая + if (length == g1) + { + value = endNode; + isQuit = true; + } + + if (!isQuit) + { + // Если требуется сделать РґРѕРї. шаг РїРѕ меньшей образующей для сокращения РєРѕР»-РІР° единичных шагов. + // Можно это условие заменить РЅР° 2 * length > g1 - без РІСЃСЏРєРёС… + 1 + if (length > Math.Abs(length - g1)) + { + value = isClockwise ? startNode + g1 : startNode - g1; + } + else + { + // Рдем РІ противоположную сторону, С‚.Рє. это будет первый этап "единичного" шага. + value = isClockwise ? startNode - g1 : startNode + g1; + } + } + + // Рндекс найден, "нормализируем" его. + if (value > 0) + { + // РќРµ требует нормализации. + if (value <= nodesCount) + { + return value; + } + + // Остаток будет следующим индексом узла, РіРґРµ условный пакет будет находиться + return value % nodesCount; + } + + // Рндекс "находится" РІ обратной стороне, для крупных отрицательных индексов такая схема работает. + // Можно заменить РЅР° nodes - value (это так просто) РїСЂРё оптимальных графах + return nodesCount - Math.Abs(value) % nodesCount; + } + + public List<List<int>> Generate_ROU_routing() + { + int iterations_count; // для того чтобы программа РЅРµ зависала, если РЅРµ может посчитать маршрут + + int start_node; + int end_node; + List<int> route; + + this.min_ways_routing_ROU = new List<List<int>>(); + + try + { + if (!this.is_created) + { + throw new Exception("Описание топологии РЅРµ было задано или задано РЅРµ полностью"); + } + + for (int i = 0; i < this.node_count; i++) + { + for (int j = 0; j < this.node_count; j++) + { + iterations_count = 0; + + start_node = i + 1; + end_node = j + 1; + route = new List<int>(); + route.Add(start_node - 1 + Settings.Get_node_naming_start_index()); + while (end_node != start_node) + { + iterations_count++; + start_node = ROU_routing(start_node, end_node, this.node_count, this.generators[0], this.generators[1]); + route.Add(start_node - 1 + Settings.Get_node_naming_start_index()); + + if (iterations_count > Settings.Get_error_iterations_count()) + { + throw new Exception("Превышено количество итераций моделирования маршрута для алгоритма ROU"); + } + } + this.min_ways_routing_ROU.Add(route); + } + } + } + catch (Exception ex) + { + this.error_message = ex.Message; + return null; + } + + return this.min_ways_routing_ROU; + } // проверка РЅР° ошибки добавлена + + private int ROU_routing(int start_node, int end_node, int node_count, int s1 = 1, int s2 = 2) + { + //чтобы начальный всегда был меньше конечного + //117 1 43 - надо устранение 2 циклов РїРѕ большой образующей + //500 1 276 - надо устранение 2+ циклов РїРѕ большой образующей + if (start_node > end_node) + { + start_node = start_node - Step_cicles(end_node, start_node, node_count, s1, s2); + //start_node = start_node - Step(end_node, start_node, N, s1, s2); + } + else + { + start_node = start_node + Step_cicles(start_node, end_node, node_count, s1, s2); + //start_node = start_node + Step(start_node, end_node, N, s1, s2); + } + + // ! работает тоже + // чтобы начальный всегда был меньше конечного + //if(start_node > end_node) + //{ + // end_node = end_node + N; + //} + //start_node = start_node + Step(start_node, end_node, N, s1, s2); + + // нормализация + if (start_node > node_count) + { + start_node = start_node - node_count; + } + else if (start_node <= 0) + { + start_node = start_node + node_count; + } + return start_node; + } + + /* + * РџРѕРёСЃРє шага, РєРѕРіРґР° 2 образующие, s1=1. Устраняются циклы. + */ + private int Step_cicles(int start_node, int end_node, int node_count, int s1, int s2) + { + int best_way_R = 0, step_R = 0, best_way_L = 0, step_L = 0; + int s = end_node - start_node; + + // лучший путь вправо Рё шаг + int R1 = s / s2 + s % s2; + int R2 = s / s2 - s % s2 + s2 + 1; + if (s % s2 == 0) + { + best_way_R = R1; + step_R = s2; + } + else + { + if (R1 < R2) + { + best_way_R = R1; + step_R = s1; + } + else + { + best_way_R = R2; + step_R = s2; + } + } + + //1 цикл + int R5 = (s + node_count) / s2 + (s + node_count) % s2; + int R6 = (s + node_count) / s2 - (s + node_count) % s2 + s2 + 1; + if (R5 < best_way_R) + { + best_way_R = R5; + step_R = s2; + } + if (R6 < best_way_R) + { + best_way_R = R6; + step_R = s2; + } + + //2 цикл + int R9 = (s + node_count + node_count) / s2 + (s + node_count + node_count) % s2; + int R10 = (s + node_count + node_count) / s2 - (s + node_count + node_count) % s2 + s2 + 1; + if (R9 < best_way_R) + { + best_way_R = R9; + step_R = s2; + } + if (R10 < best_way_R) + { + best_way_R = R10; + step_R = s2; + } + //3 цикл + //.. + + // лучший путь влево Рё шаг + s = start_node - end_node + node_count; + int L1 = s / s2 + s % s2; + int L2 = s / s2 - s % s2 + s2 + 1; + if (s % s2 == 0) + { + best_way_L = L1; + step_L = -s2; + } + else + { + if (L1 < L2) + { + best_way_L = L1; + step_L = -s1; + } + else + { + best_way_L = L2; + step_L = -s2; + } + } + + //1 цикл + int R7 = (s + node_count) / s2 + (s + node_count) % s2; + int R8 = (s + node_count) / s2 - (s + node_count) % s2 + s2 + 1; + if (R7 < best_way_L) + { + best_way_L = R7; + step_L = -s2; + } + if (R8 < best_way_L) + { + best_way_L = R8; + step_L = -s2; + } + + //2 цикл + int R11 = (s + node_count + node_count) / s2 + (s + node_count + node_count) % s2; + int R12 = (s + node_count + node_count) / s2 - (s + node_count + node_count) % s2 + s2 + 1; + if (R11 < best_way_L) + { + best_way_L = R11; + step_L = -s2; + } + if (R12 < best_way_L) + { + best_way_L = R12; + step_L = -s2; + } + + // решаем РєСѓРґР° шагнуть, Рё шагаем + if (best_way_R < best_way_L) + { + return step_R; + } + else + { + return step_L; + } + } + + /* + * РџРѕРёСЃРє шага, РєРѕРіРґР° 2 образующие, s1=1. Циклы РЅРµ проверяются. + */ + private int Step(int start_node, int end_node, int node_count, int s1 = 1, int s2 = 2) + { + int best_way_R = 0, step_R = 0, best_way_L = 0, step_L = 0; + int s = end_node - start_node; + + // лучший путь вправо Рё шаг + int R1 = s / s2 + s % s2; + int R2 = s / s2 - s % s2 + s2 + 1; + if (s % s2 == 0) + { + best_way_R = R1; + step_R = s2; + } + else + { + if (R1 < R2) + { + best_way_R = R1; + step_R = s1; + } + else + { + best_way_R = R2; + step_R = s2; + } + } + + // лучший путь влево Рё шаг + s = start_node - end_node + node_count; + int L1 = s / s2 + s % s2; + int L2 = s / s2 - s % s2 + s2 + 1; + if (s % s2 == 0) + { + best_way_L = L1; + step_L = -s2; + } + else + { + if (L1 < L2) + { + best_way_L = L1; + step_L = -s1; + } + else + { + best_way_L = L2; + step_L = -s2; + } + } + + // решаем РєСѓРґР° шагнуть, Рё шагаем + if (best_way_R < best_way_L) + { + return step_R; + } + else + { + return step_L; + } + } + + public List<List<int>> Generate_APM_routing() + { + this.min_ways_routing_APM = new List<List<int>>(); + int start_node; + int end_node; + List<int> route; // то что будет записываться РІ итоговый лист + List<int> buff_route; + + try + { + if (!this.is_created || this.p == 0) + { + throw new Exception("Описание топологии РЅРµ было задано или РЅРµ было произведено создание топологии"); + } + for (int i = 0; i < this.node_count; i++) + { + start_node = 1; + end_node = i + 1; + route = new List<int>(); + buff_route = new List<int>(); + buff_route = APM_routing(start_node, end_node, diameter, this.p); + + route.Add(start_node - 1 + Settings.Get_node_naming_start_index()); + for (int j = 0; j < 3; j++) + { + for (int k = 0; k < Math.Abs(buff_route[j]); k++) + { + if (buff_route[j] > 0) + { + start_node = start_node + generators[j]; + start_node = start_node % node_count; + if (start_node == 0) + { + start_node = node_count; + } + route.Add(start_node - 1 + Settings.Get_node_naming_start_index()); + } + else + { + start_node = start_node - generators[j]; + if (start_node < 0) + { + start_node = node_count + start_node; + } + if (start_node == 0) + { + start_node = node_count; + } + route.Add(start_node - 1 + Settings.Get_node_naming_start_index()); + } + } + } + + this.min_ways_routing_APM.Add(route); + } + } + catch (Exception ex) + { + this.error_message = ex.Message; + return null; + } + + return this.min_ways_routing_APM; + } + + private List<int> APM_routing(int start_node, int end_node, int d, int p) + { + bool flag_dir = false; // вычисояем как обычно + List<int> result = new List<int>(); + int V = end_node - start_node; + if (V >= node_count / 2) + { + V = node_count - V; + flag_dir = true; // инвертируем знаки РІ итоговом векторе + } + int gamma = 2 * (d + 1 - p); + int i = V / generators[2]; + int j, k, k1; + bool step; + + if (V < (i + 1) * generators[1]) + { + j = (V - i * generators[2]) / (generators[2] - generators[1]); + k = V - i * generators[2] - j * (generators[2] - generators[1]) - gamma; + k1 = i + 2 * j + gamma - d - 1; + step = false; + } + else + { + j = (V - (i + 1) * generators[1]) / (generators[2] - generators[1]); + k = V - (i + 1) * generators[1] - j * (generators[2] - generators[1]) - gamma + 1; + k1 = i + gamma - d - 1; + step = true; + } + + if (!step) // шаг 2 + { + if (((i + 2 * j) >= 0 && (i + 2 * j) <= (d - gamma) && (k >= -gamma) && (k <= 0)) || + (((i + 2 * j) > (d - gamma)) && (i + 2 * j) <= d && k >= -gamma && k < -k1)) + { + result.Add(k + gamma); + result.Add(-j); + result.Add(i + j); + } + else if (((i + 2 * j) >= 0 && (i + 2 * j) <= (d - gamma) && k >= 0 && k <= (gamma - 3)) || + ((i + 2 * j) > (d - gamma) && (i + 2 * j) <= d && k > k1 && k <= (gamma - 3))) + { + result.Add(-(gamma - k - 2)); + result.Add(-(j + 1)); + result.Add(i + j + 1); + } + else + { + result.Add(k); + result.Add(d + 1 - gamma / 2 - j); + result.Add(-(d - gamma / 2 - i - j)); + } + } + else // шаг 3 + { + if ((i >= 0 && i <= (d - gamma) && k > -gamma && k <= 0) || + (i > (d - gamma) && i <= (d - gamma / 2) && k > -gamma && k < -k1)) + { + result.Add(gamma - 1 - Math.Abs(k)); + result.Add(i + 1 - j); + result.Add(j); + } + else if ((i > (d - gamma) && i <= (d - gamma / 2) && Math.Abs(k) <= k1)) + { + result.Add(k); + result.Add(-(d - gamma / 2 - i + j)); + result.Add(-(d + 1 - gamma / 2 - j)); + } + else + { + result.Add(-(gamma - 1 - k)); + result.Add(i - j); + result.Add(j + 1); + } + } + + if (flag_dir) + { + result[0] = -result[0]; + result[1] = -result[1]; + result[2] = -result[2]; + } + + return result; + } + + public List<List<int>> Generate_APO_routing() + { + this.min_ways_routing_APO = new List<List<int>>(); + int start_node; + int end_node; + List<int> route; // то что будет записываться РІ итоговый лист + List<int> buff_route; + + try + { + if (!this.is_created) + { + throw new Exception("Описание топологии РЅРµ было задано или задано РЅРµ полностью"); + } + + for (int i = 0; i < this.node_count; i++) + { + for (int j = 0; j < this.node_count; j++) + { + start_node = i + 1; + end_node = j + 1; + route = new List<int>(); + buff_route = new List<int>(); // получаем сколько нужно пройти РїРѕ первой Рё РїРѕ второй образующим + buff_route = APO_routing(start_node, end_node, generators[0]); + + route.Add(start_node - 1 + Settings.Get_node_naming_start_index());// сначала записываем узел РёР· которого идем + for (int k = 0; k < 2; k++) + { + for (int m = 0; m < Math.Abs(buff_route[k]); m++) + { + if (buff_route[k] > 0) + { + start_node = start_node + generators[k]; + start_node = start_node % node_count; + if (start_node == 0) + { + start_node = node_count; + } + route.Add(start_node - 1 + Settings.Get_node_naming_start_index()); + + } + else + { + start_node = start_node - generators[k]; + if (start_node < 0) + { + start_node = node_count + start_node; + } + if (start_node == 0) + { + start_node = node_count; + } + route.Add(start_node - 1 + Settings.Get_node_naming_start_index()); + } + } + } + + this.min_ways_routing_APO.Add(route); + } + } + } + catch (Exception ex) + { + this.error_message = ex.Message; + return null; + } + + return this.min_ways_routing_APO; + } + + private List<int> APO_routing(int start_node, int end_node, int s1) + { + List<int> result = new List<int>(); //хранит 2 числа сколько нужно шагов РїРѕ РїРѕ первой образующей Рё сколько РїРѕ второй + int sgn = 0; + int alpha = 0; + int betta = 0; + int k = 0; + + k = Math.Abs(start_node - end_node); + if (end_node <= start_node) + { + sgn = -1; + } + else + { + sgn = 1; + } + + if (k > (node_count / 2)) + { + sgn = -sgn; + k = node_count - k; + } + + betta = k % s1; + alpha = k / s1 - betta; + + if ((alpha >= (betta - s1)) && (alpha <= s1)) + { + result.Add(alpha * sgn); + result.Add(betta * sgn); + } + else if (alpha < (betta - s1)) + { + result.Add((alpha + s1 + 1) * sgn); + result.Add((betta - s1) * sgn); + } + else + { + result.Add((alpha - (s1 + 1)) * sgn); + result.Add((betta + s1) * sgn); + } + + return result; + } + + public List<List<int>> Generate_AAO_routing() + { + this.min_ways_routing_AAO = new List<List<int>>(); + int start_node; + int end_node; + List<int> route; + List<int> buff_route; + Random rnd = new Random(); + + try + { + if (!this.is_created) + { + throw new Exception("Описание топологии РЅРµ было задано или задано РЅРµ полностью"); + } + + int[] node_name_x = new int[this.node_count]; // координата X узла (колво шагов РїРѕ малой РѕР±СЂ) + int[] node_name_y = new int[this.node_count]; // координата Y узла (колво шагов РїРѕ большой РѕР±СЂ) + + for (int i = 1; i < this.node_count; i++) // генерация координат узлов + { + List<int> buff_list = new List<int>(this.min_ways_routing_deikstra[i]); + for (int j = 1; j < buff_list.Count; j++) + { + int checker = (buff_list[j] - buff_list[j - 1]); + if (checker == this.generators[0]) + { + node_name_x[i] += 1; + } + else if (checker == this.generators[1]) + { + node_name_y[i] += 1; + } + else if (checker == -this.generators[0]) + { + node_name_x[i] -= 1; + } + else if (checker == -this.generators[1]) + { + node_name_y[i] -= 1; + } + else + { + if (checker > 0) + { + checker = (buff_list[j] - buff_list[j - 1]) - this.node_count; + if (checker == -this.generators[0]) + { + node_name_x[i] -= 1; + } + else if (checker == -this.generators[1]) + { + node_name_y[i] -= 1; + } + } + else + { + checker = (buff_list[j] - buff_list[j - 1]) + this.node_count; + if (checker == this.generators[0]) + { + node_name_x[i] += 1; + } + else if (checker == this.generators[1]) + { + node_name_y[i] += 1; + } + } + } + } + } // генерация координат узлов + + for (int i = 0; i < node_count; i++) + { + //start_node = 1; + //end_node = i + 1; + + start_node = rnd.Next(1, node_count); + end_node = rnd.Next(1, node_count); + + route = new List<int>(); + buff_route = new List<int>(); // получаем сколько нужно пройти РїРѕ первой Рё РїРѕ второй образующим + buff_route = AAO_routing(node_name_x[start_node - 1], node_name_y[start_node - 1], node_name_x[end_node - 1], node_name_y[end_node - 1]); + route.Add(start_node - 1 + Settings.Get_node_naming_start_index()); + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < Math.Abs(buff_route[j]); k++) + { + if (buff_route[j] > 0) + { + start_node = start_node + generators[j]; + start_node = start_node % node_count; + if (start_node == 0) + { + start_node = node_count; + } + route.Add(start_node - 1 + Settings.Get_node_naming_start_index()); + + } + else + { + start_node = start_node - generators[j]; + if (start_node < 0) + { + start_node = node_count + start_node; + } + if (start_node == 0) + { + start_node = node_count; + } + route.Add(start_node - 1 + Settings.Get_node_naming_start_index()); + } + } + } + + this.min_ways_routing_AAO.Add(route); + } + + } + catch (Exception ex) + { + this.error_message = ex.Message; + return null; + } + + return this.min_ways_routing_AAO; + } + + private List<int> AAO_routing(int x_start_node, int y_start_node, int x_dest_node, int y_dest_node) + { + List<int> result = new List<int>(); //хранит 2 числа сколько нужно шагов РїРѕ РїРѕ первой образующей Рё сколько РїРѕ второй + int dx = x_dest_node - x_start_node; + int dy = y_dest_node - y_start_node; + + int abs_summ = Math.Abs(dx) + Math.Abs(dy); + if (abs_summ > this.diameter) + { + int[] dxi = new int[8]; + int[] dyi = new int[8]; + + dxi[0] = dx + this.diameter + 1; dyi[0] = dy - this.diameter; + dxi[1] = dx - 1; dyi[1] = dy + 2 * this.diameter; + dxi[2] = dx + 2 * this.diameter + 1; dyi[2] = dy; + dxi[3] = dx + this.diameter; dyi[3] = dy + this.diameter; + dxi[4] = dx - this.diameter - 1; dyi[4] = dy + this.diameter; + dxi[5] = dx + 1; dyi[5] = dy - 2 * this.diameter; + dxi[6] = dx - 2 * this.diameter - 1; dyi[6] = dy; + dxi[7] = dx - this.diameter; dyi[7] = dy - this.diameter; + + dx = dxi[0]; dy = dyi[0]; + + for (int i = 1; i < 8; i++) + { + abs_summ = Math.Abs(dx) + Math.Abs(dy); + int abs_summ2 = Math.Abs(dxi[i]) + Math.Abs(dyi[i]); + + if (abs_summ2 < abs_summ) + { + dx = dxi[i]; dy = dyi[i]; + } + } + } + + result.Add(dx); + result.Add(dy); + + return result; + } + + public List<List<int>> Generate_AAO_routing_orig() + { + this.min_ways_routing_AAO_orig = new List<List<int>>(); + int start_node; + int end_node; + List<int> route; + List<int> buff_route; + Random rnd = new Random(); + + try + { + if (!this.is_created) + { + throw new Exception("Описание топологии РЅРµ было задано или задано РЅРµ полностью"); + } + + int[] node_name_x = new int[this.node_count]; // координата X узла (колво шагов РїРѕ малой РѕР±СЂ) + int[] node_name_y = new int[this.node_count]; // координата Y узла (колво шагов РїРѕ большой РѕР±СЂ) + + for (int i = 1; i < this.node_count; i++) // генерация координат узлов + { + List<int> buff_list = new List<int>(this.min_ways_routing_deikstra[i]); + for (int j = 1; j < buff_list.Count; j++) + { + int checker = (buff_list[j] - buff_list[j - 1]); + if (checker == this.generators[0]) + { + node_name_x[i] += 1; + } + else if (checker == this.generators[1]) + { + node_name_y[i] += 1; + } + else if (checker == -this.generators[0]) + { + node_name_x[i] -= 1; + } + else if (checker == -this.generators[1]) + { + node_name_y[i] -= 1; + } + else + { + if (checker > 0) + { + checker = (buff_list[j] - buff_list[j - 1]) - this.node_count; + if (checker == -this.generators[0]) + { + node_name_x[i] -= 1; + } + else if (checker == -this.generators[1]) + { + node_name_y[i] -= 1; + } + } + else + { + checker = (buff_list[j] - buff_list[j - 1]) + this.node_count; + if (checker == this.generators[0]) + { + node_name_x[i] += 1; + } + else if (checker == this.generators[1]) + { + node_name_y[i] += 1; + } + } + } + } + } // генерация координат узлов + + int count = 0; + int[] ai = new int[4]; + int[] bi = new int[4]; + + string FileName; + string Base_FolderName; + string file_name; + string FilePath; + + FileStream fs; + StreamReader sr; + + file_name = node_count.ToString() + "_nodes"; + Base_FolderName = "zeroes"; + + FileName = file_name + ".txt"; + FilePath = Directory.GetCurrentDirectory() + @"\" + Base_FolderName + @"\" + FileName; + + fs = new FileStream(FilePath, FileMode.Open, FileAccess.ReadWrite); + sr = new StreamReader(fs); + + for (int i = 0; i < 4; i++) + { + string buffer = sr.ReadLine(); + string[] buffer2 = buffer.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); + if (buffer2.Length == 2) + { + ai[count] = Int32.Parse(buffer2[0]); + bi[count] = Int32.Parse(buffer2[1]); + count++; + } + } + + sr.Close(); + fs.Close(); + + for (int i = 0; i < node_count; i++) + { + //start_node = 1; + //end_node = i + 1; + + start_node = 9;//rnd.Next(1, node_count); + end_node = 5;//rnd.Next(1, node_count); + + route = new List<int>(); + buff_route = new List<int>(); // получаем сколько нужно пройти РїРѕ первой Рё РїРѕ второй образующим + buff_route = AAO_routing_orig(node_name_x[start_node - 1], node_name_y[start_node - 1], node_name_x[end_node - 1], node_name_y[end_node - 1], ai, bi, count); + route.Add(start_node - 1 + Settings.Get_node_naming_start_index()); + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < Math.Abs(buff_route[j]); k++) + { + if (buff_route[j] > 0) + { + start_node = start_node + generators[j]; + start_node = start_node % node_count; + if (start_node == 0) + { + start_node = node_count; + } + route.Add(start_node - 1 + Settings.Get_node_naming_start_index()); + + } + else + { + start_node = start_node - generators[j]; + if (start_node < 0) + { + start_node = node_count + start_node; + } + if (start_node == 0) + { + start_node = node_count; + } + route.Add(start_node - 1 + Settings.Get_node_naming_start_index()); + } + } + } + + this.min_ways_routing_AAO_orig.Add(route); + } + + } + catch (Exception ex) + { + this.error_message = ex.Message; + return null; + } + + return this.min_ways_routing_AAO_orig; + } + + private List<int> AAO_routing_orig(int x_start_node, int y_start_node, int x_dest_node, int y_dest_node, int[] ai, int[] bi, int count) + { + List<int> result = new List<int>(); //хранит 2 числа сколько нужно шагов РїРѕ РїРѕ первой образующей Рё сколько РїРѕ второй + int dx = x_dest_node - x_start_node; + int dy = y_dest_node - y_start_node; + + int abs_summ = Math.Abs(dx) + Math.Abs(dy); + if (abs_summ >= this.diameter) + { + int[] dxi = new int[9]; + int[] dyi = new int[9]; + + for (int i = 0; i < count; i++) + { + dxi[i] = dx + ai[i]; dyi[i] = dy + bi[i]; + dxi[i + count] = dx - ai[i]; dyi[i + count] = dy - bi[i]; + } + dxi[count * 2] = dx; dyi[count * 2] = dy; + + dx = dxi[0]; dy = dyi[0]; + + for (int i = 1; i < (count * 2 + 1); i++) + { + abs_summ = Math.Abs(dx) + Math.Abs(dy); + int abs_summ2 = Math.Abs(dxi[i]) + Math.Abs(dyi[i]); + + if (abs_summ2 < abs_summ) + { + dx = dxi[i]; dy = dyi[i]; + } + } + } + + result.Add(dx); + result.Add(dy); + + return result; + } + + + public double Calculate_efficiency_simple() + { + double deikstra_algorithm_L = 0; + double simple_algorithm_L = 0; + + for (int i = 0; i < this.min_ways_routing_deikstra.Count; i++) + { + deikstra_algorithm_L += this.min_ways_routing_deikstra[i].Count - 1; + simple_algorithm_L += this.min_ways_routing_simple[i].Count - 1; + } + + efficiency_simple = Math.Round((deikstra_algorithm_L / simple_algorithm_L), 3); + return this.efficiency_simple; + } + + public double Calculate_efficiency_ROU() + { + double deikstra_algorithm_L = 0; + double ROU_algorithm_L = 0; + + for (int i = 0; i < this.min_ways_routing_deikstra.Count; i++) + { + deikstra_algorithm_L += this.min_ways_routing_deikstra[i].Count - 1; + ROU_algorithm_L += this.min_ways_routing_ROU[i].Count - 1; + } + + efficiency_ROU = Math.Round((deikstra_algorithm_L / ROU_algorithm_L), 3); + return this.efficiency_ROU; + } + + public double Calculate_efficiency_APM() + { + double deikstra_algorithm_L = 0; + double APM_algorithm_L = 0; + + for (int i = 0; i < this.min_ways_routing_deikstra.Count; i++) + { + deikstra_algorithm_L += this.min_ways_routing_deikstra[i].Count - 1; + APM_algorithm_L += this.min_ways_routing_APM[i].Count - 1; + } + + efficiency_APM = Math.Round((deikstra_algorithm_L / APM_algorithm_L), 3); + return this.efficiency_APM; + } + + public double Calculate_efficiency_APO() + { + double deikstra_algorithm_L = 0; + double APO_algorithm_L = 0; + + for (int i = 0; i < this.min_ways_routing_deikstra.Count; i++) + { + deikstra_algorithm_L += this.min_ways_routing_deikstra[i].Count - 1; + APO_algorithm_L += this.min_ways_routing_APO[i].Count - 1; + } + + efficiency_APO = Math.Round((deikstra_algorithm_L / APO_algorithm_L), 3); + return this.efficiency_APO; + } + + + public List<List<int>> Generate_GA_routing(CancellationToken token) + { + this.min_ways_routing_GA = new List<List<int>>(); + + for (int m = 0; m < node_count; m++) + { + int iterations_count; // для того чтобы программа РЅРµ зависала, если РЅРµ может посчитать маршрут + + int start_node; + int end_node; + List<int> route; + + try + { + if (!this.is_created) + { + throw new Exception("Описание топологии РЅРµ было задано или задано РЅРµ полностью"); + } + + for (int i = 0; i < this.node_count; i++) + { + if (token.IsCancellationRequested) + { + token.ThrowIfCancellationRequested(); + } + iterations_count = 0; + + start_node = m; + end_node = i; + route = new List<int>(); + route.Add(start_node + Settings.Get_node_naming_start_index()); + while (end_node != start_node) + { + iterations_count++; + + start_node = GA_routing(start_node, end_node); + route.Add(start_node + Settings.Get_node_naming_start_index()); + + if (iterations_count > Settings.Get_error_iterations_count()) + { + throw new Exception("Превышено количество итераций моделирования маршрута для алгоритма GA"); + } + } + this.min_ways_routing_GA.Add(route); + } + } + catch (Exception ex) + { + this.error_message = ex.Message; + return null; + } + } + + return this.min_ways_routing_GA; + } + + private int GA_routing(int start_node, int end_node) + { + int relative_destination = node_count + 100; + int next_node = node_count + 100; + List<int> generators = new List<int> { this.generators[0], this.generators[1] }; + + if (end_node > start_node) + { + if (end_node - start_node <= (start_node + node_count) - end_node) + { + relative_destination = end_node - start_node; + } + else + { + relative_destination = end_node - (start_node + node_count); + } + } + else if (end_node < start_node) + { + if (start_node - end_node <= (end_node + node_count) - start_node) + { + relative_destination = end_node - start_node; + } + else + { + relative_destination = (end_node + node_count) - start_node; + } + } + else + { + relative_destination = 0; + } + + if (relative_destination > 0) + { + if (relative_destination > generators[1]) + { + next_node = start_node + generators[1]; + } + else if (generators[1] - relative_destination < relative_destination) + { + next_node = start_node + generators[1]; + } + else + { + next_node = start_node + 1; + } + } + else if (relative_destination < 0) + { + if (-relative_destination > generators[1]) + { + next_node = start_node + node_count - generators[1]; + } + else if (generators[1] - (-relative_destination) < -relative_destination) + { + next_node = start_node + node_count - generators[1]; + } + else + { + next_node = start_node + node_count - 1; + } + } + + return next_node % node_count; + } + + public double Calculate_efficiency_GA(CancellationToken token) + { + double deikstra_algorithm_L = 0; + double simple_algorithm_L = 0; + + for (int i = 0; i < this.min_ways_routing_deikstra.Count; i++) + { + if (token.IsCancellationRequested) + { + token.ThrowIfCancellationRequested(); + } + deikstra_algorithm_L += this.min_ways_routing_deikstra[i].Count - 1; + simple_algorithm_L += this.min_ways_routing_GA[i].Count - 1; + } + + efficiency_GA = Math.Round((deikstra_algorithm_L / simple_algorithm_L), 3); + return this.efficiency_GA; + } + + public double Calculate_average_distance_GA(CancellationToken token) + { + average_distance_GA = 0; + + for (int i = 0; i < this.min_ways_routing_GA.Count; i++) + { + if (token.IsCancellationRequested) + { + token.ThrowIfCancellationRequested(); + } + average_distance_GA += min_ways_routing_GA[i].Count; + } + average_distance_GA /= min_ways_routing_GA.Count; + + return average_distance_GA; + } + + protected override int GetCordinatesSize() + { + int coordinates_size = 0; + int counter = 1; + while (counter < node_count) + { + coordinates_size++; + counter *= 2; + } + return coordinates_size; + } + + protected override string descipher_router(RouterOptions.Algorithm obj) + { + string response = "..\\..\\..\\verilog-primitives\\src\\alg\\circulant\\"; + + switch (obj) + { + case RouterOptions.Algorithm.GA: + response += "GA.sv"; + break; + default: + throw new NotImplementedException($"Algorithm {obj} was not implemented into this switch statement."); + } + + return response; + } + + public override void createRouter(string project_path, router_options parametrs) + { + base.createRouter(project_path, parametrs); + + string router_format = descipher_router(parametrs.queue_position); + string router_text = ""; + string router_json = File.ReadAllText("..\\..\\..\\router_variants.json"); + var router_variants = JsonSerializer.Deserialize<Dictionary<string, Dictionary<string, Dictionary<string, List<string>>>>>(router_json); + + switch (parametrs.algorithm, parametrs.queue_position) + { + case (RouterOptions.Algorithm.GA, RouterOptions.Queue_position.Front): + router_text = String.Format(router_format, String.Join("\n ", router_variants["circulant"]["ga"]["front"].Select(s => $"{s}")).Split("c#_splitter")); + break; + case (RouterOptions.Algorithm.GA, RouterOptions.Queue_position.Rear): + router_text = String.Format(router_format, String.Join("\n ", router_variants["circulant"]["ga"]["rear"].Select(s => $"{s}")).Split("c#_splitter")); + break; + default: + throw new NotImplementedException($"Router format {parametrs.algorithm}, {parametrs.queue_position} was not implemented into this switch statement."); + } + + File.WriteAllText(project_path + "\\src\\router.sv", router_text); + + + string file_to_format = "noc"; + string file_text = ""; + file_text = File.ReadAllText("..\\..\\..\\verilog-primitives\\inc\\" + file_to_format + ".svh"); + File.WriteAllText(project_path + "\\inc\\" + file_to_format + ".svh", String.Format(file_text, + parametrs.packet_width, + GetCordinatesSize(), + node_count + )); + + file_to_format = "noc_CIRCULANT"; + var new_generators = this.generators.Slice(0, this.generators.Count - 1); + new_generators = new_generators.Select(s => this.node_count - s).Reverse().Concat(new_generators).ToList(); + file_text = File.ReadAllText("..\\..\\..\\verilog-primitives\\inc\\" + file_to_format + ".svh"); + File.WriteAllText(project_path + "\\inc\\" + file_to_format + ".svh", String.Format(file_text, + "{`CS'd" + String.Join(", `CS'd", new_generators.Select(s => $"{s}")) + "}", + this.generators[1] + )); + + file_to_format = "queue"; + file_text = File.ReadAllText("..\\..\\..\\verilog-primitives\\inc\\" + file_to_format + ".svh"); + File.WriteAllText(project_path + "\\inc\\" + file_to_format + ".svh", String.Format(file_text, + parametrs.queue_length, get_bits(parametrs.queue_length) + )); + + file_to_format = "router"; + file_text = File.ReadAllText("..\\..\\..\\verilog-primitives\\inc\\" + file_to_format + ".svh"); + File.WriteAllText(project_path + "\\inc\\" + file_to_format + ".svh", String.Format(file_text, + this.generators.Count * 2 - 1, + this.get_bits(this.generators.Count * 2 - 1) + )); + + } + public override void createNoC(string project_path, router_options parameters) + { + base.createNoC(project_path, parameters); + + File.Copy("..\\..\\..\\verilog-primitives\\sel\\circle.sv", project_path + "\\noc\\toplevel.sv"); + File.Copy("..\\..\\..\\verilog-primitives\\noc\\circulant.sv", project_path + "\\noc\\noc.sv"); + File.Copy("..\\..\\..\\verilog-primitives\\tb\\routing\\circle.sv", project_path + "\\tb\\tb_routing.sv"); + + switch (parameters.queue_position) + { + case RouterOptions.Queue_position.Front: + File.Copy("..\\..\\..\\verilog-primitives\\tb\\queueing\\front\\circle.sv", project_path + "\\tb\\tb_queueing.sv"); + break; + case RouterOptions.Queue_position.Rear: + File.Copy("..\\..\\..\\verilog-primitives\\tb\\queueing\\rear\\circle.sv", project_path + "\\tb\\tb_queueing.sv"); + break; + } + } + } +} diff --git a/Shared/GraphMesh.cs b/Shared/GraphMesh.cs new file mode 100644 index 0000000000000000000000000000000000000000..0ad92e6a56b5e3f9e179831826e59f1a8b987dd9 --- /dev/null +++ b/Shared/GraphMesh.cs @@ -0,0 +1,332 @@ +п»їusing System.Text; +using System.Text.Json; + +namespace HDLNoCGen +{ + class GraphMesh : Graph, IRectangleLike + { + public override string getSignature() + { + return "Mesh"; + } + + protected List<List<int>> ways_routing_XY { get; set; } + + protected double efficiencyXY { get; set; } + + protected double average_distance_XY { get; set; } + + public GraphMesh() : base() + { + this.ways_routing_XY = null; + this.graphId = GraphType.Mesh; + } + + public GraphMesh(GraphDeserializer graph_des) : base(graph_des) + { + + } + + public GraphMesh(string paraneters, CancellationToken token) + { + this.graphId = GraphType.Mesh; + this.node_count = 1; + + string[] buffer = paraneters.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries); + string[] buffer_topology = buffer[0].Trim().Split(new string[] { "M", "m", ";", ":", ", ", ")", " " }, StringSplitOptions.RemoveEmptyEntries); + generators = new List<int>(); + + for (int i = 0; i < buffer_topology.Length && i < 2; i++) + { + generators.Add(Convert.ToInt32(buffer_topology[i])); + this.node_count *= generators[i]; + } + + if (generators.Min() < 2) + { + throw new Exception("Неправильно задана топология"); + } + + + generators.Sort(); + + diameter = generators[0]; + + string[] buffer_parameters; + if (buffer.Length > 1) + { + buffer_parameters = buffer[1].Trim().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); + buffer_parameters[0].Trim(); + string[] sub_buffer_parameters = buffer_parameters[0].Trim().Split(new string[] { "=" }, StringSplitOptions.RemoveEmptyEntries); + //this.p = Convert.ToInt32(sub_buffer_parameters[1]); + this.node_count = Convert.ToInt32(buffer_parameters[1]) * Convert.ToInt32(buffer_parameters[2]); + } + + //string[] buffer = paraneters.Split(new string[] { "РЎ(", "C(", ";", ":", ", ", ")", " " }, StringSplitOptions.RemoveEmptyEntries); + //this.node_count = Convert.ToInt32(buffer[0]); + //this.p = Convert.ToInt32(param_2); + + + + this.is_created = true; + } + + protected override void SetNodeCountFromGenerators(List<int> generators) + { + this.node_count = generators[0] * generators[1]; + } + + public List<List<int>> Get_ways_routing_XY() + { + return this.ways_routing_XY; + } + + public double getXY_Efficiency(CancellationToken token) + { + calculateEfficiencyXY(token); + return this.efficiencyXY; + } + + private void calculateEfficiencyXY (CancellationToken token) + { + double deikstra_count = 0; + double XY_count = 0; + + for (int i = 0; i < this.min_ways_routing_deikstra.Count; i++) + { + if (token.IsCancellationRequested) + { + token.ThrowIfCancellationRequested(); + } + deikstra_count += this.min_ways_routing_deikstra[i].Count - 1; + XY_count += this.ways_routing_XY[i].Count - 1; + } + + this.efficiencyXY = Math.Round(deikstra_count / XY_count, 3); + } + + public List<List<int>> Generate_XY_routing(CancellationToken token) + { + int iterations_count; // для того чтобы программа РЅРµ зависала, если РЅРµ может посчитать маршрут + + int start_node; + int end_node; + List<int> route; + + this.ways_routing_XY = new List<List<int>>(); + + try + { + if (!this.is_created) + { + throw new Exception("Описание топологии РЅРµ было задано или задано РЅРµ полностью"); + } + + for (int i = 0; i < this.node_count; i++) + { + for (int j = 0; j < this.node_count; j++) + { + if (token.IsCancellationRequested) + { + token.ThrowIfCancellationRequested(); + } + iterations_count = 0; + start_node = i; + end_node = j; + route = new List<int>(); + route.Add(start_node + Settings.Get_node_naming_start_index()); + while (start_node != end_node) + { + iterations_count++; + + start_node = XY_routing(start_node, end_node, generators, node_count); + route.Add(start_node + Settings.Get_node_naming_start_index()); + + if (iterations_count > Settings.Get_error_iterations_count()) + { + throw new Exception("Превышено количество итераций моделирования маршрута для алгоритма Simple"); + } + } + this.ways_routing_XY.Add(route); + } + } + } + catch (Exception ex) + { + this.error_message = ex.Message; + return null; + } + + return this.ways_routing_XY; + } // проверка РЅР° ошибки добавлена + + private int XY_routing(int start_node, int end_node, List<int> generators, int node_count) + { + int S = end_node - start_node; + if (S == 0) + { + return (start_node); + } + else if ((start_node % generators[1]) < (end_node % generators[1])) + { + start_node++; + } + else if ((start_node % generators[1]) > (end_node % generators[1])) + { + start_node--; + } + else if ((((start_node % generators[0]) < (end_node % generators[0])) && (start_node % node_count) < (end_node % node_count)) || ((start_node % node_count) < (end_node % node_count))) + { + start_node += generators[1]; + } + else if ((start_node % generators[0]) > (end_node % generators[0]) || ((start_node % node_count) > (end_node % node_count))) + { + start_node -= generators[1]; + } + //if (start_node == 0) + //start_node = this.node_count; + return (start_node); + } + + public double Calculate_average_distance_XY(CancellationToken token) + { + average_distance_XY = 0; + + for (int i = 0; i < this.ways_routing_XY.Count; i++) + { + if (token.IsCancellationRequested) + { + token.ThrowIfCancellationRequested(); + } + average_distance_XY += ways_routing_XY[i].Count; + } + average_distance_XY /= ways_routing_XY.Count; + + return average_distance_XY; + } + + protected override void Create_matr_smej() + { + this.matr_smej = new int[this.node_count, this.node_count]; + int n = generators[0]; + int m = generators[1]; + + for (int i = 0; i < this.node_count; i++) + { + if (i % m != 0) + { + matr_smej[i, i - 1] = 1; + matr_smej[i - 1, i] = 1; + } + if (i / m != 0) + { + matr_smej[i, i - m] = 1; + matr_smej[i - m, i] = 1; + } + } + } + + protected override int GetCordinatesSize() + { + int coordinates_size = 0; + int counter = 1; + while (counter < generators.Max()) + { + coordinates_size++; + counter *= 2; + } + return coordinates_size; + } + + protected override string descipher_router(RouterOptions.Algorithm obj) + { + string response = "..\\..\\..\\verilog-primitives\\src\\alg\\mesh\\"; + + switch (obj) + { + case RouterOptions.Algorithm.XY: + response += "XY.sv"; + break; + default: + throw new NotImplementedException($"Algorithm {obj} was not implemented into this switch statement."); + } + + return response; + } + + public override void createRouter(string project_path, router_options parametrs) + { + base.createRouter(project_path, parametrs); + + string router_format = descipher_router(parametrs.queue_position); + string router_text = ""; + string router_json = File.ReadAllText("..\\..\\..\\router_variants.json"); + var router_variants = JsonSerializer.Deserialize<Dictionary<string, Dictionary<string, Dictionary<string, List<string>>>>>(router_json); + + switch (parametrs.algorithm, parametrs.queue_position) + { + case (RouterOptions.Algorithm.XY, RouterOptions.Queue_position.Front): + router_text = String.Format(router_format, String.Join("\n ", router_variants["mesh"]["xy"]["front"].Select(s => $"{s}")).Split("c#_splitter")); + break; + case (RouterOptions.Algorithm.XY, RouterOptions.Queue_position.Rear): + router_text = String.Format(router_format, String.Join("\n ", router_variants["mesh"]["xy"]["rear"].Select(s => $"{s}")).Split("c#_splitter")); + break; + default: + throw new NotImplementedException($"Router format {parametrs.algorithm}, {parametrs.queue_position} was not implemented into this switch statement."); + } + + File.WriteAllText(project_path + "\\src\\router.sv", router_text); + + + string file_to_format = "noc"; + string file_text = ""; + file_text = File.ReadAllText("..\\..\\..\\verilog-primitives\\inc\\" + file_to_format+".svh"); + File.WriteAllText(project_path + "\\inc\\" + file_to_format + ".svh", String.Format(file_text, + parametrs.packet_width, + GetCordinatesSize(), + node_count + )); + + file_to_format = "noc_XY"; + file_text = File.ReadAllText("..\\..\\..\\verilog-primitives\\inc\\" + file_to_format + ".svh"); + File.WriteAllText(project_path + "\\inc\\" + file_to_format + ".svh", String.Format(file_text, + generators[0], generators[1] + )); + + file_to_format = "queue"; + file_text = File.ReadAllText("..\\..\\..\\verilog-primitives\\inc\\" + file_to_format + ".svh"); + File.WriteAllText(project_path + "\\inc\\" + file_to_format + ".svh", String.Format(file_text, + parametrs.queue_length, get_bits(parametrs.queue_length) + )); + + file_to_format = "router"; + file_text = File.ReadAllText("..\\..\\..\\verilog-primitives\\inc\\" + file_to_format + ".svh"); + File.WriteAllText(project_path + "\\inc\\" + file_to_format + ".svh", String.Format(file_text, + 5, + this.get_bits(5) + )); + + + } + + public override void createNoC(string project_path, router_options parameters) + { + base.createNoC(project_path, parameters); + + File.Copy("..\\..\\..\\verilog-primitives\\noc\\mesh.sv", project_path + "\\noc\\noc.sv"); + File.Copy("..\\..\\..\\verilog-primitives\\sel\\rectangle.sv", project_path + "\\noc\\toplevel.sv"); + File.Copy("..\\..\\..\\verilog-primitives\\tb\\routing\\rectangle.sv", project_path + "\\tb\\tb_routing.sv"); + + switch (parameters.queue_position) + { + case RouterOptions.Queue_position.Front: + File.Copy("..\\..\\..\\verilog-primitives\\tb\\queueing\\front\\rectangle.sv", project_path + "\\tb\\tb_queueing.sv"); + break; + case RouterOptions.Queue_position.Rear: + File.Copy("..\\..\\..\\verilog-primitives\\tb\\queueing\\rear\\rectangle.sv", project_path + "\\tb\\tb_queueing.sv"); + break; + } + } + } +} + diff --git a/Shared/GraphTorus.cs b/Shared/GraphTorus.cs new file mode 100644 index 0000000000000000000000000000000000000000..2dde309d6edd71f9649c187badc325e116f2a679 --- /dev/null +++ b/Shared/GraphTorus.cs @@ -0,0 +1,383 @@ +п»їusing System.Text; +using System.Text.Json; + +namespace HDLNoCGen +{ + class GraphTorus : Graph, IRectangleLike + { + public override string getSignature() + { + return "Torus"; + } + + protected List<List<int>> ways_routing_XY { get; set; } + + protected double XY_Efficiency { get; set; } + protected double average_distance_XY { get; set; } + + private void calculateEfficiencyXY(CancellationToken token) + { + double deikstra_count = 0; + double XY_count = 0; + + for (int i = 0; i < this.min_ways_routing_deikstra.Count; i++) + { + if (token.IsCancellationRequested) + { + token.ThrowIfCancellationRequested(); + } + deikstra_count += this.min_ways_routing_deikstra[i].Count - 1; + XY_count += this.ways_routing_XY[i].Count - 1; + } + + this.XY_Efficiency = Math.Round(deikstra_count / XY_count, 3); + } + + protected override void SetNodeCountFromGenerators(List<int> generators) + { + this.node_count = generators[0] * generators[1]; + } + + public List<List<int>> Get_ways_routing_XY() + { + return this.ways_routing_XY; + } + + public double getXY_Efficiency(CancellationToken token) + { + calculateEfficiencyXY(token); + return this.XY_Efficiency; + } + + public GraphTorus() : base() + { + this.graphId = GraphType.Torus; + this.diameter = 0; + this.matr_smej = null; + } + + public GraphTorus(GraphDeserializer graph_des) : base(graph_des) + { + + } + + public GraphTorus(string parameters, CancellationToken token) + { + this.graphId = GraphType.Torus; + + string[] buffer = parameters.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries); + string[] buffer_topology = buffer[0].Trim().Split(new string[] { "T", "t", ";", ":", ", ", ")", " " }, StringSplitOptions.RemoveEmptyEntries); + generators = new List<int>(); + for (int i = 0; i < buffer_topology.Length && i < 2; i++) + { + generators.Add(Convert.ToInt32(buffer_topology[i])); + } + generators.Sort(); + + if (generators.Count < 2 || generators.Min() < 2) + { + throw(new Exception("Ошибка создания топологии")); + } + + this.node_count = generators[0] * generators[1]; + + //string[] buffer = parameters.Split(new string[] { "РЎ(", "C(", ";", ":", ", ", ")", " " }, StringSplitOptions.RemoveEmptyEntries); + //this.node_count = Convert.ToInt32(buffer[0]); + //this.p = Convert.ToInt32(param_2); + + this.is_created = true; + } + + protected override void Create_matr_smej() + { + if (generators.Count < 2) + return; + this.matr_smej = new int[this.node_count, this.node_count]; + int n = generators[0]; + int m = generators[1]; + + for (int i = 0; i < this.node_count; i++) + { + if (i % m != m - 1) + { + this.matr_smej[i, i + 1] = 1; + this.matr_smej[i + 1, i] = 1; + } + if (i % m == 0) + { + this.matr_smej[i, i + m - 1] = 1; + this.matr_smej[i + m - 1, i] = 1; + } + if (i < (this.node_count - m)) + { + this.matr_smej[i, i + m] = 1; + this.matr_smej[i + m, i] = 1; + } + if (i < m) + { + this.matr_smej[i, i + m * (n - 1)] = 1; + this.matr_smej[i + m * (n - 1), i] = 1; + } + } + } + + + public List<List<int>> Generate_XY_routing(CancellationToken token) + { + int iterations_count; + + int start_node; + int end_node; + List<int> route; + + this.ways_routing_XY = new List<List<int>>(); + + try + { + if (!this.is_created) + { + throw new Exception("Описание топологии РЅРµ было задано или задано РЅРµ полностью"); + } + + for (int i = 0; i < this.node_count; i++) + { + for (int j = 0; j < this.node_count; j++) + { + if (token.IsCancellationRequested) + { + token.ThrowIfCancellationRequested(); + } + iterations_count = 0; + start_node = i; + end_node = j; + route = new List<int>(); + route.Add(start_node + Settings.Get_node_naming_start_index()); + while (start_node != end_node) + { + iterations_count++; + + start_node = XY_routing(start_node, end_node, generators, node_count); + route.Add(start_node + Settings.Get_node_naming_start_index()); + if (iterations_count > Settings.Get_error_iterations_count()) + { + throw new Exception("Превышено количество итераций моделирования маршрута для алгоритма Simple"); + } + } + this.ways_routing_XY.Add(route); + } + } + } + catch (Exception ex) + { + this.error_message = ex.Message; + return null; + } + + return this.ways_routing_XY; + } + + private int XY_routing(int start_node, int end_node, List<int> generators, int node_count) + { + int start_x = start_node % generators[1]; + int end_x = end_node % generators[1]; + int start_y = start_node / generators[1]; + int end_y = end_node / generators[1]; + int step = 0; + + if (start_x < end_x) + { + if (end_x - start_x < generators[1] - end_x + start_x) + { + step = 1; + } + else + { + if (start_x == 0) + { + step = generators[1] - 1; + } + else + { + step = -1; + } + } + } + else if (start_x > end_x) + { + if (start_x - end_x < generators[1] - start_x + end_x) + { + step = -1; + } + else + { + if (start_x == generators[1] - 1) + { + step = -generators[1] + 1; + } + else + { + step = 1; + } + } + } + else + { + if (start_y < end_y) + { + if (end_y - start_y < generators[0] - end_y + start_y) + { + step = generators[1]; + } + else + { + if (start_y == 0) + { + step = generators[1] * (generators[0] - 1); + } + else + { + step = -generators[1]; + } + } + } + else if (start_y > end_y) + { + if (start_y - end_y < generators[0] - start_y + end_y) + { + step = -generators[1]; + } + else + { + if (start_y == generators[0] - 1) + { + step = -generators[1] * (generators[0] - 1); + } + else + { + step = generators[1]; + } + } + } + } + + return start_node + step; + } + + public double Calculate_average_distance_XY(CancellationToken token) + { + average_distance_XY = 0; + + for (int i = 0; i < this.ways_routing_XY.Count; i++) + { + if (token.IsCancellationRequested) + { + token.ThrowIfCancellationRequested(); + } + average_distance_XY += ways_routing_XY[i].Count; + } + average_distance_XY /= ways_routing_XY.Count; + + return average_distance_XY; + } + + protected override int GetCordinatesSize() + { + int coordinates_size = 0; + int counter = 1; + while (counter < generators.Max()) + { + coordinates_size++; + counter *= 2; + } + return coordinates_size; + } + + protected override string descipher_router(RouterOptions.Algorithm obj) + { + string response = "..\\..\\..\\verilog-primitives\\src\\alg\\torus\\"; + + switch (obj) + { + case RouterOptions.Algorithm.XY: + response += "XY.sv"; + break; + default: + throw new NotImplementedException($"Algorithm {obj} was not implemented into this switch statement."); + } + + return response; + } + + public override void createRouter(string project_path, router_options parametrs) + { + base.createRouter(project_path, parametrs); + + string router_format = descipher_router(parametrs.queue_position); + string router_text = ""; + string router_json = File.ReadAllText("..\\..\\..\\router_variants.json"); + var router_variants = JsonSerializer.Deserialize<Dictionary<string, Dictionary<string, Dictionary<string, List<string>>>>>(router_json); + + switch (parametrs.algorithm, parametrs.queue_position) + { + case (RouterOptions.Algorithm.XY, RouterOptions.Queue_position.Front): + router_text = String.Format(router_format, String.Join("\n ", router_variants["torus"]["xy"]["front"].Select(s => $"{s}")).Split("c#_splitter")); + break; + case (RouterOptions.Algorithm.XY, RouterOptions.Queue_position.Rear): + router_text = String.Format(router_format, String.Join("\n ", router_variants["torus"]["xy"]["rear"].Select(s => $"{s}")).Split("c#_splitter")); + break; + default: + throw new NotImplementedException($"Router format {parametrs.algorithm}, {parametrs.queue_position} was not implemented into this switch statement."); + } + + File.WriteAllText(project_path + "\\src\\router.sv", router_text); + + + string file_to_format = "noc"; + string file_text = ""; + file_text = File.ReadAllText("..\\..\\..\\verilog-primitives\\inc\\" + file_to_format + ".svh"); + File.WriteAllText(project_path + "\\inc\\" + file_to_format + ".svh", String.Format(file_text, + parametrs.packet_width, + GetCordinatesSize(), + node_count + )); + + file_to_format = "noc_XY"; + file_text = File.ReadAllText("..\\..\\..\\verilog-primitives\\inc\\" + file_to_format + ".svh"); + File.WriteAllText(project_path + "\\inc\\" + file_to_format + ".svh", String.Format(file_text, + generators[0], generators[1] + )); + + file_to_format = "queue"; + file_text = File.ReadAllText("..\\..\\..\\verilog-primitives\\inc\\" + file_to_format + ".svh"); + File.WriteAllText(project_path + "\\inc\\" + file_to_format + ".svh", String.Format(file_text, + parametrs.queue_length, get_bits(parametrs.queue_length) + )); + + file_to_format = "router"; + file_text = File.ReadAllText("..\\..\\..\\verilog-primitives\\inc\\" + file_to_format + ".svh"); + File.WriteAllText(project_path + "\\inc\\" + file_to_format + ".svh", String.Format(file_text, + 5, + this.get_bits(5) + )); + + } + public override void createNoC(string project_path, router_options parameters) + { + base.createNoC(project_path, parameters); + + File.Copy("..\\..\\..\\verilog-primitives\\noc\\torus.sv", project_path + "\\noc\\noc.sv"); + File.Copy("..\\..\\..\\verilog-primitives\\sel\\rectangle.sv", project_path + "\\noc\\toplevel.sv"); + File.Copy("..\\..\\..\\verilog-primitives\\tb\\routing\\rectangle.sv", project_path + "\\tb\\tb_routing.sv"); + + switch (parameters.queue_position) + { + case RouterOptions.Queue_position.Front: + File.Copy("..\\..\\..\\verilog-primitives\\tb\\queueing\\front\\rectangle.sv", project_path + "\\tb\\tb_queueing.sv"); + break; + case RouterOptions.Queue_position.Rear: + File.Copy("..\\..\\..\\verilog-primitives\\tb\\queueing\\rear\\rectangle.sv", project_path + "\\tb\\tb_queueing.sv"); + break; + } + } + } +} diff --git a/Shared/IRectangleLike.cs b/Shared/IRectangleLike.cs new file mode 100644 index 0000000000000000000000000000000000000000..01ff058d450a1f2f51f1b851f247d1543570b135 --- /dev/null +++ b/Shared/IRectangleLike.cs @@ -0,0 +1,9 @@ +п»їnamespace HDLNoCGen +{ + internal interface IRectangleLike + { + List<List<int>> Generate_XY_routing(CancellationToken token); + + List<List<int>> Get_ways_routing_XY(); + } +} diff --git a/Shared/IRoundLike.cs b/Shared/IRoundLike.cs new file mode 100644 index 0000000000000000000000000000000000000000..fa4a8071ad0f9e7afa104c61c283f5957e4e1765 --- /dev/null +++ b/Shared/IRoundLike.cs @@ -0,0 +1,30 @@ +п»їnamespace HDLNoCGen +{ + internal interface IRoundLike + { + List<List<int>> Generate_ROU_routing(); + + List<List<int>> Generate_APO_routing(); + + List<List<int>> Generate_APM_routing(); + + List<List<int>> Generate_AAO_routing(); + + List<List<int>> Generate_Simple_routing(); + + List<List<int>> Generate_GA_routing(CancellationToken token); + + double Calculate_efficiency_simple(); + + double Calculate_efficiency_ROU(); + + double Calculate_efficiency_APM(); + + double Calculate_efficiency_APO(); + + double Calculate_efficiency_GA(CancellationToken token); + + double Calculate_average_distance_GA(CancellationToken token); + + } +} diff --git a/Shared/ProjectGenerator.cs b/Shared/ProjectGenerator.cs new file mode 100644 index 0000000000000000000000000000000000000000..4b5660ca24a0d1e823a301ff2be03b5bb7913bfb --- /dev/null +++ b/Shared/ProjectGenerator.cs @@ -0,0 +1,511 @@ +п»їusing Npgsql; +using NpgsqlTypes; +using System.Diagnostics; +using System.Globalization; +using System.Management; +using System.Reflection.Metadata; +using System.Text; + +namespace HDLNoCGen +{ + + public struct ParsedReport + { + public string graphType { get; set; } + public string algorithm { get; set; } + public int nodeCount { get; set; } + public string generators { get; set; } + public int infoLength { get; set; } + public double efficiency { get; set; } + public double averageDistance { get; set; } + public int numberOfALMs { get; set; } + public int numberOfRegisters { get; set; } + + } + + static class ProjectGenerator + { + #region legacy code + + public static void initializeTCL(string project_name, string routing_algorithm, string graph_signature, List<int> generators) + { + string top_entity_name = $"top_level_{project_name}"; + string router_name = $"router_{project_name}"; + string data_selector_name = $"data_selector_{project_name}"; + + FileStream fs; + StreamWriter sw; + + Directory.CreateDirectory($"{Settings.Get_project_path()}{project_name}"); + fs = new FileStream($"{Settings.Get_project_path()}{project_name}\\Setup.tcl", FileMode.Create, FileAccess.ReadWrite); + sw = new StreamWriter(fs); + + sw.WriteLine($"project_new {project_name} -overwrite"); + sw.WriteLine(); + sw.WriteLine("set_global_assignment -name FAMILY \"Cyclone V\""); + sw.WriteLine("set_global_assignment -name DEVICE 5CGXFC9E7F35C8"); + sw.WriteLine($"set_global_assignment -name VERILOG_FILE {data_selector_name}.v"); + sw.WriteLine($"set_global_assignment -name VERILOG_FILE {top_entity_name}.v"); + sw.WriteLine($"set_global_assignment -name VERILOG_FILE {router_name}.v"); + sw.WriteLine($"set_global_assignment -name TOP_LEVEL_ENTITY {top_entity_name}"); + sw.WriteLine(); + sw.WriteLine("load_package flow"); + sw.WriteLine("execute_flow -compile"); + sw.WriteLine(); + sw.WriteLine("project_close"); + + sw.Close(); + fs.Close(); + } + + public static void createBat(string project_name) + { + FileStream fs; + StreamWriter sw; + + Directory.CreateDirectory($"{Settings.Get_project_path()}{project_name}"); + fs = new FileStream($"{Settings.Get_project_path()}{project_name}\\Compile.bat", FileMode.Create, FileAccess.ReadWrite); + sw = new StreamWriter(fs); + + sw.WriteLine("C:"); + sw.WriteLine("cd \\"); + sw.WriteLine($"cd {Settings.Get_project_path()}{project_name}"); + sw.WriteLine($"{Settings.Get_path_to_quartus()}quartus_sh -t Setup.tcl"); + + sw.Close(); + fs.Close(); + + } + #endregion + + public static void killProcessAndChildren(int pid) + { + if (pid == 0) + { + return; + } + ManagementObjectSearcher searcher = new ManagementObjectSearcher("Select * From Win32_Process Where ParentProcessID=" + pid); + ManagementObjectCollection moc = searcher.Get(); + foreach (ManagementObject mo in moc) + { + killProcessAndChildren(Convert.ToInt32(mo["ProcessID"])); + } + try + { + Process proc = Process.GetProcessById(pid); + proc.Kill(); + } + catch (ArgumentException) + { + // Process already exited. + } + catch (System.ComponentModel.Win32Exception) + { + //Access rejected + } + + GC.Collect(); + + } + + /// <summary> + /// Функция для генерации tcl + /// </summary> + /// <param name="project_path">Путь Рє корневой папке проекта.</param> + /// <param name="project_name">Название проекта.</param> + /// <param name="toplevel_entity_name">Название top level entity.</param> + public static void createSetupSH(string project_path, string project_name, string toplevel_entity_name) + { + var fs = new FileStream($"{project_path}\\Setup_sh.tcl", FileMode.Create, FileAccess.ReadWrite); + var sw = new StreamWriter(fs); + + string top_entity_folder = toplevel_entity_name switch + { + "noc" => "noc", + "toplevel" => "noc", + "router" => "src", + _ => throw new Exception($"Toplevel '{toplevel_entity_name}' does not exist. It should be either 'noc' or 'router'.") + }; + + sw.WriteLine($"project_new {project_name} -overwrite"); + sw.WriteLine(); + sw.WriteLine("set_global_assignment -name FAMILY \"Cyclone V\""); + sw.WriteLine("set_global_assignment -name DEVICE 5CGXFC9E7F35C8"); + sw.WriteLine($"set_global_assignment -name TOP_LEVEL_ENTITY {toplevel_entity_name}"); + sw.WriteLine($"set_global_assignment -name SYSTEMVERILOG_FILE {top_entity_folder}/{toplevel_entity_name}.sv"); + sw.WriteLine(); + sw.WriteLine("load_package flow"); + sw.WriteLine("execute_flow -compile"); + sw.WriteLine(); + sw.WriteLine("project_close"); + + sw.Close(); + fs.Close(); + } + + /// <summary> + /// Функция для генерации tcl + /// </summary> + /// <param name="project_path">Путь Рє корневой папке проекта.</param> + /// <param name="project_name">Название проекта.</param> + public static void createSetupSTA(string project_path, string project_name) + { + var fs = new FileStream($"{project_path}\\Setup_sta.tcl", FileMode.Create, FileAccess.ReadWrite); + var sw = new StreamWriter(fs); + + sw.WriteLine($"project_open {project_name}"); + sw.WriteLine(); + sw.WriteLine("create_timing_netlist -model slow "); + sw.WriteLine("read_sdc"); + sw.WriteLine("update_timing_netlist"); + sw.WriteLine(); + sw.WriteLine("set outfile1 [open \"clocker.logger\" w+] "); + sw.WriteLine(" puts $outfile1 [get_clock_fmax_info]"); + sw.WriteLine("close $outfile1"); + sw.WriteLine(); + sw.WriteLine("delete_timing_netlist"); + sw.WriteLine(); + sw.WriteLine("project_close"); + + sw.Close(); + fs.Close(); + } + + public static void createSimulateScript(string project_path, string project_name, string mode) + { + var fs = new FileStream($"{project_path}\\Modelsim_simulate.tcl", FileMode.Create, FileAccess.ReadWrite); + var sw = new StreamWriter(fs); + + sw.WriteLine($"vlib work"); + sw.WriteLine($"vlog -sv tb/tb_{mode}.sv"); + sw.WriteLine($"vsim work.tb_{mode}"); + sw.WriteLine($"run -all"); + + sw.Close(); + fs.Close(); + } + + public static Tuple<string, Process, Process> routerPreparation(Graph graph, string project_name, string project_path, router_options parametres) + { + string path = $"{project_path}\\{project_name}"; + + graph.createRouter(path, parametres); + FileStream fs; + StreamWriter sw; + + fs = new FileStream($"{path}\\Compile.bat", FileMode.Create, FileAccess.ReadWrite); + sw = new StreamWriter(fs); + + sw.WriteLine($"{path.Substring(0, 2)}"); + sw.WriteLine($"cd {path}\n"); + sw.WriteLine($"{Settings.Get_path_to_quartus()}quartus_sh -t Setup_sh.tcl"); + sw.WriteLine($"{Settings.Get_path_to_quartus()}quartus_sta -t Setup_sta.tcl"); + + sw.Close(); + fs.Close(); + + + fs = new FileStream($"{path}\\Simulate.bat", FileMode.Create, FileAccess.ReadWrite); + sw = new StreamWriter(fs); + + sw.WriteLine($"{path.Substring(0, 2)}"); + sw.WriteLine($"cd {path}\n"); + sw.WriteLine($"vsim -c -do Modelsim_simulate.tcl"); + + sw.Close(); + fs.Close(); + + Process simulation_process = new Process(); + Process compilation_process = new Process(); + + Console.CancelKeyPress += delegate { + killProcessAndChildren(compilation_process.Id); + killProcessAndChildren(simulation_process.Id); + }; + + string comp_path = path + "\\Compile.bat"; + string sim_path = path + "\\Simulate.bat"; + + compilation_process.StartInfo.FileName = comp_path; + compilation_process.StartInfo.UseShellExecute = false; + compilation_process.StartInfo.RedirectStandardOutput = true; + compilation_process.StartInfo.CreateNoWindow = true; + compilation_process.EnableRaisingEvents = true; + compilation_process.StartInfo.StandardOutputEncoding = Encoding.GetEncoding("utf-8"); + + simulation_process.StartInfo.FileName = sim_path; + simulation_process.StartInfo.UseShellExecute = false; + simulation_process.StartInfo.RedirectStandardOutput = true; + simulation_process.StartInfo.CreateNoWindow = true; + simulation_process.EnableRaisingEvents = true; + simulation_process.StartInfo.StandardOutputEncoding = Encoding.GetEncoding("utf-8"); + + return new Tuple<string, Process, Process>(path, compilation_process, simulation_process); + } + + public static void networkCompilation(CancellationToken GeneralPurposeCancellationToken, + Process compile, Process simulate, + Graph graph, router_options parameters, + string path, string project_name, + bool create_database_entry, bool cleanup) + { + + List<int> generators = graph.generators; + string graph_signature = ""; + switch (graph.graphId) + { + case GraphType.Circulant: + graph_signature = "c"; + break; + case GraphType.Mesh: + graph_signature = "m"; + break; + case GraphType.Torus: + graph_signature = "t"; + break; + }; + + + string simulation_report = ""; + string[] separators = { "Errors: ", ", Warnings: " }; + + DataReceivedEventHandler simulationTextReader = (s, ev) => + { + if (!String.IsNullOrEmpty(ev.Data)) + { + simulation_report += $"{ev.Data}\n"; + Console.WriteLine($"{ev.Data}\n"); + } + }; + + EventHandler simulationFinishingHandler = (s, ev) => + { + List<string> sliced_report = simulation_report.Split(separators, System.StringSplitOptions.None).ToList(); + + if (!sliced_report[1].Equals("0") || !sliced_report[3].Equals("0")) + { + FileStream fs = new FileStream($"{Settings.Get_project_path()}\\simulation_error_logs.log", FileMode.Append, FileAccess.Write); + StreamWriter sw = new StreamWriter(fs); + + sw.WriteLine($"{graph_signature} {String.Join(" ", generators)}, Errors: {sliced_report[0]}, Warnings: {sliced_report[1]}"); + + sw.Close(); + fs.Close(); + + killProcessAndChildren(simulate.Id); + + throw new Exception("Simulation error"); + } + + }; + + simulate.OutputDataReceived += simulationTextReader; + simulate.Exited += simulationFinishingHandler; + + createSimulateScript(path, project_name, "routing"); + + simulate.Start(); + simulate.BeginOutputReadLine(); + + simulate.WaitForExit(); + simulate.CancelOutputRead(); + + + createSimulateScript(path, project_name, "queueing"); + + simulate.Start(); + simulate.BeginOutputReadLine(); + + simulate.WaitForExit(); + simulate.CancelOutputRead(); + + + double algorithmEf = 0; + double algorithmAd = 0; + EventHandler compilationFinishingHandler; + + switch (graph.graphId) + { + case GraphType.Circulant: + + GraphCirculant graphCirculant = graph as GraphCirculant; + + graphCirculant.Generate_GA_routing(GeneralPurposeCancellationToken); + algorithmEf = graphCirculant.Calculate_efficiency_GA(GeneralPurposeCancellationToken); + algorithmAd = graphCirculant.Calculate_average_distance_GA(GeneralPurposeCancellationToken); + + break; + case GraphType.Mesh: + + GraphMesh graphMesh = graph as GraphMesh; + + graphMesh.Generate_XY_routing(GeneralPurposeCancellationToken); + algorithmEf = graphMesh.getXY_Efficiency(GeneralPurposeCancellationToken); + algorithmAd = graphMesh.Calculate_average_distance_XY(GeneralPurposeCancellationToken); + break; + case GraphType.Torus: + + GraphTorus graphTorus = graph as GraphTorus; + + graphTorus.Generate_XY_routing(GeneralPurposeCancellationToken); + algorithmEf = graphTorus.getXY_Efficiency(GeneralPurposeCancellationToken); + algorithmAd = graphTorus.Calculate_average_distance_XY(GeneralPurposeCancellationToken); + break; + default: + throw new NotImplementedException($"Graph type {graph.graphId} was not implemented into this switch statement."); + } + + //Подготовлен запуск + createSetupSH(path, project_name, "toplevel"); + createSetupSTA(path, project_name); + + if (create_database_entry) + { + string queue_type = parameters.queue_type switch + { + RouterOptions.Queue_types.Index => "index", + RouterOptions.Queue_types.Pointer => "pointer", + RouterOptions.Queue_types.Line => "line", + _ => "-" + }; + string queue_position = parameters.queue_position switch + { + RouterOptions.Queue_position.Front => "front", + RouterOptions.Queue_position.Rear => "rear", + _ => "-" + }; + string arb_type = parameters.arbiter_type switch + { + RouterOptions.Arbiter_types.Round_Robin => "round_robin", + _ => "-" + }; + string algorithm = parameters.algorithm switch + { + RouterOptions.Algorithm.XY => "xy", + RouterOptions.Algorithm.GA => "ga", + _ => "-" + }; + + string signature = graph.getSignature(); + ParsedReport parsedReport = new ParsedReport + { + graphType = signature, + algorithm = algorithm, + nodeCount = graph.node_count, + generators = String.Join(", ", generators.Select(s => $"{s}")), + infoLength = Convert.ToInt32(parameters.info_width), + efficiency = algorithmEf, + averageDistance = algorithmAd, + numberOfALMs = -1, + numberOfRegisters = -1 + }; + + List<string> fitmentSummary = new List<string>(0); + compilationFinishingHandler = (s, ev) => + { + FileStream fs = new FileStream($"{path}\\{project_name}.fit.summary", FileMode.Open, FileAccess.Read); + StreamReader sr = new StreamReader(fs); + + string line; + while ((line = sr.ReadLine()) != null) + { + fitmentSummary.Add($"{line}"); + } + + sr.Close(); + fs.Close(); + + + int alm_start_index = fitmentSummary[7].IndexOf(':') + 2; + int alm_length = fitmentSummary[7].IndexOf('/') - 1 - alm_start_index; + List<string> separated_number = new List<string>(fitmentSummary[7].Substring(alm_start_index, alm_length).Split(',')); + int thousand_separator = 1; + + for (int i = separated_number.Count - 1; i >= 0; i--) + { + parsedReport.numberOfALMs += Int32.Parse(separated_number[i]) * thousand_separator; + thousand_separator *= 1000; + } + + int reg_start_index = fitmentSummary[8].IndexOf(':') + 2; + parsedReport.numberOfRegisters = Int32.Parse(fitmentSummary[8].Substring(reg_start_index)); + + //mark + var connectionString = $"Server={Settings.server};Port={Settings.port};Database={Settings.database};User Id={Settings.username};Password={Settings.password}"; + + var connection = new NpgsqlConnection(connectionString); + connection.Open(); + + var createTableCommand = new NpgsqlCommand("CREATE TABLE IF NOT EXISTS TestingReportsNetwork (" + + "graph_type VARCHAR(20)," + + "buffers VARCHAR(20)," + + "buffers_position VARCHAR(20)," + + "buffers_number INTEGER," + + "arbiter VARCHAR(20)," + + "algorithm VARCHAR(20)," + + "generators VARCHAR(20)," + + "info_length INTEGER," + + "ALMs INTEGER," + + "Registers INTEGER," + + "Frequency REAL," + + "PRIMARY KEY(graph_type, buffers, buffers_position, buffers_number, arbiter, algorithm, generators, info_length)" + + ")", connection); + createTableCommand.ExecuteNonQuery(); + + var insertCommand = new NpgsqlCommand("INSERT INTO TestingReportsNetwork (graph_type, buffers, buffers_position, buffers_number, arbiter, algorithm, generators, info_length, ALMs, Registers, Frequency)" + + "VALUES (@graph_type, @buffers, @buffers_position, @buffers_number, @arbiter, @algorithm, @generators, @info_length, @ALMs, @Registers, @Frequency)", connection); + insertCommand.Parameters.Add(new NpgsqlParameter("graph_type", NpgsqlDbType.Varchar)); + insertCommand.Parameters.Add(new NpgsqlParameter("buffers", NpgsqlDbType.Varchar)); + insertCommand.Parameters.Add(new NpgsqlParameter("buffers_position", NpgsqlDbType.Varchar)); + insertCommand.Parameters.Add(new NpgsqlParameter("buffers_number", NpgsqlDbType.Integer)); + insertCommand.Parameters.Add(new NpgsqlParameter("arbiter", NpgsqlDbType.Varchar)); + insertCommand.Parameters.Add(new NpgsqlParameter("algorithm", NpgsqlDbType.Varchar)); + insertCommand.Parameters.Add(new NpgsqlParameter("generators", NpgsqlDbType.Varchar)); + insertCommand.Parameters.Add(new NpgsqlParameter("info_length", NpgsqlDbType.Integer)); + insertCommand.Parameters.Add(new NpgsqlParameter("ALMs", NpgsqlDbType.Integer)); + insertCommand.Parameters.Add(new NpgsqlParameter("Registers", NpgsqlDbType.Integer)); + insertCommand.Parameters.Add(new NpgsqlParameter("Frequency", NpgsqlDbType.Real)); + + + insertCommand.Parameters["graph_type"].Value = parsedReport.graphType; + insertCommand.Parameters["algorithm"].Value = parsedReport.algorithm; + insertCommand.Parameters["generators"].Value = parsedReport.generators; + insertCommand.Parameters["info_length"].Value = parameters.info_width; + insertCommand.Parameters["ALMs"].Value = parsedReport.numberOfALMs; + insertCommand.Parameters["Registers"].Value = parsedReport.numberOfRegisters; + + insertCommand.Parameters["buffers"].Value = queue_type; + insertCommand.Parameters["buffers_position"].Value = queue_position; + insertCommand.Parameters["buffers_number"].Value = Convert.ToInt32(parameters.queue_length); + insertCommand.Parameters["arbiter"].Value = arb_type; + + fs = new FileStream($"{path}\\clocker.logger", FileMode.Open, FileAccess.Read); + sr = new StreamReader(fs); + + insertCommand.Parameters["Frequency"].Value = float.Parse(sr.ReadLine().Split(' ')[1], new CultureInfo("en-US")); + + sr.Close(); + fs.Close(); + + insertCommand.ExecuteNonQuery(); + + connection.Close(); + + Console.WriteLine("Запись РІ базу данных прошла успешно\n"); + //mark + + }; + } + else compilationFinishingHandler = (s, ev) => { }; + + compile.Exited += compilationFinishingHandler; + + compile.Start(); + compile.BeginOutputReadLine(); + + compile.WaitForExit(); + Console.WriteLine("Process exited with code " + compile.ExitCode); + } + } +} + diff --git a/Shared/ProjectSettings.cs b/Shared/ProjectSettings.cs new file mode 100644 index 0000000000000000000000000000000000000000..f2501ff2590995543f9bd8c6200237723cfaed7b --- /dev/null +++ b/Shared/ProjectSettings.cs @@ -0,0 +1,74 @@ +п»їusing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HDLNoCGen +{ + public class ProjectMetadata + { + public string name { get; set; } + + public ProjectMetadata () + { + name = ""; + } + } + public class GraphVerilogMetadata + { + public bool graphSerialized { get; set; } + public bool verilogGenerated { get; set; } + + public GraphVerilogMetadata () + { + graphSerialized = false; + verilogGenerated = false; + } + } + public class QuartusMetadata + { + public bool quartusCompiled { get; set; } + public string deviceName { get; set; } + + public QuartusMetadata () + { + quartusCompiled = false; + deviceName = "5CGXFC9E7F35C8"; + } + } + public class DatabaseMetadata + { + public string dbIp { get; set; } + public string dbUsername { get; set; } + public string dbPassword { get; set; } + public string dbName { get; set; } + public int dbPort { get; set; } + public bool writtenToDB { get; set; } + + public DatabaseMetadata () + { + dbIp = ""; + dbUsername = ""; + dbPassword = ""; + dbName = ""; + dbPort = -1; + writtenToDB = false; + } + } + public class ProjectSettings + { + public ProjectMetadata projectMetadata { get; set; } + public GraphVerilogMetadata graphVerilogMetadata { get; set; } + public QuartusMetadata quartusMetadata { get; set; } + public DatabaseMetadata databaseMetadata { get; set; } + + public ProjectSettings () + { + projectMetadata = new ProjectMetadata (); + graphVerilogMetadata = new GraphVerilogMetadata (); + quartusMetadata = new QuartusMetadata (); + databaseMetadata = new DatabaseMetadata (); + } + } +} diff --git a/Shared/Settings.cs b/Shared/Settings.cs new file mode 100644 index 0000000000000000000000000000000000000000..89073147fd92d7b263983673359f21f972253c74 --- /dev/null +++ b/Shared/Settings.cs @@ -0,0 +1,446 @@ +п»їusing System; +using System.Text.Json; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.Serialization.Formatters.Binary; +using System.Text; +using System.Threading.Tasks; +using System.Reflection; +using System.Xml; +using System.Security.Cryptography.Xml; +using System.Security.Cryptography; +using static System.Formats.Asn1.AsnWriter; +using static System.Runtime.InteropServices.JavaScript.JSType; +using System.Runtime.CompilerServices; + +namespace HDLNoCGen +{ + public static class Settings + { + public static string settings_file_name = "settings.json"; + public static string algorithms_file_name = "algorithms.json"; + + public static int back_color_graph { get; set; } // фон, РЅР° котором отрисовывается граф + public static bool black_graph_color { get; set; } // черно-белая отрисовка графа + public static bool alternative_draw_graph { get; set; } // отрисовка образующих эллипсом + public static int pen_node_color { get; set; } // цвет, которым рисуются узлы Рё основная образующая + public static int pen_node_width { get; set; } // ширина линий, которыми рисуются узлы Рё образующие + public static int vertex_size { get; set; } // размер отрисовки вершин (диаметр окружности) + public static string node_naming_font_name { get; set; } // название шрифта, которым подписываются узлы + public static int node_naming_font_size { get; set; } // размер шрифта, которым подписываются узлы + public static int node_naming_brush_color { get; set; } // цвет шрифта, которым подписываются узлы + public static bool node_naming { get; set; } // нумерация узлов графа + public static int node_naming_start_index { get; set; } // начало нумерации СЃ 0 или СЃ 1 - соответствует записанному числу + public static int node_naming_interval { get; set; } // интервал нумерации узлов + public static int node_naming_string_offset { get; set; } // смещение РїРѕРґРїРёСЃРё узлв РѕС‚ центра узла + public static int route_color { get; set; } // цвет отрисовки маршрута + public static int route_width { get; set; } // щирина линии, которой отрисовывается маршрут + + public static int error_iterations_count { get; set; } // количество шагов маршрута, после которого считать, что алгоритм РЅРµ может построить + // РІ форме настрое этого параметра РїРѕРєР° нет + public static string quartus_folder_path { get; set; } + public static string project_folder_path { get; set; } + + public static bool[] circulant_algorithms_checked { get; set; } + public static bool[] mesh_algorithms_checked { get; set; } + public static bool[] torus_algorithms_checked { get; set; } + + public static string server { get; set; } + public static string port { get; set; } + public static string username { get; set; } + public static string database { get; set; } + public static string password { get; set; } + public static byte[] encpassword { get; set; } + + // добавить нужные поля Рё функции для РёС… установки Рё получения + + public static void Load() + { + try + { + string json = File.ReadAllText(settings_file_name); + SettingsSerializer serializer = JsonSerializer.Deserialize<SettingsSerializer>(json); + + var source_fields = serializer.GetType().GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); + var destination_fields = typeof(Settings).GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); + + foreach (var source_field in source_fields) + { + var destination_field = destination_fields.Single(p => p.Name == source_field.Name); + destination_field.SetValue(serializer, source_field.GetValue(serializer)); + } + + if (encpassword != null) + password = Encoding.Unicode.GetString(ProtectedData.Unprotect(encpassword, null, DataProtectionScope.LocalMachine)); + } + catch + { + back_color_graph = -1; + black_graph_color = false; + alternative_draw_graph = false; + pen_node_color = -16777216; + pen_node_width = 5; + vertex_size = 30; + node_naming_font_name = "Arial"; + node_naming_font_size = 7; + node_naming_brush_color = -16777216; + node_naming = true; + node_naming_start_index = 0; + node_naming_interval = 1; + node_naming_string_offset = 50; + route_color = -10496; + route_width = 5; + error_iterations_count = 300; + quartus_folder_path = ""; + project_folder_path = ""; + + circulant_algorithms_checked = new bool[] { false }; + mesh_algorithms_checked = new bool[] { false, false }; + torus_algorithms_checked = new bool[] { false }; + + server = ""; + port = ""; + username = ""; + database = ""; + } + } + + public static void Save() + { + SettingsSerializer serializer = new SettingsSerializer(); + + var destination_fields = serializer.GetType().GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); + var source_fields = typeof(Settings).GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); + + if(password != null) + encpassword = ProtectedData.Protect(Encoding.Unicode.GetBytes(password), null, DataProtectionScope.LocalMachine); + + foreach (var destination_field in destination_fields) + { + var source_field = source_fields.Single(p => p.Name == destination_field.Name); + destination_field.SetValue(serializer, source_field.GetValue(null)); + } + + var options = new JsonSerializerOptions() + { + WriteIndented = true + }; + + string json = JsonSerializer.Serialize(serializer, options); + File.WriteAllText(settings_file_name, json); + } + + public static int Get_back_color_graph() + { + return back_color_graph; + } + + public static bool Get_black_graph_color() + { + return black_graph_color; + } + + public static bool Get_alternative_draw_graph() + { + return alternative_draw_graph; + } + + public static bool Get_draw_graph() + { + return alternative_draw_graph; + } + + public static int Get_pen_node_color() + { + return pen_node_color; + } + + public static int Get_pen_node_width() + { + return pen_node_width; + } + + public static int Get_vertex_size() + { + return vertex_size; + } + + public static string Get_node_naming_font_name() + { + return node_naming_font_name; + } + + public static int Get_node_naming_font_size() + { + return node_naming_font_size; + } + + public static int Get_node_naming_brush_color() + { + return node_naming_brush_color; + } + + public static bool Get_node_naming() + { + return node_naming; + } + + public static int Get_node_naming_start_index() + { + return node_naming_start_index; + } + + public static int Get_node_naming_string_offset() + { + return node_naming_string_offset; + } + + public static int Get_node_naming_interval() + { + return node_naming_interval; + } + + public static int Get_route_color() + { + return route_color; + } + + public static int Get_route_width() + { + return route_width; + } + + public static int Get_error_iterations_count() + { + return error_iterations_count; + } + public static string Get_path_to_quartus() + { + return quartus_folder_path; + } + public static string Get_project_path() + { + return project_folder_path; + } + + public static string Get_server() + { + return server; + } + public static string Get_port() + { + return port; + } + public static string Get_username() + { + return username; + } + public static byte[] Get_encpassword() + { + return encpassword; + } + + public static bool Get_checked_routing_algorithms_circulant(int index) + { + return circulant_algorithms_checked[index]; + } + + public static bool Get_checked_routing_algorithms_mesh(int index) + { + return mesh_algorithms_checked[index]; + } + + public static bool Get_checked_routing_algorithms_torus(int index) + { + return torus_algorithms_checked[index]; + } + + public static void Set_back_color_graph(int color) + { + back_color_graph = color; + } + + public static void Set_black_graph_color(bool graph_color) + { + black_graph_color = graph_color; + } + + public static void Set_alternative_draw_graph(bool alternative_draw) + { + alternative_draw_graph = alternative_draw; + } + + public static void Set_pen_node_color(int color) + { + pen_node_color = color; + } + + public static void Set_pen_node_width(int width) + { + pen_node_width = width; + } + + public static void Set_vertex_size(int size) + { + vertex_size = size; + } + + public static void Set_node_naming_font_name(string name) + { + node_naming_font_name = name; + } + + public static void Set_node_naming_font_size(int size) + { + node_naming_font_size = size; + } + + public static void Set_node_naming_brush_color(int color) + { + node_naming_brush_color = color; + } + + public static void Set_node_naming(bool naming) + { + node_naming = naming; + } + + public static void Set_node_naming_start_index(int index) + { + node_naming_start_index = index; + } + + public static void Set_node_naming_string_offset(int string_offset) + { + node_naming_string_offset = string_offset; + } + + public static void Set_node_naming_interval(int naming_interval) + { + node_naming_interval = naming_interval; + } + + public static void Set_route_color(int color) + { + route_color = color; + } + + public static void Set_route_width(int width) + { + route_width = width; + } + + public static void Set_error_iterations_count(int iterations_count) + { + error_iterations_count = iterations_count; + } + public static void Set_path_to_quartus(string way_to_quartus) + { + quartus_folder_path = way_to_quartus; + } + public static void Set_project_path(string project_path) + { + project_folder_path = project_path; + } + + public static void Set_server(string new_server) + { + server = new_server; + } + public static void Set_port(string new_port) + { + port = new_port; + } + public static void Set_username(string new_username) + { + username = new_username; + } + public static void Set_serverh(byte[] new_encpassword) + { + encpassword = new_encpassword; + } + + public static void Set_checked_routing_algorithms_circulant(int index, bool state) + { + circulant_algorithms_checked[index] = state; + } + public static void Set_checked_routing_algorithms_mesh(int index, bool state) + { + mesh_algorithms_checked[index] = state; + } + + public static void Set_checked_routing_algorithms_torus(int index, bool state) + { + torus_algorithms_checked[index] = state; + } + + } + + public class SettingsSerializer + { + public int back_color_graph { get; set; } // фон, РЅР° котором отрисовывается граф + public bool black_graph_color { get; set; } // черно-белая отрисовка графа + public bool alternative_draw_graph { get; set; } // отрисовка образующих эллипсом + public int pen_node_color { get; set; } // цвет, которым рисуются узлы Рё основная образующая + public int pen_node_width { get; set; } // ширина линий, которыми рисуются узлы Рё образующие + public int vertex_size { get; set; } // размер отрисовки вершин (диаметр окружности) + public string node_naming_font_name { get; set; } // название шрифта, которым подписываются узлы + public int node_naming_font_size { get; set; } // размер шрифта, которым подписываются узлы + public int node_naming_brush_color { get; set; } // цвет шрифта, которым подписываются узлы + public bool node_naming { get; set; } // нумерация узлов графа + public int node_naming_start_index { get; set; } // начало нумерации СЃ 0 или СЃ 1 - соответствует записанному числу + public int node_naming_interval { get; set; } // интервал нумерации узлов + public int node_naming_string_offset { get; set; } // смещение РїРѕРґРїРёСЃРё узлв РѕС‚ центра узла + public int route_color { get; set; } // цвет отрисовки маршрута + public int route_width { get; set; } // щирина линии, которой отрисовывается маршрут + + public int error_iterations_count { get; set; } // количество шагов маршрута, после которого считать, что алгоритм РЅРµ может построить + // РІ форме настрое этого параметра РїРѕРєР° нет + public string quartus_folder_path { get; set; } + public string project_folder_path { get; set; } + + public bool[] circulant_algorithms_checked { get; set; } + public bool[] mesh_algorithms_checked { get; set; } + public bool[] torus_algorithms_checked { get; set; } + + public string server { get; set; } + public string port { get; set; } + public string username { get; set; } + public string database { get; set; } + public byte[] encpassword { get; set; } + + public SettingsSerializer() + { + back_color_graph = -1; + black_graph_color = false; + alternative_draw_graph = false; + pen_node_color = -16777216; + pen_node_width = 5; + vertex_size = 30; + node_naming_font_name = "Arial"; + node_naming_font_size = 7; + node_naming_brush_color = -16777216; + node_naming = true; + node_naming_start_index = 0; + node_naming_interval = 1; + node_naming_string_offset = 50; + route_color = -10496; + route_width = 5; + error_iterations_count = 300; + quartus_folder_path = " "; + project_folder_path = " "; + server = " "; + database = " "; + port = " "; + username = " "; + encpassword = [0]; + + + circulant_algorithms_checked = new bool[] { false }; + mesh_algorithms_checked = new bool[] { false, false }; + torus_algorithms_checked = new bool[] { false }; + + } + } +}