Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

23 implement network card #27

Merged
merged 9 commits into from
Oct 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions src/MimaSim/MimaSim.Desktop/Core/NetworkService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System;
using System.Diagnostics;
using MimaSim.Core;
using MimaSim.MIMA.Components;
using MimaSim.MIMA.Components.Network;
using NATS.Net;

namespace MimaSim.Desktop.Core;

public class NetworkService : INetworkService
{
private NatsClient _client;
private string _subject;

public async void Init()
{
_client = new NatsClient("demo.nats.io");

_subject = $"mimasim.networks.{CPU.Instance.NIC.NetworkAddress}.>";
await foreach (var msg in _client.SubscribeAsync<byte[]>(subject: _subject))
{
Debug.WriteLine($"Received: {msg.Subject}: {Frame.Unpack(msg.Data!)}");
}
}

public async void Send(Frame frame)
{
await _client.PublishAsync(subject: _subject, data: frame.Pack());
}

public void Receive(Action<Frame> action)
{
throw new NotImplementedException();
}
}
1 change: 1 addition & 0 deletions src/MimaSim/MimaSim.Desktop/MimaSim.Desktop.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
<PackageReference Include="Avalonia.Desktop" Version="11.1.4"/>
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.1.4"/>
<PackageReference Include="NATS.Net" Version="2.5.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3"/>
</ItemGroup>

Expand Down
1 change: 1 addition & 0 deletions src/MimaSim/MimaSim.Desktop/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public static void Main(string[] args)
{
Locator.CurrentMutable.RegisterLazySingleton<ICache>(() => new DesktopCache());
Locator.CurrentMutable.RegisterLazySingleton<IInterop>(() => new Interop());
Locator.CurrentMutable.RegisterLazySingleton<INetworkService>(() => new NetworkService());

BuildAvaloniaApp()
.StartWithClassicDesktopLifetime(args);
Expand Down
81 changes: 0 additions & 81 deletions src/MimaSim/MimaSim.Desktop/run.txt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" Width="75" x:CompileBindings="False"
x:Class="MimaSim.Controls.MimaComponents.NetworkCardControl">
<Border BorderBrush="Black" BorderThickness="1" Margin="5">
<Button Classes="clickable" Command="{Binding OpenNetworkSettingsCommand}">
<StackPanel Spacing="5">
<TextBlock Text="NIC" TextAlignment="Center" VerticalAlignment="Center" />
<PathIcon Data="{DynamicResource network}" Width="25" Height="25" />
</StackPanel>
</Button>
</Border>
</UserControl>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;

namespace MimaSim.Controls.MimaComponents;

public partial class NetworkCardControl : UserControl
{
public NetworkCardControl()
{
InitializeComponent();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="clr-namespace:MimaSim.Controls"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:CompileBindings="False"
x:Class="MimaSim.Controls.MimaComponents.Popups.NetworkCardPopupControl">
<controls:DialogControl CommandText="OK" IsCancelEnabled="False" Header="Network Card">
<Grid ColumnDefinitions="*,*" RowDefinitions="*,*,*">
<TextBlock Grid.Row="0" Grid.Column="0" Text="MAC-Addresse: " />
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding MAC}" />

<TextBlock Grid.Row="1" Grid.Column="0" Text="IP-Addresse: " />
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding IP}" />

<TextBlock Grid.Row="2" Grid.Column="0" Text="Subnetz-Maske: " />
<TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding SubnetMask}" />
</Grid>
</controls:DialogControl>
</UserControl>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using Avalonia.Controls;

namespace MimaSim.Controls.MimaComponents.Popups;

