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; } } }