using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
public class LogToVcdConverter
{
public class Signal
{
public string Name { get; set; }
public string Id { get; set; }
public bool Value { get; set; }
public string VcdId { get; set; }
}
private readonly Dictionary<string, Signal> _signals = new Dictionary<string, Signal>();
private readonly List<KeyValuePair<long, List<string>>> _valueChanges = new List<KeyValuePair<long, List<string>>>();
private string GenerateVcdId(int index)
{
const string chars = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
var sb = new StringBuilder();
if (index == 0)
{
return chars[0].ToString();
}
while (index > 0)
{
sb.Insert(0, chars[index % chars.Length]);
index /= chars.Length;
}
return sb.ToString();
}
public void ParseLogFile(string logFilePath)
{
using (var reader = new StreamReader(logFilePath))
{
string line;
bool isParsingDefinitions = true;
long currentTime = 0;
while ((line = reader.ReadLine()) != null)
{
line = line.Trim();
if (string.IsNullOrEmpty(line)) continue;
if (line.StartsWith("#"))
{
isParsingDefinitions = false;
currentTime = long.Parse(line.Substring(1));
_valueChanges.Add(new KeyValuePair<long, List<string>>(currentTime, new List<string>()));
}
else if (isParsingDefinitions)
{
var parts = line.TrimEnd(';').Split('|');
if (parts.Length == 3)
{
var signal = new Signal
{
Name = parts[0],
Id = parts[1],
Value = bool.Parse(parts[2]),
VcdId = GenerateVcdId(_signals.Count)
};
_signals[signal.Id] = signal;
}
}
else
{
_valueChanges.Last().Value.Add(line);
}
}
}
}
public void WriteVcdFile(string vcdFilePath)
{
using (var writer = new StreamWriter(vcdFilePath))
{
writer.WriteLine($"$date {DateTime.Now} $end");
writer.WriteLine("$version Log to VCD Converter $end");
writer.WriteLine("$timescale 1ps $end");
writer.WriteLine();
writer.WriteLine("$scope module simulation $end");
foreach (var signal in _signals.Values)
{
writer.WriteLine($"$var wire 1 {signal.VcdId} {signal.Name} $end");
}
writer.WriteLine("$upscope $end");
writer.WriteLine("$enddefinitions $end");
writer.WriteLine();
writer.WriteLine("$dumpvars");
foreach (var signal in _signals.Values)
{
writer.WriteLine($"{(signal.Value ? '1' : '0')}{signal.VcdId}");
}
writer.WriteLine("$end");
foreach (var change in _valueChanges)
{
writer.WriteLine($"#{change.Key}");
foreach (var signalId in change.Value)
{
if (_signals.TryGetValue(signalId, out var signal))
{
signal.Value = !signal.Value;
writer.WriteLine($"{(signal.Value ? '1' : '0')}{signal.VcdId}");
}
}
}
}
}
public static void Main(string[] args)
{
if (args.Length != 2)
{
Console.WriteLine("Usage: LogToVcdConverter <input_logfile_path> <output_vcdfile_path>");
return;
}
string logFile = args[0];
string vcdFile = args[1];
if (!File.Exists(logFile))
{
Console.WriteLine($"Error: Input log file not found at '{logFile}'");
return;
}
var converter = new LogToVcdConverter();
try
{
Console.WriteLine("Parsing log file...");
converter.ParseLogFile(logFile);
Console.WriteLine("Writing VCD file...");
converter.WriteVcdFile(vcdFile);
Console.WriteLine($"Successfully converted '{logFile}' to '{vcdFile}'.");
}
catch (Exception ex)
{
Console.WriteLine($"An error occurred: {ex.Message}");
}
}
}