Adds experimental host.

This commit is contained in:
Felix Queißner 2016-06-17 09:24:08 +02:00
parent fa4efc8b1c
commit b07cb36418
14 changed files with 436 additions and 12 deletions

View file

@ -181,17 +181,7 @@ namespace SuperVM.Assembler
}
}
ulong encoded = 0;
encoded |= ((uint)(instruction.ExecutionZ) << 0);
encoded |= ((uint)(instruction.ExecutionN) << 2);
encoded |= ((uint)(instruction.Input0) << 4);
encoded |= ((uint)(instruction.Input1) << 6);
encoded |= ((uint)(instruction.Command) << 7);
encoded |= ((uint)(instruction.CommandInfo) << 13);
encoded |= ((uint)(instruction.ModifyFlags ? 1 : 0) << 29);
encoded |= ((uint)(instruction.Output) << 30);
encoded |= ((ulong)argument << 32);
ulong encoded = instruction.Encode();
code.Add(encoded);
instructions.Add(instruction);

View file

@ -33,6 +33,10 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
@ -51,6 +55,7 @@
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SuperVM\SuperVM.csproj">

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="SharpZipLib" version="0.86.0" targetFramework="net46" />
</packages>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/>
</startup>
</configuration>

View file

@ -0,0 +1,215 @@
using ICSharpCode.SharpZipLib.Core;
using ICSharpCode.SharpZipLib.Zip;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SuperVM.ExperimentalHost
{
class Program
{
private static bool running;
static void Main(string[] args)
{
var zf = new ZipFile("executable.zip");
NameValueCollection meta;
var metaConfFile = zf.GetEntry("meta.conf");
using (var stream = zf.GetInputStream(metaConfFile))
{
meta = ReadConfiguration(stream);
}
// Default memory size to
int memsize = int.Parse(meta["memsize"] ?? "16384");
var codeName = meta["code"] ?? "code.bin";
var dataName = meta["data"];
if (codeName == null)
throw new InvalidDataException();
Module module;
{ // Load code
var codeFile = zf.GetEntry(codeName);
var bits = new byte[codeFile.Size];
using (var stream = zf.GetInputStream(codeFile))
{
for (int i = 0; i < bits.Length; i += stream.Read(bits, i, bits.Length - i)) ;
}
var instr = new ulong[bits.Length / sizeof(ulong)];
Buffer.BlockCopy(bits, 0, instr, 0, instr.Length * sizeof(ulong));
module = new Module(instr.Select(Instruction.Decode).ToArray());
}
byte[] initialMemory = null;
if (dataName != null)
{
var dataFile = zf.GetEntry(dataName);
using (var stream = zf.GetInputStream(dataFile))
{
using (var ms = new MemoryStream())
{
stream.CopyTo(ms);
initialMemory = ms.ToArray();
}
}
}
Memory memory = new Memory(memsize);
if (initialMemory != null)
{
Array.Copy(initialMemory, memory.Raw, Math.Min(initialMemory.Length, memsize));
}
var process = new Process(module, memory);
process.SysCall += Process_SysCall;
running = true;
var watch = Stopwatch.StartNew();
long instructions = 0;
while (running)
{
process.Step();
instructions++;
}
watch.Stop();
Console.WriteLine();
Console.WriteLine("Time: {0}", watch.Elapsed);
Console.WriteLine("Count: {0}", instructions);
Console.WriteLine("IPS: {0}", instructions / watch.Elapsed.TotalSeconds);
Console.ReadLine();
}
private static void Process_SysCall(object sender, Process.CommandExecutionEnvironment e)
{
switch (e.Additional)
{
case 0: running = false; break;
case 1: // putc
Console.Write((char)(e.Input0 & 0xFF));
break;
case 2: // puti
Console.Write(e.Input0);
break;
default:
throw new InvalidOperationException("Unkown syscall: " + e.Additional);
}
}
static NameValueCollection ReadConfiguration(Stream stream)
{
var nvc = new NameValueCollection();
using (var reader = new StreamReader(stream, Encoding.ASCII))
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
if (line.StartsWith("#"))
continue;
var parts = line.Split('=');
if (parts.Length != 2)
throw new InvalidDataException();
nvc[parts[0].Trim()] = parts[1].Trim();
}
}
return nvc;
}
// Calling example:
// WebClient webClient = new WebClient();
// Stream data = webClient.OpenRead("http://www.example.com/test.zip");
// This stream cannot be opened with the ZipFile class because CanSeek is false.
// UnzipFromStream(data, @"c:\temp");
public void UnzipFromStream(Stream zipStream, string outFolder)
{
ZipInputStream zipInputStream = new ZipInputStream(zipStream);
ZipEntry zipEntry = zipInputStream.GetNextEntry();
while (zipEntry != null)
{
String entryFileName = zipEntry.Name;
// to remove the folder from the entry:- entryFileName = Path.GetFileName(entryFileName);
// Optionally match entrynames against a selection list here to skip as desired.
// The unpacked length is available in the zipEntry.Size property.
byte[] buffer = new byte[4096]; // 4K is optimum
// Manipulate the output filename here as desired.
String fullZipToPath = Path.Combine(outFolder, entryFileName);
string directoryName = Path.GetDirectoryName(fullZipToPath);
if (directoryName.Length > 0)
Directory.CreateDirectory(directoryName);
// Unzip file in buffered chunks. This is just as fast as unpacking to a buffer the full size
// of the file, but does not waste memory.
// The "using" will close the stream even if an exception occurs.
using (FileStream streamWriter = File.Create(fullZipToPath))
{
StreamUtils.Copy(zipInputStream, streamWriter, buffer);
}
zipEntry = zipInputStream.GetNextEntry();
}
}
public void ExtractZipFile(string archiveFilenameIn, string password, string outFolder)
{
ZipFile zf = null;
try
{
FileStream fs = File.OpenRead(archiveFilenameIn);
zf = new ZipFile(fs);
if (!String.IsNullOrEmpty(password))
{
zf.Password = password; // AES encrypted entries are handled automatically
}
foreach (ZipEntry zipEntry in zf)
{
if (!zipEntry.IsFile)
{
continue; // Ignore directories
}
String entryFileName = zipEntry.Name;
// to remove the folder from the entry:- entryFileName = Path.GetFileName(entryFileName);
// Optionally match entrynames against a selection list here to skip as desired.
// The unpacked length is available in the zipEntry.Size property.
byte[] buffer = new byte[4096]; // 4K is optimum
Stream zipStream = zf.GetInputStream(zipEntry);
// Manipulate the output filename here as desired.
String fullZipToPath = Path.Combine(outFolder, entryFileName);
string directoryName = Path.GetDirectoryName(fullZipToPath);
if (directoryName.Length > 0)
Directory.CreateDirectory(directoryName);
// Unzip file in buffered chunks. This is just as fast as unpacking to a buffer the full size
// of the file, but does not waste memory.
// The "using" will close the stream even if an exception occurs.
using (FileStream streamWriter = File.Create(fullZipToPath))
{
StreamUtils.Copy(zipStream, streamWriter, buffer);
}
}
}
finally
{
if (zf != null)
{
zf.IsStreamOwner = true; // Makes close also shut the underlying stream
zf.Close(); // Ensure we release resources
}
}
}
}
}

