diff --git a/changelog/2025-11-17T21_35_22+01_00_fixed_dumpvcd_trace_limit b/changelog/2025-11-17T21_35_22+01_00_fixed_dumpvcd_trace_limit new file mode 100644 index 0000000000..bc244ee173 --- /dev/null +++ b/changelog/2025-11-17T21_35_22+01_00_fixed_dumpvcd_trace_limit @@ -0,0 +1 @@ +FIXED: Removed the limit on the number of traces in `dumpVCD`. Also removed unnecessary double newlines after 1-bit signals. [#3082](https://github.com/clash-lang/clash-compiler/issues/3082) diff --git a/clash-prelude/src/Clash/Signal/Trace.hs b/clash-prelude/src/Clash/Signal/Trace.hs index 6250c014c1..d24f42ad6e 100644 --- a/clash-prelude/src/Clash/Signal/Trace.hs +++ b/clash-prelude/src/Clash/Signal/Trace.hs @@ -115,6 +115,7 @@ import Data.IORef import Data.List (foldl') #endif import Data.List (foldl1', unzip4, transpose, uncons) +import Data.List.Extra (snoc) import qualified Data.Map.Strict as Map import Data.Maybe (fromMaybe, catMaybes) import qualified Data.Text as Text @@ -349,8 +350,6 @@ dumpVCD## (offset, cycles) traceMap now error $ "dumpVCD: cycles was " ++ show cycles ++ ", but cannot be negative." | null traceMap = error $ "dumpVCD: no traces found. Extend the given trace names." - | Map.size traceMap > 126 - 33 = - Left $ "Tracemap contains more than 93 traces, which is not supported by VCD." | (nm:_) <- offensiveNames = Left $ unwords [ "Trace '" ++ nm ++ "' contains" , "non-printable ASCII characters, which is not" @@ -373,7 +372,10 @@ dumpVCD## (offset, cycles) traceMap now where offensiveNames = filter (any (not . printable)) traceNames - labels = map chr [33..126] + -- Generate labels in the pattern a,b,c,aa,ab,ac,ba,bb,bc,ca,cb,cc,aaa,... + labels = concatMap (\s -> map (snoc s) alphabet) ([]: labels) + where + alphabet = map chr [33..126] timescale = foldl1' gcd (Map.keys periodMap) periodMap = toPeriodMap traceMap @@ -414,7 +416,7 @@ dumpVCD## (offset, cycles) traceMap now headerTimescale = ["$timescale", (show timescale) ++ "ps", "$end"] headerWires = [ Text.unwords $ headerWire w l n | (w, l, n) <- (zip3 widths labels traceNames)] - headerWire w l n = map Text.pack ["$var wire", show w, [l], n, "$end"] + headerWire w l n = map Text.pack ["$var wire", show w, l, n, "$end"] initValues = map Text.pack $ zipWith ($) formatters inits formatters = zipWith format widths labels @@ -422,14 +424,14 @@ dumpVCD## (offset, cycles) traceMap now tails = map changed valuess' -- | Format single value according to VCD spec - format :: Width -> Char -> Value -> String - format 1 label (0,0) = ['0', label, '\n'] - format 1 label (0,1) = ['1', label, '\n'] - format 1 label (1,_) = ['x', label, '\n'] + format :: Width -> String -> Value -> String + format 1 label (0,0) = '0': label + format 1 label (0,1) = '1': label + format 1 label (1,_) = 'x': label format 1 label (mask,val) = error $ "Can't format 1 bit wide value for " ++ show label ++ ": value " ++ show val ++ " and mask " ++ show mask format n label (mask,val) = - "b" ++ map digit (reverse [0..n-1]) ++ " " ++ [label] + "b" ++ map digit (reverse [0..n-1]) ++ " " ++ label where digit d = case (testBit mask d, testBit val d) of (False,False) -> '0'