public partial class NetworkCardPopupControl : UserControl
{
public NetworkCardPopupControl()
{
InitializeComponent();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:core="clr-namespace:MimaSim.Core"
xmlns:mimaComponents="clr-namespace:MimaSim.Controls.MimaComponents"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="MimaSim.Controls.MimaComponents.Wrappers.NetworkCardWrapper">
<Canvas Height="190" Width="75">
<mimaComponents:NetworkCardControl Canvas.Left="0" />
<mimaComponents:BusControl Canvas.Top="55" Canvas.Left="35" Width="15" Height="127" State="None" core:BusRegistry.Id="base_to_nic" />
</Canvas>
</UserControl>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;

namespace MimaSim.Controls.MimaComponents.Wrappers;

public partial class NetworkCardWrapper : UserControl
{
public NetworkCardWrapper()
{
InitializeComponent();
}
}
2 changes: 2 additions & 0 deletions src/MimaSim/MimaSim/Controls/MimaControl.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
x:Class="MimaSim.Controls.MimaControl">
<Border BorderBrush="Black" BorderThickness="1">
<Canvas>
<w:NetworkCardWrapper Canvas.Top="10" Canvas.Left="440" />

<w:AluWrapperControl Canvas.Top="20" Canvas.Left="190" />
<w:MemoryWrapper Canvas.Top="75" Canvas.Left="350" />

Expand Down
12 changes: 12 additions & 0 deletions src/MimaSim/MimaSim/Core/INetworkService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System;
using MimaSim.MIMA.Components.Network;

namespace MimaSim.Core;

public interface INetworkService
{
void Init();

void Send(Frame frame);
void Receive(Action<Frame> action);
}
11 changes: 9 additions & 2 deletions src/MimaSim/MimaSim/MIMA/Components/CPU.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using MimaSim.MIMA.Components.Graphics;
using MimaSim.MIMA.Components.Network;
using Splat;

namespace MimaSim.MIMA.Components;

Expand All @@ -17,6 +20,7 @@ public class CPU
public readonly Clock Clock = new(250);
public readonly ControlUnit ControlUnit = new();
public readonly Bus DataBus = new();
public readonly NetworkCard NIC;

public readonly static Dictionary<OpCodes, IInstruction> Instructions = new();
public readonly Memory Memory = new((int)Math.Pow(2, 8));
Expand All @@ -37,6 +41,7 @@ public CPU()
{
ALU = new ALU(this);
Stack = new Stack(this);
NIC = new NetworkCard(Locator.Current.GetService<ICache>()!);

ControlUnit.IAR.Bus.Subscribe(_ =>
{
Expand Down Expand Up @@ -64,11 +69,11 @@ public CPU()

ControlUnit.AddSysCall(SysCall.DRAW, () =>
{
var isTextMode = CPU.Instance.ControlUnit.HasFlag(Flags.TextMode);
var isTextMode = ControlUnit.HasFlag(Flags.TextMode);

if (isTextMode)
{
var ch = (char)CPU.Instance.Display.DC.GetValueWithoutNotification();
var ch = (char)Display.DC.GetValueWithoutNotification();
Instance.Display.DrawChar(ch);
}
else
Expand Down Expand Up @@ -146,6 +151,8 @@ public void SetRegister(byte reg, short value)

public bool Step()
{
ControlUnit.InvokeInterrupt();

var instr = Fetch();
var result = Step((OpCodes)instr);

Expand Down
12 changes: 12 additions & 0 deletions src/MimaSim/MimaSim/MIMA/Components/ControlUnit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,21 @@ public class ControlUnit
public Register IAR = new("IAR");
public Register SP = new("SP", 49);
public Register SCR = new("SCR");
public Action? _interrupt;

private Dictionary<SysCall, Action> _syscalls = new();

public void Interrupt(Action? action)
{
_interrupt += action;
}

public void InvokeInterrupt()
{
_interrupt?.Invoke();
_interrupt = null;
}

public void AddSysCall(SysCall syscall, Action action)
{
_syscalls.TryAdd(syscall, action);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using Avalonia.Threading;
using MimaSim.Controls.MimaComponents;

namespace MimaSim.MIMA.Components;
namespace MimaSim.MIMA.Components.Graphics;

public class Display
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace MimaSim.MIMA.Components;
namespace MimaSim.MIMA.Components.Graphics;

public enum DisplayColor
{
Expand Down
71 changes: 71 additions & 0 deletions src/MimaSim/MimaSim/MIMA/Components/Network/Frame.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using System.Net;

namespace MimaSim.MIMA.Components.Network;

public readonly record struct Frame(
IPAddress FromIPAddress,
MacAddress FromMacAddress,
IPAddress? ToIPAddress,
MacAddress ToMacAddress,
byte[] Data)
{
public byte[] Pack()
{
using (var memoryStream = new System.IO.MemoryStream())
{
// Pack FromIPAddress
byte[] fromIpBytes = FromIPAddress.GetAddressBytes();
memoryStream.Write(fromIpBytes, 0, fromIpBytes.Length);

// Pack FromMacAddress
byte[] fromMacBytes = FromMacAddress.GetBytes();
memoryStream.Write(fromMacBytes, 0, fromMacBytes.Length);

// Pack ToIPAddress
byte[] toIpBytes = ToIPAddress.GetAddressBytes();
memoryStream.Write(toIpBytes, 0, toIpBytes.Length);

// Pack ToMacAddress
byte[] toMacBytes = ToMacAddress.GetBytes();
memoryStream.Write(toMacBytes, 0, toMacBytes.Length);

// Pack Data
memoryStream.Write(Data, 0, Data.Length);

return memoryStream.ToArray();
}
}

public static Frame Unpack(byte[] data)
{
using (var memoryStream = new System.IO.MemoryStream(data))
{
// Unpack FromIPAddress
byte[] fromIpBytes = new byte[4]; // Assuming IPv4
memoryStream.Read(fromIpBytes, 0, fromIpBytes.Length);
IPAddress fromIp = new IPAddress(fromIpBytes);

// Unpack FromMacAddress
byte[] fromMacBytes = new byte[6]; // Assuming MAC address is 6 bytes
memoryStream.Read(fromMacBytes, 0, fromMacBytes.Length);
MacAddress fromMac = new MacAddress(fromMacBytes);

// Unpack ToIPAddress

byte[] toIpBytes = new byte[4];
memoryStream.Read(toIpBytes, 0, toIpBytes.Length);
IPAddress? toIp = new IPAddress(toIpBytes);

// Unpack ToMacAddress
byte[] toMacBytes = new byte[6];
memoryStream.Read(toMacBytes, 0, toMacBytes.Length);
MacAddress toMac = new MacAddress(toMacBytes);

// Unpack Data
byte[] dataBuffer = new byte[memoryStream.Length - memoryStream.Position];
memoryStream.Read(dataBuffer, 0, dataBuffer.Length);

return new Frame(fromIp, fromMac, toIp, toMac, dataBuffer);
}
}
}
52 changes: 52 additions & 0 deletions src/MimaSim/MimaSim/MIMA/Components/Network/MacAddress.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using System;
using System.Linq;

namespace MimaSim.MIMA.Components.Network;

public readonly record struct MacAddress(byte[] address)
{
private readonly byte[] _address = address;

public static MacAddress Parse(string macAddress)
{
if (!TryParse(macAddress, out var a))
throw new FormatException("Ungültiges MAC-Adressformat.");

return a;
}

public static MacAddress Generate()
{
var random = new Random();
var bytes = new byte[6];
random.NextBytes(bytes);

bytes[0] = (byte)(bytes[0] & 0xFE);

return new MacAddress(bytes);
}

public static bool TryParse(string macAddress, out MacAddress address)
{
var cleanedMac = macAddress.Replace(":", "").Replace("-", "").Replace(".", "");

if (cleanedMac.Length != 12 || !cleanedMac.All(Uri.IsHexDigit))
{
address = default;
return false;
}

address = new MacAddress(Enumerable.Range(0, 6)
.Select(i => Convert.ToByte(cleanedMac.Substring(i * 2, 2), 16))
.ToArray());

return true;
}

public override string ToString()
{
return string.Join(":", _address.Select(b => b.ToString("X2")));
}

public byte[] GetBytes() => _address;
}
Loading
Loading