/// <summary> /// Update methods /// </summary> /// <param name="ckt">The circuit</param> /// <param name="setup"></param> public void UpdateMethods(SpiceDevice dev, SpiceSetup setup, string ckt = "ckt") { // Get-set string[] keys = Declarations.Keys.ToArray(); foreach (var key in keys) { string code = Regex.Replace(Declarations[key], $@"get\s*\{{\s*value\s*\=\s*\w+\s*\-\>\s*(?<var>\w+)\s*;\s*\}}", (Match m) => $"get => {m.Groups["var"].Value};", RegexOptions.Multiline); Declarations[key] = code; } // Methods for (int i = 0; i < Methods.Count; i++) { string code = Regex.Replace(Methods[i], $@"\*\s*\(\s*{ckt}\s*\-\>\s*CKTstate(?<state>\d+)\s*\+\s*(?<node>\w+)\s*\)", (Match m) => $"ckt.State.States[{m.Groups["state"].Value}][{setup.StatesVariable} + {m.Groups["node"].Value}]"); code = Regex.Replace(code, dev.DeviceName + "_", "", RegexOptions.IgnoreCase); code = Regex.Replace(code, $@"\*\s*\(\s*{ckt}\s*\-\>\s*CKTrhsOld\s*\+\s*(?<node>\w+)\s*\)", (Match m) => $"ckt.State.Real.Solution[{m.Groups["node"].Value}]"); // If it just a simple setter, then use the shorthand notation Regex simpleset = new Regex(@"\s*\{\s*value\s*\=\s*(?<value>[^;]+);(\s*return\s*\(\s*OK\s*\)\s*;)?\s*\}\s*$"); code = simpleset.Replace(code, (Match m) => $" => {m.Groups["value"].Value};"); Methods[i] = code; } }
/// <summary> /// Constructor /// </summary> /// <param name="dev">The spice device</param> public SpiceDefinitions(SpiceDevice dev, SpiceSetup setup) { // Get the variable string var = setup.StatesVariable; string code; // Open the definitions file using (StreamReader sr = new StreamReader(Path.Combine(dev.Folder, dev.Def))) code = sr.ReadToEnd(); // Find all the states Dictionary <string, int> list = new Dictionary <string, int>(); Regex r = new Regex($@"#define\s*(?<name>\w+)\s*{setup.StatesVariable}\s*\+\s*(?<offset>\d+)"); var ms = r.Matches(code); int max = 0; foreach (Match m in ms) { int offset = Convert.ToInt32(m.Groups["offset"].Value); list.Add(m.Groups["name"].Value, offset); max = Math.Max(offset + 1, max); StateNames.Add(m.Groups["name"].Value); } // Store the ordered states States = new string[max]; foreach (var s in list) { States[s.Value] = s.Key; } }
/// <summary> /// Constructor /// </summary> /// <param name="dev">Device</param> public SpiceTruncate(SpiceDevice dev, SpiceSetup setup) { string content = dev.GetMethod(SpiceDevice.Methods.Trunc); ReadMethod(content); // Copy the matrix nodes states = setup.StatesVariable; }
/// <summary> /// Constructor /// </summary> /// <param name="dev">The Spice device</param> public SpiceAcLoad(SpiceDevice dev, SpiceSetup setup) { string content = dev.GetMethod(SpiceDevice.Methods.AcLoad); ReadMethod(content); // Copy the matrix nodes foreach (string n in setup.MatrixNodes.Keys) { matrixnodes.Add(n, setup.MatrixNodes[n]); } states = setup.StatesVariable; }
/// <summary> /// Constructor /// </summary> /// <param name="dev">The spice device</param> public SpiceDefinitions(SpiceDevice dev, SpiceSetup setup) { // Get the variable string var = setup.StatesVariable; string code; Count = 0; // Open the definitions file using (StreamReader sr = new StreamReader(Path.Combine(dev.Folder, dev.Def))) code = sr.ReadToEnd(); // Find all the states Regex r = new Regex($@"#define\s*(?<name>\w+)\s*{setup.StatesVariable}\s*\+\s*(?<offset>\d+)"); var ms = r.Matches(code); foreach (Match m in ms) { int offset = Convert.ToInt32(m.Groups["offset"].Value); States.Add(new Tuple <int, string>(offset, m.Groups["name"].Value)); StateNames.Add(m.Groups["name"].Value); Count = Math.Max(Count, offset + 1); } }
/// <summary> /// Read a device /// </summary> /// <param name="dev"></param> public SpiceClassGenerator(SpiceDevice dev, Methods export = Methods.All) { // Get all model and device methods dev.BuildMethodTable(); name = dev.DeviceName.ToUpper(); // Extract the parameters paramExtr = new ParameterExtractor(); paramExtr.Extract(dev); // Get all parameters paramMod = new SpiceParam(dev, paramExtr.Model, SpiceDevice.Methods.ModelParam, SpiceDevice.Methods.ModelAsk); paramDev = new SpiceParam(dev, paramExtr.Device, SpiceDevice.Methods.Param, SpiceDevice.Methods.Ask); // Extract the setup if (export.HasFlag(Methods.Setup)) { setup = new SpiceSetup(dev); setupDev = setup.ExportDevice(paramMod, paramDev); setupMod = setup.ExportModel(paramMod); foreach (var v in setup.SharedLocalVariables) { shared.Add(v.Key, v.Value); } foreach (var v in setup.ModelVariablesExtra) { modelextra.Add(v); } foreach (var v in setup.DeviceVariablesExtra) { deviceextra.Add(v); } // Update the methods paramMod.UpdateMethods(dev, setup); paramDev.UpdateMethods(dev, setup); } // Extract the state definitions if (setup != null) { definitions = new SpiceDefinitions(dev, setup); foreach (var v in definitions.StateNames) { paramDev.Variables.Add(v); } } // Temperature-dependent calculations if (export.HasFlag(Methods.Temperature)) { temp = new SpiceTemperature(dev); tempDev = temp.ExportDevice(paramMod, paramDev); tempMod = temp.ExportModel(paramMod); foreach (var v in temp.SharedLocalVariables) { if (shared.ContainsKey(v.Key) && shared[v.Key] != v.Value) { throw new Exception($"Cannot share variable {v.Key}"); } shared.Add(v.Key, v.Value); } foreach (var v in temp.ModelVariablesExtra) { modelextra.Add(v); } foreach (var v in temp.DeviceVariablesExtra) { deviceextra.Add(v); } } // Loading if (export.HasFlag(Methods.Load) && setup != null) { load = new SpiceLoad(dev, setup); loadDev = load.ExportDevice(paramMod, paramDev); loadMod = load.ExportModel(paramMod); foreach (var v in load.SharedLocalVariables) { if (shared.ContainsKey(v.Key) && shared[v.Key] != v.Value) { throw new Exception($"Cannot share variable {v.Key}"); } shared.Add(v.Key, v.Value); } foreach (var v in load.ModelVariablesExtra) { modelextra.Add(v); } foreach (var v in load.DeviceVariablesExtra) { deviceextra.Add(v); } } // AC loading if (export.HasFlag(Methods.AcLoad) && setup != null) { acload = new SpiceAcLoad(dev, setup); acloadDev = acload.ExportDevice(paramMod, paramDev); acloadMod = acload.ExportModel(paramMod); foreach (var v in acload.SharedLocalVariables) { if (shared.ContainsKey(v.Key) && shared[v.Key] != v.Value) { throw new Exception($"Cannot share variable {v.Key}"); } shared.Add(v.Key, v.Value); } foreach (var v in acload.ModelVariablesExtra) { modelextra.Add(v); } foreach (var v in acload.DeviceVariablesExtra) { deviceextra.Add(v); } } // PZ loading if (export.HasFlag(Methods.PzLoad)) { pzload = new SpicePzLoad(dev, setup); pzloadDev = pzload.ExportDevice(paramMod, paramDev); pzloadMod = pzload.ExportModel(paramMod); foreach (var v in pzload.SharedLocalVariables) { if (shared.ContainsKey(v.Key) && shared[v.Key] != v.Value) { throw new Exception($"Cannot share variable {v.Key}"); } shared.Add(v.Key, v.Value); } foreach (var v in pzload.ModelVariablesExtra) { modelextra.Add(v); } foreach (var v in pzload.DeviceVariablesExtra) { deviceextra.Add(v); } } // Truncation if (export.HasFlag(Methods.Truncate)) { trunc = new SpiceTruncate(dev, setup); truncDev = trunc.ExportDevice(paramMod, paramDev); truncMod = trunc.ExportModel(paramMod); foreach (var v in trunc.SharedLocalVariables) { if (shared.ContainsKey(v.Key) && shared[v.Key] != v.Value) { throw new Exception($"Cannot share variable {v.Key}"); } shared.Add(v.Key, v.Value); } foreach (var v in trunc.ModelVariablesExtra) { modelextra.Add(v); } foreach (var v in trunc.DeviceVariablesExtra) { deviceextra.Add(v); } } // Apply default values! string[] names = paramMod.Declarations.Keys.ToArray(); foreach (string n in names) { // Find out if the name of the variable with this ID if (setup.ModelDefaultValues.ContainsKey(n)) { paramMod.Declarations[n] = Regex.Replace(paramMod.Declarations[n], @"\(\);", $"({setup.ModelDefaultValues[n]});"); } } names = paramDev.Declarations.Keys.ToArray(); foreach (string n in names) { // Find out if the name of the variable with this ID if (setup.DeviceDefaultValues.ContainsKey(n)) { paramDev.Declarations[n] = Regex.Replace(paramDev.Declarations[n], @"\(\);", $"({setup.DeviceDefaultValues[n]});"); } } }