packages feed

crackNum-3.30: src/CrackNum/Options.hs

---------------------------------------------------------------------------
-- |
-- Module      :  CrackNum.Options
-- Copyright   :  (c) Levent Erkok
-- License     :  BSD3
-- Maintainer  :  erkokl@gmail.com
-- Stability   :  experimental
--
-- Command-line options, and the help text
-----------------------------------------------------------------------------

{-# OPTIONS_GHC -Wall -Werror #-}

module CrackNum.Options(
     getSize, getRM, pgmOptions, helpStr, usage
   ) where

import Data.Char  (toLower)
import Text.Read  (readMaybe)

import System.Console.GetOpt (ArgDescr(..), OptDescr(..), usageInfo)

import CrackNum.Types
import CrackNum.Formats

-- | Given an integer flag value, turn it into a flag
getSize :: String -> (Int -> Flag) -> String -> Flag
getSize flg f n = case readMaybe n of
                    Just i | i > 0 -> f i
                           | True  -> BadFlag ["Option " ++ show flg ++ " requires an integer >= 1. Received: " ++ show n]
                    Nothing        -> BadFlag ["Option " ++ show flg ++ " requires an integer argument. Received: " ++ show n]

getRM :: String -> Flag
getRM "rne" = RMode RNE
getRM "rna" = RMode RNA
getRM "rtp" = RMode RTP
getRM "rtn" = RMode RTN
getRM "rtz" = RMode RTZ
getRM m     = BadFlag $  [ "Invalid rounding mode."
                         , ""
                         , "  Must be one of:"
                         ]
                      ++ [ "     " ++ show r | r <- [minBound .. maxBound::RM]]
                      ++ [ ""
                         , "Received: " ++ m
                         ]

-- | Options we accept
pgmOptions :: [OptDescr Flag]
pgmOptions = [
      Option "i"  []               (ReqArg (getSize "-i" Signed)   "N" )    "Signed   integer of N-bits"
    , Option "w"  []               (ReqArg (getSize "-w" Unsigned) "N" )    "Unsigned integer of N-bits"
    , Option "f"  []               (ReqArg getFP                   "fp")    "Floating point format fp"
    , Option "r"  []               (ReqArg (getRM . map toLower)   "rm")    "Rounding mode to use. If not given, Nearest-ties-to-Even."
    , Option "l"  []               (ReqArg (getSize "-l" Lanes)    "lanes") "Number of lanes to decode"
    , Option "h?" ["help"]         (NoArg Help)                             "print help, with examples"
    , Option "v"  ["version"]      (NoArg Version)                          "print version info"
    , Option "d"  ["debug"]        (NoArg Debug)                            "debug mode, developers only"
    , Option ""   ["gui"]          (NoArg GUI)                              "launch the graphical interface"
    , Option ""   ["list-formats"] (NoArg Formats)                          "list the formats supported by -f, one per line"
    ]

-- | Help info
helpStr :: String -> String
helpStr pn = usageInfo ("Usage: " ++ pn ++ " value OR binary/hex-pattern") pgmOptions

-- | Print usage info and examples.
usage :: String -> IO ()
usage pn = putStr $ unlines $ [ helpStr pn
                              , "Supported floating-point formats (for use with -f):"
                              , ""
                              ]
                           ++ map ("  " ++) fpFormatsHelp
                           ++ [ ""
                              , "Examples:"
                              , " Encoding:"
                              , "   " ++ pn ++ " -i4       -- -2                   -- encode as 4-bit signed integer"
                              , "   " ++ pn ++ " -w4       2                       -- encode as 4-bit unsigned integer"
                              , "   " ++ pn ++ " -f3+4     2.5                     -- encode as float with 3 bits exponent, 4 bits significand"
                              , "   " ++ pn ++ " -f3+4     2.5 -rRTZ               -- encode as above, but use RTZ rounding mode."
                              , "   " ++ pn ++ " -fbp      2.5                     -- encode as a brain-precision float"
                              , "   " ++ pn ++ " -ftf32    2.5                     -- encode as a TensorFloat-32 float"
                              , "   " ++ pn ++ " -fdp      2.5                     -- encode as a double-precision float"
                              , "   " ++ pn ++ " -fqp      2.5                     -- encode as a quad-precision float"
                              , "   " ++ pn ++ " -fe4m3    2.5                     -- encode as an E4M3 FP8 float"
                              , "   " ++ pn ++ " -fe5m2    2.5                     -- encode as an E5M2 FP8 float"
                              , "   " ++ pn ++ " -ffp4     2.5                     -- encode as an FP4 (E2M1) float"
                              , "   " ++ pn ++ " -ffp4e0m3 3.5                     -- encode as an FP4 (E0M3) sign-magnitude integer"
                              , "   " ++ pn ++ " -fe8m0    2.5                     -- encode as an E8M0 MX scale (power of two)"
                              , "   " ++ pn ++ " -fsp      0x3.2p5                 -- encode as single-precision from hex-float"
                              , ""
                              , " Decoding:"
                              , "   " ++ pn ++ " -i4       0b0110                  -- decode as 4-bit signed integer, from binary"
                              , "   " ++ pn ++ " -w4       0xE                     -- decode as 4-bit unsigned integer, from hex"
                              , "   " ++ pn ++ " -f3+4     0b0111001               -- decode as float with 3 bits exponent, 4 bits significand"
                              , "   " ++ pn ++ " -fbp      0x000F                  -- decode as a brain-precision float"
                              , "   " ++ pn ++ " -ftf32    19\\'h0000F              -- decode as a TensorFloat-32 float"
                              , "   " ++ pn ++ " -fdp      0x8000000000000000      -- decode as a double-precision float"
                              , "   " ++ pn ++ " -fhp      0x8000                  -- decode as a half-precision float"
                              , "   " ++ pn ++ " -ffp4     0b0111                  -- decode as an FP4 (E2M1) float"
                              , "   " ++ pn ++ " -ffp4e0m3 0b1101                  -- decode as an FP4 (E0M3) sign-magnitude integer"
                              , "   " ++ pn ++ " -fe8m0    0x7F                    -- decode as an E8M0 MX scale (power of two)"
                              , "   " ++ pn ++ " -l4 -fhp  64\\'hbdffaaffdc71fc60   -- decode as half-precision float over 4 lanes using verilog notation"
                              , ""
                              , " GUI:"
                              , "   " ++ pn ++ " --gui                             -- launch the graphical interface"
                              , "   " ++ pn ++ " --gui      0xdeadbeef             -- launch the GUI, pre-filled with the given value"
                              , "   " ++ pn ++ " --gui -fsp 0xdeadbeef             -- launch the GUI, using the given format"
                              , ""
                              , " Notes:"
                              , "   - For encoding:"
                              , "       - Use -- to separate your argument if it's a negative number."
                              , "       - For floats: You can pass in NaN, Inf, -0, -Inf etc as the argument"
                              , "                     along with a decimal (2.3, -4.1e5) or hexadecimal float (0x2.4p3)"
                              , "       - FP4 (E2M1) has neither NaN nor Inf, so those inputs are rejected. Finite"
                              , "         values outside its range of [-6, 6] saturate to the nearest end-point."
                              , "       - FP4 (E0M3) is a sign-magnitude integer: a sign bit and a 3-bit magnitude,"
                              , "         covering -7 to 7, with both a positive and a negative zero. It has no NaN"
                              , "         and no Inf either, and values outside [-7, 7] saturate to the end-point."
                              , "       - E8M0 (MX scale) is all exponent: no sign bit and no significand at all,"
                              , "         so every value is a power of two, from 2^-127 to 2^127. It has no zero"
                              , "         and no Inf, and 0xFF is its only NaN. Negative inputs are rejected;"
                              , "         values outside the range saturate to the nearest end-point."
                              , "   - For decoding:"
                              , "       - Use hexadecimal (0x) binary (0b), or N'h (verilog) notation as input."
                              , "         Input must have one of these prefixes."
                              , "       - You can use _,- or space as a digit to improve readability for the pattern to be decoded"
                              , "       - With -lN parameter, you can decode multiple lanes of data."
                              , "       - If you use verilog input format, then we will infer the number of lanes unless you provide it."
                              ]