View file

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// Allgemeine Informationen über eine Assembly werden über die folgenden
// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
// die einer Assembly zugeordnet sind.
[assembly: AssemblyTitle("SuperVM.ExperimentalHost")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SuperVM.ExperimentalHost")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar
// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von
// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen.
[assembly: ComVisible(false)]
// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
[assembly: Guid("4fe5c136-c634-4ec5-a373-13b1a18a3a2b")]
// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
//
// Hauptversion
// Nebenversion
// Buildnummer
// Revision
//
// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
// übernehmen, indem Sie "*" eingeben:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View file

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{4FE5C136-C634-4EC5-A373-13B1A18A3A2B}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>SuperVM.ExperimentalHost</RootNamespace>
<AssemblyName>SuperVM.ExperimentalHost</AssemblyName>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<RunPostBuildEvent>Always</RunPostBuildEvent>
</PropertyGroup>
<ItemGroup>
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SuperVM\SuperVM.csproj">
<Project>{014295b7-06bd-47c7-b8ca-d046984b0f35}</Project>
<Name>SuperVM</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="demo.asm" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>$(SolutionDir)SuperVM.Assembler\bin\Debug\SuperVM.Assembler.exe $(ProjectDir)demo.asm
cp $(ProjectDir)demo.bin $(TargetDir)code.bin
$(TargetDir)pack.bat</PostBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View file

@ -0,0 +1,13 @@

main:
push 0 ; ptr
loop:
[i0:peek] load [f:yes]
[ex(z)=1] jmp @end
[i0:pop] syscall [ci:1]
[i0:arg] [i1:pop] add 1
jmp @loop
end:
syscall [ci:0] ; quit

Binary file not shown.

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="SharpZipLib" version="0.86.0" targetFramework="net452" />
</packages>

View file

@ -9,6 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SuperVM", "SuperVM\SuperVM.
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SuperVM.Assembler", "SuperVM.Assembler\SuperVM.Assembler.csproj", "{A84B2773-0EB8-4F3A-B342-68DDD9BD675E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SuperVM.ExperimentalHost", "SuperVM.ExperimentalHost\SuperVM.ExperimentalHost.csproj", "{4FE5C136-C634-4EC5-A373-13B1A18A3A2B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -27,6 +29,10 @@ Global
{A84B2773-0EB8-4F3A-B342-68DDD9BD675E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A84B2773-0EB8-4F3A-B342-68DDD9BD675E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A84B2773-0EB8-4F3A-B342-68DDD9BD675E}.Release|Any CPU.Build.0 = Release|Any CPU
{4FE5C136-C634-4EC5-A373-13B1A18A3A2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4FE5C136-C634-4EC5-A373-13B1A18A3A2B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4FE5C136-C634-4EC5-A373-13B1A18A3A2B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4FE5C136-C634-4EC5-A373-13B1A18A3A2B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View file

@ -17,5 +17,39 @@ namespace SuperVM
public bool ModifyFlags;
public OutputType Output;
public uint Argument;
public override string ToString() => $"({Input0},{Input1}) {Command} -> {Output}";
public ulong Encode()
{
ulong encoded = 0;
encoded |= ((uint)(this.ExecutionZ) << 0);
encoded |= ((uint)(this.ExecutionN) << 2);
encoded |= ((uint)(this.Input0) << 4);
encoded |= ((uint)(this.Input1) << 6);
encoded |= ((uint)(this.Command) << 7);
encoded |= ((uint)(this.CommandInfo) << 13);
encoded |= ((uint)(this.ModifyFlags ? 1 : 0) << 29);
encoded |= ((uint)(this.Output) << 30);
encoded |= ((ulong)this.Argument << 32);
return encoded;
}
public static Instruction Decode(ulong encoded)
{
var instr = new Instruction();
instr.ExecutionZ = (ExecutionMode)((encoded >> 0) & 3);
instr.ExecutionN = (ExecutionMode)((encoded >> 2) & 3);
instr.Input0 = (InputType)((encoded >> 4) & 3);
instr.Input1 = (InputType)((encoded >> 6) & 1);
instr.Command = (Command)((encoded >> 7) & 63);
instr.CommandInfo = (ushort)((encoded >> 13) & 65535);
instr.ModifyFlags = ((encoded >> 29) & 1) != 0;
instr.Output = (OutputType)((encoded >> 30) & 3);
instr.Argument = (uint)(encoded >> 32);
return instr;
}
}
}

View file

@ -8,6 +8,12 @@ namespace SuperVM
{
partial class Process
{
public Process(Module module, Memory memory)
{
this.Module = module;
this.Memory = memory;
}
private static class Cmd
{

View file

@ -167,7 +167,7 @@ namespace SuperVM
public Module Module { get; set; }
public Memory Memory { get; set; }
public Memory Memory { get; set; } = new Memory(16384);
public uint CodePointer { get; set; }
public uint StackPointer { get; set; }
@ -189,12 +189,34 @@ namespace SuperVM
this.Process = process;
}
/// <summary>
/// First input value
/// </summary>
public uint Input0 { get; set; }
/// <summary>
/// Second input value
/// </summary>
public uint Input1 { get; set; }
/// <summary>
/// The command argument
/// </summary>
public uint Argument { get; set; }
/// <summary>
/// The command info
/// </summary>
public uint Additional { get; set; }
/// <summary>
/// The output of the command.
/// </summary>
public uint Output { get; set; }
/// <summary>
/// The executing process.
/// </summary>
public Process Process { get; private set; }
}
}