internal static void VisitScalarValueChange(ReadOnlyMemory <byte> text, IDToVarDef idToVariable, SimPass pass, BitAllocator bitAlloc) { UnsafeMemory <BitState> bits = bitAlloc.GetBits(1); BitState bit = ToBitState(text.Span[0]); var id = text.Slice(1); bits.Span[0] = bit; if (idToVariable.TryGetValue(id, out List <VarDef>?variable)) { pass.BinValue = new BinaryVarValue(bits, variable, ((int)bit & 0b10) == 0); } else { throw new Exception($"Unknown variable identifier: {id}"); } }
internal static unsafe (UnsafeMemory <BitState> bits, bool isValidBinary) ToBitStates(ReadOnlySpan <byte> valueText, BitAllocator bitAlloc) { UnsafeMemory <BitState> bitsMem = bitAlloc.GetBits(valueText.Length); Span <BitState> bits = bitsMem.Span; ulong isValidBinary = 0; int index = 0; if (Ssse3.IsSupported && bits.Length >= Vector128 <byte> .Count) { int vecBitCount = bits.Length / Vector128 <byte> .Count; fixed(BitState *bitsPtr = bits) { fixed(byte *textPtr = valueText) { Vector128 <ulong> isValidBin = Vector128 <ulong> .Zero; for (; index < vecBitCount; index++) { var charText = Avx.LoadVector128(textPtr + index * Vector128 <byte> .Count); var byteText = Avx.Shuffle(charText, shuffleIdxs); var firstBit = Avx.And(onlyFirstBit, Avx.Or(byteText, Avx.ShiftRightLogical(byteText.AsInt32(), 1).AsByte())); var secondBit = Avx.And(onlySecondBit, Avx.ShiftRightLogical(byteText.AsInt32(), 5).AsByte()); var bytesAsBitStates = Avx.Or(firstBit, secondBit); Avx.Store((byte *)bitsPtr + bits.Length - (index + 1) * Vector128 <byte> .Count, bytesAsBitStates); isValidBin = Avx.Or(isValidBin, secondBit.AsUInt64()); } isValidBinary = isValidBin.GetElement(0) | isValidBin.GetElement(1); } } index *= Vector128 <byte> .Count; } for (; index < bits.Length; index++) { BitState bit = ToBitState(valueText[index]); bits[bits.Length - index - 1] = bit; isValidBinary |= (uint)bit & 0b10; } return(bitsMem, isValidBinary == 0); }
internal static void VisitRealVectorValueChange(VCDLexer lexer, ReadOnlySpan <byte> valueText, IDToVarDef idToVariable, SimPass pass, BitAllocator bitAlloc) { Span <char> chars = stackalloc char[valueText.Length]; valueText.CopyToCharArray(chars); double value = double.Parse(chars, NumberStyles.Float, CultureInfo.InvariantCulture); var id = lexer.NextWordAsMem(); if (idToVariable.TryGetValue(id, out List <VarDef>?variable)) { pass.RealValue = new RealVarValue(value, variable); } else { throw new Exception($"Unknown variable identifier: {id}"); } }
internal static void VisitBinaryVectorValueChange(VCDLexer lexer, ReadOnlySpan <byte> valueText, IDToVarDef idToVariable, SimPass pass, BitAllocator bitAlloc) { (UnsafeMemory <BitState> bits, bool isValidBinary) = ToBitStates(valueText, bitAlloc); var id = lexer.NextWordAsMem(); if (idToVariable.TryGetValue(id, out List <VarDef>?variables)) { pass.BinValue = new BinaryVarValue(bits, variables, isValidBinary); } else { throw new Exception($"Unknown variable identifier: {id}"); } }
internal static void VisitValueChange(VCDLexer lexer, ReadOnlyMemory <byte> text, IDToVarDef idToVariable, SimPass pass, BitAllocator bitAlloc) { if (text.Length < 2) { throw new Exception($"Invalid value change: {text.ToString()}"); } ReadOnlySpan <byte> textSpan = text.Span; if (textSpan[0] == 'b' || textSpan[0] == 'B') { VisitBinaryVectorValueChange(lexer, textSpan.Slice(1), idToVariable, pass, bitAlloc); } else if (textSpan[0] == 'r' || textSpan[0] == 'R') { VisitRealVectorValueChange(lexer, textSpan.Slice(1), idToVariable, pass, bitAlloc); } else { VisitScalarValueChange(text, idToVariable, pass, bitAlloc); } }
internal static List <VarValue> VisitValueChangeStream(VCDLexer lexer, IDToVarDef idToVariable, SimPass pass, BitAllocator bitAlloc) { List <VarValue> changes = new List <VarValue>(); while (!lexer.IsEmpty()) { ReadOnlyMemory <byte> text = lexer.NextWordAsMem(); ReadOnlySpan <byte> endToken = new byte[] { (byte)'$', (byte)'e', (byte)'n', (byte)'d' }; if (text.Span.SequenceEqual(endToken)) { break; } VisitValueChange(lexer, text, idToVariable, pass, bitAlloc); if (pass.BinValue.HasValue) { changes.Add(pass.BinValue); } else if (pass.RealValue.HasValue) { changes.Add(pass.RealValue); } else { throw new Exception("Expected to read a value change but found none."); } } pass.Reset(); return(changes); }
internal static void VisitSimCmd(VCDLexer lexer, IDToVarDef idToVariable, SimPass pass, BitAllocator bitAlloc) { ReadOnlyMemory <byte> declWordMem = lexer.NextWordAsMem(); ReadOnlySpan <byte> declWord = declWordMem.Span; ReadOnlySpan <byte> endToken = new byte[] { (byte)'$', (byte)'e', (byte)'n', (byte)'d' }; ReadOnlySpan <byte> commentToken = new byte[] { (byte)'$', (byte)'c', (byte)'o', (byte)'m', (byte)'m', (byte)'e', (byte)'n', (byte)'t' }; ReadOnlySpan <byte> dumpAllToken = new byte[] { (byte)'$', (byte)'d', (byte)'u', (byte)'m', (byte)'p', (byte)'a', (byte)'l', (byte)'l' }; ReadOnlySpan <byte> dumpOffToken = new byte[] { (byte)'$', (byte)'d', (byte)'u', (byte)'m', (byte)'p', (byte)'o', (byte)'f', (byte)'f' }; ReadOnlySpan <byte> dumpOnToken = new byte[] { (byte)'$', (byte)'d', (byte)'u', (byte)'m', (byte)'p', (byte)'o', (byte)'n' }; ReadOnlySpan <byte> dumpVarsToken = new byte[] { (byte)'$', (byte)'d', (byte)'u', (byte)'m', (byte)'p', (byte)'v', (byte)'a', (byte)'r', (byte)'s' }; ReadOnlySpan <byte> hashtagToken = new byte[] { (byte)'#' }; //It may be the case that it's first discovered now that // the end of the file has been reached. if (declWord.Length == 0) { if (lexer.IsWordsRemaining()) { throw new Exception("Invalid simulation command."); } return; } if (declWord.SequenceEqual(commentToken)) { string text = lexer.NextUntil(endToken).ToCharString(); lexer.ExpectNextWord(endToken); pass.SimCmd = new Comment(text); } else if (declWord.SequenceEqual(dumpAllToken)) { pass.SimCmd = new DumpAll(VisitValueChangeStream(lexer, idToVariable, pass, bitAlloc)); } else if (declWord.SequenceEqual(dumpOffToken)) { pass.SimCmd = new DumpOff(VisitValueChangeStream(lexer, idToVariable, pass, bitAlloc)); } else if (declWord.SequenceEqual(dumpOnToken)) { pass.SimCmd = new DumpOn(VisitValueChangeStream(lexer, idToVariable, pass, bitAlloc)); } else if (declWord.SequenceEqual(dumpVarsToken)) { pass.SimCmd = new DumpVars(VisitValueChangeStream(lexer, idToVariable, pass, bitAlloc)); } else if (declWord.StartsWith(hashtagToken)) { pass.SimCmd = VisitSimTime(declWord); } else { VisitValueChange(lexer, declWordMem, idToVariable, pass, bitAlloc); } }