using Microsoft.CodeAnalysis;
using NIFPGA.lvbitx;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
namespace ShakerFpga
{
[Generator(LanguageNames.CSharp)]
internal class ShakerFpgaSourceGenerator : IIncrementalGenerator
{
public void Initialize(IncrementalGeneratorInitializationContext context)
{
context.RegisterPostInitializationOutput(c =>
{
var names = typeof(ShakerFpgaSourceGenerator).Assembly.GetManifestResourceNames().First(x => x.IndexOf(".lvbitx")>=0);
NIFPGA.lvbitx.Bitfile bitfile = NIFPGA.lvbitx.Parse.ParseFile(typeof(ShakerFpgaSourceGenerator).Assembly.GetManifestResourceStream(names),names);
string s = string.Join(",", bitfile.VI.Registers.Select(x => x.Name));
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendLine("/// ");
stringBuilder.AppendLine("/// This code was generated by Source Generator.");
stringBuilder.AppendLine("/// ");
stringBuilder.AppendLine("using NIFPGA;");
stringBuilder.AppendLine("using FxpConvert.Common;");
stringBuilder.AppendLine("namespace ShakerFpga");
stringBuilder.AppendLine("{");
stringBuilder.AppendLine(" public sealed class ShakerFpga");
stringBuilder.AppendLine(" {");
stringBuilder.AppendLine(" private static ShakerFpga myFpga;");
stringBuilder.AppendLine(" private readonly NIFPGA.FPGA fpga;");
stringBuilder.AppendLine(" public string BitstreamMD5 => fpga.BitstreamMD5;");
stringBuilder.AppendLine(" public string BitfileVersion => fpga.BitfileVersion;");
stringBuilder.AppendLine(" public string SignatureRegister => fpga.SignatureRegister;");
stringBuilder.AppendLine(" public string BitstreamVersion => fpga.BitstreamVersion;");
stringBuilder.AppendLine(" public string SignatureNames => fpga.SignatureNames;");
stringBuilder.AppendLine(" public bool LastError => fpga.Error;");
stringBuilder.AppendLine(" public NiFpga_Status LastStatus => fpga.LastStatus;");
stringBuilder.AppendLine(" public string LastMessage => fpga.Message;");
stringBuilder.AppendLine(" private ShakerFpga(IFxpConvert convert)");
stringBuilder.AppendLine(" {");
stringBuilder.AppendLine(" fpga = new FPGA(convert);");
stringBuilder.AppendLine(" }");
stringBuilder.AppendLine(" static ShakerFpga()");
stringBuilder.AppendLine(" {");
stringBuilder.AppendLine(" }");
stringBuilder.AppendLine(" public Irq Irq => fpga.Irq;");
stringBuilder.AppendLine(" public void Open(string bitfile, string resource, NiFpga_OpenAttribute attribute) => fpga.Open(bitfile, resource, attribute);");
stringBuilder.AppendLine(" public void Close() => fpga.Close();");
stringBuilder.AppendLine(" public void Run() => fpga.Run();");
stringBuilder.AppendLine(" public void Download() => fpga.Download();");
stringBuilder.AppendLine(" public void FpgaFinalize() => fpga.FpgaFinalize();");
stringBuilder.AppendLine(" public void Abort() => fpga.Abort();");
stringBuilder.AppendLine(" public void Reset() => fpga.Reset();");
stringBuilder.AppendLine(" public static ShakerFpga CreateFpga(IFxpConvert convert)");
stringBuilder.AppendLine(" {");
stringBuilder.AppendLine(" myFpga ??= new ShakerFpga(convert);");
stringBuilder.AppendLine(" return myFpga;");
stringBuilder.AppendLine(" }");
stringBuilder.AppendLine(" public static ShakerFpga Instance");
stringBuilder.AppendLine(" {");
stringBuilder.AppendLine(" get");
stringBuilder.AppendLine(" {");
stringBuilder.AppendLine(" if (myFpga == null)");
stringBuilder.AppendLine(" {");
stringBuilder.AppendLine(" throw new Exception(\"must call first CreateFpga\");");
stringBuilder.AppendLine(" }");
stringBuilder.AppendLine(" return myFpga;");
stringBuilder.AppendLine(" }");
stringBuilder.AppendLine(" }");
stringBuilder.AppendLine(" #region 寄存器定义");
bitfile.VI.Registers.ForEach(x => GeneratorRegister(x, stringBuilder));
stringBuilder.AppendLine(" #endregion");
stringBuilder.AppendLine(" #region Fifo定义");
bitfile.Project.DMA.ForEach(x => GeneratorFifo(x, stringBuilder));
stringBuilder.AppendLine(" #endregion");
stringBuilder.AppendLine(" }");
stringBuilder.AppendLine("}");
c.AddSource("ShakerFpga.g.cs", stringBuilder.ToString());
});
}
private void GeneratorRegister(Register register, StringBuilder stringBuilder)
{
string protype = GetProType(register);
string proname = $"{register.Name.Split('_')[0]}";
proname = RemovePropertySpecialcharacters(proname);
stringBuilder.AppendLine($" private {protype} _{proname};");
stringBuilder.AppendLine($" /// ");
stringBuilder.AppendLine($" /// {register.Name}");
stringBuilder.AppendLine($" /// ");
stringBuilder.AppendLine($" public {protype} {proname}");
stringBuilder.AppendLine(" {");
stringBuilder.AppendLine(" get");
stringBuilder.AppendLine(" {");
stringBuilder.AppendLine($" if(_" + proname + "==null)");
stringBuilder.AppendLine(" {");
stringBuilder.AppendLine($" _" + proname + $"=({protype})fpga.Properties[\"{register.Name}\"];");
stringBuilder.AppendLine(" }");
stringBuilder.AppendLine($" return _" + proname + ";");
stringBuilder.AppendLine(" }");
stringBuilder.AppendLine(" }");
}
private void GeneratorFifo(DMA dma,StringBuilder stringBuilder)
{
string protype = GetFifoType(dma);
string proname = $"{dma.Name.Split('_')[0]}";
proname = RemovePropertySpecialcharacters(proname);
stringBuilder.AppendLine($" private {protype} _{proname};");
stringBuilder.AppendLine($" /// ");
stringBuilder.AppendLine($" /// {dma.Name}");
stringBuilder.AppendLine($" /// ");
stringBuilder.AppendLine($" public {protype} {proname}");
stringBuilder.AppendLine(" {");
stringBuilder.AppendLine(" get");
stringBuilder.AppendLine(" {");
stringBuilder.AppendLine($" if(_" + proname + "==null)");
stringBuilder.AppendLine(" {");
stringBuilder.AppendLine($" _" + proname + $"=({protype})fpga.Fifos[\"{dma.Name}\"];");
stringBuilder.AppendLine(" }");
stringBuilder.AppendLine($" return _" + proname + ";");
stringBuilder.AppendLine(" }");
stringBuilder.AppendLine(" }");
}
private string GetFifoType(DMA dma)
{
string direction = dma.Direction == "TargetToHost" ? "ReadFifo" : "WriteFifo";
string protype = string.Empty;
switch (dma.Datatype)
{
case NIFPGA.lvbitx.Datatype.Boolean:
protype = $"{direction}";
break;
case NIFPGA.lvbitx.Datatype.Int8:
protype = $"{direction}";
break;
case NIFPGA.lvbitx.Datatype.Double:
protype = $"{direction}";
break;
case NIFPGA.lvbitx.Datatype.Float:
protype = $"{direction}";
break;
case NIFPGA.lvbitx.Datatype.FXP:
protype = $"{(dma.Direction == "TargetToHost" ? "ReadFXPFifo" : "WriteFXPFifo")}";
break;
case NIFPGA.lvbitx.Datatype.Int16:
protype = $"{direction}";
break;
case NIFPGA.lvbitx.Datatype.Int32:
protype = $"{direction}";
break;
case NIFPGA.lvbitx.Datatype.Int64:
protype = $"{direction}";
break;
case NIFPGA.lvbitx.Datatype.Uint16:
protype = $"{direction}";
break;
case NIFPGA.lvbitx.Datatype.Uint32:
protype = $"{direction}";
break;
case NIFPGA.lvbitx.Datatype.Uint64:
protype = $"{direction}";
break;
case NIFPGA.lvbitx.Datatype.Uint8:
protype = $"{direction}";
break;
default:
throw new Exception("类型错误");
}
return protype;
}
private string RemovePropertySpecialcharacters(string s)
{
string proname = Regex.Replace(s,@"\((.+?)\)","", RegexOptions.IgnoreCase).Replace("(", "_").Replace(")", "_").Replace("/", "_").Replace("__", "_").Trim('_');
return char.ToUpper(proname[0]) + proname.Substring(1);
}
private string GetProType(Register register)
{
string value = "";
switch (register.Datatype)
{
case NIFPGA.lvbitx.Datatype.Boolean:
if(!register.Indicator)
{
value = "FPGAWriteProperty";
}
else
{
value = "FPGAReadProperty";
}
break;
case NIFPGA.lvbitx.Datatype.Int8:
if (!register.Indicator)
{
value = "FPGAWriteProperty";
}
else
{
value = "FPGAReadProperty";
}
break;
case NIFPGA.lvbitx.Datatype.Uint8:
if (!register.Indicator)
{
value = "FPGAWriteProperty";
}
else
{
value = "FPGAReadProperty";
}
break;
case NIFPGA.lvbitx.Datatype.Int16:
if (!register.Indicator)
{
value = "FPGAWriteProperty";
}
else
{
value = "FPGAReadProperty";
}
break;
case NIFPGA.lvbitx.Datatype.Uint16:
if (!register.Indicator)
{
value = "FPGAWriteProperty";
}
else
{
value = "FPGAReadProperty";
}
break;
case NIFPGA.lvbitx.Datatype.Int32:
if (!register.Indicator)
{
value = "FPGAWriteProperty";
}
else
{
value = "FPGAReadProperty";
}
break;
case NIFPGA.lvbitx.Datatype.Uint32:
if (!register.Indicator)
{
value = "FPGAWriteProperty";
}
else
{
value = "FPGAReadProperty";
}
break;
case NIFPGA.lvbitx.Datatype.Int64:
if (!register.Indicator)
{
value = "FPGAWriteProperty";
}
else
{
value = "FPGAReadProperty";
}
break;
case NIFPGA.lvbitx.Datatype.Uint64:
if (!register.Indicator)
{
value = "FPGAWriteProperty";
}
else
{
value = "FPGAReadProperty";
}
break;
case NIFPGA.lvbitx.Datatype.Float:
if (!register.Indicator)
{
value = "FPGAWriteProperty";
}
else
{
value = "FPGAReadProperty";
}
break;
case NIFPGA.lvbitx.Datatype.Double:
if (!register.Indicator)
{
value = "FPGAWriteProperty";
}
else
{
value = "FPGAReadProperty";
}
break;
case NIFPGA.lvbitx.Datatype.FXP:
if(!register.Indicator)
{
value = "FPGAFXPWriteProperty";
}
else
{
value = "FPGAFXPReadProperty";
}
break;
case NIFPGA.lvbitx.Datatype.Array:
switch (register.ArrayValueType)
{
case NIFPGA.lvbitx.Datatype.Boolean:
if(!register.Indicator)
{
value = "FPGAArrayWriteProperty";
}
else
{
value = "FPGAArrayReadProperty";
}
break;
case NIFPGA.lvbitx.Datatype.Int8:
if (!register.Indicator)
{
value = "FPGAArrayWriteProperty";
}
else
{
value = "FPGAArrayReadProperty";
}
break;
case NIFPGA.lvbitx.Datatype.Uint8:
if (!register.Indicator)
{
value = "FPGAArrayWriteProperty";
}
else
{
value = "FPGAArrayReadProperty";
}
break;
case NIFPGA.lvbitx.Datatype.Int16:
if (!register.Indicator)
{
value = "FPGAArrayWriteProperty";
}
else
{
value = "FPGAArrayReadProperty";
}
break;
case NIFPGA.lvbitx.Datatype.Uint16:
if (!register.Indicator)
{
value = "FPGAArrayWriteProperty";
}
else
{
value = "FPGAArrayReadProperty";
}
break;
case NIFPGA.lvbitx.Datatype.Int32:
if (!register.Indicator)
{
value = "FPGAArrayWriteProperty";
}
else
{
value = "FPGAArrayReadProperty";
}
break;
case NIFPGA.lvbitx.Datatype.Uint32:
if (!register.Indicator)
{
value = "FPGAArrayWriteProperty";
}
else
{
value = "FPGAArrayReadProperty";
}
break;
case NIFPGA.lvbitx.Datatype.Int64:
if (!register.Indicator)
{
value = "FPGAArrayWriteProperty";
}
else
{
value = "FPGAArrayReadProperty";
}
break;
case NIFPGA.lvbitx.Datatype.Uint64:
if (!register.Indicator)
{
value = "FPGAArrayWriteProperty";
}
else
{
value = "FPGAArrayReadProperty";
}
break;
case NIFPGA.lvbitx.Datatype.Float:
if (!register.Indicator)
{
value = "FPGAArrayWriteProperty";
}
else
{
value = "FPGAArrayReadProperty";
}
break;
case NIFPGA.lvbitx.Datatype.Double:
if (!register.Indicator)
{
value = "FPGAArrayWriteProperty";
}
else
{
value = "FPGAArrayReadProperty";
}
break;
case NIFPGA.lvbitx.Datatype.FXP:
if (!register.Indicator)
{
value = "FPGAArrayFXPWriteProperty";
}
else
{
value = "FPGAArrayFXPReadProperty";
}
break;
}
break;
}
return value;
}
}
}